code review test fixups

This commit is contained in:
Mathieu Fenniak 2025-03-30 15:57:29 -06:00 committed by Gusted
parent 7546fb083f
commit 481dcafa52

View file

@ -9,12 +9,12 @@
// routers/web/repo/actions/**
// @watch end
import {expect} from '@playwright/test';
import {expect, type Page, type TestInfo} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
const workflow_trigger_notification_text = 'This workflow has a workflow_dispatch event trigger.';
async function dispatchSuccess(page, testInfo) {
async function dispatchSuccess(page: Page, testInfo: TestInfo) {
test.skip(testInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
@ -81,16 +81,19 @@ test('workflow dispatch box not available for unauthenticated users', async ({pa
await save_visual(page);
});
async function simulatePollingInterval(page) {
async function completeDynamicRefresh(page: Page) {
// Ensure that the reloading indicator isn't active, indicating that dynamic refresh is done.
await expect(page.locator('#reloading-indicator')).not.toHaveClass(/(^|\s)is-loading(\s|$)/);
}
async function simulatePollingInterval(page: Page) {
// In order to simulate the background page sitting around for > 30s, a custom event `simulate-polling-interval` is
// fired into the document to mimic the polling interval expiring -- although this isn't a perfectly great E2E test
// with this kind of mimicry, it's better than having multiple >30s execution-time tests.
// No other way to trigger a client-side event other than using browser-side eval:
// eslint-disable-next-line playwright/no-eval
await page.$eval('html', () => {
await page.evaluate(() => {
document.dispatchEvent(new Event('simulate-polling-interval'));
});
await completeDynamicRefresh(page);
}
test.describe('workflow list dynamic refresh', () => {
@ -102,18 +105,20 @@ test.describe('workflow list dynamic refresh', () => {
// mimic a user returning to the tab on their browser, which should trigger the workflow list to refresh and display
// the newly dispatched workflow from the other page.
const backgroundPage = await (await page.context()).newPage();
const backgroundPage = await page.context().newPage();
await backgroundPage.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
// Mirror the `Workflow Authenticated user2 > dispatch success` test:
await dispatchSuccess(page, testInfo);
const latestDispatchedRun = await page.locator('.run-list>:first-child .flex-item-body>b').textContent();
expect(latestDispatchedRun).toMatch(/^#/); // workflow ID, eg. "#53"
// No other way to trigger a visibilitychange event other than using browser-side eval:
// eslint-disable-next-line playwright/no-eval
await backgroundPage.$eval('html', () => {
// Synthetically trigger a visibilitychange event, as if we were returning to backgroundPage:
await backgroundPage.evaluate(() => {
document.dispatchEvent(new Event('visibilitychange'));
});
await expect(backgroundPage.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible();
await completeDynamicRefresh(page);
await expect(backgroundPage.locator('.run-list>:first-child .flex-item-body>b', {hasText: latestDispatchedRun})).toBeVisible();
await save_visual(backgroundPage);
});
@ -122,14 +127,16 @@ test.describe('workflow list dynamic refresh', () => {
// which triggers a workflow dispatch. After the polling, the page should refresh and show the newly dispatched
// workflow from the other page.
const backgroundPage = await (await page.context()).newPage();
const backgroundPage = await page.context().newPage();
await backgroundPage.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
// Mirror the `Workflow Authenticated user2 > dispatch success` test:
await dispatchSuccess(page, testInfo);
const latestDispatchedRun = await page.locator('.run-list>:first-child .flex-item-body>b').textContent();
expect(latestDispatchedRun).toMatch(/^#/); // workflow ID, eg. "#53"
await simulatePollingInterval(page);
await expect(backgroundPage.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible();
await simulatePollingInterval(backgroundPage);
await expect(backgroundPage.locator('.run-list>:first-child .flex-item-body>b', {hasText: latestDispatchedRun})).toBeVisible();
await save_visual(backgroundPage);
});
@ -137,11 +144,13 @@ test.describe('workflow list dynamic refresh', () => {
// Verify that after the page is dynamically refreshed, the 'Actor', 'Status', and 'Run workflow' dropdowns work
// correctly -- that the htmx morph hasn't messed up any JS event handlers.
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
await simulatePollingInterval(page);
// Mirror the `Workflow Authenticated user2 > dispatch success` test -- this creates data for the 'Actor' dropdown
await dispatchSuccess(page, testInfo);
// Perform a dynamic refresh before checking the functionality of each dropdown.
await simulatePollingInterval(page);
// Workflow run dialog
await expect(page.locator('input[name="inputs[string2]"]')).toBeHidden();
await page.locator('#workflow_dispatch_dropdown>button').click();
@ -161,14 +170,14 @@ test.describe('workflow list dynamic refresh', () => {
await expect(page.getByText('All Actors')).toBeVisible();
});
test('refresh does not break interacting with open drop-downs', async ({page}) => {
test('refresh does not break interacting with open drop-downs', async ({page}, testInfo) => {
// Verify that if the polling refresh occurs while interacting with any multi-step dropdown on the page, the
// multi-step interaction continues to be visible and functional. This is implemented by preventing the refresh,
// but that isn't the subject of the test here -- as long as the dropdown isn't broken by the refresh, that's fine.
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
// Mirror the `Workflow Authenticated user2 > dispatch success` test -- this creates data for the 'Actor' dropdown
// await dispatchSuccess(page, testInfo);
await dispatchSuccess(page, testInfo);
// Workflow run dialog
await expect(page.locator('input[name="inputs[string2]"]')).toBeHidden();