@times-components/ts-components 1.146.2-be27d508c972211ad80599875cd69c63bf67d4b1.45 → 1.146.2-e5795a0ef59e2adb61ba52aeb7332fda4405cb7a.4

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 (156) hide show
  1. package/dist/components/opta/football/opta-match-stats/matchday-live/DesktopWidget.d.ts +10 -0
  2. package/dist/components/opta/football/opta-match-stats/matchday-live/DesktopWidget.js +69 -0
  3. package/dist/components/opta/football/opta-match-stats/matchday-live/MobileWidget.d.ts +12 -0
  4. package/dist/components/opta/football/opta-match-stats/matchday-live/MobileWidget.js +90 -0
  5. package/dist/components/opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.d.ts +12 -0
  6. package/dist/components/opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.js +10 -0
  7. package/dist/components/opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.stories.js +24 -0
  8. package/dist/components/opta/football/opta-match-stats/matchday-live/__tests__/MobileWidget.test.js +57 -0
  9. package/dist/components/{carousel-component/__tests__/DefaultPageDot.test.d.ts → opta/football/opta-match-stats/matchday-live/__tests__/OptaMatchStatsMatchdayLive.test.d.ts} +1 -0
  10. package/dist/components/opta/football/opta-match-stats/matchday-live/__tests__/OptaMatchStatsMatchdayLive.test.js +48 -0
  11. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/MatchdayLiveController.d.ts +1 -0
  12. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/MatchdayLiveController.js +19 -0
  13. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/NavigationWrapper.d.ts +12 -0
  14. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/NavigationWrapper.js +67 -0
  15. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/WidgetContainer.d.ts +6 -0
  16. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/WidgetContainer.js +736 -0
  17. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/__tests__/NavigationWrapper.test.js +33 -0
  18. package/dist/components/opta/football/opta-match-stats/matchday-live/styles/__tests__/WidgetContainer.test.js +36 -0
  19. package/dist/components/opta/football/opta-match-stats/shared/styles.js +8 -1
  20. package/dist/components/opta/football/opta-match-stats/summary/OptaMatchStatsSummary.js +2 -2
  21. package/dist/components/opta/football/opta-match-stats/summary/OptaMatchStatsSummary.stories.js +1 -1
  22. package/dist/components/opta/football/opta-match-stats/summary/WidgetContainer.js +19 -5
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +2 -2
  25. package/package.json +3 -3
  26. package/rnw.js +1 -1
  27. package/src/components/opta/football/opta-match-stats/commentary/__tests__/__snapshots__/OptaMatchStatsCommentary.test.tsx.snap +1 -1
  28. package/src/components/opta/football/opta-match-stats/matchday-live/DesktopWidget.tsx +108 -0
  29. package/src/components/opta/football/opta-match-stats/matchday-live/MobileWidget.tsx +158 -0
  30. package/src/components/opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.stories.tsx +38 -0
  31. package/src/components/opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.tsx +23 -0
  32. package/src/components/opta/football/opta-match-stats/matchday-live/__tests__/MobileWidget.test.tsx +69 -0
  33. package/src/components/opta/football/opta-match-stats/matchday-live/__tests__/OptaMatchStatsMatchdayLive.test.tsx +61 -0
  34. package/src/components/opta/football/opta-match-stats/matchday-live/__tests__/__snapshots__/OptaMatchStatsMatchdayLive.test.tsx.snap +61 -0
  35. package/src/components/opta/football/opta-match-stats/matchday-live/styles/MatchdayLiveController.tsx +19 -0
  36. package/src/components/opta/football/opta-match-stats/matchday-live/styles/NavigationWrapper.tsx +81 -0
  37. package/src/components/opta/football/opta-match-stats/matchday-live/styles/WidgetContainer.tsx +767 -0
  38. package/src/components/opta/football/opta-match-stats/matchday-live/styles/__tests__/NavigationWrapper.test.tsx +67 -0
  39. package/src/components/opta/football/opta-match-stats/matchday-live/styles/__tests__/WidgetContainer.test.tsx +64 -0
  40. package/src/components/opta/football/opta-match-stats/shared/styles.ts +8 -0
  41. package/src/components/opta/football/opta-match-stats/stats-graphs/__tests__/__snapshots__/OptaMatchStatsGraphs.test.tsx.snap +1 -1
  42. package/src/components/opta/football/opta-match-stats/summary/OptaMatchStatsSummary.stories.tsx +1 -1
  43. package/src/components/opta/football/opta-match-stats/summary/OptaMatchStatsSummary.tsx +1 -1
  44. package/src/components/opta/football/opta-match-stats/summary/WidgetContainer.tsx +18 -4
  45. package/src/components/opta/football/opta-match-stats/summary/__tests__/__snapshots__/OptaMatchStatsSummary.test.tsx.snap +1 -1
  46. package/src/index.ts +3 -2
  47. package/dist/components/carousel-component/CarouselComponent.stories.js +0 -146
  48. package/dist/components/carousel-component/CarouselItem.d.ts +0 -3
  49. package/dist/components/carousel-component/CarouselItem.js +0 -12
  50. package/dist/components/carousel-component/DefaultNavigationArrow.d.ts +0 -8
  51. package/dist/components/carousel-component/DefaultNavigationArrow.js +0 -6
  52. package/dist/components/carousel-component/DefaultPageDot.d.ts +0 -8
  53. package/dist/components/carousel-component/DefaultPageDot.js +0 -4
  54. package/dist/components/carousel-component/__tests__/CarouselComponent.test.js +0 -163
  55. package/dist/components/carousel-component/__tests__/CarouselItem.test.js +0 -80
  56. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.js +0 -62
  57. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.js +0 -68
  58. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.d.ts +0 -1
  59. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.js +0 -459
  60. package/dist/components/carousel-component/hooks/useCarousel.d.ts +0 -2
  61. package/dist/components/carousel-component/hooks/useCarousel.js +0 -167
  62. package/dist/components/carousel-component/index.d.ts +0 -4
  63. package/dist/components/carousel-component/index.js +0 -20
  64. package/dist/components/carousel-component/styles.d.ts +0 -28
  65. package/dist/components/carousel-component/styles.js +0 -172
  66. package/dist/components/carousel-component/types.d.ts +0 -53
  67. package/dist/components/carousel-component/types.js +0 -2
  68. package/dist/components/trip-cards/SkeletonCard.d.ts +0 -7
  69. package/dist/components/trip-cards/SkeletonCard.js +0 -22
  70. package/dist/components/trip-cards/TripCard.d.ts +0 -3
  71. package/dist/components/trip-cards/TripCard.js +0 -49
  72. package/dist/components/trip-cards/TripCards.stories.d.ts +0 -1
  73. package/dist/components/trip-cards/TripCards.stories.js +0 -159
  74. package/dist/components/trip-cards/TripCardsLayout.d.ts +0 -3
  75. package/dist/components/trip-cards/TripCardsLayout.js +0 -56
  76. package/dist/components/trip-cards/__tests__/SkeletonCard.test.d.ts +0 -1
  77. package/dist/components/trip-cards/__tests__/SkeletonCard.test.js +0 -139
  78. package/dist/components/trip-cards/__tests__/TripCard.test.d.ts +0 -1
  79. package/dist/components/trip-cards/__tests__/TripCard.test.js +0 -95
  80. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.d.ts +0 -1
  81. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.js +0 -314
  82. package/dist/components/trip-cards/__tests__/assets.test.d.ts +0 -1
  83. package/dist/components/trip-cards/__tests__/assets.test.js +0 -165
  84. package/dist/components/trip-cards/__tests__/helpers.test.d.ts +0 -1
  85. package/dist/components/trip-cards/__tests__/helpers.test.js +0 -220
  86. package/dist/components/trip-cards/__tests__/index.test.d.ts +0 -1
  87. package/dist/components/trip-cards/__tests__/index.test.js +0 -478
  88. package/dist/components/trip-cards/__tests__/mockData.test.d.ts +0 -1
  89. package/dist/components/trip-cards/__tests__/mockData.test.js +0 -57
  90. package/dist/components/trip-cards/__tests__/skeletonStyles.test.d.ts +0 -1
  91. package/dist/components/trip-cards/__tests__/skeletonStyles.test.js +0 -194
  92. package/dist/components/trip-cards/assets/BoatIcon.d.ts +0 -1
  93. package/dist/components/trip-cards/assets/BoatIcon.js +0 -4
  94. package/dist/components/trip-cards/assets/CalendarIcon.d.ts +0 -1
  95. package/dist/components/trip-cards/assets/CalendarIcon.js +0 -4
  96. package/dist/components/trip-cards/assets/ChevronRightIcon.d.ts +0 -1
  97. package/dist/components/trip-cards/assets/ChevronRightIcon.js +0 -4
  98. package/dist/components/trip-cards/assets/LocationIcon.d.ts +0 -1
  99. package/dist/components/trip-cards/assets/LocationIcon.js +0 -4
  100. package/dist/components/trip-cards/assets/MoonIcon.d.ts +0 -1
  101. package/dist/components/trip-cards/assets/MoonIcon.js +0 -4
  102. package/dist/components/trip-cards/assets/index.d.ts +0 -6
  103. package/dist/components/trip-cards/assets/index.js +0 -7
  104. package/dist/components/trip-cards/helpers.d.ts +0 -11
  105. package/dist/components/trip-cards/helpers.js +0 -138
  106. package/dist/components/trip-cards/index.d.ts +0 -4
  107. package/dist/components/trip-cards/index.js +0 -68
  108. package/dist/components/trip-cards/mockData.d.ts +0 -3
  109. package/dist/components/trip-cards/mockData.js +0 -317
  110. package/dist/components/trip-cards/skeletonStyles.d.ts +0 -9
  111. package/dist/components/trip-cards/skeletonStyles.js +0 -37
  112. package/dist/components/trip-cards/styles.d.ts +0 -43
  113. package/dist/components/trip-cards/styles.js +0 -404
  114. package/dist/components/trip-cards/types.d.ts +0 -119
  115. package/dist/components/trip-cards/types.js +0 -2
  116. package/src/components/carousel-component/CarouselComponent.stories.tsx +0 -220
  117. package/src/components/carousel-component/CarouselItem.tsx +0 -26
  118. package/src/components/carousel-component/DefaultNavigationArrow.tsx +0 -37
  119. package/src/components/carousel-component/DefaultPageDot.tsx +0 -20
  120. package/src/components/carousel-component/__tests__/CarouselComponent.test.tsx +0 -259
  121. package/src/components/carousel-component/__tests__/CarouselItem.test.tsx +0 -140
  122. package/src/components/carousel-component/__tests__/DefaultNavigationArrow.test.tsx +0 -153
  123. package/src/components/carousel-component/__tests__/DefaultPageDot.test.tsx +0 -105
  124. package/src/components/carousel-component/hooks/__tests__/useCarousel.test.ts +0 -625
  125. package/src/components/carousel-component/hooks/useCarousel.ts +0 -229
  126. package/src/components/carousel-component/index.tsx +0 -92
  127. package/src/components/carousel-component/styles.ts +0 -188
  128. package/src/components/carousel-component/types.ts +0 -62
  129. package/src/components/trip-cards/SkeletonCard.tsx +0 -64
  130. package/src/components/trip-cards/TripCard.tsx +0 -140
  131. package/src/components/trip-cards/TripCards.stories.tsx +0 -224
  132. package/src/components/trip-cards/TripCardsLayout.tsx +0 -145
  133. package/src/components/trip-cards/__tests__/SkeletonCard.test.tsx +0 -169
  134. package/src/components/trip-cards/__tests__/TripCard.test.tsx +0 -120
  135. package/src/components/trip-cards/__tests__/TripCardsLayout.test.tsx +0 -583
  136. package/src/components/trip-cards/__tests__/assets.test.tsx +0 -206
  137. package/src/components/trip-cards/__tests__/helpers.test.ts +0 -272
  138. package/src/components/trip-cards/__tests__/index.test.tsx +0 -550
  139. package/src/components/trip-cards/__tests__/mockData.test.ts +0 -67
  140. package/src/components/trip-cards/__tests__/skeletonStyles.test.tsx +0 -256
  141. package/src/components/trip-cards/assets/BoatIcon.tsx +0 -17
  142. package/src/components/trip-cards/assets/CalendarIcon.tsx +0 -17
  143. package/src/components/trip-cards/assets/ChevronRightIcon.tsx +0 -20
  144. package/src/components/trip-cards/assets/LocationIcon.tsx +0 -17
  145. package/src/components/trip-cards/assets/MoonIcon.tsx +0 -17
  146. package/src/components/trip-cards/assets/index.ts +0 -7
  147. package/src/components/trip-cards/helpers.ts +0 -176
  148. package/src/components/trip-cards/index.tsx +0 -119
  149. package/src/components/trip-cards/mockData.ts +0 -345
  150. package/src/components/trip-cards/skeletonStyles.ts +0 -46
  151. package/src/components/trip-cards/styles.ts +0 -450
  152. package/src/components/trip-cards/types.ts +0 -128
  153. /package/dist/components/{carousel-component/CarouselComponent.stories.d.ts → opta/football/opta-match-stats/matchday-live/OptaMatchStatsMatchdayLive.stories.d.ts} +0 -0
  154. /package/dist/components/{carousel-component/__tests__/CarouselComponent.test.d.ts → opta/football/opta-match-stats/matchday-live/__tests__/MobileWidget.test.d.ts} +0 -0
  155. /package/dist/components/{carousel-component/__tests__/CarouselItem.test.d.ts → opta/football/opta-match-stats/matchday-live/styles/__tests__/NavigationWrapper.test.d.ts} +0 -0
  156. /package/dist/components/{carousel-component/__tests__/DefaultNavigationArrow.test.d.ts → opta/football/opta-match-stats/matchday-live/styles/__tests__/WidgetContainer.test.d.ts} +0 -0
