Skip to content

Commit

Permalink
Add tests that mock + advance time
Browse files Browse the repository at this point in the history
  • Loading branch information
bmitchinson committed Mar 18, 2024
1 parent 8030141 commit 8569566
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,5 @@ auto-generated categorization table.

### Next Up

- Need tests that can advance the mock time to test reset / submit sets time to
current.
- Blog post about time mock
- Need shadcn before adding more features
12 changes: 11 additions & 1 deletion tests/CommonTestOperations.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { expect, type Page } from "@playwright/test";
import { format, parse } from "date-fns";

const formatOfDatetimeFieldValue = "yyyy-MM-dd'T'HH:mm";

export const mockedClockDatetimeString = "2023-05-12T01:30";

export const mockedClockDate = parse(
mockedClockDatetimeString,
"yyyy-MM-dd'T'HH:mm",
formatOfDatetimeFieldValue,
new Date()
);

export const dateToDatetimeFieldValue = (date: Date) =>
format(date, formatOfDatetimeFieldValue);

export const fillPurchaseFormWithValidData = async (page: Page) => {
await page.getByLabel("Amount").fill("10.77");
await page.getByLabel("Description").fill("cool trip");
Expand Down Expand Up @@ -62,6 +67,11 @@ export const categoryOnForm = async (page: Page) => {
}
};

export const advanceTimeOneMinute = async (page: Page) =>
await page.evaluate(() => {
(window as any).advanceTimeOneMinute();
});

export const expectTheseAtPurchaseIndex = async (
page: Page,
values: string[],
Expand Down
70 changes: 53 additions & 17 deletions tests/main-page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import {
expectTheseAtPurchaseIndex,
mockedClockDate,
mockedClockDatetimeString,
advanceTimeOneMinute,
dateToDatetimeFieldValue,
} from "./CommonTestOperations";
import { format } from "date-fns";
import { add, format } from "date-fns";

// TODO: Use shadcn/ui

Expand All @@ -25,17 +27,21 @@ test.beforeEach(async ({ page }) => {

// Update the Date accordingly in your test pages
await page.addInitScript(`{
// Extend Date constructor to default to fakeNow
window.__minutesPassed = 0;
window.advanceTimeOneMinute = () => {
console.log("TIME ADVANCING TO " + ++window.__minutesPassed + " MINUTE(S) PASSED.");
}
Date.now = () => {
return ${fakeNow} + window.__minutesPassed * 60000;
}
Date = class extends Date {
constructor(...args) {
(args.length === 0) ? super(${fakeNow}) : super(...args)
(args.length === 0) ? super(${fakeNow} + window.__minutesPassed * 60000) : super(...args)
}
}
// Override Date.now() to start from fakeNow
const __DateNowOffset = ${fakeNow} - Date.now();
const __DateNow = Date.now;
Date.now = () => __DateNow() + __DateNowOffset;
}`);

await clearFirebaseData().then(createFakePurchases);
Expand Down Expand Up @@ -77,13 +83,25 @@ test.describe("Entry form", () => {

// todo-postshadcn: add clear button to form

test("Defaults to the current datetime", async ({ page }) => {});
test("Defaults to the current datetime", async ({ page }) => {
await advanceTimeOneMinute(page);
await advanceTimeOneMinute(page);
await page.getByText("Submit").click();

const expectedTime = add(mockedClockDate, { minutes: 2 });
await expect(page.getByTestId("datetime-input")).toHaveValue(
new RegExp(dateToDatetimeFieldValue(expectedTime))
);
});
});

test.describe("Adding", () => {
test("Adding a purchase saves it to the database", async ({ page }) => {
test.beforeEach(async ({ page }) => {
await clearFirebaseData().then(() => page.goto("/"));
await fillPurchaseFormWithValidData(page);
});

test("Adding a purchase saves it to the database", async ({ page }) => {
await page.getByText("Submit").click();

await expect(page.getByTestId("purchase-list-item-0")).toContainText(
Expand All @@ -95,8 +113,18 @@ test.describe("Adding", () => {
await expect(page.getByTestId("purchase-list-item-0")).toContainText("Gas");
});

// TODO done but needs test
// test("Adding a purchase÷ resets date/time to current time");
test("Adding a purchase resets date/time to current time", async ({
page,
}) => {
await advanceTimeOneMinute(page);
await advanceTimeOneMinute(page);
await page.getByText("Submit").click();

const expectedTime = add(mockedClockDate, { minutes: 2 });
await expect(page.getByTestId("datetime-input")).toHaveValue(
new RegExp(dateToDatetimeFieldValue(expectedTime))
);
});

// todo-postshadcn: validation for each field (right now you can just do category)
});
Expand Down Expand Up @@ -217,11 +245,19 @@ test("Tests running in playwright use fake database", async ({ page }) => {
});
});

// test.describe("Reset", async ({ page }) => {
// todo: reset should populate to an updated time, not the time when the page was loaded
// done but needs test.
// need a way to advance time a minute
// });
test.describe("Reset", () => {
test("Reseting updates time in date/time entry", async ({ page }) => {
await advanceTimeOneMinute(page);
await advanceTimeOneMinute(page);

await page.getByText("Reset").click();

const expectedTime = add(mockedClockDate, { minutes: 2 });
await expect(page.getByTestId("datetime-input")).toHaveValue(
new RegExp(dateToDatetimeFieldValue(expectedTime))
);
});
});

// todo: enable some of these tests to run in offline mode
// as well?
Expand Down

0 comments on commit 8569566

Please sign in to comment.