import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
def test_wasm_frontend_assets_are_registered_in_component_bundle():
package_json = json.loads((ROOT / "package.json").read_text(encoding="utf-8"))
components = package_json["bundle"]["components"]
assert "js/wasm-extension-component.js" in components
assert "js/components/lnbits-extension-permissions.js" in components
assert "js/components/admin/lnbits-admin-wasm-runtime.js" in components
assert "js/components/admin/lnbits-admin-wasm-limit-config.js" in components
def test_wasm_extension_routes_keep_global_wallet_dialog_mounted():
base_template = (ROOT / "lnbits/templates/base.html").read_text(encoding="utf-8")
wallet_dialog_start = base_template.index("", wallet_dialog_start
)
wallet_dialog = base_template[wallet_dialog_start:wallet_dialog_end]
assert 'v-if="g.user && !g.isPublicPage"' in wallet_dialog
assert "!$route.path.startsWith('/ext/')" not in wallet_dialog
def test_wasm_frontend_bridge_restricts_api_routes_and_realtime_actions():
bridge = (ROOT / "lnbits/static/js/wasm-extension-component.js").read_text(
encoding="utf-8"
)
assert "allowedApiRoute(method, path)" in bridge
assert "url.origin !== window.location.origin" in bridge
assert "Extension API route is not allowed." in bridge
assert "extensionRoute(path)" in bridge
assert "Extension route must stay inside this extension." in bridge
assert "message.action === 'payment.subscribe'" in bridge
assert "message.action === 'payment.unsubscribe'" in bridge
assert "message.action === 'websocket.subscribe'" in bridge
assert "message.action === 'websocket.unsubscribe'" in bridge
assert "message.action === 'websocket.send'" in bridge
assert "sendWebsocket(message)" in bridge
assert "Unknown websocket subscription." not in bridge
assert "if (!subscription) {\n return\n }" in bridge
assert "message.action === 'navigation.replace'" in bridge
assert "message.action === 'navigation.open_new_tab'" in bridge
assert "openNewTab(message)" in bridge
assert "newTabUrl(rawUrl)" in bridge
assert "copyNewTabLink()" in bridge
assert "navigator.clipboard.writeText(prompt.url)" in bridge
assert 'label="Copy Link"' in bridge
assert "window.open(prompt.url, '_blank', 'noopener,noreferrer')" in bridge
assert "Only HTTP and HTTPS links can be opened." in bridge
assert "This link is not on the same domain as this LNbits page." in bridge
assert "message.action === 'storage.session.get'" in bridge
assert "message.action === 'storage.session.set'" in bridge
assert "bridgeSessionStorageKey(rawKey)" in bridge
assert "lnbits.ext.session.${this.bridge.extensionId}.${key}" in bridge
assert "hasBridgePermission('websocket.subscribe')" in bridge
assert "/api/v1/ext/ws/${encodeURIComponent(" in bridge
assert "/api/v1/ws/${encodeURIComponent(paymentHash)}" in bridge
assert "message.action === 'ui.scan_qr'" in bridge
def test_wasm_extension_install_ui_requests_permissions_before_install_paths():
extensions_page = (ROOT / "lnbits/static/js/pages/extensions.js").read_text(
encoding="utf-8"
)
permissions_template = (
ROOT / "lnbits/templates/components/lnbits-extension-permissions.vue"
).read_text(encoding="utf-8")
wasm_bulk_update_skip_message = (
"Skipping ${ext.id}; this extension update requires permission approval."
)
assert "await this.resolveExtensionPermissionGrant(release)" in extensions_page
assert "permissions: grantedPermissions" in extensions_page
assert "release.extension_type === 'wasm'" in extensions_page
assert "this.selectedExtension?.isWasm === true" in extensions_page
assert "saveManagedExtensionPermissions()" in extensions_page
assert (
"`/api/v1/extension/${this.selectedExtension.id}/permissions`"
in extensions_page
)
assert "editableAppendPublicLimits" in permissions_template
assert "max_rows_per_source" in permissions_template
assert "editableWebsocketPublishLimits" in permissions_template
assert "max_messages_per_second" in permissions_template
assert wasm_bulk_update_skip_message in extensions_page
def test_extension_install_ui_warns_only_for_python_releases():
extensions_template = (ROOT / "lnbits/templates/pages/extensions.vue").read_text(
encoding="utf-8"
)
assert "release.extension_type !== 'wasm'" in extensions_template
assert (
"'Python extensions have full server access. Trust the source.'"
in extensions_template
)
assert '