diff --git a/playwright.config.ts b/playwright.config.ts index 194f7f7d36..625dc3bc69 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,4 @@ -import {devices} from '@playwright/test'; +import {devices, type PlaywrightTestConfig} from '@playwright/test'; const BASE_URL = process.env.GITEA_URL?.replace?.(/\/$/g, '') || 'http://localhost:3000'; @@ -8,7 +8,7 @@ const BASE_URL = process.env.GITEA_URL?.replace?.(/\/$/g, '') || 'http://localho */ export default { testDir: './tests/e2e/', - testMatch: /.*\.test\.e2e\.js/, // Match any .test.e2e.js files + testMatch: /.*\.test\.e2e\.ts/, // Match any .test.e2e.js files // you can adjust this value locally to match your machine's power, // or pass `--workers x` to playwright @@ -99,4 +99,4 @@ export default { outputDir: 'tests/e2e/test-artifacts/', /* Folder for test artifacts such as screenshots, videos, traces, etc. */ snapshotDir: 'tests/e2e/test-snapshots/', -}; +} satisfies PlaywrightTestConfig; diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 4f93cfb64a..8fae664564 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -77,7 +77,7 @@ and playwright to perform tests on it. > (e.g. when only creating new content), > or that they restore the initial state for the next browser run. -#### With the playwright UI: +#### With the playwright UI: Playwright ships with an integrated UI mode which allows you to run individual tests and to debug them by seeing detailed traces of what playwright does. @@ -90,7 +90,7 @@ npx playwright test --ui #### Running individual tests ``` -npx playwright test actions.test.e2e.js:9 +npx playwright test actions.test.e2e.ts:9 ``` First, specify the complete test filename, @@ -144,7 +144,7 @@ TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgr ### Running individual tests -Example command to run `example.test.e2e.js` test file: +Example command to run `example.test.e2e.ts` test file: > **Note** > Unlike integration tests, this filtering is at the file level, not function @@ -211,7 +211,7 @@ Feel free to improve the logic used there if you need more advanced functionalit If you can, perform automated accessibility testing using [AxeCore](https://github.com/dequelabs/axe-core-npm/blob/develop/packages/playwright/README.md). -Take a look at `shared/forms.js` and some other places for inspiration. +Take a look at `shared/forms.ts` and some other places for inspiration. ### List related files coverage diff --git a/tests/e2e/actions.test.e2e.js b/tests/e2e/actions.test.e2e.ts similarity index 99% rename from tests/e2e/actions.test.e2e.js rename to tests/e2e/actions.test.e2e.ts index 01ddb7b971..5e3ae7e3ff 100644 --- a/tests/e2e/actions.test.e2e.js +++ b/tests/e2e/actions.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/repo/actions/** // web_src/css/actions.css @@ -12,7 +10,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/changes.go b/tests/e2e/changes.go index d9ea830951..1e5533bc6b 100644 --- a/tests/e2e/changes.go +++ b/tests/e2e/changes.go @@ -29,7 +29,7 @@ func initChangedFiles() { globalPatterns := []string{ // meta and config "Makefile", - "playwright.config.js", + "playwright.config.ts", ".forgejo/workflows/testing.yml", "tests/e2e/*.go", "tests/e2e/shared/*", diff --git a/tests/e2e/dashboard-ci-status.test.e2e.js b/tests/e2e/dashboard-ci-status.test.e2e.ts similarity index 97% rename from tests/e2e/dashboard-ci-status.test.e2e.js rename to tests/e2e/dashboard-ci-status.test.e2e.ts index 289430055c..a5bdc7ade9 100644 --- a/tests/e2e/dashboard-ci-status.test.e2e.js +++ b/tests/e2e/dashboard-ci-status.test.e2e.ts @@ -1,11 +1,9 @@ -// @ts-check - // @watch start // web_src/js/components/DashboardRepoList.vue // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 3e1bcefd66..b8c89625c0 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -79,7 +79,7 @@ func TestMain(m *testing.M) { // TestE2e should be the only test e2e necessary. It will collect all "*.test.e2e.js" files in this directory and build a test for each. func TestE2e(t *testing.T) { // Find the paths of all e2e test files in test directory. - searchGlob := filepath.Join(filepath.Dir(setting.AppPath), "tests", "e2e", "*.test.e2e.js") + searchGlob := filepath.Join(filepath.Dir(setting.AppPath), "tests", "e2e", "*.test.e2e.ts") paths, err := filepath.Glob(searchGlob) if err != nil { t.Fatal(err) diff --git a/tests/e2e/example.test.e2e.js b/tests/e2e/example.test.e2e.ts similarity index 96% rename from tests/e2e/example.test.e2e.js rename to tests/e2e/example.test.e2e.ts index a413a218c6..90fd9169a4 100644 --- a/tests/e2e/example.test.e2e.js +++ b/tests/e2e/example.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/user/auth/** // web_src/js/features/user-** @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, save_visual} from './utils_e2e.js'; +import {test, login_user, save_visual} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/explore.test.e2e.js b/tests/e2e/explore.test.e2e.ts similarity index 96% rename from tests/e2e/explore.test.e2e.js rename to tests/e2e/explore.test.e2e.ts index eb0c723f36..44c9b21f58 100644 --- a/tests/e2e/explore.test.e2e.js +++ b/tests/e2e/explore.test.e2e.ts @@ -1,4 +1,3 @@ -// @ts-check // document is a global in evaluate, so it's safe to ignore here // eslint playwright/no-conditional-in-test: 0 @@ -8,7 +7,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test} from './utils_e2e.js'; +import {test} from './utils_e2e.ts'; test('Explore view taborder', async ({page}) => { await page.goto('/explore/repos'); diff --git a/tests/e2e/issue-comment.test.e2e.js b/tests/e2e/issue-comment.test.e2e.ts similarity index 99% rename from tests/e2e/issue-comment.test.e2e.js rename to tests/e2e/issue-comment.test.e2e.ts index 8a1e48d75f..7b8326b832 100644 --- a/tests/e2e/issue-comment.test.e2e.js +++ b/tests/e2e/issue-comment.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // web_src/js/features/comp/** // web_src/js/features/repo-** @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, login} from './utils_e2e.js'; +import {test, login_user, login} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/issue-sidebar.test.e2e.js b/tests/e2e/issue-sidebar.test.e2e.ts similarity index 99% rename from tests/e2e/issue-sidebar.test.e2e.js rename to tests/e2e/issue-sidebar.test.e2e.ts index 8b5fa59331..31962bf3b4 100644 --- a/tests/e2e/issue-sidebar.test.e2e.js +++ b/tests/e2e/issue-sidebar.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/repo/issue/view_content/** // web_src/css/repo/issue-** @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, login} from './utils_e2e.js'; +import {test, login_user, login} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/markdown-editor.test.e2e.js b/tests/e2e/markdown-editor.test.e2e.ts similarity index 99% rename from tests/e2e/markdown-editor.test.e2e.js rename to tests/e2e/markdown-editor.test.e2e.ts index 36b35d7e8e..5db242bb36 100644 --- a/tests/e2e/markdown-editor.test.e2e.js +++ b/tests/e2e/markdown-editor.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // web_src/js/features/comp/ComboMarkdownEditor.js // web_src/css/editor/combomarkdowneditor.css @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, load_logged_in_context, login_user} from './utils_e2e.js'; +import {test, load_logged_in_context, login_user} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/markup.test.e2e.js b/tests/e2e/markup.test.e2e.ts similarity index 92% rename from tests/e2e/markup.test.e2e.js rename to tests/e2e/markup.test.e2e.ts index f7ec31709d..2cf32669e4 100644 --- a/tests/e2e/markup.test.e2e.js +++ b/tests/e2e/markup.test.e2e.ts @@ -1,11 +1,9 @@ -// @ts-check - // @watch start // web_src/css/markup/** // @watch end import {expect} from '@playwright/test'; -import {test} from './utils_e2e.js'; +import {test} from './utils_e2e.ts'; test('markup with #xyz-mode-only', async ({page}) => { const response = await page.goto('/user2/repo1/issues/1'); diff --git a/tests/e2e/org-settings.test.e2e.js b/tests/e2e/org-settings.test.e2e.ts similarity index 89% rename from tests/e2e/org-settings.test.e2e.js rename to tests/e2e/org-settings.test.e2e.ts index 21f34c123d..b645d94161 100644 --- a/tests/e2e/org-settings.test.e2e.js +++ b/tests/e2e/org-settings.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/org/team/new.tmpl // web_src/css/form.css @@ -7,8 +5,8 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, login} from './utils_e2e.js'; -import {validate_form} from './shared/forms.js'; +import {test, login_user, login} from './utils_e2e.ts'; +import {validate_form} from './shared/forms.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/profile_actions.test.e2e.js b/tests/e2e/profile_actions.test.e2e.ts similarity index 98% rename from tests/e2e/profile_actions.test.e2e.js rename to tests/e2e/profile_actions.test.e2e.ts index d168037041..efb4dd2f49 100644 --- a/tests/e2e/profile_actions.test.e2e.js +++ b/tests/e2e/profile_actions.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // routers/web/user/** // templates/shared/user/** @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test('Follow actions', async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/reaction-selectors.test.e2e.js b/tests/e2e/reaction-selectors.test.e2e.ts similarity index 99% rename from tests/e2e/reaction-selectors.test.e2e.js rename to tests/e2e/reaction-selectors.test.e2e.ts index 184f25fe18..a52b47e036 100644 --- a/tests/e2e/reaction-selectors.test.e2e.js +++ b/tests/e2e/reaction-selectors.test.e2e.ts @@ -1,12 +1,10 @@ -// @ts-check - // @watch start // web_src/js/features/comp/ReactionSelector.js // routers/web/repo/issue.go // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/release.test.e2e.js b/tests/e2e/release.test.e2e.ts similarity index 97% rename from tests/e2e/release.test.e2e.js rename to tests/e2e/release.test.e2e.ts index 76c7ac0212..373f23dfa7 100644 --- a/tests/e2e/release.test.e2e.js +++ b/tests/e2e/release.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // models/repo/attachment.go // modules/structs/attachment.go @@ -11,8 +9,8 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.js'; -import {validate_form} from './shared/forms.js'; +import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts'; +import {validate_form} from './shared/forms.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/repo-code.test.e2e.js b/tests/e2e/repo-code.test.e2e.ts similarity index 99% rename from tests/e2e/repo-code.test.e2e.js rename to tests/e2e/repo-code.test.e2e.ts index fdb92762ff..5207a6389c 100644 --- a/tests/e2e/repo-code.test.e2e.js +++ b/tests/e2e/repo-code.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // web_src/js/features/repo-code.js // web_src/css/repo.css @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/repo-commitgraph.test.e2e.js b/tests/e2e/repo-commitgraph.test.e2e.ts similarity index 98% rename from tests/e2e/repo-commitgraph.test.e2e.js rename to tests/e2e/repo-commitgraph.test.e2e.ts index f06c68a55d..2a6fb1e6d7 100644 --- a/tests/e2e/repo-commitgraph.test.e2e.js +++ b/tests/e2e/repo-commitgraph.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/repo/graph.tmpl // web_src/css/features/gitgraph.css @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/repo-migrate.test.e2e.js b/tests/e2e/repo-migrate.test.e2e.ts similarity index 98% rename from tests/e2e/repo-migrate.test.e2e.js rename to tests/e2e/repo-migrate.test.e2e.ts index 2ad4400340..c4d1604a6f 100644 --- a/tests/e2e/repo-migrate.test.e2e.js +++ b/tests/e2e/repo-migrate.test.e2e.ts @@ -1,11 +1,9 @@ -// @ts-check - // @watch start // web_src/js/features/repo-migrate.js // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(({browser}, workerInfo) => login_user(browser, workerInfo, 'user2')); diff --git a/tests/e2e/repo-settings.test.e2e.js b/tests/e2e/repo-settings.test.e2e.ts similarity index 95% rename from tests/e2e/repo-settings.test.e2e.js rename to tests/e2e/repo-settings.test.e2e.ts index b4fdc1ae6c..8bd7299182 100644 --- a/tests/e2e/repo-settings.test.e2e.js +++ b/tests/e2e/repo-settings.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/webhook/shared-settings.tmpl // templates/repo/settings/** @@ -9,8 +7,8 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, login} from './utils_e2e.js'; -import {validate_form} from './shared/forms.js'; +import {test, login_user, login} from './utils_e2e.ts'; +import {validate_form} from './shared/forms.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/repo-wiki.test.e2e.js b/tests/e2e/repo-wiki.test.e2e.ts similarity index 94% rename from tests/e2e/repo-wiki.test.e2e.js rename to tests/e2e/repo-wiki.test.e2e.ts index eb6c033748..5b681c583c 100644 --- a/tests/e2e/repo-wiki.test.e2e.js +++ b/tests/e2e/repo-wiki.test.e2e.ts @@ -1,12 +1,10 @@ -// @ts-check - // @watch start // templates/repo/wiki/** // web_src/css/repo** // @watch end import {expect} from '@playwright/test'; -import {test} from './utils_e2e.js'; +import {test} from './utils_e2e.ts'; test(`Search for long titles and test for no overflow`, async ({page}, workerInfo) => { test.skip(workerInfo.project.name === 'Mobile Safari', 'Fails as always, see https://codeberg.org/forgejo/forgejo/pulls/5326#issuecomment-2313275'); diff --git a/tests/e2e/right-settings-button.test.e2e.js b/tests/e2e/right-settings-button.test.e2e.ts similarity index 99% rename from tests/e2e/right-settings-button.test.e2e.js rename to tests/e2e/right-settings-button.test.e2e.ts index 87e10c040c..bfb1800a27 100644 --- a/tests/e2e/right-settings-button.test.e2e.js +++ b/tests/e2e/right-settings-button.test.e2e.ts @@ -1,5 +1,3 @@ -// @ts-check - // @watch start // templates/org/** // templates/repo/** @@ -7,7 +5,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.js'; +import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; test.beforeAll(async ({browser}, workerInfo) => { await login_user(browser, workerInfo, 'user2'); diff --git a/tests/e2e/shared/forms.js b/tests/e2e/shared/forms.ts similarity index 92% rename from tests/e2e/shared/forms.js rename to tests/e2e/shared/forms.ts index 5775c40826..52432ccbe8 100644 --- a/tests/e2e/shared/forms.js +++ b/tests/e2e/shared/forms.ts @@ -1,8 +1,7 @@ -import {expect} from '@playwright/test'; +import {expect, type Page} from '@playwright/test'; import {AxeBuilder} from '@axe-core/playwright'; -export async function validate_form({page}, scope) { - scope ??= 'form'; +export async function validate_form({page}: {page: Page}, scope: 'form' | 'fieldset' = 'form') { const accessibilityScanResults = await new AxeBuilder({page}) // disable checking for link style - should be fixed, but not now .disableRules('link-in-text-block') diff --git a/tests/e2e/utils_e2e.js b/tests/e2e/utils_e2e.ts similarity index 80% rename from tests/e2e/utils_e2e.js rename to tests/e2e/utils_e2e.ts index 7cfd7388ca..050847c5ed 100644 --- a/tests/e2e/utils_e2e.js +++ b/tests/e2e/utils_e2e.ts @@ -1,4 +1,4 @@ -import {expect, test as baseTest} from '@playwright/test'; +import {expect, test as baseTest, type Browser, type BrowserContextOptions, type APIRequestContext, type TestInfo, type Page} from '@playwright/test'; export const test = baseTest.extend({ context: async ({browser}, use) => { @@ -6,7 +6,7 @@ export const test = baseTest.extend({ }, }); -async function test_context(browser, options) { +async function test_context(browser: Browser, options?: BrowserContextOptions) { const context = await browser.newContext(options); context.on('page', (page) => { @@ -21,7 +21,7 @@ const LOGIN_PASSWORD = 'password'; // log in user and store session info. This should generally be // run in test.beforeAll(), then the session can be loaded in tests. -export async function login_user(browser, workerInfo, user) { +export async function login_user(browser: Browser, workerInfo: TestInfo, user: string) { test.setTimeout(60000); // Set up a new context const context = await test_context(browser); @@ -47,7 +47,7 @@ export async function login_user(browser, workerInfo, user) { return context; } -export async function load_logged_in_context(browser, workerInfo, user) { +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`}); @@ -59,12 +59,12 @@ export async function load_logged_in_context(browser, workerInfo, user) { return context; } -export async function login({browser}, workerInfo) { +export async function login({browser}: {browser: Browser}, workerInfo: TestInfo) { const context = await load_logged_in_context(browser, workerInfo, 'user2'); - return await context.newPage(); + return await context?.newPage(); } -export async function save_visual(page) { +export async function save_visual(page: Page) { // Optionally include visual testing if (process.env.VISUAL_TEST) { await page.waitForLoadState('networkidle'); @@ -83,7 +83,7 @@ export async function save_visual(page) { // Create a temporary user and login to that user and store session info. // This should ideally run on a per test basis. -export async function create_temp_user(browser, workerInfo, request) { +export async function create_temp_user(browser: Browser, workerInfo: TestInfo, request: APIRequestContext) { const username = globalThis.crypto.randomUUID(); const newUser = await request.post(`/api/v1/admin/users`, { headers: { diff --git a/tests/e2e/webauthn.test.e2e.js b/tests/e2e/webauthn.test.e2e.ts similarity index 94% rename from tests/e2e/webauthn.test.e2e.js rename to tests/e2e/webauthn.test.e2e.ts index 7168de223a..38e6b27821 100644 --- a/tests/e2e/webauthn.test.e2e.js +++ b/tests/e2e/webauthn.test.e2e.ts @@ -1,6 +1,5 @@ // Copyright 2024 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT -// @ts-check // @watch start // templates/user/auth/** @@ -9,7 +8,7 @@ // @watch end import {expect} from '@playwright/test'; -import {test, create_temp_user} from './utils_e2e.js'; +import {test, create_temp_user} from './utils_e2e.ts'; test('WebAuthn register & login flow', async ({browser, request}, workerInfo) => { test.skip(workerInfo.project.name !== 'chromium', 'Uses Chrome protocol'); @@ -31,7 +30,7 @@ test('WebAuthn register & login flow', async ({browser, request}, workerInfo) => transport: 'usb', automaticPresenceSimulation: true, isUserVerified: true, - backupEligibility: true, + backupEligibility: true, // TODO: this doesn't seem to be available?! }, });