fix: finish identity recovery before workspace readiness
CI / lint (pull_request) Successful in 3m45s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 7m28s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-27 14:34:13 +00:00
1 parent 5ccf499b1a
commit 02b9fdd2e4
6 files changed
+111 -8

No files matched your search

@@ -60,6 +60,7 @@ def test_release_artifact_guides_an_empty_mobile_account_to_first_work(
expect(sheet).to_be_hidden()
expect(page.locator("#find-work-sheet")).to_be_visible()
page.locator("#close-find-work").click()
expect(page.locator("#find-work-sheet")).to_be_hidden()
context.set_offline(True)
page.locator('[data-mobile-task="work"]').click()
@@ -70,8 +71,9 @@ def test_release_artifact_guides_an_empty_mobile_account_to_first_work(
expect(page.locator("#mobile-first-task-create")).to_be_focused()
page.locator("#close-mobile-first-task").click()
expect(sheet).to_be_hidden()
context.set_offline(False)
page.evaluate(
probe_result = page.evaluate(
"""() => {
document.querySelector('[data-mobile-today-hud]').hidden = false;
localStorage.setItem('stackchain.first-task.v1:timmy', 'coaching');
@@ -82,17 +84,54 @@ def test_release_artifact_guides_an_empty_mobile_account_to_first_work(
getLogin: () => 'timmy', hasWork: () => true, isTodayActive: () => true,
coach: isolatedCoach,
});
return window.firstTaskOutcomeProbe.refresh();
return {
result: window.firstTaskOutcomeProbe.refresh(),
state: localStorage.getItem('stackchain.first-task.v1:timmy'),
mobile: matchMedia('(max-width: 600px)').matches,
};
}"""
)
assert probe_result == {"result": "coaching", "state": "coaching", "mobile": True}
coach = page.locator("[data-mobile-first-task-coach]")
expect(coach).to_be_visible()
try:
expect(coach).to_be_visible()
except AssertionError as error:
raise AssertionError(page.evaluate("""() => {
const coach = document.querySelector('[data-mobile-first-task-coach]');
const hud = coach.closest('[data-mobile-today-hud]');
return {
coachHidden: coach.hidden,
coachDisplay: getComputedStyle(coach).display,
hudHidden: hud.hidden,
hudOverlay: hud.getAttribute('data-overlay-hidden'),
hudDisplay: getComputedStyle(hud).display,
open: Array.from(document.querySelectorAll('dialog, .open'))
.filter(element => element.open || element.classList.contains('open'))
.map(element => element.id || element.className),
};
}""")) from error
expect(coach).to_contain_text("Complete your first task")
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
assert page.evaluate("window.firstTaskOutcomeProbe.completeOutcome()") is True
completion = page.evaluate("""() => {
const completed = window.firstTaskOutcomeProbe.completeOutcome();
return {
completed,
status: document.querySelector('#today-sync-status').textContent,
pending: Object.keys(localStorage).filter(key =>
key.startsWith('stackchain.today-sync.v1.timmy.operation.')),
};
}""")
assert completion["completed"] is True
assert completion["pending"]
assert "sync pending" in completion["status"]
expect(page.locator("#mobile-first-task-receipt")).to_be_visible()
expect(coach).to_be_hidden()
expect(page.locator("#today-sync-status")).to_contain_text("Today saved to account")
remote_activation = page.evaluate("""async () => {
const response = await fetch('api/v1/today');
return (await response.json()).first_task_state;
}""")
assert remote_activation == "complete"
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
fresh_context = browser.new_context(
+10 -1
View File
@@ -278,7 +278,16 @@ def test_release_artifact_plans_hands_off_and_opens_next_mobile_issue(tmp_path:
assert page.evaluate("""() => !Object.keys(localStorage).some(
key => key.startsWith('stackchain.today-sync.v1.timmy.operation.')
)""")
expect(page.locator("#today-break-status")).to_contain_text("On break · resume in")
try:
expect(page.locator("#today-break-status")).to_contain_text("On break · resume in")
except AssertionError as error:
raise AssertionError(page.evaluate("""() => ({
login: document.querySelector('#current-user')?.textContent,
timers: Object.fromEntries(Object.keys(localStorage)
.filter(key => key.startsWith('stackchain.today-timer.v1.'))
.map(key => [key, JSON.parse(localStorage.getItem(key))])),
status: document.querySelector('#today-break-status').outerHTML,
})""")) from error
if page.locator("#issue-sheet").get_attribute("class") == "issue-sheet open":
page.locator("#close-issue-sheet").click()
if page.locator("#plan-today-sheet").is_visible():
+29
View File
@@ -117,6 +117,32 @@ const poller = createContextPoller({{
}
def test_context_poller_can_force_a_full_identity_refresh_after_adoption():
script = f"""
const createContextPoller = require({json.dumps(str(POLLER))});
const requested = [];
const seed = {{
context:{{user:{{login:'timmy'}}}}, events:[], notifications:[],
revisions:{{context:'0123456789abcdef.1',events:'fedcba9876543210.2'}},
}};
const poller = createContextPoller({{
fetchContext: revisions => {{
requested.push({{...revisions}});
return Promise.resolve({{...seed, freshness:{{sections:{{context:{{degraded:false}}}}}}}});
}},
onSnapshot: () => {{}}, onError: error => {{ throw error; }},
setTimer: () => 1, clearTimer: () => {{}},
}});
poller.adopt(seed);
(async () => {{
await poller.refresh({{force:true, full:true}});
process.stdout.write(JSON.stringify({{requested}}));
}})();
"""
assert run_node(script) == {"requested": [{}]}
def test_context_poller_adopts_progressive_snapshot_before_revision_conditional_refresh():
script = f"""
const createContextPoller = require({json.dumps(str(POLLER))});
@@ -200,6 +226,9 @@ def test_dashboard_adopts_progressive_snapshot_or_falls_back_to_immediate_load()
assert "let adoptedProgressiveSnapshot = contextPoller.adopt(progressiveWorkHandoff?.liveSnapshot);" in source
assert "contextPoller.adoptPending(progressiveWorkHandoff.liveSnapshotPromise)" in source
assert "if (!adoptedProgressiveSnapshot) await load();" in source
assert "contextPoller.refresh({ force:true, full:true })" in source
assert "fetchReviewJson('api/v1/background-identity')" in source
assert "initialAccountRecovery = timerView.restore(todaySync.flush());" in source
def test_context_poller_uses_failed_section_retry_before_healthy_freshness_deadline():