diff --git a/e2e/specs/admin.spec.ts b/e2e/specs/admin.spec.ts index 235a254f..fee8bc18 100644 --- a/e2e/specs/admin.spec.ts +++ b/e2e/specs/admin.spec.ts @@ -1109,12 +1109,17 @@ test("US-102 pause a relay and settle the bill", async ({seed, as}) => { const invoices = history.getByRole("listitem") // The whole period, not just its start: the two invoices meet at a month boundary, so either - // date on its own reads the same on both of them. + // date on its own reads the same on both of them. Formatted by the browser rather than by node, + // so the locale is the one the app rendered with — see dayLabel in dms.spec.ts. const period = ({start, end}: {start: number; end: number}) => - `${new Date(start * 1000).toLocaleDateString()} – ${new Date(end * 1000).toLocaleDateString()}` + page.evaluate( + ([from, to]) => + `${new Date(from * 1000).toLocaleDateString()} – ${new Date(to * 1000).toLocaleDateString()}`, + [start, end], + ) await expect(invoices.first()).toContainText("$9.00") - await expect(invoices.first()).toContainText(period(openPeriod)) + await expect(invoices.first()).toContainText(await period(openPeriod)) await expect(invoices.nth(1)).toContainText("$5.00") - await expect(invoices.nth(1)).toContainText(period(paidPeriod)) + await expect(invoices.nth(1)).toContainText(await period(paidPeriod)) }) diff --git a/e2e/specs/articles-threads.spec.ts b/e2e/specs/articles-threads.spec.ts index 61bc4540..0ff1a72e 100644 --- a/e2e/specs/articles-threads.spec.ts +++ b/e2e/specs/articles-threads.spec.ts @@ -96,10 +96,14 @@ const expectReactionRoundTrip = async (page: Page, scope: Locator, opener: Locat await expect(pill).toHaveCount(0) } -// formatTimestamp renders a short date and a short time in the environment's own locale, which node -// shares, so the date half of it is what a spec can name without pinning a format. -const shortDate = (seconds: number) => - new Intl.DateTimeFormat(undefined, {dateStyle: "short"}).format(new Date(seconds * 1000)) +// formatTimestamp renders a short date and a short time, so the date half of it is what a spec can +// name without pinning a format. Formatted by the browser rather than by node, so the locale and the +// timezone are the ones the app rendered with — see dayLabel in dms.spec.ts. +const shortDate = (page: Page, seconds: number) => + page.evaluate( + ts => new Intl.DateTimeFormat(undefined, {dateStyle: "short"}).format(new Date(ts * 1000)), + seconds, + ) // The card is a div carrying an overlay link, so it is found by its component rather than by a // role — its own contents include a profile button and the room and action links. @@ -284,7 +288,7 @@ test("US-038 browse, filter, and read articles", async ({seed, as}) => { await expect(garden).toContainText("Written by") await expect(garden).toContainText("Alice Anderson") await expect(garden).toContainText("A short teaser about gardens.") - await expect(garden).toContainText(shortDate(at(4, HOUR))) + await expect(garden).toContainText(await shortDate(page, at(4, HOUR))) const authors = page .locator("section") @@ -308,7 +312,7 @@ test("US-038 browse, filter, and read articles", async ({seed, as}) => { await expect(page.getByRole("heading", {name: "Tending the Garden"}).first()).toBeVisible() await expect(page.locator('img[src="https://images.test/garden.jpg"]')).toBeVisible() await expect(page.getByText("A short teaser about gardens.")).toBeVisible() - await expect(page.getByText(/^Published /)).toContainText(shortDate(at(4, HOUR))) + await expect(page.getByText(/^Published /)).toContainText(await shortDate(page, at(4, HOUR))) const markdown = page.locator(".content-markdown") @@ -658,7 +662,9 @@ test("US-042 start a thread and see it filed under its room", async ({seed, as}) await expect(chairs.getByRole("cell").nth(0)).toContainText("Chair procurement") await expect(chairs.getByRole("cell").nth(1)).toContainText("Bob Barker") await expect(chairs.getByRole("cell").nth(2)).toHaveText("2") - await expect(chairs.getByRole("cell").nth(3)).toContainText(shortDate(at(4, HOUR) + 60)) + await expect(chairs.getByRole("cell").nth(3)).toContainText( + await shortDate(page, at(4, HOUR) + 60), + ) await pageBar(page).getByRole("button", {name: "Create", exact: true}).click() diff --git a/e2e/specs/community.spec.ts b/e2e/specs/community.spec.ts index 2da7d21d..8112091d 100644 --- a/e2e/specs/community.spec.ts +++ b/e2e/specs/community.spec.ts @@ -63,10 +63,15 @@ const openCard = (card: Locator, title: string) => card.getByText(title).click() // its progress bar. const pollOption = (page: Page, label: string) => page.locator(".card-sm").filter({hasText: label}) -// dateFormatter in @welshman/lib resolves the environment's own locale, which node shares. -const longDate = (seconds: number) => - new Intl.DateTimeFormat(undefined, {year: "numeric", month: "long", day: "numeric"}).format( - new Date(seconds * 1000), +// The options mirror dateFormatter in @welshman/lib. Formatted by the browser rather than by node, +// so the locale and the timezone are the ones the app rendered with — see dayLabel in dms.spec.ts. +const longDate = (page: Page, seconds: number) => + page.evaluate( + ts => + new Intl.DateTimeFormat(undefined, {year: "numeric", month: "long", day: "numeric"}).format( + new Date(ts * 1000), + ), + seconds, ) // The selections of every poll response this page put on the wire, oldest first. A multiple choice @@ -204,7 +209,7 @@ test("US-046 create and browse a calendar event", async ({seed, as}) => { const market = card("Winter Market") await expect(market).toBeVisible() - await expect(market).toContainText(longDate(Math.floor(target.getTime() / 1000))) + await expect(market).toContainText(await longDate(page, Math.floor(target.getTime() / 1000))) }) test("US-047 manage your own calendar event", async ({seed, as}) => { @@ -249,7 +254,7 @@ test("US-047 manage your own calendar event", async ({seed, as}) => { const eventCard = page.locator(".card.z-feature") await expect(page.getByRole("heading", {name: "Harvest Supper", exact: true})).toBeVisible() - await expect(eventCard).toContainText(longDate(at(-2, DAY))) + await expect(eventCard).toContainText(await longDate(page, at(-2, DAY))) await expect(eventCard).toContainText("The Old Mill") await expect(eventCard).toContainText("Alice Anderson")