feat: review activity before Today updates (Closes #1060)
This commit is contained in:
1 parent
e290293bf1
commit
47626338ba
5 files changed
+228
-4
No files matched your search
@@ -216,8 +216,9 @@ const elements=Object.fromEntries(selectors.map(selector=>[selector,new Element(
|
||||
const target={{identity:'issue:stackchain/dashboard:1058:',kind:'issue',repository:'stackchain/dashboard',number:1058,label:'#1058',title:'Voice progress'}};
|
||||
const calls=[];
|
||||
const voice={{open:async identity=>calls.push(['open',identity]),cancel:()=>calls.push(['cancel'])}};
|
||||
const activity={{open:async value=>calls.push(['activity-open',value.identity]),close:()=>calls.push(['activity-close'])}};
|
||||
const view=createView({{
|
||||
progress:{{load:()=> 'Saved text',save:()=>true}},currentTarget:()=>target,qs:selector=>elements[selector],voice,
|
||||
progress:{{load:()=> 'Saved text',save:()=>true}},currentTarget:()=>target,qs:selector=>elements[selector],voice,activity,
|
||||
photos:{{open:async()=>calls.push(['photos'])}},
|
||||
}});
|
||||
(async()=>{{
|
||||
@@ -231,13 +232,112 @@ const view=createView({{
|
||||
"opened": {
|
||||
"body": "Saved text",
|
||||
"sheet": True,
|
||||
"calls": [["open", "issue:stackchain/dashboard:1058:"], ["photos"]],
|
||||
"calls": [["open", "issue:stackchain/dashboard:1058:"], ["photos"], ["activity-open", "issue:stackchain/dashboard:1058:"]],
|
||||
},
|
||||
"closed": True,
|
||||
"calls": [["open", "issue:stackchain/dashboard:1058:"], ["photos"], ["cancel"]],
|
||||
"calls": [
|
||||
["open", "issue:stackchain/dashboard:1058:"],
|
||||
["photos"],
|
||||
["activity-open", "issue:stackchain/dashboard:1058:"],
|
||||
["cancel"],
|
||||
["activity-close"],
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_recent_activity_loads_the_exact_issue_newest_page_before_rendering():
|
||||
script = f"""
|
||||
const {{createActivity}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
const calls=[]; const paints=[];
|
||||
const page={{comments:[{{id:2,body:'Latest',user:{{login:'alex'}},created_at:'2026-08-18T01:00:00Z'}}],page:3,older_page:2,total:41}};
|
||||
const activity=createActivity({{
|
||||
fetchJson:async path=>{{calls.push(path);return page;}},
|
||||
createPager:({{loadPage}})=>({{reset:value=>value,loadOlder:()=>loadPage(2)}}),
|
||||
paint:value=>paints.push(value), setStatus:value=>calls.push('status:'+value),
|
||||
}});
|
||||
const target={{identity:'issue:stackchain/dashboard:1060:',kind:'issue',repository:'stackchain/dashboard',number:1060}};
|
||||
(async()=>{{await activity.open(target);process.stdout.write(JSON.stringify({{calls,paints}}));}})()
|
||||
.catch(error=>{{console.error(error);process.exit(1);}});
|
||||
"""
|
||||
output = run_node(script)
|
||||
assert output["calls"] == [
|
||||
"status:Loading recent activity…",
|
||||
"api/v1/repos/stackchain/dashboard/issues/1060/comments?limit=20",
|
||||
"status:",
|
||||
]
|
||||
assert output["paints"] == [{
|
||||
"comments": [{
|
||||
"id": 2,
|
||||
"body": "Latest",
|
||||
"user": {"login": "alex"},
|
||||
"created_at": "2026-08-18T01:00:00Z",
|
||||
}],
|
||||
"page": 3,
|
||||
"older_page": 2,
|
||||
"total": 41,
|
||||
}]
|
||||
|
||||
|
||||
def test_recent_activity_rejects_a_slow_response_after_close():
|
||||
script = f"""
|
||||
const {{createActivity}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
let resolve; const paints=[]; const statuses=[];
|
||||
const activity=createActivity({{
|
||||
fetchJson:()=>new Promise(done=>{{resolve=done;}}),
|
||||
createPager:()=>({{reset:value=>value}}), paint:value=>paints.push(value), setStatus:value=>statuses.push(value),
|
||||
}});
|
||||
const target={{identity:'pull:stackchain/dashboard:9:',kind:'pull',repository:'stackchain/dashboard',number:9}};
|
||||
(async()=>{{const pending=activity.open(target);activity.close();resolve({{comments:[{{id:1}}]}});const result=await pending;process.stdout.write(JSON.stringify({{result,paints,statuses}}));}})()
|
||||
.catch(error=>{{console.error(error);process.exit(1);}});
|
||||
"""
|
||||
assert run_node(script) == {
|
||||
"result": False,
|
||||
"paints": [],
|
||||
"statuses": ["Loading recent activity…", ""],
|
||||
}
|
||||
|
||||
|
||||
def test_recent_activity_retry_recovers_the_same_pull_after_failure():
|
||||
script = f"""
|
||||
const {{createActivity}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
const calls=[]; const paints=[]; let fail=true;
|
||||
const activity=createActivity({{
|
||||
fetchJson:async path=>{{calls.push(path);if(fail)throw new Error('offline');return {{comments:[],page:1,older_page:null,total:0}};}},
|
||||
createPager:()=>({{reset:value=>value}}), paint:value=>paints.push(value),
|
||||
}});
|
||||
const target={{identity:'pull:stackchain/dashboard:9:',kind:'pull',repository:'stackchain/dashboard',number:9}};
|
||||
(async()=>{{const opened=await activity.open(target);fail=false;const retried=await activity.retry();process.stdout.write(JSON.stringify({{opened,retried,calls,paints}}));}})()
|
||||
.catch(error=>{{console.error(error);process.exit(1);}});
|
||||
"""
|
||||
output = run_node(script)
|
||||
assert output["opened"] is False
|
||||
assert output["retried"] is True
|
||||
assert output["calls"] == [
|
||||
"api/v1/repos/stackchain/dashboard/pulls/9/comments?limit=20",
|
||||
"api/v1/repos/stackchain/dashboard/pulls/9/comments?limit=20",
|
||||
]
|
||||
assert output["paints"] == [{"comments": [], "page": 1, "older_page": None, "total": 0}]
|
||||
|
||||
|
||||
def test_recent_activity_load_older_paints_the_deduplicated_page():
|
||||
script = f"""
|
||||
const {{createActivity}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
const calls=[]; const paints=[];
|
||||
const activity=createActivity({{
|
||||
fetchJson:async path=>{{calls.push(path);return {{comments:[],page:2,older_page:null,total:20}};}},
|
||||
createPager:({{loadPage}})=>({{reset:value=>value,loadOlder:async()=>{{await loadPage(2);return {{comments:[{{id:1}}],page:2,older_page:null,total:21}};}}}}),
|
||||
paint:value=>paints.push(value),
|
||||
}});
|
||||
const target={{identity:'issue:stackchain/dashboard:1060:',kind:'issue',repository:'stackchain/dashboard',number:1060}};
|
||||
(async()=>{{await activity.open(target);const loaded=await activity.loadOlder();process.stdout.write(JSON.stringify({{loaded,calls,paints}}));}})()
|
||||
.catch(error=>{{console.error(error);process.exit(1);}});
|
||||
"""
|
||||
output = run_node(script)
|
||||
assert output["loaded"] is True
|
||||
assert output["calls"][-1] == "api/v1/repos/stackchain/dashboard/issues/1060/comments?page=2&limit=20"
|
||||
assert output["paints"][-1]["comments"] == [{"id": 1}]
|
||||
|
||||
|
||||
def test_mobile_progress_sheet_is_accessible_bundled_and_safe_area_aware():
|
||||
html = (ROOT / "frontend" / "index.html").read_text()
|
||||
css = (ROOT / "frontend" / "dashboard.css").read_text()
|
||||
@@ -248,6 +348,11 @@ def test_mobile_progress_sheet_is_accessible_bundled_and_safe_area_aware():
|
||||
assert 'id="today-progress-sheet"' in html
|
||||
assert 'aria-labelledby="today-progress-title"' in html
|
||||
assert 'id="today-progress-body"' in html
|
||||
assert 'id="today-progress-activity"' in html
|
||||
assert 'id="today-progress-activity-list"' in html
|
||||
assert 'id="today-progress-activity-status"' in html
|
||||
assert 'id="retry-today-progress-activity"' in html
|
||||
assert 'id="load-older-today-progress-activity"' in html
|
||||
for control in (
|
||||
"voice-today-progress",
|
||||
"start-voice-today-progress",
|
||||
@@ -278,6 +383,11 @@ def test_mobile_progress_sheet_is_accessible_bundled_and_safe_area_aware():
|
||||
assert "photos:todayProgressPhotos" in dashboard
|
||||
assert "['today-progress', '#today-progress-body']" in dashboard
|
||||
assert "voice:todayProgressVoice" in dashboard
|
||||
assert "mountTodayProgressActivity" in dashboard
|
||||
assert "activity:mountTodayProgressActivity" in dashboard
|
||||
assert ".today-progress-activity-list" in css
|
||||
assert ".today-progress-activity-actions button" in css
|
||||
assert "min-height:44px" in css
|
||||
assert "const controller = issueAttachment.mount" in TODAY_PROGRESS.read_text()
|
||||
assert "const checkpointAttachments = await photos?.serialize?.() || [];" in TODAY_PROGRESS.read_text()
|
||||
assert "progress.save(openedTarget.identity, body.value, checkpointAttachments)" in TODAY_PROGRESS.read_text()
|
||||
|
||||
Reference in new issue
Block a user