diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml index b1e4e301..7d58d20f 100644 --- a/.gitea/workflows/main.yml +++ b/.gitea/workflows/main.yml @@ -27,20 +27,25 @@ jobs: run: npm run typecheck Playwright: - name: Run end-to-end tests + timeout-minutes: 60 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '18' - - name: Install dependencies - run: npm ci - - name: Install playwright browsers - run: npx playwright install --with-deps - - name: Run Playwright Test - run: npx playwright test - + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 Github: needs: test_with_playwright diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index 7ae1425e..00e5ed2d 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -27,16 +27,22 @@ jobs: run: npm run typecheck Playwright: - name: Run end-to-end tests + timeout-minutes: 60 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '18' - - name: Install dependencies - run: npm ci - - name: Install playwright browsers - run: npx playwright install --with-deps - - name: Run Playwright Test - run: npx playwright test + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index c1695636..bc4e3d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ stats.html pnpm-lock.yaml bun.lockb .jj +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index ecb1857a..bb693a44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nanostores/router": "0.11.0", "@nanostores/solid": "0.4.2", + "@playwright/test": "1.41.2", "@popperjs/core": "2.11.8", "@sentry/browser": "5.30.0", "@solid-primitives/media": "2.2.3", @@ -4695,6 +4696,21 @@ "node": ">=10.12.0" } }, + "node_modules/@playwright/test": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", + "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", + "dev": true, + "dependencies": { + "playwright": "1.41.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", @@ -13253,6 +13269,50 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", + "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", + "dev": true, + "dependencies": { + "playwright-core": "1.41.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", + "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "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/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index 41334bce..75167868 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nanostores/router": "0.11.0", "@nanostores/solid": "0.4.2", + "@playwright/test": "1.41.2", "@popperjs/core": "2.11.8", "@sentry/browser": "5.30.0", "@solid-primitives/media": "2.2.3", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..250c22cb --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * 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, + // }, +}) diff --git a/test/basic-routes.test.сjs b/test/basic-routes.test.сjs deleted file mode 100644 index 52eb41a2..00000000 --- a/test/basic-routes.test.сjs +++ /dev/null @@ -1,38 +0,0 @@ -const { chromium } = require('playwright'); - -;(async () => { - const browser = await chromium.launch(); - const context = await browser.newContext(); - - // Define the URLs to visit - const pagesToVisit = [ - 'http://localhost:3000/', - 'http://localhost:3000/feed', - 'http://localhost:3000/create', - 'http://localhost:3000/about/donate', - 'http://localhost:3000/authors', - 'http://localhost:3000/topics', - 'http://localhost:3000/inbox', - ]; - - // Loop through the pages and visit each one - for (const pageUrl of pagesToVisit) { - const page = await context.newPage(); - - // Log a message before visiting the page - console.log(`Visiting page: ${pageUrl}`); - - await page.goto(pageUrl); - - // Add your test assertions here if needed - - // Log a message after visiting the page - console.log(`Finished visiting page: ${pageUrl}`); - - // Close the page before moving to the next one - await page.close(); - } - - // Close the browser - await browser.close(); -})(); diff --git a/tests/basic-routes.spec.ts b/tests/basic-routes.spec.ts new file mode 100644 index 00000000..67956cc4 --- /dev/null +++ b/tests/basic-routes.spec.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test' + +const pagesTitles = { + 'http://localhost:3000/': 'Дискурс', + 'http://localhost:3000/feed': 'Дискурс: лента', + 'http://localhost:3000/create': 'Дискурс', + 'http://localhost:3000/about/donate': 'Дискурс: поддержка', + 'http://localhost:3000/authors': 'Дискурс: авторы', + 'http://localhost:3000/topics': 'Дискурс: темы', + 'http://localhost:3000/inbox': 'Дискурс', +} + +test('has title', async ({ page }) => { + await page.goto('http://localhost:3000/') + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Дискурс/) +}) + +test('check some links', async ({ page }) => { + await page.goto('http://localhost:3000/feed') + + await expect(page).toHaveTitle(/Дискурс/) + + // Click the get started link. + // await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects page to have a heading with the name of Installation. + //await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +})