Skip to content

Commit

Permalink
test: add e2e tests
Browse files Browse the repository at this point in the history
Signed-off-by: rare-magma <[email protected]>
  • Loading branch information
rare-magma committed Feb 25, 2024
1 parent cf30731 commit 1977dbd
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 37 deletions.
10 changes: 9 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,15 @@ You will also see any lint errors in the console.

Launches the test runner in the interactive watch mode.

6. Update package-lock.json when installing a new lib:
6. Run end to end tests

```sh
pnpm e2e:ui
```

Launches the e2e test runner in the interactive mode.

7. Update package-lock.json when installing a new lib:

```sh
npm i --package-lock-only
Expand Down
20 changes: 0 additions & 20 deletions e2e/example.spec.ts

This file was deleted.

164 changes: 164 additions & 0 deletions e2e/happyPath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { expect, test } from "@playwright/test";

test("should complete the happy path", async ({ page, isMobile }) => {
await page.goto("/");

// "should show landing page
await expect(page.getByText("new")).toBeVisible();
await expect(page.getByText("help")).toBeVisible();

// should create new budget
await page.getByText("new").click();

await expect(page.getByText("Statistics")).toBeVisible();
await expect(page.getByText("Revenue")).toBeVisible();
await expect(page.getByText("Expenses")).toBeVisible();

// should create new incomes
await page.locator("#Revenue-1-name").click();
await page.locator("#Revenue-1-name").fill("salary");

await expect(page.locator("#Revenue-1-name")).toHaveValue("salary");

await page.locator("#Revenue-1-value").click();
await page.locator("#Revenue-1-value").fill("1000");
await page.locator("#Revenue-1-name").click();

await expect(page.locator("#Revenue-1-value")).toHaveValue("$1,000");

await page.getByLabel("add item to Revenue").click();
await page.getByLabel("item 2 name").fill("sale");
await page.getByLabel("item 2 name").press("Tab");
await page.getByLabel("item 2 value").fill("50");
await page.getByLabel("item 2 value").press("Tab");

await expect(page.getByLabel("item 2 name")).toHaveValue("sale");
await expect(page.getByLabel("item 2 value")).toHaveValue("$50");

await page.locator("#Revenue-2-operate-button").press("Tab");
await page.getByLabel("delete item 2").press("Tab");
await page.getByLabel("add item to Revenue").press("Enter");
await page.getByLabel("item 3 name").fill("bonus");
await page.getByLabel("item 3 name").press("Tab");
await page.getByLabel("item 3 value").fill("25");
await page.getByLabel("item 3 value").press("Tab");
await page.locator("#Revenue-3-operate-button").press("Enter");
await page.getByLabel("add", { exact: true }).fill("10");
await page.getByLabel("add", { exact: true }).press("Enter");

await expect(page.getByLabel("item 3 name")).toHaveValue("bonus");
await expect(page.getByLabel("item 3 value")).toHaveValue("$35");

// should create new expenses
await page.locator("#Expenses-1-name").click();
await page.locator("#Expenses-1-name").fill("rent");
await page.locator("#Expenses-1-name").press("Tab");
await page.locator("#Expenses-1-value").fill("500.75");
await page.locator("#Expenses-1-value").press("Tab");
await page.locator("#Expenses-1-operate-button").press("Tab");
await page.locator("#delete-Expenses-1-button").press("Tab");

await expect(page.locator("#Expenses-1-name")).toHaveValue("rent");
await expect(page.locator("#Expenses-1-value")).toHaveValue("$500.75");

await page.getByLabel("add item to Expenses").press("Enter");
await page.locator("#Expenses-2-name").fill("groceries");
await page.locator("#Expenses-2-name").press("Tab");
await page.locator("#Expenses-2-value").fill("100");
await page.locator("#Expenses-2-value").press("Tab");
await page.locator("#Expenses-2-operate-button").press("Tab");
await page.locator("#delete-Expenses-2-button").press("Tab");

await expect(page.locator("#Expenses-2-name")).toHaveValue("groceries");
await expect(page.locator("#Expenses-2-value")).toHaveValue("$100");

await page.getByLabel("add item to Expenses").press("Enter");
await page.locator("#Expenses-3-name").fill("item");
await page.locator("#Expenses-3-name").press("Tab");
await page.locator("#Expenses-3-value").fill("50");

await expect(page.locator("#Expenses-3-name")).toHaveValue("item");
await expect(page.locator("#Expenses-3-value")).toHaveValue("$50");

await page.locator("#Expenses-3-operate-button").click();
await page.getByLabel("select type of operation on").click();
await page.getByLabel("subtraction").click();
await page.getByLabel("subtract", { exact: true }).click();
await page.getByLabel("subtract", { exact: true }).fill("50");
await page.getByLabel("apply change to item value").click();

await expect(page.locator("#Expenses-3-value")).toHaveValue("$0");

await page.getByLabel("add item to Expenses").click();
await page.getByLabel("item 4 name").fill("mistake");
await page.getByLabel("item 4 value").click();
await page.getByLabel("item 4 value").fill("20");
await expect(page.locator("#Expenses-4-name")).toHaveValue("mistake");
await expect(page.locator("#Expenses-4-value")).toHaveValue("$20");

await page.getByLabel("delete item 4").click();
await page.getByLabel("confirm item 4 deletion").click();

await expect(page.locator("#Expenses-4-name")).not.toBeVisible();
await expect(page.locator("#Expenses-4-value")).not.toBeVisible();

// should undo changes
if (isMobile) {
await page.getByLabel("Toggle navigation").click();
await expect(page.locator("#offcanvasNavbarLabel-expand-md")).toBeVisible();
}

await page.getByLabel("undo change").click();

await expect(page.locator("#Expenses-4-name")).toHaveValue("mistake");
await expect(page.locator("#Expenses-4-value")).toHaveValue("$20");

// should handle statistics changes
await page.getByLabel("reserves").click();
await page.getByLabel("reserves").fill("2000");

await expect(page.locator("#reserves")).toHaveValue("$2,000");
await expect(page.getByLabel("available", { exact: true })).toHaveValue(
"$464.25",
);
await expect(page.locator("#with-goal")).toHaveValue("$355.75");
await expect(page.locator("#saved")).toHaveValue("$108.5");

await page.getByLabel("calculate savings goal").click();

await expect(page.getByLabel("available", { exact: true })).toHaveValue(
"$464.25",
);
await expect(page.locator("#with-goal")).toHaveValue("$0");
await expect(page.locator("#saved")).toHaveValue("$464.25");

// should handle budget changes
await page.getByLabel("budget name").fill("2024-01");
await expect(page.getByLabel("budget name")).toHaveValue("2024-01");

if (isMobile) {
await page.getByLabel("Toggle navigation").click();
}

await page.getByLabel("new budget").click();

await expect(page.getByLabel("go to older budget")).toBeVisible();
await expect(page.getByLabel("budget name")).not.toHaveValue("2024-01");

if (isMobile) {
await page.getByLabel("Toggle navigation").click();
}
await page.getByLabel("delete budget").click();
await page.getByLabel("confirm budget deletion").click();

await expect(page.getByLabel("budget name")).toHaveValue("2024-01");

if (isMobile) {
await page.getByLabel("Toggle navigation").click();
}
await page.getByLabel("clone budget").click();

await expect(page.getByLabel("budget name")).toHaveValue("2024-01-clone");

await page.close();
});
85 changes: 85 additions & 0 deletions e2e/settingsHappyPath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { expect, test } from "@playwright/test";
import fs from "fs";

test("should complete the settings happy path", async ({ page, isMobile }) => {
await page.goto("/");

// should show charts page
await page.getByText("new").click();
await page.locator("#Expenses-1-name").click();
await page.locator("#Expenses-1-name").fill("rent");
await page.locator("#Expenses-1-name").press("Tab");
await page.locator("#Expenses-1-value").fill("500.75");

await expect(page.locator("#Expenses-1-name")).toHaveValue("rent");
await expect(page.locator("#Expenses-1-value")).toHaveValue("$500.75");

await page.getByLabel("open charts view").click();

await expect(page.getByText("Revenue vs expenses")).toBeVisible();
await expect(page.getByText("Savings", { exact: true })).toBeVisible();
await expect(page.getByText("Reserves", { exact: true })).toBeVisible();
await expect(page.getByText("Available vs with goal")).toBeVisible();
await expect(page.getByText("Savings goal")).toBeVisible();

await page.getByPlaceholder("Filter...").click();
await page.getByPlaceholder("Filter...").fill("rent");
await page.getByLabel(/rent/).click();

await page.getByText("strict match").click();
await expect(page.getByText("Expenses filtered by: rent")).toBeVisible();

await page.getByLabel("go back to budgets").click();

await expect(page.getByText("Statistics")).toBeVisible();

// should handle settings changes
if (isMobile) {
await page.getByLabel("Toggle navigation").click();
}
await page.getByLabel("budget settings").click();
await page.getByLabel("select display currency").click();
await page.getByLabel("select display currency").fill("eur");
await page.getByLabel("EUR").click();

await expect(page.getByText("€0.00")).toBeVisible();
await expect(page.getByText("CSV")).toBeVisible();

// should handle downloads
const csvDownloadPromise = page.waitForEvent("download");
await page.getByLabel("export budget as csv").click();
const csvDownload = await csvDownloadPromise;
expect(csvDownload.suggestedFilename()).toMatch(/.csv/);
expect(
(await fs.promises.stat(await csvDownload.path())).size,
).toBeGreaterThan(0);

await page.getByLabel("budget settings").click();
await expect(page.getByText("JSON")).toBeVisible();

const jsonDownloadPromise = page.waitForEvent("download");
await page.getByLabel("export budget as json").click();
const jsonDownload = await jsonDownloadPromise;
expect(jsonDownload.suggestedFilename()).toMatch(/.json/);
expect(
(await fs.promises.stat(await jsonDownload.path())).size,
).toBeGreaterThan(0);

// should handle import
await page.locator("#import").setInputFiles("./guitos-sample.json");

await expect(page.getByLabel("go to older budget")).toBeVisible();
await page.getByLabel("go to older budget").click();

if (isMobile) {
await page.getByLabel("Toggle navigation").click();
}

await expect(
page.getByRole("combobox", { name: "search in budgets" }),
).toBeVisible();

await expect(page.getByLabel("budget name")).toHaveValue("2023-08");

await page.close();
});
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
"build": "vite build",
"serve": "vite preview",
"test": "vitest",
"e2e": "playwright test --reporter=list --project chromium",
"e2e:ui": "playwright test --ui --project chromium",
"e2e:mobile": "playwright test --reporter=list --project 'Mobile Chrome'",
"e2e:mobile:ui": "playwright test --ui --project 'Mobile Chrome'",
"coverage": "vitest run --coverage --silent",
"coverage:ui": "vitest --ui --open --coverage --silent",
"lint": "pnpm dlx eslint src e2e --fix && pnpm dlx stylelint src/**/*.css --fix && pnpm dlx prettier --write src e2e",
Expand Down
22 changes: 6 additions & 16 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default defineConfig({
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
baseURL: "http://localhost:5173",

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
Expand Down Expand Up @@ -56,22 +56,12 @@ export default defineConfig({
name: "Mobile Safari",
use: { ...devices["iPhone 12"] },
},

/* Test against branded browsers. */
// {
// name: "Microsoft Edge",
// use: { ...devices["Desktop Edge"], channel: "msedge" },
// },
// {
// name: "Google Chrome",
// use: { ...devices["Desktop Chrome"], channel: "chrome" },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
webServer: {
command: "pnpm run start",
url: "http://localhost:5173",
reuseExistingServer: !process.env.CI,
},
});

0 comments on commit 1977dbd

Please sign in to comment.