Files
yellowjacket/e2e/specs/failure-voice.spec.ts
T
logan 4615afe7f7
Build & publish Arch package / arch-package (push) Successful in 2m0s
CI / check (push) Successful in 2m29s
Search index maintenance / maintain-index (push) Successful in 6s
CI / e2e (push) Failing after 6m23s
test(e2e): freeze Settings' and Downloads' keyboard reach
A component test sees the markup; only this tier sees that the control
is reachable through the app's own tab order. Also stops
failure-voice.spec assuming the Libraries section starts collapsed — it
is the one section that starts open now, so a blind click on the
disclosure closed it and the rest of the spec ran against a hidden row.
2026-08-12 12:17:13 -04:00

72 lines
2.5 KiB
TypeScript

import { test, expect } from '../support/fixtures.js';
/**
* Plan 007 phase 3: a failure the user caused has to reach the user.
*
* The failure is induced through `/__test/sql` rather than staged in the
* UI: a second library called "Decoy" makes `RenameLibrary` reject with
* its duplicate-name error, which is a real binding rejection on a path
* the audit found ends at `console.error` (errors.m5).
*/
test.describe('a failed binding says so', () => {
const DECOY = 'Decoy';
test.afterEach(async ({ testctl }) => {
await testctl.sql('DELETE FROM libraries WHERE name = ?', [DECOY]);
});
test('a rejected rename reaches the user, not the console', async ({
app,
testctl,
}) => {
// The library that was seeded by running the app, i.e. the one row
// that is not the decoy.
const health = await testctl.health();
const seeded = health.libraries[0].name as string;
await testctl.sql(
'INSERT INTO libraries (name, path) VALUES (?, ?)',
[DECOY, '/tmp/yj-decoy-library'],
);
await app.getByTestId('nav-settings').click();
const page = app.locator('config-page');
// Libraries is the one section that starts expanded (H-22), so ask
// the disclosure what state it is in rather than assuming one — a
// blind click used to expand it and now collapses it.
const disclosure = page
.locator('config-section[heading="Libraries"]')
.locator('.header');
if ((await disclosure.getAttribute('aria-expanded')) === 'false') {
await disclosure.click();
}
// Renaming the decoy to its own name is a no-op the backend
// accepts, so the rename has to happen on the other row.
const row = page.locator('.library-row').filter({ hasText: seeded });
// Through the overflow menu, not by clicking the name: the name's
// own click bubbles to config-page's document handler, which closes
// the editor it just opened.
await expect(row).toBeVisible();
await row.locator('.overflow-btn').click();
await row.getByText('Rename', { exact: true }).click();
const input = row.locator('.edit-input');
await input.fill(DECOY);
await input.press('Enter');
// The message is the assertion: a name it can act on, and none of
// the Go error's wrapping.
const notice = app.getByTestId('notification').first();
await expect(notice).toBeVisible();
await expect(notice).toContainText(DECOY);
await expect(notice).not.toContainText('could not rename library:');
});
});