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
276 changes: 234 additions & 42 deletions packages/fiori/cypress/specs/IllustratedMessage.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import IllustratedMessage from "../../src/IllustratedMessage.js";
import Label from "@ui5/webcomponents/dist/Label.js";
import "@ui5/webcomponents-fiori/dist/illustrations/AllIllustrations.js"
import Panel from "@ui5/webcomponents/dist/Panel.js";
import { setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js";

describe("Accessibility", () => {
it("should add aria-hidden and role=presetation to the SVG when decorative is true", () => {
Expand Down Expand Up @@ -156,73 +157,92 @@ describe("IllustratedMessage 'design' property", () => {
});
});

describe("Vertical responsiveness", () => {
it("content with auto design shrinks to fit the parent container", () => {
const expectedMedia = "dialog";

describe("Width-based responsiveness (auto height)", () => {
it("media is base when container width is 100px", () => {
cy.mount(
<div style={{ height: "300px" }}>
<div style={{ width: "100px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should(($contents) => {
const scrollHeight = $contents[0].scrollHeight;
const offsetHeight = $contents[0].offsetHeight;
.should("have.attr", "media", IllustratedMessage.MEDIA.BASE);
});

expect(scrollHeight).to.be.lessThan(300);
expect(scrollHeight).to.equal(offsetHeight);
});
it("media is dot when container width is 200px", () => {
cy.mount(
<div style={{ width: "200px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.prop", "media", expectedMedia);
.should("have.attr", "media", IllustratedMessage.MEDIA.DOT);
});

it("content with auto design expands to fit the parent container", () => {
const expectedMedia = "scene";
it("media is spot when container width is 300px", () => {
cy.mount(
<div style={{ width: "300px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SPOT);
});

it("media is dialog when container width is 500px", () => {
cy.mount(
<div style={{ height: "500px" }}>
<div style={{ width: "500px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should(($contents) => {
const scrollHeight = $contents[0].scrollHeight;
const offsetHeight = $contents[0].offsetHeight;
expect(scrollHeight).to.be.lessThan(500);
expect(scrollHeight).to.equal(offsetHeight);
});

.should("have.attr", "media", IllustratedMessage.MEDIA.DIALOG);
});

it("media is scene when container width is 800px", () => {
cy.mount(
<div style={{ width: "800px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.prop", "media", expectedMedia);
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);
});

it("content with fixed design fits the parent container", () => {
it("media updates from dot to scene when container width expands", () => {
// This test guards against a specific bug: without the `scrollHeight > clientHeight`
// guard in _checkHeightConstraints, _contentHeightForMedia["scene"] gets recorded
// while scene is rendered at full width. When width then shrinks (dot media), the
// container height (auto) shrinks too. On re-expansion, _mediaExceedsContainerHeight("scene")
// compares the stored scene height against the current (small) clientHeight and wrongly
// blocks the upgrade back to scene.
cy.mount(
<div>
<IllustratedMessage design="Dialog" />
<div id="resizable-container" style={{ width: "800px", height: "auto" }}>
<IllustratedMessage />
</div>
);

cy.get("div")
.invoke("css", "height", "250px");
// First render at wide width so _contentHeightForMedia["scene"] gets populated
cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);

// Shrink to dot — clientHeight (auto) now equals the small dot illustration height
cy.get("#resizable-container")
.invoke("css", "width", "200px");

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-root")
.should(($contents) => {
const scrollHeight = $contents[0].scrollHeight;
const offsetHeight = $contents[0].offsetHeight;
expect(scrollHeight).to.be.lessThan(250);
expect(scrollHeight).to.equal(offsetHeight);
});
.should("have.attr", "media", IllustratedMessage.MEDIA.DOT);

// Expand back — must resolve to scene, not stay stuck at dot/dialog
cy.get("#resizable-container")
.invoke("css", "width", "800px");

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);
});

it("shows image with unconstrained height when container has auto height", () => {
Expand All @@ -240,8 +260,88 @@ describe("Vertical responsiveness", () => {
.find(".ui5-illustrated-message-illustration svg")
.should("have.css", "height", "160px");
});
});

describe("Height-based responsiveness (restricted height, wide container)", () => {
after(() => {
// Restore theme so that a switch performed inside this describe does not bleed into
// subsequent specs. Mirrors the pattern in IllustratedMessageV5.cy.tsx.
cy.wrap({ setTheme }).invoke("setTheme", "sap_horizon");
});

it("media is scene when container height is 600px", () => {
cy.mount(
<div style={{ width: "800px", height: "600px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("media shrinks to dialog when container height is 350px", () => {
cy.mount(
<div style={{ width: "800px", height: "350px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.DIALOG);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("media shrinks to spot when container height is 250px", () => {
cy.mount(
<div style={{ width: "800px", height: "250px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SPOT);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("media shrinks to dot when container height is 180px", () => {
cy.mount(
<div style={{ width: "800px", height: "180px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.DOT);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("Illustration visible, when container fit content height", () => {
it("illustration is visible when container height fits content", () => {
cy.mount(
<div style={{ height: "440px" }}>
<IllustratedMessage design="Scene" />
Expand All @@ -257,7 +357,7 @@ describe("Vertical responsiveness", () => {
});
});

it("Illustration visible, when IM slotted and container has fixed height", () => {
it("illustration is visible when IM is slotted and container has fixed height", () => {
cy.mount(
<Panel style={{ height: "19rem" }} noAnimation>
<IllustratedMessage name="AddColumn" />
Expand All @@ -272,6 +372,98 @@ describe("Vertical responsiveness", () => {
expect(scrollHeight).to.not.equal(0);
});
});

it("clears the content-height cache on theme change so media re-evaluates freshly", () => {
cy.mount(
<div style={{ width: "800px", height: "600px" }}>
<IllustratedMessage />
</div>
);

// Baseline: scene fits comfortably in 800×600.
cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);

// Poison the cache with an impossibly large scene content-height. On the next render without a
// cache clear, `_applyMedia` would treat scene as exceeding the container and downgrade.
cy.get("[ui5-illustrated-message]").then(($el) => {
const im = $el[0] as unknown as IllustratedMessage;
im._contentHeightForMedia[IllustratedMessage.MEDIA.SCENE] = 99999;
});

// Fire a theme change. The fix installs an `attachThemeLoaded` listener that clears the
// cache before the framework's themeAware re-render measures against the new theme.
cy.wrap({ setTheme }).invoke("setTheme", "sap_fiori_3");

// If the cache was cleared, the poisoned entry is gone and scene stays selected.
// Without the fix, the stale entry blocks scene and media downgrades to dialog.
cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SCENE);

cy.get("[ui5-illustrated-message]").then(($el) => {
const im = $el[0] as unknown as IllustratedMessage;
// The cache was cleared and then re-populated only if the (fresh) content actually
// overflows the container. In 800×600 nothing overflows, so no scene entry should
// remain from the poisoned value.
expect(im._contentHeightForMedia[IllustratedMessage.MEDIA.SCENE]).to.be.undefined;
});
});
});

describe("Height-based responsiveness (restricted height, dialog-width container)", () => {
it("media is dialog when container height is 500px", () => {
cy.mount(
<div style={{ width: "500px", height: "500px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.DIALOG);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("media shrinks to spot when container height is 250px", () => {
cy.mount(
<div style={{ width: "500px", height: "250px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.SPOT);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});

it("media shrinks to dot when container height is 180px", () => {
cy.mount(
<div style={{ width: "500px", height: "180px" }}>
<IllustratedMessage />
</div>
);

cy.get("[ui5-illustrated-message]")
.should("have.attr", "media", IllustratedMessage.MEDIA.DOT);

cy.get("[ui5-illustrated-message]")
.shadow()
.find(".ui5-illustrated-message-inner")
.should(($el) => {
expect($el[0].scrollHeight).to.be.lte($el[0].offsetHeight + 1);
});
});
});

describe("Dot design resource handling", () => {
Expand Down
Loading
Loading