mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
fix(desktop): custom emoji reaction rendering + picker autofocus (#831)
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -93,3 +93,74 @@ test("custom emoji round-trips through select-all + send to the timeline", async
|
||||
// The composer clears after send.
|
||||
await expect(input.locator("img[data-custom-emoji]")).toHaveCount(0);
|
||||
});
|
||||
|
||||
// Regression guard for custom-emoji REACTIONS.
|
||||
//
|
||||
// The bug (shipped in the custom-emoji launch, PR #816): the reaction renderer
|
||||
// put the relay emoji URL straight into <img src> without going through
|
||||
// rewriteRelayUrl(). WKWebView bypasses WARP, so the direct relay URL gets a
|
||||
// Cloudflare Access 403 and shows a broken image — even though the same emoji
|
||||
// rendered fine inline in chat (that path rewrites). The chat path was covered
|
||||
// by the tests above; the reaction path was not, which is why it slipped.
|
||||
//
|
||||
// This drives the real interactive react flow (hover -> Open reactions ->
|
||||
// emoji-mart custom category) so it exercises the add_reaction Tauri command,
|
||||
// then asserts the rendered reaction <img> src points at the localhost media
|
||||
// proxy. On the pre-fix code the src would be the raw relay URL, so this test
|
||||
// fails there — exactly the assertion that would have caught the bug.
|
||||
//
|
||||
// `:react:` is a relay-hosted fixture emoji (URL on the relay origin matching
|
||||
// rewriteRelayUrl()'s /media/{64-hex}.{ext} pattern), and the mock bridge
|
||||
// answers get_media_proxy_port with port 54321 so the rewrite resolves to a
|
||||
// real localhost URL rather than the sprout-media:// fallback.
|
||||
|
||||
const REACTION_SHORTCODE = "react";
|
||||
const MOCK_MEDIA_PROXY_PORT = 54321;
|
||||
// A seeded message in `general` with a real 64-hex id — the only reactable
|
||||
// target in mock mode (getReactionTargetId() requires a 64-hex `e` tag, which
|
||||
// user-sent mock messages don't have). Mirrors REACTION_TARGET_CONTENT in the
|
||||
// bridge.
|
||||
const REACTION_TARGET_CONTENT = "React to me with a custom emoji";
|
||||
|
||||
test("reacting with a custom emoji renders via the localhost media proxy", async ({
|
||||
page,
|
||||
}) => {
|
||||
await openGeneral(page);
|
||||
|
||||
// Reveal the hover action bar on the seeded reaction-target message, then
|
||||
// open the reaction picker.
|
||||
const row = page
|
||||
.getByTestId("message-row")
|
||||
.filter({ hasText: REACTION_TARGET_CONTENT })
|
||||
.last();
|
||||
await expect(row).toBeVisible();
|
||||
await row.hover();
|
||||
await row.getByLabel("Open reactions").click();
|
||||
|
||||
// emoji-mart renders inside a Shadow DOM web component. Search by shortcode
|
||||
// to surface the custom emoji, then click it.
|
||||
const picker = page.locator("em-emoji-picker");
|
||||
await picker.locator("input[type='search']").fill(REACTION_SHORTCODE);
|
||||
// Custom emoji buttons carry the shortcode as their `title` (no aria-label).
|
||||
await picker.locator(`button[title='${REACTION_SHORTCODE}']`).first().click();
|
||||
|
||||
// The reaction pill renders the custom emoji as an <img alt=":react:">. Its
|
||||
// src must be the localhost proxy URL — proving rewriteRelayUrl() ran. A raw
|
||||
// relay URL here is the bug.
|
||||
const reactionImg = row.locator(`img[alt=':${REACTION_SHORTCODE}:']`);
|
||||
await expect(reactionImg).toBeVisible();
|
||||
await expect(reactionImg).toHaveAttribute(
|
||||
"src",
|
||||
new RegExp(
|
||||
`^http://localhost:${MOCK_MEDIA_PROXY_PORT}/media/[\\da-f]{64}\\.png$`,
|
||||
),
|
||||
);
|
||||
|
||||
// Toggle the reaction back off: click the pill, which fires remove_reaction
|
||||
// -> emits a kind:5 deletion targeting the reaction event. The pill must
|
||||
// disappear. Guards the mock-bridge deletion path: the reaction event needs a
|
||||
// 64-hex id, because the timeline only honors deletions whose `e` tag is
|
||||
// 64-hex (getDeletionTargets). A 32-hex reaction id leaves a stale pill here.
|
||||
await row.getByLabel(`Toggle :${REACTION_SHORTCODE}: reaction`).click();
|
||||
await expect(reactionImg).toHaveCount(0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user