[CHORE] Add playwright eslint plugin
- Add https://github.com/playwright-community/eslint-plugin-playwright as a linter for the playwright tests. - `no-networkidle` and `no-conditional-in-test` are disabled as fixing those doesn't seem to really improve testing quality for our use case. - Some non-recommended linters are enabled to ensure consistency (the prefer rules).
This commit is contained in:
parent
d405143919
commit
40baa96fc3
11 changed files with 66 additions and 20 deletions
26
package-lock.json
generated
26
package-lock.json
generated
|
@ -75,6 +75,7 @@
|
|||
"eslint-plugin-jquery": "1.5.1",
|
||||
"eslint-plugin-no-jquery": "2.7.0",
|
||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||
"eslint-plugin-playwright": "1.6.2",
|
||||
"eslint-plugin-regexp": "2.6.0",
|
||||
"eslint-plugin-sonarjs": "0.25.1",
|
||||
"eslint-plugin-unicorn": "52.0.0",
|
||||
|
@ -6331,6 +6332,31 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-playwright": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-1.6.2.tgz",
|
||||
"integrity": "sha512-mraN4Em3b5jLt01q7qWPyLg0Q5v3KAWfJSlEWwldyUXoa7DSPrBR4k6B6LROLqipsG8ndkwWMdjl1Ffdh15tag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"examples"
|
||||
],
|
||||
"dependencies": {
|
||||
"globals": "^13.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40.0",
|
||||
"eslint-plugin-jest": ">=25"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint-plugin-jest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
"eslint-plugin-jquery": "1.5.1",
|
||||
"eslint-plugin-no-jquery": "2.7.0",
|
||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||
"eslint-plugin-playwright": "1.6.2",
|
||||
"eslint-plugin-regexp": "2.6.0",
|
||||
"eslint-plugin-sonarjs": "0.25.1",
|
||||
"eslint-plugin-unicorn": "52.0.0",
|
||||
|
|
23
tests/e2e/.eslintrc.yaml
Normal file
23
tests/e2e/.eslintrc.yaml
Normal file
|
@ -0,0 +1,23 @@
|
|||
plugins:
|
||||
- eslint-plugin-playwright
|
||||
|
||||
extends:
|
||||
- ../../.eslintrc.yaml
|
||||
- plugin:playwright/recommended
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaVersion: latest
|
||||
|
||||
env:
|
||||
browser: true
|
||||
|
||||
rules:
|
||||
playwright/no-conditional-in-test: [0]
|
||||
playwright/no-networkidle: [0]
|
||||
playwright/no-skipped-test: [2, {allowConditional: true}]
|
||||
playwright/prefer-comparison-matcher: [2]
|
||||
playwright/prefer-equality-matcher: [2]
|
||||
playwright/prefer-to-contain: [2]
|
||||
playwright/prefer-to-have-length: [2]
|
||||
playwright/require-to-throw-message: [2]
|
|
@ -8,7 +8,7 @@ test.beforeAll(async ({browser}, workerInfo) => {
|
|||
|
||||
const workflow_trigger_notification_text = 'This workflow has a workflow_dispatch event trigger.';
|
||||
|
||||
test('Test workflow dispatch present', async ({browser}, workerInfo) => {
|
||||
test('workflow dispatch present', async ({browser}, workerInfo) => {
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
/** @type {import('@playwright/test').Page} */
|
||||
const page = await context.newPage();
|
||||
|
@ -26,7 +26,7 @@ test('Test workflow dispatch present', async ({browser}, workerInfo) => {
|
|||
await expect(menu).toBeVisible();
|
||||
});
|
||||
|
||||
test('Test workflow dispatch error: missing inputs', async ({browser}, workerInfo) => {
|
||||
test('workflow dispatch error: missing inputs', async ({browser}, workerInfo) => {
|
||||
test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
|
||||
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
|
@ -38,11 +38,8 @@ test('Test workflow dispatch error: missing inputs', async ({browser}, workerInf
|
|||
|
||||
await page.locator('#workflow_dispatch_dropdown>button').click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Remove the required attribute so we can trigger the error message!
|
||||
await page.evaluate(() => {
|
||||
// eslint-disable-next-line no-undef
|
||||
const elem = document.querySelector('input[name="inputs[string2]"]');
|
||||
elem?.removeAttribute('required');
|
||||
});
|
||||
|
@ -53,7 +50,7 @@ test('Test workflow dispatch error: missing inputs', async ({browser}, workerInf
|
|||
await expect(page.getByText('Require value for input "String w/o. default".')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Test workflow dispatch success', async ({browser}, workerInfo) => {
|
||||
test('workflow dispatch success', async ({browser}, workerInfo) => {
|
||||
test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
|
||||
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
|
@ -64,7 +61,6 @@ test('Test workflow dispatch success', async ({browser}, workerInfo) => {
|
|||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await page.locator('#workflow_dispatch_dropdown>button').click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.type('input[name="inputs[string2]"]', 'abc');
|
||||
await page.locator('#workflow-dispatch-submit').click();
|
||||
|
@ -75,7 +71,7 @@ test('Test workflow dispatch success', async ({browser}, workerInfo) => {
|
|||
await expect(page.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible();
|
||||
});
|
||||
|
||||
test('Test workflow dispatch box not available for unauthenticated users', async ({page}) => {
|
||||
test('workflow dispatch box not available for unauthenticated users', async ({page}) => {
|
||||
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ test('Switch branch', async ({browser}, workerInfo) => {
|
|||
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await expect(page.locator('#loading-indicator')).not.toBeVisible();
|
||||
await expect(page.locator('#loading-indicator')).toBeHidden();
|
||||
await expect(page.locator('#rel-container')).toBeVisible();
|
||||
await expect(page.locator('#rev-container')).toBeVisible();
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ test('Load Homepage', async ({page}) => {
|
|||
await expect(page.locator('.logo')).toHaveAttribute('src', '/assets/img/logo.svg');
|
||||
});
|
||||
|
||||
test('Test Register Form', async ({page}, workerInfo) => {
|
||||
test('Register Form', async ({page}, workerInfo) => {
|
||||
const response = await page.goto('/user/sign_up');
|
||||
await expect(response?.status()).toBe(200); // Status OK
|
||||
await page.type('input[name=user_name]', `e2e-test-${workerInfo.workerIndex}`);
|
||||
|
@ -29,7 +29,7 @@ test('Test Register Form', async ({page}, workerInfo) => {
|
|||
save_visual(page);
|
||||
});
|
||||
|
||||
test('Test Login Form', async ({page}, workerInfo) => {
|
||||
test('Login Form', async ({page}, workerInfo) => {
|
||||
const response = await page.goto('/user/login');
|
||||
await expect(response?.status()).toBe(200); // Status OK
|
||||
|
||||
|
@ -44,7 +44,7 @@ test('Test Login Form', async ({page}, workerInfo) => {
|
|||
save_visual(page);
|
||||
});
|
||||
|
||||
test('Test Logged In User', async ({browser}, workerInfo) => {
|
||||
test('Logged In User', async ({browser}, workerInfo) => {
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
const page = await context.newPage();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @ts-check
|
||||
// document is a global in evaluate, so it's safe to ignore here
|
||||
/* eslint no-undef: 0 */
|
||||
// eslint playwright/no-conditional-in-test: 0
|
||||
import {test, expect} from '@playwright/test';
|
||||
|
||||
test('Explore view taborder', async ({page}) => {
|
||||
|
|
|
@ -67,7 +67,7 @@ test('Issue: Labels', async ({browser}, workerInfo) => {
|
|||
await expect(response?.status()).toBe(200);
|
||||
// preconditions
|
||||
await expect(labelList.filter({hasText: 'label1'})).toBeVisible();
|
||||
await expect(labelList.filter({hasText: 'label2'})).not.toBeVisible();
|
||||
await expect(labelList.filter({hasText: 'label2'})).toBeHidden();
|
||||
// add label2
|
||||
await page.locator('.select-label').click();
|
||||
// label search could be tested this way:
|
||||
|
@ -81,7 +81,7 @@ test('Issue: Labels', async ({browser}, workerInfo) => {
|
|||
await page.locator('.select-label .item').filter({hasText: 'label2'}).click();
|
||||
await page.locator('.select-label').click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(labelList.filter({hasText: 'label2'})).not.toBeVisible();
|
||||
await expect(labelList.filter({hasText: 'label2'})).toBeHidden();
|
||||
await expect(labelList.filter({hasText: 'label1'})).toBeVisible();
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ test.beforeAll(async ({browser}, workerInfo) => {
|
|||
await login_user(browser, workerInfo, 'user2');
|
||||
});
|
||||
|
||||
test('Test markdown indentation', async ({browser}, workerInfo) => {
|
||||
test('markdown indentation', async ({browser}, workerInfo) => {
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
|
||||
const initText = `* first\n* second\n* third\n* last`;
|
||||
|
@ -79,7 +79,7 @@ test('Test markdown indentation', async ({browser}, workerInfo) => {
|
|||
await expect(textarea).toHaveValue(initText);
|
||||
});
|
||||
|
||||
test('Test markdown list continuation', async ({browser}, workerInfo) => {
|
||||
test('markdown list continuation', async ({browser}, workerInfo) => {
|
||||
const context = await load_logged_in_context(browser, workerInfo, 'user2');
|
||||
|
||||
const initText = `* first\n* second\n* third\n* last`;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @ts-check
|
||||
import {test, expect} from '@playwright/test';
|
||||
|
||||
test('Test markup with #xyz-mode-only', async ({page}) => {
|
||||
test('markup with #xyz-mode-only', async ({page}) => {
|
||||
const response = await page.goto('/user2/repo1/issues/1');
|
||||
await expect(response?.status()).toBe(200);
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
@ -9,5 +9,5 @@ test('Test markup with #xyz-mode-only', async ({page}) => {
|
|||
const comment = page.locator('.comment-body>.markup', {hasText: 'test markup light/dark-mode-only'});
|
||||
await expect(comment).toBeVisible();
|
||||
await expect(comment.locator('[src$="#gh-light-mode-only"]')).toBeVisible();
|
||||
await expect(comment.locator('[src$="#gh-dark-mode-only"]')).not.toBeVisible();
|
||||
await expect(comment.locator('[src$="#gh-dark-mode-only"]')).toBeHidden();
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ test('Follow actions', async ({browser}, workerInfo) => {
|
|||
await expect(page.locator('#block-user')).toBeVisible();
|
||||
await page.locator('#block-user .ok').click();
|
||||
await expect(page.locator('.block')).toContainText('Unblock');
|
||||
await expect(page.locator('#block-user')).not.toBeVisible();
|
||||
await expect(page.locator('#block-user')).toBeHidden();
|
||||
|
||||
// Check that following the user yields in a error being shown.
|
||||
await followButton.click();
|
||||
|
|
Loading…
Reference in a new issue