@windstream/react-shared-components 0.1.93 → 0.1.95

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.
Files changed (112) hide show
  1. package/dist/contentful/index.esm.js +2 -2
  2. package/dist/contentful/index.esm.js.map +1 -1
  3. package/dist/contentful/index.js +3 -3
  4. package/dist/contentful/index.js.map +1 -1
  5. package/dist/core.d.ts +2 -2
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.esm.js +1 -1
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +3 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/styles.css +1 -1
  12. package/dist/utils/index.esm.js +1 -1
  13. package/dist/utils/index.js +1 -1
  14. package/package.json +14 -8
  15. package/src/components/accordion/index.test.tsx +270 -0
  16. package/src/components/alert-card/index.test.tsx +152 -0
  17. package/src/components/animation-wrapper/index.test.tsx +424 -0
  18. package/src/components/brand-button/index.test.tsx +292 -0
  19. package/src/components/button/index.test.tsx +91 -0
  20. package/src/components/call-button/index.test.tsx +260 -0
  21. package/src/components/checkbox/index.test.tsx +252 -0
  22. package/src/components/checklist/index.test.tsx +231 -0
  23. package/src/components/checklist/index.tsx +64 -29
  24. package/src/components/checklist/types.ts +7 -1
  25. package/src/components/collapse/index.test.tsx +277 -0
  26. package/src/components/collapse/index.tsx +1 -0
  27. package/src/components/divider/index.test.tsx +53 -0
  28. package/src/components/image/index.test.tsx +174 -0
  29. package/src/components/input/index.test.tsx +348 -0
  30. package/src/components/link/index.test.tsx +199 -0
  31. package/src/components/list/index.test.tsx +166 -0
  32. package/src/components/material-icon/index.test.tsx +130 -0
  33. package/src/components/modal/index.test.tsx +310 -0
  34. package/src/components/next-image/index.test.tsx +406 -0
  35. package/src/components/pagination/index.test.tsx +521 -0
  36. package/src/components/radio-button/index.test.tsx +151 -0
  37. package/src/components/see-more/index.test.tsx +96 -0
  38. package/src/components/select/index.test.tsx +256 -0
  39. package/src/components/select-plan-button/index.test.tsx +173 -0
  40. package/src/components/skeleton/index.test.tsx +74 -0
  41. package/src/components/spinner/index.test.tsx +76 -0
  42. package/src/components/text/index.test.tsx +65 -0
  43. package/src/components/tooltip/index.test.tsx +50 -0
  44. package/src/components/view-cart-button/index.test.tsx +57 -0
  45. package/src/contentful/blocks/accordion/index.test.tsx +218 -0
  46. package/src/contentful/blocks/accordion/index.tsx +3 -1
  47. package/src/contentful/blocks/address-input-banner/index.test.tsx +132 -0
  48. package/src/contentful/blocks/anchored-bottom-banner/index.test.tsx +287 -0
  49. package/src/contentful/blocks/blogs-grid/BlogGrid.stories.tsx +5 -4
  50. package/src/contentful/blocks/blogs-grid/index.test.tsx +355 -0
  51. package/src/contentful/blocks/blogs-grid-base/index.test.tsx +274 -0
  52. package/src/contentful/blocks/breadcrumbs/index.test.tsx +281 -0
  53. package/src/contentful/blocks/button/index.test.tsx +339 -0
  54. package/src/contentful/blocks/callout/index.test.tsx +539 -0
  55. package/src/contentful/blocks/cards/blog-card/index.test.tsx +218 -0
  56. package/src/contentful/blocks/cards/floating-image-card/index.test.tsx +201 -0
  57. package/src/contentful/blocks/cards/full-image-card/index.test.tsx +216 -0
  58. package/src/contentful/blocks/cards/index.test.tsx +39 -0
  59. package/src/contentful/blocks/cards/product-card/index.test.tsx +263 -0
  60. package/src/contentful/blocks/cards/simple-card/index.test.tsx +364 -0
  61. package/src/contentful/blocks/cards/simple-card/index.tsx +1 -1
  62. package/src/contentful/blocks/cards/testimonial-card/index.test.tsx +180 -0
  63. package/src/contentful/blocks/carousel/helper.test.tsx +539 -0
  64. package/src/contentful/blocks/carousel/index.test.tsx +308 -0
  65. package/src/contentful/blocks/carousel/types.test.ts +16 -0
  66. package/src/contentful/blocks/cart-retention-banner/index.test.tsx +409 -0
  67. package/src/contentful/blocks/cart-retention-banner/index.tsx +4 -4
  68. package/src/contentful/blocks/comparison-table/index.test.tsx +114 -0
  69. package/src/contentful/blocks/cookiebanner/index.test.tsx +277 -0
  70. package/src/contentful/blocks/cta-callout/index.test.tsx +244 -0
  71. package/src/contentful/blocks/dynamic-tabs/index.test.tsx +240 -0
  72. package/src/contentful/blocks/email-input-block/index.test.tsx +213 -0
  73. package/src/contentful/blocks/email-input-block/index.tsx +40 -35
  74. package/src/contentful/blocks/find-kinetic/index.test.tsx +269 -0
  75. package/src/contentful/blocks/floating-banner/index.test.tsx +246 -0
  76. package/src/contentful/blocks/footer/index.test.tsx +302 -0
  77. package/src/contentful/blocks/image-promo-bar/helper.test.tsx +61 -0
  78. package/src/contentful/blocks/image-promo-bar/index.test.tsx +467 -0
  79. package/src/contentful/blocks/image-promo-bar/index.tsx +248 -246
  80. package/src/contentful/blocks/image-promo-bar/vimeo-embed.test.tsx +142 -0
  81. package/src/contentful/blocks/image-promo-bar/youtube-embed.test.tsx +104 -0
  82. package/src/contentful/blocks/modal/index.test.tsx +209 -0
  83. package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.test.tsx +208 -0
  84. package/src/contentful/blocks/navigation/index.test.tsx +924 -0
  85. package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.test.tsx +131 -0
  86. package/src/contentful/blocks/primary-hero/index.test.tsx +286 -0
  87. package/src/contentful/blocks/primary-hero/index.tsx +7 -4
  88. package/src/contentful/blocks/search-block/index.test.tsx +268 -0
  89. package/src/contentful/blocks/shape-background-wrapper/index.test.tsx +284 -0
  90. package/src/contentful/blocks/text/index.test.tsx +36 -0
  91. package/src/contentful/index.test.ts +45 -0
  92. package/src/global-mocks/contentful/to-document.ts +25 -0
  93. package/src/global-mocks/cookie.ts +48 -0
  94. package/src/global-mocks/cx.ts +37 -0
  95. package/src/global-mocks/index.ts +89 -0
  96. package/src/global-mocks/speed-card-bg.ts +27 -0
  97. package/src/global-mocks/utm.ts +49 -0
  98. package/src/hooks/contentful/use-contentful-rich-text.test.tsx +1758 -0
  99. package/src/hooks/contentful/use-contentful-rich-text.tsx +1 -1
  100. package/src/hooks/contentful/use-processed-check-list.test.tsx +277 -0
  101. package/src/hooks/use-body-scroll-lock.test.ts +134 -0
  102. package/src/hooks/use-carousel-swipe.test.ts +393 -0
  103. package/src/hooks/use-outside-click.test.ts +142 -0
  104. package/src/index.ts +1 -1
  105. package/src/next/index.test.ts +7 -0
  106. package/src/setupTests.ts +17 -11
  107. package/src/utils/contentful/to-document.test.ts +85 -0
  108. package/src/utils/cookie.test.ts +180 -0
  109. package/src/utils/cx.test.ts +90 -0
  110. package/src/utils/index.test.ts +115 -0
  111. package/src/utils/speed-card-bg.test.ts +46 -0
  112. package/src/utils/utm.test.ts +359 -0
