Skip to content

Commit 35ab53a

Browse files
committed
fix(tests): use more accurate totalValue
Enhances the tests to ensure the totalValue is more accurate. Establishes that totalValue is indeed the total value of the products in the event.
1 parent 2aff369 commit 35ab53a

File tree

2 files changed

+149
-5
lines changed

2 files changed

+149
-5
lines changed

packages/hydrogen-react/src/analytics-schema-custom-storefront-customer-tracking.test.ts

Lines changed: 134 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,107 @@ import {
88
import {
99
BASE_PAYLOAD,
1010
BASE_PRODUCT_PAYLOAD,
11+
getProductsValue,
12+
getProductValue,
13+
randomNatural,
1114
} from './analytics-schema.test.helpers.js';
1215
import type {
1316
ShopifyAnalyticsPayload,
17+
ShopifyAnalyticsProduct,
1418
ShopifyMonorailPayload,
1519
ShopifyPageViewPayload,
1620
} from './analytics-types.js';
1721
import {version} from '../package.json';
1822

23+
describe(`product value helpers - accurate results`, () => {
24+
describe(`getProductValue`, () => {
25+
it(`gets single quantity product value`, () => {
26+
const productPayload = {
27+
...BASE_PRODUCT_PAYLOAD,
28+
quantity: 1,
29+
};
30+
const calculatedValue = getProductValue(productPayload);
31+
32+
expectType<ShopifyAnalyticsProduct>(productPayload);
33+
expect(calculatedValue).toEqual(parseFloat(productPayload.price));
34+
});
35+
36+
it(`gets arbitrary quantity product value`, () => {
37+
const productPayload = {
38+
...BASE_PRODUCT_PAYLOAD,
39+
quantity: randomNatural(),
40+
};
41+
const calculatedValue = getProductValue(productPayload);
42+
43+
expectType<ShopifyAnalyticsProduct>(productPayload);
44+
expect(calculatedValue).toBeCloseTo(
45+
parseFloat(productPayload.price) * productPayload.quantity,
46+
);
47+
});
48+
});
49+
50+
describe(`getProductsValue`, () => {
51+
it(`gets singleton products value`, () => {
52+
const productPayload = {
53+
...BASE_PRODUCT_PAYLOAD,
54+
quantity: randomNatural(),
55+
};
56+
const productsPayload = [productPayload];
57+
const addToCartPayload = {
58+
...BASE_PAYLOAD,
59+
cartId: 'gid://shopify/Cart/abc123',
60+
products: productsPayload,
61+
totalValue: getProductsValue(productsPayload),
62+
};
63+
64+
expectType<ShopifyAnalyticsProduct>(productPayload);
65+
expect(addToCartPayload.totalValue).toBeCloseTo(
66+
parseFloat(productPayload.price) * productPayload.quantity,
67+
);
68+
});
69+
70+
it(`gets tuple products value`, () => {
71+
const productPayload = {
72+
...BASE_PRODUCT_PAYLOAD,
73+
quantity: randomNatural(),
74+
};
75+
const productsPayload = [productPayload, productPayload];
76+
const addToCartPayload = {
77+
...BASE_PAYLOAD,
78+
cartId: 'gid://shopify/Cart/abc123',
79+
products: productsPayload,
80+
totalValue: getProductsValue(productsPayload),
81+
};
82+
83+
expectType<ShopifyAnalyticsProduct>(productPayload);
84+
expect(addToCartPayload.totalValue).toBeCloseTo(
85+
parseFloat(productPayload.price) * productPayload.quantity * 2,
86+
);
87+
});
88+
89+
it(`gets N products value`, () => {
90+
const productPayload = {
91+
...BASE_PRODUCT_PAYLOAD,
92+
quantity: randomNatural(),
93+
};
94+
const productsPayload = new Array(randomNatural()).fill(productPayload);
95+
const addToCartPayload = {
96+
...BASE_PAYLOAD,
97+
cartId: 'gid://shopify/Cart/abc123',
98+
products: productsPayload,
99+
totalValue: getProductsValue(productsPayload),
100+
};
101+
102+
expectType<ShopifyAnalyticsProduct>(productPayload);
103+
expect(addToCartPayload.totalValue).toBeCloseTo(
104+
parseFloat(productPayload.price) *
105+
productPayload.quantity *
106+
productsPayload.length,
107+
);
108+
});
109+
});
110+
});
111+
19112
describe(`analytics schema - custom storefront customer tracking`, () => {
20113
describe('page view', () => {
21114
it(`base payload with default values`, () => {
@@ -141,7 +234,7 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
141234
const pageViewPayload = {
142235
...BASE_PAYLOAD,
143236
pageType: 'product',
144-
totalValue: 100,
237+
totalValue: getProductsValue(BASE_PAYLOAD.products),
145238
};
146239
const events = pageView(pageViewPayload);
147240

@@ -169,7 +262,6 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
169262
...BASE_PAYLOAD,
170263
pageType: 'product',
171264
products: [productPayload],
172-
totalValue: 100,
173265
};
174266
const events = pageView(pageViewPayload);
175267

@@ -184,7 +276,6 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
184276
expect(events[1]).toEqual(
185277
getExpectedPayload(pageViewPayload, {
186278
event_name: 'product_page_rendered',
187-
total_value: pageViewPayload.totalValue,
188279
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
189280
products: expect.anything(),
190281
canonical_url: pageViewPayload.url,
@@ -217,7 +308,7 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
217308
...BASE_PAYLOAD,
218309
pageType: 'product',
219310
products: [productPayload],
220-
totalValue: 100,
311+
totalValue: getProductValue(productPayload),
221312
};
222313
const events = pageView(pageViewPayload);
223314

@@ -293,7 +384,6 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
293384
...BASE_PAYLOAD,
294385
cartId: 'gid://shopify/Cart/abc123',
295386
products: [productPayload],
296-
totalValue: 100,
297387
};
298388
const events = addToCart(addToCartPayload);
299389

@@ -322,6 +412,45 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
322412
price: parseFloat(productPayload.price),
323413
});
324414
});
415+
416+
it(`with base product payload quantity 1`, () => {
417+
const productPayload = {
418+
...BASE_PRODUCT_PAYLOAD,
419+
quantity: 1,
420+
};
421+
const addToCartPayload = {
422+
...BASE_PAYLOAD,
423+
cartId: 'gid://shopify/Cart/abc123',
424+
products: [productPayload],
425+
totalVale: getProductValue(productPayload),
426+
};
427+
const events = addToCart(addToCartPayload);
428+
429+
expectType<ShopifyMonorailPayload[]>(events);
430+
expect(events.length).toBe(1);
431+
expect(events[0]).toEqual(
432+
getExpectedPayload(addToCartPayload, {
433+
event_name: 'product_added_to_cart',
434+
cart_token: 'abc123',
435+
total_value: addToCartPayload.totalValue,
436+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
437+
products: expect.anything(),
438+
}),
439+
);
440+
const productEventPayload = events[0].payload;
441+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
442+
const product = JSON.parse(
443+
(productEventPayload.products && productEventPayload.products[0]) ||
444+
'{}',
445+
);
446+
expect(product).toEqual({
447+
...getForwardedProductPayload(productPayload),
448+
variant: '',
449+
quantity: 1,
450+
product_id: 1,
451+
price: parseFloat(productPayload.price),
452+
});
453+
});
325454
});
326455
});
327456

packages/hydrogen-react/src/analytics-schema.test.helpers.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,18 @@ export const BASE_PRODUCT_PAYLOAD: ShopifyAnalyticsProduct = {
2626
brand: faker.string.sample(),
2727
price: faker.number.float().toString(),
2828
};
29+
30+
export const randomNatural = () => faker.number.int({min: 1, max: 1000});
31+
32+
/** Get singular product value */
33+
export const getProductValue = (product: ShopifyAnalyticsProduct): number =>
34+
parseFloat(product.price) * (product.quantity || 0);
35+
/** Reduce all products and get totalValue */
36+
export const getProductsValue = (
37+
products?: ShopifyAnalyticsProduct[],
38+
): number | undefined =>
39+
products?.reduce(
40+
(previousValue, currentProduct) =>
41+
previousValue + getProductValue(currentProduct),
42+
0,
43+
);

0 commit comments

Comments
 (0)