@financial-times/cp-content-pipeline-ui 9.12.0 → 9.13.0

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 (36) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/lib/components/ContentLayout/index.d.ts +24 -0
  3. package/lib/components/ContentLayout/index.js +34 -0
  4. package/lib/components/ContentLayout/index.js.map +1 -0
  5. package/lib/components/ContentLayout/test/index.spec.d.ts +1 -0
  6. package/lib/components/ContentLayout/test/index.spec.js +57 -0
  7. package/lib/components/ContentLayout/test/index.spec.js.map +1 -0
  8. package/lib/components/Topper/index.js +1 -1
  9. package/lib/components/Topper/index.js.map +1 -1
  10. package/lib/components/content-tree/Clip/components/index.d.ts +0 -2
  11. package/lib/components/content-tree/Clip/components/index.js +1 -5
  12. package/lib/components/content-tree/Clip/components/index.js.map +1 -1
  13. package/lib/components/content-tree/Clip/template/component.d.ts +1 -1
  14. package/lib/components/content-tree/Clip/template/component.js +3 -3
  15. package/lib/components/content-tree/Clip/template/component.js.map +1 -1
  16. package/lib/components/content-tree/Clip/test/snapshot.spec.js +26 -0
  17. package/lib/components/content-tree/Clip/test/snapshot.spec.js.map +1 -1
  18. package/lib/main.scss +6 -0
  19. package/package.json +4 -4
  20. package/src/components/ContentLayout/index.tsx +91 -0
  21. package/src/components/ContentLayout/test/__snapshots__/index.spec.tsx.snap +96 -0
  22. package/src/components/ContentLayout/test/index.spec.tsx +81 -0
  23. package/src/components/Topper/index.tsx +2 -1
  24. package/src/components/content-tree/Clip/components/index.tsx +0 -2
  25. package/src/components/content-tree/Clip/template/component.tsx +23 -24
  26. package/src/components/content-tree/Clip/test/__snapshots__/snapshot.spec.tsx.snap +277 -0
  27. package/src/components/content-tree/Clip/test/snapshot.spec.tsx +40 -0
  28. package/tsconfig.tsbuildinfo +1 -1
  29. package/lib/components/content-tree/Clip/components/Container.d.ts +0 -6
  30. package/lib/components/content-tree/Clip/components/Container.js +0 -13
  31. package/lib/components/content-tree/Clip/components/Container.js.map +0 -1
  32. package/lib/components/content-tree/Clip/components/ContentLayout.d.ts +0 -6
  33. package/lib/components/content-tree/Clip/components/ContentLayout.js +0 -13
  34. package/lib/components/content-tree/Clip/components/ContentLayout.js.map +0 -1
  35. package/src/components/content-tree/Clip/components/Container.tsx +0 -32
  36. package/src/components/content-tree/Clip/components/ContentLayout.tsx +0 -18
