fix: purge every private offline store (Closes #889)
This commit is contained in:
1 parent
2eea42859e
commit
a60f2cfac3
10 files changed
+95
-18
No files matched your search
@@ -300,7 +300,7 @@ def test_offline_shell_precaches_exact_runtime_without_superseded_page_modules()
|
||||
|
||||
assert f"BASE + '{build.runtime_name}'" in build.service_worker_source
|
||||
for source in build.page_sources:
|
||||
if source == "static/background-issue-sync.js":
|
||||
if f"importScripts(BASE + '{source}')" in build.service_worker_source:
|
||||
continue
|
||||
assert f"BASE + '{source}'" not in build.service_worker_source
|
||||
|
||||
|
||||
@@ -100,7 +100,9 @@ const controller = createLoginController({{
|
||||
async def test_login_loads_private_data_purger_before_controller():
|
||||
html = await login()
|
||||
|
||||
assert '<script src="static/private-data-registry.js"></script>' in html
|
||||
assert '<script src="static/private-device-data.js"></script>' in html
|
||||
assert html.index('static/private-data-registry.js') < html.index('static/private-device-data.js')
|
||||
assert html.index('static/private-device-data.js') < html.index('static/login.js')
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FRONTEND = ROOT / "frontend"
|
||||
REGISTRY = FRONTEND / "private-data-registry.js"
|
||||
|
||||
|
||||
def test_private_database_registry_covers_every_shipped_indexeddb_store():
|
||||
harness = f"""
|
||||
const databases = require({json.dumps(str(REGISTRY))});
|
||||
process.stdout.write(JSON.stringify(databases));
|
||||
"""
|
||||
completed = subprocess.run(
|
||||
["node", "-e", harness], text=True, capture_output=True, check=True
|
||||
)
|
||||
registered = set(json.loads(completed.stdout))
|
||||
|
||||
opened = set()
|
||||
for path in FRONTEND.glob("*.js"):
|
||||
source = path.read_text()
|
||||
opened.update(re.findall(r"dbName\s*=\s*['\"](stackchain-[^'\"]+)['\"]", source))
|
||||
opened.update(re.findall(r"createIndexedDbTransaction\([^\n]+['\"](stackchain-[^'\"]+)['\"]", source))
|
||||
|
||||
assert registered == opened
|
||||
assert registered == {
|
||||
"stackchain-background-outbox-v1",
|
||||
"stackchain-offline-work-v2",
|
||||
"stackchain-unfiled-captures-v1",
|
||||
}
|
||||
|
||||
|
||||
def test_every_private_data_purge_context_consumes_the_shared_registry():
|
||||
for name in ("private-device-data.js", "session.js", "service-worker.js"):
|
||||
source = (FRONTEND / name).read_text()
|
||||
assert "stackchainPrivateDatabases" in source
|
||||
assert not re.search(r"deletePrivateDatabase\(['\"]stackchain-", source)
|
||||
|
||||
html = (FRONTEND / "index.html").read_text()
|
||||
assert html.index('static/private-data-registry.js') < html.index('static/session.js')
|
||||
@@ -6,6 +6,7 @@ import pytest
|
||||
|
||||
|
||||
WORKER = Path(__file__).resolve().parents[1] / "frontend" / "service-worker.js"
|
||||
PRIVATE_DATA_REGISTRY = WORKER.parent / "private-data-registry.js"
|
||||
|
||||
|
||||
def run_worker_scenario(scenario: str) -> dict:
|
||||
@@ -46,6 +47,7 @@ const context = {{
|
||||
location: {{ href: 'https://forge.example/dashboard/service-worker.js', origin: 'https://forge.example' }},
|
||||
__STACKCHAIN_NAVIGATION_TIMEOUT_MS: 15,
|
||||
__STACKCHAIN_PUSH_ACTION_TIMEOUT_MS: 15,
|
||||
stackchainPrivateDatabases: require({json.dumps(str(PRIVATE_DATA_REGISTRY))}),
|
||||
__STACKCHAIN_SHARED_ATTACHMENT_STORE: {{
|
||||
put: async (id, value) => {{ state.sharedRecords[id] = value; }},
|
||||
get: async id => state.sharedRecords[id] || null,
|
||||
@@ -316,7 +318,9 @@ def test_revoked_background_session_purges_worker_data_and_notifies_dashboard_cl
|
||||
assert result["outcome"] == {"status": 401, "code": "session_revoked"}
|
||||
assert result["state"]["outboxPurges"] == 1
|
||||
assert result["state"]["deletedDatabases"] == [
|
||||
"stackchain-unfiled-captures-v1"
|
||||
"stackchain-background-outbox-v1",
|
||||
"stackchain-offline-work-v2",
|
||||
"stackchain-unfiled-captures-v1",
|
||||
]
|
||||
assert result["state"]["deleted"] == ["stackchain-dashboard-old"]
|
||||
assert result["state"]["clientMessages"] == [
|
||||
@@ -406,7 +410,9 @@ def test_device_purge_message_stops_worker_outbox_and_acknowledges_completion():
|
||||
|
||||
assert result["state"]["outboxPurges"] == 1
|
||||
assert result["state"]["deletedDatabases"] == [
|
||||
"stackchain-unfiled-captures-v1"
|
||||
"stackchain-background-outbox-v1",
|
||||
"stackchain-offline-work-v2",
|
||||
"stackchain-unfiled-captures-v1",
|
||||
]
|
||||
assert result["replies"] == [{"ok": True}]
|
||||
|
||||
@@ -999,7 +1005,9 @@ def test_expired_offline_lease_purges_private_worker_data_and_refuses_cached_she
|
||||
assert result["body"] == "Your Stackchain session expired. Reconnect and sign in."
|
||||
assert result["state"]["outboxPurges"] == 1
|
||||
assert result["state"]["deletedDatabases"] == [
|
||||
"stackchain-unfiled-captures-v1"
|
||||
"stackchain-background-outbox-v1",
|
||||
"stackchain-offline-work-v2",
|
||||
"stackchain-unfiled-captures-v1",
|
||||
]
|
||||
assert result["state"]["deleted"] == ["stackchain-dashboard-old"]
|
||||
assert "private cached dashboard" not in result["body"]
|
||||
|
||||
Reference in new issue
Block a user