UNPKG

12.5 kBJavaScriptView Raw
1import {
2 flattenList,
3 getVariantFromProductDetails,
4 getProductDetailForFlattenedProductList,
5 normalizeServerList
6} from './list-transforms';
7
8const MOCK_LIST = {
9 '6952315': {
10 options: { quantity: 1 },
11 variants: {
12 '6952315-170-white': {
13 options: {
14 quantity: 1
15 },
16 parentArticleNumber: '6952315'
17 }
18 }
19 },
20 '502935480': {
21 variants: null,
22 options: {
23 quantity: 1
24 }
25 },
26 '441922-Classic-16': {
27 variants: null,
28 options: {
29 quantity: 1
30 }
31 },
32 'without-base': {
33 options: null,
34 variants: {
35 'with-variant': {
36 options: {
37 quantity: 1
38 },
39 parentArticleNumber: 'without-base'
40 }
41 }
42 }
43};
44
45const MOCK_PRODUCT_WITH_VARIANTS = {
46 variants: {
47 options: [
48 {
49 name: 'Size',
50 values: ['36', '37', '38'],
51 __typename: 'ProductVariantOption'
52 }
53 ],
54 values: [
55 {
56 id: '441728-36',
57 articleNumber: '441728-36',
58 values: ['36'],
59 stockStatus: {
60 buyable: true,
61 text: 'In stock',
62 __typename: 'StockStatus'
63 },
64 images: [
65 {
66 alt: '441728',
67 title: 'Belt Light',
68 url: 'https://www.demostore.se/pub_images/original/441728.jpg',
69 __typename: 'ProductImage'
70 }
71 ],
72 __typename: 'ProductVariant'
73 },
74 {
75 id: '441728-37',
76 articleNumber: '441728-37',
77 values: ['37'],
78 stockStatus: {
79 buyable: true,
80 text: 'In stock',
81 __typename: 'StockStatus'
82 },
83 images: [
84 {
85 alt: 'Belt Light',
86 title: 'Belt Light',
87 url: 'https://www.demostore.se/pub_images/original/441728.jpg',
88 __typename: 'ProductImage'
89 }
90 ],
91 __typename: 'ProductVariant'
92 },
93 {
94 id: '441728-38',
95 articleNumber: '441728-38',
96 values: ['38'],
97 stockStatus: {
98 buyable: true,
99 text: 'In stock',
100 __typename: 'StockStatus'
101 },
102 images: [
103 {
104 alt: 'Belt Light',
105 title: 'Belt Light',
106 url: 'https://www.demostore.se/pub_images/original/441728.jpg',
107 __typename: 'ProductImage'
108 }
109 ],
110 __typename: 'ProductVariant'
111 }
112 ],
113 __typename: 'ProductVariants'
114 },
115 id: 483,
116 articleNumber: '441728',
117 name: 'Belt Light',
118 hasConfigurations: false,
119 hasVariants: true,
120 isPreOrder: false,
121 stockStatus: {
122 buyable: true,
123 text: 'In stock',
124 __typename: 'StockStatus'
125 },
126 __typename: 'Product',
127 images: [
128 {
129 alt: '441728',
130 title: 'Belt Light',
131 url: 'https://www.demostore.se/pub_images/original/441728.jpg',
132 __typename: 'ProductImage'
133 }
134 ]
135};
136
137const MOCK_PRODUCT_QUERY_RESULT = {
138 loading: false,
139 data: {
140 products: [
141 {
142 variants: {
143 options: [
144 {
145 name: 'Size',
146 values: ['36', '37', '38'],
147 __typename: 'ProductVariantOption'
148 }
149 ],
150 values: [
151 {
152 id: '441728-36',
153 articleNumber: '441728-36',
154 values: ['36'],
155 stockStatus: {
156 buyable: true,
157 text: 'In stock',
158 __typename: 'StockStatus'
159 },
160 images: [
161 {
162 alt: '441728',
163 title: 'Belt Light',
164 url:
165 'https://www.demostore.se/pub_images/original/VARIANTIMAGE.jpg',
166 __typename: 'ProductImage'
167 }
168 ],
169 __typename: 'ProductVariant'
170 },
171 {
172 id: '441728-37',
173 articleNumber: '441728-37',
174 values: ['37'],
175 stockStatus: {
176 buyable: true,
177 text: 'In stock',
178 __typename: 'StockStatus'
179 },
180 images: [
181 {
182 alt: 'Belt Light',
183 title: 'Belt Light',
184 url:
185 'https://www.demostore.se/pub_images/original/441728.jpg',
186 __typename: 'ProductImage'
187 }
188 ],
189 __typename: 'ProductVariant'
190 },
191 {
192 id: '441728-38',
193 articleNumber: '441728-38',
194 values: ['38'],
195 stockStatus: {
196 buyable: true,
197 text: 'In stock',
198 __typename: 'StockStatus'
199 },
200 images: [
201 {
202 alt: 'Belt Light',
203 title: 'Belt Light',
204 url:
205 'https://www.demostore.se/pub_images/original/441728.jpg',
206 __typename: 'ProductImage'
207 }
208 ],
209 __typename: 'ProductVariant'
210 }
211 ],
212 __typename: 'ProductVariants'
213 },
214 id: 483,
215 articleNumber: '441728',
216 name: 'Belt Light',
217 subName: 'PantsUp',
218 hasConfigurations: false,
219 hasVariants: true,
220 isPreOrder: false,
221 stockStatus: {
222 buyable: true,
223 text: 'In stock',
224 __typename: 'StockStatus'
225 },
226 primaryRoute: {
227 id: 'accessories/belts/belt-light',
228 path: '/accessories/belts/belt-light',
229 slug: 'belt-light',
230 __typename: 'Route'
231 },
232 price: {
233 incVat: 500,
234 exVat: 400,
235 vat: 100,
236 __typename: 'Price'
237 },
238 previousPrice: {
239 incVat: 1375,
240 exVat: 1100,
241 vat: 275,
242 __typename: 'Price'
243 },
244 __typename: 'Product',
245 badges: [
246 {
247 name: 'SALE Top Left',
248 url:
249 'https://www.demostore.se/M1/production/images/overlay/overlay8_en-GB.png',
250 location: 'TOP_LEFT',
251 style: '',
252 text: '',
253 __typename: 'ProductBadge'
254 }
255 ],
256 images: [
257 {
258 alt: '441728',
259 title: 'Belt Light',
260 url: 'https://www.demostore.se/pub_images/original/441728.jpg',
261 __typename: 'ProductImage'
262 }
263 ]
264 }
265 ]
266 }
267};
268
269describe('flattenList', () => {
270 it('takes a normalized list and returns an array of items', () => {
271 const flattened = flattenList(MOCK_LIST);
272
273 expect(flattened).toMatchSnapshot();
274 });
275
276 it('creates a unique entry for each variant', () => {
277 const options = { quantity: 1 };
278
279 const list = {
280 baseProduct: {
281 options: null,
282 variants: {
283 'variant-one': {
284 options,
285 parentArticleNumber: 'baseProduct'
286 },
287 'variant-two': {
288 options,
289 parentArticleNumber: 'baseProduct'
290 }
291 }
292 }
293 };
294
295 const flattened = flattenList(list);
296 expect(flattened).toHaveLength(2);
297 expect(flattened[0].articleNumber).toBe('variant-one');
298 expect(flattened[1].articleNumber).toBe('variant-two');
299 });
300 it('creates unique entries for variants and the base product', () => {
301 const options = { quantity: 1 };
302
303 const list = {
304 baseProduct: {
305 options: options,
306 variants: {
307 'variant-one': {
308 options,
309 parentArticleNumber: 'baseProduct'
310 },
311 'variant-two': {
312 options,
313 parentArticleNumber: 'baseProduct'
314 }
315 }
316 }
317 };
318
319 const flattened = flattenList(list);
320 expect(flattened).toHaveLength(3);
321 expect(flattened[0].articleNumber).toBe('variant-one');
322 expect(flattened[1].articleNumber).toBe('variant-two');
323 expect(flattened[2].articleNumber).toBe('baseProduct');
324 });
325});
326
327describe('getVariantFromProductDetails', () => {
328 it('returns null when no variant is given', () => {
329 const result = getVariantFromProductDetails(
330 undefined,
331 MOCK_PRODUCT_WITH_VARIANTS
332 );
333
334 expect(result).toBe(null);
335 });
336 it('returns the correct variant when a variant article number is given', () => {
337 const result = getVariantFromProductDetails(
338 '441728-37',
339 MOCK_PRODUCT_WITH_VARIANTS
340 );
341
342 expect(result).toBe(
343 MOCK_PRODUCT_WITH_VARIANTS.variants.values.find(
344 variant => variant.articleNumber === '441728-37'
345 )
346 );
347 });
348 it('returns null when a variant cannot be found', () => {
349 const result = getVariantFromProductDetails(
350 'fgdgdfg',
351 MOCK_PRODUCT_WITH_VARIANTS
352 );
353
354 expect(result).toBe(null);
355 });
356});
357
358describe('getProductDetailForFlattenedProductList', () => {
359 let result;
360 let baseProduct;
361 let variant;
362 beforeEach(() => {
363 const options = { quantity: 2 };
364 const list = [
365 {
366 articleNumber: '441728',
367 options
368 },
369 {
370 articleNumber: '441728-36',
371 options,
372 parentArticleNumber: '441728'
373 }
374 ];
375 const queryResult = MOCK_PRODUCT_QUERY_RESULT;
376
377 result = getProductDetailForFlattenedProductList(list, queryResult);
378 baseProduct = result[0];
379 variant = result[1];
380 });
381 it(`gets product detail for each item in a flattened list`, () => {
382 expect(result.length).toBe(2);
383 });
384 it(`returns validation messages for products that can't be added to the cart`, () => {
385 expect(baseProduct.validation.status).toBe(`missingVariant`);
386 });
387 it(`appends variant detail to variant key and sets isVariant`, () => {
388 expect(variant.variant.articleNumber).toBe('441728-36');
389 expect(variant.isVariant).toBe(true);
390 expect(baseProduct.variant).toBe(null);
391 expect(baseProduct.isVariant).toBe(false);
392 });
393});
394
395describe('normalizeServerList', () => {
396 let serverList;
397 beforeEach(() => {
398 serverList = {
399 customerProductList: {
400 items: [
401 {
402 quantity: 1,
403 description: 'hello',
404 product: {
405 articleNumber: 'without-variants'
406 },
407 variant: null
408 },
409 {
410 quantity: 1,
411 description: 'hello',
412 product: {
413 articleNumber: 'with-variants'
414 },
415 variant: {
416 articleNumber: 'the-variant'
417 }
418 },
419 {
420 quantity: 1,
421 description: 'hello',
422 product: {
423 articleNumber: 'with-many-variants'
424 },
425 variant: {
426 articleNumber: 'variant-one'
427 }
428 },
429 {
430 quantity: 1,
431 description: 'hello',
432 product: {
433 articleNumber: 'with-many-variants'
434 },
435 variant: {
436 articleNumber: 'variant-two'
437 }
438 },
439 {
440 quantity: 1,
441 description: 'hello',
442 product: {
443 articleNumber: 'with-base-and-variants'
444 },
445 variant: null
446 },
447 {
448 quantity: 1,
449 description: 'hello',
450 product: {
451 articleNumber: 'with-base-and-variants'
452 },
453 variant: {
454 articleNumber: 'variant-one'
455 }
456 }
457 ]
458 }
459 };
460 });
461 it('returns an empty object if an invalid list if passed in', () => {
462 const result = normalizeServerList({ not: 'a list' });
463
464 expect(result).toEqual({});
465 });
466 it('creates the expected shape', () => {
467 const result = normalizeServerList(serverList);
468
469 expect(result['without-variants'].variants).toBe(null);
470 expect(result['without-variants'].options.quantity).toBe(1);
471
472 expect(result['with-variants'].options).toBe(null);
473 expect(
474 result['with-variants'].variants['the-variant'].options.quantity
475 ).toBe(1);
476
477 expect(result['with-many-variants'].options).toBe(null);
478 expect(result['with-many-variants'].variants['variant-one']).toBeDefined();
479 expect(result['with-many-variants'].variants['variant-two']).toBeDefined();
480
481 expect(result['with-base-and-variants'].options).toBeDefined();
482 expect(
483 result['with-base-and-variants'].variants['variant-one']
484 ).toBeDefined();
485 });
486});