@tapcart/mobile-components 0.12.4 → 0.12.6

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.
@@ -2,6 +2,7 @@ import { Collection, Product, BaseSearchClient } from "app-studio-types";
2
2
  interface UseRecommendationProps {
3
3
  searchClient?: BaseSearchClient<Product>;
4
4
  query?: string;
5
+ customSearchConfig?: Record<string, any>;
5
6
  queryVariables: Record<string, any>;
6
7
  apiURL: string;
7
8
  }
@@ -9,9 +10,10 @@ interface UseRecommendationReturn {
9
10
  products: Product[];
10
11
  collections: Collection[];
11
12
  searches: string[];
13
+ facets: any[];
12
14
  isLoading: boolean;
13
15
  error: any;
14
16
  }
15
- declare const useRecommendations: ({ searchClient, query, queryVariables, apiURL, }: UseRecommendationProps) => UseRecommendationReturn;
17
+ declare const useRecommendations: ({ searchClient, query, customSearchConfig, queryVariables, apiURL, }: UseRecommendationProps) => UseRecommendationReturn;
16
18
  export { useRecommendations };
17
19
  //# sourceMappingURL=use-recommendations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IAGd,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAiBD,QAAA,MAAM,kBAAkB,qDAQrB,sBAAsB,KAAG,uBA6F3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAiBD,QAAA,MAAM,kBAAkB,yEASrB,sBAAsB,KAAG,uBAkG3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -24,7 +24,7 @@ const getCollections = (collections) => {
24
24
  const recommendationsLocalStorage = new RecommendationsLocalStorage();
25
25
  const useRecommendations = ({
26
26
  // Search client props
27
- searchClient, query = "",
27
+ searchClient, query = "", customSearchConfig,
28
28
  // API props (backwards compatibility)
29
29
  queryVariables, apiURL, }) => {
30
30
  // When searchClient is provided, use search client approach
@@ -40,12 +40,13 @@ queryVariables, apiURL, }) => {
40
40
  const searchClientFetcher = () => __awaiter(void 0, void 0, void 0, function* () {
41
41
  if (!searchClient)
42
42
  return null;
43
- // Call searchClient.getRecommendations (returns string[] directly)
43
+ // Call searchClient.getRecommendations with optional custom config
44
44
  const recommendations = yield searchClient.getRecommendations({
45
45
  query: recommendation,
46
+ customSearchConfig,
46
47
  });
47
48
  // Format as expected by the hook
48
- return Object.assign(Object.assign({}, recommendations), { collections: [] });
49
+ return Object.assign({ collections: [], facets: [] }, recommendations);
49
50
  });
50
51
  // API fetcher (backwards compatibility)
51
52
  const apiFetcher = (body) => fetch(constructURL(apiURL), {
@@ -64,6 +65,7 @@ queryVariables, apiURL, }) => {
64
65
  type: "searchClient",
65
66
  query: recommendation,
66
67
  language: queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.language,
68
+ customSearchConfig,
67
69
  }
68
70
  : {
69
71
  appId: queryVariables.appId,
@@ -84,12 +86,14 @@ queryVariables, apiURL, }) => {
84
86
  products: data === null || data === void 0 ? void 0 : data.products,
85
87
  collections: getCollections(data === null || data === void 0 ? void 0 : data.collections),
86
88
  searches: data === null || data === void 0 ? void 0 : data.searches,
89
+ facets: (data === null || data === void 0 ? void 0 : data.facets) || [],
87
90
  });
88
- }, [data]);
91
+ }, [data, recommendation, queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.language]);
89
92
  return {
90
93
  products: cachedRecommendation === null || cachedRecommendation === void 0 ? void 0 : cachedRecommendation.products,
91
94
  collections: cachedRecommendation === null || cachedRecommendation === void 0 ? void 0 : cachedRecommendation.collections,
92
95
  searches: cachedRecommendation === null || cachedRecommendation === void 0 ? void 0 : cachedRecommendation.searches,
96
+ facets: (cachedRecommendation === null || cachedRecommendation === void 0 ? void 0 : cachedRecommendation.facets) || [],
93
97
  isLoading: !cachedRecommendation && isLoading,
94
98
  error: error,
95
99
  };
