@financial-times/cp-content-pipeline-schema 3.12.2 → 3.14.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.
- package/CHANGELOG.md +32 -0
- package/lib/datasources/origami-image.js +3 -3
- package/lib/datasources/origami-image.js.map +1 -1
- package/lib/datasources/url-management.js +45 -7
- package/lib/datasources/url-management.js.map +1 -1
- package/lib/datasources/url-management.test.js +97 -0
- package/lib/datasources/url-management.test.js.map +1 -1
- package/lib/generated/index.d.ts +11 -11
- package/lib/helpers/imageService.js +1 -1
- package/lib/helpers/imageService.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/model/Clip.d.ts +3 -1
- package/lib/model/Clip.js +4 -2
- package/lib/model/Clip.js.map +1 -1
- package/lib/model/Clip.test.js +26 -37
- package/lib/model/Clip.test.js.map +1 -1
- package/lib/model/Concept.js +8 -2
- package/lib/model/Concept.js.map +1 -1
- package/lib/model/Content.js +6 -1
- package/lib/model/Content.js.map +1 -1
- package/lib/model/FlourishSource.js +2 -2
- package/lib/model/FlourishSource.js.map +1 -1
- package/lib/model/Image.js +1 -1
- package/lib/model/Image.js.map +1 -1
- package/lib/model/Image.test.js +8 -8
- package/lib/model/Image.test.js.map +1 -1
- package/lib/model/LeadFlourish.js +1 -1
- package/lib/model/LeadFlourish.js.map +1 -1
- package/lib/model/Person.js +1 -1
- package/lib/model/Person.js.map +1 -1
- package/lib/model/Person.test.js +2 -2
- package/lib/model/Person.test.js.map +1 -1
- package/lib/model/Picture.test.js +4 -2
- package/lib/model/Picture.test.js.map +1 -1
- package/lib/model/RichText.test.js +9 -9
- package/lib/model/Topper.js +1 -1
- package/lib/model/Topper.js.map +1 -1
- package/lib/model/Topper.test.js +3 -2
- package/lib/model/Topper.test.js.map +1 -1
- package/lib/resolvers/content-tree/bodyXMLToTree.test.js +176 -176
- package/lib/resolvers/content-tree/references/ClipSet.d.ts +2 -1
- package/lib/resolvers/content-tree/references/ClipSet.js +2 -2
- package/lib/resolvers/content-tree/references/ClipSet.js.map +1 -1
- package/lib/resolvers/content-tree/references/RawImage.js +1 -1
- package/lib/resolvers/content-tree/references/RawImage.js.map +1 -1
- package/package.json +1 -1
- package/src/datasources/origami-image.ts +3 -3
- package/src/datasources/url-management.test.ts +126 -0
- package/src/datasources/url-management.ts +48 -8
- package/src/generated/index.ts +11 -11
- package/src/helpers/imageService.ts +1 -1
- package/src/index.ts +1 -1
- package/src/model/Clip.test.ts +164 -145
- package/src/model/Clip.ts +7 -3
- package/src/model/Concept.ts +8 -2
- package/src/model/Content.ts +6 -1
- package/src/model/FlourishSource.ts +3 -6
- package/src/model/Image.test.ts +8 -10
- package/src/model/Image.ts +1 -1
- package/src/model/LeadFlourish.ts +1 -1
- package/src/model/Person.test.ts +2 -2
- package/src/model/Person.ts +1 -1
- package/src/model/Picture.test.ts +4 -2
- package/src/model/RichText.test.ts +9 -9
- package/src/model/Topper.test.ts +4 -2
- package/src/model/Topper.ts +1 -1
- package/src/model/__snapshots__/Byline.test.ts.snap +99 -99
- package/src/model/__snapshots__/RichText.test.ts.snap +305 -305
- package/src/resolvers/content-tree/bodyXMLToTree.test.ts +176 -176
- package/src/resolvers/content-tree/references/ClipSet.ts +3 -2
- package/src/resolvers/content-tree/references/RawImage.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/typedefs/image.graphql +11 -11
package/src/model/Clip.test.ts
CHANGED
|
@@ -1,154 +1,173 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryContext } from '..'
|
|
2
|
+
import { Clip } from './Clip'
|
|
3
|
+
const mockContext = {
|
|
4
|
+
systemCode: 'cp-content-pipeline',
|
|
5
|
+
} as unknown as QueryContext
|
|
2
6
|
|
|
3
7
|
describe('Clip', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
describe('poster', () => {
|
|
9
|
+
it('uses the Origami Image Service when a url is provided', () => {
|
|
10
|
+
const clip = new Clip(
|
|
11
|
+
{
|
|
12
|
+
id: 'http://api.ft.com/things/1234',
|
|
13
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
14
|
+
dataSource: [{}],
|
|
15
|
+
poster: {
|
|
16
|
+
id: 'http://api.ft.com/things/1234',
|
|
17
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
18
|
+
members: [
|
|
19
|
+
{
|
|
7
20
|
id: 'http://api.ft.com/things/1234',
|
|
8
|
-
type:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
22
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
mockContext
|
|
28
|
+
)
|
|
29
|
+
expect(clip.poster()).toContain('https://images.ft.com/v3/image/raw/')
|
|
30
|
+
expect(clip.poster()).toContain(
|
|
31
|
+
'source=cp-content-pipeline&fit=scale-down&quality=highest'
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
it('returns an empty string if an image url is not provided', () => {
|
|
35
|
+
const clip = new Clip(
|
|
36
|
+
{
|
|
37
|
+
id: 'http://api.ft.com/things/1234',
|
|
38
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
39
|
+
dataSource: [{}],
|
|
40
|
+
poster: {
|
|
41
|
+
id: 'http://api.ft.com/things/1234',
|
|
42
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
43
|
+
members: [
|
|
44
|
+
{
|
|
29
45
|
id: 'http://api.ft.com/things/1234',
|
|
30
|
-
type:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
47
|
+
binaryUrl: '',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
mockContext
|
|
53
|
+
)
|
|
54
|
+
expect(clip.poster()).toEqual('')
|
|
55
|
+
})
|
|
56
|
+
it('uses a default width if a layout is not provided', () => {
|
|
57
|
+
const clip = new Clip(
|
|
58
|
+
{
|
|
59
|
+
id: 'http://api.ft.com/things/1234',
|
|
60
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
61
|
+
dataSource: [{}],
|
|
62
|
+
poster: {
|
|
63
|
+
id: 'http://api.ft.com/things/1234',
|
|
64
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
65
|
+
members: [
|
|
66
|
+
{
|
|
50
67
|
id: 'http://api.ft.com/things/1234',
|
|
51
|
-
type:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
69
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
mockContext
|
|
75
|
+
)
|
|
76
|
+
expect(clip.poster()).toContain('width=700')
|
|
77
|
+
})
|
|
78
|
+
it('uses a default width if a layout is not supported', () => {
|
|
79
|
+
const clip = new Clip(
|
|
80
|
+
{
|
|
81
|
+
id: 'http://api.ft.com/things/1234',
|
|
82
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
83
|
+
dataSource: [{}],
|
|
84
|
+
poster: {
|
|
85
|
+
id: 'http://api.ft.com/things/1234',
|
|
86
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
87
|
+
members: [
|
|
88
|
+
{
|
|
71
89
|
id: 'http://api.ft.com/things/1234',
|
|
72
|
-
type:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
91
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
mockContext,
|
|
97
|
+
'I-dont-exist'
|
|
98
|
+
)
|
|
99
|
+
expect(clip.poster()).toEqual(
|
|
100
|
+
'https://images.ft.com/v3/image/raw/http%3A%2F%2Fvideo.ft.com%2F1234.jpg?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
101
|
+
)
|
|
102
|
+
})
|
|
103
|
+
it('generates an image with the appropriate width for a `in-line` layout', () => {
|
|
104
|
+
const clip = new Clip(
|
|
105
|
+
{
|
|
106
|
+
id: 'http://api.ft.com/things/1234',
|
|
107
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
108
|
+
dataSource: [{}],
|
|
109
|
+
poster: {
|
|
110
|
+
id: 'http://api.ft.com/things/1234',
|
|
111
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
112
|
+
members: [
|
|
113
|
+
{
|
|
92
114
|
id: 'http://api.ft.com/things/1234',
|
|
93
|
-
type:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
116
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
mockContext,
|
|
122
|
+
'in-line'
|
|
123
|
+
)
|
|
124
|
+
expect(clip.poster()).toContain('width=700')
|
|
125
|
+
})
|
|
126
|
+
it('generates an image with the appropriate width for a `mid-grid` layout', () => {
|
|
127
|
+
const clip = new Clip(
|
|
128
|
+
{
|
|
129
|
+
id: 'http://api.ft.com/things/1234',
|
|
130
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
131
|
+
dataSource: [{}],
|
|
132
|
+
poster: {
|
|
133
|
+
id: 'http://api.ft.com/things/1234',
|
|
134
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
135
|
+
members: [
|
|
136
|
+
{
|
|
113
137
|
id: 'http://api.ft.com/things/1234',
|
|
114
|
-
type:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
138
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
139
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
mockContext,
|
|
145
|
+
'mid-grid'
|
|
146
|
+
)
|
|
147
|
+
expect(clip.poster()).toContain('width=900')
|
|
148
|
+
})
|
|
149
|
+
it('generates an image with the appropriate width for a `full-grid` layout', () => {
|
|
150
|
+
const clip = new Clip(
|
|
151
|
+
{
|
|
152
|
+
id: 'http://api.ft.com/things/1234',
|
|
153
|
+
type: 'http://www.ft.com/ontology/content/Clip',
|
|
154
|
+
dataSource: [{}],
|
|
155
|
+
poster: {
|
|
156
|
+
id: 'http://api.ft.com/things/1234',
|
|
157
|
+
type: 'http://www.ft.com/ontology/content/ImageSet',
|
|
158
|
+
members: [
|
|
159
|
+
{
|
|
134
160
|
id: 'http://api.ft.com/things/1234',
|
|
135
|
-
type:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
],
|
|
149
|
-
},
|
|
150
|
-
}, 'full-grid');
|
|
151
|
-
expect(clip.poster()).toContain('width=1200');
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
});
|
|
161
|
+
type: 'http://www.ft.com/ontology/content/Image',
|
|
162
|
+
binaryUrl: 'http://video.ft.com/1234.jpg',
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
mockContext,
|
|
168
|
+
'full-grid'
|
|
169
|
+
)
|
|
170
|
+
expect(clip.poster()).toContain('width=1200')
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
})
|
package/src/model/Clip.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from '../resolvers/literal-union'
|
|
7
7
|
import { ClipFormat } from '../resolvers/scalars'
|
|
8
8
|
import imageServiceUrl from '../helpers/imageService'
|
|
9
|
+
import { QueryContext } from '..'
|
|
9
10
|
|
|
10
11
|
type ClipSource = {
|
|
11
12
|
binaryUrl: string
|
|
@@ -26,8 +27,11 @@ interface ClipVideo {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export class Clip implements ClipVideo {
|
|
29
|
-
constructor(
|
|
30
|
-
|
|
30
|
+
constructor(
|
|
31
|
+
private clip: ClipMetadata,
|
|
32
|
+
private context: QueryContext,
|
|
33
|
+
private layout?: string
|
|
34
|
+
) {}
|
|
31
35
|
type() {
|
|
32
36
|
return 'clip'
|
|
33
37
|
}
|
|
@@ -83,7 +87,7 @@ export class Clip implements ClipVideo {
|
|
|
83
87
|
return url
|
|
84
88
|
? imageServiceUrl({
|
|
85
89
|
url,
|
|
86
|
-
systemCode:
|
|
90
|
+
systemCode: this.context.systemCode,
|
|
87
91
|
width:
|
|
88
92
|
this.layout && mapSizes[this.layout] ? mapSizes[this.layout] : 700,
|
|
89
93
|
})
|
package/src/model/Concept.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { QueryContext } from '..'
|
|
|
3
3
|
import { uuidFromUrl } from '../helpers/metadata'
|
|
4
4
|
import isError from '../helpers/isError'
|
|
5
5
|
import conceptIds from '@financial-times/n-concept-ids'
|
|
6
|
+
import { OperationalError } from '@dotcom-reliability-kit/errors'
|
|
6
7
|
|
|
7
8
|
const CAPI_ID_PREFIX = /^https?:\/\/(?:www|api)\.ft\.com\/things?\//
|
|
8
9
|
const BASE_URL = 'https://www.ft.com/stream/'
|
|
@@ -53,7 +54,7 @@ export class Concept {
|
|
|
53
54
|
#systemCode: string
|
|
54
55
|
|
|
55
56
|
constructor(private capiConcept: Annotation, private context: QueryContext) {
|
|
56
|
-
this.#systemCode = context.systemCode
|
|
57
|
+
this.#systemCode = context.systemCode
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
apiUrl() {
|
|
@@ -155,7 +156,12 @@ export class Concept {
|
|
|
155
156
|
if (isError(error)) {
|
|
156
157
|
this.context.logger.warn({
|
|
157
158
|
event: 'RECOVERABLE_ERROR',
|
|
158
|
-
error
|
|
159
|
+
error: new OperationalError({
|
|
160
|
+
code: 'CONCEPT_VANITY_ERROR',
|
|
161
|
+
message: `Could not get vanity URL for concept. This means we'll be displaying the underlying URL instead of the vanity, which will cause additional redirects.`,
|
|
162
|
+
uuid: this.id(),
|
|
163
|
+
cause: error,
|
|
164
|
+
}),
|
|
159
165
|
})
|
|
160
166
|
}
|
|
161
167
|
}
|
package/src/model/Content.ts
CHANGED
|
@@ -252,7 +252,12 @@ export class Content {
|
|
|
252
252
|
if (isError(error)) {
|
|
253
253
|
this.context.logger.warn({
|
|
254
254
|
event: 'RECOVERABLE_ERROR',
|
|
255
|
-
error
|
|
255
|
+
error: new OperationalError({
|
|
256
|
+
code: 'CONTENT_VANITY_ERROR',
|
|
257
|
+
message: `Could not get vanity URL for content. This means we'll be displaying the underlying URL instead of the vanity, which will cause additional redirects.`,
|
|
258
|
+
uuid: this.id(),
|
|
259
|
+
cause: error,
|
|
260
|
+
}),
|
|
256
261
|
})
|
|
257
262
|
}
|
|
258
263
|
}
|
|
@@ -43,7 +43,7 @@ export class FlourishSource {
|
|
|
43
43
|
private flourishData: FlourishData,
|
|
44
44
|
private context: QueryContext
|
|
45
45
|
) {
|
|
46
|
-
this.#systemCode = context.systemCode
|
|
46
|
+
this.#systemCode = context.systemCode
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
id() {
|
|
@@ -71,10 +71,7 @@ export class FlourishSource {
|
|
|
71
71
|
}/thumbnail?cacheBuster=${cacheBusterTimestamp}`
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
static async getImageMetadata(
|
|
75
|
-
data: FlourishData,
|
|
76
|
-
context: QueryContext
|
|
77
|
-
) {
|
|
74
|
+
static async getImageMetadata(data: FlourishData, context: QueryContext) {
|
|
78
75
|
const url = FlourishSource.fallbackUrl(data)
|
|
79
76
|
|
|
80
77
|
try {
|
|
@@ -114,7 +111,7 @@ export class FlourishSource {
|
|
|
114
111
|
url() {
|
|
115
112
|
return imageServiceUrl({
|
|
116
113
|
url: this.flourishUrl(),
|
|
117
|
-
systemCode:
|
|
114
|
+
systemCode: this.context.systemCode,
|
|
118
115
|
width: this.width(),
|
|
119
116
|
})
|
|
120
117
|
}
|
package/src/model/Image.test.ts
CHANGED
|
@@ -50,9 +50,7 @@ describe('Image', () => {
|
|
|
50
50
|
it('transforms the URL to use the Origami Image Service', () => {
|
|
51
51
|
expect(
|
|
52
52
|
sourceSet.every((source) =>
|
|
53
|
-
source.url.startsWith(
|
|
54
|
-
'https://www.ft.com/__origami/service/image/v2'
|
|
55
|
-
)
|
|
53
|
+
source.url.startsWith('https://images.ft.com/v3/image')
|
|
56
54
|
)
|
|
57
55
|
).toBeTruthy()
|
|
58
56
|
})
|
|
@@ -83,7 +81,7 @@ describe('Image', () => {
|
|
|
83
81
|
expect(sourceSet.length).toEqual(1)
|
|
84
82
|
expect(sourceSet[0]).toEqual({
|
|
85
83
|
dpr: 1,
|
|
86
|
-
url: 'https://
|
|
84
|
+
url: 'https://images.ft.com/v3/image/raw/ftcms%3A00000000-0000-0000-0000-000000000001?source=image-test&fit=scale-down&quality=highest&width=1000&dpr=1',
|
|
87
85
|
width: 1000,
|
|
88
86
|
})
|
|
89
87
|
})
|
|
@@ -97,7 +95,7 @@ describe('Image', () => {
|
|
|
97
95
|
expect(sourceSet.length).toEqual(1)
|
|
98
96
|
expect(sourceSet[0]).toEqual({
|
|
99
97
|
dpr: 1,
|
|
100
|
-
url: 'https://
|
|
98
|
+
url: 'https://images.ft.com/v3/image/raw/ftcms%3A00000000-0000-0000-0000-000000000001?source=image-test&fit=scale-down&quality=highest&width=500&dpr=1',
|
|
101
99
|
width: 500,
|
|
102
100
|
})
|
|
103
101
|
})
|
|
@@ -150,15 +148,15 @@ describe('Image', () => {
|
|
|
150
148
|
})
|
|
151
149
|
it('returns an image service URL with the requested width and max DPR 2', () => {
|
|
152
150
|
expect(sourceSet).toMatchInlineSnapshot(`
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
[
|
|
152
|
+
{
|
|
155
153
|
"dpr": 1,
|
|
156
|
-
"url": "https://
|
|
154
|
+
"url": "https://images.ft.com/v3/image/raw/ftcms%3A00000000-0000-0000-0000-000000000001?source=image-test&fit=scale-down&quality=highest&width=3000&dpr=1",
|
|
157
155
|
"width": 3000,
|
|
158
156
|
},
|
|
159
|
-
|
|
157
|
+
{
|
|
160
158
|
"dpr": 2,
|
|
161
|
-
"url": "https://
|
|
159
|
+
"url": "https://images.ft.com/v3/image/raw/ftcms%3A00000000-0000-0000-0000-000000000001?source=image-test&fit=scale-down&quality=highest&width=3000&dpr=2",
|
|
162
160
|
"width": 3000,
|
|
163
161
|
},
|
|
164
162
|
]
|
package/src/model/Image.ts
CHANGED
|
@@ -41,7 +41,7 @@ export class CAPIImage implements Image {
|
|
|
41
41
|
private context: QueryContext,
|
|
42
42
|
private leadImage?: LeadImage
|
|
43
43
|
) {
|
|
44
|
-
this.#systemCode = context.systemCode
|
|
44
|
+
this.#systemCode = context.systemCode
|
|
45
45
|
this.#dataSources = context.dataSources
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -5,7 +5,7 @@ import { FlourishSource } from './FlourishSource'
|
|
|
5
5
|
export class LeadFlourish {
|
|
6
6
|
#systemCode: string
|
|
7
7
|
constructor(private capiResponse: Content, private context: QueryContext) {
|
|
8
|
-
this.#systemCode = context.systemCode
|
|
8
|
+
this.#systemCode = context.systemCode
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
async fallbackImage() {
|
package/src/model/Person.test.ts
CHANGED
|
@@ -28,14 +28,14 @@ describe('Person model', () => {
|
|
|
28
28
|
it('returns the headshot for an author', async () => {
|
|
29
29
|
const model = new Person(capiPerson as CapiPerson, context)
|
|
30
30
|
expect(await model.headshot({})).toEqual(
|
|
31
|
-
'https://
|
|
31
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fd1e00ek4ebabms.cloudfront.net%2Fproduction%2Fuploaded-files%2Ffthead-v1_robert-shrimsley-cc467908-15d6-474d-94d8-171594ceabb9.png?source=image-test&fit=scale-down&quality=highest&width=150&dpr=1'
|
|
32
32
|
)
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
it('can resize headshot and provide high resolution version', async () => {
|
|
36
36
|
const model = new Person(capiPerson as CapiPerson, context)
|
|
37
37
|
expect(await model.headshot({ width: 300, dpr: 2 })).toEqual(
|
|
38
|
-
'https://
|
|
38
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fd1e00ek4ebabms.cloudfront.net%2Fproduction%2Fuploaded-files%2Ffthead-v1_robert-shrimsley-cc467908-15d6-474d-94d8-171594ceabb9.png?source=image-test&fit=scale-down&quality=highest&width=300&dpr=2'
|
|
39
39
|
)
|
|
40
40
|
})
|
|
41
41
|
|
package/src/model/Person.ts
CHANGED
|
@@ -34,12 +34,13 @@ describe('Picture model', () => {
|
|
|
34
34
|
} as ImageSet
|
|
35
35
|
|
|
36
36
|
const mockContext = {} as QueryContext
|
|
37
|
+
mockContext.systemCode = 'cp-content-pipeline-api'
|
|
37
38
|
|
|
38
39
|
describe('finding the standard image', () => {
|
|
39
40
|
it('uses the StandardInline image if it exists', () => {
|
|
40
41
|
const picture = new Picture(mockImageSet, isLiveBlog, mockContext)
|
|
41
42
|
expect(picture.standard().url()).toEqual(
|
|
42
|
-
'https://
|
|
43
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fcloudfront.com%2Fstandard-inline.jpg?source=cp-content-pipeline-api&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
43
44
|
)
|
|
44
45
|
})
|
|
45
46
|
|
|
@@ -51,6 +52,7 @@ describe('Picture model', () => {
|
|
|
51
52
|
apiUrl: 'https://api.ft.com/content/image-set',
|
|
52
53
|
canBeSyndicated: 'verify',
|
|
53
54
|
description: 'imageset description',
|
|
55
|
+
systemCode: 'cp-content-pipeline-api',
|
|
54
56
|
id: 'https://api.ft.com/content/image-set',
|
|
55
57
|
members: [
|
|
56
58
|
{
|
|
@@ -81,7 +83,7 @@ describe('Picture model', () => {
|
|
|
81
83
|
mockContext
|
|
82
84
|
)
|
|
83
85
|
expect(picture.standard().url()).toEqual(
|
|
84
|
-
'https://
|
|
86
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fcloudfront.com%2Fdesktop.jpg?source=cp-content-pipeline-api&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
85
87
|
)
|
|
86
88
|
})
|
|
87
89
|
})
|
|
@@ -15,12 +15,12 @@ describe('RichText resolver', () => {
|
|
|
15
15
|
'The UK’s first ID Buzz campervan is available to rent. On a test-drive in Sussex, it charms both passengers and passers-by'
|
|
16
16
|
)
|
|
17
17
|
expect(await model.structured()).toMatchInlineSnapshot(`
|
|
18
|
-
|
|
19
|
-
"references":
|
|
18
|
+
{
|
|
19
|
+
"references": [],
|
|
20
20
|
"text": "",
|
|
21
|
-
"tree":
|
|
22
|
-
"children":
|
|
23
|
-
|
|
21
|
+
"tree": {
|
|
22
|
+
"children": [
|
|
23
|
+
{
|
|
24
24
|
"type": "text",
|
|
25
25
|
"value": "The UK’s first ID Buzz campervan is available to rent. On a test-drive in Sussex, it charms both passengers and passers-by",
|
|
26
26
|
},
|
|
@@ -35,11 +35,11 @@ describe('RichText resolver', () => {
|
|
|
35
35
|
it('should handle nulls', async () => {
|
|
36
36
|
const model = new RichText('standfirst', null)
|
|
37
37
|
expect(await model.structured()).toMatchInlineSnapshot(`
|
|
38
|
-
|
|
39
|
-
"references":
|
|
38
|
+
{
|
|
39
|
+
"references": [],
|
|
40
40
|
"text": "",
|
|
41
|
-
"tree":
|
|
42
|
-
"children":
|
|
41
|
+
"tree": {
|
|
42
|
+
"children": [],
|
|
43
43
|
"type": "body",
|
|
44
44
|
"version": 1,
|
|
45
45
|
},
|
package/src/model/Topper.test.ts
CHANGED
|
@@ -15,6 +15,8 @@ import imageServiceUrl from '../helpers/imageService'
|
|
|
15
15
|
import { capiPerson } from '../fixtures/capiPerson'
|
|
16
16
|
|
|
17
17
|
const context = {} as unknown as QueryContext
|
|
18
|
+
context.systemCode = 'cp-content-pipeline'
|
|
19
|
+
|
|
18
20
|
describe('produces the correct types', () => {
|
|
19
21
|
it('defaults when there is no topper, is normal headline, is paper background', () => {
|
|
20
22
|
const clonedBase = cloneDeep(baseCapiObject)
|
|
@@ -375,7 +377,7 @@ describe('produces correct images', () => {
|
|
|
375
377
|
const topper = new Topper(capiResponse, context)
|
|
376
378
|
const fallback = topper.fallbackImage()
|
|
377
379
|
expect(fallback?.url()).toEqual(
|
|
378
|
-
'https://
|
|
380
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fcloudfront.com%2Ftopper-standard.png?source=cp-content-pipeline&fit=scale-down&quality=highest&width=700&dpr=1'
|
|
379
381
|
)
|
|
380
382
|
})
|
|
381
383
|
it('uses the main image as fallback if no lead images', () => {
|
|
@@ -505,7 +507,7 @@ describe('headshot method', () => {
|
|
|
505
507
|
.mockResolvedValue(new Person(capiPerson, context))
|
|
506
508
|
|
|
507
509
|
expect(await topper.headshot({})).toBe(
|
|
508
|
-
'https://
|
|
510
|
+
'https://images.ft.com/v3/image/raw/https%3A%2F%2Fd1e00ek4ebabms.cloudfront.net%2Fproduction%2Fuploaded-files%2Ffthead-v1_robert-shrimsley-cc467908-15d6-474d-94d8-171594ceabb9.png?source=cp-content-pipeline&fit=scale-down&quality=highest&width=150&dpr=1'
|
|
509
511
|
)
|
|
510
512
|
})
|
|
511
513
|
})
|
package/src/model/Topper.ts
CHANGED