Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions tests/image-component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,12 @@ describe("Image SSR rendering", () => {
}),
);
expect(html).toContain('sizes="(max-width: 768px) 100vw, 50vw"');
// With `sizes`, emit a w-descriptor srcSet of allowed widths filtered by the
// minimum vw percentage (Next.js-style), and use the largest candidate as src.
expect(html).toContain(`${optUrlHtml("/img.png", 640)} 640w`);
expect(html).toContain(`${optUrlHtml("/img.png", 750)} 750w`);
expect(html).toContain(`${optUrlHtml("/img.png", 3840)} 3840w`);
expect(html).toContain(`src="${optUrlHtml("/img.png", 3840)}"`);
expect(html).not.toContain(`${optUrlHtml("/img.png", 640)} 1x`);
});

Expand Down Expand Up @@ -366,6 +371,30 @@ describe("Image srcSet generation", () => {
// Fill mode: no srcSet (srcSet is only for local non-fill images with width)
expect(html).not.toContain("srcSet");
});

// Regression for issue #1966 — port of Next.js
// test/unit/next-image-get-img-props.test.ts (width:100, height:200, no sizes).
// A fixed-size image with no `sizes` must emit a 1x/2x x-descriptor srcSet and
// leave `sizes` undefined. A w-descriptor srcSet with no `sizes` defaults to
// sizes=100vw per the HTML spec, which over-fetches a viewport-sized image.
it("emits a 1x/2x x-descriptor srcSet and no sizes for fixed images (#1966)", () => {
const html = ReactDOMServer.renderToString(
React.createElement(Image, {
alt: "fixed",
src: "/fixed.png",
width: 100,
height: 200,
}),
);
// [100, 200] quantized up against allSizes → [128, 256], emitted as 1x / 2x.
expect(html).toContain(
`srcSet="${optUrlHtml("/fixed.png", 128)} 1x, ${optUrlHtml("/fixed.png", 256)} 2x"`,
);
// Fallback src uses the largest candidate (256) — always an allowed width.
expect(html).toContain(`src="${optUrlHtml("/fixed.png", 256)}"`);
// No `sizes` attribute (it must NOT default to 100vw for fixed images).
expect(html).not.toContain("sizes=");
});
});

// ─── getImageProps ──────────────────────────────────────────────────────
Expand Down Expand Up @@ -507,10 +536,26 @@ describe("getImageProps", () => {
height: 600,
});

expect(props.srcSet).toBeDefined();
expect(props.srcSet).toContain("/_next/image");
expect(props.srcSet).toContain("photo.png");
expect(props.srcSet).toContain("w");
// No `sizes` + numeric width → x-descriptor srcSet ([800, 1600] → [828, 1920]).
expect(props.srcSet).toBe(`${optUrl("/photo.png", 828)} 1x, ${optUrl("/photo.png", 1920)} 2x`);
});

it("generates w-descriptor srcSet when sizes is provided", () => {
const { props } = getImageProps({
alt: "sized",
src: "/photo.png",
width: 500,
height: 300,
sizes: "(max-width: 768px) 100vw, 50vw",
});

// With `sizes` → w-descriptor srcSet of allowed widths (minimum vw threshold).
// Fallback `src` is the largest candidate (widths[last]).
expect(props.srcSet).toContain(`${optUrl("/photo.png", 640)} 640w`);
expect(props.srcSet).toContain(`${optUrl("/photo.png", 750)} 750w`);
expect(props.srcSet).toContain(`${optUrl("/photo.png", 3840)} 3840w`);
expect(props.src).toBe(optUrl("/photo.png", 3840));
expect(props.sizes).toBe("(max-width: 768px) 100vw, 50vw");
});

it("handles loading=eager prop", () => {
Expand Down
5 changes: 4 additions & 1 deletion tests/shims.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20054,7 +20054,8 @@ describe("next/image enhancements", () => {
height: 600,
priority: true,
});
// Local images now route through the optimization endpoint
// Local images now route through the optimization endpoint. With no `sizes`,
// the fallback src uses the largest x-descriptor candidate (800*2 → 1920).
expect(result.props.src).toContain("/_next/image");
expect(result.props.src).toContain("url=%2Fphoto.jpg");
expect(result.props.src).toContain("w=1920");
Expand Down Expand Up @@ -20082,6 +20083,8 @@ describe("next/image enhancements", () => {
src: { src: "/imported.jpg", width: 1200, height: 800, blurDataURL: "data:..." },
alt: "Imported",
});
// No `sizes` → fallback src uses the largest x-descriptor candidate.
// [1200, 2400] quantized up → [1200, 3840] (2400 > 2048, so it clamps to 3840).
expect(result.props.src).toContain("/_next/image");
expect(result.props.src).toContain("url=%2Fimported.jpg");
expect(result.props.src).toContain("w=3840");
Expand Down
Loading