2026-05-05

This commit is contained in:
gcch 2026-05-05 09:23:41 +02:00
commit e75258efe0
59 changed files with 40440 additions and 2471 deletions

View file

@ -1,50 +1,40 @@
/** @effect-diagnostics asyncFunction:skip-file */
import type { APIRequestContext, Locator, Page, Response } from "@playwright/test";
import { expect, test } from "@playwright/test";
import { ManagedRuntime } from "effect";
import { APIClient } from "../../web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts";
import type { WCV3Products } from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products";
import type { BackendHeaders } from "./utils.ts";
import { getBackendHeadersFromHtml } from "./utils.ts";
test.describe.configure({ mode: "parallel", timeout: 60_000 });
/** _Runtime_ pour effectuer les appels API. */
const TestRuntime = ManagedRuntime.make(APIClient.Live);
test("is on the first page of the Shop", async ({ page }): Promise<void> => {
const FIRST_PAGE_NUMBER = "1";
await page.goto("https://haikuatelier.gcch.local/shop/");
const productsGrid: Locator = page.locator(".grille-produits");
await expect(productsGrid, "La grille des Produits est visible.").toBeVisible();
expect(await productsGrid.getAttribute("data-page"), "Le numéro de page initial est correct.").toBe(
FIRST_PAGE_NUMBER,
);
});
test("can scroll to the end of the grid", async ({ page }): Promise<void> => {
await scrollToGridsEnd(page);
});
test("can access all Products' pages", async ({ page, request }): Promise<void> => {
await page["goto"]("https://haikuatelier.gcch.local/shop/");
const links = await getAllProductsLinks(page, request);
for (const link of links) {
// Vérifie que le lien de la page retourne OK.
const req = await request.get(link);
await expect(req, "The Product's page is accessible").toBeOK();
}
});
const getAllProductsLinks = async (page: Page, request: APIRequestContext): Promise<Array<string>> => {
const backendHeaders: BackendHeaders = await getBackendHeadersFromHtml(page);
const response = await request.get("/wp-json/wc/v3/products?page=1&per_page=100&status=publish", {
headers: { Authorization: `Basic ${backendHeaders.authString}`, Nonce: backendHeaders.nonce },
});
const json = (await response.json()) as WCV3Products;
return json.map(p => p.permalink);
};
const scrollToGridsEnd = async (page: Page): Promise<void> => {
await page["goto"]("https://haikuatelier.gcch.local/shop/");
await page.goto("https://haikuatelier.gcch.local/shop/");
let hasMoreProducts = true;
let currentPageNumber = "1";
const productsGrid: Locator = page.locator(".grille-produits");
await expect(productsGrid, "The Product's grid is visible").toBeVisible();
expect(await productsGrid.getAttribute("data-page"), "The initial page number attribute is correct").toBe(
currentPageNumber,
);
await expect(productsGrid, "La grille des Produits est visible.").toBeVisible();
const showMoreButton: Locator = page.getByRole("button", { name: "Show more" });
await expect(showMoreButton, "The 'Show more' button is visible").toBeVisible();
await expect(showMoreButton, "Le bouton « Show more » est visible.").toBeVisible();
while (hasMoreProducts) {
const newProductsResponse: Promise<Response> = page.waitForResponse(new RegExp(".*wp-json/wc/v3/products.*"));
@ -57,7 +47,7 @@ const scrollToGridsEnd = async (page: Page): Promise<void> => {
await gridWithNewPageNumber.waitFor();
// Redondance pour expliciter la raison de l'assertion.
expect(await productsGrid.getAttribute("data-page"), "The page number attribute is incremented").toBe(
expect(await productsGrid.getAttribute("data-page"), "Le numéro de page a été incrémenté.").toBe(
newPageNumber,
);
currentPageNumber = newPageNumber;
@ -67,4 +57,44 @@ const scrollToGridsEnd = async (page: Page): Promise<void> => {
hasMoreProducts = false;
}
}
});
test("can access all Products' pages", async ({ page, request }): Promise<void> => {
await page.goto("https://haikuatelier.gcch.local/shop/");
const links = await getAllProductsLinks(page, request);
for (const link of links) {
// Vérifie que le lien de la page retourne OK.
const req = await request.get(link);
await expect(req, "La page du Produit est accessible.").toBeOK();
}
});
test("has no Product with broken images", async ({ page }): Promise<void> => {
await page.goto("https://haikuatelier.gcch.local/shop/");
await loadMoreProducts(page);
const brokenImages = await page.locator("a:has(img[src=''])").all();
const links = await Promise.all(brokenImages.map(locator => locator.getAttribute("href")));
console.info("Liens des Produits avec images cassées :", links);
expect(links.length, "Il n'y pas d'images cassées.").toEqual(0);
});
const getAllProductsLinks = async (page: Page, request: APIRequestContext): Promise<Array<string>> => {
const backendHeaders: BackendHeaders = await getBackendHeadersFromHtml(page);
const response = await request.get("/wp-json/wc/v3/products?page=1&per_page=100&status=publish", {
headers: { Authorization: `Basic ${backendHeaders.authString}`, Nonce: backendHeaders.nonce },
});
const json = (await response.json()) as WCV3Products;
return json.map(p => p.permalink);
};
const loadMoreProducts = async (page: Page): Promise<void> => {
const showMoreButton: Locator = page.getByRole("button", { name: "Show more" });
const newProductsResponse: Promise<Response> = page.waitForResponse(new RegExp(".*wp-json/wc/v3/products.*"));
await showMoreButton.click();
await newProductsResponse;
};