Skip to content

Commit

Permalink
chore: setup e2e test with playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-lebeau committed Jan 17, 2024
1 parent 37b98b6 commit 45f859f
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 10 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: deploy

on:
deployment_status:

jobs:
e2e:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
container:
image: mcr.microsoft.com/playwright:v1.40.0-jammy

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v3
with:
node-version: 20
cache: "npm"

- run: npm ci

- run: npx playwright install --with-deps

- run: npx playwright test
env:
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}

- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
2 changes: 2 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: pr

on:
push:
branches: [main]
pull_request:
branches: [main]

Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ next-env.d.ts
.env*
.flaskenv*
!.env.project
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
10 changes: 10 additions & 0 deletions e2e/anonymous.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, test } from "@playwright/test";

// Reset storage state for this file to avoid being authenticated
test.use({ storageState: { cookies: [], origins: [] } });

test("has a login button", async ({ page }) => {
await page.goto("/");

await expect(page.getByRole("link", { name: "Login" })).toBeVisible();
});
44 changes: 44 additions & 0 deletions e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { expect, test as setup } from "@playwright/test";
import { AUTH_FILE } from "../playwright.config";

if (!process.env.CI) {
try {
setup.use({ storageState: AUTH_FILE });
} catch {
// No auth file, so we need to authenticate
}
}

setup("authenticate", async ({ page }) => {
await page.goto("/");

if (await page.locator('button[name="User menu"]').isVisible()) {
// Already logged in
return;
}

await page.getByRole("link", { name: "Login" }).click();
await page.getByRole("textbox", { name: "Email" }).fill("[email protected]");
await page.getByRole("button", { name: "Sign in with Email" }).click();
await page.goto("https://ethereal.email/login");
await page
.getByRole("textbox", { name: "Email address" })
.fill(process.env.EMAIL_SERVER_USER);
await page
.getByRole("textbox", { name: "Password" })
.fill(process.env.EMAIL_SERVER_PASSWORD);
await page.getByRole("button", { name: "Log in" }).click();
await page.goto("https://ethereal.email/messages");
await page
.getByRole("link", { name: /Sign in to/ })
.first()
.click();
await page
.frameLocator("#message iframe")
.getByRole("link", { name: "Sign in" })
.click();

await expect(page.locator('button[name="User menu"]')).toBeVisible();

await page.context().storageState({ path: AUTH_FILE });
});
9 changes: 9 additions & 0 deletions e2e/home.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { expect, test } from "@playwright/test";

test("has user menu", async ({ page }) => {
await page.goto("/");

await page.locator('button[name="User menu"]').click();

await expect(page.getByText("[email protected]")).toBeVisible();
});
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const config: Config = {
collectCoverage: false,
coverageProvider: "v8",
testEnvironment: "jsdom",

testMatch: ["<rootDir>/src/**/*.test.(ts|tsx|js)"],
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
Expand Down
30 changes: 23 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"lint": "next lint -- -f gha",
"test": "jest",
"test:watch": "jest --watch",
"e2e": "playwright test",
"postinstall": "prisma generate"
},
"prisma": {
Expand Down Expand Up @@ -51,6 +52,7 @@
"zod-fetch": "^0.1.1"
},
"devDependencies": {
"@playwright/test": "^1.41.0",
"@testing-library/jest-dom": "^6.2.0",
"@testing-library/react": "^14.1.2",
"@total-typescript/ts-reset": "^0.5.1",
Expand Down
28 changes: 28 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { defineConfig, devices } from "@playwright/test";
import "dotenv/config";

export const AUTH_FILE = "playwright/.auth/user.json";

export default defineConfig({
testDir: "./e2e",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 1 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
use: {
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL,
trace: process.env.CI ? "on-first-retry" : "retain-on-failure",
},
projects: [
{ name: "setup", testMatch: /.*\.setup\.ts/ },
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
storageState: AUTH_FILE,
},
dependencies: ["setup"],
},
],
});
2 changes: 1 addition & 1 deletion prisma/seed.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const prisma = new PrismaClient();
function createBar(label, max) {
const bar = new cliProgress.SingleBar(
{
format: ` {bar} {percentage}% | ETA: {eta_formatted}s | {value}/{total} | ${label}`,
format: ` {bar} {percentage}% | ETA: {eta_formatted} | {value}/{total} | ${label}`,
},
cliProgress.Presets.shades_classic
);
Expand Down
6 changes: 5 additions & 1 deletion src/components/nav/user-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export function UserMenu({ className }: { className?: string }) {
<div className={cn(className)}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
<Button
variant="ghost"
className="relative h-8 w-8 rounded-full"
name="User menu"
>
<Avatar className="h-8 w-8">
<AvatarImage src={user.image} alt={user.name} />
<AvatarFallback>{user.initial}</AvatarFallback>
Expand Down
2 changes: 2 additions & 0 deletions src/types/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ declare global {
CI: string | undefined;
GITHUB_ACTIONS: string | undefined;

PLAYWRIGHT_TEST_BASE_URL: string;

// make typescript error when using env vars that are not defined in here
[key: string]: undefined;
}
Expand Down

0 comments on commit 45f859f

Please sign in to comment.