@@ -0,0 +1,180 @@
1
+ import {
2
+ getCookie,
3
+ getParsedCookie,
4
+ getUTMs,
5
+ removeUTMs,
6
+ setCookie,
7
+ setUTMs,
8
+ } from "./cookie";
9
+ import { Base64 } from "js-base64";
10
+ import Cookies from "js-cookie";
11
+
12
+ jest.mock("js-cookie");
13
+
14
+ const mockCookiesGet = Cookies.get as jest.Mock;
15
+ const mockCookiesSet = Cookies.set as jest.Mock;
16
+ const mockCookiesRemove = Cookies.remove as jest.Mock;
17
+
18
+ describe("cookie utilities", () => {
19
+ afterEach(() => {
20
+ mockCookiesGet.mockReset();
21
+ mockCookiesSet.mockReset();
22
+ mockCookiesRemove.mockReset();
23
+ });
24
+
25
+ // ── getUTMs ──────────────────────────────────────────
26
+ describe("getUTMs", () => {
27
+ it("returns null when window is undefined", () => {
28
+ const origWindow = globalThis.window;
29
+ // @ts-expect-error - intentionally deleting window
30
+ delete globalThis.window;
31
+ expect(getUTMs()).toBeNull();
32
+ globalThis.window = origWindow;
33
+ });
34
+
35
+ it("returns null when cookie does not exist", () => {
36
+ mockCookiesGet.mockReturnValue(undefined as any);
37
+ expect(getUTMs()).toBeNull();
38
+ expect(mockCookiesGet).toHaveBeenCalledWith("utm_parameters");
39
+ });
40
+
41
+ it("decodes and parses a valid Base64 cookie", () => {
42
+ const utms = { utm_source: "google", utm_medium: "cpc" };
43
+ const encoded = Base64.encode(JSON.stringify(utms));
44
+ mockCookiesGet.mockReturnValue(encoded as any);
45
+
46
+ expect(getUTMs()).toEqual(utms);
47
+ });
48
+
49
+ it("returns null for an invalid Base64/JSON cookie", () => {
50
+ mockCookiesGet.mockReturnValue("not-valid-base64!!!" as any);
51
+ expect(getUTMs()).toBeNull();
52
+ });
53
+ });
54
+
55
+ // ── setUTMs ──────────────────────────────────────────
56
+ describe("setUTMs", () => {
57
+ it("returns early when window is undefined", () => {
58
+ const origWindow = globalThis.window;
59
+ // @ts-expect-error - intentionally deleting window
60
+ delete globalThis.window;
61
+ setUTMs({ utm_source: "test" });
62
+ expect(mockCookiesSet).not.toHaveBeenCalled();
63
+ globalThis.window = origWindow;
64
+ });
65
+
66
+ it("encodes UTMs to Base64 and sets cookie with default domain", () => {
67
+ const utms = { utm_source: "google" };
68
+ setUTMs(utms);
69
+
70
+ const expectedEncoded = Base64.encode(JSON.stringify(utms));
71
+ expect(mockCookiesSet).toHaveBeenCalledWith(
72
+ "utm_parameters",
73
+ expectedEncoded,
74
+ { domain: ".gokinetic.com", path: "/", sameSite: "Lax" }
75
+ );
76
+ });
77
+
78
+ it("accepts a custom domain", () => {
79
+ setUTMs({ utm_source: "bing" }, ".custom.com");
80
+ expect(mockCookiesSet).toHaveBeenCalledWith(
81
+ "utm_parameters",
82
+ expect.any(String),
83
+ { domain: ".custom.com", path: "/", sameSite: "Lax" }
84
+ );
85
+ });
86
+ });
87
+
88
+ // ── removeUTMs ───────────────────────────────────────
89
+ describe("removeUTMs", () => {
90
+ it("removes cookie with default domain", () => {
91
+ removeUTMs();
92
+ expect(mockCookiesRemove).toHaveBeenCalledWith("utm_parameters", {
93
+ domain: ".gokinetic.com",
94
+ path: "/",
95
+ });
96
+ });
97
+
98
+ it("removes cookie with custom domain", () => {
99
+ removeUTMs(".other.com");
100
+ expect(mockCookiesRemove).toHaveBeenCalledWith("utm_parameters", {
101
+ domain: ".other.com",
102
+ path: "/",
103
+ });
104
+ });
105
+ });
106
+
107
+ // ── getCookie ────────────────────────────────────────
108
+ describe("getCookie", () => {
109
+ it("returns empty string when window is undefined", () => {
110
+ const origWindow = globalThis.window;
111
+ // @ts-expect-error - intentionally deleting window
112
+ delete globalThis.window;
113
+ expect(getCookie("key")).toBe("");
114
+ globalThis.window = origWindow;
115
+ });
116
+
117
+ it("returns decoded value when cookie exists", () => {
118
+ const value = "hello world";
119
+ mockCookiesGet.mockReturnValue(Base64.encode(value) as any);
120
+ expect(getCookie("my_key")).toBe(value);
121
+ });
122
+
123
+ it("returns null when cookie does not exist", () => {
124
+ mockCookiesGet.mockReturnValue(undefined as any);
125
+ expect(getCookie("missing")).toBeNull();
126
+ });
127
+ });
128
+
129
+ // ── getParsedCookie ──────────────────────────────────
130
+ describe("getParsedCookie", () => {
131
+ it("returns parsed JSON from cookie", () => {
132
+ const obj = { foo: "bar", num: 42 };
133
+ mockCookiesGet.mockReturnValue(Base64.encode(JSON.stringify(obj)) as any);
134
+ expect(getParsedCookie("key")).toEqual(obj);
135
+ });
136
+
137
+ it("returns null when cookie is missing", () => {
138
+ mockCookiesGet.mockReturnValue(undefined as any);
139
+ expect(getParsedCookie("missing")).toBeNull();
140
+ });
141
+
142
+ it("returns null when cookie has invalid JSON", () => {
143
+ mockCookiesGet.mockReturnValue(Base64.encode("not json") as any);
144
+ expect(getParsedCookie("bad")).toBeNull();
145
+ });
146
+ });
147
+
148
+ // ── setCookie ────────────────────────────────────────
149
+ describe("setCookie", () => {
150
+ it("returns early when window is undefined", () => {
151
+ const origWindow = globalThis.window;
152
+ // @ts-expect-error - intentionally deleting window
153
+ delete globalThis.window;
154
+ setCookie("key", "value", {});
155
+ expect(mockCookiesSet).not.toHaveBeenCalled();
156
+ globalThis.window = origWindow;
157
+ });
158
+
159
+ it("encodes value to Base64 and sets cookie with options", () => {
160
+ const value = { plan: "fiber", speed: 500 };
161
+ const options = { domain: ".test.com", path: "/" };
162
+ setCookie("plan_data", value, options);
163
+
164
+ const expectedEncoded = Base64.encode(JSON.stringify(value));
165
+ expect(mockCookiesSet).toHaveBeenCalledWith(
166
+ "plan_data",
167
+ expectedEncoded,
168
+ options
169
+ );
170
+ });
171
+
172
+ it("handles string values", () => {
173
+ setCookie("simple", "hello", { path: "/" });
174
+ const expectedEncoded = Base64.encode(JSON.stringify("hello"));
175
+ expect(mockCookiesSet).toHaveBeenCalledWith("simple", expectedEncoded, {
176
+ path: "/",
177
+ });
178
+ });
179
+ });
180
+ });
@@ -0,0 +1,90 @@
1
+ import { clsx, cx } from "./cx";
2
+
3
+ describe("cx utility", () => {
4
+ describe("basic class merging", () => {
5
+ it("returns empty string for no arguments", () => {
6
+ expect(cx()).toBe("");
7
+ });
8
+
9
+ it("returns single class unchanged", () => {
10
+ expect(cx("text-red-500")).toBe("text-red-500");
11
+ });
12
+
13
+ it("combines multiple classes", () => {
14
+ const result = cx("p-4", "m-2", "bg-white");
15
+ expect(result).toContain("p-4");
16
+ expect(result).toContain("m-2");
17
+ expect(result).toContain("bg-white");
18
+ });
19
+ });
20
+
21
+ describe("Tailwind conflict resolution", () => {
22
+ it("resolves conflicting padding classes (last wins)", () => {
23
+ expect(cx("p-4", "p-8")).toBe("p-8");
24
+ });
25
+
26
+ it("resolves conflicting text color classes", () => {
27
+ expect(cx("text-red-500", "text-blue-500")).toBe("text-blue-500");
28
+ });
29
+
30
+ it("resolves conflicting margin classes", () => {
31
+ expect(cx("m-2", "m-6")).toBe("m-6");
32
+ });
33
+ });
34
+
35
+ describe("custom font-variants class group", () => {
36
+ it("resolves conflicting font variant classes", () => {
37
+ expect(cx("heading1", "body1")).toBe("body1");
38
+ });
39
+
40
+ it("resolves heading vs label variants", () => {
41
+ expect(cx("heading3", "label2")).toBe("label2");
42
+ });
43
+
44
+ it("keeps non-conflicting classes alongside font variants", () => {
45
+ const result = cx("heading1", "text-red-500", "body2");
46
+ expect(result).toContain("body2");
47
+ expect(result).toContain("text-red-500");
48
+ expect(result).not.toContain("heading1");
49
+ });
50
+ });
51
+
52
+ describe("custom button-sizes class group", () => {
53
+ it("resolves conflicting button size classes", () => {
54
+ expect(cx("btn-small", "btn-large")).toBe("btn-large");
55
+ });
56
+
57
+ it("resolves btn-medium vs btn-x-large", () => {
58
+ expect(cx("btn-medium", "btn-x-large")).toBe("btn-x-large");
59
+ });
60
+ });
61
+
62
+ describe("conditional and falsy values (via clsx)", () => {
63
+ it("filters out falsy values", () => {
64
+ expect(cx("p-4", false, null, undefined, 0, "", "m-2")).toBe("p-4 m-2");
65
+ });
66
+
67
+ it("supports conditional object syntax", () => {
68
+ expect(cx({ "bg-red-500": true, "bg-blue-500": false })).toBe(
69
+ "bg-red-500"
70
+ );
71
+ });
72
+
73
+ it("supports arrays", () => {
74
+ expect(cx(["p-2", "m-4"])).toBe("p-2 m-4");
75
+ });
76
+
77
+ it("supports mixed arguments", () => {
78
+ const result = cx("base", ["arr1"], { conditional: true }, undefined);
79
+ expect(result).toContain("base");
80
+ expect(result).toContain("arr1");
81
+ expect(result).toContain("conditional");
82
+ });
83
+ });
84
+
85
+ describe("exports", () => {
86
+ it("exports clsx function", () => {
87
+ expect(typeof clsx).toBe("function");
88
+ });
89
+ });
90
+ });
@@ -0,0 +1,115 @@
1
+ /**
2
+ * This test ensures all re-exports from the utils barrel file are resolved,
3
+ * which satisfies the function coverage requirement for the barrel module.
4
+ */
5
+ import {
6
+ buildPreservedQueryHref,
7
+ clsx,
8
+ combineExistingAndNewUTMs,
9
+ cx,
10
+ getCampaignProperties,
11
+ getCookie,
12
+ getOrganicTrafficUtmParameters,
13
+ getParsedCookie,
14
+ getUtmParametersFromURL,
15
+ getUTMs,
16
+ label1BoldOptions,
17
+ removeUTMs,
18
+ renderContentfulRichText,
19
+ renderContentfulRichTextTable,
20
+ setCookie,
21
+ setUTMs,
22
+ SpeedCardBg,
23
+ toDocument,
24
+ useContentfulRichText,
25
+ useProcessedChecklist,
26
+ UTM_PARAM_NAMES,
27
+ } from "./index";
28
+
29
+ describe("utils barrel exports", () => {
30
+ it("exports cx", () => {
31
+ expect(typeof cx).toBe("function");
32
+ });
33
+
34
+ it("exports clsx", () => {
35
+ expect(typeof clsx).toBe("function");
36
+ });
37
+
38
+ it("exports SpeedCardBg", () => {
39
+ expect(typeof SpeedCardBg).toBe("function");
40
+ });
41
+
42
+ it("exports getUTMs", () => {
43
+ expect(typeof getUTMs).toBe("function");
44
+ });
45
+
46
+ it("exports setUTMs", () => {
47
+ expect(typeof setUTMs).toBe("function");
48
+ });
49
+
50
+ it("exports removeUTMs", () => {
51
+ expect(typeof removeUTMs).toBe("function");
52
+ });
53
+
54
+ it("exports getCookie", () => {
55
+ expect(typeof getCookie).toBe("function");
56
+ });
57
+
58
+ it("exports getParsedCookie", () => {
59
+ expect(typeof getParsedCookie).toBe("function");
60
+ });
61
+
62
+ it("exports setCookie", () => {
63
+ expect(typeof setCookie).toBe("function");
64
+ });
65
+
66
+ it("exports getUtmParametersFromURL", () => {
67
+ expect(typeof getUtmParametersFromURL).toBe("function");
68
+ });
69
+
70
+ it("exports combineExistingAndNewUTMs", () => {
71
+ expect(typeof combineExistingAndNewUTMs).toBe("function");
72
+ });
73
+
74
+ it("exports getOrganicTrafficUtmParameters", () => {
75
+ expect(typeof getOrganicTrafficUtmParameters).toBe("function");
76
+ });
77
+
78
+ it("exports getCampaignProperties", () => {
79
+ expect(typeof getCampaignProperties).toBe("function");
80
+ });
81
+
82
+ it("exports buildPreservedQueryHref", () => {
83
+ expect(typeof buildPreservedQueryHref).toBe("function");
84
+ });
85
+
86
+ it("exports UTM_PARAM_NAMES", () => {
87
+ expect(UTM_PARAM_NAMES).toBeDefined();
88
+ expect(Array.isArray(UTM_PARAM_NAMES)).toBe(true);
89
+ });
90
+
91
+ it("exports toDocument", () => {
92
+ expect(typeof toDocument).toBe("function");
93
+ });
94
+
95
+ it("exports renderContentfulRichText", () => {
96
+ expect(typeof renderContentfulRichText).toBe("function");
97
+ });
98
+
99
+ it("exports useContentfulRichText", () => {
100
+ expect(typeof useContentfulRichText).toBe("function");
101
+ });
102
+
103
+ it("exports renderContentfulRichTextTable", () => {
104
+ expect(typeof renderContentfulRichTextTable).toBe("function");
105
+ });
106
+
107
+ it("exports useProcessedChecklist", () => {
108
+ expect(typeof useProcessedChecklist).toBe("function");
109
+ });
110
+
111
+ it("exports label1BoldOptions", () => {
112
+ expect(label1BoldOptions).toBeDefined();
113
+ expect(label1BoldOptions.renderMark).toBeDefined();
114
+ });
115
+ });
@@ -0,0 +1,46 @@
1
+ import SpeedCardBg, { SpeedCardBg as namedExport } from "./speed-card-bg";
2
+
3
+ describe("SpeedCardBg", () => {
4
+ it("returns a valid SVG string", () => {
5
+ const svg = SpeedCardBg();
6
+ expect(svg).toContain("<svg");
7
+ expect(svg).toContain("</svg>");
8
+ expect(svg).toContain('xmlns="http://www.w3.org/2000/svg"');
9
+ });
10
+
11
+ it("uses default color #24A76A when no argument provided", () => {
12
+ const svg = SpeedCardBg();
13
+ expect(svg).toContain('fill="#24A76A"');
14
+ expect(svg).not.toContain("${color}");
15
+ });
16
+
17
+ it("applies custom color to fill attributes", () => {
18
+ const svg = SpeedCardBg("#FF0000");
19
+ expect(svg).toContain('fill="#FF0000"');
20
+ expect(svg).not.toContain('fill="#24A76A"');
21
+ });
22
+
23
+ it("has correct SVG dimensions", () => {
24
+ const svg = SpeedCardBg();
25
+ expect(svg).toContain('width="684"');
26
+ expect(svg).toContain('height="107"');
27
+ expect(svg).toContain('viewBox="0 0 684 107"');
28
+ });
29
+
30
+ it("contains two path elements for the pinwheel", () => {
31
+ const svg = SpeedCardBg();
32
+ const pathMatches = svg.match(/<path /g);
33
+ expect(pathMatches).toHaveLength(2);
34
+ });
35
+
36
+ it("fills both paths with the provided color", () => {
37
+ const color = "#ABCDEF";
38
+ const svg = SpeedCardBg(color);
39
+ const fillMatches = svg.match(new RegExp(`fill="${color}"`, "g"));
40
+ expect(fillMatches).toHaveLength(2);
41
+ });
42
+
43
+ it("exports the same function as both default and named", () => {
44
+ expect(namedExport).toBe(SpeedCardBg);
45
+ });
46
+ });