@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,206 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import {
5
- BoatIcon,
6
- CalendarIcon,
7
- ChevronRightIcon,
8
- LocationIcon,
9
- MoonIcon
10
- } from '../assets';
11
-
12
- describe('Trip Cards Assets', () => {
13
- describe('BoatIcon', () => {
14
- it('renders correctly', () => {
15
- const { container } = render(<BoatIcon />);
16
- const svg = container.querySelector('svg');
17
- expect(svg).toBeInTheDocument();
18
- });
19
-
20
- it('has correct viewBox', () => {
21
- const { container } = render(<BoatIcon />);
22
- const svg = container.querySelector('svg');
23
- expect(svg).toHaveAttribute('viewBox');
24
- });
25
-
26
- it('accepts custom props', () => {
27
- const { container } = render(<BoatIcon className="custom-class" />);
28
- const svg = container.querySelector('svg');
29
- expect(svg).toHaveClass('custom-class');
30
- });
31
-
32
- it('has fill attribute', () => {
33
- const { container } = render(<BoatIcon />);
34
- const svg = container.querySelector('svg');
35
- expect(svg).toHaveAttribute('fill');
36
- });
37
- });
38
-
39
- describe('CalendarIcon', () => {
40
- it('renders correctly', () => {
41
- const { container } = render(<CalendarIcon />);
42
- const svg = container.querySelector('svg');
43
- expect(svg).toBeInTheDocument();
44
- });
45
-
46
- it('has correct viewBox', () => {
47
- const { container } = render(<CalendarIcon />);
48
- const svg = container.querySelector('svg');
49
- expect(svg).toHaveAttribute('viewBox');
50
- });
51
-
52
- it('accepts custom props', () => {
53
- const { container } = render(<CalendarIcon data-testid="calendar" />);
54
- const svg = container.querySelector('svg');
55
- expect(svg).toHaveAttribute('data-testid', 'calendar');
56
- });
57
-
58
- it('renders path elements', () => {
59
- const { container } = render(<CalendarIcon />);
60
- const paths = container.querySelectorAll('path');
61
- expect(paths.length).toBeGreaterThan(0);
62
- });
63
- });
64
-
65
- describe('ChevronRightIcon', () => {
66
- it('renders correctly', () => {
67
- const { container } = render(<ChevronRightIcon />);
68
- const svg = container.querySelector('svg');
69
- expect(svg).toBeInTheDocument();
70
- });
71
-
72
- it('has correct dimensions', () => {
73
- const { container } = render(<ChevronRightIcon />);
74
- const svg = container.querySelector('svg');
75
- expect(svg).toHaveAttribute('width', '16');
76
- expect(svg).toHaveAttribute('height', '16');
77
- });
78
-
79
- it('has correct viewBox', () => {
80
- const { container } = render(<ChevronRightIcon />);
81
- const svg = container.querySelector('svg');
82
- expect(svg).toHaveAttribute('viewBox', '0 0 16 16');
83
- });
84
-
85
- it('renders with currentColor stroke', () => {
86
- const { container } = render(<ChevronRightIcon />);
87
- const path = container.querySelector('path');
88
- expect(path).toHaveAttribute('stroke', 'currentColor');
89
- });
90
-
91
- it('accepts custom props', () => {
92
- const { container } = render(
93
- <ChevronRightIcon style={{ color: 'red' }} />
94
- );
95
- const svg = container.querySelector('svg');
96
- expect(svg).toHaveStyle({ color: 'red' });
97
- });
98
- });
99
-
100
- describe('LocationIcon', () => {
101
- it('renders correctly', () => {
102
- const { container } = render(<LocationIcon />);
103
- const svg = container.querySelector('svg');
104
- expect(svg).toBeInTheDocument();
105
- });
106
-
107
- it('has correct viewBox', () => {
108
- const { container } = render(<LocationIcon />);
109
- const svg = container.querySelector('svg');
110
- expect(svg).toHaveAttribute('viewBox');
111
- });
112
-
113
- it('accepts custom props', () => {
114
- const { container } = render(<LocationIcon aria-label="location" />);
115
- const svg = container.querySelector('svg');
116
- expect(svg).toHaveAttribute('aria-label', 'location');
117
- });
118
-
119
- it('renders path elements', () => {
120
- const { container } = render(<LocationIcon />);
121
- const path = container.querySelector('path');
122
- expect(path).toBeInTheDocument();
123
- });
124
- });
125
-
126
- describe('MoonIcon', () => {
127
- it('renders correctly', () => {
128
- const { container } = render(<MoonIcon />);
129
- const svg = container.querySelector('svg');
130
- expect(svg).toBeInTheDocument();
131
- });
132
-
133
- it('has correct viewBox', () => {
134
- const { container } = render(<MoonIcon />);
135
- const svg = container.querySelector('svg');
136
- expect(svg).toHaveAttribute('viewBox');
137
- });
138
-
139
- it('has correct dimensions', () => {
140
- const { container } = render(<MoonIcon />);
141
- const svg = container.querySelector('svg');
142
- expect(svg).toHaveAttribute('width');
143
- expect(svg).toHaveAttribute('height');
144
- });
145
-
146
- it('accepts custom props', () => {
147
- const { container } = render(<MoonIcon id="moon-icon" />);
148
- const svg = container.querySelector('svg');
149
- expect(svg).toHaveAttribute('id', 'moon-icon');
150
- });
151
-
152
- it('renders path with fill color', () => {
153
- const { container } = render(<MoonIcon />);
154
- const path = container.querySelector('path');
155
- expect(path).toHaveAttribute('fill');
156
- });
157
- });
158
-
159
- describe('Icons Integration', () => {
160
- it('all icons render without errors', () => {
161
- const { container } = render(
162
- <div>
163
- <BoatIcon />
164
- <CalendarIcon />
165
- <ChevronRightIcon />
166
- <LocationIcon />
167
- <MoonIcon />
168
- </div>
169
- );
170
-
171
- const svgs = container.querySelectorAll('svg');
172
- expect(svgs.length).toBe(5);
173
- });
174
-
175
- it('icons can be styled with className', () => {
176
- const { container } = render(
177
- <div>
178
- <BoatIcon className="icon-style" />
179
- <CalendarIcon className="icon-style" />
180
- <LocationIcon className="icon-style" />
181
- </div>
182
- );
183
-
184
- const svgs = container.querySelectorAll('.icon-style');
185
- expect(svgs.length).toBe(3);
186
- });
187
-
188
- it('icons maintain SVG structure', () => {
189
- const icons = [
190
- <BoatIcon key="boat" />,
191
- <CalendarIcon key="calendar" />,
192
- <ChevronRightIcon key="chevron" />,
193
- <LocationIcon key="location" />,
194
- <MoonIcon key="moon" />
195
- ];
196
-
197
- icons.forEach(icon => {
198
- const { container } = render(icon);
199
- const svg = container.querySelector('svg');
200
- if (svg) {
201
- expect(svg.tagName).toBe('svg');
202
- }
203
- });
204
- });
205
- });
206
- });
@@ -1,272 +0,0 @@
1
- import { transformApiResult, fetchCruiseCards } from '../helpers';
2
- import { ApiCruiseResult } from '../types';
3
-
4
- const mockApiResult: ApiCruiseResult = {
5
- post_id: 34246,
6
- cruise_id: 2074350,
7
- cruise_title: 'Mediterranean from Barcelona',
8
- cruise_line: {
9
- name: 'MSC Cruises',
10
- link: 'https://example.com/cruise-lines/msc-cruises/',
11
- logo: 'https://example.com/msc-logo.png'
12
- },
13
- ship: {
14
- name: 'MSC Seaside',
15
- link: 'https://example.com/ships/msc-seaside/',
16
- image: 'https://example.com/ship-image.jpg'
17
- },
18
- departs: '2025-10-21',
19
- ends: '2025-10-28',
20
- date_label: 'Oct 21 - Oct 28, 2025',
21
- destination: ['Mediterranean'],
22
- duration: 7,
23
- itinerary: ['Barcelona', 'Naples', 'Rome', 'Marseille'],
24
- prices: {
25
- cheapest_price: 2000,
26
- inside: 'Enquire now',
27
- outside: 'Enquire now',
28
- balcony: '2000',
29
- suite: 'Enquire now'
30
- },
31
- was_prices: {
32
- inside: 0,
33
- outside: 0,
34
- balcony: 2500,
35
- suite: 0
36
- },
37
- link: 'https://example.com/cruises/mediterranean-from-barcelona',
38
- campaigns: ['Special Offer'],
39
- extras: {
40
- date: 'Oct 2025 - Oct 2025',
41
- duration: 'Seven Days',
42
- destination: 'Mediterranean',
43
- info: 'Seven nights onboard a four-star ship'
44
- }
45
- };
46
-
47
- describe('transformApiResult', () => {
48
- it('transforms API result to TripCardApiData format', () => {
49
- const result = transformApiResult(mockApiResult);
50
-
51
- expect(result).toEqual({
52
- cruise_id: '2074350',
53
- image: 'https://example.com/ship-image.jpg',
54
- offer_label: 'Special Offer',
55
- headline: 'Mediterranean from Barcelona',
56
- date: 'Oct 2025 - Oct 2025',
57
- duration: 'Seven Days',
58
- route: 'Barcelona → Marseille',
59
- ship: 'MSC Seaside',
60
- original_price: '£2500',
61
- price: '£2000',
62
- logo: 'https://example.com/msc-logo.png',
63
- logo_url: 'https://example.com/cruise-lines/msc-cruises/',
64
- cta_url: 'https://example.com/cruises/mediterranean-from-barcelona',
65
- cta_text: 'View Itinerary'
66
- });
67
- });
68
-
69
- it('formats price as "Enquire now" when price is 0', () => {
70
- const resultWithZeroPrice = {
71
- ...mockApiResult,
72
- prices: { ...mockApiResult.prices, cheapest_price: 0 }
73
- };
74
-
75
- const result = transformApiResult(resultWithZeroPrice);
76
-
77
- expect(result.price).toBe('Enquire now');
78
- });
79
-
80
- it('formats price as "Enquire now" when price is "Enquire now"', () => {
81
- const resultWithEnquire = {
82
- ...mockApiResult,
83
- prices: { ...mockApiResult.prices, cheapest_price: 'Enquire now' }
84
- };
85
-
86
- const result = transformApiResult(resultWithEnquire);
87
-
88
- expect(result.price).toBe('Enquire now');
89
- });
90
-
91
- it('formats numeric price with £ symbol', () => {
92
- const result = transformApiResult(mockApiResult);
93
-
94
- expect(result.price).toBe('£2000');
95
- });
96
-
97
- it('returns undefined original_price when was_price is 0', () => {
98
- const resultWithZeroWasPrice = {
99
- ...mockApiResult,
100
- was_prices: { ...mockApiResult.was_prices, balcony: 0 }
101
- };
102
-
103
- const result = transformApiResult(resultWithZeroWasPrice);
104
-
105
- expect(result.original_price).toBeUndefined();
106
- });
107
-
108
- it('returns undefined original_price when was_price is "Enquire now"', () => {
109
- const resultWithEnquireWasPrice = {
110
- ...mockApiResult,
111
- was_prices: { ...mockApiResult.was_prices, balcony: 0 },
112
- prices: {
113
- ...mockApiResult.prices,
114
- cheapest_price: 'Enquire now',
115
- balcony: 'Enquire now'
116
- }
117
- };
118
-
119
- const result = transformApiResult(resultWithEnquireWasPrice);
120
-
121
- expect(result.original_price).toBeUndefined();
122
- });
123
-
124
- it('formats route with start and end for long itineraries', () => {
125
- const result = transformApiResult(mockApiResult);
126
-
127
- expect(result.route).toBe('Barcelona → Marseille');
128
- });
129
-
130
- it('formats route with all stops for short itineraries', () => {
131
- const resultWithShortItinerary = {
132
- ...mockApiResult,
133
- itinerary: ['Barcelona', 'Rome']
134
- };
135
-
136
- const result = transformApiResult(resultWithShortItinerary);
137
-
138
- expect(result.route).toBe('Barcelona → Rome');
139
- });
140
-
141
- it('returns undefined offer_label when no campaigns', () => {
142
- const resultWithNoCampaigns = {
143
- ...mockApiResult,
144
- campaigns: []
145
- };
146
-
147
- const result = transformApiResult(resultWithNoCampaigns);
148
-
149
- expect(result.offer_label).toBeUndefined();
150
- });
151
-
152
- it('uses data from extras object', () => {
153
- const result = transformApiResult(mockApiResult);
154
-
155
- expect(result.date).toBe('Oct 2025 - Oct 2025');
156
- expect(result.duration).toBe('Seven Days');
157
- });
158
-
159
- it('handles string prices correctly', () => {
160
- const resultWithStringPrice = {
161
- ...mockApiResult,
162
- prices: { ...mockApiResult.prices, cheapest_price: '£1500pp' }
163
- };
164
-
165
- const result = transformApiResult(resultWithStringPrice);
166
-
167
- expect(result.price).toBe('£1500pp');
168
- });
169
- });
170
-
171
- describe('fetchCruiseCards', () => {
172
- beforeEach(() => {
173
- global.fetch = jest.fn();
174
- });
175
-
176
- afterEach(() => {
177
- jest.resetAllMocks();
178
- });
179
-
180
- it('filters out offers with past departure dates', async () => {
181
- const futureDate = new Date();
182
- futureDate.setFullYear(futureDate.getFullYear() + 1);
183
- const futureDateString = futureDate.toISOString().split('T')[0];
184
-
185
- const validOffer: ApiCruiseResult = {
186
- ...mockApiResult,
187
- cruise_id: 1,
188
- departs: futureDateString // Future date
189
- };
190
-
191
- const pastOffer: ApiCruiseResult = {
192
- ...mockApiResult,
193
- cruise_id: 2,
194
- departs: '2024-01-01' // Past date
195
- };
196
-
197
- const mockResponse = {
198
- results: [validOffer, pastOffer]
199
- };
200
-
201
- (global.fetch as jest.Mock).mockResolvedValueOnce({
202
- ok: true,
203
- json: async () => mockResponse
204
- });
205
-
206
- const result = await fetchCruiseCards([1, 2]);
207
-
208
- // Should only include the valid offer with future date
209
- expect(result).toHaveLength(1);
210
- expect(result[0]).toBeDefined();
211
- expect(result[0].cruise_id).toBe('1');
212
- });
213
-
214
- it('filters out offers with invalid date format', async () => {
215
- const futureDate = new Date();
216
- futureDate.setFullYear(futureDate.getFullYear() + 1);
217
- const futureDateString = futureDate.toISOString().split('T')[0];
218
-
219
- const validOffer: ApiCruiseResult = {
220
- ...mockApiResult,
221
- cruise_id: 1,
222
- departs: futureDateString
223
- };
224
-
225
- const invalidDateOffer: ApiCruiseResult = {
226
- ...mockApiResult,
227
- cruise_id: 2,
228
- departs: 'invalid-date'
229
- };
230
-
231
- const mockResponse = {
232
- results: [validOffer, invalidDateOffer]
233
- };
234
-
235
- (global.fetch as jest.Mock).mockResolvedValueOnce({
236
- ok: true,
237
- json: async () => mockResponse
238
- });
239
-
240
- const result = await fetchCruiseCards([1, 2]);
241
-
242
- expect(result).toHaveLength(1);
243
- expect(result[0]).toBeDefined();
244
- expect(result[0].cruise_id).toBe('1');
245
- });
246
-
247
- it('includes offers departing today', async () => {
248
- const today = new Date();
249
- const todayString = today.toISOString().split('T')[0];
250
-
251
- const todayOffer: ApiCruiseResult = {
252
- ...mockApiResult,
253
- cruise_id: 1,
254
- departs: todayString
255
- };
256
-
257
- const mockResponse = {
258
- results: [todayOffer]
259
- };
260
-
261
- (global.fetch as jest.Mock).mockResolvedValueOnce({
262
- ok: true,
263
- json: async () => mockResponse
264
- });
265
-
266
- const result = await fetchCruiseCards([1]);
267
-
268
- expect(result).toHaveLength(1);
269
- expect(result[0]).toBeDefined();
270
- expect(result[0].cruise_id).toBe('1');
271
- });
272
- });