diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index fc35cf39..fc2dd0bd 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -23,7 +23,6 @@ jobs: strategy: matrix: node-version: [22.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - uses: actions/checkout@v4 @@ -35,10 +34,17 @@ jobs: cache: "npm" - name: Build run: | - npm install -g typescript vite jest + npm install -g typescript vite jest playwright + npx playwright install --with-deps npm ci npm run build --if-present - name: Run CI run: | npm run lint npm test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 45cd2dcb..8d57b54f 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ bower_components venv/ /GitExtensions.settings rsconcept/frontend/public/privacy.pdf +/rsconcept/frontend/playwright-report +/rsconcept/frontend/test-results diff --git a/.vscode/extensions.json b/.vscode/extensions.json index a12abd63..22ecb699 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -19,7 +19,8 @@ "ms-python.pylint", "ms-python.autopep8", "ms-python.vscode-pylance", - "vscode-icons-team.vscode-icons" + "vscode-icons-team.vscode-icons", + "ms-playwright.playwright" ], "unwantedRecommendations": [] } diff --git a/README.md b/README.md index 745110ce..308593cd 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ This readme file is used mostly to document project dependencies and conventions - ts-jest - @types/jest - @lezer/generator + - @playwright/test
@@ -132,6 +133,7 @@ This readme file is used mostly to document project dependencies and conventions - isort - Django - SQLite + - Playwright
diff --git a/rsconcept/frontend/package-lock.json b/rsconcept/frontend/package-lock.json index 7922c691..b0d339c9 100644 --- a/rsconcept/frontend/package-lock.json +++ b/rsconcept/frontend/package-lock.json @@ -34,6 +34,7 @@ }, "devDependencies": { "@lezer/generator": "^1.7.2", + "@playwright/test": "^1.49.1", "@types/jest": "^29.5.14", "@types/node": "^22.10.5", "@types/react": "^19.0.6", @@ -2413,6 +2414,22 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", + "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.49.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@reactflow/background": { "version": "11.3.14", "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz", @@ -8450,6 +8467,53 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", + "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.49.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", + "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "dev": true, + "license": "Apache-2.0", + "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, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", diff --git a/rsconcept/frontend/package.json b/rsconcept/frontend/package.json index 791e6376..ca9d8d3f 100644 --- a/rsconcept/frontend/package.json +++ b/rsconcept/frontend/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "generate": "lezer-generator src/components/RSInput/rslang/rslangFast.grammar -o src/components/RSInput/rslang/parser.ts && lezer-generator src/components/RSInput/rslang/rslangAST.grammar -o src/components/RSInput/rslang/parserAST.ts && lezer-generator src/components/RefsInput/parse/refsText.grammar -o src/components/RefsInput/parse/parser.ts", - "test": "jest", + "test": "jest && playwright test", "dev": "vite --host", "build": "tsc && vite build", "lint": "eslint . --report-unused-disable-directives --max-warnings 0", @@ -38,6 +38,7 @@ }, "devDependencies": { "@lezer/generator": "^1.7.2", + "@playwright/test": "^1.49.1", "@types/jest": "^29.5.14", "@types/node": "^22.10.5", "@types/react": "^19.0.6", @@ -67,6 +68,9 @@ "jest": { "preset": "ts-jest", "testEnvironment": "node", + "testPathIgnorePatterns": [ + "/tests/" + ], "transform": { "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest" }, diff --git a/rsconcept/frontend/playwright.config.ts b/rsconcept/frontend/playwright.config.ts new file mode 100644 index 00000000..8bd8ad25 --- /dev/null +++ b/rsconcept/frontend/playwright.config.ts @@ -0,0 +1,31 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: 'tests', + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + reporter: 'html', + projects: [ + { + name: 'Desktop Chrome', + use: { ...devices['Desktop Chrome'] } + }, + { + name: 'Desktop Firefox', + use: { ...devices['Desktop Firefox'] } + }, + { + name: 'Desktop Safari', + use: { ...devices['Desktop Safari'] } + } + ], + use: { + baseURL: 'http://localhost:3000', + trace: 'on-first-retry' + }, + webServer: { + command: 'npm run dev', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI + } +}); diff --git a/rsconcept/frontend/tests/app.spec.ts b/rsconcept/frontend/tests/app.spec.ts new file mode 100644 index 00000000..b5b67f3b --- /dev/null +++ b/rsconcept/frontend/tests/app.spec.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@playwright/test'; + +test('should load the homepage and display login button', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle('Концепт Портал'); + await expect(page.getByRole('heading', { name: 'Портал' })).toBeVisible(); + await page.click('.h-full > .mr-1'); + await expect(page.getByText('Логин или email')).toBeVisible(); +}); diff --git a/rsconcept/frontend/tsconfig.node.json b/rsconcept/frontend/tsconfig.node.json index 364bc0ea..f1de0abc 100644 --- a/rsconcept/frontend/tsconfig.node.json +++ b/rsconcept/frontend/tsconfig.node.json @@ -6,5 +6,5 @@ "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, - "include": ["vite.config.ts", "package.json"] + "include": ["vite.config.ts", "package.json", "playwright.config.ts", "tests"] }