summaryrefslogtreecommitdiff
path: root/tools/copland/tests
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /tools/copland/tests
downloadrelic-master.tar.gz
initial commitHEADmaster
Diffstat (limited to 'tools/copland/tests')
-rw-r--r--tools/copland/tests/fixtures/org/all.html50
-rw-r--r--tools/copland/tests/fixtures/org/all.org52
-rw-r--r--tools/copland/tests/fixtures/org/all.txt66
-rw-r--r--tools/copland/tests/fixtures/org/security.html9
-rw-r--r--tools/copland/tests/fixtures/org/security.org13
-rwxr-xr-xtools/copland/tests/org-renderer.sh30
-rwxr-xr-xtools/copland/tests/serve-fixture.sh18
-rwxr-xr-xtools/copland/tests/smoke.sh188
-rw-r--r--tools/copland/tests/visual.spec.mjs94
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/home-dark-linux.pngbin0 -> 21720 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/home-light-linux.pngbin0 -> 21117 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/login-dark-linux.pngbin0 -> 33606 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/login-light-linux.pngbin0 -> 32850 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-document-dark-linux.pngbin0 -> 68961 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-document-light-linux.pngbin0 -> 67587 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-document-mobile-linux.pngbin0 -> 53550 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-dark-linux.pngbin0 -> 42595 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-light-linux.pngbin0 -> 41174 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-mobile-linux.pngbin0 -> 31636 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/repository-list-dark-linux.pngbin0 -> 16492 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/repository-list-light-linux.pngbin0 -> 15656 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/timeline-dark-linux.pngbin0 -> 46898 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/timeline-light-linux.pngbin0 -> 45662 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/timeline-mobile-linux.pngbin0 -> 35066 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/tree-dark-linux.pngbin0 -> 50142 bytes
-rw-r--r--tools/copland/tests/visual.spec.mjs-snapshots/tree-light-linux.pngbin0 -> 48683 bytes
26 files changed, 520 insertions, 0 deletions
diff --git a/tools/copland/tests/fixtures/org/all.html b/tools/copland/tests/fixtures/org/all.html
new file mode 100644
index 0000000..33fc537
--- /dev/null
+++ b/tools/copland/tests/fixtures/org/all.html
@@ -0,0 +1,50 @@
+<div class="org-document">
+<h1 class="org-title">Über &amp; &lt;Fossil&gt;</h1>
+<dl class="org-metadata">
+<dt>Author</dt><dd>Ada &lt;admin@example.test&gt;</dd>
+<dt>Date</dt><dd>2026-08-21</dd>
+</dl>
+<nav class="org-toc" aria-label="Table of contents"><h2>Contents</h2>
+<ol>
+<li class="org-toc-level-1"><a href="#intro-safety">Intro &amp; safety</a></li>
+<li class="org-toc-level-2"><a href="#duplicate">Duplicate</a></li>
+<li class="org-toc-level-1"><a href="#duplicate-2">Duplicate</a></li>
+<li class="org-toc-level-1"><a href="#日本語">日本語</a></li>
+</ol>
+</nav>
+<h1 id="intro-safety">Intro &amp; safety</h1>
+<p>A paragraph with <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <del>strike</del>, <code>&lt;code&gt;</code>, and <code>verbatim &amp; text</code>. Words_like_this and paths/like/this stay literal.</p>
+<ul>
+<li>first<ul>
+<li>nested <strong>item</strong></li>
+</ul>
+<ol>
+<li>nested ordered</li>
+</ol>
+</li>
+<li>second</li>
+</ul>
+<ol>
+<li>one</li>
+<li>two</li>
+</ol>
+<table class="org-table">
+<thead>
+<tr><th>Name</th><th>Value</th></tr>
+</thead>
+<tbody>
+<tr><td>α</td><td>&lt;tag&gt;</td></tr>
+<tr><td>two</td><td><strong>bold</strong></td></tr>
+</tbody>
+</table>
+<pre class="org-block org-src has-language"><code class="language-nix">{ pkgs, ... }: &lt;unsafe&gt; &amp; value</code></pre>
+<pre class="org-block org-example"><code>example &lt;script&gt;alert(1)&lt;/script&gt;</code></pre>
+<p><a href="https://example.test/a?x=1&amp;y=2">external</a> <a href="guide.org">relative</a> <a href="#intro-safety">internal</a> unsafe</p>
+<h2 id="duplicate">Duplicate</h2>
+<p>Text.</p>
+<h1 id="duplicate-2">Duplicate</h1>
+<p>More.</p>
+<h1 id="日本語">日本語</h1>
+<p>Unicode heading.</p>
+</div>
+
diff --git a/tools/copland/tests/fixtures/org/all.org b/tools/copland/tests/fixtures/org/all.org
new file mode 100644
index 0000000..f5c644a
--- /dev/null
+++ b/tools/copland/tests/fixtures/org/all.org
@@ -0,0 +1,52 @@
+#+TITLE: Über & <Fossil>
+#+AUTHOR: Ada <admin@example.test>
+#+DATE: 2026-08-21
+#+OPTIONS: toc:2 num:nil
+#+STARTUP: overview
+
+:PROPERTIES:
+:ID: hidden
+:END:
+
+* Intro & safety
+
+A paragraph with *bold*, /italic/, _underline_, +strike+, ~<code>~, and
+=verbatim & text=. Words_like_this and paths/like/this stay literal.
+
+- first
+ - nested *item*
+ 1. nested ordered
+- second
+
+1. one
+2. two
+
+| Name | Value |
+|------+-------|
+| α | <tag> |
+| two | *bold* |
+
+#+begin_src nix
+{ pkgs, ... }: <unsafe> & value
+#+end_src
+
+#+begin_example
+example <script>alert(1)</script>
+#+end_example
+
+[[https://example.test/a?x=1&y=2][external]]
+[[file:guide.org][relative]]
+[[*Intro & safety][internal]]
+[[javascript:alert(1)][unsafe]]
+
+** Duplicate
+
+Text.
+
+* Duplicate
+
+More.
+
+* 日本語
+
+Unicode heading.
diff --git a/tools/copland/tests/fixtures/org/all.txt b/tools/copland/tests/fixtures/org/all.txt
new file mode 100644
index 0000000..266ab90
--- /dev/null
+++ b/tools/copland/tests/fixtures/org/all.txt
@@ -0,0 +1,66 @@
+Über & <Fossil>
+
+
+
+AuthorAda <admin@example.test>
+Date2026-08-21
+
+
+
+Contents
+
+Intro & safety
+Duplicate
+Duplicate
+日本語
+
+
+
+Intro & safety
+
+A paragraph with bold, italic, underline, strike, <code>, and verbatim & text. Words_like_this and paths/like/this stay literal.
+
+first
+nested item
+
+
+nested ordered
+
+
+second
+
+
+one
+two
+
+
+
+
+
+NameValue
+
+
+
+α<tag>
+twobold
+
+
+
+{ pkgs, ... }: <unsafe> & value
+
+example <script>alert(1)</script>
+
+external relative internal unsafe
+
+Duplicate
+
+Text.
+
+Duplicate
+
+More.
+
+日本語
+
+Unicode heading.
+
diff --git a/tools/copland/tests/fixtures/org/security.html b/tools/copland/tests/fixtures/org/security.html
new file mode 100644
index 0000000..38707e0
--- /dev/null
+++ b/tools/copland/tests/fixtures/org/security.html
@@ -0,0 +1,9 @@
+<div class="org-document">
+<h1 class="org-title">&lt;img src=x onerror=alert(1)&gt;</h1>
+<p>Raw &lt;script&gt;alert(1)&lt;/script&gt; and &quot;quotes&quot;.</p>
+<p><a href="https://example.test/&quot; onmouseover=&quot;alert(1)">attribute</a> file scheme confusion</p>
+<pre class="org-block org-unknown-block"><code>&lt;img src=x onerror=alert(1)&gt;</code></pre>
+<pre class="org-block org-src has-language"><code class="language-sh">echo &quot;unterminated and escaped &lt;tag&gt;&quot;
+</code></pre>
+</div>
+
diff --git a/tools/copland/tests/fixtures/org/security.org b/tools/copland/tests/fixtures/org/security.org
new file mode 100644
index 0000000..3e7280a
--- /dev/null
+++ b/tools/copland/tests/fixtures/org/security.org
@@ -0,0 +1,13 @@
+#+TITLE: <img src=x onerror=alert(1)>
+
+Raw <script>alert(1)</script> and "quotes".
+
+[[https://example.test/" onmouseover="alert(1)][attribute]]
+[[file:javascript:alert(1)][file scheme confusion]]
+
+#+begin_export html
+<img src=x onerror=alert(1)>
+#+end_export
+
+#+begin_src sh
+echo "unterminated and escaped <tag>"
diff --git a/tools/copland/tests/org-renderer.sh b/tools/copland/tests/org-renderer.sh
new file mode 100755
index 0000000..1822d52
--- /dev/null
+++ b/tools/copland/tests/org-renderer.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+source "$root_dir/scripts/fossil-env.sh"
+fixture_dir="$root_dir/tests/fixtures/org"
+output_dir=$(mktemp -d -t copland-org-renderer.XXXXXX)
+
+for fixture in all security; do
+ "$FOSSIL" test-org-render "$fixture_dir/$fixture.org" >"$output_dir/$fixture.html"
+ diff -u "$fixture_dir/$fixture.html" "$output_dir/$fixture.html"
+done
+
+"$FOSSIL" test-org-render --text "$fixture_dir/all.org" >"$output_dir/all.txt"
+diff -u "$fixture_dir/all.txt" "$output_dir/all.txt"
+
+sed 's/$/\r/' "$fixture_dir/all.org" >"$output_dir/all-crlf.org"
+"$FOSSIL" test-org-render "$output_dir/all-crlf.org" >"$output_dir/all-crlf.html"
+diff -u "$fixture_dir/all.html" "$output_dir/all-crlf.html"
+
+if rg -n '<script|<img[^>]*onerror|href="javascript:' "$output_dir"/*.html; then
+ printf 'Unsafe active HTML escaped into Org renderer output.\n' >&2
+ exit 1
+fi
+if ! rg -q '&lt;script&gt;|&lt;img' "$output_dir/security.html"; then
+ printf 'Escaped security fixture content is missing.\n' >&2
+ exit 1
+fi
+
+printf 'Org renderer golden and security tests passed.\n'
diff --git a/tools/copland/tests/serve-fixture.sh b/tools/copland/tests/serve-fixture.sh
new file mode 100755
index 0000000..7f2bc8d
--- /dev/null
+++ b/tools/copland/tests/serve-fixture.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+source "$root_dir/scripts/fossil-env.sh"
+fixture_dir=$(mktemp -d -t copland-visual.XXXXXX)
+port=${COPLAND_TEST_PORT:-18082}
+
+require_org_fossil
+"$root_dir/scripts/create-demo.sh" "$fixture_dir"
+verify_org_mime "$fixture_dir/repositories/alpha.fossil"
+
+FOSSIL_REPOLIST_TITLE=Copland exec "$FOSSIL" server \
+ --localhost \
+ --localauth \
+ --port "$port" \
+ --repolist \
+ "$fixture_dir/repositories"
diff --git a/tools/copland/tests/smoke.sh b/tools/copland/tests/smoke.sh
new file mode 100755
index 0000000..bd54bab
--- /dev/null
+++ b/tools/copland/tests/smoke.sh
@@ -0,0 +1,188 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
+source "$root_dir/scripts/fossil-env.sh"
+test_dir=$(mktemp -d -t copland-smoke.XXXXXX)
+port=${COPLAND_TEST_PORT:-18081}
+server_pid=""
+
+finish() {
+ if [[ -n "$server_pid" ]]; then
+ kill "$server_pid" 2>/dev/null || true
+ wait "$server_pid" 2>/dev/null || true
+ fi
+}
+trap finish EXIT INT TERM
+
+require_org_fossil
+"$root_dir/scripts/create-demo.sh" "$test_dir"
+verify_org_mime "$test_dir/repositories/alpha.fossil"
+"$FOSSIL" sql -R "$test_dir/repositories/alpha.fossil" \
+ "REPLACE INTO config(name,value,mtime) VALUES('doc-glob','*.org',unixepoch());"
+"$FOSSIL" fts-config enable document -R "$test_dir/repositories/alpha.fossil" >/dev/null
+"$FOSSIL" fts-config enable wiki -R "$test_dir/repositories/alpha.fossil" >/dev/null
+"$FOSSIL" fts-config index on -R "$test_dir/repositories/alpha.fossil" >/dev/null
+"$FOSSIL" fts-config reindex -R "$test_dir/repositories/alpha.fossil" >/dev/null
+
+FOSSIL_REPOLIST_TITLE=Copland "$FOSSIL" server \
+ --localhost \
+ --localauth \
+ --port "$port" \
+ --repolist \
+ "$test_dir/repositories" >"$test_dir/server.log" 2>&1 &
+server_pid=$!
+
+base_url="http://127.0.0.1:$port"
+for attempt in $(seq 1 50); do
+ if curl --fail --location --silent "$base_url/" >/dev/null; then
+ break
+ fi
+ if [[ "$attempt" -eq 50 ]]; then
+ printf 'Fossil server did not start.\n' >&2
+ sed -n '1,120p' "$test_dir/server.log" >&2
+ exit 1
+ fi
+ sleep 0.1
+done
+
+paths=(
+ "/"
+ "/alpha/home"
+ "/alpha/timeline"
+ "/alpha/tree?ci=tip"
+ "/alpha/dir?ci=tip"
+ "/alpha/brlist"
+ "/alpha/taglist"
+ "/alpha/wiki"
+ "/alpha/wiki?name=Org%20Wiki"
+ "/alpha/wikiedit?name=New%20Org%20Page"
+ "/alpha/whistory?name=Org%20Wiki"
+ "/alpha/reportlist"
+ "/alpha/forum"
+ "/alpha/login"
+ "/alpha/sitemap"
+ "/alpha/doc/tip/docs/org-support.org"
+ "/alpha/file?name=docs/org-support.org&ci=tip"
+ "/alpha/file?name=docs/org-support.org&ci=tip&txt=1"
+ "/alpha/search?s=Native%20Org%20preview&y=d"
+ "/alpha/search?s=deployment%20guide&y=w"
+)
+
+for path in "${paths[@]}"; do
+ body=$(curl --fail --location --silent --show-error "$base_url$path")
+ if [[ "$body" != *"Copland"* ]]; then
+ printf 'Copland marker missing from %s\n' "$path" >&2
+ exit 1
+ fi
+ if [[ "$body" == *"thmainError"* ]]; then
+ printf 'TH1 template error on %s\n' "$path" >&2
+ exit 1
+ fi
+ if [[ "$path" == "/" && ("$body" != *"Alpha"* || "$body" != *"Beta"*) ]]; then
+ printf 'Demo repositories missing from repository list\n' >&2
+ exit 1
+ fi
+ if [[ "$path" == "/alpha/home" ]]; then
+ mainmenu=${body#*'<nav class="container mainmenu"'}
+ mainmenu=${mainmenu%%'</nav>'*}
+ for hidden_route in chat taglist forum reportlist sitemap ticket tkt; do
+ if [[ "$mainmenu" == *"/$hidden_route"* ]]; then
+ printf 'Hidden route /%s is still present in the main menu\n' "$hidden_route" >&2
+ exit 1
+ fi
+ done
+ fi
+ if [[ "$path" == "/alpha/wiki" ]]; then
+ if [[ "$body" != *"Available Wiki Pages"* || "$body" != *"Org Wiki"* ]]; then
+ printf 'Wiki landing page did not list available pages\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/tree?ci=tip" ]]; then
+ if [[ "$body" != *'class="org-document"'* || "$body" != *"A small repository"* ]]; then
+ printf 'README.org was not rendered below the repository tree\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/doc/tip/docs/org-support.org" ]]; then
+ if [[ "$body" != *'<title>Alpha: Native Org preview</title>'*
+ || "$body" != *'class="org-toc"'*
+ || "$body" != *'href="../README.org"'*
+ || "$body" != *'id="overview"'* ]]; then
+ printf 'Native Org /doc rendering is incomplete\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/wiki?name=Org%20Wiki" ]]; then
+ if [[ "$body" != *'<title>Alpha: Org Wiki</title>'*
+ || "$body" != *'class="org-document"'*
+ || "$body" == *'class="org-title"'*
+ || "$body" != *'href="wiki?name=Deployment+Guide"'*
+ || "$body" != *'href="doc/tip/docs/org-support.org"'* ]]; then
+ printf 'Native Org wiki rendering is incomplete\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/wikiedit?name=New%20Org%20Page" ]]; then
+ if [[ "$body" != *'value="text/x-org" selected'* ]]; then
+ printf 'Org is not the default format in the wiki editor\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/file?name=docs/org-support.org&ci=tip" ]]; then
+ if [[ "$body" != *'class="org-document"'* || "$body" != *'>Text</a>'* ]]; then
+ printf 'Native Org /file rendering or Text toggle is missing\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/file?name=docs/org-support.org&ci=tip&txt=1" ]]; then
+ if [[ "$body" == *'class="org-document"'* || "$body" != *'#+title: Native Org preview'* ]]; then
+ printf 'Org /file Text view did not show source\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/search?s=Native%20Org%20preview&y=d" ]]; then
+ if [[ "$body" != *"Native Org preview"* ]]; then
+ printf 'Org document was not found by full-text search\n' >&2
+ exit 1
+ fi
+ fi
+ if [[ "$path" == "/alpha/search?s=deployment%20guide&y=w" ]]; then
+ if [[ "$body" != *"Org Wiki"* ]]; then
+ printf 'Org wiki page was not found by full-text search\n' >&2
+ exit 1
+ fi
+ fi
+ printf 'ok %s\n' "$path"
+done
+
+default_skin_body=$(curl --fail --location --silent --show-error \
+ "$base_url/alpha/home?skin=default")
+if [[ "$default_skin_body" == *'class="site-brand"'* ]]; then
+ printf 'The original Fossil default skin is not selectable\n' >&2
+ exit 1
+fi
+copland_skin_body=$(curl --fail --location --silent --show-error \
+ "$base_url/alpha/home?skin=copland")
+if [[ "$copland_skin_body" != *'class="site-brand"'* ]]; then
+ printf 'The built-in Copland skin is not selectable\n' >&2
+ exit 1
+fi
+
+json_wiki=$(curl --fail --silent --show-error \
+ "$base_url/alpha/json/wiki/get?name=Org%20Wiki&format=html")
+if [[ "$json_wiki" != *'org-document'* || "$json_wiki" != *'contentFormat":"html'* ]]; then
+ printf 'JSON wiki output did not render Org\n' >&2
+ exit 1
+fi
+json_preview=$(curl --fail --silent --show-error \
+ --header 'Content-Type: application/json' \
+ --data '{"payload":{"body":"* JSON preview","mimetype":"text/x-org"}}' \
+ "$base_url/alpha/json/wiki/preview")
+if [[ "$json_preview" != *'org-document'* || "$json_preview" != *'JSON preview'* ]]; then
+ printf 'JSON wiki preview did not render Org\n' >&2
+ exit 1
+fi
+
+printf 'Smoke tests passed. Temporary fixtures: %s\n' "$test_dir"
diff --git a/tools/copland/tests/visual.spec.mjs b/tools/copland/tests/visual.spec.mjs
new file mode 100644
index 0000000..73559e1
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs
@@ -0,0 +1,94 @@
+import AxeBuilder from "@axe-core/playwright";
+import { expect, test } from "@playwright/test";
+
+const pages = [
+ ["repository-list", "/"],
+ ["home", "/alpha/home"],
+ ["timeline", "/alpha/timeline"],
+ ["tree", "/alpha/tree?ci=tip"],
+ ["org-document", "/alpha/doc/tip/docs/org-support.org"],
+ ["org-wiki", "/alpha/wiki?name=Org%20Wiki"],
+ ["login", "/alpha/login"],
+];
+
+for (const colorScheme of ["light", "dark"]) {
+ for (const [name, path] of pages) {
+ test(`${name} is legible in ${colorScheme} mode`, async ({ page }) => {
+ await page.emulateMedia({ colorScheme });
+ await page.goto(path);
+ await expect(page.locator("body")).toContainText("Copland");
+
+ const viewportOverflow = await page.evaluate(
+ () => document.documentElement.scrollWidth > document.documentElement.clientWidth,
+ );
+ expect(viewportOverflow).toBe(false);
+
+ let accessibilityScan = new AxeBuilder({ page })
+ .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"])
+ .disableRules(["html-has-lang"])
+ .exclude(".submenu");
+ if (name === "login") {
+ accessibilityScan = accessibilityScan.exclude("form");
+ }
+ const accessibility = await accessibilityScan.analyze();
+ expect(accessibility.violations).toEqual([]);
+
+ const screenshotMasks = [page.locator(".site-footer span:last-child")];
+ if (name === "login") {
+ screenshotMasks.push(page.locator("form"));
+ }
+ await expect(page).toHaveScreenshot(`${name}-${colorScheme}.png`, {
+ fullPage: true,
+ animations: "disabled",
+ mask: screenshotMasks,
+ maxDiffPixelRatio: 0.001,
+ });
+ });
+ }
+}
+
+test.describe("mobile", () => {
+ test.use({ viewport: { width: 320, height: 720 } });
+
+ test("navigation remains usable", async ({ page }) => {
+ await page.goto("/alpha/timeline");
+ await expect(page.locator(".site-brand")).toHaveText("Copland");
+ await expect(page.locator(".mainmenu")).toBeVisible();
+ const viewportOverflow = await page.evaluate(
+ () => document.documentElement.scrollWidth > document.documentElement.clientWidth,
+ );
+ expect(viewportOverflow).toBe(false);
+ await expect(page).toHaveScreenshot("timeline-mobile.png", {
+ fullPage: true,
+ mask: [page.locator(".site-footer span:last-child")],
+ });
+ });
+
+ test("Org documentation remains readable", async ({ page }) => {
+ await page.goto("/alpha/doc/tip/docs/org-support.org");
+ await expect(page.locator(".org-document")).toBeVisible();
+ await expect(page.locator(".org-toc")).toBeVisible();
+ const viewportOverflow = await page.evaluate(
+ () => document.documentElement.scrollWidth > document.documentElement.clientWidth,
+ );
+ expect(viewportOverflow).toBe(false);
+ await expect(page).toHaveScreenshot("org-document-mobile.png", {
+ fullPage: true,
+ mask: [page.locator(".site-footer span:last-child")],
+ });
+ });
+
+ test("Org wiki remains readable", async ({ page }) => {
+ await page.goto("/alpha/wiki?name=Org%20Wiki");
+ await expect(page.locator(".org-document")).toBeVisible();
+ await expect(page.locator(".org-toc")).toBeVisible();
+ const viewportOverflow = await page.evaluate(
+ () => document.documentElement.scrollWidth > document.documentElement.clientWidth,
+ );
+ expect(viewportOverflow).toBe(false);
+ await expect(page).toHaveScreenshot("org-wiki-mobile.png", {
+ fullPage: true,
+ mask: [page.locator(".site-footer span:last-child")],
+ });
+ });
+});
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/home-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/home-dark-linux.png
new file mode 100644
index 0000000..52f9478
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/home-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/home-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/home-light-linux.png
new file mode 100644
index 0000000..4660bf9
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/home-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/login-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/login-dark-linux.png
new file mode 100644
index 0000000..738588b
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/login-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/login-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/login-light-linux.png
new file mode 100644
index 0000000..03ba2db
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/login-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-document-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-dark-linux.png
new file mode 100644
index 0000000..15d37f9
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-document-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-light-linux.png
new file mode 100644
index 0000000..3c0785f
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-document-mobile-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-mobile-linux.png
new file mode 100644
index 0000000..d1f5cba
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-document-mobile-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-dark-linux.png
new file mode 100644
index 0000000..464197b
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-light-linux.png
new file mode 100644
index 0000000..ff3bdc1
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-mobile-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-mobile-linux.png
new file mode 100644
index 0000000..50381e0
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/org-wiki-mobile-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-dark-linux.png
new file mode 100644
index 0000000..0cf1b4f
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-light-linux.png
new file mode 100644
index 0000000..af49135
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/repository-list-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/timeline-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-dark-linux.png
new file mode 100644
index 0000000..469d7b0
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/timeline-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-light-linux.png
new file mode 100644
index 0000000..e1dbe69
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-light-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/timeline-mobile-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-mobile-linux.png
new file mode 100644
index 0000000..02ed528
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/timeline-mobile-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/tree-dark-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/tree-dark-linux.png
new file mode 100644
index 0000000..164d3eb
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/tree-dark-linux.png
Binary files differ
diff --git a/tools/copland/tests/visual.spec.mjs-snapshots/tree-light-linux.png b/tools/copland/tests/visual.spec.mjs-snapshots/tree-light-linux.png
new file mode 100644
index 0000000..ed51114
--- /dev/null
+++ b/tools/copland/tests/visual.spec.mjs-snapshots/tree-light-linux.png
Binary files differ