@fpkit/acss 3.1.1 → 3.2.1
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/libs/{chunk-2NRIP6RB.cjs → chunk-2C3YLBWP.cjs} +3 -3
- package/libs/{chunk-NWJDAHP6.cjs → chunk-2GJHKWEK.cjs} +3 -3
- package/libs/{chunk-FVROL3V5.js → chunk-2JCDEC32.js} +3 -3
- package/libs/{chunk-IRLFZ3OL.js → chunk-3XJC4XUG.js} +2 -2
- package/libs/{chunk-L6PRDL6F.cjs → chunk-5CJPTDK3.cjs} +3 -3
- package/libs/{chunk-E4OSROCA.cjs → chunk-5QSNJQVH.cjs} +3 -3
- package/libs/{chunk-O3JIHC5M.cjs → chunk-6BUJZ4DJ.cjs} +3 -3
- package/libs/{chunk-WXBFBWYF.cjs → chunk-AFINOD2L.cjs} +3 -3
- package/libs/{chunk-HRRHPLER.js → chunk-AWZLSWDO.js} +2 -2
- package/libs/chunk-DDSXKOUB.js +7 -0
- package/libs/chunk-DDSXKOUB.js.map +1 -0
- package/libs/{chunk-CWRNJA4P.js → chunk-DIJBIOFE.js} +3 -3
- package/libs/chunk-EJ6KYBFE.cjs +13 -0
- package/libs/chunk-EJ6KYBFE.cjs.map +1 -0
- package/libs/{chunk-GUJSMQ3V.cjs → chunk-EKJYOCLY.cjs} +3 -3
- package/libs/{chunk-X5RKCLDC.cjs → chunk-F64GE6RG.cjs} +4 -4
- package/libs/{chunk-5RAWNUVD.js → chunk-IBUTNPTQ.js} +2 -2
- package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
- package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
- package/libs/{chunk-MPTMPBFT.js → chunk-M7JLT62Q.js} +2 -2
- package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
- package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
- package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
- package/libs/chunk-OU52NIKA.js +8 -0
- package/libs/chunk-OU52NIKA.js.map +1 -0
- package/libs/{chunk-43TK2ICH.js → chunk-PMWL5XZ4.js} +3 -3
- package/libs/{chunk-KVKQLRJG.js → chunk-TF3GQKOY.js} +2 -2
- package/libs/{chunk-IEB64SWY.js → chunk-U5VA34SU.js} +2 -2
- package/libs/{chunk-EE3ZWSBY.cjs → chunk-URBGDUFN.cjs} +6 -6
- package/libs/chunk-WWPLBWCQ.cjs +18 -0
- package/libs/chunk-WWPLBWCQ.cjs.map +1 -0
- package/libs/{chunk-TPIB3RQP.js → chunk-ZF6Y7W57.js} +5 -5
- package/libs/component-props-50e69975.d.ts +66 -0
- package/libs/components/box/box.css +1 -0
- package/libs/components/box/box.css.map +1 -0
- package/libs/components/box/box.min.css +3 -0
- package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +4 -4
- package/libs/components/button.d.cts +10 -3
- package/libs/components/button.d.ts +10 -3
- package/libs/components/button.js +2 -2
- package/libs/components/card.cjs +7 -7
- package/libs/components/card.d.cts +13 -85
- package/libs/components/card.d.ts +13 -85
- package/libs/components/card.js +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/cluster/cluster.css +1 -0
- package/libs/components/cluster/cluster.css.map +1 -0
- package/libs/components/cluster/cluster.min.css +3 -0
- package/libs/components/dialog/dialog.cjs +7 -7
- package/libs/components/dialog/dialog.js +5 -5
- package/libs/components/form/fields.cjs +4 -4
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/textarea.cjs +4 -4
- package/libs/components/form/textarea.js +2 -2
- package/libs/components/grid/grid.css +1 -0
- package/libs/components/grid/grid.css.map +1 -0
- package/libs/components/grid/grid.min.css +3 -0
- package/libs/components/heading/heading.cjs +3 -3
- package/libs/components/heading/heading.js +2 -2
- package/libs/components/icons/icon.cjs +4 -4
- package/libs/components/icons/icon.d.cts +2 -2
- package/libs/components/icons/icon.d.ts +2 -2
- package/libs/components/icons/icon.js +2 -2
- package/libs/components/link/link.cjs +6 -6
- package/libs/components/link/link.js +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.js +2 -2
- package/libs/components/modal.cjs +4 -4
- package/libs/components/modal.d.cts +1 -1
- package/libs/components/modal.d.ts +1 -1
- package/libs/components/modal.js +3 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/stack/stack.css +1 -0
- package/libs/components/stack/stack.css.map +1 -0
- package/libs/components/stack/stack.min.css +3 -0
- package/libs/components/tables/table.d.cts +1 -1
- package/libs/components/tables/table.d.ts +1 -1
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.js +2 -2
- package/libs/hooks.cjs +4 -4
- package/libs/hooks.js +3 -3
- package/libs/{icons-287fce3a.d.ts → icons-df8e744f.d.ts} +1 -1
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +2 -2
- package/libs/icons.d.ts +2 -2
- package/libs/icons.js +2 -2
- package/libs/index.cjs +64 -63
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +923 -4
- package/libs/index.d.ts +923 -4
- package/libs/index.js +28 -28
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/alert/STYLES.mdx +790 -0
- package/src/components/badge/STYLES.mdx +610 -0
- package/src/components/box/README.mdx +401 -0
- package/src/components/box/STYLES.mdx +360 -0
- package/src/components/box/box.scss +245 -0
- package/src/components/box/box.stories.tsx +395 -0
- package/src/components/box/box.test.tsx +425 -0
- package/src/components/box/box.tsx +170 -0
- package/src/components/box/box.types.ts +166 -0
- package/src/components/breadcrumbs/STYLES.mdx +99 -0
- package/src/components/buttons/STYLES.mdx +766 -0
- package/src/components/cards/STYLES.mdx +835 -0
- package/src/components/cards/card.scss +30 -21
- package/src/components/cards/card.stories.tsx +120 -80
- package/src/components/cards/card.tsx +14 -4
- package/src/components/cards/card.types.ts +13 -0
- package/src/components/cluster/README.mdx +595 -0
- package/src/components/cluster/STYLES.mdx +626 -0
- package/src/components/cluster/cluster.scss +86 -0
- package/src/components/cluster/cluster.stories.tsx +385 -0
- package/src/components/cluster/cluster.test.tsx +655 -0
- package/src/components/cluster/cluster.tsx +94 -0
- package/src/components/cluster/cluster.types.ts +75 -0
- package/src/components/details/STYLES.mdx +445 -0
- package/src/components/dialog/STYLES.mdx +888 -0
- package/src/components/flexbox/STYLES.mdx +1 -1
- package/src/components/form/STYLES.mdx +821 -0
- package/src/components/grid/README.mdx +709 -0
- package/src/components/grid/STYLES.mdx +785 -0
- package/src/components/grid/grid.scss +287 -0
- package/src/components/grid/grid.stories.tsx +486 -0
- package/src/components/grid/grid.test.tsx +981 -0
- package/src/components/grid/grid.tsx +222 -0
- package/src/components/grid/grid.types.ts +344 -0
- package/src/components/icons/STYLES.mdx +56 -0
- package/src/components/images/STYLES.mdx +75 -0
- package/src/components/layout/STYLES.mdx +556 -0
- package/src/components/link/STYLES.mdx +75 -0
- package/src/components/list/STYLES.mdx +631 -0
- package/src/components/nav/STYLES.mdx +460 -0
- package/src/components/progress/STYLES.mdx +64 -0
- package/src/components/stack/README.mdx +400 -0
- package/src/components/stack/STYLES.mdx +414 -0
- package/src/components/stack/stack.scss +109 -0
- package/src/components/stack/stack.stories.tsx +559 -0
- package/src/components/stack/stack.test.tsx +426 -0
- package/src/components/stack/stack.tsx +141 -0
- package/src/components/stack/stack.types.ts +133 -0
- package/src/components/tag/STYLES.mdx +105 -0
- package/src/components/text-to-speech/STYLES.mdx +80 -0
- package/src/components/ui.tsx +3 -3
- package/src/index.scss +7 -2
- package/src/index.ts +305 -12
- package/src/sass/GLOBALS-STYLES.md +631 -0
- package/src/sass/_globals.scss +45 -24
- package/src/sass/_styles.scss +2 -2
- package/src/styles/box/box.css +220 -0
- package/src/styles/box/box.css.map +1 -0
- package/src/styles/cards/card.css +23 -17
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/cluster/cluster.css +71 -0
- package/src/styles/cluster/cluster.css.map +1 -0
- package/src/styles/grid/grid.css +238 -0
- package/src/styles/grid/grid.css.map +1 -0
- package/src/styles/index.css +668 -49
- package/src/styles/index.css.map +1 -1
- package/src/styles/stack/stack.css +86 -0
- package/src/styles/stack/stack.css.map +1 -0
- package/src/types/component-props.ts +42 -14
- package/src/types/layout-primitives.ts +48 -0
- package/src/types/shared.ts +10 -26
- package/libs/chunk-ENTCUJ3A.cjs +0 -13
- package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
- package/libs/chunk-HHLNOC5T.js +0 -7
- package/libs/chunk-HHLNOC5T.js.map +0 -1
- package/libs/chunk-KK47SYZI.js +0 -8
- package/libs/chunk-KK47SYZI.js.map +0 -1
- package/libs/chunk-W5TKWBFC.cjs +0 -18
- package/libs/chunk-W5TKWBFC.cjs.map +0 -1
- package/libs/component-props-67d978a2.d.ts +0 -38
- /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
- /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
- /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
- /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
- /package/libs/{chunk-L6PRDL6F.cjs.map → chunk-5CJPTDK3.cjs.map} +0 -0
- /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
- /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
- /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
- /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
- /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
- /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
- /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
- /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
- /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
- /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
- /package/libs/{chunk-MPTMPBFT.js.map → chunk-M7JLT62Q.js.map} +0 -0
- /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
- /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
- /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
- /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
- /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
- /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
- /package/libs/{chunk-EE3ZWSBY.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
- /package/libs/{chunk-TPIB3RQP.js.map → chunk-ZF6Y7W57.js.map} +0 -0
|
@@ -0,0 +1,981 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import { Grid, GridItem } from "./grid";
|
|
5
|
+
import type { GridProps, GridItemProps } from "./grid.types";
|
|
6
|
+
|
|
7
|
+
describe("Grid Component", () => {
|
|
8
|
+
describe("Rendering", () => {
|
|
9
|
+
it("should render with default props", () => {
|
|
10
|
+
render(<Grid data-testid="grid">Content</Grid>);
|
|
11
|
+
const grid = screen.getByTestId("grid");
|
|
12
|
+
expect(grid).toBeInTheDocument();
|
|
13
|
+
expect(grid.tagName).toBe("DIV");
|
|
14
|
+
expect(grid).toHaveClass("grid");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should render children correctly", () => {
|
|
18
|
+
render(
|
|
19
|
+
<Grid>
|
|
20
|
+
<div>Item 1</div>
|
|
21
|
+
<div>Item 2</div>
|
|
22
|
+
<div>Item 3</div>
|
|
23
|
+
</Grid>
|
|
24
|
+
);
|
|
25
|
+
expect(screen.getByText("Item 1")).toBeInTheDocument();
|
|
26
|
+
expect(screen.getByText("Item 2")).toBeInTheDocument();
|
|
27
|
+
expect(screen.getByText("Item 3")).toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should render with text content", () => {
|
|
31
|
+
render(<Grid>Plain text content</Grid>);
|
|
32
|
+
expect(screen.getByText("Plain text content")).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should render with Grid.Item children", () => {
|
|
36
|
+
render(
|
|
37
|
+
<Grid>
|
|
38
|
+
<GridItem>Item 1</GridItem>
|
|
39
|
+
<GridItem>Item 2</GridItem>
|
|
40
|
+
</Grid>
|
|
41
|
+
);
|
|
42
|
+
expect(screen.getByText("Item 1")).toBeInTheDocument();
|
|
43
|
+
expect(screen.getByText("Item 2")).toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("Polymorphic Rendering (as prop)", () => {
|
|
48
|
+
it("should render as div by default", () => {
|
|
49
|
+
render(<Grid data-testid="grid">Content</Grid>);
|
|
50
|
+
expect(screen.getByTestId("grid").tagName).toBe("DIV");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should render as section when as='section'", () => {
|
|
54
|
+
render(
|
|
55
|
+
<Grid as="section" data-testid="grid">
|
|
56
|
+
Content
|
|
57
|
+
</Grid>
|
|
58
|
+
);
|
|
59
|
+
expect(screen.getByTestId("grid").tagName).toBe("SECTION");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should render as article when as='article'", () => {
|
|
63
|
+
render(
|
|
64
|
+
<Grid as="article" data-testid="grid">
|
|
65
|
+
Content
|
|
66
|
+
</Grid>
|
|
67
|
+
);
|
|
68
|
+
expect(screen.getByTestId("grid").tagName).toBe("ARTICLE");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should render as ul when as='ul'", () => {
|
|
72
|
+
render(
|
|
73
|
+
<Grid as="ul" data-testid="grid">
|
|
74
|
+
<li>Item 1</li>
|
|
75
|
+
</Grid>
|
|
76
|
+
);
|
|
77
|
+
expect(screen.getByTestId("grid").tagName).toBe("UL");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should render as ol when as='ol'", () => {
|
|
81
|
+
render(
|
|
82
|
+
<Grid as="ol" data-testid="grid">
|
|
83
|
+
<li>Item 1</li>
|
|
84
|
+
</Grid>
|
|
85
|
+
);
|
|
86
|
+
expect(screen.getByTestId("grid").tagName).toBe("OL");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("Columns Prop", () => {
|
|
91
|
+
it("should apply columns=1 class", () => {
|
|
92
|
+
render(
|
|
93
|
+
<Grid columns={1} data-testid="grid">
|
|
94
|
+
Content
|
|
95
|
+
</Grid>
|
|
96
|
+
);
|
|
97
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-1");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should apply columns=2 class", () => {
|
|
101
|
+
render(
|
|
102
|
+
<Grid columns={2} data-testid="grid">
|
|
103
|
+
Content
|
|
104
|
+
</Grid>
|
|
105
|
+
);
|
|
106
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-2");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("should apply columns=3 class", () => {
|
|
110
|
+
render(
|
|
111
|
+
<Grid columns={3} data-testid="grid">
|
|
112
|
+
Content
|
|
113
|
+
</Grid>
|
|
114
|
+
);
|
|
115
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-3");
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("should apply columns=4 class", () => {
|
|
119
|
+
render(
|
|
120
|
+
<Grid columns={4} data-testid="grid">
|
|
121
|
+
Content
|
|
122
|
+
</Grid>
|
|
123
|
+
);
|
|
124
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-4");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should apply columns=6 class", () => {
|
|
128
|
+
render(
|
|
129
|
+
<Grid columns={6} data-testid="grid">
|
|
130
|
+
Content
|
|
131
|
+
</Grid>
|
|
132
|
+
);
|
|
133
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-6");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("should apply columns=12 class", () => {
|
|
137
|
+
render(
|
|
138
|
+
<Grid columns={12} data-testid="grid">
|
|
139
|
+
Content
|
|
140
|
+
</Grid>
|
|
141
|
+
);
|
|
142
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-12");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should work without columns prop", () => {
|
|
146
|
+
render(<Grid data-testid="grid">Content</Grid>);
|
|
147
|
+
const grid = screen.getByTestId("grid");
|
|
148
|
+
expect(grid).toHaveClass("grid");
|
|
149
|
+
expect(grid).not.toHaveClass("grid-cols-1");
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("Auto Prop (Auto-Fit/Auto-Fill)", () => {
|
|
154
|
+
it("should apply auto='fit' class", () => {
|
|
155
|
+
render(
|
|
156
|
+
<Grid auto="fit" minColumnWidth="15rem" data-testid="grid">
|
|
157
|
+
Content
|
|
158
|
+
</Grid>
|
|
159
|
+
);
|
|
160
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-auto-fit");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("should apply auto='fill' class", () => {
|
|
164
|
+
render(
|
|
165
|
+
<Grid auto="fill" minColumnWidth="15rem" data-testid="grid">
|
|
166
|
+
Content
|
|
167
|
+
</Grid>
|
|
168
|
+
);
|
|
169
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-auto-fill");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("should apply inline style with auto='fit'", () => {
|
|
173
|
+
render(
|
|
174
|
+
<Grid auto="fit" minColumnWidth="15rem" data-testid="grid">
|
|
175
|
+
Content
|
|
176
|
+
</Grid>
|
|
177
|
+
);
|
|
178
|
+
const grid = screen.getByTestId("grid");
|
|
179
|
+
expect(grid).toHaveStyle({
|
|
180
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))",
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should apply inline style with auto='fill'", () => {
|
|
185
|
+
render(
|
|
186
|
+
<Grid auto="fill" minColumnWidth="20rem" data-testid="grid">
|
|
187
|
+
Content
|
|
188
|
+
</Grid>
|
|
189
|
+
);
|
|
190
|
+
const grid = screen.getByTestId("grid");
|
|
191
|
+
expect(grid).toHaveStyle({
|
|
192
|
+
gridTemplateColumns: "repeat(auto-fill, minmax(20rem, 1fr))",
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe("Gap Prop", () => {
|
|
198
|
+
it("should apply gap='0' class", () => {
|
|
199
|
+
render(
|
|
200
|
+
<Grid gap="0" data-testid="grid">
|
|
201
|
+
Content
|
|
202
|
+
</Grid>
|
|
203
|
+
);
|
|
204
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-0");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("should apply gap='xs' class", () => {
|
|
208
|
+
render(
|
|
209
|
+
<Grid gap="xs" data-testid="grid">
|
|
210
|
+
Content
|
|
211
|
+
</Grid>
|
|
212
|
+
);
|
|
213
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-xs");
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should apply gap='sm' class", () => {
|
|
217
|
+
render(
|
|
218
|
+
<Grid gap="sm" data-testid="grid">
|
|
219
|
+
Content
|
|
220
|
+
</Grid>
|
|
221
|
+
);
|
|
222
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-sm");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("should apply gap='md' class", () => {
|
|
226
|
+
render(
|
|
227
|
+
<Grid gap="md" data-testid="grid">
|
|
228
|
+
Content
|
|
229
|
+
</Grid>
|
|
230
|
+
);
|
|
231
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-md");
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should apply gap='lg' class", () => {
|
|
235
|
+
render(
|
|
236
|
+
<Grid gap="lg" data-testid="grid">
|
|
237
|
+
Content
|
|
238
|
+
</Grid>
|
|
239
|
+
);
|
|
240
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-lg");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should apply gap='xl' class", () => {
|
|
244
|
+
render(
|
|
245
|
+
<Grid gap="xl" data-testid="grid">
|
|
246
|
+
Content
|
|
247
|
+
</Grid>
|
|
248
|
+
);
|
|
249
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-xl");
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe("GapX and GapY Props", () => {
|
|
254
|
+
it("should apply gapX='md' class", () => {
|
|
255
|
+
render(
|
|
256
|
+
<Grid gapX="md" data-testid="grid">
|
|
257
|
+
Content
|
|
258
|
+
</Grid>
|
|
259
|
+
);
|
|
260
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-x-md");
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("should apply gapY='lg' class", () => {
|
|
264
|
+
render(
|
|
265
|
+
<Grid gapY="lg" data-testid="grid">
|
|
266
|
+
Content
|
|
267
|
+
</Grid>
|
|
268
|
+
);
|
|
269
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-gap-y-lg");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("should apply both gapX and gapY together", () => {
|
|
273
|
+
render(
|
|
274
|
+
<Grid gapX="xl" gapY="xs" data-testid="grid">
|
|
275
|
+
Content
|
|
276
|
+
</Grid>
|
|
277
|
+
);
|
|
278
|
+
const grid = screen.getByTestId("grid");
|
|
279
|
+
expect(grid).toHaveClass("grid-gap-x-xl");
|
|
280
|
+
expect(grid).toHaveClass("grid-gap-y-xs");
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("should work with gap and gapX/gapY together", () => {
|
|
284
|
+
render(
|
|
285
|
+
<Grid gap="md" gapX="lg" data-testid="grid">
|
|
286
|
+
Content
|
|
287
|
+
</Grid>
|
|
288
|
+
);
|
|
289
|
+
const grid = screen.getByTestId("grid");
|
|
290
|
+
expect(grid).toHaveClass("grid-gap-md");
|
|
291
|
+
expect(grid).toHaveClass("grid-gap-x-lg");
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
describe("JustifyItems Prop", () => {
|
|
296
|
+
it("should apply justifyItems='start' class", () => {
|
|
297
|
+
render(
|
|
298
|
+
<Grid justifyItems="start" data-testid="grid">
|
|
299
|
+
Content
|
|
300
|
+
</Grid>
|
|
301
|
+
);
|
|
302
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-justify-items-start");
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("should apply justifyItems='center' class", () => {
|
|
306
|
+
render(
|
|
307
|
+
<Grid justifyItems="center" data-testid="grid">
|
|
308
|
+
Content
|
|
309
|
+
</Grid>
|
|
310
|
+
);
|
|
311
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-justify-items-center");
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("should apply justifyItems='end' class", () => {
|
|
315
|
+
render(
|
|
316
|
+
<Grid justifyItems="end" data-testid="grid">
|
|
317
|
+
Content
|
|
318
|
+
</Grid>
|
|
319
|
+
);
|
|
320
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-justify-items-end");
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("should apply justifyItems='stretch' class", () => {
|
|
324
|
+
render(
|
|
325
|
+
<Grid justifyItems="stretch" data-testid="grid">
|
|
326
|
+
Content
|
|
327
|
+
</Grid>
|
|
328
|
+
);
|
|
329
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-justify-items-stretch");
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe("AlignItems Prop", () => {
|
|
334
|
+
it("should apply alignItems='start' class", () => {
|
|
335
|
+
render(
|
|
336
|
+
<Grid alignItems="start" data-testid="grid">
|
|
337
|
+
Content
|
|
338
|
+
</Grid>
|
|
339
|
+
);
|
|
340
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-align-items-start");
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it("should apply alignItems='center' class", () => {
|
|
344
|
+
render(
|
|
345
|
+
<Grid alignItems="center" data-testid="grid">
|
|
346
|
+
Content
|
|
347
|
+
</Grid>
|
|
348
|
+
);
|
|
349
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-align-items-center");
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it("should apply alignItems='end' class", () => {
|
|
353
|
+
render(
|
|
354
|
+
<Grid alignItems="end" data-testid="grid">
|
|
355
|
+
Content
|
|
356
|
+
</Grid>
|
|
357
|
+
);
|
|
358
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-align-items-end");
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it("should apply alignItems='stretch' class", () => {
|
|
362
|
+
render(
|
|
363
|
+
<Grid alignItems="stretch" data-testid="grid">
|
|
364
|
+
Content
|
|
365
|
+
</Grid>
|
|
366
|
+
);
|
|
367
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-align-items-stretch");
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe("Combined Props", () => {
|
|
372
|
+
it("should apply columns and gap together", () => {
|
|
373
|
+
render(
|
|
374
|
+
<Grid columns={3} gap="md" data-testid="grid">
|
|
375
|
+
Content
|
|
376
|
+
</Grid>
|
|
377
|
+
);
|
|
378
|
+
const grid = screen.getByTestId("grid");
|
|
379
|
+
expect(grid).toHaveClass("grid");
|
|
380
|
+
expect(grid).toHaveClass("grid-cols-3");
|
|
381
|
+
expect(grid).toHaveClass("grid-gap-md");
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("should apply all alignment props together", () => {
|
|
385
|
+
render(
|
|
386
|
+
<Grid columns={4} gap="lg" justifyItems="center" alignItems="center" data-testid="grid">
|
|
387
|
+
Content
|
|
388
|
+
</Grid>
|
|
389
|
+
);
|
|
390
|
+
const grid = screen.getByTestId("grid");
|
|
391
|
+
expect(grid).toHaveClass("grid-cols-4");
|
|
392
|
+
expect(grid).toHaveClass("grid-gap-lg");
|
|
393
|
+
expect(grid).toHaveClass("grid-justify-items-center");
|
|
394
|
+
expect(grid).toHaveClass("grid-align-items-center");
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it("should combine all props with polymorphic as prop", () => {
|
|
398
|
+
render(
|
|
399
|
+
<Grid
|
|
400
|
+
as="section"
|
|
401
|
+
columns={2}
|
|
402
|
+
gap="md"
|
|
403
|
+
justifyItems="start"
|
|
404
|
+
alignItems="stretch"
|
|
405
|
+
data-testid="grid"
|
|
406
|
+
>
|
|
407
|
+
Content
|
|
408
|
+
</Grid>
|
|
409
|
+
);
|
|
410
|
+
const grid = screen.getByTestId("grid");
|
|
411
|
+
expect(grid.tagName).toBe("SECTION");
|
|
412
|
+
expect(grid).toHaveClass("grid");
|
|
413
|
+
expect(grid).toHaveClass("grid-cols-2");
|
|
414
|
+
expect(grid).toHaveClass("grid-gap-md");
|
|
415
|
+
expect(grid).toHaveClass("grid-justify-items-start");
|
|
416
|
+
expect(grid).toHaveClass("grid-align-items-stretch");
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
describe("ClassName and Classes Props", () => {
|
|
421
|
+
it("should merge className prop with utility classes", () => {
|
|
422
|
+
render(
|
|
423
|
+
<Grid className="custom-class" data-testid="grid">
|
|
424
|
+
Content
|
|
425
|
+
</Grid>
|
|
426
|
+
);
|
|
427
|
+
const grid = screen.getByTestId("grid");
|
|
428
|
+
expect(grid).toHaveClass("grid");
|
|
429
|
+
expect(grid).toHaveClass("custom-class");
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
it("should merge classes prop with utility classes", () => {
|
|
433
|
+
render(
|
|
434
|
+
<Grid classes="another-class" data-testid="grid">
|
|
435
|
+
Content
|
|
436
|
+
</Grid>
|
|
437
|
+
);
|
|
438
|
+
const grid = screen.getByTestId("grid");
|
|
439
|
+
expect(grid).toHaveClass("grid");
|
|
440
|
+
expect(grid).toHaveClass("another-class");
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it("should merge both className and classes", () => {
|
|
444
|
+
render(
|
|
445
|
+
<Grid className="custom" classes="another" data-testid="grid">
|
|
446
|
+
Content
|
|
447
|
+
</Grid>
|
|
448
|
+
);
|
|
449
|
+
const grid = screen.getByTestId("grid");
|
|
450
|
+
expect(grid).toHaveClass("grid");
|
|
451
|
+
expect(grid).toHaveClass("custom");
|
|
452
|
+
expect(grid).toHaveClass("another");
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it("should merge custom classes with all utility classes", () => {
|
|
456
|
+
render(
|
|
457
|
+
<Grid
|
|
458
|
+
columns={3}
|
|
459
|
+
gap="md"
|
|
460
|
+
justifyItems="center"
|
|
461
|
+
className="custom"
|
|
462
|
+
classes="utility"
|
|
463
|
+
data-testid="grid"
|
|
464
|
+
>
|
|
465
|
+
Content
|
|
466
|
+
</Grid>
|
|
467
|
+
);
|
|
468
|
+
const grid = screen.getByTestId("grid");
|
|
469
|
+
expect(grid).toHaveClass("grid");
|
|
470
|
+
expect(grid).toHaveClass("grid-cols-3");
|
|
471
|
+
expect(grid).toHaveClass("grid-gap-md");
|
|
472
|
+
expect(grid).toHaveClass("grid-justify-items-center");
|
|
473
|
+
expect(grid).toHaveClass("custom");
|
|
474
|
+
expect(grid).toHaveClass("utility");
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
describe("Inline Styles", () => {
|
|
479
|
+
it("should apply inline styles via styles prop", () => {
|
|
480
|
+
render(
|
|
481
|
+
<Grid styles={{ maxWidth: "1200px" }} data-testid="grid">
|
|
482
|
+
Content
|
|
483
|
+
</Grid>
|
|
484
|
+
);
|
|
485
|
+
const grid = screen.getByTestId("grid");
|
|
486
|
+
expect(grid).toHaveStyle({ maxWidth: "1200px" });
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it("should apply inline styles via style prop", () => {
|
|
490
|
+
render(
|
|
491
|
+
<Grid style={{ border: "1px solid red" }} data-testid="grid">
|
|
492
|
+
Content
|
|
493
|
+
</Grid>
|
|
494
|
+
);
|
|
495
|
+
const grid = screen.getByTestId("grid");
|
|
496
|
+
expect(grid).toHaveStyle({ border: "1px solid red" });
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it("should merge style and styles props", () => {
|
|
500
|
+
render(
|
|
501
|
+
<Grid
|
|
502
|
+
style={{ border: "1px solid red" }}
|
|
503
|
+
styles={{ maxWidth: "1200px" }}
|
|
504
|
+
data-testid="grid"
|
|
505
|
+
>
|
|
506
|
+
Content
|
|
507
|
+
</Grid>
|
|
508
|
+
);
|
|
509
|
+
const grid = screen.getByTestId("grid");
|
|
510
|
+
expect(grid).toHaveStyle({
|
|
511
|
+
border: "1px solid red",
|
|
512
|
+
maxWidth: "1200px",
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
describe("Ref Forwarding", () => {
|
|
518
|
+
it("should forward ref to the underlying element", () => {
|
|
519
|
+
const ref = { current: null as HTMLDivElement | null };
|
|
520
|
+
render(
|
|
521
|
+
<Grid ref={ref} data-testid="grid">
|
|
522
|
+
Content
|
|
523
|
+
</Grid>
|
|
524
|
+
);
|
|
525
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
526
|
+
expect(ref.current).toBe(screen.getByTestId("grid"));
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it("should forward ref with polymorphic as prop", () => {
|
|
530
|
+
const ref = { current: null as HTMLElement | null };
|
|
531
|
+
render(
|
|
532
|
+
<Grid as="section" ref={ref} data-testid="grid">
|
|
533
|
+
Content
|
|
534
|
+
</Grid>
|
|
535
|
+
);
|
|
536
|
+
expect(ref.current).toBeInstanceOf(HTMLElement);
|
|
537
|
+
expect(ref.current?.tagName).toBe("SECTION");
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
describe("ARIA and Accessibility Attributes", () => {
|
|
542
|
+
it("should accept aria-label", () => {
|
|
543
|
+
render(
|
|
544
|
+
<Grid aria-label="Product grid" data-testid="grid">
|
|
545
|
+
Content
|
|
546
|
+
</Grid>
|
|
547
|
+
);
|
|
548
|
+
expect(screen.getByTestId("grid")).toHaveAttribute("aria-label", "Product grid");
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
it("should accept aria-labelledby", () => {
|
|
552
|
+
render(
|
|
553
|
+
<>
|
|
554
|
+
<h2 id="grid-title">Products</h2>
|
|
555
|
+
<Grid aria-labelledby="grid-title" data-testid="grid">
|
|
556
|
+
<div>Product 1</div>
|
|
557
|
+
</Grid>
|
|
558
|
+
</>
|
|
559
|
+
);
|
|
560
|
+
expect(screen.getByTestId("grid")).toHaveAttribute("aria-labelledby", "grid-title");
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
it("should accept role attribute", () => {
|
|
564
|
+
render(
|
|
565
|
+
<Grid role="list" data-testid="grid">
|
|
566
|
+
Content
|
|
567
|
+
</Grid>
|
|
568
|
+
);
|
|
569
|
+
expect(screen.getByTestId("grid")).toHaveAttribute("role", "list");
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
it("should accept data attributes", () => {
|
|
573
|
+
render(
|
|
574
|
+
<Grid data-testid="grid" data-component="product-grid">
|
|
575
|
+
Content
|
|
576
|
+
</Grid>
|
|
577
|
+
);
|
|
578
|
+
expect(screen.getByTestId("grid")).toHaveAttribute("data-component", "product-grid");
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it("should accept id attribute", () => {
|
|
582
|
+
render(
|
|
583
|
+
<Grid id="main-grid" data-testid="grid">
|
|
584
|
+
Content
|
|
585
|
+
</Grid>
|
|
586
|
+
);
|
|
587
|
+
expect(screen.getByTestId("grid")).toHaveAttribute("id", "main-grid");
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
describe("Edge Cases", () => {
|
|
592
|
+
it("should handle empty children", () => {
|
|
593
|
+
render(<Grid data-testid="grid" />);
|
|
594
|
+
expect(screen.getByTestId("grid")).toBeInTheDocument();
|
|
595
|
+
expect(screen.getByTestId("grid")).toBeEmptyDOMElement();
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
it("should handle null children", () => {
|
|
599
|
+
render(<Grid data-testid="grid">{null}</Grid>);
|
|
600
|
+
expect(screen.getByTestId("grid")).toBeInTheDocument();
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
it("should handle undefined children", () => {
|
|
604
|
+
render(<Grid data-testid="grid">{undefined}</Grid>);
|
|
605
|
+
expect(screen.getByTestId("grid")).toBeInTheDocument();
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
it("should handle false children (conditional rendering)", () => {
|
|
609
|
+
const shouldShow = false;
|
|
610
|
+
render(<Grid data-testid="grid">{shouldShow && <div>Hidden</div>}</Grid>);
|
|
611
|
+
expect(screen.getByTestId("grid")).toBeInTheDocument();
|
|
612
|
+
expect(screen.queryByText("Hidden")).not.toBeInTheDocument();
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
describe("Real-World Usage Patterns", () => {
|
|
617
|
+
it("should render 3-column card grid correctly", () => {
|
|
618
|
+
render(
|
|
619
|
+
<Grid columns={3} gap="md" data-testid="grid">
|
|
620
|
+
{[...Array(6)].map((_, i) => (
|
|
621
|
+
<div key={i} className="card">
|
|
622
|
+
Card {i + 1}
|
|
623
|
+
</div>
|
|
624
|
+
))}
|
|
625
|
+
</Grid>
|
|
626
|
+
);
|
|
627
|
+
const grid = screen.getByTestId("grid");
|
|
628
|
+
expect(grid).toHaveClass("grid-cols-3");
|
|
629
|
+
expect(grid).toHaveClass("grid-gap-md");
|
|
630
|
+
expect(screen.getByText("Card 1")).toBeInTheDocument();
|
|
631
|
+
expect(screen.getByText("Card 6")).toBeInTheDocument();
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
it("should render auto-fit responsive grid correctly", () => {
|
|
635
|
+
render(
|
|
636
|
+
<Grid auto="fit" minColumnWidth="15rem" gap="lg" data-testid="grid">
|
|
637
|
+
<div>Item 1</div>
|
|
638
|
+
<div>Item 2</div>
|
|
639
|
+
<div>Item 3</div>
|
|
640
|
+
</Grid>
|
|
641
|
+
);
|
|
642
|
+
const grid = screen.getByTestId("grid");
|
|
643
|
+
expect(grid).toHaveClass("grid-auto-fit");
|
|
644
|
+
expect(grid).toHaveStyle({
|
|
645
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))",
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it("should render form layout correctly", () => {
|
|
650
|
+
render(
|
|
651
|
+
<Grid columns={2} gap="md" data-testid="grid">
|
|
652
|
+
<label htmlFor="name">Name</label>
|
|
653
|
+
<input id="name" type="text" />
|
|
654
|
+
<label htmlFor="email">Email</label>
|
|
655
|
+
<input id="email" type="email" />
|
|
656
|
+
</Grid>
|
|
657
|
+
);
|
|
658
|
+
expect(screen.getByTestId("grid")).toHaveClass("grid-cols-2");
|
|
659
|
+
expect(screen.getByLabelText("Name")).toBeInTheDocument();
|
|
660
|
+
expect(screen.getByLabelText("Email")).toBeInTheDocument();
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
describe("TypeScript Type Safety", () => {
|
|
665
|
+
it("should accept valid GridProps", () => {
|
|
666
|
+
const props: GridProps = {
|
|
667
|
+
columns: 3,
|
|
668
|
+
gap: "md",
|
|
669
|
+
justifyItems: "center",
|
|
670
|
+
alignItems: "center",
|
|
671
|
+
as: "section",
|
|
672
|
+
className: "custom",
|
|
673
|
+
children: <div>Content</div>,
|
|
674
|
+
};
|
|
675
|
+
render(<Grid {...props} data-testid="grid" />);
|
|
676
|
+
expect(screen.getByTestId("grid")).toBeInTheDocument();
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it("should accept all column values (1-12)", () => {
|
|
680
|
+
const columns: GridProps["columns"][] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
|
681
|
+
columns.forEach((col, index) => {
|
|
682
|
+
render(
|
|
683
|
+
<Grid columns={col} data-testid={`grid-${index}`}>
|
|
684
|
+
Content
|
|
685
|
+
</Grid>
|
|
686
|
+
);
|
|
687
|
+
expect(screen.getByTestId(`grid-${index}`)).toHaveClass(`grid-cols-${col}`);
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
describe("GridItem Component", () => {
|
|
694
|
+
describe("Rendering", () => {
|
|
695
|
+
it("should render with default props", () => {
|
|
696
|
+
render(<GridItem data-testid="grid-item">Content</GridItem>);
|
|
697
|
+
const item = screen.getByTestId("grid-item");
|
|
698
|
+
expect(item).toBeInTheDocument();
|
|
699
|
+
expect(item.tagName).toBe("DIV");
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
it("should render children correctly", () => {
|
|
703
|
+
render(<GridItem>Item content</GridItem>);
|
|
704
|
+
expect(screen.getByText("Item content")).toBeInTheDocument();
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
describe("Polymorphic Rendering (as prop)", () => {
|
|
709
|
+
it("should render as div by default", () => {
|
|
710
|
+
render(<GridItem data-testid="grid-item">Content</GridItem>);
|
|
711
|
+
expect(screen.getByTestId("grid-item").tagName).toBe("DIV");
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it("should render as li when as='li'", () => {
|
|
715
|
+
render(
|
|
716
|
+
<GridItem as="li" data-testid="grid-item">
|
|
717
|
+
Content
|
|
718
|
+
</GridItem>
|
|
719
|
+
);
|
|
720
|
+
expect(screen.getByTestId("grid-item").tagName).toBe("LI");
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
it("should render as section when as='section'", () => {
|
|
724
|
+
render(
|
|
725
|
+
<GridItem as="section" data-testid="grid-item">
|
|
726
|
+
Content
|
|
727
|
+
</GridItem>
|
|
728
|
+
);
|
|
729
|
+
expect(screen.getByTestId("grid-item").tagName).toBe("SECTION");
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
it("should render as article when as='article'", () => {
|
|
733
|
+
render(
|
|
734
|
+
<GridItem as="article" data-testid="grid-item">
|
|
735
|
+
Content
|
|
736
|
+
</GridItem>
|
|
737
|
+
);
|
|
738
|
+
expect(screen.getByTestId("grid-item").tagName).toBe("ARTICLE");
|
|
739
|
+
});
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
describe("Span Prop (Column Span)", () => {
|
|
743
|
+
it("should apply span=1 class", () => {
|
|
744
|
+
render(
|
|
745
|
+
<GridItem span={1} data-testid="grid-item">
|
|
746
|
+
Content
|
|
747
|
+
</GridItem>
|
|
748
|
+
);
|
|
749
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-1");
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it("should apply span=2 class", () => {
|
|
753
|
+
render(
|
|
754
|
+
<GridItem span={2} data-testid="grid-item">
|
|
755
|
+
Content
|
|
756
|
+
</GridItem>
|
|
757
|
+
);
|
|
758
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-2");
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
it("should apply span=4 class", () => {
|
|
762
|
+
render(
|
|
763
|
+
<GridItem span={4} data-testid="grid-item">
|
|
764
|
+
Content
|
|
765
|
+
</GridItem>
|
|
766
|
+
);
|
|
767
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-4");
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
it("should apply span=6 class", () => {
|
|
771
|
+
render(
|
|
772
|
+
<GridItem span={6} data-testid="grid-item">
|
|
773
|
+
Content
|
|
774
|
+
</GridItem>
|
|
775
|
+
);
|
|
776
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-6");
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
it("should apply span=8 class", () => {
|
|
780
|
+
render(
|
|
781
|
+
<GridItem span={8} data-testid="grid-item">
|
|
782
|
+
Content
|
|
783
|
+
</GridItem>
|
|
784
|
+
);
|
|
785
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-8");
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
it("should apply span=12 class", () => {
|
|
789
|
+
render(
|
|
790
|
+
<GridItem span={12} data-testid="grid-item">
|
|
791
|
+
Content
|
|
792
|
+
</GridItem>
|
|
793
|
+
);
|
|
794
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-col-span-12");
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
it("should work without span prop", () => {
|
|
798
|
+
render(<GridItem data-testid="grid-item">Content</GridItem>);
|
|
799
|
+
const item = screen.getByTestId("grid-item");
|
|
800
|
+
expect(item).not.toHaveClass("grid-col-span-1");
|
|
801
|
+
});
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
describe("RowSpan Prop", () => {
|
|
805
|
+
it("should apply rowSpan=1 class", () => {
|
|
806
|
+
render(
|
|
807
|
+
<GridItem rowSpan={1} data-testid="grid-item">
|
|
808
|
+
Content
|
|
809
|
+
</GridItem>
|
|
810
|
+
);
|
|
811
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-row-span-1");
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
it("should apply rowSpan=2 class", () => {
|
|
815
|
+
render(
|
|
816
|
+
<GridItem rowSpan={2} data-testid="grid-item">
|
|
817
|
+
Content
|
|
818
|
+
</GridItem>
|
|
819
|
+
);
|
|
820
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-row-span-2");
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
it("should apply rowSpan=3 class", () => {
|
|
824
|
+
render(
|
|
825
|
+
<GridItem rowSpan={3} data-testid="grid-item">
|
|
826
|
+
Content
|
|
827
|
+
</GridItem>
|
|
828
|
+
);
|
|
829
|
+
expect(screen.getByTestId("grid-item")).toHaveClass("grid-row-span-3");
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
it("should work without rowSpan prop", () => {
|
|
833
|
+
render(<GridItem data-testid="grid-item">Content</GridItem>);
|
|
834
|
+
const item = screen.getByTestId("grid-item");
|
|
835
|
+
expect(item).not.toHaveClass("grid-row-span-1");
|
|
836
|
+
});
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
describe("Combined Span Props", () => {
|
|
840
|
+
it("should apply both span and rowSpan together", () => {
|
|
841
|
+
render(
|
|
842
|
+
<GridItem span={4} rowSpan={2} data-testid="grid-item">
|
|
843
|
+
Content
|
|
844
|
+
</GridItem>
|
|
845
|
+
);
|
|
846
|
+
const item = screen.getByTestId("grid-item");
|
|
847
|
+
expect(item).toHaveClass("grid-col-span-4");
|
|
848
|
+
expect(item).toHaveClass("grid-row-span-2");
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
it("should combine span with polymorphic as prop", () => {
|
|
852
|
+
render(
|
|
853
|
+
<GridItem as="article" span={6} data-testid="grid-item">
|
|
854
|
+
Content
|
|
855
|
+
</GridItem>
|
|
856
|
+
);
|
|
857
|
+
const item = screen.getByTestId("grid-item");
|
|
858
|
+
expect(item.tagName).toBe("ARTICLE");
|
|
859
|
+
expect(item).toHaveClass("grid-col-span-6");
|
|
860
|
+
});
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
describe("ClassName and Classes Props", () => {
|
|
864
|
+
it("should merge className prop with utility classes", () => {
|
|
865
|
+
render(
|
|
866
|
+
<GridItem className="custom-class" data-testid="grid-item">
|
|
867
|
+
Content
|
|
868
|
+
</GridItem>
|
|
869
|
+
);
|
|
870
|
+
const item = screen.getByTestId("grid-item");
|
|
871
|
+
expect(item).toHaveClass("custom-class");
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
it("should merge classes prop with utility classes", () => {
|
|
875
|
+
render(
|
|
876
|
+
<GridItem classes="another-class" data-testid="grid-item">
|
|
877
|
+
Content
|
|
878
|
+
</GridItem>
|
|
879
|
+
);
|
|
880
|
+
const item = screen.getByTestId("grid-item");
|
|
881
|
+
expect(item).toHaveClass("another-class");
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
it("should merge custom classes with span classes", () => {
|
|
885
|
+
render(
|
|
886
|
+
<GridItem span={4} className="custom" classes="utility" data-testid="grid-item">
|
|
887
|
+
Content
|
|
888
|
+
</GridItem>
|
|
889
|
+
);
|
|
890
|
+
const item = screen.getByTestId("grid-item");
|
|
891
|
+
expect(item).toHaveClass("grid-col-span-4");
|
|
892
|
+
expect(item).toHaveClass("custom");
|
|
893
|
+
expect(item).toHaveClass("utility");
|
|
894
|
+
});
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
describe("Ref Forwarding", () => {
|
|
898
|
+
it("should forward ref to the underlying element", () => {
|
|
899
|
+
const ref = { current: null as HTMLDivElement | null };
|
|
900
|
+
render(
|
|
901
|
+
<GridItem ref={ref} data-testid="grid-item">
|
|
902
|
+
Content
|
|
903
|
+
</GridItem>
|
|
904
|
+
);
|
|
905
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
906
|
+
expect(ref.current).toBe(screen.getByTestId("grid-item"));
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
it("should forward ref with polymorphic as prop", () => {
|
|
910
|
+
const ref = { current: null as HTMLElement | null };
|
|
911
|
+
render(
|
|
912
|
+
<GridItem as="article" ref={ref} data-testid="grid-item">
|
|
913
|
+
Content
|
|
914
|
+
</GridItem>
|
|
915
|
+
);
|
|
916
|
+
expect(ref.current).toBeInstanceOf(HTMLElement);
|
|
917
|
+
expect(ref.current?.tagName).toBe("ARTICLE");
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
describe("Grid with Grid.Item Integration", () => {
|
|
922
|
+
it("should render Grid with Grid.Item children", () => {
|
|
923
|
+
render(
|
|
924
|
+
<Grid columns={12} gap="md" data-testid="grid">
|
|
925
|
+
<GridItem span={8} data-testid="main">
|
|
926
|
+
Main content
|
|
927
|
+
</GridItem>
|
|
928
|
+
<GridItem span={4} data-testid="sidebar">
|
|
929
|
+
Sidebar
|
|
930
|
+
</GridItem>
|
|
931
|
+
</Grid>
|
|
932
|
+
);
|
|
933
|
+
|
|
934
|
+
const grid = screen.getByTestId("grid");
|
|
935
|
+
const main = screen.getByTestId("main");
|
|
936
|
+
const sidebar = screen.getByTestId("sidebar");
|
|
937
|
+
|
|
938
|
+
expect(grid).toHaveClass("grid-cols-12");
|
|
939
|
+
expect(main).toHaveClass("grid-col-span-8");
|
|
940
|
+
expect(sidebar).toHaveClass("grid-col-span-4");
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
it("should handle mixed Grid.Item and regular children", () => {
|
|
944
|
+
render(
|
|
945
|
+
<Grid columns={3} gap="md">
|
|
946
|
+
<GridItem span={2}>Spans 2 columns</GridItem>
|
|
947
|
+
<div>Regular div</div>
|
|
948
|
+
</Grid>
|
|
949
|
+
);
|
|
950
|
+
|
|
951
|
+
expect(screen.getByText("Spans 2 columns")).toBeInTheDocument();
|
|
952
|
+
expect(screen.getByText("Regular div")).toBeInTheDocument();
|
|
953
|
+
});
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
describe("TypeScript Type Safety", () => {
|
|
957
|
+
it("should accept valid GridItemProps", () => {
|
|
958
|
+
const props: GridItemProps = {
|
|
959
|
+
span: 4,
|
|
960
|
+
rowSpan: 2,
|
|
961
|
+
as: "article",
|
|
962
|
+
className: "custom",
|
|
963
|
+
children: <div>Content</div>,
|
|
964
|
+
};
|
|
965
|
+
render(<GridItem {...props} data-testid="grid-item" />);
|
|
966
|
+
expect(screen.getByTestId("grid-item")).toBeInTheDocument();
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
it("should accept all span values (1-12)", () => {
|
|
970
|
+
const spans: GridItemProps["span"][] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
|
971
|
+
spans.forEach((span, index) => {
|
|
972
|
+
render(
|
|
973
|
+
<GridItem span={span} data-testid={`item-${index}`}>
|
|
974
|
+
Content
|
|
975
|
+
</GridItem>
|
|
976
|
+
);
|
|
977
|
+
expect(screen.getByTestId(`item-${index}`)).toHaveClass(`grid-col-span-${span}`);
|
|
978
|
+
});
|
|
979
|
+
});
|
|
980
|
+
});
|
|
981
|
+
});
|