@times-components/ts-components 1.146.2-a0ffbb6bc2acbec91d140a39f6be06256e702094.5 → 1.146.2-c12ed7999a41984c2ba8c437357e7a5df1914881.48

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.
Files changed (137) hide show
  1. package/dist/components/carousel-component/CarouselComponent.stories.d.ts +1 -0
  2. package/dist/components/carousel-component/CarouselComponent.stories.js +146 -0
  3. package/dist/components/carousel-component/CarouselItem.d.ts +3 -0
  4. package/dist/components/carousel-component/CarouselItem.js +12 -0
  5. package/dist/components/carousel-component/DefaultNavigationArrow.d.ts +8 -0
  6. package/dist/components/carousel-component/DefaultNavigationArrow.js +6 -0
  7. package/dist/components/carousel-component/DefaultPageDot.d.ts +8 -0
  8. package/dist/components/carousel-component/DefaultPageDot.js +4 -0
  9. package/dist/components/carousel-component/__tests__/CarouselComponent.test.d.ts +1 -0
  10. package/dist/components/carousel-component/__tests__/CarouselComponent.test.js +163 -0
  11. package/dist/components/carousel-component/__tests__/CarouselItem.test.d.ts +1 -0
  12. package/dist/components/carousel-component/__tests__/CarouselItem.test.js +80 -0
  13. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.d.ts +1 -0
  14. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.js +62 -0
  15. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.d.ts +1 -0
  16. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.js +68 -0
  17. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.d.ts +1 -0
  18. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.js +459 -0
  19. package/dist/components/carousel-component/hooks/useCarousel.d.ts +2 -0
  20. package/dist/components/carousel-component/hooks/useCarousel.js +167 -0
  21. package/dist/components/carousel-component/index.d.ts +4 -0
  22. package/dist/components/carousel-component/index.js +20 -0
  23. package/dist/components/carousel-component/styles.d.ts +28 -0
  24. package/dist/components/carousel-component/styles.js +172 -0
  25. package/dist/components/carousel-component/types.d.ts +53 -0
  26. package/dist/components/carousel-component/types.js +2 -0
  27. package/dist/components/social-embed/SocialMediaEmbed.js +15 -122
  28. package/dist/components/social-embed/SocialVendor.d.ts +16 -1
  29. package/dist/components/social-embed/SocialVendor.js +2 -41
  30. package/dist/components/social-embed/__tests__/SocialVendor.test.js +1 -8
  31. package/dist/components/social-embed/constants.d.ts +0 -1
  32. package/dist/components/social-embed/constants.js +2 -3
  33. package/dist/components/social-embed/helpers/socialMediaVendors.js +1 -6
  34. package/dist/components/social-embed/styles.d.ts +0 -1
  35. package/dist/components/social-embed/styles.js +1 -28
  36. package/dist/components/trip-cards/SkeletonCard.d.ts +7 -0
  37. package/dist/components/trip-cards/SkeletonCard.js +22 -0
  38. package/dist/components/trip-cards/TripCard.d.ts +3 -0
  39. package/dist/components/trip-cards/TripCard.js +61 -0
  40. package/dist/components/trip-cards/TripCards.stories.d.ts +1 -0
  41. package/dist/components/trip-cards/TripCards.stories.js +159 -0
  42. package/dist/components/trip-cards/TripCardsLayout.d.ts +3 -0
  43. package/dist/components/trip-cards/TripCardsLayout.js +63 -0
  44. package/dist/components/trip-cards/__tests__/SkeletonCard.test.d.ts +1 -0
  45. package/dist/components/trip-cards/__tests__/SkeletonCard.test.js +139 -0
  46. package/dist/components/trip-cards/__tests__/TripCard.test.d.ts +1 -0
  47. package/dist/components/trip-cards/__tests__/TripCard.test.js +165 -0
  48. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.d.ts +1 -0
  49. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.js +353 -0
  50. package/dist/components/trip-cards/__tests__/assets.test.d.ts +1 -0
  51. package/dist/components/trip-cards/__tests__/assets.test.js +165 -0
  52. package/dist/components/trip-cards/__tests__/helpers.test.d.ts +1 -0
  53. package/dist/components/trip-cards/__tests__/helpers.test.js +221 -0
  54. package/dist/components/trip-cards/__tests__/index.test.d.ts +1 -0
  55. package/dist/components/trip-cards/__tests__/index.test.js +482 -0
  56. package/dist/components/trip-cards/__tests__/mockData.test.d.ts +1 -0
  57. package/dist/components/trip-cards/__tests__/mockData.test.js +57 -0
  58. package/dist/components/trip-cards/__tests__/skeletonStyles.test.d.ts +1 -0
  59. package/dist/components/trip-cards/__tests__/skeletonStyles.test.js +194 -0
  60. package/dist/components/trip-cards/assets/BoatIcon.d.ts +1 -0
  61. package/dist/components/trip-cards/assets/BoatIcon.js +4 -0
  62. package/dist/components/trip-cards/assets/CalendarIcon.d.ts +1 -0
  63. package/dist/components/trip-cards/assets/CalendarIcon.js +4 -0
  64. package/dist/components/trip-cards/assets/ChevronRightIcon.d.ts +1 -0
  65. package/dist/components/trip-cards/assets/ChevronRightIcon.js +4 -0
  66. package/dist/components/trip-cards/assets/LocationIcon.d.ts +1 -0
  67. package/dist/components/trip-cards/assets/LocationIcon.js +4 -0
  68. package/dist/components/trip-cards/assets/MoonIcon.d.ts +1 -0
  69. package/dist/components/trip-cards/assets/MoonIcon.js +4 -0
  70. package/dist/components/trip-cards/assets/index.d.ts +6 -0
  71. package/dist/components/trip-cards/assets/index.js +7 -0
  72. package/dist/components/trip-cards/helpers.d.ts +11 -0
  73. package/dist/components/trip-cards/helpers.js +144 -0
  74. package/dist/components/trip-cards/index.d.ts +4 -0
  75. package/dist/components/trip-cards/index.js +68 -0
  76. package/dist/components/trip-cards/mockData.d.ts +3 -0
  77. package/dist/components/trip-cards/mockData.js +317 -0
  78. package/dist/components/trip-cards/skeletonStyles.d.ts +9 -0
  79. package/dist/components/trip-cards/skeletonStyles.js +37 -0
  80. package/dist/components/trip-cards/styles.d.ts +43 -0
  81. package/dist/components/trip-cards/styles.js +404 -0
  82. package/dist/components/trip-cards/types.d.ts +121 -0
  83. package/dist/components/trip-cards/types.js +2 -0
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.js +2 -1
  86. package/dist/utils/cookie.d.ts +1 -0
  87. package/dist/utils/cookie.js +8 -1
  88. package/package.json +3 -3
  89. package/rnw.js +1 -1
  90. package/src/components/carousel-component/CarouselComponent.stories.tsx +220 -0
  91. package/src/components/carousel-component/CarouselItem.tsx +26 -0
  92. package/src/components/carousel-component/DefaultNavigationArrow.tsx +37 -0
  93. package/src/components/carousel-component/DefaultPageDot.tsx +20 -0
  94. package/src/components/carousel-component/__tests__/CarouselComponent.test.tsx +259 -0
  95. package/src/components/carousel-component/__tests__/CarouselItem.test.tsx +140 -0
  96. package/src/components/carousel-component/__tests__/DefaultNavigationArrow.test.tsx +153 -0
  97. package/src/components/carousel-component/__tests__/DefaultPageDot.test.tsx +105 -0
  98. package/src/components/carousel-component/hooks/__tests__/useCarousel.test.ts +625 -0
  99. package/src/components/carousel-component/hooks/useCarousel.ts +229 -0
  100. package/src/components/carousel-component/index.tsx +92 -0
  101. package/src/components/carousel-component/styles.ts +188 -0
  102. package/src/components/carousel-component/types.ts +62 -0
  103. package/src/components/social-embed/SocialMediaEmbed.tsx +1 -111
  104. package/src/components/social-embed/SocialVendor.tsx +1 -46
  105. package/src/components/social-embed/__tests__/SocialVendor.test.tsx +0 -11
  106. package/src/components/social-embed/constants.ts +1 -2
  107. package/src/components/social-embed/helpers/socialMediaVendors.ts +0 -5
  108. package/src/components/social-embed/styles.ts +0 -30
  109. package/src/components/trip-cards/SkeletonCard.tsx +64 -0
  110. package/src/components/trip-cards/TripCard.tsx +172 -0
  111. package/src/components/trip-cards/TripCards.stories.tsx +224 -0
  112. package/src/components/trip-cards/TripCardsLayout.tsx +162 -0
  113. package/src/components/trip-cards/__tests__/SkeletonCard.test.tsx +169 -0
  114. package/src/components/trip-cards/__tests__/TripCard.test.tsx +255 -0
  115. package/src/components/trip-cards/__tests__/TripCardsLayout.test.tsx +671 -0
  116. package/src/components/trip-cards/__tests__/assets.test.tsx +206 -0
  117. package/src/components/trip-cards/__tests__/helpers.test.ts +273 -0
  118. package/src/components/trip-cards/__tests__/index.test.tsx +554 -0
  119. package/src/components/trip-cards/__tests__/mockData.test.ts +67 -0
  120. package/src/components/trip-cards/__tests__/skeletonStyles.test.tsx +256 -0
  121. package/src/components/trip-cards/assets/BoatIcon.tsx +17 -0
  122. package/src/components/trip-cards/assets/CalendarIcon.tsx +17 -0
  123. package/src/components/trip-cards/assets/ChevronRightIcon.tsx +20 -0
  124. package/src/components/trip-cards/assets/LocationIcon.tsx +17 -0
  125. package/src/components/trip-cards/assets/MoonIcon.tsx +17 -0
  126. package/src/components/trip-cards/assets/index.ts +7 -0
  127. package/src/components/trip-cards/helpers.ts +181 -0
  128. package/src/components/trip-cards/index.tsx +120 -0
  129. package/src/components/trip-cards/mockData.ts +345 -0
  130. package/src/components/trip-cards/skeletonStyles.ts +46 -0
  131. package/src/components/trip-cards/styles.ts +450 -0
  132. package/src/components/trip-cards/types.ts +130 -0
  133. package/src/index.ts +2 -0
  134. package/src/utils/cookie.ts +8 -0
  135. package/dist/components/social-embed/components/FacebookComponent.d.ts +0 -6
  136. package/dist/components/social-embed/components/FacebookComponent.js +0 -74
  137. package/src/components/social-embed/components/FacebookComponent.tsx +0 -93