@@ -0,0 +1,81 @@
1
+ import React from 'react'
2
+ import renderer from 'react-test-renderer'
3
+ import { ContentLayout } from '../index'
4
+
5
+ describe('ContentLayout', () => {
6
+ it('renders full-grid layout with container correctly', () => {
7
+ const tree = renderer
8
+ .create(
9
+ <ContentLayout dataLayout="full-grid" dataComponent="clip-set">
10
+ <div>Test content</div>
11
+ </ContentLayout>
12
+ )
13
+ .toJSON()
14
+
15
+ expect(tree).toMatchSnapshot()
16
+ })
17
+
18
+ it('renders mid-grid layout with container correctly', () => {
19
+ const tree = renderer
20
+ .create(
21
+ <ContentLayout dataLayout="mid-grid" dataComponent="clip-set">
22
+ <div>Test content</div>
23
+ </ContentLayout>
24
+ )
25
+ .toJSON()
26
+
27
+ expect(tree).toMatchSnapshot()
28
+ })
29
+
30
+ it('renders in-line layout with container correctly', () => {
31
+ const tree = renderer
32
+ .create(
33
+ <ContentLayout dataLayout="in-line" dataComponent="clip-set">
34
+ <div>Test content</div>
35
+ </ContentLayout>
36
+ )
37
+ .toJSON()
38
+
39
+ expect(tree).toMatchSnapshot()
40
+ })
41
+
42
+ describe('Edge cases', () => {
43
+ it('handles empty children', () => {
44
+ const tree = renderer
45
+ .create(
46
+ <ContentLayout dataLayout="full-grid" dataComponent="clip-set">
47
+ <div></div>
48
+ </ContentLayout>
49
+ )
50
+ .toJSON()
51
+
52
+ expect(tree).toMatchSnapshot()
53
+ })
54
+
55
+ it('handles null children', () => {
56
+ const tree = renderer
57
+ .create(
58
+ <ContentLayout dataLayout="full-grid" dataComponent="clip-set">
59
+ <div>{null}</div>
60
+ </ContentLayout>
61
+ )
62
+ .toJSON()
63
+
64
+ expect(tree).toMatchSnapshot()
65
+ })
66
+
67
+ it('handles conditional children', () => {
68
+ const showContent = true
69
+ const tree = renderer
70
+ .create(
71
+ <ContentLayout dataLayout="full-grid" dataComponent="clip-set">
72
+ <div>{showContent && <div>Conditional content</div>}</div>
73
+ <div>{!showContent && <div>Alternative content</div>}</div>
74
+ </ContentLayout>
75
+ )
76
+ .toJSON()
77
+
78
+ expect(tree).toMatchSnapshot()
79
+ })
80
+ })
81
+ })
@@ -69,7 +69,8 @@ const Topper: React.FC<TopperProps> = ({
69
69
  'columnists' in topper &&
70
70
  !!topper.columnists &&
71
71
  topper.columnists.length > 0
72
- const legacyHasColumnist = 'columnist' in topper && !!topper.columnist // @deprecated Replaced with usage of `columinists`
72
+ const legacyHasColumnist =
73
+ 'columnist' in topper && topper.columnist && !hasColumnists // @deprecated Replaced with usage of `columinists`
73
74
  const hasOneColumnist =
74
75
  (hasColumnists && topper.columnists.length === 1) || legacyHasColumnist
75
76
  const oneColumnist = hasOneColumnist
@@ -3,6 +3,4 @@ export { Caption } from './Caption'
3
3
  export { VideoInfoBox } from './VideoInfoBox'
4
4
  export { ClosedCaptions } from './ClosedCaptions'
5
5
  export { VideoDescription } from './VideoDescription'
6
- export { Container } from './Container'
7
- export { ContentLayout } from './ContentLayout'
8
6
  export { ClipTag } from './ClipTag'
@@ -1,5 +1,6 @@
1
1
  import React from 'react'
2
- import { ClipTag, ContentLayout, Container } from '../components'
2
+ import { ContentLayout } from '../../../ContentLayout'
3
+ import { ClipTag } from '../components'
3
4
  import { ContentProps } from '../../../types'
4
5
  import type * as ComponentWorkarounds from '../../Workarounds'
5
6
 
@@ -21,7 +22,7 @@ export interface ClipPropsOld {
21
22
  clips?: ComponentWorkarounds.Clip[]
22
23
  poster?: string
23
24
  posterAlt?: string
24
- dataLayout: string
25
+ dataLayout: 'in-line' | 'mid-grid' | 'full-grid'
25
26
  description?: string
26
27
  muted?: boolean
27
28
  caption?: string
@@ -90,28 +91,26 @@ const ClipComponent: React.FC<ClipProps> = ({
90
91
  }
91
92
 
92
93
  return (
93
- <ContentLayout dataLayout={content.dataLayout}>
94
- <Container dataLayout={content.dataLayout}>
95
- <ClipTag
96
- id={id}
97
- dataLayout={content.dataLayout}
98
- description={content.description ?? ''}
99
- poster={posterAttribute}
100
- autoplay={content.autoplay}
101
- noAudio={noAudio}
102
- loop={content.loop}
103
- muted={content.muted}
104
- clip={clip}
105
- credits={content.credits ?? ''}
106
- caption={content.caption ?? ''}
107
- systemTitle={systemTitle}
108
- accessibility={accessibility}
109
- preload={preload}
110
- dataTrackable="next-article-cp-clip"
111
- maxClipWidth={maxClipWidth}
112
- fragmentIdentifier={content.fragmentIdentifier ?? ''}
113
- />
114
- </Container>
94
+ <ContentLayout dataLayout={content.dataLayout} dataComponent="clip-set">
95
+ <ClipTag
96
+ id={id}
97
+ dataLayout={content.dataLayout}
98
+ description={content.description ?? ''}
99
+ poster={posterAttribute}
100
+ autoplay={content.autoplay}
101
+ noAudio={noAudio}
102
+ loop={content.loop}
103
+ muted={content.muted}
104
+ clip={clip}
105
+ credits={content.credits ?? ''}
106
+ caption={content.caption ?? ''}
107
+ systemTitle={systemTitle}
108
+ accessibility={accessibility}
109
+ preload={preload}
110
+ dataTrackable="next-article-cp-clip"
111
+ maxClipWidth={maxClipWidth}
112
+ fragmentIdentifier={content.fragmentIdentifier ?? ''}
113
+ />
115
114
  </ContentLayout>
116
115
  )
117
116
  }
@@ -1,5 +1,282 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`Clip Snapshot component rendered on server ContentLayout integration tests edge case: custom dataLayout value should wrap in ContentLayout 1`] = `
4
+ "<div class="n-content-layout__container--in-line" data-component="clip-set">
5
+ <div
6
+ data-cp-clip-layout="custom-layout"
7
+ data-cp-clip-poster=""
8
+ data-cp-clip-no-audio="false"
9
+ data-cp-clip-no-description="false"
10
+ data-cp-clip-caption=""
11
+ data-cp-clip-no-info-box="false"
12
+ data-cp-clip-no-caption="false"
13
+ data-cp-clip-closed-caption="false"
14
+ class="cp-clip"
15
+ data-trackable="next-article-cp-clip"
16
+ data-o-component="cp-clip"
17
+ data-cp-clip-id="localhost:8080/fakevideo.mpg"
18
+ data-cp-clip-system-title=""
19
+ id=""
20
+ >
21
+ <div
22
+ data-o-component="o-expander"
23
+ class="o-expander o-expander__info-box"
24
+ data-o-expander-shrink-to="hidden"
25
+ data-trackable="clip-info-box"
26
+ data-o-expander-collapsed-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Show video info&lt;/span&gt;"
27
+ data-o-expander-expanded-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Hide video info&lt;/span&gt;"
28
+ >
29
+ <button
30
+ data-trackable="toggle-open-close"
31
+ class="o-expander__toggle o-expander__toggle-empty"
32
+ >
33
+ <span class="o-expander__visually-hidden o3-type-detail"
34
+ >Show video info</span
35
+ >
36
+ </button>
37
+ <div class="o-expander__content video-info"></div>
38
+ </div>
39
+ <div class="cp-clip__video-container">
40
+ <video
41
+ class="cp-clip__video"
42
+ controls=""
43
+ controlsList="nodownload noremoteplayback noplaybackrate"
44
+ disablepictureinpicture=""
45
+ disableremoteplayback=""
46
+ playsinline=""
47
+ poster=""
48
+ preload="auto"
49
+ id="clip-localhost:8080/fakevideo.mpg"
50
+ crossorigin="anonymous"
51
+ style="height: fit-content; width: 100%"
52
+ >
53
+ <source
54
+ id="video-source-0-localhost:8080/fakevideo.mpg"
55
+ data-cp-component="cp-clip__video-source"
56
+ src="localhost:8080/fakevideo.mpg"
57
+ type="video/mp4"
58
+ />
59
+ </video>
60
+ </div>
61
+ <div
62
+ class="cp-clip__video-meta-info"
63
+ data-cp-clip-video-meta-info="true"
64
+ ></div>
65
+ </div>
66
+ </div>
67
+ "
68
+ `;
69
+
70
+ exports[`Clip Snapshot component rendered on server ContentLayout integration tests full-grid default render - should wrap in ContentLayout with proper classes 1`] = `
71
+ "<div class="n-content-layout" data-layout-width="full-grid">
72
+ <div class="n-content-layout__container" data-component="clip-set">
73
+ <div
74
+ data-cp-clip-layout="full-grid"
75
+ data-cp-clip-poster=""
76
+ data-cp-clip-no-audio="false"
77
+ data-cp-clip-no-description="false"
78
+ data-cp-clip-caption=""
79
+ data-cp-clip-no-info-box="false"
80
+ data-cp-clip-no-caption="false"
81
+ data-cp-clip-closed-caption="false"
82
+ class="cp-clip"
83
+ data-trackable="next-article-cp-clip"
84
+ data-o-component="cp-clip"
85
+ data-cp-clip-id="localhost:8080/fakevideo.mpg"
86
+ data-cp-clip-system-title=""
87
+ id=""
88
+ >
89
+ <div
90
+ data-o-component="o-expander"
91
+ class="o-expander o-expander__info-box"
92
+ data-o-expander-shrink-to="hidden"
93
+ data-trackable="clip-info-box"
94
+ data-o-expander-collapsed-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Show video info&lt;/span&gt;"
95
+ data-o-expander-expanded-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Hide video info&lt;/span&gt;"
96
+ >
97
+ <button
98
+ data-trackable="toggle-open-close"
99
+ class="o-expander__toggle o-expander__toggle-empty"
100
+ >
101
+ <span class="o-expander__visually-hidden o3-type-detail"
102
+ >Show video info</span
103
+ >
104
+ </button>
105
+ <div class="o-expander__content video-info"></div>
106
+ </div>
107
+ <div class="cp-clip__video-container">
108
+ <video
109
+ class="cp-clip__video"
110
+ controls=""
111
+ controlsList="nodownload noremoteplayback noplaybackrate"
112
+ disablepictureinpicture=""
113
+ disableremoteplayback=""
114
+ playsinline=""
115
+ poster=""
116
+ preload="auto"
117
+ id="clip-localhost:8080/fakevideo.mpg"
118
+ crossorigin="anonymous"
119
+ style="height: fit-content; width: 100%"
120
+ >
121
+ <source
122
+ id="video-source-0-localhost:8080/fakevideo.mpg"
123
+ data-cp-component="cp-clip__video-source"
124
+ src="localhost:8080/fakevideo.mpg"
125
+ type="video/mp4"
126
+ />
127
+ </video>
128
+ </div>
129
+ <div
130
+ class="cp-clip__video-meta-info"
131
+ data-cp-clip-video-meta-info="true"
132
+ ></div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ "
137
+ `;
138
+
139
+ exports[`Clip Snapshot component rendered on server ContentLayout integration tests in-line render - should not wrap in ContentLayout div 1`] = `
140
+ "<div class="n-content-layout__container--in-line" data-component="clip-set">
141
+ <div
142
+ data-cp-clip-layout="in-line"
143
+ data-cp-clip-poster=""
144
+ data-cp-clip-no-audio="false"
145
+ data-cp-clip-no-description="false"
146
+ data-cp-clip-caption=""
147
+ data-cp-clip-no-info-box="false"
148
+ data-cp-clip-no-caption="false"
149
+ data-cp-clip-closed-caption="false"
150
+ class="cp-clip"
151
+ data-trackable="next-article-cp-clip"
152
+ data-o-component="cp-clip"
153
+ data-cp-clip-id="localhost:8080/fakevideo.mpg"
154
+ data-cp-clip-system-title=""
155
+ id=""
156
+ >
157
+ <div
158
+ data-o-component="o-expander"
159
+ class="o-expander o-expander__info-box"
160
+ data-o-expander-shrink-to="hidden"
161
+ data-trackable="clip-info-box"
162
+ data-o-expander-collapsed-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Show video info&lt;/span&gt;"
163
+ data-o-expander-expanded-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Hide video info&lt;/span&gt;"
164
+ >
165
+ <button
166
+ data-trackable="toggle-open-close"
167
+ class="o-expander__toggle o-expander__toggle-empty"
168
+ >
169
+ <span class="o-expander__visually-hidden o3-type-detail"
170
+ >Show video info</span
171
+ >
172
+ </button>
173
+ <div class="o-expander__content video-info"></div>
174
+ </div>
175
+ <div class="cp-clip__video-container">
176
+ <video
177
+ class="cp-clip__video"
178
+ controls=""
179
+ controlsList="nodownload noremoteplayback noplaybackrate"
180
+ disablepictureinpicture=""
181
+ disableremoteplayback=""
182
+ playsinline=""
183
+ poster=""
184
+ preload="auto"
185
+ id="clip-localhost:8080/fakevideo.mpg"
186
+ crossorigin="anonymous"
187
+ style="height: fit-content; width: 100%"
188
+ >
189
+ <source
190
+ id="video-source-0-localhost:8080/fakevideo.mpg"
191
+ data-cp-component="cp-clip__video-source"
192
+ src="localhost:8080/fakevideo.mpg"
193
+ type="video/mp4"
194
+ />
195
+ </video>
196
+ </div>
197
+ <div
198
+ class="cp-clip__video-meta-info"
199
+ data-cp-clip-video-meta-info="true"
200
+ ></div>
201
+ </div>
202
+ </div>
203
+ "
204
+ `;
205
+
206
+ exports[`Clip Snapshot component rendered on server ContentLayout integration tests mid-grid default render - should wrap in ContentLayout with nested Container structure 1`] = `
207
+ "<div class="n-content-layout" data-layout-width="full-grid">
208
+ <div class="n-content-layout__container" data-component="clip-set">
209
+ <div
210
+ data-o-grid-colspan="12 S12 M12 L10 XL10"
211
+ class="n-content-layout__container--mid-grid"
212
+ >
213
+ <div
214
+ data-cp-clip-layout="mid-grid"
215
+ data-cp-clip-poster=""
216
+ data-cp-clip-no-audio="false"
217
+ data-cp-clip-no-description="false"
218
+ data-cp-clip-caption=""
219
+ data-cp-clip-no-info-box="false"
220
+ data-cp-clip-no-caption="false"
221
+ data-cp-clip-closed-caption="false"
222
+ class="cp-clip"
223
+ data-trackable="next-article-cp-clip"
224
+ data-o-component="cp-clip"
225
+ data-cp-clip-id="localhost:8080/fakevideo.mpg"
226
+ data-cp-clip-system-title=""
227
+ id=""
228
+ >
229
+ <div
230
+ data-o-component="o-expander"
231
+ class="o-expander o-expander__info-box"
232
+ data-o-expander-shrink-to="hidden"
233
+ data-trackable="clip-info-box"
234
+ data-o-expander-collapsed-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Show video info&lt;/span&gt;"
235
+ data-o-expander-expanded-toggle-text="&lt;span class=&#x27;o-expander__visually-hidden&#x27;&gt;Hide video info&lt;/span&gt;"
236
+ >
237
+ <button
238
+ data-trackable="toggle-open-close"
239
+ class="o-expander__toggle o-expander__toggle-empty"
240
+ >
241
+ <span class="o-expander__visually-hidden o3-type-detail"
242
+ >Show video info</span
243
+ >
244
+ </button>
245
+ <div class="o-expander__content video-info"></div>
246
+ </div>
247
+ <div class="cp-clip__video-container">
248
+ <video
249
+ class="cp-clip__video"
250
+ controls=""
251
+ controlsList="nodownload noremoteplayback noplaybackrate"
252
+ disablepictureinpicture=""
253
+ disableremoteplayback=""
254
+ playsinline=""
255
+ poster=""
256
+ preload="auto"
257
+ id="clip-localhost:8080/fakevideo.mpg"
258
+ crossorigin="anonymous"
259
+ style="height: fit-content; width: 100%"
260
+ >
261
+ <source
262
+ id="video-source-0-localhost:8080/fakevideo.mpg"
263
+ data-cp-component="cp-clip__video-source"
264
+ src="localhost:8080/fakevideo.mpg"
265
+ type="video/mp4"
266
+ />
267
+ </video>
268
+ </div>
269
+ <div
270
+ class="cp-clip__video-meta-info"
271
+ data-cp-clip-video-meta-info="true"
272
+ ></div>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ </div>
277
+ "
278
+ `;
279
+
3
280
  exports[`Clip Snapshot component rendered on server full-grid default render 1`] = `
4
281
  "<div class="n-content-layout" data-layout-width="full-grid">
5
282
  <div class="n-content-layout__container" data-component="clip-set">
@@ -25,6 +25,46 @@ describe('Clip Snapshot', () => {
25
25
  const url = 'localhost:8080/fakevideo.mpg'
26
26
  const poster = 'localhost:8080/fakeposter.jpg'
27
27
 
28
+ describe('ContentLayout integration tests', () => {
29
+ it('in-line render - should not wrap in ContentLayout div', () => {
30
+ const tree = renderer
31
+ .create(
32
+ <ClipServer content={{ url, dataLayout: 'in-line' }}></ClipServer>
33
+ )
34
+ .toJSON()
35
+ expect(formatString(tree)).toMatchSnapshot()
36
+ })
37
+
38
+ it('full-grid default render - should wrap in ContentLayout with proper classes', () => {
39
+ const tree = renderer
40
+ .create(
41
+ <ClipServer content={{ url, dataLayout: 'full-grid' }}></ClipServer>
42
+ )
43
+ .toJSON()
44
+ expect(formatString(tree)).toMatchSnapshot()
45
+ })
46
+
47
+ it('mid-grid default render - should wrap in ContentLayout with nested Container structure', () => {
48
+ const tree = renderer
49
+ .create(
50
+ <ClipServer content={{ url, dataLayout: 'mid-grid' }}></ClipServer>
51
+ )
52
+ .toJSON()
53
+ expect(formatString(tree)).toMatchSnapshot()
54
+ })
55
+
56
+ it('edge case: custom dataLayout value should wrap in ContentLayout', () => {
57
+ const tree = renderer
58
+ .create(
59
+ <ClipServer
60
+ content={{ url, dataLayout: 'custom-layout' }}
61
+ ></ClipServer>
62
+ )
63
+ .toJSON()
64
+ expect(formatString(tree)).toMatchSnapshot()
65
+ })
66
+ })
67
+
28
68
  it('in-line render', () => {
29
69
  const tree = renderer
30
70
  .create(