Skip to content

feat(e2e-testing): setup playwright #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
675a851
feat(playwright): init library with some examples
ilyamore88 Feb 9, 2024
eddf10a
feat(playwright): configure web server, adapt example file suite for …
ilyamore88 Feb 13, 2024
08799e5
chore(playwright): remove examples
ilyamore88 Feb 13, 2024
12e8fe3
test(input): add test case for typing
ilyamore88 Feb 13, 2024
007fb76
ci(playwright): add action for running e2e tests
ilyamore88 Mar 10, 2024
7f1ca88
ci(playground): add job for running e2e tests
ilyamore88 Mar 10, 2024
eff384b
fix(e2e-tests): pass artifact report name to the action
ilyamore88 Mar 10, 2024
60c3845
fix(playwright): enable reuseExistingServer
ilyamore88 Mar 10, 2024
976c01c
revert: fix(playwright): enable reuseExistingServer
ilyamore88 Mar 10, 2024
8fbf0bf
fix(page-loading): add waitForLoadState to prevent flaky tests
ilyamore88 Mar 10, 2024
05ac89f
fix(page-testing): wait for domcontentloaded event
ilyamore88 Mar 10, 2024
af49145
ci(playwright): remove workers set up
ilyamore88 Mar 10, 2024
ba41961
fix(page-testing): wait for networkidle event
ilyamore88 Mar 10, 2024
9450e82
refactor(e2e-tests): create separate command for e2e dev server
ilyamore88 Mar 10, 2024
8a67342
feat(e2e-dev-server): add build deps command
ilyamore88 Mar 10, 2024
cf1f54c
ci(e2e-tests): remove build step
ilyamore88 Mar 10, 2024
68a0748
Merge branch 'main' of github.com:editor-js/document-model into featu…
ilyamore88 Aug 27, 2024
3484f36
fix(tests): correct assertion for input element
ilyamore88 Aug 28, 2024
a3e9b12
Merge branch 'main' of github.com:editor-js/document-model into featu…
ilyamore88 Aug 28, 2024
1960837
feat(playwright): create fixture for playground page
ilyamore88 Aug 28, 2024
8834dea
feat(playwright): extend default test function with playground page f…
ilyamore88 Aug 28, 2024
b6772e2
feat(playwright): add basic tests for all input elements
ilyamore88 Aug 28, 2024
d28dac5
feat(playwright): make fields private
ilyamore88 Aug 28, 2024
6c919ab
Merge branch 'main' of github.com:editor-js/document-model into featu…
ilyamore88 Aug 28, 2024
f513bc9
feat(e2e-tests): move caret to the end of input elements
ilyamore88 Aug 28, 2024
c99717f
docs(playwright): add comment to extended test function
ilyamore88 Aug 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/actions/e2e-tests/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: E2E tests
description: This action runs end-to-end tests using Playwright
inputs:
working-directory:
description: 'Path to the ./packages/name_of_your_package_folder'
required: true
artifactory-report-name:
description: 'A full name of the artifact report'
required: true

runs:
using: "composite"
steps:
- uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
- uses: ./.github/actions/setup

- name: Install Playwright Browsers
run: yarn playwright install --with-deps
working-directory: ${{ inputs.working-directory }}
shell: bash

- name: Run Playwright tests
run: yarn playwright test
working-directory: ${{ inputs.working-directory }}
shell: bash

- name: Upload Playwright report to GitHub artifacts
uses: actions/upload-artifact@v3
if: always()
with:
name: ${{ inputs.artifactory-report-name }}
path: ${{ inputs.working-directory }}/playwright-report/
retention-days: 7

10 changes: 10 additions & 0 deletions .github/workflows/playground.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@ jobs:
uses: ./.github/actions/build
with:
package-name: '@editorjs/document-playground'

