feat(transcription): decouple @mention display text from person search (#380) #629

Open
marcel wants to merge 41 commits from feat/issue-380-decouple-mention-search into main
Showing only changes of commit b72ac15fec - Show all commits

View File

@@ -319,6 +319,37 @@ describe('PersonMentionEditor — stale-response race', () => {
});
});
// ─── Server failure characterization (Sara #2 on PR #629) ───────────────────
describe('PersonMentionEditor — server failure', () => {
it('on 500 response keeps the dropdown open with the empty-state copy (silent failure pinned; distinct error UX tracked separately)', async () => {
const fetchMock = vi
.fn()
.mockResolvedValue({ ok: false, status: 500, json: vi.fn().mockResolvedValue({}) });
vi.stubGlobal('fetch', fetchMock);
renderHost();
await userEvent.type(page.getByRole('textbox'), '@Aug');
await new Promise((r) => setTimeout(r, SEARCH_DEBOUNCE_MS + POST_DEBOUNCE_SLACK_MS));
// Pins current silent-failure behaviour. The day someone implements a
// distinct error UX (toast / "Suche fehlgeschlagen" copy), this test
// goes red and forces them to update the assertion.
await expect.element(page.getByText(m.person_mention_popup_empty())).toBeInTheDocument();
});
it('on a fetch reject (network failure) keeps the dropdown open with the empty-state copy', async () => {
const fetchMock = vi.fn().mockRejectedValue(new TypeError('NetworkError'));
vi.stubGlobal('fetch', fetchMock);
renderHost();
await userEvent.type(page.getByRole('textbox'), '@Aug');
await new Promise((r) => setTimeout(r, SEARCH_DEBOUNCE_MS + POST_DEBOUNCE_SLACK_MS));
await expect.element(page.getByText(m.person_mention_popup_empty())).toBeInTheDocument();
});
});
// ─── onExit cancels pending debounce (Felix #1 on PR #629) ───────────────────
describe('PersonMentionEditor — onExit cancels pending debounce', () => {