Format expected dates in the page rather than in node (#385)

Co-authored-by: Seydi Charyyev <seydi.charyev@gmail.com>
This commit is contained in:
Seydi Charyyev 2026-08-31 23:18:07 +00:00 committed by hodlbod
parent ee5d71dc1d
commit 88d8bee015
3 changed files with 33 additions and 17 deletions

View file

@ -1109,12 +1109,17 @@ test("US-102 pause a relay and settle the bill", async ({seed, as}) => {
const invoices = history.getByRole("listitem") const invoices = history.getByRole("listitem")
// The whole period, not just its start: the two invoices meet at a month boundary, so either // 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}) => 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("$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("$5.00")
await expect(invoices.nth(1)).toContainText(period(paidPeriod)) await expect(invoices.nth(1)).toContainText(await period(paidPeriod))
}) })

View file

@ -96,10 +96,14 @@ const expectReactionRoundTrip = async (page: Page, scope: Locator, opener: Locat
await expect(pill).toHaveCount(0) await expect(pill).toHaveCount(0)
} }
// formatTimestamp renders a short date and a short time in the environment's own locale, which node // formatTimestamp renders a short date and a short time, so the date half of it is what a spec can
// shares, so the date half of it is what a spec can name without pinning a format. // name without pinning a format. Formatted by the browser rather than by node, so the locale and the
const shortDate = (seconds: number) => // timezone are the ones the app rendered with — see dayLabel in dms.spec.ts.
new Intl.DateTimeFormat(undefined, {dateStyle: "short"}).format(new Date(seconds * 1000)) 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 // 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. // 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("Written by")
await expect(garden).toContainText("Alice Anderson") await expect(garden).toContainText("Alice Anderson")
await expect(garden).toContainText("A short teaser about gardens.") 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 const authors = page
.locator("section") .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.getByRole("heading", {name: "Tending the Garden"}).first()).toBeVisible()
await expect(page.locator('img[src="https://images.test/garden.jpg"]')).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("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") 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(0)).toContainText("Chair procurement")
await expect(chairs.getByRole("cell").nth(1)).toContainText("Bob Barker") 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(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() await pageBar(page).getByRole("button", {name: "Create", exact: true}).click()

View file

@ -63,10 +63,15 @@ const openCard = (card: Locator, title: string) => card.getByText(title).click()
// its progress bar. // its progress bar.
const pollOption = (page: Page, label: string) => page.locator(".card-sm").filter({hasText: label}) 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. // The options mirror dateFormatter in @welshman/lib. Formatted by the browser rather than by node,
const longDate = (seconds: number) => // so the locale and the timezone are the ones the app rendered with — see dayLabel in dms.spec.ts.
new Intl.DateTimeFormat(undefined, {year: "numeric", month: "long", day: "numeric"}).format( const longDate = (page: Page, seconds: number) =>
new Date(seconds * 1000), 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 // 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") const market = card("Winter Market")
await expect(market).toBeVisible() 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}) => { 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") const eventCard = page.locator(".card.z-feature")
await expect(page.getByRole("heading", {name: "Harvest Supper", exact: true})).toBeVisible() 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("The Old Mill")
await expect(eventCard).toContainText("Alice Anderson") await expect(eventCard).toContainText("Alice Anderson")