@@ -11,6 +11,7 @@ type Config = {
11
11
  enabled: boolean;
12
12
  fontSize: number;
13
13
  textAlignment: "left" | "right" | "center" | null;
14
+ hideZeroCents?: boolean;
14
15
  };
15
16
  productTitle?: {
16
17
  enabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../components/ui/product-card.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../components/ui/product-card.tsx"],"names":[],"mappings":"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"}
@@ -135,7 +135,7 @@ const productCardFavoriteVariants = cva("absolute ", {
135
135
  },
136
136
  });
137
137
  const ProductCard = ({ config, tapcartData, product, isLoading, favorited, onFavoriteClick, onQuickAdd, openProduct, className, }) => {
138
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20;
138
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21;
139
139
  const { variants, images, title, tags } = product;
140
140
  // Select the variant that has the lowest price that is available or just the lowest price if none are available
141
141
  let searchVariants = variants.filter((variant) => variant.available);
@@ -271,9 +271,9 @@ const ProductCard = ({ config, tapcartData, product, isLoading, favorited, onFav
271
271
  variant.compareAtPrice &&
272
272
  parseFloat((_12 = variant.compareAtPrice) === null || _12 === void 0 ? void 0 : _12.amount) >
273
273
  parseFloat(variant.price.amount), compareAtPrice: variant.compareAtPrice &&
274
- parseFloat((_13 = variant.compareAtPrice) === null || _13 === void 0 ? void 0 : _13.amount), currency: tapcartData.currency.code, locale: tapcartData.currency.locale, fontSize: (_14 = config.price) === null || _14 === void 0 ? void 0 : _14.fontSize })), ((_15 = config.favoritesIcon) === null || _15 === void 0 ? void 0 : _15.enabled) &&
274
+ parseFloat((_13 = variant.compareAtPrice) === null || _13 === void 0 ? void 0 : _13.amount), currency: tapcartData.currency.code, locale: tapcartData.currency.locale, fontSize: (_14 = config.price) === null || _14 === void 0 ? void 0 : _14.fontSize, hideZeroCents: (_15 = config.price) === null || _15 === void 0 ? void 0 : _15.hideZeroCents })), ((_16 = config.favoritesIcon) === null || _16 === void 0 ? void 0 : _16.enabled) &&
275
275
  config.favoritesIcon.layoutType === "below-image-on-right" && (_jsx("div", Object.assign({ className: "w-8 h-8 flex items-center justify-center" }, { children: _jsx(Favorite, { selected: favorited, onClick: (e) => {
276
276
  onFavoriteClick === null || onFavoriteClick === void 0 ? void 0 : onFavoriteClick(e, product);
277
- }, size: "small", iconUrl: (_17 = (_16 = config.favoritesIcon) === null || _16 === void 0 ? void 0 : _16.icon) === null || _17 === void 0 ? void 0 : _17.url, cornerRadius: (_18 = config.favoritesIcon) === null || _18 === void 0 ? void 0 : _18.cornerRadius, layoutType: (_19 = config.favoritesIcon) === null || _19 === void 0 ? void 0 : _19.layoutType, showBackground: (_20 = config.favoritesIcon) === null || _20 === void 0 ? void 0 : _20.showBackground }) })))] }))] }))] })) })));
277
+ }, size: "small", iconUrl: (_18 = (_17 = config.favoritesIcon) === null || _17 === void 0 ? void 0 : _17.icon) === null || _18 === void 0 ? void 0 : _18.url, cornerRadius: (_19 = config.favoritesIcon) === null || _19 === void 0 ? void 0 : _19.cornerRadius, layoutType: (_20 = config.favoritesIcon) === null || _20 === void 0 ? void 0 : _20.layoutType, showBackground: (_21 = config.favoritesIcon) === null || _21 === void 0 ? void 0 : _21.showBackground }) })))] }))] }))] })) })));
278
278
  };
279
279
  export { ProductCard };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.12.4",
3
+ "version": "0.12.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "style": "dist/styles.css",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=utils.wishlist.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.wishlist.test.d.ts","sourceRoot":"","sources":["../../lib/utils.wishlist.test.ts"],"names":[],"mappings":""}
@@ -1,108 +0,0 @@
1
- import { findWishlistEntry, getEnabledWishlistIntegration, supportsMultipleWishlists, } from "./utils";
2
- describe("getEnabledWishlistIntegration", () => {
3
- it("returns the first enabled wishlist integration", () => {
4
- const integrations = [
5
- { name: "tapcart-search", enabled: true },
6
- { name: "tapcart-wishlist", enabled: true, multiwishlist: true },
7
- { name: "swym", enabled: true },
8
- ];
9
- const result = getEnabledWishlistIntegration(integrations);
10
- expect(result).toEqual({
11
- name: "tapcart-wishlist",
12
- enabled: true,
13
- multiwishlist: true,
14
- });
15
- });
16
- it("returns null when no wishlist integration is enabled", () => {
17
- const integrations = [
18
- { name: "tapcart-search", enabled: true },
19
- { name: "tapcart-wishlist", enabled: false },
20
- ];
21
- expect(getEnabledWishlistIntegration(integrations)).toBeNull();
22
- });
23
- it("returns null when integrations is not an array", () => {
24
- expect(getEnabledWishlistIntegration(undefined)).toBeNull();
25
- expect(getEnabledWishlistIntegration(null)).toBeNull();
26
- });
27
- });
28
- describe("supportsMultipleWishlists", () => {
29
- it("respects explicit multiwishlist flag", () => {
30
- expect(supportsMultipleWishlists({
31
- name: "tapcart-wishlist",
32
- enabled: true,
33
- multiwishlist: false,
34
- })).toBe(false);
35
- expect(supportsMultipleWishlists({
36
- name: "tapcart-wishlist",
37
- enabled: true,
38
- multiwishlist: true,
39
- })).toBe(true);
40
- });
41
- it("defaults to true for known integrations when flag is omitted", () => {
42
- expect(supportsMultipleWishlists({
43
- name: "tapcart-wishlist-v2",
44
- enabled: true,
45
- })).toBe(true);
46
- });
47
- it("returns false for unknown integrations", () => {
48
- expect(supportsMultipleWishlists({
49
- name: "not-a-wishlist",
50
- enabled: true,
51
- })).toBe(false);
52
- });
53
- });
54
- describe("findWishlistEntry", () => {
55
- const wishlists = [
56
- {
57
- id: "wl-1",
58
- items: [
59
- {
60
- id: "item-1",
61
- productId: "gid://shopify/Product/123",
62
- variantId: "gid://shopify/ProductVariant/456",
63
- },
64
- ],
65
- },
66
- {
67
- _id: "wl-2",
68
- items: [
69
- {
70
- id: "item-2",
71
- productId: "789",
72
- variantId: "654",
73
- },
74
- ],
75
- },
76
- ];
77
- it("finds an entry when product and variant match across gid representations", () => {
78
- const match = findWishlistEntry(wishlists, "123", "456");
79
- expect(match).toEqual({
80
- wishlistId: "wl-1",
81
- item: {
82
- id: "item-1",
83
- productId: "gid://shopify/Product/123",
84
- variantId: "gid://shopify/ProductVariant/456",
85
- },
86
- });
87
- });
88
- it("falls back to product-only lookup when variant is omitted", () => {
89
- const match = findWishlistEntry(wishlists, "789");
90
- expect(match).toEqual({
91
- wishlistId: "wl-2",
92
- item: {
93
- id: "item-2",
94
- productId: "789",
95
- variantId: "654",
96
- },
97
- });
98
- });
99
- it("returns null when no matching entry is found", () => {
100
- const match = findWishlistEntry(wishlists, "999", "888");
101
- expect(match).toBeNull();
102
- });
103
- it("handles empty or invalid inputs gracefully", () => {
104
- expect(findWishlistEntry(undefined, "123")).toBeNull();
105
- expect(findWishlistEntry([], "123")).toBeNull();
106
- expect(findWishlistEntry(wishlists, undefined)).toBeNull();
107
- });
108
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=conditional-rendering.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conditional-rendering.test.d.ts","sourceRoot":"","sources":["../../tests/conditional-rendering.test.ts"],"names":[],"mappings":""}
@@ -1,476 +0,0 @@
1
- import { shouldShowBlock, evaluateConditions, getEnvState } from "../lib/utils";
2
- describe("Conditional Rendering - Bug Tests", () => {
3
- describe("V1 Conditionals (shouldShowBlock)", () => {
4
- describe("OR logic with customerTag and deviceId", () => {
5
- it("should show block when customerTag matches and deviceId does not match", () => {
6
- const envState = getEnvState({
7
- location: { country: "US", language: "en", deviceId: "device-123" },
8
- customer: { id: "customer-1", tags: ["VIP"] },
9
- });
10
- const blockState = {
11
- customerTag: [{ value: "VIP" }],
12
- deviceId: [{ value: "device-999" }], // Different device ID
13
- };
14
- const result = shouldShowBlock(envState, blockState);
15
- expect(result).toBe(true); // Should be true because customerTag matches (OR logic)
16
- });
17
- it("should show block when deviceId matches and customerTag does not match", () => {
18
- const envState = getEnvState({
19
- location: { country: "US", language: "en", deviceId: "device-123" },
20
- customer: { id: "customer-1", tags: ["Regular"] },
21
- });
22
- const blockState = {
23
- customerTag: [{ value: "VIP" }],
24
- deviceId: [{ value: "device-123" }], // Device ID matches
25
- };
26
- const result = shouldShowBlock(envState, blockState);
27
- expect(result).toBe(true); // Should be true because deviceId matches (OR logic)
28
- });
29
- it("should NOT show block when neither customerTag nor deviceId match", () => {
30
- const envState = getEnvState({
31
- location: { country: "US", language: "en", deviceId: "device-123" },
32
- customer: { id: "customer-1", tags: ["Regular"] },
33
- });
34
- const blockState = {
35
- customerTag: [{ value: "VIP" }],
36
- deviceId: [{ value: "device-999" }],
37
- };
38
- const result = shouldShowBlock(envState, blockState);
39
- expect(result).toBe(false); // Neither condition matches
40
- });
41
- it("should show block when both customerTag and deviceId match", () => {
42
- const envState = getEnvState({
43
- location: { country: "US", language: "en", deviceId: "device-123" },
44
- customer: { id: "customer-1", tags: ["VIP"] },
45
- });
46
- const blockState = {
47
- customerTag: [{ value: "VIP" }],
48
- deviceId: [{ value: "device-123" }],
49
- };
50
- const result = shouldShowBlock(envState, blockState);
51
- expect(result).toBe(true); // Both match
52
- });
53
- it("should handle missing deviceId in environment gracefully", () => {
54
- const envState = getEnvState({
55
- location: { country: "US", language: "en" },
56
- customer: { id: "customer-1", tags: ["VIP"] },
57
- });
58
- const blockState = {
59
- customerTag: [{ value: "VIP" }],
60
- deviceId: [{ value: "device-123" }],
61
- };
62
- const result = shouldShowBlock(envState, blockState);
63
- expect(result).toBe(true); // Should still show because customerTag matches
64
- });
65
- it("should handle missing customer tags gracefully", () => {
66
- const envState = getEnvState({
67
- location: { country: "US", language: "en", deviceId: "device-123" },
68
- customer: { id: "customer-1", tags: [] }, // No tags
69
- });
70
- const blockState = {
71
- customerTag: [{ value: "VIP" }],
72
- deviceId: [{ value: "device-123" }],
73
- };
74
- const result = shouldShowBlock(envState, blockState);
75
- expect(result).toBe(true); // Should show because deviceId matches
76
- });
77
- it("should handle no customer (logged out) with deviceId match", () => {
78
- const envState = getEnvState({
79
- location: { country: "US", language: "en", deviceId: "device-123" },
80
- customer: undefined, // Not logged in
81
- });
82
- const blockState = {
83
- customerTag: [{ value: "VIP" }],
84
- deviceId: [{ value: "device-123" }],
85
- };
86
- const result = shouldShowBlock(envState, blockState);
87
- expect(result).toBe(true); // Should show because deviceId matches
88
- });
89
- });
90
- });
91
- describe("V2 Conditionals (evaluateConditions)", () => {
92
- describe("OR logic with customerTag and deviceId", () => {
93
- it("should show block when customerTag matches and deviceId does not match (OR logic)", () => {
94
- const envState = getEnvState({
95
- location: { country: "US", language: "en", deviceId: "device-123" },
96
- customer: { id: "customer-1", tags: ["VIP"] },
97
- });
98
- const conditions = {
99
- logic: "OR",
100
- conditions: [
101
- {
102
- type: "customerTag",
103
- operator: "equals",
104
- value: "VIP",
105
- },
106
- {
107
- type: "deviceId",
108
- operator: "equals",
109
- value: "device-999", // Different device ID
110
- },
111
- ],
112
- };
113
- const result = evaluateConditions(conditions, envState);
114
- expect(result).toBe(true); // Should be true because customerTag matches
115
- });
116
- it("should show block when deviceId matches and customerTag does not match (OR logic)", () => {
117
- const envState = getEnvState({
118
- location: { country: "US", language: "en", deviceId: "device-123" },
119
- customer: { id: "customer-1", tags: ["Regular"] },
120
- });
121
- const conditions = {
122
- logic: "OR",
123
- conditions: [
124
- {
125
- type: "customerTag",
126
- operator: "equals",
127
- value: "VIP", // Customer doesn't have VIP tag
128
- },
129
- {
130
- type: "deviceId",
131
- operator: "equals",
132
- value: "device-123", // Device ID matches
133
- },
134
- ],
135
- };
136
- const result = evaluateConditions(conditions, envState);
137
- expect(result).toBe(true); // Should be true because deviceId matches
138
- });
139
- it("should NOT show block when neither customerTag nor deviceId match", () => {
140
- const envState = getEnvState({
141
- location: { country: "US", language: "en", deviceId: "device-123" },
142
- customer: { id: "customer-1", tags: ["Regular"] },
143
- });
144
- const conditions = {
145
- logic: "OR",
146
- conditions: [
147
- {
148
- type: "customerTag",
149
- operator: "equals",
150
- value: "VIP",
151
- },
152
- {
153
- type: "deviceId",
154
- operator: "equals",
155
- value: "device-999",
156
- },
157
- ],
158
- };
159
- const result = evaluateConditions(conditions, envState);
160
- expect(result).toBe(false); // Neither condition matches
161
- });
162
- it("should show block when both customerTag and deviceId match", () => {
163
- const envState = getEnvState({
164
- location: { country: "US", language: "en", deviceId: "device-123" },
165
- customer: { id: "customer-1", tags: ["VIP"] },
166
- });
167
- const conditions = {
168
- logic: "OR",
169
- conditions: [
170
- {
171
- type: "customerTag",
172
- operator: "equals",
173
- value: "VIP",
174
- },
175
- {
176
- type: "deviceId",
177
- operator: "equals",
178
- value: "device-123",
179
- },
180
- ],
181
- };
182
- const result = evaluateConditions(conditions, envState);
183
- expect(result).toBe(true); // Both match
184
- });
185
- it("should NOT show block when deviceId is undefined in environment but is checked in conditions", () => {
186
- const envState = getEnvState({
187
- location: { country: "US", language: "en" },
188
- customer: { id: "customer-1", tags: ["Regular"] }, // Customer doesn't have VIP tag
189
- });
190
- const conditions = {
191
- logic: "OR",
192
- conditions: [
193
- {
194
- type: "customerTag",
195
- operator: "equals",
196
- value: "VIP", // Doesn't match
197
- },
198
- {
199
- type: "deviceId",
200
- operator: "equals",
201
- value: "device-123", // deviceId has value "undefined" in context
202
- },
203
- ],
204
- };
205
- const result = evaluateConditions(conditions, envState);
206
- // deviceId is present in envState with value "undefined", so it checks and returns false
207
- expect(result).toBe(false); // Neither condition matches
208
- });
209
- it("should NOT show block when customer has no tags and deviceId doesn't match", () => {
210
- const envState = getEnvState({
211
- location: { country: "US", language: "en", deviceId: "device-123" },
212
- customer: { id: "customer-1", tags: [] }, // No tags (empty array)
213
- });
214
- const conditions = {
215
- logic: "OR",
216
- conditions: [
217
- {
218
- type: "customerTag",
219
- operator: "equals",
220
- value: "VIP", // Customer has no tags (empty array)
221
- },
222
- {
223
- type: "deviceId",
224
- operator: "equals",
225
- value: "device-999", // Device ID doesn't match
226
- },
227
- ],
228
- };
229
- const result = evaluateConditions(conditions, envState);
230
- expect(result).toBe(false); // Neither condition matches
231
- });
232
- it("should NOT show block when customer is undefined and deviceId doesn't match", () => {
233
- const envState = getEnvState({
234
- location: { country: "US", language: "en", deviceId: "device-123" },
235
- customer: undefined, // Not logged in - customer is undefined
236
- });
237
- const conditions = {
238
- logic: "OR",
239
- conditions: [
240
- {
241
- type: "customerTag",
242
- operator: "equals",
243
- value: "VIP", // Customer is undefined, so customerTag is empty array []
244
- },
245
- {
246
- type: "deviceId",
247
- operator: "equals",
248
- value: "device-999", // Device ID doesn't match
249
- },
250
- ],
251
- };
252
- const result = evaluateConditions(conditions, envState);
253
- // customerTag is present as empty array [], deviceId doesn't match
254
- expect(result).toBe(false); // Neither condition matches
255
- });
256
- it("should correctly handle AND logic with customerTag and deviceId", () => {
257
- const envState = getEnvState({
258
- location: { country: "US", language: "en", deviceId: "device-123" },
259
- customer: { id: "customer-1", tags: ["VIP"] },
260
- });
261
- const conditions = {
262
- logic: "AND",
263
- conditions: [
264
- {
265
- type: "customerTag",
266
- operator: "equals",
267
- value: "VIP",
268
- },
269
- {
270
- type: "deviceId",
271
- operator: "equals",
272
- value: "device-123",
273
- },
274
- ],
275
- };
276
- const result = evaluateConditions(conditions, envState);
277
- expect(result).toBe(true); // Both conditions must match for AND
278
- });
279
- it("should NOT show block with AND logic when only one condition matches", () => {
280
- const envState = getEnvState({
281
- location: { country: "US", language: "en", deviceId: "device-123" },
282
- customer: { id: "customer-1", tags: ["Regular"] },
283
- });
284
- const conditions = {
285
- logic: "AND",
286
- conditions: [
287
- {
288
- type: "customerTag",
289
- operator: "equals",
290
- value: "VIP", // Doesn't match
291
- },
292
- {
293
- type: "deviceId",
294
- operator: "equals",
295
- value: "device-123", // Matches
296
- },
297
- ],
298
- };
299
- const result = evaluateConditions(conditions, envState);
300
- expect(result).toBe(false); // AND requires both to match
301
- });
302
- });
303
- describe("Edge cases with missing context data", () => {
304
- it("KNOWN BEHAVIOR: returns true when checking a condition type that doesn't exist in context", () => {
305
- const envState = {
306
- // Empty context - no data
307
- };
308
- const conditions = {
309
- logic: "OR",
310
- conditions: [
311
- {
312
- type: "customerTag",
313
- operator: "equals",
314
- value: "VIP",
315
- },
316
- ],
317
- };
318
- const result = evaluateConditions(conditions, envState);
319
- // This returns TRUE when context is missing (current behavior)
320
- expect(result).toBe(true);
321
- });
322
- it("should return true for empty conditions array", () => {
323
- const envState = getEnvState({
324
- location: { country: "US", language: "en" },
325
- });
326
- const conditions = {
327
- logic: "OR",
328
- conditions: [],
329
- };
330
- const result = evaluateConditions(conditions, envState);
331
- expect(result).toBe(true); // Empty conditions should pass
332
- });
333
- });
334
- describe("Real-world bug scenario", () => {
335
- it("KNOWN BEHAVIOR: Block configured with 'VIP customer OR specific device' shows when customerTag context is missing", () => {
336
- // This simulates what happens in production:
337
- // - A block is configured to show to VIP customers OR a specific test device
338
- // - But the customerTag key is completely missing from the context
339
- // - This could happen due to a data fetching error, API change, or incomplete context setup
340
- const incompleteEnvState = {
341
- deviceLanguage: [{ value: "English" }],
342
- deviceCountry: [{ value: "United States" }],
343
- deviceId: [{ value: "random-user-device" }], // Not the test device
344
- // customerTag is MISSING entirely
345
- };
346
- const conditions = {
347
- logic: "OR",
348
- conditions: [
349
- {
350
- type: "customerTag",
351
- operator: "equals",
352
- value: "VIP",
353
- },
354
- {
355
- type: "deviceId",
356
- operator: "equals",
357
- value: "test-device-123",
358
- },
359
- ],
360
- };
361
- const result = evaluateConditions(conditions, incompleteEnvState);
362
- // This returns true (current behavior when context is missing)
363
- // Not fixing this behavior in this change
364
- expect(result).toBe(true);
365
- });
366
- it("BUG SCENARIO: Block with trailing empty condition shows to all users", () => {
367
- // This simulates what happens when a user partially deletes a condition in the UI
368
- // leaving behind an empty condition with type="" and value=""
369
- // Real-world example from production data
370
- const envState = getEnvState({
371
- location: {
372
- country: "US",
373
- language: "en",
374
- deviceId: "67442bf1-7433-443b-8446-2a0ac77dc388", // Real device ID
375
- },
376
- });
377
- const conditions = {
378
- logic: "OR",
379
- conditions: [
380
- {
381
- logic: "AND",
382
- conditions: [
383
- {
384
- type: "deviceId",
385
- operator: "equals",
386
- value: "123", // Doesn't match
387
- },
388
- ],
389
- },
390
- {
391
- logic: "OR",
392
- conditions: [
393
- {
394
- type: "deviceId",
395
- operator: "equals",
396
- value: "67442bf1-7433-443b-8446-2a0ac77dc388-a", // Doesn't match
397
- },
398
- {
399
- type: "deviceId",
400
- operator: "equals",
401
- value: "67442bf1-7433-443b-8446-2a0ac77dc388-b", // Doesn't match
402
- },
403
- ],
404
- },
405
- {
406
- logic: "AND",
407
- conditions: [
408
- {
409
- type: "",
410
- operator: "equals",
411
- value: "", // ← Empty value
412
- },
413
- ],
414
- },
415
- ],
416
- };
417
- const result = evaluateConditions(conditions, envState);
418
- // EXPECTED: false (none of the device IDs match)
419
- // ACTUAL (BUG): true (empty condition returns true, making the OR pass)
420
- expect(result).toBe(false);
421
- });
422
- it("BUG SCENARIO: Empty condition should not pass when used with AND logic", () => {
423
- const envState = getEnvState({
424
- location: {
425
- country: "US",
426
- language: "en",
427
- deviceId: "real-device-id",
428
- },
429
- });
430
- const conditions = {
431
- logic: "AND",
432
- conditions: [
433
- {
434
- type: "deviceId",
435
- operator: "equals",
436
- value: "real-device-id", // This matches
437
- },
438
- {
439
- type: "",
440
- operator: "equals",
441
- value: "",
442
- },
443
- ],
444
- };
445
- const result = evaluateConditions(conditions, envState);
446
- // EXPECTED: false (empty condition should fail)
447
- // ACTUAL (BUG): true (empty condition returns true, AND passes)
448
- expect(result).toBe(false);
449
- });
450
- it("BUG SCENARIO: Multiple empty conditions should not pass", () => {
451
- const envState = getEnvState({
452
- location: { country: "US", language: "en" },
453
- });
454
- const conditions = {
455
- logic: "OR",
456
- conditions: [
457
- {
458
- type: "",
459
- operator: "equals",
460
- value: "",
461
- },
462
- {
463
- type: "",
464
- operator: "equals",
465
- value: "",
466
- },
467
- ],
468
- };
469
- const result = evaluateConditions(conditions, envState);
470
- // EXPECTED: false (empty conditions should not pass)
471
- // ACTUAL (BUG): true (all empty conditions return true)
472
- expect(result).toBe(false);
473
- });
474
- });
475
- });
476
- });