@@ -1,550 +0,0 @@
1
- import React from 'react';
2
- import { render, screen, waitFor } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import { TripCards } from '../index';
5
- import { TripCardsElement } from '../types';
6
- import * as mockDataModule from '../mockData';
7
-
8
- global.fetch = jest.fn();
9
-
10
- // Mock ResizeObserver
11
- global.ResizeObserver = class ResizeObserver {
12
- public observe(): void {
13
- // Mock implementation
14
- }
15
- public unobserve(): void {
16
- // Mock implementation
17
- }
18
- public disconnect(): void {
19
- // Mock implementation
20
- }
21
- };
22
-
23
- describe('TripCards', () => {
24
- const mockCards = [
25
- {
26
- cruise_id: '1',
27
- image: 'image1.jpg',
28
- headline: 'Mock Cruise 1',
29
- date: 'Jan 2024',
30
- duration: '7 nights',
31
- route: 'Route 1',
32
- ship: 'Ship 1',
33
- price: '£1000',
34
- original_price: undefined,
35
- logo: 'logo1.png',
36
- logo_url: 'https://example.com',
37
- cta_url: 'link1',
38
- cta_text: 'View'
39
- },
40
- {
41
- cruise_id: '2',
42
- image: 'image2.jpg',
43
- headline: 'Mock Cruise 2',
44
- date: 'Feb 2024',
45
- duration: '14 nights',
46
- route: 'Route 2',
47
- ship: 'Ship 2',
48
- price: '£2000',
49
- original_price: undefined,
50
- logo: 'logo2.png',
51
- logo_url: 'https://example.com',
52
- cta_url: 'link2',
53
- cta_text: 'View'
54
- },
55
- {
56
- cruise_id: '3',
57
- image: 'image3.jpg',
58
- headline: 'Mock Cruise 3',
59
- date: 'Mar 2024',
60
- duration: '10 nights',
61
- route: 'Route 3',
62
- ship: 'Ship 3',
63
- price: '£1500',
64
- original_price: undefined,
65
- logo: 'logo3.png',
66
- logo_url: 'https://example.com',
67
- cta_url: 'link3',
68
- cta_text: 'View'
69
- }
70
- ];
71
-
72
- const mockElement: TripCardsElement = {
73
- title: 'Test Cruises',
74
- description: 'Test Description',
75
- tripcards: btoa(JSON.stringify([1, 2, 3])),
76
- titleurl: 'https://example.com'
77
- };
78
-
79
- beforeEach(() => {
80
- jest.clearAllMocks();
81
-
82
- // Mock matchMedia for each test
83
- Object.defineProperty(window, 'matchMedia', {
84
- writable: true,
85
- configurable: true,
86
- value: jest.fn().mockImplementation(query => ({
87
- matches: false,
88
- media: query,
89
- onchange: null,
90
- addListener: jest.fn(),
91
- removeListener: jest.fn(),
92
- addEventListener: jest.fn(),
93
- removeEventListener: jest.fn(),
94
- dispatchEvent: jest.fn()
95
- }))
96
- });
97
-
98
- jest
99
- .spyOn(mockDataModule, 'getMockTripCards')
100
- .mockImplementation((count?: number) => {
101
- return count ? mockCards.slice(0, count) : mockCards;
102
- });
103
- Object.defineProperty(window, 'innerWidth', {
104
- writable: true,
105
- configurable: true,
106
- value: 1024
107
- });
108
- });
109
-
110
- describe('Mock Data Mode', () => {
111
- it('renders cards when useMockData is true', async () => {
112
- render(<TripCards element={mockElement} useMockData={true} />);
113
-
114
- await waitFor(() => {
115
- expect(screen.getByText('Mock Cruise 1')).toBeInTheDocument();
116
- expect(screen.getByText('Mock Cruise 2')).toBeInTheDocument();
117
- });
118
- });
119
-
120
- it('renders title and description', async () => {
121
- render(<TripCards element={mockElement} useMockData={true} />);
122
-
123
- await waitFor(() => {
124
- expect(screen.getByText('Test Cruises')).toBeInTheDocument();
125
- expect(screen.getByText('Test Description')).toBeInTheDocument();
126
- });
127
- });
128
-
129
- it('respects the number of IDs', async () => {
130
- render(<TripCards element={mockElement} useMockData={true} />);
131
-
132
- await waitFor(() => {
133
- expect(mockDataModule.getMockTripCards).toHaveBeenCalledWith(3);
134
- });
135
- });
136
- });
137
-
138
- describe('Error Handling', () => {
139
- it('returns null when no IDs are provided', async () => {
140
- const emptyElement: TripCardsElement = {
141
- title: 'Test',
142
- description: 'Test',
143
- tripcards: '',
144
- titleurl: undefined
145
- };
146
-
147
- const { container } = render(<TripCards element={emptyElement} />);
148
-
149
- await waitFor(() => {
150
- expect(container.firstChild).toBeNull();
151
- });
152
- });
153
-
154
- it('returns null when fetch fails', async () => {
155
- (global.fetch as jest.Mock).mockRejectedValue(new Error('Network error'));
156
-
157
- const { container } = render(<TripCards element={mockElement} />);
158
-
159
- await waitFor(() => {
160
- expect(container.firstChild).toBeNull();
161
- });
162
- });
163
-
164
- it('returns null when response is not ok', async () => {
165
- (global.fetch as jest.Mock).mockResolvedValue({
166
- ok: false,
167
- status: 404
168
- });
169
-
170
- const { container } = render(<TripCards element={mockElement} />);
171
-
172
- await waitFor(() => {
173
- expect(container.firstChild).toBeNull();
174
- });
175
- });
176
-
177
- it('returns null when API response format is invalid', async () => {
178
- (global.fetch as jest.Mock).mockResolvedValue({
179
- ok: true,
180
- json: async () => ({ invalid: 'data' })
181
- });
182
-
183
- const { container } = render(<TripCards element={mockElement} />);
184
-
185
- await waitFor(() => {
186
- expect(container.firstChild).toBeNull();
187
- });
188
- });
189
- });
190
-
191
- describe('API Data Fetching', () => {
192
- it('fetches and displays cruise data from API', async () => {
193
- const mockApiResponse = {
194
- results: [
195
- {
196
- post_id: 1,
197
- cruise_id: 1,
198
- cruise_title: 'API Cruise 1',
199
- cruise_line: {
200
- name: 'API Line',
201
- link: 'http://line.com',
202
- logo: 'logo.png'
203
- },
204
- ship: {
205
- name: 'API Ship',
206
- link: 'http://ship.com',
207
- image: 'api-image1.jpg'
208
- },
209
- departs: '2026-03-01',
210
- ends: '2026-03-11',
211
- date_label: 'March 2024',
212
- destination: ['Port 1', 'Port 3'],
213
- duration: 10,
214
- itinerary: ['Port 1', 'Port 2', 'Port 3'],
215
- prices: {
216
- cheapest_price: 1500,
217
- inside: 1500,
218
- outside: 1800,
219
- balcony: 2000,
220
- suite: 2500
221
- },
222
- was_prices: {
223
- inside: 2000,
224
- outside: 2200,
225
- balcony: 2500,
226
- suite: 3000
227
- },
228
- link: 'api-link',
229
- campaigns: ['Special'],
230
- extras: {
231
- date: 'March 2024',
232
- duration: '10 nights',
233
- destination: 'Mediterranean',
234
- info: 'Additional info'
235
- }
236
- },
237
- {
238
- post_id: 2,
239
- cruise_id: 2,
240
- cruise_title: 'API Cruise 2',
241
- cruise_line: {
242
- name: 'API Line',
243
- link: 'http://line.com',
244
- logo: 'logo.png'
245
- },
246
- ship: {
247
- name: 'API Ship 2',
248
- link: 'http://ship.com',
249
- image: 'api-image2.jpg'
250
- },
251
- departs: '2026-04-01',
252
- ends: '2026-04-11',
253
- date_label: 'April 2024',
254
- destination: ['Port 2', 'Port 4'],
255
- duration: 10,
256
- itinerary: ['Port 2', 'Port 3', 'Port 4'],
257
- prices: {
258
- cheapest_price: 1600,
259
- inside: 1600,
260
- outside: 1900,
261
- balcony: 2100,
262
- suite: 2600
263
- },
264
- was_prices: {
265
- inside: 0,
266
- outside: 0,
267
- balcony: 0,
268
- suite: 0
269
- },
270
- link: 'api-link2',
271
- campaigns: [],
272
- extras: {
273
- date: 'April 2024',
274
- duration: '10 nights',
275
- destination: 'Caribbean',
276
- info: 'Additional info'
277
- }
278
- },
279
- {
280
- post_id: 3,
281
- cruise_id: 3,
282
- cruise_title: 'API Cruise 3',
283
- cruise_line: {
284
- name: 'API Line',
285
- link: 'http://line.com',
286
- logo: 'logo.png'
287
- },
288
- ship: {
289
- name: 'API Ship 3',
290
- link: 'http://ship.com',
291
- image: 'api-image3.jpg'
292
- },
293
- departs: '2026-05-01',
294
- ends: '2026-05-11',
295
- date_label: 'May 2024',
296
- destination: ['Port 3', 'Port 5'],
297
- duration: 10,
298
- itinerary: ['Port 3', 'Port 4', 'Port 5'],
299
- prices: {
300
- cheapest_price: 1700,
301
- inside: 1700,
302
- outside: 2000,
303
- balcony: 2200,
304
- suite: 2700
305
- },
306
- was_prices: {
307
- inside: 2100,
308
- outside: 2400,
309
- balcony: 2600,
310
- suite: 3100
311
- },
312
- link: 'api-link3',
313
- campaigns: [],
314
- extras: {
315
- date: 'May 2024',
316
- duration: '10 nights',
317
- destination: 'Alaska',
318
- info: 'Additional info'
319
- }
320
- }
321
- ]
322
- };
323
-
324
- (global.fetch as jest.Mock).mockResolvedValue({
325
- ok: true,
326
- json: async () => mockApiResponse
327
- });
328
-
329
- render(<TripCards element={mockElement} />);
330
-
331
- await waitFor(() => {
332
- expect(screen.getByText('API Cruise 1')).toBeInTheDocument();
333
- });
334
- });
335
-
336
- it('sends correct request to API', async () => {
337
- const mockApiResponse = {
338
- results: mockCards.map((card, index) => ({
339
- post_id: index + 1,
340
- cruise_id: parseInt(card.cruise_id, 10),
341
- cruise_title: card.headline,
342
- cruise_line: {
343
- name: 'Test Line',
344
- link: card.logo_url,
345
- logo: card.logo
346
- },
347
- ship: {
348
- name: card.ship,
349
- link: 'http://ship.com',
350
- image: card.image
351
- },
352
- departs: '2026-01-01',
353
- ends: '2026-01-11',
354
- date_label: card.date,
355
- destination: ['Test Port'],
356
- duration: 10,
357
- itinerary: ['Port 1', 'Port 2', 'Port 3'],
358
- prices: {
359
- cheapest_price: 1500,
360
- inside: 1500,
361
- outside: 1800,
362
- balcony: 2000,
363
- suite: 2500
364
- },
365
- was_prices: {
366
- inside: 0,
367
- outside: 0,
368
- balcony: 0,
369
- suite: 0
370
- },
371
- link: card.cta_url,
372
- campaigns: [],
373
- extras: {
374
- date: card.date,
375
- duration: card.duration,
376
- destination: 'Test',
377
- info: 'Info'
378
- }
379
- }))
380
- };
381
-
382
- (global.fetch as jest.Mock).mockResolvedValue({
383
- ok: true,
384
- json: async () => mockApiResponse
385
- });
386
-
387
- render(<TripCards element={mockElement} />);
388
-
389
- await waitFor(() => {
390
- expect(global.fetch).toHaveBeenCalledWith(
391
- 'https://www.staging-thetimes.com/holidays/wp-admin/admin-ajax.php',
392
- expect.objectContaining({
393
- method: 'POST',
394
- body: expect.any(FormData)
395
- })
396
- );
397
- });
398
- });
399
- });
400
-
401
- describe('Layout', () => {
402
- it('uses static grid for exactly 2 cards', async () => {
403
- const twoCardElement: TripCardsElement = {
404
- ...mockElement,
405
- tripcards: btoa(JSON.stringify([1, 2]))
406
- };
407
-
408
- render(<TripCards element={twoCardElement} useMockData={true} />);
409
-
410
- await waitFor(() => {
411
- expect(screen.getByText('Mock Cruise 1')).toBeInTheDocument();
412
- });
413
-
414
- expect(screen.queryByLabelText('Previous items')).not.toBeInTheDocument();
415
- });
416
-
417
- it('uses carousel for more than 2 cards', async () => {
418
- const threeCards = [
419
- ...mockCards,
420
- {
421
- cruise_id: '3',
422
- image: 'image3.jpg',
423
- headline: 'Mock Cruise 3',
424
- date: 'Mar 2024',
425
- duration: '21 nights',
426
- route: 'Route 3',
427
- ship: 'Ship 3',
428
- price: '£3000',
429
- original_price: undefined,
430
- logo: 'logo3.png',
431
- logo_url: 'https://example.com',
432
- cta_url: 'link3',
433
- cta_text: 'View'
434
- }
435
- ];
436
-
437
- jest
438
- .spyOn(mockDataModule, 'getMockTripCards')
439
- .mockReturnValue(threeCards);
440
-
441
- render(<TripCards element={mockElement} useMockData={true} />);
442
-
443
- await waitFor(() => {
444
- expect(screen.getByText('Mock Cruise 1')).toBeInTheDocument();
445
- expect(screen.getByLabelText('Previous items')).toBeInTheDocument();
446
- expect(screen.getByLabelText('Next items')).toBeInTheDocument();
447
- });
448
- });
449
- });
450
-
451
- describe('Responsive Behavior', () => {
452
- it('uses matchMedia for responsive breakpoint detection', () => {
453
- const mockMediaQuery = {
454
- matches: false,
455
- media: '(max-width: 767px)',
456
- onchange: null,
457
- addListener: jest.fn(),
458
- removeListener: jest.fn(),
459
- addEventListener: jest.fn(),
460
- removeEventListener: jest.fn(),
461
- dispatchEvent: jest.fn()
462
- };
463
-
464
- const matchMediaSpy = jest
465
- .spyOn(window, 'matchMedia')
466
- .mockReturnValue(mockMediaQuery as any);
467
-
468
- const { unmount } = render(
469
- <TripCards element={mockElement} useMockData={true} />
470
- );
471
-
472
- // Verify matchMedia was called with the correct query
473
- expect(matchMediaSpy).toHaveBeenCalledWith('(max-width: 767px)');
474
-
475
- // Verify addEventListener was called on the media query
476
- expect(mockMediaQuery.addEventListener).toHaveBeenCalledWith(
477
- 'change',
478
- expect.any(Function)
479
- );
480
-
481
- unmount();
482
-
483
- // Verify removeEventListener was called on cleanup
484
- expect(mockMediaQuery.removeEventListener).toHaveBeenCalledWith(
485
- 'change',
486
- expect.any(Function)
487
- );
488
-
489
- matchMediaSpy.mockRestore();
490
- });
491
- });
492
-
493
- describe('Props', () => {
494
- it('renders empty title when not provided', async () => {
495
- const elementWithoutTitle: TripCardsElement = {
496
- ...mockElement,
497
- title: undefined
498
- };
499
-
500
- render(<TripCards element={elementWithoutTitle} useMockData={true} />);
501
-
502
- await waitFor(() => {
503
- const titleElement = screen.getByTestId('trip-cards-title');
504
- expect(titleElement).toBeInTheDocument();
505
- expect(titleElement).toBeEmptyDOMElement();
506
- });
507
- });
508
-
509
- it('renders empty description when not provided', async () => {
510
- const elementWithoutDesc: TripCardsElement = {
511
- ...mockElement,
512
- description: undefined
513
- };
514
-
515
- render(<TripCards element={elementWithoutDesc} useMockData={true} />);
516
-
517
- await waitFor(() => {
518
- const descElement = screen.getByTestId('trip-cards-subtitle');
519
- expect(descElement).toBeInTheDocument();
520
- expect(descElement).toBeEmptyDOMElement();
521
- });
522
- });
523
-
524
- it('renders title link when provided', async () => {
525
- render(<TripCards element={mockElement} useMockData={true} />);
526
-
527
- await waitFor(() => {
528
- const link = screen.getByTestId('title-link');
529
- expect(link).toHaveAttribute('href', 'https://example.com');
530
- expect(link).toHaveAttribute('target', '_blank');
531
- });
532
- });
533
-
534
- it('does not render title link when not provided', async () => {
535
- const elementWithoutLink: TripCardsElement = {
536
- ...mockElement,
537
- titleurl: undefined
538
- };
539
-
540
- render(<TripCards element={elementWithoutLink} useMockData={true} />);
541
-
542
- await waitFor(() => {
543
- expect(screen.getByText('Mock Cruise 1')).toBeInTheDocument();
544
- });
545
-
546
- const links = screen.getAllByRole('link');
547
- expect(links.length).toBeGreaterThan(0);
548
- });
549
- });
550
- });
@@ -1,67 +0,0 @@
1
- import { getMockTripCards, mockApiResults } from '../mockData';
2
-
3
- describe('mockData', () => {
4
- describe('mockApiResults', () => {
5
- it('contains 6 cruise results', () => {
6
- expect(mockApiResults).toHaveLength(6);
7
- });
8
-
9
- it('each result has required fields', () => {
10
- mockApiResults.forEach(result => {
11
- expect(result).toHaveProperty('cruise_id');
12
- expect(result).toHaveProperty('cruise_title');
13
- expect(result).toHaveProperty('cruise_line');
14
- expect(result).toHaveProperty('ship');
15
- expect(result).toHaveProperty('prices');
16
- expect(result).toHaveProperty('was_prices');
17
- expect(result).toHaveProperty('extras');
18
- });
19
- });
20
-
21
- it('extras object contains required fields', () => {
22
- mockApiResults.forEach(result => {
23
- expect(result.extras).toHaveProperty('date');
24
- expect(result.extras).toHaveProperty('duration');
25
- expect(result.extras).toHaveProperty('destination');
26
- expect(result.extras).toHaveProperty('info');
27
- });
28
- });
29
- });
30
-
31
- describe('getMockTripCards', () => {
32
- it('returns all transformed cards when no count specified', () => {
33
- const cards = getMockTripCards();
34
-
35
- expect(cards).toHaveLength(6);
36
- });
37
-
38
- it('returns specified number of cards', () => {
39
- const cards = getMockTripCards(3);
40
-
41
- expect(cards).toHaveLength(3);
42
- });
43
-
44
- it('returns transformed TripCardApiData objects', () => {
45
- const cards = getMockTripCards(1);
46
-
47
- expect(cards[0]).toHaveProperty('cruise_id');
48
- expect(cards[0]).toHaveProperty('image');
49
- expect(cards[0]).toHaveProperty('headline');
50
- expect(cards[0]).toHaveProperty('date');
51
- expect(cards[0]).toHaveProperty('duration');
52
- expect(cards[0]).toHaveProperty('route');
53
- expect(cards[0]).toHaveProperty('ship');
54
- expect(cards[0]).toHaveProperty('price');
55
- expect(cards[0]).toHaveProperty('logo');
56
- expect(cards[0]).toHaveProperty('logo_url');
57
- expect(cards[0]).toHaveProperty('cta_url');
58
- expect(cards[0]).toHaveProperty('cta_text');
59
- });
60
-
61
- it('cruise_id is converted to string', () => {
62
- const cards = getMockTripCards(1);
63
-
64
- expect(typeof cards[0].cruise_id).toBe('string');
65
- });
66
- });
67
- });