@orangesk/orange-design-system 3.9.0 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/AnchorNavigation/style.css +1 -1
- package/build/components/AnchorNavigation/style.css.map +1 -1
- package/build/components/Carousel/style.css +1 -1
- package/build/components/Carousel/style.css.map +1 -1
- package/build/components/Megamenu/style.css +1 -1
- package/build/components/Megamenu/style.css.map +1 -1
- package/build/components/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/components/types/index.d.ts +6 -2
- package/build/lib/components.css +1 -1
- package/build/lib/components.css.map +1 -1
- package/build/lib/megamenu.css +1 -1
- package/build/lib/megamenu.css.map +1 -1
- package/build/lib/scripts.js +1 -1
- package/build/lib/scripts.js.map +1 -1
- package/build/lib/style.css +1 -1
- package/build/lib/style.css.map +1 -1
- package/build/megamenu-sprite-dark.svg +1 -0
- package/build/megamenu-sprite-light.svg +1 -0
- package/package.json +19 -20
- package/src/assets/megamenu/input-search.svg +1 -0
- package/src/assets/megamenu/input-valid.svg +1 -0
- package/src/assets/megamenu/logo-line.svg +5 -0
- package/src/assets/megamenu/megamenu-logo.svg +61 -0
- package/src/assets/megamenu/store-apple--white.svg +5 -0
- package/src/assets/megamenu/store-apple.svg +4 -0
- package/src/assets/megamenu/store-huawei--white.svg +5 -0
- package/src/assets/megamenu/store-huawei.svg +4 -0
- package/src/assets/megamenu/store-play--white.svg +7 -0
- package/src/assets/megamenu/store-play.svg +7 -0
- package/src/components/AnchorNavigation/styles/mixins.scss +7 -9
- package/src/components/BlockAction/CloneElementWithClassName.tsx +10 -7
- package/src/components/BlockAction/tests/CloneElementWithClassName.unit.test.jsx +28 -1
- package/src/components/Carousel/Carousel.static.ts +49 -0
- package/src/components/Carousel/Carousel.tsx +35 -12
- package/src/components/Carousel/constants.ts +2 -0
- package/src/components/Carousel/styles/mixins.scss +61 -0
- package/src/components/Carousel/styles/style.scss +7 -0
- package/src/components/Forms/TextInput/styles/mixins.scss +4 -2
- package/src/components/Megamenu/Logo.tsx +7 -7
- package/src/components/Megamenu/LogoJeTu.tsx +6 -58
- package/src/components/Megamenu/MegaMenuIcon.tsx +20 -11
- package/src/components/Megamenu/Megamenu.tsx +58 -48
- package/src/components/Megamenu/MegamenuBlog.tsx +14 -2
- package/src/components/Megamenu/MegamenuSearchContent.tsx +13 -0
- package/src/components/Megamenu/MyOrangeMobilePanel.tsx +3 -9
- package/src/components/Megamenu/styles/mixins.scss +21 -34
- package/src/components/Megamenu/tests/Megamenu.unit.test.jsx +158 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
|
|
1
3
|
import { render } from "@testing-library/react";
|
|
2
4
|
import "@testing-library/jest-dom/vitest";
|
|
3
5
|
|
|
4
6
|
import { Megamenu, MegamenuBlog } from "../";
|
|
7
|
+
import MegamenuController from "../Megamenu.static";
|
|
5
8
|
|
|
6
9
|
describe("Megamenu logo markup", () => {
|
|
7
10
|
it("separates top links from the language switcher without a spacer item", () => {
|
|
@@ -148,6 +151,56 @@ describe("Megamenu logo markup", () => {
|
|
|
148
151
|
expect(container).not.toHaveTextContent("0905 123 456");
|
|
149
152
|
});
|
|
150
153
|
|
|
154
|
+
it.each([false, true])(
|
|
155
|
+
"renders My Orange as SSO links without account panel markup (B2B: %s)",
|
|
156
|
+
(isB2B) => {
|
|
157
|
+
const { container } = render(
|
|
158
|
+
<Megamenu
|
|
159
|
+
isLoggedIn={false}
|
|
160
|
+
myOrangeHref="/sso"
|
|
161
|
+
isB2B={isB2B}
|
|
162
|
+
notSticky
|
|
163
|
+
/>,
|
|
164
|
+
);
|
|
165
|
+
const links = container.querySelectorAll('a[href="/sso"]');
|
|
166
|
+
|
|
167
|
+
expect(links).toHaveLength(2);
|
|
168
|
+
for (const link of links) {
|
|
169
|
+
expect(link).toHaveTextContent("Môj Orange");
|
|
170
|
+
expect(link).not.toHaveAttribute("data-megamenu-mobile-toggle");
|
|
171
|
+
expect(link).not.toHaveAttribute("aria-haspopup");
|
|
172
|
+
expect(link).not.toHaveAttribute("aria-expanded");
|
|
173
|
+
}
|
|
174
|
+
expect(
|
|
175
|
+
container.querySelector('[data-megamenu-mobile-target="my-orange"]'),
|
|
176
|
+
).toBeNull();
|
|
177
|
+
expect(
|
|
178
|
+
container.querySelector('[data-megamenu-mobile-panel="my-orange"]'),
|
|
179
|
+
).toBeNull();
|
|
180
|
+
expect(container.querySelector(".megamenu__mobile-account")).toBeNull();
|
|
181
|
+
expect(
|
|
182
|
+
container.querySelector('[data-megamenu-mobile-panel="main"]'),
|
|
183
|
+
).toBeInTheDocument();
|
|
184
|
+
|
|
185
|
+
const controller = new MegamenuController(
|
|
186
|
+
container.querySelector("[data-megamenu]"),
|
|
187
|
+
);
|
|
188
|
+
try {
|
|
189
|
+
container.querySelector('[data-megamenu-mobile-target="main"]').click();
|
|
190
|
+
expect(
|
|
191
|
+
container.querySelector('[data-megamenu-mobile-panel="main"]'),
|
|
192
|
+
).toHaveAttribute("aria-hidden", "false");
|
|
193
|
+
expect(links[0]).toHaveAttribute("href", "/sso");
|
|
194
|
+
controller.closeMobileMenu();
|
|
195
|
+
expect(
|
|
196
|
+
container.querySelector('[data-megamenu-mobile-panel="main"]'),
|
|
197
|
+
).toHaveAttribute("aria-hidden", "true");
|
|
198
|
+
} finally {
|
|
199
|
+
controller.destroy();
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
|
|
151
204
|
it("renders optional cart item count", () => {
|
|
152
205
|
const { container } = render(<Megamenu cartItems={3} notSticky />);
|
|
153
206
|
|
|
@@ -175,3 +228,108 @@ describe("Megamenu logo markup", () => {
|
|
|
175
228
|
expect(cart?.nextElementSibling).not.toBeInTheDocument();
|
|
176
229
|
});
|
|
177
230
|
});
|
|
231
|
+
|
|
232
|
+
describe("Megamenu vendor sprite markup", () => {
|
|
233
|
+
it.each([
|
|
234
|
+
["main B2C", Megamenu, false],
|
|
235
|
+
["main B2B", Megamenu, true],
|
|
236
|
+
["blog B2C", MegamenuBlog, false],
|
|
237
|
+
["blog B2B", MegamenuBlog, true],
|
|
238
|
+
])(
|
|
239
|
+
"resolves every SVG in %s through the external sprite",
|
|
240
|
+
(_, Component, isB2B) => {
|
|
241
|
+
const spritePath = `/megamenu-sprite-${isB2B ? "dark" : "light"}.svg`;
|
|
242
|
+
const sprite = new DOMParser().parseFromString(
|
|
243
|
+
readFileSync(`public${spritePath}`, "utf8"),
|
|
244
|
+
"image/svg+xml",
|
|
245
|
+
);
|
|
246
|
+
const { container } = render(
|
|
247
|
+
<Component isB2B={isB2B} className={isB2B ? "is-dark" : undefined} />,
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
expect(
|
|
251
|
+
container.querySelector("svg path, svg rect, svg circle"),
|
|
252
|
+
).toBeNull();
|
|
253
|
+
expect(container.querySelector('img[src$=".svg"]')).toBeNull();
|
|
254
|
+
for (const use of container.querySelectorAll("svg use")) {
|
|
255
|
+
const href = use.getAttribute("href") || use.getAttribute("xlink:href");
|
|
256
|
+
expect(href).toMatch(new RegExp(`^${spritePath}#`));
|
|
257
|
+
expect(use.parentElement.querySelectorAll("use")).toHaveLength(1);
|
|
258
|
+
expect(sprite.getElementById(href.split("#")[1])).not.toBeNull();
|
|
259
|
+
}
|
|
260
|
+
for (const wrapper of container.querySelectorAll(
|
|
261
|
+
".megamenu__input-wrapper",
|
|
262
|
+
)) {
|
|
263
|
+
expect(
|
|
264
|
+
wrapper.querySelector(".megamenu__input-search-icon use"),
|
|
265
|
+
).not.toBeNull();
|
|
266
|
+
expect(
|
|
267
|
+
wrapper.querySelector(".megamenu__input-status-icon use"),
|
|
268
|
+
).not.toBeNull();
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe("Megamenu dedicated sprites", () => {
|
|
275
|
+
it("keeps megamenu-owned sources and symbols out of the global sprite", () => {
|
|
276
|
+
const globalSprite = new DOMParser().parseFromString(
|
|
277
|
+
readFileSync("public/sprite.svg", "utf8"),
|
|
278
|
+
"image/svg+xml",
|
|
279
|
+
);
|
|
280
|
+
const sources = readdirSync("src/assets/megamenu").filter((file) =>
|
|
281
|
+
file.endsWith(".svg"),
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
expect(sources.length).toBeGreaterThan(0);
|
|
285
|
+
for (const file of sources) {
|
|
286
|
+
expect(existsSync(`src/assets/icons/${file}`), file).toBe(false);
|
|
287
|
+
expect(globalSprite.getElementById(file.slice(0, -4)), file).toBeNull();
|
|
288
|
+
}
|
|
289
|
+
expect(globalSprite.getElementById("rewards-accent")).toBeNull();
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("ships matching symbol IDs with theme colors and no unrelated global icons", () => {
|
|
293
|
+
const parse = (theme) =>
|
|
294
|
+
new DOMParser().parseFromString(
|
|
295
|
+
readFileSync(`public/megamenu-sprite-${theme}.svg`, "utf8"),
|
|
296
|
+
"image/svg+xml",
|
|
297
|
+
);
|
|
298
|
+
const light = parse("light");
|
|
299
|
+
const dark = parse("dark");
|
|
300
|
+
const ids = (doc) =>
|
|
301
|
+
Array.from(doc.querySelectorAll("symbol"), (s) => s.id);
|
|
302
|
+
expect(ids(light)).toEqual(ids(dark));
|
|
303
|
+
expect(ids(light)).toHaveLength(20);
|
|
304
|
+
expect(light.getElementById("user").getAttribute("fill")).toBe("#000");
|
|
305
|
+
expect(dark.getElementById("user").getAttribute("fill")).toBe("#fff");
|
|
306
|
+
expect(light.getElementById("linkedin")).toBeNull();
|
|
307
|
+
expect(light.getElementById("megamenu-logo").outerHTML).not.toEqual(
|
|
308
|
+
dark.getElementById("megamenu-logo").outerHTML,
|
|
309
|
+
);
|
|
310
|
+
expect(light.getElementById("store-apple").outerHTML).not.toEqual(
|
|
311
|
+
dark.getElementById("store-apple").outerHTML,
|
|
312
|
+
);
|
|
313
|
+
for (const doc of [light, dark]) {
|
|
314
|
+
expect(doc.querySelector("parsererror")).toBeNull();
|
|
315
|
+
for (const element of doc.querySelectorAll("[clip-path]")) {
|
|
316
|
+
const id = element
|
|
317
|
+
.getAttribute("clip-path")
|
|
318
|
+
.match(/url\(#([^)]+)\)/)?.[1];
|
|
319
|
+
expect(doc.getElementById(id)).not.toBeNull();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it.each([Megamenu, MegamenuBlog])(
|
|
326
|
+
"uses the dark sprite for an explicit dark navigation class",
|
|
327
|
+
(Component) => {
|
|
328
|
+
const { container } = render(<Component className="is-dark" />);
|
|
329
|
+
for (const use of container.querySelectorAll("use")) {
|
|
330
|
+
expect(use.getAttribute("xlink:href")).toMatch(
|
|
331
|
+
/^\/megamenu-sprite-dark\.svg#/,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
);
|