test(desktop): synchronize upload edit smoke test (#7903)

## Summary
Fix the upload/edit smoke-test race observed on main at
`6410e685a80d42db0645fadc9bbe710559ef911e`.

- Hold the mock upload at the Tauri IPC boundary and release it
explicitly after checking edit rejection, rather than assuming menu
interaction finishes within one second.
- Wait for the Radix menu to unmount: edit dispatch happens in
`onCloseAutoFocus`, after the click. Without that wait, the negative
assertion can pass before the edit callback actually runs.
- Keep the existing attachment-preservation and subsequent
successful-edit assertions. No production code or CI coverage is
changed.

## Evidence and scope
- [Main
failure](https://github.com/block/buzz/actions/runs/36189213149/job/108250341388):
`opening edit during an immediate photo upload preserves the draft`,
including an upload-progress timeout on retry.
- Investigated from #7791, which changes only `docs/nips/NIP-AR.md`. Its
PostgreSQL failures and video-menu timeout are separate; PostgreSQL
passed on this main run, and the video spec passed locally. This PR does
not claim to fix those failures or the separate pointer-interception
failure seen in the main job.
- #7843 already addresses unrelated runtime suites being selected for
docs-only PRs.

## Validation
- Full desktop `pnpm test`: 6,676 Node tests + 92 jsdom tests passed.
- Upload/edit regression repeated 5 times: passed. Holding the upload
without waiting for menu teardown failed all 5 runs, demonstrating the
second race.
- Complete file-attachment and video-attachment Playwright specs: 30
passed.
- Pre-push desktop lint, typecheck, full desktop tests, and file-size
gate passed at `46e3d4392e5b56dcb74ea864aa19aa10287f27d3`.
- `just ci` attempted: initial formatting issue corrected; second run
exceeded the 5-minute local limit during Tauri clippy. Not claiming full
repository CI green.

## Review / human verification
Self-reviewed the diff against the test contract; no production behavior
changes. Draft pending human verification and CI.

To verify: activate Hermit, then `cd desktop && pnpm test:e2e:smoke
file-attachment.spec.ts --grep "opening edit during" --repeat-each=5`.
Expect all five runs to pass, retaining the upload in the draft and
allowing edit only after upload release.

Originating conversation:
buzz://message?channel=aa7f2b48-d367-4ca1-be09-116a2eb45b99&id=1b68585ba4483a87f5a453fd7bbdd11d434e332dcb4aff8acfe1f5d2601b6561

Signed-off-by: Smartie <fb3185faacfc3760b6b4fe0085a8878d8dd537f7a7671c7d3184fe1aa1b04df4@buzz.block.builderlab.xyz>
Co-authored-by: Smartie <fb3185faacfc3760b6b4fe0085a8878d8dd537f7a7671c7d3184fe1aa1b04df4@buzz.block.builderlab.xyz>
This commit is contained in:
Bradley Axen
2026-09-25 15:52:02 -07:00
committed by GitHub
parent 6410e685a8
commit a1fb6645d9

View File

@@ -166,25 +166,49 @@ test("opening edit during an immediate photo upload preserves the draft", async
page,
}) => {
await page.goto("/");
await page.evaluate(() => {
const e2e = (
window as Window & {
__BUZZ_E2E__?: { mock?: { uploadDelayMs?: number } };
}
).__BUZZ_E2E__;
if (e2e?.mock) e2e.mock.uploadDelayMs = 1_000;
});
await page.getByTestId("channel-general").click();
await expect(page.getByTestId("chat-title")).toHaveText("general");
// Hold the upload at the IPC boundary until the edit assertion completes.
// A fixed delay races menu interaction and CI scheduling, so it can test
// an already-completed upload instead of the in-flight draft guard.
await page.evaluate(() => {
const w = window as Window & {
__RELEASE_PHOTO_UPLOAD__?: () => void;
__TAURI_INTERNALS__: {
invoke: (
command: string,
payload: unknown,
options: unknown,
) => Promise<unknown>;
};
};
const original = w.__TAURI_INTERNALS__.invoke.bind(w.__TAURI_INTERNALS__);
const gate = new Promise<void>((resolve) => {
w.__RELEASE_PHOTO_UPLOAD__ = resolve;
});
w.__TAURI_INTERNALS__.invoke = async (command, payload, options) => {
if (command === "upload_media_bytes_raw") await gate;
return original(command, payload, options);
};
});
await choosePhoto(page);
await expect(page.getByTestId("upload-progress")).toBeVisible();
await openMoreActionsMenu(page, "mock-general-welcome");
await page.getByTestId("edit-message-mock-general-welcome").click();
// Edit is dispatched by onCloseAutoFocus after Radix unmounts the menu,
// not by the click itself. Keep the upload held through that handoff.
await expect(page.getByRole("menu")).toHaveCount(0);
// Edit entry is rejected while the compacted draft cannot represent the
// reserved upload slot. The upload remains current and lands in the draft.
await expect(page.getByTestId("edit-target")).toHaveCount(0);
await expect(page.getByTestId("upload-progress")).toBeVisible();
await page.evaluate(() => {
(
window as Window & { __RELEASE_PHOTO_UPLOAD__: () => void }
).__RELEASE_PHOTO_UPLOAD__();
});
await expect(page.getByTestId("upload-progress")).toHaveCount(0, {
timeout: 5_000,
});