mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-01-19 05:33:47 +01:00
eb73daffe9
* [FEAT] Node Managment feat: node dashboard channels and transactions fix: update channel variables better types refactor ui add onchain balances and backend_name mock values for fake wallet remove app tab start implementing peers and channel management peer and channel management implement channel closing add channel states, better errors seperate payments and invoices on transactions tab display total channel balance feat: optional public page feat: show node address fix: port conversion feat: details dialog on transactions fix: peer info without alias fix: rename channel balances small improvements to channels tab feat: pagination on transactions tab test caching transactions refactor: move WALLET into wallets module fix: backwards compatibility refactor: move get_node_class to nodes modules post merge bundle fundle feat: disconnect peer feat: initial lnd support only use filtered channels for total balance adjust closing logic add basic node tests add setting for disabling transactions tab revert unnecessary changes add tests for invoices and payments improve payment and invoice implementations the previously used invoice fixture has a session scope, but a new invoice is required tests and bug fixes for channels api use query instead of body in channel delete delete requests should generally not use a body take node id through path instead of body for delete endpoint add peer management tests more tests for errors improve error handling rename id and pubkey to peer_id for consistency remove dead code fix http status codes make cache keys safer cache node public info comments for node settings rename node prop in frontend adjust tests to new status codes cln: use amount_msat instead of value for onchain balance turn transactions tab off by default enable transactions in tests only allow super user to create or delete fix prop name in admin navbar --------- Co-authored-by: jacksn <jkranawetter05@gmail.com>
220 lines
5.4 KiB
Python
220 lines
5.4 KiB
Python
# ruff: noqa: E402
|
|
import asyncio
|
|
from time import time
|
|
|
|
import uvloop
|
|
|
|
uvloop.install()
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from fastapi.testclient import TestClient
|
|
from httpx import AsyncClient
|
|
|
|
from lnbits.app import create_app
|
|
from lnbits.core.crud import (
|
|
create_account,
|
|
create_wallet,
|
|
get_user,
|
|
update_payment_status,
|
|
)
|
|
from lnbits.core.models import CreateInvoice
|
|
from lnbits.core.services import update_wallet_balance
|
|
from lnbits.core.views.api import api_payments_create_invoice
|
|
from lnbits.db import DB_TYPE, SQLITE, Database
|
|
from lnbits.settings import settings
|
|
from tests.helpers import (
|
|
clean_database,
|
|
get_hold_invoice,
|
|
get_random_invoice_data,
|
|
get_real_invoice,
|
|
)
|
|
|
|
# override settings for tests
|
|
settings.lnbits_admin_extensions = []
|
|
settings.lnbits_data_folder = "./tests/data"
|
|
settings.lnbits_admin_ui = True
|
|
settings.lnbits_extensions_default_install = []
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
def event_loop():
|
|
loop = asyncio.get_event_loop()
|
|
yield loop
|
|
loop.close()
|
|
|
|
|
|
# use session scope to run once before and once after all tests
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def app():
|
|
clean_database(settings)
|
|
app = create_app()
|
|
await app.router.startup()
|
|
yield app
|
|
await app.router.shutdown()
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def client(app):
|
|
client = AsyncClient(app=app, base_url=f"http://{settings.host}:{settings.port}")
|
|
yield client
|
|
await client.aclose()
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_client(app):
|
|
return TestClient(app)
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def db():
|
|
yield Database("database")
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def from_user():
|
|
user = await create_account()
|
|
yield user
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def from_wallet(from_user):
|
|
user = from_user
|
|
wallet = await create_wallet(user_id=user.id, wallet_name="test_wallet_from")
|
|
await update_wallet_balance(
|
|
wallet_id=wallet.id,
|
|
amount=999999999,
|
|
)
|
|
yield wallet
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def from_wallet_ws(from_wallet, test_client):
|
|
# wait a bit in order to avoid receiving topup notification
|
|
await asyncio.sleep(0.1)
|
|
with test_client.websocket_connect(f"/api/v1/ws/{from_wallet.id}") as ws:
|
|
yield ws
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def to_user():
|
|
user = await create_account()
|
|
yield user
|
|
|
|
|
|
@pytest.fixture()
|
|
def from_super_user(from_user):
|
|
prev = settings.super_user
|
|
settings.super_user = from_user.id
|
|
yield from_user
|
|
settings.super_user = prev
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def superuser():
|
|
user = await get_user(settings.super_user)
|
|
yield user
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def to_wallet(to_user):
|
|
user = to_user
|
|
wallet = await create_wallet(user_id=user.id, wallet_name="test_wallet_to")
|
|
await update_wallet_balance(
|
|
wallet_id=wallet.id,
|
|
amount=999999999,
|
|
)
|
|
yield wallet
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def to_wallet_ws(to_wallet, test_client):
|
|
# wait a bit in order to avoid receiving topup notification
|
|
await asyncio.sleep(0.1)
|
|
with test_client.websocket_connect(f"/api/v1/ws/{to_wallet.id}") as ws:
|
|
yield ws
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def inkey_headers_from(from_wallet):
|
|
wallet = from_wallet
|
|
yield {
|
|
"X-Api-Key": wallet.inkey,
|
|
"Content-type": "application/json",
|
|
}
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def adminkey_headers_from(from_wallet):
|
|
wallet = from_wallet
|
|
yield {
|
|
"X-Api-Key": wallet.adminkey,
|
|
"Content-type": "application/json",
|
|
}
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def inkey_headers_to(to_wallet):
|
|
wallet = to_wallet
|
|
yield {
|
|
"X-Api-Key": wallet.inkey,
|
|
"Content-type": "application/json",
|
|
}
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def adminkey_headers_to(to_wallet):
|
|
wallet = to_wallet
|
|
yield {
|
|
"X-Api-Key": wallet.adminkey,
|
|
"Content-type": "application/json",
|
|
}
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def invoice(to_wallet):
|
|
data = await get_random_invoice_data()
|
|
invoiceData = CreateInvoice(**data)
|
|
invoice = await api_payments_create_invoice(invoiceData, to_wallet)
|
|
yield invoice
|
|
del invoice
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="function")
|
|
async def real_invoice():
|
|
invoice = get_real_invoice(100)
|
|
yield {"bolt11": invoice["payment_request"]}
|
|
del invoice
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="session")
|
|
async def fake_payments(client, adminkey_headers_from):
|
|
# Because sqlite only stores timestamps with milliseconds
|
|
# we have to wait a second to ensure a different timestamp than previous invoices
|
|
if DB_TYPE == SQLITE:
|
|
await asyncio.sleep(1)
|
|
ts = time()
|
|
|
|
fake_data = [
|
|
CreateInvoice(amount=10, memo="aaaa", out=False),
|
|
CreateInvoice(amount=100, memo="bbbb", out=False),
|
|
CreateInvoice(amount=1000, memo="aabb", out=False),
|
|
]
|
|
|
|
for invoice in fake_data:
|
|
response = await client.post(
|
|
"/api/v1/payments", headers=adminkey_headers_from, json=invoice.dict()
|
|
)
|
|
assert response.is_success
|
|
await update_payment_status(response.json()["checking_id"], pending=False)
|
|
|
|
params = {"time[ge]": ts, "time[le]": time()}
|
|
return fake_data, params
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="function")
|
|
async def hold_invoice():
|
|
invoice = get_hold_invoice(100)
|
|
yield invoice
|
|
del invoice
|