e2e-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run E2E tests
uses: ./.github/actions/e2e-tests
with:
working-directory: packages/playground
artifactory-report-name: 'document-playground-e2e-report'
1 change: 1 addition & 0 deletions packages/playground/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
project: [
'./tsconfig.json',
'./tsconfig.eslint.json',
'./tsconfig.playwright.json'
],
ecmaVersion: 2022,
extraFileExtensions: [ '.vue' ],
Expand Down
4 changes: 4 additions & 0 deletions packages/playground/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ dist-ssr
*.njsproj
*.sln
*.sw?
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
9 changes: 7 additions & 2 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
"type": "module",
"packageManager": "yarn@4.0.1",
"scripts": {
"dev": "concurrently -n \"TSC Watch\",Vite \"yarn dev:dependencies\" \"vite\"",
"dev": "concurrently -n \"TSC Watch\",Vite \"yarn dev:dependencies\" \"vite --port 3123\"",
"build": "yarn build:dependencies && vue-tsc && vite build",
"preview": "yarn build:dependencies && vite preview",
"build:dependencies": "yarn workspaces foreach -Rpt --from $npm_package_name --exclude $npm_package_name run build",
"dev:dependencies": "yarn workspaces foreach -Rp --from $npm_package_name --exclude $npm_package_name run dev",
"lint": "eslint src --ext .ts,.vue",
"lint:ci": "yarn lint --max-warnings 0",
"lint:fix": "yarn lint --fix"
"lint:fix": "yarn lint --fix",
"test": "playwright test",
"test:ui": "yarn test --ui",
"e2e-dev-server": "yarn build:dependencies && vite --port 3123"
},
"dependencies": {
"@editorjs/core": "workspace:^",
Expand All @@ -20,7 +23,9 @@
"vue": "^3.3.4"
},
"devDependencies": {
"@playwright/test": "^1.41.2",
"@types/eslint": "^8",
"@types/node": "^20.11.17",
"@vitejs/plugin-vue": "^4.2.3",
"concurrently": "^8.2.2",
"eslint": "^8.53.0",
Expand Down
81 changes: 81 additions & 0 deletions packages/playground/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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'],
[process.env.CI ? 'github' : 'line']
],
/* 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:3123',

/* 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: 'yarn e2e-dev-server',
url: 'http://localhost:3123',
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000,
},
});
31 changes: 31 additions & 0 deletions packages/playground/tests/contenteditable.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@playwright/test';
import { test } from './utils/test';

test.describe('Contenteditable field', () => {
test('should be visible', async ({ playgroundPage }) => {
const contenteditable = playgroundPage.contenteditable;

await expect(contenteditable).toBeVisible();
});

test('should be focusable', async ({ playgroundPage }) => {
const contenteditable = playgroundPage.contenteditable;

await contenteditable.click();

await expect(contenteditable).toBeFocused();
});

test('should accept text', async ({ playgroundPage }) => {
const contenteditable = playgroundPage.contenteditable;
const initialText = await contenteditable.textContent();
const inputText = 'Hello, World!';
const expectedText = initialText + inputText;

await contenteditable.click();
await contenteditable.press('Control+ArrowRight');
await contenteditable.pressSequentially(inputText);

await expect(contenteditable).toHaveText(expectedText);
});
});
49 changes: 49 additions & 0 deletions packages/playground/tests/fixtures/PlaygroundPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { Locator, Page } from '@playwright/test';

/**
* Playground page fixture to help access the page elements
*/
export class PlaygroundPage {
readonly #input: Locator;
readonly #textarea: Locator;
readonly #contenteditable: Locator;

/**
* Sets locators for input, textarea and contenteditable elements
*
* @param page - Playwright page object
*/
constructor(public readonly page: Page) {
this.#input = page.locator('input');
this.#textarea = page.locator('textarea');
this.#contenteditable = page.locator('[contenteditable]').first(); // hack to get the first contenteditable element
}

/**
* Navigates to the playground page
*/
public async goto(): Promise<void> {
await this.page.goto('/');
}

/**
* Returns the native input locator
*/
public get input(): Locator {
return this.#input;
}

/**
* Returns the textarea locator
*/
public get textarea(): Locator {
return this.#textarea;
}

/**
* Returns the contenteditable locator
*/
public get contenteditable(): Locator {
return this.#contenteditable;
}
}
31 changes: 31 additions & 0 deletions packages/playground/tests/input.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@playwright/test';
import { test } from './utils/test';

test.describe('Native input element', () => {
test('should be visible', async ({ playgroundPage }) => {
const input = playgroundPage.input;

await expect(input).toBeVisible();
});

test('should be focusable', async ({ playgroundPage }) => {
const input = playgroundPage.input;

await input.click();

await expect(input).toBeFocused();
});

test('should accept text', async ({ playgroundPage }) => {
const input = playgroundPage.input;
const initialText = await input.inputValue();
const inputText = 'Hello, World!';
const expectedText = initialText + inputText;

await input.click();
await input.press('Control+ArrowRight');
await input.pressSequentially(inputText, { delay: 100 });

await expect(input).toHaveValue(expectedText);
});
});
31 changes: 31 additions & 0 deletions packages/playground/tests/textarea.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@playwright/test';
import { test } from './utils/test';

test.describe('Textarea field', () => {
test('should be visible', async ({ playgroundPage }) => {
const textarea = playgroundPage.textarea;

await expect(textarea).toBeVisible();
});

test('should be focusable', async ({ playgroundPage }) => {
const textarea = playgroundPage.textarea;

await textarea.click();

await expect(textarea).toBeFocused();
});

test('should accept text', async ({ playgroundPage }) => {
const textarea = playgroundPage.textarea;
const initialText = await textarea.inputValue();
const inputText = 'Hello, World!';
const expectedText = initialText + inputText;

await textarea.click();
await textarea.press('Control+ArrowRight');
await textarea.pressSequentially(inputText, { delay: 100 });

await expect(textarea).toHaveValue(expectedText);
});
});
15 changes: 15 additions & 0 deletions packages/playground/tests/utils/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { test as base } from '@playwright/test';
import { PlaygroundPage } from '../fixtures/PlaygroundPage';

/**
* Custom test wrapper to extend the base test with the playground page fixture
*/
export const test = base.extend<{ playgroundPage: PlaygroundPage }>({
playgroundPage: async ({ page }, use) => {
const playgroundPage = new PlaygroundPage(page);

await playgroundPage.goto();

await use(playgroundPage);
},
});
3 changes: 2 additions & 1 deletion packages/playground/tsconfig.node.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"allowSyntheticDefaultImports": true
},
"include": [
"vite.config.ts"
"vite.config.ts",
"playwright.config.ts"
]
}
9 changes: 9 additions & 0 deletions packages/playground/tsconfig.playwright.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"strict": true,
},
"include": [
"tests/**/*.ts"
]
}
Loading
Loading