2nd stage draft pydantic
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from lnbits.core.models.extensions import InstallableExtension
|
||||
from lnbits.core.models.lnurl import StoredPayLink
|
||||
from lnbits.core.models.users import UserLabel
|
||||
from lnbits.core.models.wallets import (
|
||||
Wallet,
|
||||
WalletPermission,
|
||||
WalletSharePermission,
|
||||
WalletShareStatus,
|
||||
)
|
||||
from lnbits.db import dict_to_model
|
||||
|
||||
|
||||
def test_user_label_uses_pydantic_v2_pattern_validation():
|
||||
label = UserLabel(name="label-1", color="#FF00AA")
|
||||
|
||||
assert label.name == "label-1"
|
||||
assert label.color == "#FF00AA"
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
UserLabel(name="label-1", color="bad-color")
|
||||
|
||||
|
||||
def test_wallet_has_stored_paylinks_field_and_mirrors_it():
|
||||
source_wallet = Wallet(
|
||||
id="source-wallet-id",
|
||||
user="source-user-id",
|
||||
name="source",
|
||||
adminkey="admin-key",
|
||||
inkey="invoice-key",
|
||||
)
|
||||
source_wallet.stored_paylinks.links.append(
|
||||
StoredPayLink(lnurl="lnurl1example", label="saved paylink")
|
||||
)
|
||||
|
||||
shared_wallet = Wallet(
|
||||
id="shared-wallet-id",
|
||||
user="shared-user-id",
|
||||
name="shared",
|
||||
adminkey="shared-admin-key",
|
||||
inkey="shared-invoice-key",
|
||||
)
|
||||
source_wallet.extra.shared_with.append(
|
||||
WalletSharePermission(
|
||||
request_id="share-request-id",
|
||||
username="shared-user",
|
||||
shared_with_wallet_id=shared_wallet.id,
|
||||
permissions=[WalletPermission.VIEW_PAYMENTS],
|
||||
status=WalletShareStatus.APPROVED,
|
||||
)
|
||||
)
|
||||
shared_wallet.mirror_shared_wallet(source_wallet)
|
||||
|
||||
assert shared_wallet.stored_paylinks.links[0].lnurl == "lnurl1example"
|
||||
assert shared_wallet.stored_paylinks.links[0].label == "saved paylink"
|
||||
|
||||
|
||||
def test_db_dict_to_model_parses_optional_nested_pydantic_v2_models():
|
||||
ext = dict_to_model(
|
||||
{
|
||||
"id": "ext-id",
|
||||
"name": "Extension",
|
||||
"version": "1.0.0",
|
||||
"active": 1,
|
||||
"meta": (
|
||||
'{"installed_release": {"name": "Release", "version": "1.0.0", '
|
||||
'"archive": "https://example.com/release.zip", '
|
||||
'"source_repo": "lnbits/example"}, "payments": [], '
|
||||
'"dependencies": [], "featured": false, '
|
||||
'"has_paid_release": false, "has_free_release": false}'
|
||||
),
|
||||
},
|
||||
InstallableExtension,
|
||||
)
|
||||
|
||||
assert ext.meta is not None
|
||||
assert ext.meta.installed_release is not None
|
||||
assert ext.meta.installed_release.source_repo == "lnbits/example"
|
||||
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from lnbits.settings import RedirectPath
|
||||
from lnbits.settings import EditableSettings, RedirectPath, Settings, UpdateSettings
|
||||
|
||||
lnurlp_redirect_path = {
|
||||
"from_path": "/.well-known/lnurlp",
|
||||
@@ -166,3 +167,60 @@ def test_redirect_path_new_path_from(lnurlp: RedirectPath):
|
||||
lnurlp.new_path_from("/.well-known/lnurlp/path/more")
|
||||
== "/lnurlp/api/v1/well-known/path/more"
|
||||
)
|
||||
|
||||
|
||||
def test_settings_loads_env_and_dotenv_values(tmp_path, monkeypatch):
|
||||
env_file = tmp_path / ".env"
|
||||
env_file.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"lnbits_admin_users=alice,bob",
|
||||
"STRIKE_API_ENDPOINT=https://dotenv.strike.example",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.chdir(tmp_path)
|
||||
monkeypatch.setenv("LNBITS_ALLOWED_USERS", ' ["carol", "dave"] ')
|
||||
monkeypatch.setenv("STRIKE_API_KEY", "secret-key")
|
||||
monkeypatch.setenv("STRIKE_API_ENDPOINT", "https://env.strike.example")
|
||||
|
||||
settings = Settings()
|
||||
|
||||
assert settings.lnbits_admin_users == ["alice", "bob"]
|
||||
assert settings.lnbits_allowed_users == ["carol", "dave"]
|
||||
assert settings.strike_api_endpoint == "https://env.strike.example"
|
||||
assert settings.strike_api_key == "secret-key"
|
||||
|
||||
|
||||
def test_editable_settings_from_dict_ignores_unknown_fields():
|
||||
editable_settings = EditableSettings.from_dict(
|
||||
{"lnbits_admin_users": ["alice"], "unknown_setting": "ignored"}
|
||||
)
|
||||
|
||||
assert editable_settings.lnbits_admin_users == ["alice"]
|
||||
assert "unknown_setting" not in editable_settings.model_dump()
|
||||
|
||||
|
||||
def test_update_settings_splits_string_lists_and_forbids_extra_fields():
|
||||
updated = UpdateSettings.model_validate(
|
||||
{
|
||||
"lnbits_admin_users": "alice,bob",
|
||||
"strike_api_endpoint": "https://api.strike.me/v1",
|
||||
"strike_api_key": "secret-key",
|
||||
}
|
||||
)
|
||||
|
||||
assert updated.lnbits_admin_users == ["alice", "bob"]
|
||||
assert updated.strike_api_endpoint == "https://api.strike.me/v1"
|
||||
assert updated.strike_api_key == "secret-key"
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
UpdateSettings.model_validate({"unknown_setting": True})
|
||||
|
||||
|
||||
def test_update_settings_schema_does_not_include_env_names():
|
||||
schema = UpdateSettings.model_json_schema()
|
||||
|
||||
assert "properties" in schema
|
||||
assert all("env_names" not in prop for prop in schema["properties"].values())
|
||||
|
||||
Reference in New Issue
Block a user