Add persistent gallery zoom and proportional card layout
All checks were successful
Deploy Sokko G / deploy (push) Successful in 18s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 18s
This commit is contained in:
parent
386212041f
commit
273bc5d528
11 changed files with 158 additions and 19 deletions
|
|
@ -1,4 +1,4 @@
|
|||
// Rôle : couvre les mutations persistantes des liens, compteurs et checklists.
|
||||
// Rôle : couvre les parcours persistants des liens, compteurs, checklists et galeries d'images.
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
|
|
@ -151,7 +151,20 @@ test("images open a gallery and navigate the current collection without looping"
|
|||
await tool.getByRole("button", { name: "Galerie", exact: true }).click();
|
||||
const dialog = page.getByRole("dialog", { name: "Galerie d'images", exact: true });
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(dialog.locator(".image-viewer-gallery-item")).toHaveCount(3);
|
||||
const thumbnails = dialog.locator(".image-viewer-gallery-item");
|
||||
const gallery = dialog.locator(".image-viewer-gallery");
|
||||
await expect(thumbnails).toHaveCount(3);
|
||||
const initialThumbnailWidth = (await thumbnails.first().boundingBox()).width;
|
||||
await dialog.getByRole("button", { name: "Agrandir les aperçus", exact: true }).click();
|
||||
await expect.poll(async () => (await thumbnails.first().boundingBox()).width).toBeCloseTo(initialThumbnailWidth + 40, 0);
|
||||
expect(await page.evaluate(() => globalThis.localStorage.getItem("sokkog:image-gallery-thumbnail-width"))).toBe("300");
|
||||
expect(await gallery.evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
|
||||
await dialog.getByRole("button", { name: "Fermer", exact: true }).click();
|
||||
await page.reload();
|
||||
await tool.getByRole("button", { name: "Galerie", exact: true }).click();
|
||||
await expect.poll(async () => (await thumbnails.first().boundingBox()).width).toBeCloseTo(300, 0);
|
||||
await dialog.getByRole("button", { name: "Réduire les aperçus", exact: true }).click();
|
||||
await expect.poll(async () => (await thumbnails.first().boundingBox()).width).toBeCloseTo(260, 0);
|
||||
await dialog.getByRole("button", { name: "Afficher en grand : Second", exact: true }).click();
|
||||
await expect(page.locator(".image-viewer-title")).toHaveText("Second");
|
||||
await expect(page.locator(".image-viewer-position")).toHaveText("2 / 3");
|
||||
|
|
@ -175,6 +188,11 @@ test("images open a gallery and navigate the current collection without looping"
|
|||
expect(galleryBox.y).toBeGreaterThanOrEqual(0);
|
||||
expect(galleryBox.x + galleryBox.width).toBeLessThanOrEqual(390);
|
||||
expect(galleryBox.y + galleryBox.height).toBeLessThanOrEqual(844);
|
||||
const zoomIn = dialog.getByRole("button", { name: "Agrandir les aperçus", exact: true });
|
||||
for (let step = 0; step < 4; step += 1) await zoomIn.click();
|
||||
await expect(zoomIn).toBeDisabled();
|
||||
expect(await page.evaluate(() => globalThis.localStorage.getItem("sokkog:image-gallery-thumbnail-width"))).toBe("420");
|
||||
expect(await gallery.evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
|
||||
await dialog.getByRole("button", { name: "Fermer", exact: true }).click();
|
||||
|
||||
await tool.locator(".image-preview").nth(2).click();
|
||||
|
|
@ -182,3 +200,48 @@ test("images open a gallery and navigate the current collection without looping"
|
|||
await expect(page.getByRole("button", { name: "Image suivante", exact: true })).toBeDisabled();
|
||||
await page.getByRole("button", { name: "Fermer", exact: true }).click();
|
||||
});
|
||||
|
||||
test("image gallery keeps proportional cards and compact centered rows at maximum zoom", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1550, height: 900 });
|
||||
const makeImage = (index) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="640" height="360"><rect width="640" height="360" fill="hsl(${index * 45} 70% 45%)"/></svg>`)}`;
|
||||
const tool = await setup(page, "images", {
|
||||
images: Array.from({ length: 7 }, (_, index) => ({ id: `image-${index}`, label: `Image ${index + 1}`, dataUrl: makeImage(index) }))
|
||||
});
|
||||
await page.evaluate(() => globalThis.localStorage.setItem("sokkog:image-gallery-thumbnail-width", "420"));
|
||||
await tool.getByRole("button", { name: "Galerie", exact: true }).click();
|
||||
|
||||
const dialog = page.getByRole("dialog", { name: "Galerie d'images", exact: true });
|
||||
const gallery = dialog.locator(".image-viewer-gallery");
|
||||
const cards = gallery.locator(".image-viewer-gallery-item");
|
||||
await expect(cards).toHaveCount(7);
|
||||
await expect.poll(() => cards.first().locator("img").evaluate((image) => image.naturalWidth)).toBe(640);
|
||||
const boxes = await cards.evaluateAll((elements) => elements.map((element) => {
|
||||
const box = element.getBoundingClientRect();
|
||||
return { x: box.x, y: box.y, width: box.width, height: box.height };
|
||||
}));
|
||||
expect(boxes[0].width / boxes[0].height).toBeCloseTo(4 / 3, 2);
|
||||
expect(boxes.slice(0, 3).every((box) => Math.abs(box.y - boxes[0].y) < 1)).toBe(true);
|
||||
expect(boxes.slice(3, 6).every((box) => Math.abs(box.y - boxes[3].y) < 1)).toBe(true);
|
||||
expect(boxes[3].y).toBeGreaterThan(boxes[0].y + boxes[0].height);
|
||||
expect(boxes[6].y).toBeGreaterThan(boxes[3].y + boxes[3].height);
|
||||
|
||||
const gap = boxes[1].x - boxes[0].x - boxes[0].width;
|
||||
const galleryBox = await gallery.boundingBox();
|
||||
expect(gap).toBeGreaterThanOrEqual(10);
|
||||
expect(gap).toBeLessThanOrEqual(14);
|
||||
expect(boxes[0].x - galleryBox.x).toBeGreaterThan(gap * 2);
|
||||
expect(galleryBox.x + galleryBox.width - boxes[2].x - boxes[2].width).toBeGreaterThan(gap * 2);
|
||||
expect(boxes[6].x + boxes[6].width / 2).toBeCloseTo(galleryBox.x + galleryBox.width / 2, 0);
|
||||
|
||||
const firstCard = cards.first();
|
||||
const frameBox = await firstCard.locator(".image-viewer-gallery-frame").boundingBox();
|
||||
const imageBox = await firstCard.locator("img").boundingBox();
|
||||
const captionBox = await firstCard.locator(".image-viewer-gallery-caption").boundingBox();
|
||||
expect(imageBox.x).toBeGreaterThanOrEqual(frameBox.x);
|
||||
expect(imageBox.y).toBeGreaterThanOrEqual(frameBox.y);
|
||||
expect(imageBox.x + imageBox.width).toBeLessThanOrEqual(frameBox.x + frameBox.width);
|
||||
expect(imageBox.y + imageBox.height).toBeLessThanOrEqual(frameBox.y + frameBox.height);
|
||||
expect(captionBox.y + captionBox.height).toBeLessThanOrEqual(boxes[0].y + boxes[0].height);
|
||||
expect(await gallery.evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
|
||||
expect(await gallery.evaluate((element) => element.scrollHeight > element.clientHeight)).toBe(true);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue