feat: file mobile Drafts sequentially (Closes #629)
This commit is contained in:
1 parent
1079ec6561
commit
7948d2e353
8 files changed
+176
-18
No files matched your search
@@ -684,6 +684,7 @@ def test_install_precaches_complete_subpath_scoped_app_shell():
|
||||
"/dashboard/static/widgets.js",
|
||||
"/dashboard/static/drafts.js",
|
||||
"/dashboard/static/unfiled-captures.js",
|
||||
"/dashboard/static/draft-filing-session.js",
|
||||
"/dashboard/static/draft-capacity-dialog.js",
|
||||
"/dashboard/static/outbox-coordinator.js",
|
||||
"/dashboard/static/issue-outbox.js",
|
||||
|
||||
@@ -8,6 +8,7 @@ from tests.dashboard_bundle import dashboard
|
||||
|
||||
|
||||
UNFILED = Path(__file__).parents[1] / "frontend" / "unfiled-captures.js"
|
||||
DRAFT_SESSION = Path(__file__).parents[1] / "frontend" / "draft-filing-session.js"
|
||||
|
||||
|
||||
def run_node(script: str):
|
||||
@@ -15,6 +16,28 @@ def run_node(script: str):
|
||||
return json.loads(result.stdout)
|
||||
|
||||
|
||||
def test_draft_filing_session_navigates_stable_capture_ids_and_reconciles_removed_items():
|
||||
script = f"""
|
||||
const createDraftFilingSession = require({json.dumps(str(DRAFT_SESSION))});
|
||||
let captures = [{{id:'newest'}}, {{id:'middle'}}, {{id:'oldest'}}];
|
||||
const session = createDraftFilingSession({{list:()=>captures}});
|
||||
const opened = session.start('middle');
|
||||
const skipped = session.next();
|
||||
captures = [{{id:'newest'}}];
|
||||
const afterFiled = session.removeCurrentAndNext('oldest');
|
||||
const previous = session.previous();
|
||||
process.stdout.write(JSON.stringify({{opened,skipped,afterFiled,previous}}));
|
||||
"""
|
||||
output = run_node(script)
|
||||
|
||||
assert output == {
|
||||
"opened": {"id": "middle", "position": 2, "total": 3, "remaining": 1},
|
||||
"skipped": {"id": "oldest", "position": 3, "total": 3, "remaining": 0},
|
||||
"afterFiled": {"id": "newest", "position": 1, "total": 1, "remaining": 0},
|
||||
"previous": {"id": "newest", "position": 1, "total": 1, "remaining": 0},
|
||||
}
|
||||
|
||||
|
||||
def test_unfiled_captures_block_at_capacity_until_oldest_is_explicitly_replaced():
|
||||
script = f"""
|
||||
const createUnfiledCaptures = require({json.dumps(str(UNFILED))});
|
||||
@@ -335,13 +358,13 @@ async def test_mobile_composer_exposes_cold_offline_save_and_account_safe_resume
|
||||
assert "requestAnimationFrame(() =>" in html
|
||||
assert "savedCard?.scrollIntoView({block:'nearest'})" in html
|
||||
assert "Saved to Drafts. Choose a repository when you’re ready to file it." in html
|
||||
assert "await unfiledCaptures.resume(item.capture_id, activeFlushLogin)" in html
|
||||
assert "await dependencies.captures.resume(captureId, dependencies.getLogin())" in DRAFT_SESSION.read_text()
|
||||
assert "await createIssueAttachmentController.serialize()" in html
|
||||
assert "createUnfiledAttachmentStore()" in html
|
||||
assert "createIssueAttachmentController.restore(resumed.attachment)" in html
|
||||
assert "await unfiledCaptures.completeResume(resumedUnfiledCaptureId)" in html
|
||||
assert "dependencies.attachment[resumed.attachment ? 'restore' : 'clear'](resumed.attachment)" in DRAFT_SESSION.read_text()
|
||||
assert "await unfiledCaptures.completeResume(rUC)" in html
|
||||
assert "item.hasAttachment ? ' · Screenshot attached' : ''" in html
|
||||
assert "issueCapture.saveDraft(resumed)" in html
|
||||
assert "dependencies.issueCapture.saveDraft(resumed)" in DRAFT_SESSION.read_text()
|
||||
assert "item.kind === 'unfiled-issue'" in html
|
||||
assert '.create-issue-actions button { min-height:44px;' in html
|
||||
assert '.draft-card:focus-visible' in html
|
||||
@@ -349,6 +372,25 @@ async def test_mobile_composer_exposes_cold_offline_save_and_account_safe_resume
|
||||
assert '@media(max-width:320px)' in html
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_mobile_drafts_expose_a_safe_sequential_filing_session():
|
||||
html = await dashboard()
|
||||
|
||||
assert '<script src="static/draft-filing-session.js"></script>' in html
|
||||
assert 'id="draft-filing-session"' in html
|
||||
assert 'id="draft-filing-progress"' in html
|
||||
assert 'id="previous-draft"' in html
|
||||
assert 'id="skip-draft"' in html
|
||||
assert "dFS.start(item.capture_id)" in html
|
||||
assert "await dFS.nextCapture()" in html
|
||||
assert "await dFS.advance(fS.id)" in html
|
||||
feature = DRAFT_SESSION.read_text()
|
||||
assert "Draft ${state.position} of ${state.total}" in feature
|
||||
assert "qs('#submit-new-issue').textContent = state.remaining ? 'File & next' : 'File final Draft'" in feature
|
||||
assert '.draft-filing-session-actions button { min-height:44px;' in html
|
||||
assert 'padding-bottom:calc(10px + env(safe-area-inset-bottom))' in html
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_mobile_capture_capacity_requires_an_explicit_preserving_decision():
|
||||
html = await dashboard()
|
||||
|
||||
Reference in new issue
Block a user