fix: lint
This commit is contained in:
@@ -85,7 +85,9 @@ async def test_asset_api_upload_list_update_and_delete(
|
||||
assert deleted.status_code == 200
|
||||
assert deleted.json()["success"] is True
|
||||
|
||||
missing = await client.get(f"/api/v1/assets/{asset['id']}", headers=user_headers_from)
|
||||
missing = await client.get(
|
||||
f"/api/v1/assets/{asset['id']}", headers=user_headers_from
|
||||
)
|
||||
assert missing.status_code == 404
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ from fastapi.responses import RedirectResponse
|
||||
from httpx import AsyncClient
|
||||
|
||||
from lnbits.core.crud.users import get_account, update_account
|
||||
from lnbits.core.views.auth_api import get_account_by_email
|
||||
from lnbits.core.models.users import Account
|
||||
from lnbits.core.services.users import create_user_account
|
||||
from lnbits.core.views.auth_api import get_account_by_email
|
||||
from lnbits.settings import Settings
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ async def test_auth_api_logout_and_update_ui_customization(
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_auth_api_sso_login_and_callback(
|
||||
http_client: AsyncClient, mocker
|
||||
):
|
||||
async def test_auth_api_sso_login_and_callback(http_client: AsyncClient, mocker):
|
||||
user = await create_user_account(
|
||||
Account(
|
||||
id=uuid4().hex,
|
||||
|
||||
@@ -163,7 +163,9 @@ async def test_callback_api_handles_subscription_flows_and_validation(mocker):
|
||||
)
|
||||
assert create_fiat_invoice_mock.await_count == 2
|
||||
|
||||
with pytest.raises(ValueError, match="PayPal subscription event missing custom metadata."):
|
||||
with pytest.raises(
|
||||
ValueError, match="PayPal subscription event missing custom metadata."
|
||||
):
|
||||
await handle_paypal_event(
|
||||
{
|
||||
"id": "evt_bad_sale",
|
||||
|
||||
@@ -220,7 +220,9 @@ async def test_extension_api_pay_to_enable_and_catalog_views(mocker, admin_user)
|
||||
await create_installed_extension(
|
||||
_installable_extension(
|
||||
ext_id,
|
||||
pay_to_enable=PayToEnableInfo(required=True, amount=10, wallet=admin_wallet.id),
|
||||
pay_to_enable=PayToEnableInfo(
|
||||
required=True, amount=10, wallet=admin_wallet.id
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -410,6 +412,10 @@ async def test_extension_api_activate_uninstall_install_invoice_and_cleanup(mock
|
||||
@pytest.mark.anyio
|
||||
async def test_extension_api_review_endpoints(mocker):
|
||||
ext_id = f"review_{uuid4().hex[:8]}"
|
||||
reviews_base = "https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r"
|
||||
tags_url = f"{reviews_base}/tags"
|
||||
reviews_url = f"{reviews_base}/reviews/{ext_id}?offset=0&limit=5"
|
||||
create_review_url = f"{reviews_base}/reviews"
|
||||
request = Request(
|
||||
{
|
||||
"type": "http",
|
||||
@@ -421,10 +427,10 @@ async def test_extension_api_review_endpoints(mocker):
|
||||
)
|
||||
mock_client = _MockHTTPClient(
|
||||
{
|
||||
"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/tags": _MockHTTPResponse(
|
||||
tags_url: _MockHTTPResponse(
|
||||
json_data=[{"tag": "good", "avg_rating": 900, "review_count": 3}]
|
||||
),
|
||||
f"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/reviews/{ext_id}?offset=0&limit=5": _MockHTTPResponse(
|
||||
reviews_url: _MockHTTPResponse(
|
||||
json_data={
|
||||
"data": [
|
||||
{
|
||||
@@ -438,7 +444,7 @@ async def test_extension_api_review_endpoints(mocker):
|
||||
"total": 1,
|
||||
}
|
||||
),
|
||||
"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/reviews": _MockHTTPResponse(
|
||||
create_review_url: _MockHTTPResponse(
|
||||
json_data={
|
||||
"payment_hash": f"hash_{uuid4().hex[:8]}",
|
||||
"payment_request": "lnbc1review",
|
||||
@@ -446,7 +452,9 @@ async def test_extension_api_review_endpoints(mocker):
|
||||
),
|
||||
}
|
||||
)
|
||||
mocker.patch("lnbits.core.views.extension_api.httpx.AsyncClient", return_value=mock_client)
|
||||
mocker.patch(
|
||||
"lnbits.core.views.extension_api.httpx.AsyncClient", return_value=mock_client
|
||||
)
|
||||
|
||||
tags = await get_extension_reviews_tags()
|
||||
assert tags[0].tag == "good"
|
||||
|
||||
@@ -7,7 +7,6 @@ from lnbits.core.crud.extensions import create_user_extension, get_user_extensio
|
||||
from lnbits.core.crud.users import get_account
|
||||
from lnbits.core.models.extensions import (
|
||||
Extension,
|
||||
ExtensionMeta,
|
||||
ExtensionRelease,
|
||||
UserExtension,
|
||||
)
|
||||
@@ -81,7 +80,9 @@ async def test_extensions_builder_api_build_preview_and_cleanup(
|
||||
"lnbits.core.views.extensions_builder_api.build_extension_from_data",
|
||||
mocker.AsyncMock(return_value=(_release(ext_id), build_dir)),
|
||||
)
|
||||
clean_mock = mocker.patch("lnbits.core.views.extensions_builder_api.clean_extension_builder_data")
|
||||
clean_mock = mocker.patch(
|
||||
"lnbits.core.views.extensions_builder_api.clean_extension_builder_data"
|
||||
)
|
||||
|
||||
try:
|
||||
settings.lnbits_data_folder = str(tmp_path)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
from pytest_mock.plugin import MockerFixture
|
||||
@@ -9,8 +7,8 @@ from lnbits.fiat.base import FiatSubscriptionResponse
|
||||
|
||||
|
||||
class FakeStripeWallet:
|
||||
def __init__(self, secret: str | None = "secret"):
|
||||
self._secret = secret
|
||||
def __init__(self, secret: str | None = None):
|
||||
self._secret = secret if secret is not None else "connection-token"
|
||||
|
||||
async def create_terminal_connection_token(self) -> dict[str, str]:
|
||||
if self._secret is None:
|
||||
@@ -77,6 +75,7 @@ async def test_fiat_api_test_provider_and_subscription_lifecycle(
|
||||
assert created.status_code == 200
|
||||
assert created.json()["checkout_session_url"] == "https://stripe.example/checkout"
|
||||
provider.create_subscription.assert_awaited_once()
|
||||
assert provider.create_subscription.await_args is not None
|
||||
assert provider.create_subscription.await_args.args[2].wallet_id == from_wallet.id
|
||||
|
||||
cancelled = await client.delete(
|
||||
|
||||
@@ -20,13 +20,13 @@ from lnbits.core.models import Account, CreateInvoice
|
||||
from lnbits.core.models.lnurl import CreateLnurlPayment, LnurlScan
|
||||
from lnbits.core.models.wallets import KeyType, WalletTypeInfo
|
||||
from lnbits.core.services.payments import create_wallet_invoice
|
||||
from lnbits.core.services.users import create_user_account
|
||||
from lnbits.core.views.lnurl_api import (
|
||||
api_lnurlscan,
|
||||
api_lnurlscan_post,
|
||||
api_payments_pay_lnurl,
|
||||
api_perform_lnurlauth,
|
||||
)
|
||||
from lnbits.core.services.users import create_user_account
|
||||
|
||||
TEST_BOLT11 = (
|
||||
"lnbc1pnsu5z3pp57getmdaxhg5kc9yh2a2qsh7cjf4gnccgkw0qenm8vsqv50w7s"
|
||||
@@ -57,9 +57,13 @@ async def test_lnurl_api_scan_routes_validate_and_forward(mocker):
|
||||
)
|
||||
|
||||
scanned = await api_lnurlscan("lnurl1example")
|
||||
assert isinstance(scanned, LnurlPayResponse)
|
||||
assert scanned.callback == pay_response.callback
|
||||
|
||||
scanned_post = await api_lnurlscan_post(scan=LnurlScan(lnurl=LnAddress("alice@example.com")))
|
||||
scanned_post = await api_lnurlscan_post(
|
||||
scan=LnurlScan(lnurl=LnAddress("alice@example.com"))
|
||||
)
|
||||
assert isinstance(scanned_post, LnurlPayResponse)
|
||||
assert scanned_post.callback == pay_response.callback
|
||||
|
||||
mocker.patch(
|
||||
@@ -102,6 +106,7 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
|
||||
mocker.AsyncMock(return_value=auth_response),
|
||||
)
|
||||
authenticated = await api_perform_lnurlauth(auth_response, wallet_info)
|
||||
assert isinstance(authenticated, LnurlAuthResponse)
|
||||
assert authenticated.k1 == "k1-value"
|
||||
|
||||
mocker.patch(
|
||||
@@ -114,7 +119,7 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
|
||||
action_response = LnurlPayActionResponse(
|
||||
pr=LightningInvoice(TEST_BOLT11),
|
||||
disposable=False,
|
||||
successAction=MessageAction(message="paid"),
|
||||
successAction=parse_obj_as(MessageAction, {"message": "paid"}),
|
||||
)
|
||||
fetch_mock = mocker.patch(
|
||||
"lnbits.core.views.lnurl_api.fetch_lnurl_pay_request",
|
||||
@@ -126,13 +131,16 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
|
||||
)
|
||||
|
||||
paid = await api_payments_pay_lnurl(
|
||||
CreateLnurlPayment(res=pay_response, amount=2_000, unit="USD", comment="thanks"),
|
||||
CreateLnurlPayment(
|
||||
res=pay_response, amount=2_000, unit="USD", comment="thanks"
|
||||
),
|
||||
wallet_info,
|
||||
)
|
||||
assert paid.payment_hash == payment.payment_hash
|
||||
fetch_mock.assert_awaited_once()
|
||||
pay_mock.assert_awaited_once()
|
||||
assert pay_mock.await_args is not None
|
||||
assert action_response.successAction is not None
|
||||
assert pay_mock.await_args.kwargs["extra"] == {
|
||||
"stored": True,
|
||||
"success_action": action_response.successAction.json(),
|
||||
|
||||
+54
-39
@@ -1,9 +1,10 @@
|
||||
from typing import Any
|
||||
from collections.abc import Callable
|
||||
from typing import Any, cast
|
||||
from uuid import uuid4
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
from fastapi import HTTPException
|
||||
from pytest_mock.plugin import MockerFixture
|
||||
|
||||
from lnbits.core.views import node_api
|
||||
@@ -12,6 +13,8 @@ from lnbits.nodes.base import (
|
||||
ChannelBalance,
|
||||
ChannelPoint,
|
||||
ChannelState,
|
||||
ChannelStats,
|
||||
Node,
|
||||
NodeChannel,
|
||||
NodeFees,
|
||||
NodeInfoResponse,
|
||||
@@ -46,13 +49,13 @@ class FakeNode:
|
||||
color="#ffffff",
|
||||
num_peers=1,
|
||||
blockheight=1,
|
||||
channel_stats={
|
||||
"counts": {ChannelState.ACTIVE: 1},
|
||||
"avg_size": 3000,
|
||||
"biggest_size": 3000,
|
||||
"smallest_size": 3000,
|
||||
"total_capacity": 3000,
|
||||
},
|
||||
channel_stats=ChannelStats(
|
||||
counts={ChannelState.ACTIVE: 1},
|
||||
avg_size=3000,
|
||||
biggest_size=3000,
|
||||
smallest_size=3000,
|
||||
total_capacity=3000,
|
||||
),
|
||||
addresses=["127.0.0.1:9735"],
|
||||
onchain_balance_sat=1,
|
||||
onchain_confirmed_sat=1,
|
||||
@@ -146,8 +149,20 @@ class FakeNode:
|
||||
return "fake-node-id"
|
||||
|
||||
|
||||
class FakeFundingSource:
|
||||
def __init__(
|
||||
self,
|
||||
features: list[Feature],
|
||||
node_factory: Callable[[Any], Any] | None,
|
||||
):
|
||||
self.features = features
|
||||
self.__node_cls__ = node_factory
|
||||
|
||||
|
||||
class MockHTTPResponse:
|
||||
def __init__(self, json_data: dict[str, Any], status_error: Exception | None = None):
|
||||
def __init__(
|
||||
self, json_data: dict[str, Any], status_error: Exception | None = None
|
||||
):
|
||||
self._json_data = json_data
|
||||
self._status_error = status_error
|
||||
|
||||
@@ -181,26 +196,24 @@ async def test_node_api_dependency_guards(settings: Settings, mocker: MockerFixt
|
||||
original_public = settings.lnbits_public_node_ui
|
||||
try:
|
||||
settings.lnbits_node_ui = True
|
||||
funding_source = type("FundingSource", (), {})()
|
||||
funding_source.features = []
|
||||
funding_source.__node_cls__ = None
|
||||
funding_source = FakeFundingSource([], None)
|
||||
mocker.patch(
|
||||
"lnbits.core.views.node_api.get_funding_source",
|
||||
return_value=funding_source,
|
||||
)
|
||||
with pytest.raises(Exception) as excinfo:
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
node_api.require_node()
|
||||
assert excinfo.value.status_code == 501
|
||||
|
||||
node_enabled_source = type("FundingSource", (), {})()
|
||||
node_enabled_source.features = [Feature.nodemanager]
|
||||
node_enabled_source.__node_cls__ = lambda wallet: "fake-node"
|
||||
node_enabled_source = FakeFundingSource(
|
||||
[Feature.nodemanager], lambda wallet: "fake-node"
|
||||
)
|
||||
mocker.patch(
|
||||
"lnbits.core.views.node_api.get_funding_source",
|
||||
return_value=node_enabled_source,
|
||||
)
|
||||
settings.lnbits_node_ui = False
|
||||
with pytest.raises(Exception) as disabled:
|
||||
with pytest.raises(HTTPException) as disabled:
|
||||
node_api.require_node()
|
||||
assert disabled.value.status_code == 503
|
||||
|
||||
@@ -208,7 +221,7 @@ async def test_node_api_dependency_guards(settings: Settings, mocker: MockerFixt
|
||||
assert node_api.require_node() == "fake-node"
|
||||
|
||||
settings.lnbits_public_node_ui = False
|
||||
with pytest.raises(Exception) as public_disabled:
|
||||
with pytest.raises(HTTPException) as public_disabled:
|
||||
node_api.check_public()
|
||||
assert public_disabled.value.status_code == 503
|
||||
finally:
|
||||
@@ -222,6 +235,7 @@ async def test_node_api_route_functions_with_fake_node(
|
||||
mocker: MockerFixture,
|
||||
):
|
||||
fake_node = FakeNode()
|
||||
node = cast(Node, fake_node)
|
||||
original_transactions = settings.lnbits_node_ui_transactions
|
||||
settings.lnbits_node_ui_transactions = True
|
||||
rank_response = MockHTTPResponse(
|
||||
@@ -243,23 +257,23 @@ async def test_node_api_route_functions_with_fake_node(
|
||||
try:
|
||||
assert await node_api.api_get_ok() is None
|
||||
|
||||
public_info = await node_api.api_get_public_info(node=fake_node)
|
||||
public_info = await node_api.api_get_public_info(node=node)
|
||||
assert public_info.backend_name == "FakeNode"
|
||||
|
||||
info = await node_api.api_get_info(node=fake_node)
|
||||
info = await node_api.api_get_info(node=node)
|
||||
assert info is not None
|
||||
assert info.id == "node-id"
|
||||
|
||||
channels = await node_api.api_get_channels(node=fake_node)
|
||||
channels = await node_api.api_get_channels(node=node)
|
||||
assert channels is not None
|
||||
assert channels[0].id == "chan-1"
|
||||
|
||||
channel = await node_api.api_get_channel("chan-1", node=fake_node)
|
||||
channel = await node_api.api_get_channel("chan-1", node=node)
|
||||
assert channel is not None
|
||||
assert channel.peer_id == "peer-1"
|
||||
|
||||
created = await node_api.api_create_channel(
|
||||
node=fake_node,
|
||||
node=node,
|
||||
peer_id="peer-1",
|
||||
funding_amount=10_000,
|
||||
push_amount=100,
|
||||
@@ -272,41 +286,41 @@ async def test_node_api_route_functions_with_fake_node(
|
||||
funding_txid=None,
|
||||
output_index=None,
|
||||
force=True,
|
||||
node=fake_node,
|
||||
node=node,
|
||||
)
|
||||
assert deleted is not None
|
||||
assert deleted[0].id == "chan-1"
|
||||
|
||||
await node_api.api_set_channel_fees(
|
||||
"chan-1",
|
||||
node=fake_node,
|
||||
node=node,
|
||||
fee_ppm=42,
|
||||
fee_base_msat=7,
|
||||
)
|
||||
assert fake_node.fees_updated == ("chan-1", 7, 42)
|
||||
|
||||
payments = await node_api.api_get_payments(node=fake_node, filters=Filters())
|
||||
payments = await node_api.api_get_payments(node=node, filters=Filters())
|
||||
assert payments is not None
|
||||
assert payments.total == 1
|
||||
|
||||
invoices = await node_api.api_get_invoices(node=fake_node, filters=Filters())
|
||||
invoices = await node_api.api_get_invoices(node=node, filters=Filters())
|
||||
assert invoices is not None
|
||||
assert invoices.total == 1
|
||||
|
||||
peers = await node_api.api_get_peers(node=fake_node)
|
||||
peers = await node_api.api_get_peers(node=node)
|
||||
assert peers[0].id == "peer-1"
|
||||
|
||||
connect = await node_api.api_connect_peer(
|
||||
uri="peer-1@127.0.0.1:9735", node=fake_node
|
||||
uri="peer-1@127.0.0.1:9735", node=node
|
||||
)
|
||||
assert connect["uri"] == "peer-1@127.0.0.1:9735"
|
||||
|
||||
disconnect = await node_api.api_disconnect_peer("peer-1", node=fake_node)
|
||||
disconnect = await node_api.api_disconnect_peer("peer-1", node=node)
|
||||
assert disconnect["peer_id"] == "peer-1"
|
||||
|
||||
rank = await node_api.api_get_1ml_stats(node=fake_node)
|
||||
rank = await node_api.api_get_1ml_stats(node=node)
|
||||
assert rank is not None
|
||||
assert rank["channelcount"] == 2
|
||||
assert rank.channelcount == 2
|
||||
finally:
|
||||
settings.lnbits_node_ui_transactions = original_transactions
|
||||
|
||||
@@ -317,6 +331,7 @@ async def test_node_api_transactions_and_rank_errors(
|
||||
mocker: MockerFixture,
|
||||
):
|
||||
fake_node = FakeNode()
|
||||
node = cast(Node, fake_node)
|
||||
original_transactions = settings.lnbits_node_ui_transactions
|
||||
settings.lnbits_node_ui_transactions = False
|
||||
|
||||
@@ -334,16 +349,16 @@ async def test_node_api_transactions_and_rank_errors(
|
||||
)
|
||||
|
||||
try:
|
||||
with pytest.raises(Exception) as payments:
|
||||
await node_api.api_get_payments(node=fake_node, filters=Filters())
|
||||
with pytest.raises(HTTPException) as payments:
|
||||
await node_api.api_get_payments(node=node, filters=Filters())
|
||||
assert payments.value.status_code == 503
|
||||
|
||||
with pytest.raises(Exception) as invoices:
|
||||
await node_api.api_get_invoices(node=fake_node, filters=Filters())
|
||||
with pytest.raises(HTTPException) as invoices:
|
||||
await node_api.api_get_invoices(node=node, filters=Filters())
|
||||
assert invoices.value.status_code == 503
|
||||
|
||||
with pytest.raises(Exception) as rank:
|
||||
await node_api.api_get_1ml_stats(node=fake_node)
|
||||
with pytest.raises(HTTPException) as rank:
|
||||
await node_api.api_get_1ml_stats(node=node)
|
||||
assert rank.value.status_code == 404
|
||||
assert rank.value.detail == "Node not found on 1ml.com"
|
||||
finally:
|
||||
|
||||
@@ -11,6 +11,7 @@ from lnbits.core.models.payments import CancelInvoice, CreatePayment, SettleInvo
|
||||
from lnbits.core.models.users import AccountId
|
||||
from lnbits.core.models.wallets import KeyType, WalletTypeInfo
|
||||
from lnbits.core.services.payments import create_wallet_invoice
|
||||
from lnbits.core.services.users import create_user_account
|
||||
from lnbits.core.views.payment_api import (
|
||||
api_all_payments_paginated,
|
||||
api_payments_cancel,
|
||||
@@ -20,7 +21,6 @@ from lnbits.core.views.payment_api import (
|
||||
api_payments_settle,
|
||||
api_payments_wallets_stats,
|
||||
)
|
||||
from lnbits.core.services.users import create_user_account
|
||||
from lnbits.db import Filters
|
||||
from lnbits.wallets.base import InvoiceResponse
|
||||
|
||||
|
||||
@@ -96,5 +96,7 @@ async def test_user_api_create_wallet_validates_currency():
|
||||
with pytest.raises(ValueError, match="Currency 'INVALID' not allowed."):
|
||||
await api_users_create_user_wallet(user.id, name="invalid", currency="INVALID")
|
||||
|
||||
wallet = await api_users_create_user_wallet(user.id, name="eur wallet", currency="EUR")
|
||||
wallet = await api_users_create_user_wallet(
|
||||
user.id, name="eur wallet", currency="EUR"
|
||||
)
|
||||
assert wallet.currency == "EUR"
|
||||
|
||||
@@ -13,7 +13,9 @@ def _admin_headers(adminkey: str) -> dict[str, str]:
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_wallet_api_share_invite_reject_accept_and_delete(http_client: AsyncClient):
|
||||
async def test_wallet_api_share_invite_reject_accept_and_delete(
|
||||
http_client: AsyncClient,
|
||||
):
|
||||
owner = await create_user_account(
|
||||
Account(
|
||||
id=uuid4().hex,
|
||||
@@ -129,7 +131,9 @@ async def test_wallet_api_paginated_update_reset_and_store_paylinks(
|
||||
assert renamed.json()["name"] == "renamed-wallet"
|
||||
|
||||
original_admin_key = extra_wallet.adminkey
|
||||
reset = await http_client.put(f"/api/v1/wallet/reset/{extra_wallet.id}?usr={user.id}")
|
||||
reset = await http_client.put(
|
||||
f"/api/v1/wallet/reset/{extra_wallet.id}?usr={user.id}"
|
||||
)
|
||||
assert reset.status_code == 200
|
||||
assert reset.json()["adminkey"] != original_admin_key
|
||||
|
||||
@@ -181,4 +185,6 @@ async def test_wallet_api_shared_wallet_requires_source_id(http_client: AsyncCli
|
||||
json={"wallet_type": "lightning-shared"},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.json()["detail"] == "Shared wallet ID is required for shared wallets."
|
||||
assert (
|
||||
response.json()["detail"] == "Shared wallet ID is required for shared wallets."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user