feat: prioritize mobile delivery recovery (Closes #1012)
CI / lint (pull_request) Successful in 2m58s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 2m5s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-17 08:30:09 +00:00
1 parent db28cc5690
commit 246f995b56
5 files changed
+58 -11

No files matched your search

@@ -101,6 +101,15 @@ def test_release_artifact_bootstraps_mobile_home_and_returns_from_insights(
bounds = control.bounding_box()
assert bounds and bounds["height"] >= 44
page.locator('[data-mobile-task="queues"]').click()
delivery_queue = page.locator('[data-mobile-queue="delivery"]')
expect(delivery_queue).to_be_visible()
expect(delivery_queue).to_contain_text("Delivery")
delivery_bounds = delivery_queue.bounding_box()
assert delivery_bounds and delivery_bounds["height"] >= 44
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
page.locator("#close-mobile-queues").click()
page.locator("#app-menu-toggle").click()
page.locator("#open-insights").click()
expect(page.locator("#insights-sheet")).to_be_visible()
+42 -7
View File
@@ -355,7 +355,7 @@ sheet.close = function () {{ this.open = false; this.listeners.close?.(); }};
const close = new FakeElement();
const badge = new FakeElement();
const deadline = new FakeElement();
const rows = Object.fromEntries(['today','agenda','attention','update','filed','later','draft','recaps'].map(name => [name, new FakeElement()]));
const rows = Object.fromEntries(['today','agenda','delivery','attention','update','filed','later','draft','recaps'].map(name => [name, new FakeElement()]));
const counts = Object.fromEntries(Object.keys(rows).map(name => [name, new FakeElement()]));
const selected = [];
const utilities = [];
@@ -366,7 +366,7 @@ const dock = createDock({{
observe() {{}},
}});
dock.start();
dock.updateQueues({{today:2, agenda:5, attention:1, update:5, filed:2, later:3, draft:4}});
dock.updateQueues({{today:2, agenda:5, delivery:1, attention:1, update:5, filed:2, later:3, draft:4}});
queues.click();
const opened = sheet.open;
rows.update.click();
@@ -411,9 +411,9 @@ process.stdout.write(JSON.stringify({{
"utilities": ["recaps:trigger"],
"badge": "0 active",
"populated": {
"badge": "6 active",
"badge": "7 active",
"badgeHidden": False,
"badgeLabel": "Queues: Today 2, Agenda 5 due, Attention 1, Updates 5, Filed 2, Later 3, Drafts 4; 6 active queues",
"badgeLabel": "Queues: Today 2, Agenda 5 due, Delivery 1, Attention 1, Updates 5, Filed 2, Later 3, Drafts 4; 7 active queues",
"deadline": "5 due",
"deadlineHidden": False,
"agendaDue": "true",
@@ -422,13 +422,13 @@ process.stdout.write(JSON.stringify({{
"badge": "1 active",
"badgeHidden": False,
"deadlineHidden": True,
"badgeLabel": "Queues: Today 0, Agenda 0 due, Attention 0, Updates 7, Filed 0, Later 0, Drafts 0; 1 active queue",
"badgeLabel": "Queues: Today 0, Agenda 0 due, Delivery 0, Attention 0, Updates 7, Filed 0, Later 0, Drafts 0; 1 active queue",
},
"clearedBadgeHidden": True,
"clearedDeadlineHidden": True,
"clearedAgendaDue": None,
"clearedBadgeLabel": "Queues: no active queues; no upcoming deadlines",
"counts": {"today": "0", "agenda": "0", "attention": "0", "update": "0", "filed": "0", "later": "0", "draft": "0", "recaps": "0"},
"counts": {"today": "0", "agenda": "0", "delivery": "0", "attention": "0", "update": "0", "filed": "0", "later": "0", "draft": "0", "recaps": "0"},
"updateLabel": "Updates, 0 unread conversations",
"queueFocuses": 3,
"columnState": None,
@@ -503,6 +503,37 @@ process.stdout.write(JSON.stringify({{result, calls}}));
assert json.loads(result.stdout) == {"result": "opened", "calls": ["delivery-recovery"]}
def test_mobile_work_prioritizes_and_revalidates_actionable_delivery_recovery():
script = f"""
const createLauncher = require({json.dumps(str(QUEUE_LAUNCHER))});
const calls = [];
let counts = {{delivery:2, attention:3, today:1, update:4}};
const launcher = createLauncher({{
getCounts: () => counts,
openDelivery: () => {{ calls.push('delivery-recovery'); return 'opened-delivery'; }},
openUpdates: () => {{ calls.push('updates'); return 'opened-updates'; }},
selectFilter: name => calls.push('filter:' + name),
firstAction: () => null,
announce: () => {{}},
openFindWork: () => calls.push('find'),
}});
const delivery = launcher.recommend();
const opened = launcher.continueWork();
counts = {{delivery:0, attention:0, today:0, update:4}};
const afterRecovery = launcher.recommend();
process.stdout.write(JSON.stringify({{delivery, opened, afterRecovery, calls}}));
"""
result = subprocess.run(["node", "-e", script], capture_output=True, text=True)
assert result.returncode == 0, result.stderr
assert json.loads(result.stdout) == {
"delivery": {"name": "delivery", "count": 2, "label": "Recover Delivery (2)"},
"opened": "opened-delivery",
"afterRecovery": {"name": "update", "count": 4, "label": "Resume Updates (4)"},
"calls": ["delivery-recovery"],
}
def test_mobile_work_continues_into_filed_follow_up_before_later_work():
script = f"""
const createLauncher = require({json.dumps(str(QUEUE_LAUNCHER))});
@@ -600,7 +631,7 @@ const work = {{attributes: {{}}, setAttribute(name, value) {{ this.attributes[na
const workLabel = {{textContent:''}};
const dock = createDock({{nav:{{}}, buttons:{{work}}, workLabel}});
const labels = {{}};
for (const mode of ['attention','update','agenda','filed','later','draft']) {{
for (const mode of ['delivery','attention','update','agenda','filed','later','draft']) {{
dock.updateWork(mode);
labels[mode] = [workLabel.textContent, work.attributes['aria-label']];
}}
@@ -610,6 +641,7 @@ process.stdout.write(JSON.stringify(labels));
assert result.returncode == 0, result.stderr
assert json.loads(result.stdout) == {
"delivery": ["Delivery", "Open Delivery"],
"attention": ["Attention", "Open Attention"],
"update": ["Updates", "Resume Updates"],
"agenda": ["Agenda", "Open Agenda"],
@@ -646,6 +678,9 @@ async def test_dashboard_renders_and_wires_mobile_queue_switcher():
assert "counts.agenda = agendaItems.length;" in html
assert 'data-agenda-group' in html
assert 'data-mobile-queue="attention"' in html
assert 'data-mobile-queue="delivery"' in html
assert '<strong>Delivery</strong><small>Needs recovery</small>' in html
assert 'data-mobile-queue-count="delivery"' in html
assert 'data-mobile-queue="update"' in html
assert '<strong>Updates</strong><small>Unread conversations</small>' in html
assert 'data-mobile-queue="filed"' in html