From c17b4bdaeb3134ac281e35199929d02a2caf19e7 Mon Sep 17 00:00:00 2001
From: Otto Richter <git@otto.splvs.net>
Date: Mon, 11 Nov 2024 18:44:55 +0100
Subject: [PATCH] tests(e2e): Separate accessibility and form checks

- automatically test for light and dark themes
---
 tests/e2e/shared/accessibility.ts | 35 +++++++++++++++++++++++++++++++
 tests/e2e/shared/forms.ts         | 15 ++++++-------
 2 files changed, 41 insertions(+), 9 deletions(-)
 create mode 100644 tests/e2e/shared/accessibility.ts

diff --git a/tests/e2e/shared/accessibility.ts b/tests/e2e/shared/accessibility.ts
new file mode 100644
index 0000000000..6675e0d9eb
--- /dev/null
+++ b/tests/e2e/shared/accessibility.ts
@@ -0,0 +1,35 @@
+import {expect, type Page} from '@playwright/test';
+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';
+
+  let accessibilityScanner = await 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
+  for (const incl of includes) {
+    // passing the whole array seems to be not supported
+    accessibilityScanner = accessibilityScanner.include(incl);
+  }
+  for (const excl of excludes) {
+    accessibilityScanner = accessibilityScanner.exclude(excl);
+  }
+
+  // scan the page both in dark and light theme
+  let accessibilityScanResults = await accessibilityScanner.analyze();
+  expect(accessibilityScanResults.violations).toEqual([]);
+  await page.emulateMedia({colorScheme: 'dark'});
+  // in https://codeberg.org/forgejo/forgejo/pulls/5899 there have been
+  // some weird failures related to contrast scanning,
+  // reporting for colours that haven't been used and no trace in the
+  // screenshots.
+  // Since this was only happening with some browsers and not always,
+  // my bet is on a transition effect on dark/light mode switch.
+  // Waiting a little seems to work around this.
+  await page.waitForTimeout(100); // eslint-disable-line playwright/no-wait-for-timeout
+  accessibilityScanResults = await accessibilityScanner.analyze();
+  expect(accessibilityScanResults.violations).toEqual([]);
+  await page.emulateMedia({colorScheme: 'light'});
+}
diff --git a/tests/e2e/shared/forms.ts b/tests/e2e/shared/forms.ts
index 52432ccbe8..2728acf5e7 100644
--- a/tests/e2e/shared/forms.ts
+++ b/tests/e2e/shared/forms.ts
@@ -1,17 +1,14 @@
 import {expect, type Page} from '@playwright/test';
-import {AxeBuilder} from '@axe-core/playwright';
+import {accessibilityCheck} from './accessibility.ts';
 
 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')
-    .include(scope)
+  const excludedElements = [
     // exclude automated tooltips from accessibility scan, remove when fixed
-    .exclude('span[data-tooltip-content')
+    'span[data-tooltip-content',
     // exclude weird non-semantic HTML disabled content
-    .exclude('.disabled')
-    .analyze();
-  expect(accessibilityScanResults.violations).toEqual([]);
+    '.disabled',
+  ];
+  await accessibilityCheck({page}, [scope], excludedElements, []);
 
   // assert CSS properties that needed to be overriden for forms (ensure they remain active)
   const boxes = page.getByRole('checkbox').or(page.getByRole('radio'));