Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c3937ec70 |
@@ -3929,38 +3929,6 @@ fused half and was missing the retry; it has both now.
|
|||||||
Worth generalising: a spec that resizes and then measures is asserting
|
Worth generalising: a spec that resizes and then measures is asserting
|
||||||
about a moving target for the next dozen frames. Fuse, then poll.
|
about a moving target for the next dozen frames. Fuse, then poll.
|
||||||
|
|
||||||
## "The first N tracks" is not a way to ask for an ordinary one (2026-08-20)
|
|
||||||
|
|
||||||
`queue-selection.spec.ts` staged its queue from the first few rows of
|
|
||||||
`library.Library.GetTracks(0)` and clicked a track *name*, which
|
|
||||||
`explore-link` routes to that track's **album** page. Four tracks in the
|
|
||||||
fixture library have no album at all — `01 Tone A`, `02 Tone B`,
|
|
||||||
`Title Only`, `no-tags-at-all` — and a name with nothing to route to
|
|
||||||
renders as **plain text**, not as a link.
|
|
||||||
|
|
||||||
Two things follow, and the second is the sharper one.
|
|
||||||
|
|
||||||
**The order is the scan's.** `GetTracks` returns `audio_files.id` order,
|
|
||||||
i.e. the order the scan inserted rows, which depends on concurrency and
|
|
||||||
directory traversal. Locally the first eight are all from two proper
|
|
||||||
albums, so the spec passed twice over; CI rebuilds its seed with a real
|
|
||||||
scan, got a different eight, and failed on both engines. This is the
|
|
||||||
same family as "a seed freezes every default it has already persisted" —
|
|
||||||
the fixture library is not a list, it is a *set* with an incidental
|
|
||||||
order, and no spec should depend on that order.
|
|
||||||
|
|
||||||
**A loose locator hid it.** The row was located with
|
|
||||||
`.locator('.explore-link').first()`, and a row has two — the title and
|
|
||||||
the artist. When the title is plain text, `first()` silently resolves to
|
|
||||||
the **artist** link, so the click went somewhere real and the assertion
|
|
||||||
was about a destination the test had not exercised. `.track-title
|
|
||||||
.explore-link` is the locator that says which one it means; the loose
|
|
||||||
one turned a fixture problem into a mystery.
|
|
||||||
|
|
||||||
The general rule for this repo's fixture library: it is deliberately
|
|
||||||
full of edge cases (untagged, unicode, duplicates, extremes), so a spec
|
|
||||||
that wants an *ordinary* track has to **say so** — filter on the
|
|
||||||
property it depends on rather than slicing.
|
|
||||||
## A nested rule starting with an element name is dropped on the phone (2026-08-20)
|
## A nested rule starting with an element name is dropped on the phone (2026-08-20)
|
||||||
|
|
||||||
`CLAUDE.md` records that the device renders in **Chrome 113**, which
|
`CLAUDE.md` records that the device renders in **Chrome 113**, which
|
||||||
|
|||||||
@@ -93,31 +93,10 @@ async function queueSixAndOpen(app: Page): Promise<void> {
|
|||||||
'library.Library.GetTracks',
|
'library.Library.GetTracks',
|
||||||
[0],
|
[0],
|
||||||
10_000,
|
10_000,
|
||||||
)) as { FilePath: string; TrackName: string; Album: string }[];
|
)) as { FilePath: string; TrackName: string }[];
|
||||||
|
|
||||||
const long = tracks.find((t) => t.TrackName === longTitle);
|
const long = tracks.find((t) => t.TrackName === longTitle);
|
||||||
|
const rest = tracks.filter((t) => t.TrackName !== longTitle).slice(0, 5);
|
||||||
/**
|
|
||||||
* **Tracks that have an album**, which is a requirement of one of
|
|
||||||
* the tests and was previously left to luck (#156).
|
|
||||||
*
|
|
||||||
* `explore-link` routes a track name to its *album's* page, so a
|
|
||||||
* track with no album renders a name that navigates nowhere — and
|
|
||||||
* the fixture library deliberately contains two (`01 Tone A`,
|
|
||||||
* `02 Tone B`). Which tracks arrive first is `audio_files.id`
|
|
||||||
* order, i.e. the order the **scan** inserted them, which depends
|
|
||||||
* on concurrency and directory traversal: locally the first eight
|
|
||||||
* all had albums and the spec passed twice over, and CI rebuilds
|
|
||||||
* its seed with a real scan and got a different eight.
|
|
||||||
*
|
|
||||||
* Asking for what the test needs is the fix. It is not a
|
|
||||||
* narrowing: every assertion here wants an ordinary track, and
|
|
||||||
* "the first five rows" was never a way to ask for one in a
|
|
||||||
* library whose whole purpose is edge cases.
|
|
||||||
*/
|
|
||||||
const rest = tracks
|
|
||||||
.filter((t) => t.TrackName !== longTitle && t.Album !== '')
|
|
||||||
.slice(0, 5);
|
|
||||||
|
|
||||||
// Index 3 is the long one: far enough down that a shift-extend has
|
// Index 3 is the long one: far enough down that a shift-extend has
|
||||||
// room either side of it.
|
// room either side of it.
|
||||||
@@ -244,14 +223,7 @@ test.describe('selecting in the queue with a mouse', () => {
|
|||||||
.poll(() => selected(app), { timeout: HIGHLIGHT_MS })
|
.poll(() => selected(app), { timeout: HIGHLIGHT_MS })
|
||||||
.toEqual([1]);
|
.toEqual([1]);
|
||||||
|
|
||||||
// `.track-title .explore-link`, not `.explore-link` first(): a row
|
await row(app, 2).locator('.explore-link').first().click();
|
||||||
// has two, and which one `first()` finds depends on whether the
|
|
||||||
// *title* is a link at all. It is not, for a track with no album —
|
|
||||||
// `explore-link` renders plain text where it cannot route — so the
|
|
||||||
// loose locator silently clicked the **artist** instead and the
|
|
||||||
// assertion below was about a different destination than the one
|
|
||||||
// being exercised (#156).
|
|
||||||
await row(app, 2).locator('.track-title .explore-link').click();
|
|
||||||
|
|
||||||
await expect(app.getByTestId('main-content')).toHaveAttribute(
|
await expect(app.getByTestId('main-content')).toHaveAttribute(
|
||||||
'data-active-view',
|
'data-active-view',
|
||||||
|
|||||||
Reference in New Issue
Block a user