Fix payments chart (#1851)

* feat: payment history endpoint

* test payment history

* use new endpoint in frontend

* refactor tests
This commit is contained in:
jackstar12 2023-09-12 14:38:30 +02:00 committed by GitHub
parent f526a93b6c
commit 4c16675b3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 243 additions and 90 deletions

View file

@ -1,5 +1,6 @@
# ruff: noqa: E402
import asyncio
from time import time
import uvloop
@ -11,11 +12,16 @@ 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
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 Database
from lnbits.db import DB_TYPE, SQLITE, Database
from lnbits.settings import settings
from tests.helpers import (
clean_database,
@ -173,6 +179,31 @@ async def real_invoice():
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)

View file

@ -1,23 +1,21 @@
import asyncio
import hashlib
from time import time
import pytest
from lnbits import bolt11
from lnbits.core.crud import get_standalone_payment, update_payment_details
from lnbits.core.models import Payment
from lnbits.core.models import CreateInvoice, Payment
from lnbits.core.views.admin_api import api_auditor
from lnbits.core.views.api import api_payment
from lnbits.db import DB_TYPE, SQLITE
from lnbits.settings import settings
from lnbits.wallets import get_wallet_class
from tests.conftest import CreateInvoice, api_payments_create_invoice
from ...helpers import (
cancel_invoice,
get_random_invoice_data,
is_fake,
is_regtest,
pay_real_invoice,
settle_invoice,
)
@ -250,29 +248,13 @@ async def test_pay_invoice_adminkey(client, invoice, adminkey_headers_from):
@pytest.mark.asyncio
async def test_get_payments(client, from_wallet, adminkey_headers_from):
# Because sqlite only stores timestamps with milliseconds we have to wait a second
# to ensure a different timestamp than previous invoices due to this limitation
# both payments (normal and paginated) are tested at the same time as they are
# almost identical anyways
if DB_TYPE == SQLITE:
await asyncio.sleep(1)
ts = time()
fake_data = [
CreateInvoice(amount=10, memo="aaaa"),
CreateInvoice(amount=100, memo="bbbb"),
CreateInvoice(amount=1000, memo="aabb"),
]
for invoice in fake_data:
await api_payments_create_invoice(invoice, from_wallet)
async def test_get_payments(client, adminkey_headers_from, fake_payments):
fake_data, filters = fake_payments
async def get_payments(params: dict):
params["time[ge]"] = ts
response = await client.get(
"/api/v1/payments",
params=params,
params=filters | params,
headers=adminkey_headers_from,
)
assert response.status_code == 200
@ -298,9 +280,14 @@ async def test_get_payments(client, from_wallet, adminkey_headers_from):
payments = await get_payments({"amount[gt]": 10000})
assert len(payments) == 2
@pytest.mark.asyncio
async def test_get_payments_paginated(client, adminkey_headers_from, fake_payments):
fake_data, filters = fake_payments
response = await client.get(
"/api/v1/payments/paginated",
params={"limit": 2, "time[ge]": ts},
params=filters | {"limit": 2},
headers=adminkey_headers_from,
)
assert response.status_code == 200
@ -309,6 +296,38 @@ async def test_get_payments(client, from_wallet, adminkey_headers_from):
assert paginated["total"] == len(fake_data)
@pytest.mark.asyncio
@pytest.mark.skipif(
is_regtest, reason="payments wont be confirmed rightaway in regtest"
)
async def test_get_payments_history(client, adminkey_headers_from, fake_payments):
fake_data, filters = fake_payments
response = await client.get(
"/api/v1/payments/history",
params=filters,
headers=adminkey_headers_from,
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
assert data[0]["spending"] == sum(
payment.amount * 1000 for payment in fake_data if payment.out
)
assert data[0]["income"] == sum(
payment.amount * 1000 for payment in fake_data if not payment.out
)
response = await client.get(
"/api/v1/payments/history?group=INVALID",
params=filters,
headers=adminkey_headers_from,
)
assert response.status_code == 400
# check POST /api/v1/payments/decode
@pytest.mark.asyncio
async def test_decode_invoice(client, invoice):