From a85f4db97cf78c22bdc15e2bbc8057fb8f5a2791 Mon Sep 17 00:00:00 2001 From: SnapOtter Date: Tue, 5 May 2026 20:53:02 +0800 Subject: [PATCH] test: add portrait fixture images and extreme-height regression test Add test-portrait-tall.png (200x4000) and test-portrait-extreme.png (100x6000) fixtures. Update crop overflow tests to use fixture files instead of generating images at runtime, and add a second test case for extremely tall images. --- tests/e2e/gui-tools-essential.spec.ts | 40 +++++++++++++++++------ tests/fixtures/test-portrait-extreme.png | Bin 0 -> 15881 bytes tests/fixtures/test-portrait-tall.png | Bin 0 -> 11649 bytes 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 tests/fixtures/test-portrait-extreme.png create mode 100644 tests/fixtures/test-portrait-tall.png diff --git a/tests/e2e/gui-tools-essential.spec.ts b/tests/e2e/gui-tools-essential.spec.ts index c36a3f0e..4f9c3675 100644 --- a/tests/e2e/gui-tools-essential.spec.ts +++ b/tests/e2e/gui-tools-essential.spec.ts @@ -1,4 +1,3 @@ -import { execFileSync } from "node:child_process"; import path from "node:path"; import { expect, test, uploadTestImage, waitForProcessing } from "./helpers"; @@ -198,19 +197,12 @@ test.describe("GUI Essential Tools", () => { await expect(page.getByTestId("crop-download")).toBeVisible({ timeout: 15_000 }); }); - test("tall portrait image fits within viewport without overflow", async ({ + test("tall portrait image (200x4000) fits within viewport without overflow", async ({ loggedInPage: page, }) => { await page.goto("/crop"); - // Create a tall portrait image (200x2000) to trigger overflow - const portraitPath = path.join(process.cwd(), "test-results", "test-portrait-tall.png"); - const script = [ - "const sharp = require('sharp');", - `sharp({create:{width:200,height:2000,channels:4,background:{r:0,g:128,b:255,alpha:1}}}).png().toFile('${portraitPath.replace(/'/g, "\\'")}')`, - ].join(" "); - execFileSync("node", ["-e", script], { cwd: process.cwd(), timeout: 5000 }); - + const portraitPath = path.join(process.cwd(), "tests", "fixtures", "test-portrait-tall.png"); const fileChooserPromise = page.waitForEvent("filechooser"); await page.locator("[class*='border-dashed']").first().click(); const fileChooser = await fileChooserPromise; @@ -224,6 +216,34 @@ test.describe("GUI Essential Tools", () => { const box = await img.boundingBox(); expect(box).not.toBeNull(); expect(box!.y + box!.height).toBeLessThanOrEqual(viewport.height); + expect(box!.y).toBeGreaterThanOrEqual(0); + }); + + test("extremely tall portrait image (100x6000) fits within viewport without overflow", async ({ + loggedInPage: page, + }) => { + await page.goto("/crop"); + + const extremePath = path.join( + process.cwd(), + "tests", + "fixtures", + "test-portrait-extreme.png", + ); + const fileChooserPromise = page.waitForEvent("filechooser"); + await page.locator("[class*='border-dashed']").first().click(); + const fileChooser = await fileChooserPromise; + await fileChooser.setFiles(extremePath); + await page.waitForTimeout(1000); + + const img = page.locator(".ReactCrop img"); + await expect(img).toBeVisible(); + + const viewport = page.viewportSize()!; + const box = await img.boundingBox(); + expect(box).not.toBeNull(); + expect(box!.y + box!.height).toBeLessThanOrEqual(viewport.height); + expect(box!.y).toBeGreaterThanOrEqual(0); }); }); diff --git a/tests/fixtures/test-portrait-extreme.png b/tests/fixtures/test-portrait-extreme.png new file mode 100644 index 0000000000000000000000000000000000000000..f55a7f343719fd834908b5871c670303789d3930 GIT binary patch literal 15881 zcmeAS@N?(olHy`uVBq!ia0vp^DGUta1srTZme-x~nLvuOz$3Dlfr0r22s3W24$5X= zP+;(MaSW-L^X8(V-~j`MBO8*cd>Ey}bbG2UEVx@<_wL;3lNJB?9!L}&=85c9%r;EX zZCi76!d8h*V$Ro+PDG6gjs^(L6NBOKOmY&VIcTU9DV@W!+&eNni}9qO zWm`fhd9-OX+EyIUcJgT1K3WS5Y%MTawvTp@M@I~3FPE!#)S_CZ;;N1st^XJC+B4_XT_)Cc58+wh}p z_|Y~zEf(jD&Z`cYWdNgN@1tYyqdf>(wDw2a@S|<`LD_~MZMToEMjkTllYz}axNILS z+egcGTxo+AZ3#>>N89Z~sog$ImxW^{%Yn@lRIz<{?zZsg8SUi_mE=0yS{F~V`};B( zIv5q&Y?mGWlEA&%VAjFr?;bzn*gr@Y9pV|Lh2wCG#Q|NUPTQ3#WAE}&YR1Mj7$t7M;(kN<_Tu9vR2%0vM8)e>rY>A{^8fFkFOaj{uwqq%ywLG zR^dXLK!!2L7D<*{JWRQ4jb@|5qhT_dAO=frkQtCn$vzN;z=4AUQ5F>#jFx=^lEy~s zn$h}~#0)<$d3Cf19&II#HjzjB2ZOA_8cEHi5mW?^HVQ~=6pW5vjCNpnm_~c7G#;}V zm?C(P)w!dE^Jw8b1jfn-Ca;bb!89&{N9SlpC#VKuV18)VdZUAeG@jEPn1P7VZXfP$ z-~UTuz(oPP>Y%j%gJmLfwDKBkmDj-J+tK2f#>Mf_uC1w4tbfa#&&Mml)}YXqy3DWq zaXFK{Z$rb5&iUJ!AAC<_Ycy>>Fv~IFtipygfe2%cHIgjXc$l(Bg-62#TY`9yFc68v zLSi5iCEtK#g67e@I9d>mmcm1#3L22SO4B0v8~dtu6{X!DlVyQxsu?_8{an^LB{Ts5 D9reC# literal 0 HcmV?d00001