@evenicanpm/storefront-core 1.6.0 → 1.8.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/__mocks__/next-image.tsx +3 -1
- package/package.json +3 -3
- package/src/api-manager/datasources/d365/d365-product.datasource.ts +1 -1
- package/src/api-manager/datasources/d365/utils/product-inventory-utils.ts +1 -3
- package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +7 -5
- package/src/api-manager/datasources/e4/product/e4-product.datasource.ts +1 -4
- package/src/api-manager/datasources/e4/product/e4-product.translator.ts +13 -19
- package/src/api-manager/datasources/e4/utils/unwrap-e4-variants.ts +10 -13
- package/src/auth/auth-options.ts +34 -1
- package/src/auth/providers/entra-external-id-provider.ts +50 -0
- package/src/auth/providers/index.ts +8 -1
- package/src/auth/refresh-token.ts +1 -1
- package/src/cms/blocks/interfaces.ts +2 -0
- package/src/components-v2/BazaarMenu.stories.tsx +1 -1
- package/src/components-v2/BazaarMenu.tsx +4 -3
- package/src/components-v2/T/__tests__/T.test.tsx +91 -0
- package/src/components-v2/accordion/__tests__/accordion-header.test.tsx +28 -0
- package/src/components-v2/carousel/__tests__/carousel.test.tsx +208 -0
- package/src/components-v2/carousel-cards/carousel-card-1/__tests__/carousel-card-1.test.tsx +81 -0
- package/src/components-v2/categories/__tests__/category-menu.test.tsx +115 -0
- package/src/components-v2/categories/category-list/category-list.tsx +5 -1
- package/src/components-v2/categories/category-menu.tsx +11 -5
- package/src/components-v2/flex-box/__tests__/flex-box.test.tsx +88 -0
- package/src/components-v2/header/__tests__/header.test.tsx +122 -0
- package/src/components-v2/icons/__tests__/icons.test.tsx +53 -0
- package/src/components-v2/mobile-navigation/__tests__/mobile-navigation-bar.test.tsx +94 -0
- package/src/components-v2/nav-link/__tests__/nav-link.test.tsx +75 -0
- package/src/components-v2/navbar/__tests__/navbar.test.tsx +96 -0
- package/src/components-v2/product-cards/__tests__/product-cards.test.tsx +91 -0
- package/src/components-v2/product-dialog/__tests__/product-dialog.test.tsx +129 -0
- package/src/components-v2/product-dimensions/__tests__/product-dimensions.test.tsx +130 -0
- package/src/components-v2/product-dimensions/compound/dimensions-group-list-chip.tsx +36 -37
- package/src/components-v2/product-quantity-buttons/__tests__/product-quantity-buttons.test.tsx +77 -0
- package/src/components-v2/product-quantity-variants/__tests__/product-quantity-variants.test.tsx +109 -0
- package/src/components-v2/products-view/__tests__/products-view.test.tsx +147 -0
- package/src/components-v2/progress/__tests__/progress.test.tsx +62 -0
- package/src/components-v2/scrollbar/Scrollbar.stories.tsx +2 -2
- package/src/components-v2/scrollbar/__tests__/scrollbar.test.tsx +93 -0
- package/src/components-v2/search-bar/__tests__/search-bar.test.tsx +142 -0
- package/src/components-v2/search-bar/compound/results.tsx +1 -1
- package/src/components-v2/section/__tests__/section.test.tsx +100 -0
- package/src/components-v2/side-nav/__tests__/side-nav.test.tsx +156 -0
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +14 -15
- package/src/components-v2/wishlist-dialogs/styles.ts +8 -10
- package/src/pages-v2/account/addresses/address-item.tsx +2 -1
- package/src/pages-v2/checkout/checkout-alt-form/checkout-form.tsx +6 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +9 -8
- package/src/pages-v2/product-details/bopis/find-in-store-modal.tsx +1 -1
- package/src/pages-v2/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -0
- package/src/pages-v2/product-list/product-list-context.tsx +123 -44
- package/src/pages-v2/product-list/range-filter.tsx +36 -25
- package/src/pages-v2/product-list/selected-facets.tsx +15 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import Home from "../home";
|
|
3
|
+
import ShoppingBagOutlined from "../shopping-bag-outlined";
|
|
4
|
+
import CartBag from "../cart-bag";
|
|
5
|
+
import User from "../user";
|
|
6
|
+
|
|
7
|
+
describe("Icon components", () => {
|
|
8
|
+
it("renders Home icon", () => {
|
|
9
|
+
render(<Home data-testid="home-icon" />);
|
|
10
|
+
|
|
11
|
+
const icon = screen.getByTestId("home-icon");
|
|
12
|
+
expect(icon).toBeInTheDocument();
|
|
13
|
+
expect(icon.tagName).toBe("svg");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("renders ShoppingBagOutlined icon", () => {
|
|
17
|
+
render(<ShoppingBagOutlined data-testid="bag-icon" />);
|
|
18
|
+
|
|
19
|
+
const icon = screen.getByTestId("bag-icon");
|
|
20
|
+
expect(icon).toBeInTheDocument();
|
|
21
|
+
expect(icon.tagName).toBe("svg");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("renders CartBag icon", () => {
|
|
25
|
+
render(<CartBag data-testid="cart-bag-icon" />);
|
|
26
|
+
|
|
27
|
+
const icon = screen.getByTestId("cart-bag-icon");
|
|
28
|
+
expect(icon).toBeInTheDocument();
|
|
29
|
+
expect(icon.tagName).toBe("svg");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("renders User icon", () => {
|
|
33
|
+
render(<User data-testid="user-icon" />);
|
|
34
|
+
|
|
35
|
+
const icon = screen.getByTestId("user-icon");
|
|
36
|
+
expect(icon).toBeInTheDocument();
|
|
37
|
+
expect(icon.tagName).toBe("svg");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("accepts size prop", () => {
|
|
41
|
+
render(<Home data-testid="home-sized" fontSize="large" />);
|
|
42
|
+
|
|
43
|
+
const icon = screen.getByTestId("home-sized");
|
|
44
|
+
expect(icon).toBeInTheDocument();
|
|
45
|
+
expect(icon.tagName).toBe("svg");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("accepts color prop", () => {
|
|
49
|
+
render(<Home data-testid="home-colored" color="primary" />);
|
|
50
|
+
|
|
51
|
+
expect(screen.getByTestId("home-colored")).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
4
|
+
import MobileNavigationBar from "../mobile-navigation-bar";
|
|
5
|
+
import Home from "../../icons/home";
|
|
6
|
+
|
|
7
|
+
vi.mock("@mui/material/useMediaQuery", () => ({
|
|
8
|
+
default: vi.fn(() => true),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
vi.mock(
|
|
12
|
+
"@evenicanpm/storefront-core/src/api-manager/services/cart/queries/get-cart",
|
|
13
|
+
() => ({
|
|
14
|
+
default: {
|
|
15
|
+
useData: vi.fn(() => ({ data: { TotalItems: 2 } })),
|
|
16
|
+
},
|
|
17
|
+
}),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
vi.mock("next-intl", () => ({
|
|
21
|
+
useTranslations: vi.fn(() => (key: string) => key),
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
describe("mobile-navigation-bar", () => {
|
|
25
|
+
it("does not render when media query is false", () => {
|
|
26
|
+
const mock = vi.mocked(useMediaQuery);
|
|
27
|
+
mock.mockReturnValue(false);
|
|
28
|
+
|
|
29
|
+
const { container } = render(<MobileNavigationBar />);
|
|
30
|
+
|
|
31
|
+
mock.mockReturnValue(true);
|
|
32
|
+
expect(container.innerHTML).toBe("");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("renders default menu items when media query is true", () => {
|
|
36
|
+
render(<MobileNavigationBar />);
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText("home")).toBeInTheDocument();
|
|
39
|
+
expect(screen.getByText("category")).toBeInTheDocument();
|
|
40
|
+
expect(screen.getByText("cart")).toBeInTheDocument();
|
|
41
|
+
expect(screen.getByText("account")).toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("renders custom menu list when provided", () => {
|
|
45
|
+
const customMenu = [
|
|
46
|
+
{ title: "custom1", Icon: Home, href: "/custom1" },
|
|
47
|
+
{ title: "custom2", Icon: Home, href: "/custom2" },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
render(<MobileNavigationBar menuList={customMenu} />);
|
|
51
|
+
|
|
52
|
+
expect(screen.getByText("custom1")).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByText("custom2")).toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("renders custom children when provided", () => {
|
|
57
|
+
render(
|
|
58
|
+
<MobileNavigationBar>
|
|
59
|
+
<div>Custom Navigation Item</div>
|
|
60
|
+
</MobileNavigationBar>,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
expect(screen.getByText("Custom Navigation Item")).toBeInTheDocument();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("renders MenuItem with title, Icon, and href", () => {
|
|
67
|
+
render(
|
|
68
|
+
<MobileNavigationBar
|
|
69
|
+
menuList={[{ title: "test", Icon: Home, href: "/test" }]}
|
|
70
|
+
/>,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const link = screen.getByText("test").closest("a");
|
|
74
|
+
expect(link).toHaveAttribute("href", "/test");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("displays cart badge with item count", () => {
|
|
78
|
+
render(
|
|
79
|
+
<MobileNavigationBar
|
|
80
|
+
menuList={[{ title: "cart", Icon: Home, href: "/cart" }]}
|
|
81
|
+
/>,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(screen.getByText("cart")).toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("renders MenuItem without href for non-link items", () => {
|
|
88
|
+
render(
|
|
89
|
+
<MobileNavigationBar menuList={[{ title: "nolink", Icon: Home }]} />,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
expect(screen.getByText("nolink")).toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import NavLink from "../nav-link";
|
|
4
|
+
|
|
5
|
+
vi.mock("next/navigation", () => ({
|
|
6
|
+
usePathname: vi.fn(() => "/products"),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
import { usePathname } from "next/navigation";
|
|
10
|
+
|
|
11
|
+
describe("nav-link", () => {
|
|
12
|
+
it("renders as a link with href", () => {
|
|
13
|
+
render(<NavLink href="/products">Products</NavLink>);
|
|
14
|
+
|
|
15
|
+
const link = screen.getByRole("link", { name: "Products" });
|
|
16
|
+
expect(link).toBeInTheDocument();
|
|
17
|
+
expect(link).toHaveAttribute("href", "/products");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("applies active state when route matches", () => {
|
|
21
|
+
render(<NavLink href="/products">Products</NavLink>);
|
|
22
|
+
|
|
23
|
+
const link = screen.getByRole("link", { name: "Products" });
|
|
24
|
+
expect(link).toBeInTheDocument();
|
|
25
|
+
expect(link).toHaveAttribute("href", "/products");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("applies inactive state when route does not match", () => {
|
|
29
|
+
render(<NavLink href="/about">About</NavLink>);
|
|
30
|
+
|
|
31
|
+
const link = screen.getByRole("link", { name: "About" });
|
|
32
|
+
expect(link).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("handles root path correctly", () => {
|
|
36
|
+
vi.mocked(usePathname).mockReturnValue("/");
|
|
37
|
+
|
|
38
|
+
render(<NavLink href="/">Home</NavLink>);
|
|
39
|
+
|
|
40
|
+
const link = screen.getByRole("link", { name: "Home" });
|
|
41
|
+
expect(link).toHaveAttribute("href", "/");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("accepts custom className", () => {
|
|
45
|
+
render(
|
|
46
|
+
<NavLink href="/products" className="custom-class">
|
|
47
|
+
Products
|
|
48
|
+
</NavLink>,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const link = screen.getByRole("link", { name: "Products" });
|
|
52
|
+
expect(link).toHaveClass("custom-class");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("accepts custom style", () => {
|
|
56
|
+
render(
|
|
57
|
+
<NavLink href="/products" style={{ textDecoration: "underline" }}>
|
|
58
|
+
Products
|
|
59
|
+
</NavLink>,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const link = screen.getByRole("link", { name: "Products" });
|
|
63
|
+
expect(link).toHaveStyle("text-decoration: underline");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("renders children correctly", () => {
|
|
67
|
+
render(
|
|
68
|
+
<NavLink href="/products">
|
|
69
|
+
<span>Product Link</span>
|
|
70
|
+
</NavLink>,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(screen.getByText("Product Link")).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
vi.mock("next-intl", () => ({
|
|
5
|
+
useTranslations: () => (key: string) => key,
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
vi.mock(
|
|
9
|
+
"@evenicanpm/storefront-core/src/components-v2/navbar/categories",
|
|
10
|
+
() => ({
|
|
11
|
+
default: () => <div data-testid="navbar-categories">Categories</div>,
|
|
12
|
+
}),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
vi.mock(
|
|
16
|
+
"@evenicanpm/storefront-core/src/components-v2/navbar/nav-list",
|
|
17
|
+
() => ({
|
|
18
|
+
default: () => <div data-testid="navbar-nav-list">Navigation List</div>,
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
import Navbar from "../navbar";
|
|
23
|
+
|
|
24
|
+
describe("navbar", () => {
|
|
25
|
+
it("renders default navbar with categories and navigation", () => {
|
|
26
|
+
render(<Navbar />);
|
|
27
|
+
|
|
28
|
+
expect(screen.getByTestId("navbar-categories")).toBeInTheDocument();
|
|
29
|
+
expect(screen.getByTestId("navbar-nav-list")).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("renders custom children when provided", () => {
|
|
33
|
+
render(
|
|
34
|
+
<Navbar>
|
|
35
|
+
<div>Custom Content</div>
|
|
36
|
+
</Navbar>,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
expect(screen.getByText("Custom Content")).toBeInTheDocument();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("renders Navbar.Content wrapper", () => {
|
|
43
|
+
render(
|
|
44
|
+
<Navbar>
|
|
45
|
+
<Navbar.Content>
|
|
46
|
+
<div>Content Wrapper</div>
|
|
47
|
+
</Navbar.Content>
|
|
48
|
+
</Navbar>,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(screen.getByText("Content Wrapper")).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("hides categories when hideCategories is true", () => {
|
|
55
|
+
render(
|
|
56
|
+
<Navbar hideCategories={true}>
|
|
57
|
+
<Navbar.Content>
|
|
58
|
+
<Navbar.Categories />
|
|
59
|
+
<Navbar.Navigation />
|
|
60
|
+
</Navbar.Content>
|
|
61
|
+
</Navbar>,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
expect(screen.queryByTestId("navbar-categories")).not.toBeInTheDocument();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("renders Navigation subcomponent", () => {
|
|
68
|
+
render(
|
|
69
|
+
<Navbar>
|
|
70
|
+
<Navbar.Navigation />
|
|
71
|
+
</Navbar>,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(screen.getByTestId("navbar-nav-list")).toBeInTheDocument();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("renders Categories subcomponent when not hidden", () => {
|
|
78
|
+
render(
|
|
79
|
+
<Navbar hideCategories={false}>
|
|
80
|
+
<Navbar.Categories />
|
|
81
|
+
</Navbar>,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(screen.getByTestId("navbar-categories")).toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("accepts border and elevation props", () => {
|
|
88
|
+
render(
|
|
89
|
+
<Navbar border={1} elevation={4}>
|
|
90
|
+
<div>Content</div>
|
|
91
|
+
</Navbar>,
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
expect(screen.getByText("Content")).toBeInTheDocument();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import DiscountChip from "../discount-chip";
|
|
4
|
+
import FavoriteButton from "../favorite-button";
|
|
5
|
+
import ProductPrice from "../product-price";
|
|
6
|
+
import ProductRating from "../product-rating";
|
|
7
|
+
import ProductTitle from "../product-title";
|
|
8
|
+
|
|
9
|
+
vi.mock("next-intl", () => ({
|
|
10
|
+
useTranslations: () => (key: string) => key,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe("product-cards components", () => {
|
|
14
|
+
describe("DiscountChip", () => {
|
|
15
|
+
it("renders discount chip", () => {
|
|
16
|
+
const { container } = render(<DiscountChip discount={20} />);
|
|
17
|
+
expect(container.firstChild).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("renders with custom sx props", () => {
|
|
21
|
+
const { container } = render(
|
|
22
|
+
<DiscountChip discount={15} sx={{ color: "red" }} />,
|
|
23
|
+
);
|
|
24
|
+
expect(container.querySelector("*")).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("FavoriteButton", () => {
|
|
29
|
+
it("renders favorite button", () => {
|
|
30
|
+
const { container } = render(
|
|
31
|
+
<FavoriteButton isFavorite={false} onToggle={vi.fn()} />,
|
|
32
|
+
);
|
|
33
|
+
expect(container.querySelector("button")).toBeTruthy();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("accepts onToggle handler", () => {
|
|
37
|
+
const handleClick = vi.fn();
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<FavoriteButton isFavorite={false} onToggle={handleClick} />,
|
|
40
|
+
);
|
|
41
|
+
expect(container.querySelector("button")).toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("ProductPrice", () => {
|
|
46
|
+
it("renders product price", () => {
|
|
47
|
+
const { container } = render(
|
|
48
|
+
<ProductPrice price={99.99} discount={20} />,
|
|
49
|
+
);
|
|
50
|
+
expect(container.firstChild).toBeTruthy();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("renders with sale price", () => {
|
|
54
|
+
const { container } = render(<ProductPrice price={100} discount={50} />);
|
|
55
|
+
expect(container.querySelector("*")).toBeTruthy();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("ProductRating", () => {
|
|
60
|
+
it("renders product rating", () => {
|
|
61
|
+
const { container } = render(<ProductRating showRating rating={4.5} />);
|
|
62
|
+
expect(container.firstChild).toBeTruthy();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("renders with zero rating", () => {
|
|
66
|
+
const { container } = render(<ProductRating showRating rating={0} />);
|
|
67
|
+
expect(container.firstChild).toBeTruthy();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("ProductTitle", () => {
|
|
72
|
+
it("renders product title", () => {
|
|
73
|
+
render(<ProductTitle title="Test Product" slug="test-product" />);
|
|
74
|
+
expect(screen.getByText("Test Product")).toBeInTheDocument();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("renders with long title", () => {
|
|
78
|
+
const longTitle =
|
|
79
|
+
"This is a very long product title that should be rendered correctly";
|
|
80
|
+
render(<ProductTitle title={longTitle} slug="long-product-title" />);
|
|
81
|
+
expect(screen.getByText(longTitle)).toBeInTheDocument();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("renders as a link", () => {
|
|
85
|
+
const { container } = render(
|
|
86
|
+
<ProductTitle title="Product" slug="product-slug" />,
|
|
87
|
+
);
|
|
88
|
+
expect(container.querySelector("a")).toBeTruthy();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { render } from "@testing-library/react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
import ProductDialog from "../index";
|
|
5
|
+
|
|
6
|
+
vi.mock("next-intl", () => ({
|
|
7
|
+
useTranslations: () => (key: string) => key,
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock(
|
|
11
|
+
"@evenicanpm/storefront-core/src/api-manager/services/product/queries/get-product-details",
|
|
12
|
+
() => ({
|
|
13
|
+
default: {
|
|
14
|
+
useData: vi.fn(() => ({
|
|
15
|
+
data: {
|
|
16
|
+
RecordId: 1,
|
|
17
|
+
Name: "Test Product",
|
|
18
|
+
Description: "Test description",
|
|
19
|
+
},
|
|
20
|
+
})),
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
vi.mock(
|
|
26
|
+
"@evenicanpm/storefront-core/src/api-manager/services/product/queries/get-product-availability",
|
|
27
|
+
() => ({
|
|
28
|
+
default: {
|
|
29
|
+
useData: vi.fn(() => ({ data: { OrgUnitAvailabilities: [] } })),
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
vi.mock(
|
|
35
|
+
"@evenicanpm/storefront-core/src/components-v2/product-dialog/compound/product-dialog",
|
|
36
|
+
() => ({
|
|
37
|
+
default: Object.assign(
|
|
38
|
+
({
|
|
39
|
+
children,
|
|
40
|
+
openDialog,
|
|
41
|
+
}: {
|
|
42
|
+
children: ReactNode;
|
|
43
|
+
openDialog: boolean;
|
|
44
|
+
}) => {
|
|
45
|
+
if (!openDialog) return null;
|
|
46
|
+
return <div data-testid="product-dialog">{children}</div>;
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
Content: Object.assign(
|
|
50
|
+
({ children }: { children: ReactNode }) => (
|
|
51
|
+
<div data-testid="product-dialog-content">{children}</div>
|
|
52
|
+
),
|
|
53
|
+
{
|
|
54
|
+
Images: () => <div data-testid="product-images">Images</div>,
|
|
55
|
+
Info: Object.assign(
|
|
56
|
+
({ children }: { children: ReactNode }) => (
|
|
57
|
+
<div data-testid="product-info">{children}</div>
|
|
58
|
+
),
|
|
59
|
+
{
|
|
60
|
+
Name: () => <div data-testid="product-name">Name</div>,
|
|
61
|
+
Category: () => (
|
|
62
|
+
<div data-testid="product-category">Category</div>
|
|
63
|
+
),
|
|
64
|
+
Description: () => (
|
|
65
|
+
<div data-testid="product-description">Description</div>
|
|
66
|
+
),
|
|
67
|
+
Rating: () => <div data-testid="product-rating">Rating</div>,
|
|
68
|
+
AddToCart: () => (
|
|
69
|
+
<button type="button" data-testid="add-to-cart">
|
|
70
|
+
Add to Cart
|
|
71
|
+
</button>
|
|
72
|
+
),
|
|
73
|
+
},
|
|
74
|
+
),
|
|
75
|
+
},
|
|
76
|
+
),
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
describe("ProductDialog", () => {
|
|
83
|
+
it("renders ProductDialog component", () => {
|
|
84
|
+
const { container } = render(
|
|
85
|
+
<ProductDialog productId={1} openDialog={true} />,
|
|
86
|
+
);
|
|
87
|
+
expect(container.firstChild).toBeTruthy();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("passes correct props", () => {
|
|
91
|
+
const { container } = render(
|
|
92
|
+
<ProductDialog productId={2} openDialog={true} />,
|
|
93
|
+
);
|
|
94
|
+
expect(
|
|
95
|
+
container.querySelector("[data-testid='product-dialog']"),
|
|
96
|
+
).toBeTruthy();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("handles close handler", () => {
|
|
100
|
+
const handleClose = vi.fn();
|
|
101
|
+
const { container } = render(
|
|
102
|
+
<ProductDialog
|
|
103
|
+
productId={1}
|
|
104
|
+
openDialog={true}
|
|
105
|
+
handleCloseDialog={handleClose}
|
|
106
|
+
/>,
|
|
107
|
+
);
|
|
108
|
+
expect(container.firstChild).toBeTruthy();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("renders with different product IDs", () => {
|
|
112
|
+
const { rerender, container } = render(
|
|
113
|
+
<ProductDialog productId={1} openDialog={true} />,
|
|
114
|
+
);
|
|
115
|
+
expect(container.firstChild).toBeTruthy();
|
|
116
|
+
|
|
117
|
+
rerender(<ProductDialog productId={2} openDialog={true} />);
|
|
118
|
+
expect(container.firstChild).toBeTruthy();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("renders with composition structure", () => {
|
|
122
|
+
const { container } = render(
|
|
123
|
+
<ProductDialog productId={1} openDialog={true} />,
|
|
124
|
+
);
|
|
125
|
+
expect(
|
|
126
|
+
container.querySelector("[data-testid='product-dialog']"),
|
|
127
|
+
).toBeTruthy();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { render } from "@testing-library/react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
import ProductDimensions from "../index";
|
|
5
|
+
import type { ProductDimensionValueInventoryAvailability } from "@msdyn365-commerce/retail-proxy";
|
|
6
|
+
|
|
7
|
+
vi.mock("next-intl", () => ({
|
|
8
|
+
useTranslations: () => (key: string) => key,
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
vi.mock(
|
|
12
|
+
"@evenicanpm/storefront-core/src/components-v2/product-dimensions/compound/dimensions",
|
|
13
|
+
() => ({
|
|
14
|
+
Dimensions: Object.assign(
|
|
15
|
+
({ children }: { children: ReactNode }) => (
|
|
16
|
+
<div data-testid="dimensions">{children}</div>
|
|
17
|
+
),
|
|
18
|
+
{
|
|
19
|
+
Group: Object.assign(
|
|
20
|
+
({ children }: { children: ReactNode }) => (
|
|
21
|
+
<div data-testid="dimension-group">{children}</div>
|
|
22
|
+
),
|
|
23
|
+
{
|
|
24
|
+
Label: () => <div data-testid="dimension-label">Dimension</div>,
|
|
25
|
+
List: () => (
|
|
26
|
+
<ul data-testid="dimension-list">
|
|
27
|
+
<li>Value</li>
|
|
28
|
+
</ul>
|
|
29
|
+
),
|
|
30
|
+
Error: () => <div data-testid="dimension-error">Error</div>,
|
|
31
|
+
},
|
|
32
|
+
),
|
|
33
|
+
},
|
|
34
|
+
),
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
describe("ProductDimensions", () => {
|
|
39
|
+
const mockDimension: ProductDimensionValueInventoryAvailability = {
|
|
40
|
+
DimensionTypeValue: 1,
|
|
41
|
+
DimensionValue: {
|
|
42
|
+
RecordId: 1,
|
|
43
|
+
Value: "Red",
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const mockDimensionGroups: ProductDimensionValueInventoryAvailability[][] = [
|
|
48
|
+
[mockDimension],
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const mockSelectDimensions: Record<
|
|
52
|
+
number,
|
|
53
|
+
ProductDimensionValueInventoryAvailability
|
|
54
|
+
> = {};
|
|
55
|
+
|
|
56
|
+
const mockHandleChangeVariant = vi.fn();
|
|
57
|
+
|
|
58
|
+
it("renders product dimensions", () => {
|
|
59
|
+
const { container } = render(
|
|
60
|
+
<ProductDimensions
|
|
61
|
+
dimensionGroups={mockDimensionGroups}
|
|
62
|
+
selectDimensions={mockSelectDimensions}
|
|
63
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
64
|
+
/>,
|
|
65
|
+
);
|
|
66
|
+
expect(container.querySelector("[data-testid='dimensions']")).toBeTruthy();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("renders multiple dimension groups", () => {
|
|
70
|
+
const multipleDimensions: ProductDimensionValueInventoryAvailability[][] = [
|
|
71
|
+
[mockDimension],
|
|
72
|
+
[{ ...mockDimension, DimensionValue: { RecordId: 2, Value: "Large" } }],
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const { container } = render(
|
|
76
|
+
<ProductDimensions
|
|
77
|
+
dimensionGroups={multipleDimensions}
|
|
78
|
+
selectDimensions={mockSelectDimensions}
|
|
79
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
80
|
+
/>,
|
|
81
|
+
);
|
|
82
|
+
expect(container.querySelector("[data-testid='dimensions']")).toBeTruthy();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("passes handleChangeVariant callback", () => {
|
|
86
|
+
const { container } = render(
|
|
87
|
+
<ProductDimensions
|
|
88
|
+
dimensionGroups={mockDimensionGroups}
|
|
89
|
+
selectDimensions={mockSelectDimensions}
|
|
90
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
91
|
+
/>,
|
|
92
|
+
);
|
|
93
|
+
expect(container.firstChild).toBeTruthy();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("shows dimension error when provided", () => {
|
|
97
|
+
const { container } = render(
|
|
98
|
+
<ProductDimensions
|
|
99
|
+
dimensionGroups={mockDimensionGroups}
|
|
100
|
+
selectDimensions={mockSelectDimensions}
|
|
101
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
102
|
+
showDimensionError={true}
|
|
103
|
+
/>,
|
|
104
|
+
);
|
|
105
|
+
expect(container.firstChild).toBeTruthy();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("renders with selected dimensions", () => {
|
|
109
|
+
const selectedDimensions = { 0: mockDimension };
|
|
110
|
+
const { container } = render(
|
|
111
|
+
<ProductDimensions
|
|
112
|
+
dimensionGroups={mockDimensionGroups}
|
|
113
|
+
selectDimensions={selectedDimensions}
|
|
114
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
115
|
+
/>,
|
|
116
|
+
);
|
|
117
|
+
expect(container.querySelector("[data-testid='dimensions']")).toBeTruthy();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("renders empty dimension groups", () => {
|
|
121
|
+
const { container } = render(
|
|
122
|
+
<ProductDimensions
|
|
123
|
+
dimensionGroups={[]}
|
|
124
|
+
selectDimensions={mockSelectDimensions}
|
|
125
|
+
handleChangeVariant={mockHandleChangeVariant}
|
|
126
|
+
/>,
|
|
127
|
+
);
|
|
128
|
+
expect(container.firstChild).toBeTruthy();
|
|
129
|
+
});
|
|
130
|
+
});
|