152 lines
6.8 KiB
Python
152 lines
6.8 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import threading
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
if os.getenv("STACKCHAIN_RUN_RELEASE_E2E") != "1":
|
|
pytest.skip("packaged Today summary journey runs only in its gated CI job", allow_module_level=True)
|
|
pytest.importorskip("playwright.sync_api")
|
|
from playwright.sync_api import expect, sync_playwright
|
|
|
|
from fake_gitea import FakeGiteaServer
|
|
from test_mobile_offline_issue_release import ACCESS_TOKEN, ROOT, hydrate_workspace, release_server
|
|
|
|
|
|
@pytest.mark.parametrize(("width", "height"), [(320, 568), (390, 844)])
|
|
def test_release_artifact_reviews_and_shares_a_private_mobile_today_summary(
|
|
tmp_path: Path, width: int, height: int
|
|
):
|
|
archives = sorted((ROOT / "dist").glob("stackchain-dashboard-*.tar.gz"))
|
|
assert len(archives) == 1, "browser job must download exactly one assembled release archive"
|
|
|
|
fake = FakeGiteaServer(("127.0.0.1", 0))
|
|
fake_thread = threading.Thread(target=fake.serve_forever, daemon=True)
|
|
fake_thread.start()
|
|
fake_url = f"http://127.0.0.1:{fake.server_port}"
|
|
browser_errors: list[str] = []
|
|
|
|
try:
|
|
with release_server(archives[0], tmp_path, fake_url) as origin, sync_playwright() as playwright:
|
|
browser = playwright.chromium.launch(args=["--ignore-certificate-errors"])
|
|
context = browser.new_context(
|
|
viewport={"width": width, "height": height}, ignore_https_errors=True
|
|
)
|
|
page = context.new_page()
|
|
page.add_init_script(
|
|
"Object.defineProperty(navigator, 'share', {configurable:true, value:async payload => { window.__sharedSummary = payload; }});"
|
|
)
|
|
page.on("pageerror", lambda error: browser_errors.append(error.stack or str(error)))
|
|
page.on(
|
|
"console",
|
|
lambda message: browser_errors.append(message.text)
|
|
if message.type == "error"
|
|
else None,
|
|
)
|
|
page.goto(origin + "/", wait_until="networkidle")
|
|
page.locator('input[name="device_label"]').fill("Today summary release phone")
|
|
page.locator('input[name="access_token"]').fill(ACCESS_TOKEN)
|
|
page.locator("#submit-sign-in").click()
|
|
page.wait_for_url(origin + "/", wait_until="networkidle")
|
|
hydrate_workspace(page)
|
|
|
|
page.evaluate(
|
|
"""
|
|
() => {
|
|
const summary=createTodaySummary({
|
|
storage:localStorage,getLogin:()=> 'timmy',
|
|
share:payload=>navigator.share(payload),
|
|
copy:text=>navigator.clipboard.writeText(text),
|
|
createOperationId:()=> 'release-summary-op',
|
|
resolveTarget:async target=>({...target,kind:'issue',title:'Daily status',state:'open'}),
|
|
enqueueDurably:async message=>{ window.__queuedSummary=message; return {item:message,durability:'background'}; },
|
|
});
|
|
const view=createTodaySummaryView({summary,qs:selector=>document.querySelector(selector),escapeHtml:value=>String(value)});
|
|
window.__summaryTest={summary,view};
|
|
view.open(
|
|
[{identity:'issue:acme/mobile:41:',title:'Ship mobile capture',context:'acme/mobile#41',actual_minutes:42}],
|
|
[{identity:'issue:acme/mobile:42:',title:'Review release',context:'acme/mobile#42'}],
|
|
);
|
|
}
|
|
"""
|
|
)
|
|
|
|
sheet = page.locator("#today-summary-sheet")
|
|
expect(sheet).to_be_visible()
|
|
expect(page.locator("#today-summary-preview")).to_have_text(
|
|
"Today\n- Ship mobile capture\n\nTomorrow\n- Review release"
|
|
)
|
|
assert "42m" not in page.locator("#today-summary-preview").inner_text()
|
|
for control in page.locator(".today-summary-actions button").all():
|
|
bounds = control.bounding_box()
|
|
assert bounds and bounds["height"] >= 44
|
|
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
|
|
|
|
page.locator("#today-summary-destination").fill("acme/mobile#41")
|
|
page.evaluate(
|
|
"""
|
|
() => {
|
|
window.__summaryTest.summary.setDestination(document.querySelector('#today-summary-destination').value);
|
|
return window.__summaryTest.view.validateDestination(document.querySelector('#validate-today-summary-destination'));
|
|
}
|
|
"""
|
|
)
|
|
expect(page.locator("#today-summary-target")).to_contain_text(
|
|
"acme/mobile#41 · issue · Daily status"
|
|
)
|
|
expect(page.locator("#post-today-summary")).to_be_enabled()
|
|
page.evaluate(
|
|
"window.__summaryTest.view.postDraft(document.querySelector('#post-today-summary'))"
|
|
)
|
|
expect(sheet).to_be_hidden()
|
|
assert page.evaluate("window.__queuedSummary") == {
|
|
"kind": "search-reply",
|
|
"repository": "acme/mobile",
|
|
"number": 41,
|
|
"targetKind": "issue",
|
|
"body": "Today\n- Ship mobile capture\n\nTomorrow\n- Review release",
|
|
"operationId": "release-summary-op",
|
|
}
|
|
|
|
page.evaluate(
|
|
"""
|
|
window.__summaryTest.view.open(
|
|
[{identity:'issue:acme/mobile:41:',title:'Ship mobile capture',context:'acme/mobile#41',actual_minutes:42}],
|
|
[{identity:'issue:acme/mobile:42:',title:'Review release',context:'acme/mobile#42'}]
|
|
)
|
|
"""
|
|
)
|
|
expect(sheet).to_be_visible()
|
|
|
|
page.evaluate(
|
|
"""
|
|
() => {
|
|
window.__summaryTest.summary.includeActuals(true);
|
|
window.__summaryTest.summary.setNote('Waiting on review');
|
|
window.__summaryTest.view.render();
|
|
}
|
|
"""
|
|
)
|
|
expect(page.locator("#today-summary-preview")).to_contain_text(
|
|
"Ship mobile capture (42m)"
|
|
)
|
|
page.evaluate(
|
|
"window.__summaryTest.view.shareDraft(document.querySelector('#share-today-summary'))"
|
|
)
|
|
expect(sheet).to_be_hidden()
|
|
assert page.evaluate("window.__sharedSummary") == {
|
|
"title": "Today summary",
|
|
"text": "Today\n- Ship mobile capture (42m)\n\nTomorrow\n- Review release\n\nNote\nWaiting on review",
|
|
}
|
|
assert page.evaluate(
|
|
"localStorage.getItem('stackchain.today-summary-draft.v1.timmy')"
|
|
) is None
|
|
assert browser_errors == []
|
|
browser.close()
|
|
finally:
|
|
fake.shutdown()
|
|
fake.server_close()
|
|
fake_thread.join(timeout=5)
|