add e2e tests

This commit is contained in:
Pavel Mineev 2022-08-21 20:25:20 -07:00 committed by Dmitry Verkhoturov
parent 9ad3be2e97
commit 0f7ac514fb
13 changed files with 353 additions and 3 deletions

View File

@ -1,14 +1,20 @@
/logs/
/target/
/var/
/frontend/node_modules/
/frontend/apps/remark42/node_modules/
/frontend/apps/remark42/public/
/.vscode/
/.idea/
/bin/
/.git/
# frontend files not needed in docker image
/frontend/node_modules/
/frontend/apps/remark42/node_modules/
/frontend/apps/remark42/public/
# e2e tests arficats
/frontend/e2e/playwright-report/
/frontend/e2e/playwright/.cache/
/frontend/e2e/test-results/
# source files
docker-compose.yml
compose-dev-backend.yml
@ -28,3 +34,4 @@ debug.test
*.test
remark42
/backend/var/
/playwright-report/

34
.github/workflows/e2e-tests.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: e2e
on:
push:
branches: [master]
paths:
- "frontend/apps/remark42/**"
- "frontend/e2e/**"
pull_request:
branches: [master]
paths:
- "frontend/apps/remark42/**"
- "frontend/e2e/**"
jobs:
tests:
name: Tests
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build & run containers
id: tests
run: COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f compose-e2e-test.yml up --build --quiet-pull --exit-code-from tests
- uses: actions/upload-artifact@v2
if: always()
with:
name: playwright-report
path: ./playwright-report/
retention-days: 30

1
.gitignore vendored
View File

@ -24,3 +24,4 @@ compose-private-frontend.yml
compose-private.yml
/backend/_example/*/vendor
http-client.env.json
/playwright-report/

36
compose-e2e-test.yml Normal file
View File

@ -0,0 +1,36 @@
# compose for running e2e tests in CI
version: "2"
services:
remark42:
build:
context: .
dockerfile: Dockerfile
args:
- SKIP_BACKEND_TEST=true
- SKIP_FRONTEND_TEST=true
image: umputun/remark42:dev
container_name: "remark42"
environment:
# remark42 hostname used for proper dev auth work for tests container which connects to it
# using the such hostname (unlike local development where 127.0.0.1 is used)
- REMARK_URL=http://remark42:8080
- SECRET=12345
- DEBUG=true
- ADMIN_PASSWD=password
- AUTH_DEV=true # activate local OAuth "dev" listening on http://remark42:8084
- ADMIN_SHARED_ID=dev_user # set admin flag for default user on local oauth2
- AUTH_ANON=true
- AUTH_EMAIL_ENABLE=true
volumes:
- ./var:/srv/var
tests:
build:
context: ./frontend
dockerfile: Dockerfile.e2e
depends_on: [remark42]
volumes:
- ./playwright-report:/frontend/e2e/playwright-report

7
frontend/.dockerignore Normal file
View File

@ -0,0 +1,7 @@
/.vscode/
/.idea/
# e2e tests arficats
/e2e/playwright-report/
/e2e/playwright/.cache/
/e2e/test-results/

15
frontend/Dockerfile.e2e Normal file
View File

@ -0,0 +1,15 @@
FROM mcr.microsoft.com/playwright:v1.25.0-focal
ENV CI true
WORKDIR /frontend
COPY ./package.json ./pnpm-workspace.yaml ./pnpm-lock.yaml /frontend/
COPY ./e2e/package.json /frontend/e2e/
RUN corepack enable pnpm && pnpm install
COPY ./e2e/playwright.config.ts /frontend/e2e/
COPY ./e2e/tests /frontend/e2e/tests/
WORKDIR /frontend/e2e
CMD pnpm test

4
frontend/e2e/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
node_modules/
/test-results/
/playwright-report/
/playwright/.cache/

19
frontend/e2e/package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "@remark42/tests",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"test": "playwright test"
},
"author": "Paul Mineev <paul@mineev.me>",
"license": "MIT",
"devDependencies": {
"@playwright/test": "^1.25.0",
"@types/node": "^18.7.8",
"nanoid": "^4.0.0",
"playwright": "^1.25.0",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
}
}

View File

@ -0,0 +1,107 @@
import type { PlaywrightTestConfig } from '@playwright/test'
import { devices } from '@playwright/test'
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './tests',
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000,
},
/* 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: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: process.env.CI ? 'http://remark42:8080' : 'http://127.0.0.1:8080',
/* 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: {
// channel: 'msedge',
// },
// },
// {
// name: 'Google Chrome',
// use: {
// channel: 'chrome',
// },
// },
],
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
// outputDir: 'test-results/',
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// port: 3000,
// },
}
export default config

View File

@ -0,0 +1,8 @@
/** @type {import('prettier').Config} */
module.exports = {
singleQuote: true,
semi: false,
arrowParens: 'always',
trailingComma: 'es5',
printWidth: 120,
}

