Skip to content

Commit aa28a44

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 aa28a44

File tree

2 files changed

+151
-5
lines changed

2 files changed

+151
-5
lines changed

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

Lines changed: 136 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,7 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
169262
...BASE_PAYLOAD,
170263
pageType: 'product',
171264
products: [productPayload],
172-
totalValue: 100,
265+
totalValue: getProductValue(productPayload),
173266
};
174267
const events = pageView(pageViewPayload);
175268

@@ -184,7 +277,6 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
184277
expect(events[1]).toEqual(
185278
getExpectedPayload(pageViewPayload, {
186279
event_name: 'product_page_rendered',
187-
total_value: pageViewPayload.totalValue,
188280
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
189281
products: expect.anything(),
190282
canonical_url: pageViewPayload.url,
@@ -217,7 +309,7 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
217309
...BASE_PAYLOAD,
218310
pageType: 'product',
219311
products: [productPayload],
220-
totalValue: 100,
312+
totalValue: getProductValue(productPayload),
221313
};
222314
const events = pageView(pageViewPayload);
223315

@@ -293,7 +385,7 @@ describe(`analytics schema - custom storefront customer tracking`, () => {
293385
...BASE_PAYLOAD,
294386
cartId: 'gid://shopify/Cart/abc123',
295387
products: [productPayload],
296-
totalValue: 100,
388+
totalValue: getProductValue(productPayload),
297389
};
298390
const events = addToCart(addToCartPayload);
299391

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

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)