@@ -0,0 +1,671 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import { TripCardsLayout } from '../TripCardsLayout';
5
+ import { TripCardApiData } from '../types';
6
+ import { tealiumTrackingHandler } from '../../../helpers/tracking/TrackingHandler';
7
+
8
+ jest.mock('../../../helpers/tracking/TrackingHandler', () => ({
9
+ tealiumTrackingHandler: jest.fn()
10
+ }));
11
+
12
+ const mockElement = {
13
+ class: 'trip-cards',
14
+ tripcards: btoa(JSON.stringify([1, 2])),
15
+ title: 'Test Cruises',
16
+ titleurl: 'https://example.com',
17
+ description: 'Test Description'
18
+ };
19
+
20
+ const MockCard = ({ card }: { card?: TripCardApiData }) => (
21
+ <div data-testid="mock-card">
22
+ {card ? card.headline || 'Mock Card' : 'Mock Card'}
23
+ </div>
24
+ );
25
+
26
+ // Mock ResizeObserver
27
+ global.ResizeObserver = class ResizeObserver {
28
+ public observe(): void {
29
+ // Mock implementation
30
+ }
31
+ public unobserve(): void {
32
+ // Mock implementation
33
+ }
34
+ public disconnect(): void {
35
+ // Mock implementation
36
+ }
37
+ };
38
+
39
+ describe('TripCardsLayout', () => {
40
+ beforeEach(() => {
41
+ jest.clearAllMocks();
42
+ Element.prototype.scrollTo = jest.fn();
43
+
44
+ // Mock matchMedia for each test
45
+ Object.defineProperty(window, 'matchMedia', {
46
+ writable: true,
47
+ configurable: true,
48
+ value: jest.fn().mockImplementation(query => ({
49
+ matches: false,
50
+ media: query,
51
+ onchange: null,
52
+ addListener: jest.fn(),
53
+ removeListener: jest.fn(),
54
+ addEventListener: jest.fn(),
55
+ removeEventListener: jest.fn(),
56
+ dispatchEvent: jest.fn()
57
+ }))
58
+ });
59
+ });
60
+
61
+ afterEach(() => {
62
+ jest.clearAllMocks();
63
+ });
64
+
65
+ describe('Rendering', () => {
66
+ it('renders with title and description', () => {
67
+ const items = [
68
+ { id: '1', data: undefined },
69
+ { id: '2', data: undefined }
70
+ ];
71
+
72
+ render(
73
+ <TripCardsLayout
74
+ element={mockElement}
75
+ items={items}
76
+ CardComponent={MockCard}
77
+ itemsPerPage={2}
78
+ />
79
+ );
80
+
81
+ expect(screen.getByText('Test Cruises')).toBeInTheDocument();
82
+ expect(screen.getByText('Test Description')).toBeInTheDocument();
83
+ });
84
+
85
+ it('renders empty title when not provided', () => {
86
+ const elementWithoutTitle = {
87
+ ...mockElement,
88
+ title: undefined
89
+ };
90
+
91
+ const items = [{ id: '1', data: undefined }];
92
+
93
+ const { container } = render(
94
+ <TripCardsLayout
95
+ element={elementWithoutTitle}
96
+ items={items}
97
+ CardComponent={MockCard}
98
+ itemsPerPage={2}
99
+ />
100
+ );
101
+
102
+ const title = container.querySelector('h2');
103
+ expect(title).toBeInTheDocument();
104
+ expect(title).toBeEmptyDOMElement();
105
+ });
106
+
107
+ it('renders empty description when not provided', () => {
108
+ const elementWithoutDesc = {
109
+ ...mockElement,
110
+ description: undefined
111
+ };
112
+
113
+ const items = [{ id: '1', data: undefined }];
114
+
115
+ const { container } = render(
116
+ <TripCardsLayout
117
+ element={elementWithoutDesc}
118
+ items={items}
119
+ CardComponent={MockCard}
120
+ itemsPerPage={2}
121
+ />
122
+ );
123
+
124
+ const description = container.querySelector('p');
125
+ expect(description).toBeInTheDocument();
126
+ expect(description).toBeEmptyDOMElement();
127
+ });
128
+
129
+ it('renders title link when provided', () => {
130
+ const items = [{ id: '1', data: undefined }];
131
+
132
+ render(
133
+ <TripCardsLayout
134
+ element={mockElement}
135
+ items={items}
136
+ CardComponent={MockCard}
137
+ itemsPerPage={2}
138
+ />
139
+ );
140
+
141
+ const link = screen.getByTestId('trip-cards-title-link');
142
+ expect(link).toHaveAttribute('href', 'https://example.com');
143
+ expect(link).toHaveAttribute('target', '_blank');
144
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer');
145
+ });
146
+
147
+ it('renders two links when titleurl is provided', () => {
148
+ const items = [{ id: '1', data: undefined }];
149
+
150
+ render(
151
+ <TripCardsLayout
152
+ element={mockElement}
153
+ items={items}
154
+ CardComponent={MockCard}
155
+ itemsPerPage={2}
156
+ />
157
+ );
158
+
159
+ const links = screen.getAllByRole('link');
160
+ expect(links).toHaveLength(2);
161
+
162
+ const titleLink = screen.getByTestId('trip-cards-title-link');
163
+ const iconLink = screen.getByTestId('title-link');
164
+
165
+ expect(titleLink).toHaveAttribute('href', 'https://example.com');
166
+ expect(iconLink).toHaveAttribute('href', 'https://example.com');
167
+ });
168
+
169
+ it('does not render title link when not provided', () => {
170
+ const elementWithoutLink = {
171
+ ...mockElement,
172
+ titleurl: undefined
173
+ };
174
+
175
+ const items = [{ id: '1', data: undefined }];
176
+
177
+ render(
178
+ <TripCardsLayout
179
+ element={elementWithoutLink}
180
+ items={items}
181
+ CardComponent={MockCard}
182
+ itemsPerPage={2}
183
+ />
184
+ );
185
+
186
+ const links = screen.queryAllByRole('link');
187
+ expect(links.length).toBe(0);
188
+ });
189
+
190
+ it('renders ChevronRightIcon in title link', () => {
191
+ const items = [{ id: '1', data: undefined }];
192
+
193
+ const { container } = render(
194
+ <TripCardsLayout
195
+ element={mockElement}
196
+ items={items}
197
+ CardComponent={MockCard}
198
+ itemsPerPage={2}
199
+ />
200
+ );
201
+
202
+ const svg = container.querySelector('svg');
203
+ expect(svg).toBeInTheDocument();
204
+ });
205
+ });
206
+
207
+ describe('Static Grid Layout', () => {
208
+ it('renders static grid for exactly 2 items', () => {
209
+ const items = [
210
+ { id: '1', data: undefined },
211
+ { id: '2', data: undefined }
212
+ ];
213
+
214
+ render(
215
+ <TripCardsLayout
216
+ element={mockElement}
217
+ items={items}
218
+ CardComponent={MockCard}
219
+ itemsPerPage={2}
220
+ />
221
+ );
222
+
223
+ const staticGrid = screen.getByTestId('static-cards-grid');
224
+ expect(staticGrid).toBeInTheDocument();
225
+ });
226
+
227
+ it('renders correct number of cards in static grid', () => {
228
+ const items = [
229
+ { id: '1', data: undefined },
230
+ { id: '2', data: undefined }
231
+ ];
232
+
233
+ render(
234
+ <TripCardsLayout
235
+ element={mockElement}
236
+ items={items}
237
+ CardComponent={MockCard}
238
+ itemsPerPage={2}
239
+ />
240
+ );
241
+
242
+ const cards = screen.getAllByTestId('mock-card');
243
+ expect(cards.length).toBe(2);
244
+ });
245
+
246
+ it('passes correct props to CardComponent in static grid', () => {
247
+ const mockData: TripCardApiData = {
248
+ cruise_id: '1',
249
+ image: 'test.jpg',
250
+ headline: 'Test Cruise',
251
+ date: 'Jan 2024',
252
+ duration: '7 nights',
253
+ route: 'Test Route',
254
+ ship: 'Test Ship',
255
+ price: '£1000',
256
+ logo: 'logo.png',
257
+ logo_url: 'https://example.com',
258
+ logo_name: 'Test Cruise Line',
259
+ cta_url: 'https://example.com',
260
+ cta_text: 'View'
261
+ };
262
+
263
+ const items = [{ id: '1', data: mockData }, { id: '2', data: undefined }];
264
+
265
+ render(
266
+ <TripCardsLayout
267
+ element={mockElement}
268
+ items={items}
269
+ CardComponent={MockCard}
270
+ itemsPerPage={2}
271
+ />
272
+ );
273
+
274
+ expect(screen.getByText('Test Cruise')).toBeInTheDocument();
275
+ });
276
+ });
277
+
278
+ describe('Carousel Layout', () => {
279
+ it('renders carousel for more than 2 items', () => {
280
+ const items = [
281
+ { id: '1', data: undefined },
282
+ { id: '2', data: undefined },
283
+ { id: '3', data: undefined }
284
+ ];
285
+
286
+ render(
287
+ <TripCardsLayout
288
+ element={mockElement}
289
+ items={items}
290
+ CardComponent={MockCard}
291
+ itemsPerPage={2}
292
+ />
293
+ );
294
+
295
+ const cards = screen.getAllByTestId('mock-card');
296
+ expect(cards.length).toBe(3);
297
+ });
298
+
299
+ it('renders navigation arrows in carousel', () => {
300
+ const items = [
301
+ { id: '1', data: undefined },
302
+ { id: '2', data: undefined },
303
+ { id: '3', data: undefined }
304
+ ];
305
+
306
+ render(
307
+ <TripCardsLayout
308
+ element={mockElement}
309
+ items={items}
310
+ CardComponent={MockCard}
311
+ itemsPerPage={2}
312
+ />
313
+ );
314
+
315
+ expect(screen.getByLabelText('Previous items')).toBeInTheDocument();
316
+ expect(screen.getByLabelText('Next items')).toBeInTheDocument();
317
+ });
318
+
319
+ it('renders page dots in carousel', () => {
320
+ const items = [
321
+ { id: '1', data: undefined },
322
+ { id: '2', data: undefined },
323
+ { id: '3', data: undefined },
324
+ { id: '4', data: undefined }
325
+ ];
326
+
327
+ render(
328
+ <TripCardsLayout
329
+ element={mockElement}
330
+ items={items}
331
+ CardComponent={MockCard}
332
+ itemsPerPage={2}
333
+ />
334
+ );
335
+
336
+ expect(screen.getByLabelText('Previous items')).toBeInTheDocument();
337
+ expect(screen.getByLabelText('Next items')).toBeInTheDocument();
338
+
339
+ // With 4 items and 2 per page, we have 2 pages, so we should have 2 dot buttons
340
+ const pageDots = screen.getAllByLabelText(/Go to page/i);
341
+ expect(pageDots.length).toBe(2);
342
+ });
343
+
344
+ it('renders carousel for 1 item', () => {
345
+ const items = [{ id: '1', data: undefined }];
346
+
347
+ render(
348
+ <TripCardsLayout
349
+ element={mockElement}
350
+ items={items}
351
+ CardComponent={MockCard}
352
+ itemsPerPage={2}
353
+ />
354
+ );
355
+
356
+ const cards = screen.getAllByTestId('mock-card');
357
+ expect(cards.length).toBe(1);
358
+ });
359
+
360
+ it('wraps cards in CarouselItem with correct widthConfig', () => {
361
+ const items = [
362
+ { id: '1', data: undefined },
363
+ { id: '2', data: undefined },
364
+ { id: '3', data: undefined }
365
+ ];
366
+
367
+ render(
368
+ <TripCardsLayout
369
+ element={mockElement}
370
+ items={items}
371
+ CardComponent={MockCard}
372
+ itemsPerPage={2}
373
+ />
374
+ );
375
+
376
+ // Verify carousel is rendering by checking for cards
377
+ const cards = screen.getAllByTestId('mock-card');
378
+ expect(cards.length).toBe(3);
379
+ });
380
+ });
381
+
382
+ describe('Card Rendering', () => {
383
+ it('renders each item with unique key', () => {
384
+ const items = [
385
+ { id: 'card-1', data: undefined },
386
+ { id: 'card-2', data: undefined }
387
+ ];
388
+
389
+ render(
390
+ <TripCardsLayout
391
+ element={mockElement}
392
+ items={items}
393
+ CardComponent={MockCard}
394
+ itemsPerPage={2}
395
+ />
396
+ );
397
+
398
+ const cards = screen.getAllByTestId('mock-card');
399
+ expect(cards.length).toBe(2);
400
+ });
401
+
402
+ it('passes data to CardComponent', () => {
403
+ const mockData: TripCardApiData = {
404
+ cruise_id: '123',
405
+ image: 'image.jpg',
406
+ headline: 'Specific Cruise',
407
+ date: 'Feb 2024',
408
+ duration: '10 nights',
409
+ route: 'Route A',
410
+ ship: 'Ship X',
411
+ price: '£2000',
412
+ logo: 'logo.png',
413
+ logo_url: 'https://example.com',
414
+ logo_name: 'Test Cruise Line',
415
+ cta_url: 'https://example.com',
416
+ cta_text: 'Book'
417
+ };
418
+
419
+ const items = [
420
+ { id: '1', data: mockData },
421
+ { id: '2', data: undefined },
422
+ { id: '3', data: undefined }
423
+ ];
424
+
425
+ render(
426
+ <TripCardsLayout
427
+ element={mockElement}
428
+ items={items}
429
+ CardComponent={MockCard}
430
+ itemsPerPage={2}
431
+ />
432
+ );
433
+
434
+ expect(screen.getByText('Specific Cruise')).toBeInTheDocument();
435
+ });
436
+
437
+ it('handles empty items array', () => {
438
+ const { container } = render(
439
+ <TripCardsLayout
440
+ element={mockElement}
441
+ items={[]}
442
+ CardComponent={MockCard}
443
+ itemsPerPage={2}
444
+ />
445
+ );
446
+
447
+ expect(container.firstChild).toBeInTheDocument();
448
+ const cards = screen.queryAllByTestId('mock-card');
449
+ expect(cards.length).toBe(0);
450
+ });
451
+ });
452
+
453
+ describe('Container Structure', () => {
454
+ it('renders main container', () => {
455
+ const items = [{ id: '1', data: undefined }];
456
+
457
+ render(
458
+ <TripCardsLayout
459
+ element={mockElement}
460
+ items={items}
461
+ CardComponent={MockCard}
462
+ itemsPerPage={2}
463
+ />
464
+ );
465
+
466
+ const mainContainer = screen.getByTestId('trip-cards-container');
467
+ expect(mainContainer).toBeInTheDocument();
468
+ });
469
+
470
+ it('renders title section', () => {
471
+ const items = [{ id: '1', data: undefined }];
472
+
473
+ render(
474
+ <TripCardsLayout
475
+ element={mockElement}
476
+ items={items}
477
+ CardComponent={MockCard}
478
+ itemsPerPage={2}
479
+ />
480
+ );
481
+
482
+ const titleSection = screen.getByTestId('title-section');
483
+ expect(titleSection).toBeInTheDocument();
484
+ });
485
+
486
+ it('renders title bar with content', () => {
487
+ const items = [{ id: '1', data: undefined }];
488
+
489
+ render(
490
+ <TripCardsLayout
491
+ element={mockElement}
492
+ items={items}
493
+ CardComponent={MockCard}
494
+ itemsPerPage={2}
495
+ />
496
+ );
497
+
498
+ const titleBar = screen.getByTestId('title-bar');
499
+ const titleContent = screen.getByTestId('title-content');
500
+
501
+ expect(titleBar).toBeInTheDocument();
502
+ expect(titleContent).toBeInTheDocument();
503
+ });
504
+ });
505
+
506
+ describe('ItemsPerPage', () => {
507
+ it('respects itemsPerPage prop', () => {
508
+ const items = Array.from({ length: 6 }, (_, i) => ({
509
+ id: `${i}`,
510
+ data: undefined
511
+ }));
512
+
513
+ render(
514
+ <TripCardsLayout
515
+ element={mockElement}
516
+ items={items}
517
+ CardComponent={MockCard}
518
+ itemsPerPage={3}
519
+ />
520
+ );
521
+
522
+ const cards = screen.getAllByTestId('mock-card');
523
+ expect(cards.length).toBe(6);
524
+ });
525
+
526
+ it('handles itemsPerPage of 1', () => {
527
+ const items = [
528
+ { id: '1', data: undefined },
529
+ { id: '2', data: undefined }
530
+ ];
531
+
532
+ render(
533
+ <TripCardsLayout
534
+ element={mockElement}
535
+ items={items}
536
+ CardComponent={MockCard}
537
+ itemsPerPage={1}
538
+ />
539
+ );
540
+
541
+ const cards = screen.getAllByTestId('mock-card');
542
+ expect(cards.length).toBe(2);
543
+ });
544
+ });
545
+
546
+ describe('Edge Cases', () => {
547
+ it('handles large number of items', () => {
548
+ const items = Array.from({ length: 50 }, (_, i) => ({
549
+ id: `${i}`,
550
+ data: undefined
551
+ }));
552
+
553
+ render(
554
+ <TripCardsLayout
555
+ element={mockElement}
556
+ items={items}
557
+ CardComponent={MockCard}
558
+ itemsPerPage={2}
559
+ />
560
+ );
561
+
562
+ const cards = screen.getAllByTestId('mock-card');
563
+ expect(cards.length).toBe(50);
564
+ });
565
+
566
+ it('handles empty title and description', () => {
567
+ const emptyElement = {
568
+ ...mockElement,
569
+ title: '',
570
+ description: ''
571
+ };
572
+
573
+ const items = [{ id: '1', data: undefined }];
574
+
575
+ const { container } = render(
576
+ <TripCardsLayout
577
+ element={emptyElement}
578
+ items={items}
579
+ CardComponent={MockCard}
580
+ itemsPerPage={2}
581
+ />
582
+ );
583
+
584
+ const title = container.querySelector('h2');
585
+ const description = container.querySelector('p');
586
+
587
+ expect(title).toBeInTheDocument();
588
+ expect(description).toBeInTheDocument();
589
+ if (title && description) {
590
+ expect(title.textContent).toBe('');
591
+ expect(description.textContent).toBe('');
592
+ }
593
+ });
594
+ });
595
+
596
+ describe('Tracking', () => {
597
+ it('calls tealiumTrackingHandler when title link is clicked', () => {
598
+ const items = [{ id: '1', data: undefined }];
599
+
600
+ render(
601
+ <TripCardsLayout
602
+ element={mockElement}
603
+ items={items}
604
+ CardComponent={MockCard}
605
+ itemsPerPage={2}
606
+ />
607
+ );
608
+
609
+ const titleLink = screen.getByTestId('trip-cards-title-link');
610
+ fireEvent.click(titleLink);
611
+
612
+ expect(tealiumTrackingHandler).toHaveBeenCalledWith(
613
+ 'trip cards component Test Cruises',
614
+ 'navigation',
615
+ 'click',
616
+ undefined,
617
+ undefined,
618
+ {
619
+ app_content_location: 'uk'
620
+ }
621
+ );
622
+ });
623
+
624
+ it('calls tealiumTrackingHandler when icon link is clicked', () => {
625
+ const items = [{ id: '1', data: undefined }];
626
+
627
+ render(
628
+ <TripCardsLayout
629
+ element={mockElement}
630
+ items={items}
631
+ CardComponent={MockCard}
632
+ itemsPerPage={2}
633
+ />
634
+ );
635
+
636
+ const iconLink = screen.getByTestId('title-link');
637
+ fireEvent.click(iconLink);
638
+
639
+ expect(tealiumTrackingHandler).toHaveBeenCalledWith(
640
+ 'trip cards component Test Cruises',
641
+ 'navigation',
642
+ 'click',
643
+ undefined,
644
+ undefined,
645
+ {
646
+ app_content_location: 'uk'
647
+ }
648
+ );
649
+ });
650
+
651
+ it('does not call tealiumTrackingHandler when title link is not clicked', () => {
652
+ const elementWithoutLink = {
653
+ ...mockElement,
654
+ titleurl: undefined
655
+ };
656
+
657
+ const items = [{ id: '1', data: undefined }];
658
+
659
+ render(
660
+ <TripCardsLayout
661
+ element={elementWithoutLink}
662
+ items={items}
663
+ CardComponent={MockCard}
664
+ itemsPerPage={2}
665
+ />
666
+ );
667
+
668
+ expect(tealiumTrackingHandler).not.toHaveBeenCalled();
669
+ });
670
+ });
671
+ });