Add Playwright support for Task List

This commit is contained in:
Steve Kinney
2024-10-02 06:26:54 -05:00
parent 46d716bb38
commit a212170602
8 changed files with 152 additions and 37 deletions

2
.gitignore vendored
View File

@@ -15,6 +15,8 @@ pids/
dist/ dist/
build/ build/
out/ out/
playwright-report
test-results
# Environment variables # Environment variables
.env .env

View File

@@ -21,6 +21,7 @@
}, },
"homepage": "https://github.com/stevekinney/testing-javascript#readme", "homepage": "https://github.com/stevekinney/testing-javascript#readme",
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.47.2",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0", "@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1", "@testing-library/react": "^16.0.1",
@@ -39,7 +40,8 @@
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"vite": "^5.4.6", "vite": "^5.4.6",
"vitest": "^2.1.1" "vitest": "^2.1.1",
"wait-port": "^1.1.0"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.20.3", "body-parser": "^1.20.3",

View File

@@ -0,0 +1,78 @@
// @ts-check
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config({ path: path.resolve(__dirname, '.env') });
/**
* @see https://playwright.dev/docs/test-configuration
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* 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',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// 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,
// },
});

View File

@@ -1,3 +1,4 @@
import * as url from 'node:url';
import express from 'express'; import express from 'express';
import bodyParser from 'body-parser'; import bodyParser from 'body-parser';
import chalk from 'chalk'; import chalk from 'chalk';
@@ -59,7 +60,16 @@ app.delete('/api/tasks/:id', (req, res) => {
res.sendStatus(204); // No content to send back res.sendStatus(204); // No content to send back
}); });
const PORT = process.env.PORT || 3000; if (import.meta.url.startsWith('file:')) {
app.listen(PORT, () => { const modulePath = url.fileURLToPath(import.meta.url);
console.log(chalk.magenta(`Server is running on port ${chalk.green(PORT)}`)); if (process.argv[1] === modulePath) {
}); const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(
chalk.magenta(`Server is running on port ${chalk.green(PORT)}`),
);
});
}
}
export default app;

View File

@@ -0,0 +1,22 @@
import { test, expect } from '@playwright/test';
/** @type {import('../start-server').DevelopmentServer} */
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:5173');
});
test('it should load the page', async ({ page }) => {
await expect(page).toHaveTitle('Task List');
});
test('it should add a task', async ({ page }) => {
const input = page.getByLabel('Create Task');
const submit = page.getByRole('button', { name: 'Create Task' });
await input.fill('Learn Playwright');
await submit.click();
const heading = await page.getByRole('heading', { name: 'Learn Playwright' });
await expect(heading).toBeVisible();
});

63
package-lock.json generated
View File

@@ -87,7 +87,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", "@playwright/test": "^1.47.2",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@vitest/ui": "^2.1.1", "@vitest/ui": "^2.1.1",
@@ -179,6 +179,7 @@
"lucide-react": "^0.441.0" "lucide-react": "^0.441.0"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.47.2",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0", "@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1", "@testing-library/react": "^16.0.1",
@@ -197,7 +198,8 @@
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"vite": "^5.4.6", "vite": "^5.4.6",
"vitest": "^2.1.1" "vitest": "^2.1.1",
"wait-port": "^1.1.0"
} }
}, },
"examples/task-list/node_modules/chalk": { "examples/task-list/node_modules/chalk": {
@@ -1259,35 +1261,6 @@
"vite": "^5.0.0" "vite": "^5.0.0"
} }
}, },
"node_modules/@tailwindcss/nesting": {
"version": "0.0.0-insiders.565cd3e",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-nested": "^5.0.5"
},
"peerDependencies": {
"postcss": "^8.2.15"
}
},
"node_modules/@tailwindcss/nesting/node_modules/postcss-nested": {
"version": "5.0.6",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.0.6"
},
"engines": {
"node": ">=12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/@testing-library/dom": { "node_modules/@testing-library/dom": {
"version": "10.4.0", "version": "10.4.0",
"license": "MIT", "license": "MIT",
@@ -5790,6 +5763,34 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/wait-port": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz",
"integrity": "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
"commander": "^9.3.0",
"debug": "^4.3.4"
},
"bin": {
"wait-port": "bin/wait-port.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/wait-port/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/webidl-conversions": { "node_modules/webidl-conversions": {
"version": "7.0.0", "version": "7.0.0",
"dev": true, "dev": true,

View File

@@ -9,7 +9,7 @@ export const css = {
postcss: { postcss: {
plugins: [ plugins: [
tailwindcss({ tailwindcss({
content: ['./src/**/*.{html,js,jsx,ts,tsx}'], content: ['./src/**/*.{html,js,jsx,ts,tsx}', './index.html'],
theme: { theme: {
extend: { extend: {
container: { container: {