View File

@ -0,0 +1,30 @@
import { test } from '@playwright/test'
import { nanoid } from 'nanoid'
import * as path from 'path'
test.describe('Post comment', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/web/')
})
test('as dev user', async ({ page, browserName }) => {
const iframe = page.frameLocator('iframe[name]')
await iframe.locator('text=Sign In').click()
const [authPage] = await Promise.all([
page.waitForEvent('popup'),
iframe.locator("[title='Sign In with Dev']").click(),
])
await authPage.locator('text=Authorize').click()
// triggers tab visibility and enables widget to re-render with auth state
await page.press('iframe[name]', 'Tab')
await iframe.locator('textarea').click()
const message = `Hello world! ${nanoid()}`
await iframe.locator('textarea').type(message)
await iframe.locator('text=Send').click()
// checks if comment was posted
iframe.locator(`text=${message}`).first()
await page.reload()
// checks if saved comment is visible
iframe.locator(`text=${message}`).first()
})
})

View File

@ -213,6 +213,22 @@ importers:
webpack-cli: 4.10.0_orc2ewcajya4tocnqelr4vzh7u
webpack-dev-server: 4.9.3_77l47gmqkrqiei5z7sbwz5iaj4
e2e:
specifiers:
'@playwright/test': ^1.25.0
'@types/node': ^18.7.8
nanoid: ^4.0.0
playwright: ^1.25.0
ts-node: ^10.9.1
typescript: ^4.7.4
devDependencies:
'@playwright/test': 1.25.0
'@types/node': 18.7.8
nanoid: 4.0.0
playwright: 1.25.0
ts-node: 10.9.1_itmtyrrie7wpjnrpwbb5uqyzwa
typescript: 4.7.4
packages/api:
specifiers:
'@types/node': ^18.0.5
@ -2346,6 +2362,15 @@ packages:
resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==}
dev: true
/@playwright/test/1.25.0:
resolution: {integrity: sha512-j4EZhTTQI3dBeWblE21EV//swwmBtOpIrLdOIJIRv4uqsLdHgBg1z+JtTg+AeC5o2bAXIE26kDNW5A0TimG8Bg==}
engines: {node: '>=14'}
hasBin: true
dependencies:
'@types/node': 18.7.8
playwright-core: 1.25.0
dev: true
/@polka/url/1.0.0-next.21:
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
dev: true
@ -2880,6 +2905,10 @@ packages:
resolution: {integrity: sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==}
dev: true
/@types/node/18.7.8:
resolution: {integrity: sha512-/YP55EMK2341JkODUb8DM9O0x1SIz2aBvyF33Uf1c76St3VpsMXEIW0nxuKkq/5cxnbz0RD9cfwNZHEAZQD3ag==}
dev: true
/@types/normalize-package-data/2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
dev: true
@ -8393,6 +8422,12 @@ packages:
hasBin: true
dev: true
/nanoid/4.0.0:
resolution: {integrity: sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==}
engines: {node: ^14 || ^16 || >=18}
hasBin: true
dev: true
/nanospinner/1.1.0:
resolution: {integrity: sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==}
dependencies:
@ -8980,6 +9015,21 @@ packages:
find-up: 4.1.0
dev: true
/playwright-core/1.25.0:
resolution: {integrity: sha512-kZ3Jwaf3wlu0GgU0nB8UMQ+mXFTqBIFz9h1svTlNduNKjnbPXFxw7mJanLVjqxHJRn62uBfmgBj93YHidk2N5Q==}
engines: {node: '>=14'}
hasBin: true
dev: true
/playwright/1.25.0:
resolution: {integrity: sha512-Z+pQNWI17Qx/tHhnmgMmPsptsisXpKgAnUvYv98kctlHUJaqMt2400P8kTw9vEPoC0xdxqu0JhxO7pDTmaaIKw==}
engines: {node: '>=14'}
hasBin: true
requiresBuild: true
dependencies:
playwright-core: 1.25.0
dev: true
/postcss-attribute-case-insensitive/5.0.2_postcss@8.4.14:
resolution: {integrity: sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==}
engines: {node: ^12 || ^14 || >=16}
@ -11138,6 +11188,37 @@ packages:
yn: 3.1.1
dev: true
/ts-node/10.9.1_itmtyrrie7wpjnrpwbb5uqyzwa:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
'@types/node': 18.7.8
acorn: 8.7.1
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 4.7.4
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
/ts-node/10.9.1_tdn3ypgnfy6bmey2q4hu5jonwi:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true

View File

@ -1,3 +1,4 @@
packages:
- "apps/*"
- "e2e"
- "packages/*"