feat: surface photo-only reply drafts in My Work (Closes #1396)
This commit is contained in:
1 parent
306d6e3056
commit
fa876e1e38
13 files changed
+474
-12
No files matched your search
@@ -0,0 +1,99 @@
|
||||
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 mobile photo-draft 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, release_server
|
||||
|
||||
|
||||
def test_release_artifact_finds_and_reopens_photo_only_reply_from_mobile_my_work(tmp_path: Path):
|
||||
archives = sorted((ROOT / "dist").glob("stackchain-dashboard-*.tar.gz"))
|
||||
assert len(archives) == 1, "browser job must provide 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}"
|
||||
|
||||
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": 390, "height": 844}, ignore_https_errors=True)
|
||||
page = context.new_page()
|
||||
page.goto(origin + "/", wait_until="networkidle")
|
||||
page.locator('input[name="device_label"]').fill("Photo draft 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")
|
||||
|
||||
page.evaluate(
|
||||
"""() => new Promise((resolve, reject) => {
|
||||
const request=indexedDB.open('stackchain-conversation-reply-drafts-v1',1);
|
||||
request.onerror=()=>reject(request.error);
|
||||
request.onupgradeneeded=()=>{
|
||||
if (!request.result.objectStoreNames.contains('drafts')) {
|
||||
request.result.createObjectStore('drafts',{keyPath:'id'});
|
||||
}
|
||||
};
|
||||
request.onsuccess=()=>{
|
||||
const transaction=request.result.transaction('drafts','readwrite');
|
||||
transaction.objectStore('drafts').put({
|
||||
id:'timmy:issue:acme%2Fmobile%3A41', version:1, ownerLogin:'timmy',
|
||||
scope:'conversation', kind:'issue', repository:'acme/mobile', number:41,
|
||||
updatedAt:Date.now(), attachments:[{
|
||||
filename:'rack-label.jpg', contentType:'image/jpeg',
|
||||
blob:new Blob(['field evidence'],{type:'image/jpeg'}), note:'Rack label',
|
||||
}],
|
||||
});
|
||||
transaction.oncomplete=resolve;
|
||||
transaction.onerror=()=>reject(transaction.error);
|
||||
};
|
||||
})"""
|
||||
)
|
||||
page.reload(wait_until="networkidle")
|
||||
stored = page.evaluate(
|
||||
"""() => new Promise((resolve,reject)=>{
|
||||
const request=indexedDB.open('stackchain-conversation-reply-drafts-v1',1);
|
||||
request.onerror=()=>reject(request.error);
|
||||
request.onsuccess=()=>{
|
||||
const values=request.result.transaction('drafts','readonly').objectStore('drafts').getAll();
|
||||
values.onsuccess=()=>resolve(values.result.map(item=>({ownerLogin:item.ownerLogin,kind:item.kind,number:item.number})));
|
||||
values.onerror=()=>reject(values.error);
|
||||
};
|
||||
})"""
|
||||
)
|
||||
assert stored == [{"ownerLogin": "timmy", "kind": "issue", "number": 41}]
|
||||
inventory = page.evaluate(
|
||||
"""() => createConversationReplyDraftStore({indexedDB,getOwnerLogin:()=> 'timmy'}).list()"""
|
||||
)
|
||||
assert len(inventory) == 1
|
||||
expect(page.locator('[data-work-count="draft"]')).to_have_text("1", timeout=10_000)
|
||||
page.locator('[data-mobile-task="queues"]').click()
|
||||
page.locator('[data-mobile-queue="draft"]').click()
|
||||
|
||||
card = page.locator(".draft-card", has_text="acme/mobile#41")
|
||||
expect(card).to_contain_text("1 saved photo")
|
||||
resume = card.get_by_role("button", name="Resume draft")
|
||||
bounds = resume.bounding_box()
|
||||
assert bounds and bounds["height"] >= 44
|
||||
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
|
||||
|
||||
resume.dispatch_event("click")
|
||||
expect(page.locator("#issue-sheet")).to_be_visible()
|
||||
expect(page.locator("#issue-attachment-preview")).to_be_visible()
|
||||
expect(page.locator("#issue-attachment-meta")).to_contain_text("rack-label.jpg")
|
||||
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
|
||||
browser.close()
|
||||
finally:
|
||||
fake.shutdown()
|
||||
fake.server_close()
|
||||
fake_thread.join(timeout=5)
|
||||
Reference in new issue
Block a user