feat: mention teammates from Today updates (Closes #1064)
This commit is contained in:
1 parent
a65aed5862
commit
a6c769901d
8 files changed
+104
-27
No files matched your search
@@ -89,6 +89,11 @@ class FakeGiteaHandler(BaseHTTPRequestHandler):
|
||||
self._json(200, REPOSITORY)
|
||||
elif path == "/api/v1/repos/search":
|
||||
self._json(200, {"data": [REPOSITORY], "ok": True})
|
||||
elif path == "/api/v1/repos/acme/mobile/assignees":
|
||||
self._json(200, [
|
||||
USER,
|
||||
{"id": 2, "login": "alex", "full_name": "Alexander", "active": True},
|
||||
])
|
||||
elif path == "/api/v1/repos/issues/search":
|
||||
is_assigned_scan = query.get("assigned") == ["true"] and query.get("type") == ["issues"]
|
||||
is_available_scan = not any(
|
||||
|
||||
@@ -96,6 +96,33 @@ def test_release_artifact_plans_hands_off_and_opens_next_mobile_issue(tmp_path:
|
||||
"created_at": "2026-08-18T00:00:00Z",
|
||||
}]
|
||||
}
|
||||
page.locator("[data-mobile-today-update]").click()
|
||||
expect(page.locator("#today-progress-sheet")).to_be_visible()
|
||||
progress = page.locator("#today-progress-body")
|
||||
progress.fill("Pairing with @al")
|
||||
mention = page.locator('#today-progress-body-mentions [data-login="alex"]')
|
||||
try:
|
||||
expect(mention).to_be_visible()
|
||||
except AssertionError as error:
|
||||
raise AssertionError({
|
||||
"status": page.locator("#today-progress-body-mention-status").text_content(),
|
||||
"requests": fake.requests[-20:],
|
||||
"browser_errors": browser_errors,
|
||||
"failed_responses": failed_responses,
|
||||
}) from error
|
||||
mention_bounds = mention.bounding_box()
|
||||
assert mention_bounds and mention_bounds["height"] >= 44
|
||||
mention.click()
|
||||
expect(progress).to_have_value("Pairing with @alex ")
|
||||
page.locator("#post-today-progress").click()
|
||||
expect(page.locator("#today-progress-sheet")).to_be_hidden()
|
||||
admitted = page.evaluate("""() => {
|
||||
const record = JSON.parse(localStorage.getItem('stackchain.authored-outbox.v1') || 'null');
|
||||
return record?.items?.find(item => item.kind === 'issue-comment' && item.number === 41);
|
||||
}""")
|
||||
assert admitted and admitted["repository"] == "acme/mobile"
|
||||
assert admitted["body"] == "Pairing with @alex"
|
||||
|
||||
page.locator("[data-mobile-today-update]").click()
|
||||
expect(page.locator("#today-progress-sheet")).to_be_visible()
|
||||
owned = page.locator('[data-comment-id="701"]')
|
||||
@@ -192,7 +219,10 @@ def test_release_artifact_plans_hands_off_and_opens_next_mobile_issue(tmp_path:
|
||||
expect(page.locator("#issue-comment")).to_have_value("")
|
||||
expect(page.locator("[data-mobile-today-hud]")).to_have_attribute("data-overlay-hidden", "true")
|
||||
expect(page.locator("[data-mobile-today-hud]")).to_contain_text("Polish desktop filters")
|
||||
assert fake.comments == [(41, "Handoff complete; continuing with the next Today item.")]
|
||||
assert fake.comments == [
|
||||
(41, "Pairing with @alex"),
|
||||
(41, "Handoff complete; continuing with the next Today item."),
|
||||
]
|
||||
|
||||
receipt = page.locator("#today-completion-undo")
|
||||
expect(receipt).to_be_visible()
|
||||
|
||||
@@ -54,12 +54,13 @@ def test_all_conversation_composers_offer_accessible_mobile_mentions():
|
||||
css = CSS.read_text()
|
||||
|
||||
assert '<script src="static/mention-composer.js"></script>' in html
|
||||
for composer in ("issue-comment", "pull-comment", "update-reply"):
|
||||
for composer in ("issue-comment", "pull-comment", "update-reply", "today-progress-body"):
|
||||
assert f'id="{composer}-mentions"' in html
|
||||
assert f'id="{composer}-mention-status"' in html
|
||||
assert f"textarea:qs('#{composer}')" in dashboard
|
||||
assert f"listbox:qs('#{composer}-mentions')" in dashboard
|
||||
assert dashboard.count("createMentionComposer({") == 3
|
||||
assert f"['{composer}'," in dashboard
|
||||
assert dashboard.count("createMentionComposer({") == 1
|
||||
assert "['today-progress-body',()=>currentTodayProgressTarget()?.repository]" in dashboard
|
||||
assert "mentions:todayProgressMentions" in dashboard
|
||||
assert "mention-candidates?q=" in dashboard
|
||||
assert ".mention-options" in css
|
||||
assert "min-height:44px" in css
|
||||
|
||||
@@ -245,6 +245,42 @@ const view=createView({{
|
||||
}
|
||||
|
||||
|
||||
def test_progress_sheet_dismisses_mentions_when_opened_switched_or_closed():
|
||||
script = f"""
|
||||
const {{createView}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
class Element {{
|
||||
constructor() {{ this.hidden=false;this.value='';this.textContent='';this.open=false;this.listeners={{}}; }}
|
||||
addEventListener(name,callback) {{ this.listeners[name]=callback; }}
|
||||
click() {{ return this.listeners.click?.(); }}
|
||||
showModal() {{ this.open=true; }} close() {{ this.open=false; }} focus() {{}}
|
||||
}}
|
||||
const selectors=['#today-progress-sheet','#today-progress-body','#today-progress-status','[data-mobile-today-update]',
|
||||
'#today-progress-target','#cancel-today-progress','#save-today-progress','#post-today-progress'];
|
||||
const elements=Object.fromEntries(selectors.map(selector=>[selector,new Element()]));
|
||||
const issue={{identity:'issue:stackchain/dashboard:1064:',kind:'issue',repository:'stackchain/dashboard',number:1064,label:'#1064',title:'Mentions'}};
|
||||
const pull={{identity:'pull:stackchain/dashboard:77:',kind:'pull',repository:'stackchain/dashboard',number:77,label:'#77',title:'Other'}};
|
||||
let target=issue; let dismissals=0;
|
||||
const view=createView({{
|
||||
progress:{{load:()=>'',save:()=>true}},currentTarget:()=>target,qs:selector=>elements[selector],
|
||||
mentions:{{dismiss:()=>dismissals++}},
|
||||
}});
|
||||
(async()=>{{
|
||||
await elements['[data-mobile-today-update]'].click();
|
||||
const afterOpen=dismissals;
|
||||
target=pull; view.update();
|
||||
const afterSwitch=dismissals;
|
||||
await elements['#cancel-today-progress'].click();
|
||||
process.stdout.write(JSON.stringify({{afterOpen,afterSwitch,afterClose:dismissals,closed:!elements['#today-progress-sheet'].open}}));
|
||||
}})().catch(error=>{{console.error(error);process.exit(1);}});
|
||||
"""
|
||||
assert run_node(script) == {
|
||||
"afterOpen": 1,
|
||||
"afterSwitch": 2,
|
||||
"afterClose": 3,
|
||||
"closed": True,
|
||||
}
|
||||
|
||||
|
||||
def test_recent_activity_loads_the_exact_issue_newest_page_before_rendering():
|
||||
script = f"""
|
||||
const {{createActivity}}=require({json.dumps(str(TODAY_PROGRESS))});
|
||||
|
||||
Reference in new issue
Block a user