Refactor visual tests

We use built in devices for testing instead of our own custom ones.
Split up desktop and mobile visual tests for better separation.
This commit is contained in:
Rūdolfs Ošiņš
2024-01-05 17:45:20 +00:00
parent e194de4218
commit 5684b8ef42
13 changed files with 180 additions and 223 deletions
+3 -3
View File
@@ -46,7 +46,7 @@ jobs:
- name: Install Playwright browsers
if: steps.playwright-dep-cache.outputs.cache-hit != 'true'
run: npx playwright install chromium
run: npx playwright install chromium webkit --with-deps
- name: Install Radicle binaries
run: |
@@ -57,9 +57,9 @@ jobs:
- name: Run Playwright tests
run: |
if [ ${{ github.ref }} = "refs/heads/master" ]; then
npm run test:e2e -- --project visual --update-snapshots || true;
npm run test:e2e -- --project visual-desktop visual-mobile --update-snapshots || true;
else
npm run test:e2e -- --project visual;
npm run test:e2e -- --project visual-desktop visual-mobile;
fi
# We don't care about logs in visual snapshot tests, only the images.
+24 -5
View File
@@ -41,7 +41,7 @@ const config: PlaywrightTestConfig = {
},
},
{
name: "visual",
name: "visual-desktop",
timeout: 60_000,
expect: {
timeout: 30_000,
@@ -51,13 +51,32 @@ const config: PlaywrightTestConfig = {
animations: "disabled",
},
},
testDir: "./tests/visual",
snapshotDir: "./tests/visual/snapshots",
testDir: "./tests/visual/desktop",
snapshotDir: "./tests/visual/snapshots/desktop",
retries: 0,
use: {
...devices["Desktop Chrome"],
...devices["Desktop Chrome HiDPI"],
actionTimeout: 0,
trace: "off",
},
},
{
name: "visual-mobile",
timeout: 60_000,
expect: {
timeout: 30_000,
toHaveScreenshot: {
threshold: 0.01,
scale: "device",
animations: "disabled",
},
},
testDir: "./tests/visual/mobile",
snapshotDir: "./tests/visual/snapshots/mobile",
retries: 0,
use: {
...devices["iPhone 13 Mini"],
actionTimeout: 0,
deviceScaleFactor: 2,
trace: "off",
},
},
+1 -8
View File
@@ -3,7 +3,7 @@ import type * as Stream from "node:stream";
import * as Fs from "node:fs/promises";
import * as Path from "node:path";
import assert from "node:assert";
import { test as base, expect, type ViewportSize } from "@playwright/test";
import { test as base, expect } from "@playwright/test";
import * as Process from "./process.js";
import * as issue from "@tests/support/cobs/issue.js";
@@ -18,13 +18,6 @@ export { expect };
const fixturesDir = Path.resolve(supportDir, "..", "./fixtures");
type ViewportTypes = "iPhoneXR" | "Desktop";
export const viewportSizes: Record<ViewportTypes, ViewportSize> = {
iPhoneXR: { width: 414, height: 896 },
Desktop: { width: 1280, height: 720 },
};
export const test = base.extend<{
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
forAllTests: void;
+148
View File
@@ -0,0 +1,148 @@
import type { Page } from "@playwright/test";
import { test, expect, markdownUrl } from "@tests/support/fixtures.js";
async function goToSection(section: string, page: Page) {
await page.goto(`${markdownUrl}/tree/main/cheatsheet.md`, {
waitUntil: "networkidle",
});
await page.getByText("Collapse").click();
await page.locator(`[href="${section}"]`).click();
}
test.describe("markdown rendering basics", async () => {
test.use({ viewport: { width: 1600, height: 1200 } });
test("table of contents", async ({ page }) => {
await page.goto(
`${markdownUrl}/tree/main/cheatsheet.md#table-of-contents`,
{
waitUntil: "networkidle",
},
);
await page.getByText("Collapse").click();
await expect(page.getByText("Table of Contents")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("headers", async ({ page }) => {
await goToSection("#headers", page);
await expect(page.getByText("###### H6")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("emphasis", async ({ page }) => {
await goToSection("#emphasis", page);
await expect(page.getByText("Emphasis, aka").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("lists", async ({ page }) => {
await goToSection("#lists", page);
await expect(page.getByText("First ordered list").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("links", async ({ page }) => {
await goToSection("#links", page);
await expect(page.getByText("There are two ways")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("images", async ({ page }) => {
await goToSection("#images", page);
await expect(page.getByText("Here's our logo").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("code and syntax highlighting", async ({ page }) => {
await goToSection("#code", page);
await expect(page.getByText("Code blocks are part")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("tables", async ({ page }) => {
await goToSection("#tables", page);
await expect(page.getByText("Tables aren't part of the")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("blockquotes", async ({ page }) => {
await goToSection("#blockquotes", page);
await expect(page.getByText("Blockquotes are").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("inline HTML", async ({ page }) => {
await goToSection("#html", page);
await expect(page.getByText("You can also use raw HTML")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("horizontal rule", async ({ page }) => {
await goToSection("#hr", page);
await expect(page.getByText("Three or more...").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("line breaks", async ({ page }) => {
await goToSection("#lines", page);
await expect(page.getByText("My basic recommendation")).toBeVisible();
await expect(page).toHaveScreenshot();
});
test("videos", async ({ page }) => {
await goToSection("#videos", page);
await expect(page.getByText("They can't be added")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test("footnotes", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/footnotes.md#footnotes`, {
waitUntil: "networkidle",
});
await expect(
page.locator(
"text=This is an example footnote[0]. And some radicle[1] examples.",
),
).toBeVisible();
await page.getByText("Collapse").click();
await expect(page.getByText("0. https://example.com ↩")).toBeVisible();
await expect(page.getByText("1. https://radicle.xyz ↩")).toBeVisible();
await expect(page).toHaveScreenshot({ fullPage: true });
await page.getByText("Plain").click();
await expect(
page.locator(
"text=This is an example footnote[^0]. And some radicle[^1] examples.",
),
).toBeVisible();
await expect(page.getByText("[^0]: https://example.com")).toBeVisible();
await expect(page.getByText("[^1]: https://radicle.xyz")).toBeVisible();
});
test("math", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/math.md`, {
waitUntil: "networkidle",
});
await expect(page.getByText("The Cauchy-Schwarz Inequality")).toBeVisible();
await page.getByText("Collapse").click();
await expect(page).toHaveScreenshot({ fullPage: true });
});
test("relative image not able to being loaded", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/loading-image.md`, {
waitUntil: "networkidle",
});
await page.getByText("Collapse").click();
await expect(page).toHaveScreenshot({ fullPage: true });
});
test("markdown in issues is not overflowing", async ({ page }) => {
await page.goto(`${markdownUrl}/issues`, {
waitUntil: "networkidle",
});
await page.getByText("Collapse").click();
await page.getByRole("link", { name: "This title has markdown" }).click();
await expect(page).toHaveScreenshot({ fullPage: true });
});
-194
View File
@@ -1,194 +0,0 @@
import type { Page } from "@playwright/test";
import {
test,
expect,
markdownUrl,
viewportSizes,
} from "@tests/support/fixtures.js";
async function goToSection(section: string, page: Page) {
await page.goto(`${markdownUrl}/tree/main/cheatsheet.md`, {
waitUntil: "networkidle",
});
await page.locator(`[href="${section}"]`).click();
}
const viewportWidth = viewportSizes["Desktop"].width;
test.describe("markdown rendering", async () => {
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 450 } });
test("table of contents", async ({ page }) => {
await page.goto(
`${markdownUrl}/tree/main/cheatsheet.md#table-of-contents`,
{
waitUntil: "networkidle",
},
);
await expect(page.getByText("Table of Contents")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({
viewport: { width: viewportWidth, height: 1030 },
});
test("headers", async ({ page }) => {
await goToSection("#headers", page);
await expect(page.getByText("###### H6")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 470 } });
test("emphasis", async ({ page }) => {
await goToSection("#emphasis", page);
await expect(page.getByText("Emphasis, aka").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 1100 } });
test("lists", async ({ page }) => {
await goToSection("#lists", page);
await expect(page.getByText("First ordered list").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 1024 } });
test("links", async ({ page }) => {
await goToSection("#links", page);
await expect(page.getByText("There are two ways")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 520 } });
test("images", async ({ page }) => {
await goToSection("#images", page);
await expect(page.getByText("Here's our logo").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 1130 } });
test("code and syntax highlighting", async ({ page }) => {
await goToSection("#code", page);
await expect(page.getByText("Code blocks are part")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test("footnotes", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/footnotes.md#footnotes`, {
waitUntil: "networkidle",
});
await expect(
page.locator(
"text=This is an example footnote[0]. And some radicle[1] examples.",
),
).toBeVisible();
await expect(page.getByText("0. https://example.com ↩")).toBeVisible();
await expect(page.getByText("1. https://radicle.xyz ↩")).toBeVisible();
await expect(page).toHaveScreenshot({ fullPage: true });
await page.getByText("Plain").click();
await expect(
page.locator(
"text=This is an example footnote[^0]. And some radicle[^1] examples.",
),
).toBeVisible();
await expect(page.getByText("[^0]: https://example.com")).toBeVisible();
await expect(page.getByText("[^1]: https://radicle.xyz")).toBeVisible();
});
});
test.describe(async () => {
test("math", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/math.md`, {
waitUntil: "networkidle",
});
await expect(
page.getByText("The Cauchy-Schwarz Inequality"),
).toBeVisible();
await expect(page).toHaveScreenshot({ fullPage: true });
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 1100 } });
test("tables", async ({ page }) => {
await goToSection("#tables", page);
await expect(page.getByText("Tables aren't part of the")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 450 } });
test("blockquotes", async ({ page }) => {
await goToSection("#blockquotes", page);
await expect(page.getByText("Blockquotes are").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 510 } });
test("inline HTML", async ({ page }) => {
await goToSection("#html", page);
await expect(page.getByText("You can also use raw HTML")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 710 } });
test("horizontal rule", async ({ page }) => {
await goToSection("#hr", page);
await expect(page.getByText("Three or more...").first()).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 625 } });
test("line breaks", async ({ page }) => {
await goToSection("#lines", page);
await expect(page.getByText("My basic recommendation")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
test.describe(async () => {
test.use({ viewport: { width: viewportWidth, height: 500 } });
test("videos", async ({ page }) => {
await goToSection("#videos", page);
await expect(page.getByText("They can't be added")).toBeVisible();
await expect(page).toHaveScreenshot();
});
});
});
test("relative image not able to being loaded", async ({ page }) => {
await page.goto(`${markdownUrl}/tree/main/loading-image.md`, {
waitUntil: "networkidle",
});
await expect(page).toHaveScreenshot({ fullPage: true });
});
test("markdown in issues is not overflowing", async ({ page }) => {
await page.goto(`${markdownUrl}/issues`, {
waitUntil: "networkidle",
});
await page.getByRole("link", { name: "This title has markdown" }).click();
await expect(page).toHaveScreenshot({ fullPage: true });
});
+4 -10
View File
@@ -1,11 +1,4 @@
import {
test,
expect,
cobUrl,
viewportSizes,
} from "@tests/support/fixtures.js";
test.use({ viewport: viewportSizes["iPhoneXR"] });
import { test, expect, cobUrl } from "@tests/support/fixtures.js";
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
@@ -68,11 +61,12 @@ test("patch page", async ({ page }) => {
["This patch is going to be archived", "archived"],
["Let's add a README", "merged"],
["Add subtitle to README", "open"],
["Taking another stab at the README", "open"],
];
for (const [name, state] of patches) {
await page.goto(`${cobUrl}/patches?state=${state}`);
await page.goto(`${cobUrl}/patches?state=${state}`, {
waitUntil: "networkidle",
});
await page.getByRole("link", { name }).click();
await page.getByRole("heading", { name }).waitFor();
await expect(page).toHaveScreenshot({ fullPage: true });
-3
View File
@@ -3,11 +3,8 @@ import {
expect,
sourceBrowsingUrl,
test,
viewportSizes,
} from "@tests/support/fixtures.js";
test.use({ viewport: viewportSizes["iPhoneXR"] });
test("source tree page", async ({ page }) => {
await page.goto(sourceBrowsingUrl, { waitUntil: "networkidle" });
await expect(page).toHaveScreenshot();
View File