From 5679c86dacca73a694ea0a8a3364d1db80c86785 Mon Sep 17 00:00:00 2001
From: Ivan <8611739+IRBorisov@users.noreply.github.com>
Date: Tue, 14 Jan 2025 16:11:33 +0300
Subject: [PATCH] R: Integrate Playwright as end-to-end testing
---
.github/workflows/frontend.yml | 10 +++-
.gitignore | 2 +
.vscode/extensions.json | 3 +-
README.md | 2 +
rsconcept/frontend/package-lock.json | 64 +++++++++++++++++++++++++
rsconcept/frontend/package.json | 6 ++-
rsconcept/frontend/playwright.config.ts | 31 ++++++++++++
rsconcept/frontend/tests/app.spec.ts | 9 ++++
rsconcept/frontend/tsconfig.node.json | 2 +-
9 files changed, 124 insertions(+), 5 deletions(-)
create mode 100644 rsconcept/frontend/playwright.config.ts
create mode 100644 rsconcept/frontend/tests/app.spec.ts
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"]
}