add playwright tests
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -25,3 +25,9 @@ dist-ssr
|
||||
|
||||
# env
|
||||
.env*
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
||||
76
package-lock.json
generated
76
package-lock.json
generated
@@ -25,8 +25,10 @@
|
||||
"@eslint/compat": "^1.2.9",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "^9.28.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/node": "^22.15.30",
|
||||
"@vitejs/plugin-react": "^4.5.1",
|
||||
"@vitest/ui": "^3.2.2",
|
||||
"eslint": "^9.28.0",
|
||||
@@ -1493,6 +1495,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz",
|
||||
"integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.52.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@polka/url": {
|
||||
"version": "1.0.0-next.29",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
||||
@@ -2151,6 +2168,15 @@
|
||||
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz",
|
||||
"integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
@@ -6520,6 +6546,50 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz",
|
||||
"integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright-core": "1.52.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz",
|
||||
"integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright/node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
@@ -7983,6 +8053,12 @@
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unicode-properties": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"backend": "cd ../kt-backend && npm start",
|
||||
"analyze": "source-map-explorer 'dist/**/*.js'",
|
||||
"test": "vitest",
|
||||
"i18n": "npx i18next 'src/**/*.{js,jsx,ts,tsx}' --config i18next-parser.config.cjs"
|
||||
"test:e2e": "playwright test",
|
||||
"i18n": "i18next 'src/**/*.{js,jsx,ts,tsx}' --config i18next-parser.config.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
@@ -35,8 +36,10 @@
|
||||
"@eslint/compat": "^1.2.9",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "^9.28.0",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/node": "^22.15.30",
|
||||
"@vitejs/plugin-react": "^4.5.1",
|
||||
"@vitest/ui": "^3.2.2",
|
||||
"eslint": "^9.28.0",
|
||||
@@ -53,4 +56,4 @@
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vitest": "^3.2.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
playwright.config.js
Normal file
81
playwright.config.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// @ts-check
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// import dotenv from 'dotenv';
|
||||
// import path from 'path';
|
||||
// dotenv.config({ path: path.resolve(__dirname, '.env') });
|
||||
|
||||
/**
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './test/e2e/',
|
||||
/* 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://localhost: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://localhost:3000',
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
});
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useContext, useState } from 'react'
|
||||
import { Button, TextField, DialogActions, DialogContent, DialogTitle, Radio, RadioGroup, FormControlLabel, FormControl, FormLabel, Autocomplete } from '@mui/material'
|
||||
import useFetch from '../UseFetch/UseFetch'
|
||||
import { DialogContext } from './Context'
|
||||
|
||||
export default function ProfileDialog({ apiServer, edit, t, token }) {
|
||||
export default function ProfileDialog({
|
||||
apiServer,
|
||||
edit,
|
||||
token
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
const { data: clubs = [], loading } = useFetch(apiServer + '/getClubs' + token)
|
||||
const dialog = useContext(DialogContext)
|
||||
|
||||
|
||||
97
test/e2e/basic.spec.js
Normal file
97
test/e2e/basic.spec.js
Normal file
@@ -0,0 +1,97 @@
|
||||
// e2e/basic.spec.js
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
const login = async (page, email = 'mario@wattsche.de', password = 'mmario84') => {
|
||||
await page.goto('http://localhost:5173/')
|
||||
await page.getByRole('banner').getByRole('button').nth(3).click()
|
||||
await page.getByRole('textbox', { name: 'Email' }).fill(email)
|
||||
await page.getByRole('textbox', { name: 'Passwort' }).fill(password)
|
||||
await page.getByRole('main').getByRole('button').click()
|
||||
// Optional: Warte auf ein Element, das nur nach Login sichtbar ist
|
||||
await page.waitForSelector('text=Alexander Zott')
|
||||
await expect(page.getByText('Alexander Zott')).toBeTruthy()
|
||||
}
|
||||
|
||||
test('Startseite lädt', async ({ page }) => {
|
||||
await page.goto('http://localhost:5173')
|
||||
console.log(await page.title())
|
||||
await page.pause()
|
||||
await expect(page).toHaveTitle('Karateturniere.de')
|
||||
})
|
||||
|
||||
test('login', async ({ page }) => {
|
||||
await login(page)
|
||||
})
|
||||
|
||||
test('Teilnehmer hinzufügen', async ({ page }) => {
|
||||
await login(page)
|
||||
await page.getByRole('button', { name: 'Teilnehmer hinzufügen' }).click()
|
||||
await page.getByRole('textbox', { name: 'Name', exact: true }).fill('qqq')
|
||||
await page.getByRole('textbox', { name: 'Vorname' }).fill('qqq')
|
||||
await page.getByRole('textbox', { name: 'Vorname' }).press('Tab')
|
||||
await page.getByRole('combobox', { name: 'Verein' }).click()
|
||||
await page.getByRole('option', { name: 'KD tv remagen' }).click()
|
||||
await page.getByRole('combobox', { name: 'Gürtel' }).click()
|
||||
await page.getByRole('option', { name: '8. Kyu' }).click()
|
||||
await page.getByRole('textbox', { name: 'Geburtstag' }).fill('1111-11-11')
|
||||
await page.getByRole('button', { name: 'OK' }).click()
|
||||
await page.getByRole('textbox', { name: 'search' }).click()
|
||||
await page.getByRole('textbox', { name: 'search' }).fill('qqq')
|
||||
await page.getByText('qqq qqq')
|
||||
expect(await page.getByText('qqq qqq')).toBeTruthy()
|
||||
})
|
||||
|
||||
test('teilnehmer löschen', async ({ page }) => {
|
||||
await login(page)
|
||||
await page.getByRole('textbox', { name: 'search' }).click()
|
||||
await page.getByRole('textbox', { name: 'search' }).fill('qqq')
|
||||
await page
|
||||
.locator('div')
|
||||
// TODO : Fix has text
|
||||
.filter({ hasText: /^94\. Kyu91311\.11\.1111aaa aaa1\. Bonn-Bad Godesberger KD 1965 e\.V\.$/ })
|
||||
.getByRole('button')
|
||||
.nth(1)
|
||||
.click()
|
||||
await page.getByRole('button', { name: 'Delete' }).click()
|
||||
expect(await page.getByText('qqq qqq')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('Teilnehmer anmelden', async ({ page }) => {
|
||||
await login(page)
|
||||
await page.getByRole('button', { name: 'Anmeldung' }).first().click()
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^325DAN285\/6\/1997Alexander ZottKen Seikan KaiserslauternKataKumite$/ })
|
||||
.getByLabel('Kata')
|
||||
.click()
|
||||
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^325DAN285\/6\/1997Alexander ZottKen Seikan KaiserslauternKataKumite$/ })
|
||||
.getByLabel('Kumite')
|
||||
.click()
|
||||
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^3273\. Kyu335\/1\/1992Pascal ChristmannKen Seikan KaiserslauternKataKumite$/ })
|
||||
.getByLabel('Kata')
|
||||
.click()
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^3273\. Kyu335\/1\/1992Pascal ChristmannKen Seikan KaiserslauternKataKumite$/ })
|
||||
.getByLabel('Kumite')
|
||||
.click()
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^2390Kata-Team-Mixed8\. Kyu - 6\. Kyuage8 - 112$/ })
|
||||
.getByLabel('register Team', { exact: true })
|
||||
.click()
|
||||
await page
|
||||
.locator('div')
|
||||
.filter({ hasText: /^2429Kata-Team-Mixed8\. Kyu - 6\. Kyuage8 - 111$/ })
|
||||
.getByLabel('register Team', { exact: true })
|
||||
.click()
|
||||
await page.locator('div').filter({ hasText: /^3$/ }).click()
|
||||
await expect(page.getByRole('main')).toContainText('3')
|
||||
await expect(page.getByRole('main')).toContainText('2')
|
||||
})
|
||||
@@ -5,5 +5,6 @@ export default defineConfig({
|
||||
environment: 'jsdom',
|
||||
globals: true, // <-- macht describe, it, expect und auch React global für Tests
|
||||
setupFiles: ['./vitest.setup.js'], // eigene Setup-Datei (siehe unten)
|
||||
exclude: ['e2e', 'tests/e2e', '**/e2e/**', '**/playwright/**'],
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user