mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-21 17:34:24 +01:00
Merge pull request 'test: fix e2e tests' (#5968) from viceice/test/e2e-fixes into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5968
This commit is contained in:
commit
01ab0583f5
|
@ -20,7 +20,6 @@ const workflow_trigger_notification_text = 'This workflow has a workflow_dispatc
|
|||
|
||||
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();
|
||||
|
||||
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
|
||||
|
@ -40,7 +39,6 @@ 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');
|
||||
/** @type {import('@playwright/test').Page} */
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
|
||||
|
@ -62,14 +60,13 @@ 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');
|
||||
/** @type {import('@playwright/test').Page} */
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
|
||||
|
||||
await page.locator('#workflow_dispatch_dropdown>button').click();
|
||||
|
||||
await page.type('input[name="inputs[string2]"]', 'abc');
|
||||
await page.fill('input[name="inputs[string2]"]', 'abc');
|
||||
await page.locator('#workflow-dispatch-submit').click();
|
||||
|
||||
await expect(page.getByText('Workflow run was successfully requested.')).toBeVisible();
|
||||
|
|
|
@ -21,10 +21,10 @@ test('Load Homepage', async ({page}) => {
|
|||
test('Register Form', async ({page}, workerInfo) => {
|
||||
const response = await page.goto('/user/sign_up');
|
||||
expect(response?.status()).toBe(200); // Status OK
|
||||
await page.type('input[name=user_name]', `e2e-test-${workerInfo.workerIndex}`);
|
||||
await page.type('input[name=email]', `e2e-test-${workerInfo.workerIndex}@test.com`);
|
||||
await page.type('input[name=password]', 'test123test123');
|
||||
await page.type('input[name=retype]', 'test123test123');
|
||||
await page.fill('input[name=user_name]', `e2e-test-${workerInfo.workerIndex}`);
|
||||
await page.fill('input[name=email]', `e2e-test-${workerInfo.workerIndex}@test.com`);
|
||||
await page.fill('input[name=password]', 'test123test123');
|
||||
await page.fill('input[name=retype]', 'test123test123');
|
||||
await page.click('form button.ui.primary.button:visible');
|
||||
// Make sure we routed to the home page. Else login failed.
|
||||
expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`);
|
||||
|
|
|
@ -4,19 +4,18 @@
|
|||
// web_src/js/features/repo-issue**
|
||||
// @watch end
|
||||
|
||||
import {expect} from '@playwright/test';
|
||||
/* eslint playwright/expect-expect: ["error", { "assertFunctionNames": ["check_wip"] }] */
|
||||
|
||||
import {expect, type Page} from '@playwright/test';
|
||||
import {test, login_user, login} from './utils_e2e.ts';
|
||||
|
||||
test.beforeAll(async ({browser}, workerInfo) => {
|
||||
await login_user(browser, workerInfo, 'user2');
|
||||
});
|
||||
|
||||
/* eslint-disable playwright/expect-expect */
|
||||
// some tests are reported to have no assertions,
|
||||
// which is not correct, because they use the global helper function
|
||||
test.describe('Pull: Toggle WIP', () => {
|
||||
const prTitle = 'pull5';
|
||||
async function toggle_wip_to({page}, should) {
|
||||
async function toggle_wip_to({page}, should: boolean) {
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
if (should) {
|
||||
await page.getByText('Still in progress?').click();
|
||||
|
@ -25,7 +24,7 @@ test.describe('Pull: Toggle WIP', () => {
|
|||
}
|
||||
}
|
||||
|
||||
async function check_wip({page}, is) {
|
||||
async function check_wip({page}, is: boolean) {
|
||||
const elemTitle = 'h1';
|
||||
const stateLabel = '.issue-state-label';
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
|
@ -96,12 +95,11 @@ test.describe('Pull: Toggle WIP', () => {
|
|||
await expect(page.locator('h1')).toContainText(maxLenStr);
|
||||
});
|
||||
});
|
||||
/* eslint-enable playwright/expect-expect */
|
||||
|
||||
test('Issue: Labels', async ({browser}, workerInfo) => {
|
||||
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
|
||||
|
||||
async function submitLabels({page}) {
|
||||
async function submitLabels({page}: {page: Page}) {
|
||||
const submitted = page.waitForResponse('/user2/repo1/issues/labels');
|
||||
await page.locator('textarea').first().click(); // close via unrelated element
|
||||
await submitted;
|
||||
|
@ -199,7 +197,7 @@ test('New Issue: Assignees', async ({browser}, workerInfo) => {
|
|||
|
||||
// Assign other user (with searchbox)
|
||||
await page.locator('.select-assignees.dropdown').click();
|
||||
await page.type('.select-assignees .menu .search input', 'user4');
|
||||
await page.fill('.select-assignees .menu .search input', 'user4');
|
||||
await expect(page.locator('.select-assignees .menu .item').filter({hasText: 'user2'})).toBeHidden();
|
||||
await expect(page.locator('.select-assignees .menu .item').filter({hasText: 'user4'})).toBeVisible();
|
||||
await page.locator('.select-assignees .menu .item').filter({hasText: 'user4'}).click();
|
||||
|
|
|
@ -29,7 +29,7 @@ test('markdown indentation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Indent, then unindent first line
|
||||
await textarea.focus();
|
||||
await textarea.evaluate((it) => it.setSelectionRange(0, 0));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(0, 0));
|
||||
await indent.click();
|
||||
await expect(textarea).toHaveValue(`${tab}* first\n* second\n* third\n* last`);
|
||||
await unindent.click();
|
||||
|
@ -45,7 +45,7 @@ test('markdown indentation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Subsequently, select a chunk of 2nd and 3rd line and indent both, preserving the cursor position in relation to text
|
||||
await textarea.focus();
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('hird')));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('hird')));
|
||||
await indent.click();
|
||||
const lines23 = `* first\n${tab}${tab}* second\n${tab}* third\n* last`;
|
||||
await expect(textarea).toHaveValue(lines23);
|
||||
|
@ -60,7 +60,7 @@ test('markdown indentation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Indent and unindent with cursor at the end of the line
|
||||
await textarea.focus();
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('cond')));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('cond')));
|
||||
await textarea.press('End');
|
||||
await indent.click();
|
||||
await expect(textarea).toHaveValue(`* first\n${tab}* second\n* third\n* last`);
|
||||
|
@ -69,7 +69,7 @@ test('markdown indentation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Check that Tab does work after input
|
||||
await textarea.focus();
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Shift+Enter'); // Avoid triggering the prefix continuation feature
|
||||
await textarea.pressSequentially('* least');
|
||||
await indent.click();
|
||||
|
@ -78,7 +78,7 @@ test('markdown indentation', async ({browser}, workerInfo) => {
|
|||
// Check that partial indents are cleared
|
||||
await textarea.focus();
|
||||
await textarea.fill(initText);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.indexOf('* second'), it.value.indexOf('* second')));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('* second'), it.value.indexOf('* second')));
|
||||
await textarea.pressSequentially(' ');
|
||||
await unindent.click();
|
||||
await expect(textarea).toHaveValue(initText);
|
||||
|
@ -99,7 +99,7 @@ test('markdown list continuation', async ({browser}, workerInfo) => {
|
|||
await textarea.fill(initText);
|
||||
|
||||
// Test continuation of '* ' prefix
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('cond')));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('cond')));
|
||||
await textarea.press('End');
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('middle');
|
||||
|
@ -112,7 +112,7 @@ test('markdown list continuation', async ({browser}, workerInfo) => {
|
|||
await expect(textarea).toHaveValue(`* first\n* second\n${tab}* middle\n${tab}* muddle\n* third\n* last`);
|
||||
|
||||
// Test breaking in the middle of a line
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.lastIndexOf('ddle'), it.value.lastIndexOf('ddle')));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.lastIndexOf('ddle'), it.value.lastIndexOf('ddle')));
|
||||
await textarea.pressSequentially('tate');
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('me');
|
||||
|
@ -120,7 +120,7 @@ test('markdown list continuation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Test not triggering when Shift held
|
||||
await textarea.fill(initText);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Shift+Enter');
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('...but not least');
|
||||
|
@ -128,28 +128,28 @@ test('markdown list continuation', async ({browser}, workerInfo) => {
|
|||
|
||||
// Test continuation of ordered list
|
||||
await textarea.fill(`1. one\n2. two`);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('three');
|
||||
await expect(textarea).toHaveValue(`1. one\n2. two\n3. three`);
|
||||
|
||||
// Test continuation of alternative ordered list syntax
|
||||
await textarea.fill(`1) one\n2) two`);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('three');
|
||||
await expect(textarea).toHaveValue(`1) one\n2) two\n3) three`);
|
||||
|
||||
// Test continuation of blockquote
|
||||
await textarea.fill(`> knowledge is power`);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('france is bacon');
|
||||
await expect(textarea).toHaveValue(`> knowledge is power\n> france is bacon`);
|
||||
|
||||
// Test continuation of checklists
|
||||
await textarea.fill(`- [ ] have a problem\n- [x] create a solution`);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('write a test');
|
||||
await expect(textarea).toHaveValue(`- [ ] have a problem\n- [x] create a solution\n- [ ] write a test`);
|
||||
|
@ -174,7 +174,7 @@ test('markdown list continuation', async ({browser}, workerInfo) => {
|
|||
];
|
||||
for (const prefix of prefixes) {
|
||||
await textarea.fill(`${prefix}one`);
|
||||
await textarea.evaluate((it) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
|
||||
await textarea.press('Enter');
|
||||
await textarea.pressSequentially('two');
|
||||
await expect(textarea).toHaveValue(`${prefix}one\n${prefix}two`);
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
// routers/web/repo/issue.go
|
||||
// @watch end
|
||||
|
||||
import {expect} from '@playwright/test';
|
||||
import {expect, type Locator} from '@playwright/test';
|
||||
import {test, login_user, load_logged_in_context} from './utils_e2e.ts';
|
||||
|
||||
test.beforeAll(async ({browser}, workerInfo) => {
|
||||
await login_user(browser, workerInfo, 'user2');
|
||||
});
|
||||
|
||||
const assertReactionCounts = (comment, counts) =>
|
||||
const assertReactionCounts = (comment: Locator, counts: unknown) =>
|
||||
expect(async () => {
|
||||
await expect(comment.locator('.reactions')).toBeVisible();
|
||||
|
||||
|
@ -29,7 +29,7 @@ const assertReactionCounts = (comment, counts) =>
|
|||
return expect(reactions).toStrictEqual(counts);
|
||||
}).toPass();
|
||||
|
||||
async function toggleReaction(menu, reaction) {
|
||||
async function toggleReaction(menu: Locator, reaction: string) {
|
||||
await menu.evaluateAll((menus) => menus[0].focus());
|
||||
await menu.locator('.add-reaction').click();
|
||||
await menu.locator(`[role=menuitem][data-reaction-content="${reaction}"]`).click();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// services/gitdiff/**
|
||||
// @watch end
|
||||
|
||||
import {expect} from '@playwright/test';
|
||||
import {expect, type Page} from '@playwright/test';
|
||||
import {test, login_user, login} from './utils_e2e.ts';
|
||||
import {accessibilityCheck} from './shared/accessibility.ts';
|
||||
|
||||
|
@ -12,7 +12,7 @@ test.beforeAll(async ({browser}, workerInfo) => {
|
|||
await login_user(browser, workerInfo, 'user2');
|
||||
});
|
||||
|
||||
async function assertSelectedLines(page, nums) {
|
||||
async function assertSelectedLines(page: Page, nums: string[]) {
|
||||
const pageAssertions = async () => {
|
||||
expect(
|
||||
await Promise.all((await page.locator('tr.active [data-line-number]').all()).map((line) => line.getAttribute('data-line-number'))),
|
||||
|
|
|
@ -3,9 +3,9 @@ import {AxeBuilder} from '@axe-core/playwright';
|
|||
|
||||
export async function accessibilityCheck({page}: {page: Page}, includes: string[], excludes: string[], disabledRules: string[]) {
|
||||
// contrast of inline links is still a global issue in Forgejo
|
||||
disabledRules += 'link-in-text-block';
|
||||
disabledRules.push('link-in-text-block');
|
||||
|
||||
let accessibilityScanner = await new AxeBuilder({page})
|
||||
let accessibilityScanner = new AxeBuilder({page})
|
||||
.disableRules(disabledRules);
|
||||
// passing the whole array seems to be not supported,
|
||||
// iterating has the nice side-effectof skipping this if the array is empty
|
||||
|
|
|
@ -33,8 +33,8 @@ export async function login_user(browser: Browser, workerInfo: TestInfo, user: s
|
|||
expect(response?.status()).toBe(200); // Status OK
|
||||
|
||||
// Fill out form
|
||||
await page.type('input[name=user_name]', user);
|
||||
await page.type('input[name=password]', LOGIN_PASSWORD);
|
||||
await page.fill('input[name=user_name]', user);
|
||||
await page.fill('input[name=password]', LOGIN_PASSWORD);
|
||||
await page.click('form button.ui.primary.button:visible');
|
||||
|
||||
await page.waitForLoadState();
|
||||
|
@ -48,15 +48,13 @@ export async function login_user(browser: Browser, workerInfo: TestInfo, user: s
|
|||
}
|
||||
|
||||
export async function load_logged_in_context(browser: Browser, workerInfo: TestInfo, user: string) {
|
||||
let context;
|
||||
try {
|
||||
context = await test_context(browser, {storageState: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`});
|
||||
return await test_context(browser, {storageState: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`});
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
throw new Error(`Could not find state for '${user}'. Did you call login_user(browser, workerInfo, '${user}') in test.beforeAll()?`);
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export async function login({browser}: {browser: Browser}, workerInfo: TestInfo) {
|
||||
|
|
|
@ -30,7 +30,6 @@ test('WebAuthn register & login flow', async ({browser, request}, workerInfo) =>
|
|||
transport: 'usb',
|
||||
automaticPresenceSimulation: true,
|
||||
isUserVerified: true,
|
||||
backupEligibility: true, // TODO: this doesn't seem to be available?!
|
||||
},
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue