@windstream/react-shared-components 0.1.93 → 0.1.94
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/README.md +635 -635
- package/dist/contentful/index.esm.js +3 -3
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +3 -3
- package/dist/contentful/index.js.map +1 -1
- package/dist/core.d.ts +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +13 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/next/index.esm.js +2 -2
- package/dist/next/index.esm.js.map +1 -1
- package/dist/next/index.js +2 -2
- package/dist/next/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/index.esm.js +1 -1
- package/dist/utils/index.esm.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +191 -185
- package/src/components/accordion/Accordion.stories.tsx +230 -230
- package/src/components/accordion/index.test.tsx +270 -0
- package/src/components/accordion/index.tsx +70 -70
- package/src/components/accordion/types.ts +12 -12
- package/src/components/alert-card/AlertCard.stories.tsx +171 -171
- package/src/components/alert-card/index.test.tsx +152 -0
- package/src/components/alert-card/index.tsx +41 -41
- package/src/components/alert-card/types.ts +13 -13
- package/src/components/animation-wrapper/index.test.tsx +424 -0
- package/src/components/animation-wrapper/index.tsx +129 -129
- package/src/components/animation-wrapper/types.ts +11 -11
- package/src/components/brand-button/BrandButton.stories.tsx +223 -223
- package/src/components/brand-button/helpers.ts +35 -35
- package/src/components/brand-button/index.test.tsx +292 -0
- package/src/components/brand-button/index.tsx +120 -120
- package/src/components/brand-button/types.ts +38 -38
- package/src/components/button/Button.stories.tsx +108 -108
- package/src/components/button/index.test.tsx +91 -0
- package/src/components/button/index.tsx +27 -27
- package/src/components/button/types.ts +14 -14
- package/src/components/call-button/CallButton.stories.tsx +324 -324
- package/src/components/call-button/index.test.tsx +260 -0
- package/src/components/call-button/index.tsx +106 -106
- package/src/components/call-button/types.ts +16 -16
- package/src/components/checkbox/Checkbox.stories.tsx +247 -247
- package/src/components/checkbox/index.test.tsx +252 -0
- package/src/components/checkbox/index.tsx +197 -197
- package/src/components/checkbox/types.ts +27 -27
- package/src/components/checklist/Checklist.stories.tsx +150 -150
- package/src/components/checklist/index.test.tsx +231 -0
- package/src/components/checklist/index.tsx +96 -61
- package/src/components/checklist/types.ts +23 -17
- package/src/components/collapse/Collapse.stories.tsx +255 -255
- package/src/components/collapse/index.test.tsx +277 -0
- package/src/components/collapse/index.tsx +47 -46
- package/src/components/collapse/types.ts +6 -6
- package/src/components/divider/Divider.stories.tsx +205 -205
- package/src/components/divider/index.test.tsx +53 -0
- package/src/components/divider/index.tsx +22 -22
- package/src/components/divider/type.ts +3 -3
- package/src/components/image/Image.stories.tsx +113 -113
- package/src/components/image/index.test.tsx +174 -0
- package/src/components/image/index.tsx +25 -25
- package/src/components/image/types.ts +40 -40
- package/src/components/input/Input.stories.tsx +325 -325
- package/src/components/input/index.test.tsx +348 -0
- package/src/components/input/index.tsx +177 -177
- package/src/components/input/types.ts +37 -37
- package/src/components/link/Link.stories.tsx +163 -163
- package/src/components/link/index.test.tsx +199 -0
- package/src/components/link/index.tsx +116 -116
- package/src/components/link/types.ts +25 -25
- package/src/components/list/List.stories.tsx +272 -272
- package/src/components/list/index.test.tsx +166 -0
- package/src/components/list/index.tsx +88 -88
- package/src/components/list/list-item/index.tsx +38 -38
- package/src/components/list/list-item/types.ts +13 -13
- package/src/components/list/types.ts +29 -29
- package/src/components/material-icon/MaterialIcon.stories.tsx +322 -322
- package/src/components/material-icon/constants.ts +99 -99
- package/src/components/material-icon/index.test.tsx +130 -0
- package/src/components/material-icon/index.tsx +47 -47
- package/src/components/material-icon/types.ts +31 -31
- package/src/components/modal/Modal.stories.tsx +171 -171
- package/src/components/modal/index.test.tsx +310 -0
- package/src/components/modal/index.tsx +164 -164
- package/src/components/modal/types.ts +24 -24
- package/src/components/next-image/index.test.tsx +406 -0
- package/src/components/next-image/index.tsx +74 -74
- package/src/components/next-image/types.ts +1 -1
- package/src/components/pagination/index.test.tsx +521 -0
- package/src/components/pagination/index.tsx +91 -91
- package/src/components/pagination/types.ts +6 -6
- package/src/components/radio-button/RadioButton.stories.tsx +307 -307
- package/src/components/radio-button/index.test.tsx +151 -0
- package/src/components/radio-button/index.tsx +75 -75
- package/src/components/radio-button/types.ts +21 -21
- package/src/components/see-more/SeeMore.stories.tsx +181 -181
- package/src/components/see-more/index.test.tsx +96 -0
- package/src/components/see-more/index.tsx +44 -44
- package/src/components/see-more/types.ts +4 -4
- package/src/components/select/Select.stories.tsx +411 -411
- package/src/components/select/index.test.tsx +256 -0
- package/src/components/select/index.tsx +155 -155
- package/src/components/select/types.ts +36 -36
- package/src/components/select-plan-button/SelectPlanButton.stories.tsx +184 -184
- package/src/components/select-plan-button/index.test.tsx +173 -0
- package/src/components/select-plan-button/index.tsx +63 -63
- package/src/components/select-plan-button/types.ts +17 -17
- package/src/components/skeleton/Skeleton.stories.tsx +179 -179
- package/src/components/skeleton/index.test.tsx +74 -0
- package/src/components/skeleton/index.tsx +61 -61
- package/src/components/skeleton/types.ts +4 -4
- package/src/components/spinner/Spinner.stories.tsx +335 -335
- package/src/components/spinner/index.test.tsx +76 -0
- package/src/components/spinner/index.tsx +44 -44
- package/src/components/spinner/types.ts +5 -5
- package/src/components/text/Text.stories.tsx +321 -321
- package/src/components/text/index.test.tsx +65 -0
- package/src/components/text/index.tsx +25 -25
- package/src/components/text/types.ts +45 -45
- package/src/components/tooltip/Tooltip.stories.tsx +219 -219
- package/src/components/tooltip/index.test.tsx +50 -0
- package/src/components/tooltip/index.tsx +74 -74
- package/src/components/tooltip/types.ts +7 -7
- package/src/components/view-cart-button/ViewCartButton.stories.tsx +252 -252
- package/src/components/view-cart-button/index.test.tsx +57 -0
- package/src/components/view-cart-button/index.tsx +42 -42
- package/src/components/view-cart-button/types.ts +5 -5
- package/src/contentful/blocks/accordion/Accordion.stories.mocks.tsx +128 -128
- package/src/contentful/blocks/accordion/Accordion.stories.tsx +98 -98
- package/src/contentful/blocks/accordion/index.test.tsx +218 -0
- package/src/contentful/blocks/accordion/index.tsx +114 -112
- package/src/contentful/blocks/accordion/types.ts +34 -34
- package/src/contentful/blocks/address-input-banner/index.test.tsx +132 -0
- package/src/contentful/blocks/address-input-banner/index.tsx +52 -52
- package/src/contentful/blocks/address-input-banner/types.ts +14 -14
- package/src/contentful/blocks/anchored-bottom-banner/index.test.tsx +287 -0
- package/src/contentful/blocks/anchored-bottom-banner/index.tsx +181 -181
- package/src/contentful/blocks/anchored-bottom-banner/types.ts +13 -13
- package/src/contentful/blocks/blogs-grid/BlogGrid.stories.mocks.tsx +144 -144
- package/src/contentful/blocks/blogs-grid/BlogGrid.stories.tsx +157 -156
- package/src/contentful/blocks/blogs-grid/index.test.tsx +355 -0
- package/src/contentful/blocks/blogs-grid/index.tsx +134 -134
- package/src/contentful/blocks/blogs-grid/types.ts +26 -26
- package/src/contentful/blocks/blogs-grid-base/index.test.tsx +274 -0
- package/src/contentful/blocks/blogs-grid-base/index.tsx +119 -119
- package/src/contentful/blocks/blogs-grid-base/types.ts +36 -36
- package/src/contentful/blocks/breadcrumbs/BreadcrumbNavigation.stories.tsx +147 -147
- package/src/contentful/blocks/breadcrumbs/index.test.tsx +281 -0
- package/src/contentful/blocks/breadcrumbs/index.tsx +95 -95
- package/src/contentful/blocks/breadcrumbs/types.ts +8 -8
- package/src/contentful/blocks/button/Button.stories.tsx +40 -40
- package/src/contentful/blocks/button/index.test.tsx +339 -0
- package/src/contentful/blocks/button/index.tsx +131 -131
- package/src/contentful/blocks/button/types.ts +39 -39
- package/src/contentful/blocks/callout/Callout.stories.tsx +23 -23
- package/src/contentful/blocks/callout/index.test.tsx +539 -0
- package/src/contentful/blocks/callout/index.tsx +277 -277
- package/src/contentful/blocks/callout/types.ts +78 -78
- package/src/contentful/blocks/cards/Cards.stories.tsx +23 -23
- package/src/contentful/blocks/cards/blog-card/index.test.tsx +218 -0
- package/src/contentful/blocks/cards/blog-card/index.tsx +129 -129
- package/src/contentful/blocks/cards/blog-card/types.ts +34 -34
- package/src/contentful/blocks/cards/floating-image-card/index.test.tsx +201 -0
- package/src/contentful/blocks/cards/floating-image-card/index.tsx +119 -119
- package/src/contentful/blocks/cards/floating-image-card/types.ts +30 -30
- package/src/contentful/blocks/cards/full-image-card/index.test.tsx +216 -0
- package/src/contentful/blocks/cards/full-image-card/index.tsx +130 -130
- package/src/contentful/blocks/cards/full-image-card/types.ts +29 -29
- package/src/contentful/blocks/cards/index.test.tsx +39 -0
- package/src/contentful/blocks/cards/index.tsx +13 -13
- package/src/contentful/blocks/cards/product-card/index.test.tsx +263 -0
- package/src/contentful/blocks/cards/product-card/index.tsx +251 -251
- package/src/contentful/blocks/cards/product-card/types.ts +28 -28
- package/src/contentful/blocks/cards/simple-card/index.test.tsx +364 -0
- package/src/contentful/blocks/cards/simple-card/index.tsx +325 -325
- package/src/contentful/blocks/cards/simple-card/types.ts +71 -71
- package/src/contentful/blocks/cards/testimonial-card/index.test.tsx +180 -0
- package/src/contentful/blocks/cards/testimonial-card/index.tsx +90 -90
- package/src/contentful/blocks/cards/testimonial-card/types.tsx +12 -12
- package/src/contentful/blocks/cards/types.ts +1 -1
- package/src/contentful/blocks/carousel/Carousel.stories.tsx +23 -23
- package/src/contentful/blocks/carousel/helper.test.tsx +539 -0
- package/src/contentful/blocks/carousel/helper.tsx +494 -494
- package/src/contentful/blocks/carousel/index.test.tsx +308 -0
- package/src/contentful/blocks/carousel/index.tsx +87 -87
- package/src/contentful/blocks/carousel/types.test.ts +16 -0
- package/src/contentful/blocks/carousel/types.ts +145 -145
- package/src/contentful/blocks/cart-retention-banner/index.test.tsx +409 -0
- package/src/contentful/blocks/cart-retention-banner/index.tsx +109 -109
- package/src/contentful/blocks/cart-retention-banner/types.ts +11 -11
- package/src/contentful/blocks/comparison-table/index.test.tsx +114 -0
- package/src/contentful/blocks/comparison-table/index.tsx +29 -29
- package/src/contentful/blocks/comparison-table/types.ts +6 -6
- package/src/contentful/blocks/cookiebanner/index.test.tsx +277 -0
- package/src/contentful/blocks/cookiebanner/index.tsx +146 -146
- package/src/contentful/blocks/cookiebanner/type.ts +7 -7
- package/src/contentful/blocks/cta-callout/CtaCallout.stories.tsx +46 -46
- package/src/contentful/blocks/cta-callout/index.test.tsx +244 -0
- package/src/contentful/blocks/cta-callout/index.tsx +73 -73
- package/src/contentful/blocks/cta-callout/types.ts +26 -26
- package/src/contentful/blocks/dynamic-tabs/index.test.tsx +240 -0
- package/src/contentful/blocks/dynamic-tabs/index.tsx +204 -204
- package/src/contentful/blocks/dynamic-tabs/types.ts +21 -21
- package/src/contentful/blocks/email-input-block/index.test.tsx +213 -0
- package/src/contentful/blocks/email-input-block/index.tsx +121 -116
- package/src/contentful/blocks/email-input-block/types.ts +16 -16
- package/src/contentful/blocks/find-kinetic/FindKinetic.stories.tsx +23 -23
- package/src/contentful/blocks/find-kinetic/index.test.tsx +269 -0
- package/src/contentful/blocks/find-kinetic/index.tsx +138 -138
- package/src/contentful/blocks/find-kinetic/types.ts +20 -20
- package/src/contentful/blocks/floating-banner/FloatingBanner.stories.tsx +34 -34
- package/src/contentful/blocks/floating-banner/index.test.tsx +246 -0
- package/src/contentful/blocks/floating-banner/index.tsx +97 -97
- package/src/contentful/blocks/floating-banner/types.ts +22 -22
- package/src/contentful/blocks/footer/Footer.stories.tsx +317 -317
- package/src/contentful/blocks/footer/index.test.tsx +302 -0
- package/src/contentful/blocks/footer/index.tsx +91 -91
- package/src/contentful/blocks/footer/types.ts +13 -13
- package/src/contentful/blocks/image-promo-bar/ImagePromoBar.stories.tsx +23 -23
- package/src/contentful/blocks/image-promo-bar/helper.test.tsx +61 -0
- package/src/contentful/blocks/image-promo-bar/helper.tsx +28 -28
- package/src/contentful/blocks/image-promo-bar/index.test.tsx +467 -0
- package/src/contentful/blocks/image-promo-bar/index.tsx +246 -246
- package/src/contentful/blocks/image-promo-bar/types.ts +44 -44
- package/src/contentful/blocks/image-promo-bar/vimeo-embed.test.tsx +142 -0
- package/src/contentful/blocks/image-promo-bar/vimeo-embed.tsx +93 -93
- package/src/contentful/blocks/image-promo-bar/youtube-embed.test.tsx +104 -0
- package/src/contentful/blocks/image-promo-bar/youtube-embed.tsx +46 -46
- package/src/contentful/blocks/modal/constants.ts +53 -53
- package/src/contentful/blocks/modal/index.test.tsx +209 -0
- package/src/contentful/blocks/modal/index.tsx +108 -108
- package/src/contentful/blocks/modal/types.ts +12 -12
- package/src/contentful/blocks/navigation/Navigation.stories.mocks.tsx +78 -78
- package/src/contentful/blocks/navigation/Navigation.stories.tsx +138 -138
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.test.tsx +208 -0
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.tsx +141 -141
- package/src/contentful/blocks/navigation/index.test.tsx +924 -0
- package/src/contentful/blocks/navigation/index.tsx +569 -569
- package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.test.tsx +131 -0
- package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.tsx +82 -82
- package/src/contentful/blocks/navigation/types.ts +71 -71
- package/src/contentful/blocks/primary-hero/PrimaryHero.stories.tsx +23 -23
- package/src/contentful/blocks/primary-hero/index.test.tsx +286 -0
- package/src/contentful/blocks/primary-hero/index.tsx +239 -236
- package/src/contentful/blocks/primary-hero/types.ts +37 -37
- package/src/contentful/blocks/search-block/index.test.tsx +268 -0
- package/src/contentful/blocks/search-block/index.tsx +90 -90
- package/src/contentful/blocks/search-block/types.ts +15 -15
- package/src/contentful/blocks/shape-background-wrapper/ShapeBackgroundWrapper.stories.tsx +26 -26
- package/src/contentful/blocks/shape-background-wrapper/index.test.tsx +284 -0
- package/src/contentful/blocks/shape-background-wrapper/index.tsx +124 -124
- package/src/contentful/blocks/shape-background-wrapper/types.ts +36 -36
- package/src/contentful/blocks/text/Text.stories.tsx +23 -23
- package/src/contentful/blocks/text/index.test.tsx +36 -0
- package/src/contentful/blocks/text/index.tsx +12 -12
- package/src/contentful/blocks/text/types.ts +1 -1
- package/src/contentful/index.test.ts +45 -0
- package/src/contentful/index.ts +105 -105
- package/src/global-mocks/contentful/to-document.ts +25 -0
- package/src/global-mocks/cookie.ts +48 -0
- package/src/global-mocks/cx.ts +37 -0
- package/src/global-mocks/index.ts +89 -0
- package/src/global-mocks/speed-card-bg.ts +27 -0
- package/src/global-mocks/utm.ts +49 -0
- package/src/hooks/contentful/use-contentful-rich-text.test.tsx +1758 -0
- package/src/hooks/contentful/use-contentful-rich-text.tsx +309 -309
- package/src/hooks/contentful/use-processed-check-list.test.tsx +277 -0
- package/src/hooks/contentful/use-processed-check-list.ts +63 -63
- package/src/hooks/use-body-scroll-lock.test.ts +134 -0
- package/src/hooks/use-body-scroll-lock.ts +34 -34
- package/src/hooks/use-carousel-swipe.test.ts +393 -0
- package/src/hooks/use-carousel-swipe.ts +264 -264
- package/src/hooks/use-outside-click.test.ts +142 -0
- package/src/hooks/use-outside-click.ts +17 -17
- package/src/index.ts +107 -107
- package/src/next/index.test.ts +7 -0
- package/src/next/index.ts +5 -5
- package/src/setupTests.ts +52 -46
- package/src/stories/DocsTemplate.tsx +24 -24
- package/src/styles/globals.css +343 -343
- package/src/types/global.d.ts +9 -9
- package/src/types/micro-components.ts +99 -99
- package/src/types/utm.ts +49 -49
- package/src/utils/contentful/to-document.test.ts +85 -0
- package/src/utils/contentful/to-document.ts +24 -24
- package/src/utils/cookie.test.ts +180 -0
- package/src/utils/cookie.ts +84 -84
- package/src/utils/cx.test.ts +90 -0
- package/src/utils/cx.ts +49 -49
- package/src/utils/index.test.ts +115 -0
- package/src/utils/index.ts +41 -41
- package/src/utils/speed-card-bg.test.ts +46 -0
- package/src/utils/speed-card-bg.ts +24 -24
- package/src/utils/utm.test.ts +359 -0
- package/src/utils/utm.ts +221 -221
package/src/types/global.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
declare module "*.module.css" {
|
|
2
|
-
const classes: { [key: string]: string };
|
|
3
|
-
export default classes;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
declare module "*.css" {
|
|
7
|
-
const content: string;
|
|
8
|
-
export default content;
|
|
9
|
-
}
|
|
1
|
+
declare module "*.module.css" {
|
|
2
|
+
const classes: { [key: string]: string };
|
|
3
|
+
export default classes;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module "*.css" {
|
|
7
|
+
const content: string;
|
|
8
|
+
export default content;
|
|
9
|
+
}
|
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import { ButtonProps } from "@shared/contentful";
|
|
2
|
-
|
|
3
|
-
export interface Asset {
|
|
4
|
-
url?: string | null;
|
|
5
|
-
title?: string | null;
|
|
6
|
-
description?: string | null;
|
|
7
|
-
contentType?: string | null;
|
|
8
|
-
width?: number | null;
|
|
9
|
-
height?: number | null;
|
|
10
|
-
}
|
|
11
|
-
export interface Button {
|
|
12
|
-
anchorId?: string | null;
|
|
13
|
-
showButtonAs?: "solid" | "text" | null;
|
|
14
|
-
buttonLabel: string; // required in your model
|
|
15
|
-
buttonPrefix?: string | null;
|
|
16
|
-
href?: string | null;
|
|
17
|
-
target?: "_blank" | "_self" | null;
|
|
18
|
-
badge?: string | null;
|
|
19
|
-
preserveQueryParameters: boolean; // non-null in your model
|
|
20
|
-
badgeIcon?: Asset | null;
|
|
21
|
-
buttonVariant?: "primary_brand" | "primary_inverse" | "secondary" | null;
|
|
22
|
-
buttonIcon?: Asset | null;
|
|
23
|
-
buttonIconPosition?: boolean | null; // matches EntryFieldTypes.Boolean in your model
|
|
24
|
-
clickToOpen?: "accordion" | "modal" | "tab" | null;
|
|
25
|
-
tabmodalNameToOpen?: string | null;
|
|
26
|
-
preDefinedFunctionExecution?: "check availability" | null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface ButtonGroup {
|
|
30
|
-
__typename: "ComponentButtonGroup";
|
|
31
|
-
anchorId?: string | null;
|
|
32
|
-
title?: string | null;
|
|
33
|
-
itemsCollection?: {
|
|
34
|
-
items: Button[];
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
export interface Card {
|
|
38
|
-
anchorId?: string;
|
|
39
|
-
title?: string;
|
|
40
|
-
body?: {
|
|
41
|
-
json: any; // Contentful Rich Text
|
|
42
|
-
};
|
|
43
|
-
image?: Asset;
|
|
44
|
-
imageLink?: string;
|
|
45
|
-
imageAlignment?: "Left" | "Right" | "Center" | string;
|
|
46
|
-
imageView?: "Full" | "Inset" | string;
|
|
47
|
-
cta?: Button;
|
|
48
|
-
ctaAlignment?: "Left" | "Right" | "Center" | string;
|
|
49
|
-
textColor?: string;
|
|
50
|
-
backgroundColor?: string;
|
|
51
|
-
showBackgroundImage?: boolean;
|
|
52
|
-
pinwheelColor?: "blue" | "green" | "navy" | "purple" | "white" | "yellow";
|
|
53
|
-
iconToRichTextAlignment?: string;
|
|
54
|
-
phoneNumber?: string;
|
|
55
|
-
workingHours?: string;
|
|
56
|
-
titleLocation?: "Top" | "Bottom" | string;
|
|
57
|
-
ctaBottom?: Button;
|
|
58
|
-
ctaAlignmentBottom?: "Left" | "Right" | "Center" | string;
|
|
59
|
-
imageFloatingType?: boolean;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface VideoLink {
|
|
63
|
-
image?: Asset;
|
|
64
|
-
videoPopup?: boolean;
|
|
65
|
-
link?: string;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface Checklist {
|
|
69
|
-
list?: {
|
|
70
|
-
items: {
|
|
71
|
-
checkListTitle?: { json: any };
|
|
72
|
-
icon?: Asset;
|
|
73
|
-
anchorId?: string;
|
|
74
|
-
}[];
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface RichTextItem {
|
|
79
|
-
title?: string;
|
|
80
|
-
isTargetBlank?: boolean;
|
|
81
|
-
richText?: { json: any };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type CheckPlansProps = {
|
|
85
|
-
className?: string;
|
|
86
|
-
title?: string;
|
|
87
|
-
ctaAlignment?: "new-row" | "same-row";
|
|
88
|
-
ctaText?: string;
|
|
89
|
-
buttonVariant?: "primary_brand" | "secondary" | "primary_inverse";
|
|
90
|
-
showButtonAs?: "solid" | "unstyled" | "text" | undefined;
|
|
91
|
-
cta?: ButtonProps;
|
|
92
|
-
speedCardConfig?: {
|
|
93
|
-
isModalOpen?: boolean;
|
|
94
|
-
setModalOpen?: () => void;
|
|
95
|
-
speed?: string;
|
|
96
|
-
techType?: string;
|
|
97
|
-
isMax?: boolean;
|
|
98
|
-
};
|
|
99
|
-
};
|
|
1
|
+
import { ButtonProps } from "@shared/contentful";
|
|
2
|
+
|
|
3
|
+
export interface Asset {
|
|
4
|
+
url?: string | null;
|
|
5
|
+
title?: string | null;
|
|
6
|
+
description?: string | null;
|
|
7
|
+
contentType?: string | null;
|
|
8
|
+
width?: number | null;
|
|
9
|
+
height?: number | null;
|
|
10
|
+
}
|
|
11
|
+
export interface Button {
|
|
12
|
+
anchorId?: string | null;
|
|
13
|
+
showButtonAs?: "solid" | "text" | null;
|
|
14
|
+
buttonLabel: string; // required in your model
|
|
15
|
+
buttonPrefix?: string | null;
|
|
16
|
+
href?: string | null;
|
|
17
|
+
target?: "_blank" | "_self" | null;
|
|
18
|
+
badge?: string | null;
|
|
19
|
+
preserveQueryParameters: boolean; // non-null in your model
|
|
20
|
+
badgeIcon?: Asset | null;
|
|
21
|
+
buttonVariant?: "primary_brand" | "primary_inverse" | "secondary" | null;
|
|
22
|
+
buttonIcon?: Asset | null;
|
|
23
|
+
buttonIconPosition?: boolean | null; // matches EntryFieldTypes.Boolean in your model
|
|
24
|
+
clickToOpen?: "accordion" | "modal" | "tab" | null;
|
|
25
|
+
tabmodalNameToOpen?: string | null;
|
|
26
|
+
preDefinedFunctionExecution?: "check availability" | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ButtonGroup {
|
|
30
|
+
__typename: "ComponentButtonGroup";
|
|
31
|
+
anchorId?: string | null;
|
|
32
|
+
title?: string | null;
|
|
33
|
+
itemsCollection?: {
|
|
34
|
+
items: Button[];
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface Card {
|
|
38
|
+
anchorId?: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
body?: {
|
|
41
|
+
json: any; // Contentful Rich Text
|
|
42
|
+
};
|
|
43
|
+
image?: Asset;
|
|
44
|
+
imageLink?: string;
|
|
45
|
+
imageAlignment?: "Left" | "Right" | "Center" | string;
|
|
46
|
+
imageView?: "Full" | "Inset" | string;
|
|
47
|
+
cta?: Button;
|
|
48
|
+
ctaAlignment?: "Left" | "Right" | "Center" | string;
|
|
49
|
+
textColor?: string;
|
|
50
|
+
backgroundColor?: string;
|
|
51
|
+
showBackgroundImage?: boolean;
|
|
52
|
+
pinwheelColor?: "blue" | "green" | "navy" | "purple" | "white" | "yellow";
|
|
53
|
+
iconToRichTextAlignment?: string;
|
|
54
|
+
phoneNumber?: string;
|
|
55
|
+
workingHours?: string;
|
|
56
|
+
titleLocation?: "Top" | "Bottom" | string;
|
|
57
|
+
ctaBottom?: Button;
|
|
58
|
+
ctaAlignmentBottom?: "Left" | "Right" | "Center" | string;
|
|
59
|
+
imageFloatingType?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface VideoLink {
|
|
63
|
+
image?: Asset;
|
|
64
|
+
videoPopup?: boolean;
|
|
65
|
+
link?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface Checklist {
|
|
69
|
+
list?: {
|
|
70
|
+
items: {
|
|
71
|
+
checkListTitle?: { json: any };
|
|
72
|
+
icon?: Asset;
|
|
73
|
+
anchorId?: string;
|
|
74
|
+
}[];
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface RichTextItem {
|
|
79
|
+
title?: string;
|
|
80
|
+
isTargetBlank?: boolean;
|
|
81
|
+
richText?: { json: any };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type CheckPlansProps = {
|
|
85
|
+
className?: string;
|
|
86
|
+
title?: string;
|
|
87
|
+
ctaAlignment?: "new-row" | "same-row";
|
|
88
|
+
ctaText?: string;
|
|
89
|
+
buttonVariant?: "primary_brand" | "secondary" | "primary_inverse";
|
|
90
|
+
showButtonAs?: "solid" | "unstyled" | "text" | undefined;
|
|
91
|
+
cta?: ButtonProps;
|
|
92
|
+
speedCardConfig?: {
|
|
93
|
+
isModalOpen?: boolean;
|
|
94
|
+
setModalOpen?: () => void;
|
|
95
|
+
speed?: string;
|
|
96
|
+
techType?: string;
|
|
97
|
+
isMax?: boolean;
|
|
98
|
+
};
|
|
99
|
+
};
|
package/src/types/utm.ts
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UTM Parameter Types
|
|
3
|
-
*
|
|
4
|
-
* Type definitions for UTM tracking parameters used across Kinetic applications.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** All tracked UTM and click-ID parameter names */
|
|
8
|
-
export type UTMProperty =
|
|
9
|
-
| "utm_content"
|
|
10
|
-
| "utm_medium"
|
|
11
|
-
| "utm_campaign"
|
|
12
|
-
| "utm_source"
|
|
13
|
-
| "utm_term"
|
|
14
|
-
| "utm_campaign_id"
|
|
15
|
-
| "utm_adgroup_id"
|
|
16
|
-
| "fbclid"
|
|
17
|
-
| "gclid"
|
|
18
|
-
| "msclkid";
|
|
19
|
-
|
|
20
|
-
/** Partial record of UTM parameter values */
|
|
21
|
-
export type UTMProperties = Partial<Record<UTMProperty, string>>;
|
|
22
|
-
|
|
23
|
-
/** Segment campaign context schema */
|
|
24
|
-
export interface CampaignProperties {
|
|
25
|
-
name?: string;
|
|
26
|
-
source?: string;
|
|
27
|
-
medium?: string;
|
|
28
|
-
term?: string;
|
|
29
|
-
content?: string;
|
|
30
|
-
campaign_id?: string;
|
|
31
|
-
adgroup_id?: string;
|
|
32
|
-
gclid?: string;
|
|
33
|
-
fbclid?: string;
|
|
34
|
-
msclkid?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** List of all UTM parameter names for filtering */
|
|
38
|
-
export const UTM_PARAM_NAMES: UTMProperty[] = [
|
|
39
|
-
"utm_content",
|
|
40
|
-
"utm_medium",
|
|
41
|
-
"utm_campaign",
|
|
42
|
-
"utm_source",
|
|
43
|
-
"utm_term",
|
|
44
|
-
"utm_campaign_id",
|
|
45
|
-
"utm_adgroup_id",
|
|
46
|
-
"fbclid",
|
|
47
|
-
"gclid",
|
|
48
|
-
"msclkid",
|
|
49
|
-
];
|
|
1
|
+
/**
|
|
2
|
+
* UTM Parameter Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for UTM tracking parameters used across Kinetic applications.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** All tracked UTM and click-ID parameter names */
|
|
8
|
+
export type UTMProperty =
|
|
9
|
+
| "utm_content"
|
|
10
|
+
| "utm_medium"
|
|
11
|
+
| "utm_campaign"
|
|
12
|
+
| "utm_source"
|
|
13
|
+
| "utm_term"
|
|
14
|
+
| "utm_campaign_id"
|
|
15
|
+
| "utm_adgroup_id"
|
|
16
|
+
| "fbclid"
|
|
17
|
+
| "gclid"
|
|
18
|
+
| "msclkid";
|
|
19
|
+
|
|
20
|
+
/** Partial record of UTM parameter values */
|
|
21
|
+
export type UTMProperties = Partial<Record<UTMProperty, string>>;
|
|
22
|
+
|
|
23
|
+
/** Segment campaign context schema */
|
|
24
|
+
export interface CampaignProperties {
|
|
25
|
+
name?: string;
|
|
26
|
+
source?: string;
|
|
27
|
+
medium?: string;
|
|
28
|
+
term?: string;
|
|
29
|
+
content?: string;
|
|
30
|
+
campaign_id?: string;
|
|
31
|
+
adgroup_id?: string;
|
|
32
|
+
gclid?: string;
|
|
33
|
+
fbclid?: string;
|
|
34
|
+
msclkid?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** List of all UTM parameter names for filtering */
|
|
38
|
+
export const UTM_PARAM_NAMES: UTMProperty[] = [
|
|
39
|
+
"utm_content",
|
|
40
|
+
"utm_medium",
|
|
41
|
+
"utm_campaign",
|
|
42
|
+
"utm_source",
|
|
43
|
+
"utm_term",
|
|
44
|
+
"utm_campaign_id",
|
|
45
|
+
"utm_adgroup_id",
|
|
46
|
+
"fbclid",
|
|
47
|
+
"gclid",
|
|
48
|
+
"msclkid",
|
|
49
|
+
];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { toDocument } from "./to-document";
|
|
2
|
+
|
|
3
|
+
import { BLOCKS, type Document } from "@contentful/rich-text-types";
|
|
4
|
+
|
|
5
|
+
const makeDocument = (text = "Hello"): Document => ({
|
|
6
|
+
nodeType: BLOCKS.DOCUMENT,
|
|
7
|
+
data: {},
|
|
8
|
+
content: [
|
|
9
|
+
{
|
|
10
|
+
nodeType: BLOCKS.PARAGRAPH,
|
|
11
|
+
data: {},
|
|
12
|
+
content: [{ nodeType: "text", value: text, marks: [], data: {} }],
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("toDocument", () => {
|
|
18
|
+
// ── Falsy inputs ─────────────────────────────────────
|
|
19
|
+
it("returns null for null", () => {
|
|
20
|
+
expect(toDocument(null)).toBeNull();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("returns null for undefined", () => {
|
|
24
|
+
expect(toDocument(undefined)).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("returns null for empty string", () => {
|
|
28
|
+
expect(toDocument("")).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("returns null for 0", () => {
|
|
32
|
+
expect(toDocument(0)).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("returns null for false", () => {
|
|
36
|
+
expect(toDocument(false)).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ── REST/CDA Document ────────────────────────────────
|
|
40
|
+
it("returns Document directly when given a valid REST Document", () => {
|
|
41
|
+
const doc = makeDocument();
|
|
42
|
+
expect(toDocument(doc)).toBe(doc);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ── GraphQL RichText { json: Document } ──────────────
|
|
46
|
+
it("extracts Document from GraphQL format { json, links }", () => {
|
|
47
|
+
const doc = makeDocument("GraphQL");
|
|
48
|
+
const graphql = { json: doc, links: { assets: [] } };
|
|
49
|
+
expect(toDocument(graphql)).toBe(doc);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("extracts Document from GraphQL format without links", () => {
|
|
53
|
+
const doc = makeDocument("NoLinks");
|
|
54
|
+
expect(toDocument({ json: doc })).toBe(doc);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("returns null when json property is not a valid Document", () => {
|
|
58
|
+
expect(toDocument({ json: "not-a-document" })).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns null when json property is null", () => {
|
|
62
|
+
expect(toDocument({ json: null })).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ── Non-matching objects ─────────────────────────────
|
|
66
|
+
it("returns null for an object without nodeType or json", () => {
|
|
67
|
+
expect(toDocument({ foo: "bar" })).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("returns null for an object with nodeType but no content", () => {
|
|
71
|
+
expect(toDocument({ nodeType: BLOCKS.DOCUMENT })).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("returns null for an array", () => {
|
|
75
|
+
expect(toDocument([1, 2, 3])).toBeNull();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("returns null for a number", () => {
|
|
79
|
+
expect(toDocument(42)).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("returns null for a non-empty string", () => {
|
|
83
|
+
expect(toDocument("hello")).toBeNull();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { Document } from "@contentful/rich-text-types";
|
|
2
|
-
|
|
3
|
-
type GraphqlRichText = { json: Document; links?: unknown };
|
|
4
|
-
|
|
5
|
-
const isDocument = (v: unknown): v is Document =>
|
|
6
|
-
!!v &&
|
|
7
|
-
typeof v === "object" &&
|
|
8
|
-
"nodeType" in (v as any) &&
|
|
9
|
-
"content" in (v as any);
|
|
10
|
-
|
|
11
|
-
export const toDocument = (v: unknown | null | undefined): Document | null => {
|
|
12
|
-
if (!v) return null;
|
|
13
|
-
|
|
14
|
-
// REST/CDA Document
|
|
15
|
-
if (isDocument(v)) return v;
|
|
16
|
-
|
|
17
|
-
// GraphQL RichText { json: Document, links? }
|
|
18
|
-
if (typeof v === "object" && v !== null && "json" in (v as any)) {
|
|
19
|
-
const json = (v as GraphqlRichText).json;
|
|
20
|
-
return isDocument(json) ? json : null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return null;
|
|
24
|
-
};
|
|
1
|
+
import type { Document } from "@contentful/rich-text-types";
|
|
2
|
+
|
|
3
|
+
type GraphqlRichText = { json: Document; links?: unknown };
|
|
4
|
+
|
|
5
|
+
const isDocument = (v: unknown): v is Document =>
|
|
6
|
+
!!v &&
|
|
7
|
+
typeof v === "object" &&
|
|
8
|
+
"nodeType" in (v as any) &&
|
|
9
|
+
"content" in (v as any);
|
|
10
|
+
|
|
11
|
+
export const toDocument = (v: unknown | null | undefined): Document | null => {
|
|
12
|
+
if (!v) return null;
|
|
13
|
+
|
|
14
|
+
// REST/CDA Document
|
|
15
|
+
if (isDocument(v)) return v;
|
|
16
|
+
|
|
17
|
+
// GraphQL RichText { json: Document, links? }
|
|
18
|
+
if (typeof v === "object" && v !== null && "json" in (v as any)) {
|
|
19
|
+
const json = (v as GraphqlRichText).json;
|
|
20
|
+
return isDocument(json) ? json : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
@@ -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
|
+
});
|