directus

Форк
0
/
transformations.test.ts 
316 строк · 8.0 Кб
1
import type { File } from '@directus/types';
2
import { describe, expect, test } from 'vitest';
3
import type { Transformation, TransformationParams } from '../types/assets.js';
4
import { maybeExtractFormat, resolvePreset } from './transformations.js';
5

6
const inputFile = {
7
	id: '43a15f67-84a7-4e07-880d-e46a9f33c542',
8
	storage: 'local',
9
	filename_disk: 'test',
10
	filename_download: 'test',
11
	title: null,
12
	type: null,
13
	folder: null,
14
	uploaded_by: null,
15
	uploaded_on: '2023-12-19T16:12:53.149Z',
16
	charset: null,
17
	filesize: 123,
18
	width: 1920,
19
	height: 1080,
20
	duration: null,
21
	embed: null,
22
	description: null,
23
	location: null,
24
	tags: null,
25
	metadata: null,
26
	modified_by: null,
27
	modified_on: '',
28
	focal_point_x: null,
29
	focal_point_y: null,
30
} satisfies File;
31

32
describe('resolvePreset', () => {
33
	test('Prevent input mutation #18301', () => {
34
		const transformationParams: TransformationParams = {
35
			key: 'system-small-cover',
36
			format: 'jpg',
37
			transforms: [
38
				[
39
					'resize',
40
					{
41
						width: 64,
42
						height: 64,
43
						fit: 'cover',
44
					},
45
				],
46
			],
47
		};
48

49
		resolvePreset({ transformationParams }, inputFile);
50

51
		expect(transformationParams.transforms).toStrictEqual([
52
			[
53
				'resize',
54
				{
55
					width: 64,
56
					height: 64,
57
					fit: 'cover',
58
				},
59
			],
60
		]);
61
	});
62

63
	test('Add toFormat transformation', () => {
64
		const transformationParams: TransformationParams = {
65
			key: 'system-small-cover',
66
			format: 'jpg',
67
			quality: 80,
68
			transforms: [
69
				[
70
					'resize',
71
					{
72
						width: 64,
73
						height: 64,
74
						fit: 'cover',
75
					},
76
				],
77
			],
78
		};
79

80
		const output = resolvePreset({ transformationParams }, inputFile);
81

82
		expect(output).toStrictEqual([
83
			[
84
				'resize',
85
				{
86
					width: 64,
87
					height: 64,
88
					fit: 'cover',
89
				},
90
			],
91
			['toFormat', 'jpg', { quality: 80 }],
92
		]);
93
	});
94

95
	test('Add resize transformation: cover without focal point', () => {
96
		const transformationParams: TransformationParams = {
97
			key: 'system-small-cover',
98
			width: 64,
99
			height: 64,
100
			fit: 'cover',
101
		};
102

103
		const output = resolvePreset({ transformationParams }, inputFile);
104

105
		expect(output).toStrictEqual([
106
			[
107
				'resize',
108
				{
109
					width: 64,
110
					height: 64,
111
					fit: 'cover',
112
					withoutEnlargement: undefined,
113
				},
114
			],
115
		]);
116
	});
117

118
	test('Add resize transformation: cover with centered focal point', () => {
119
		const transformationParams: TransformationParams = {
120
			key: 'system-small-cover',
121
			width: 64,
122
			height: 64,
123
			fit: 'cover',
124
		};
125

126
		const output = resolvePreset(
127
			{ transformationParams },
128
			{ ...inputFile, focal_point_x: inputFile.width / 2, focal_point_y: inputFile.height / 2 },
129
		);
130

131
		/*
132
		 * The following is relevant for a centered focal point
133
		 * The initial aspect ratio is 16:9 so we have to resize the image to an intermediate size
134
		 * that fully covers our desired 1:1 aspect ratio and then crop out the final dimensions
135
		 * This results in: 1080/64 == 16.875   -->   1920/16.875 == 113.77 (round up) == 114 width
136
		 * Next we need the inner padding to get the centered crop: (114 - 64) / 2 == 25
137
		 * That results in the following
138
		 * <──────────114───────────>
139
		 * <──25──><───64───><──25──>
140
		 * ┌──────┬──────────┬──────┐
141
		 * │      │          │      │
142
		 * │      │ extract  │      │
143
		 * │      │ centered │      │
144
		 * │      │          │      │
145
		 * └──────┴──────────┴──────┘
146
		 */
147
		expect(output).toStrictEqual([
148
			[
149
				'resize',
150
				{
151
					width: 114,
152
					height: 64,
153
					fit: 'cover',
154
					withoutEnlargement: undefined,
155
				},
156
			],
157
			['extract', { left: 25, top: 0, width: 64, height: 64 }],
158
		]);
159
	});
160

161
	test('Add resize transformation: cover with negative focal point', () => {
162
		const transformationParams: TransformationParams = {
163
			key: 'system-small-cover',
164
			width: 64,
165
			height: 64,
166
			fit: 'cover',
167
		};
168

169
		const output = resolvePreset({ transformationParams }, { ...inputFile, focal_point_x: -999, focal_point_y: -999 });
170

171
		/*
172
		 * That should result in the following
173
		 * <──────────114────────────>
174
		 * <─────64──────><────50────>
175
		 * ┌─────────────┬───────────┐
176
		 * │             │           │
177
		 * │   extract   │           │
178
		 * │             │           │
179
		 * └─────────────┴───────────┘
180
		 */
181
		expect(output).toStrictEqual([
182
			[
183
				'resize',
184
				{
185
					width: 114,
186
					height: 64,
187
					fit: 'cover',
188
					withoutEnlargement: undefined,
189
				},
190
			],
191
			['extract', { left: 0, top: 0, width: 64, height: 64 }],
192
		]);
193
	});
194

195
	test('Add resize transformation: cover with out of bounds focal point', () => {
196
		const transformationParams: TransformationParams = {
197
			key: 'system-small-cover',
198
			width: 64,
199
			height: 64,
200
			fit: 'cover',
201
		};
202

203
		const output = resolvePreset({ transformationParams }, { ...inputFile, focal_point_x: 9999, focal_point_y: -999 });
204

205
		/*
206
		 * That should result in the following
207
		 * <──────────114────────────>
208
		 * <────50────><─────64──────>
209
		 * ┌───────────┬─────────────┐
210
		 * │           │             │
211
		 * │           │   extract   │
212
		 * │           │             │
213
		 * └───────────┴─────────────┘
214
		 */
215
		expect(output).toStrictEqual([
216
			[
217
				'resize',
218
				{
219
					width: 114,
220
					height: 64,
221
					fit: 'cover',
222
					withoutEnlargement: undefined,
223
				},
224
			],
225
			['extract', { left: 50, top: 0, width: 64, height: 64 }],
226
		]);
227
	});
228

229
	test('Add resize transformation: contain', () => {
230
		const transformationParams: TransformationParams = {
231
			key: 'system-small-cover',
232
			width: 64,
233
			height: 64,
234
			fit: 'contain',
235
		};
236

237
		const output = resolvePreset({ transformationParams }, inputFile);
238

239
		expect(output).toStrictEqual([
240
			[
241
				'resize',
242
				{
243
					width: 64,
244
					height: 64,
245
					fit: 'contain',
246
					withoutEnlargement: undefined,
247
				},
248
			],
249
		]);
250
	});
251

252
	test('Resolve auto format (fallback)', () => {
253
		const transformationParams: TransformationParams = {
254
			format: 'auto',
255
		};
256

257
		const output = resolvePreset({ transformationParams }, inputFile);
258

259
		expect(output).toStrictEqual([['toFormat', 'jpg', { quality: undefined }]]);
260
	});
261

262
	test('Resolve auto format (with accept header)', () => {
263
		const transformationParams: TransformationParams = {
264
			format: 'auto',
265
		};
266

267
		const output = resolvePreset({ transformationParams, acceptFormat: 'avif' }, inputFile);
268

269
		expect(output).toStrictEqual([['toFormat', 'avif', { quality: undefined }]]);
270
	});
271

272
	test('Resolve auto format (format with transparency support)', () => {
273
		const transformationParams: TransformationParams = {
274
			format: 'auto',
275
		};
276

277
		const inputFileAvif = { ...inputFile, type: 'image/avif' };
278

279
		const output = resolvePreset({ transformationParams }, inputFileAvif);
280

281
		expect(output).toStrictEqual([['toFormat', 'png', { quality: undefined }]]);
282
	});
283

284
	test('Resolve auto format (original type)', () => {
285
		const transformationParams: TransformationParams = {
286
			format: 'auto',
287
		};
288

289
		const inputFilePng = { ...inputFile, type: 'image/png' };
290

291
		const output = resolvePreset({ transformationParams }, inputFilePng);
292

293
		expect(output).toStrictEqual([['toFormat', 'png', { quality: undefined }]]);
294
	});
295
});
296

297
describe('maybeExtractFormat', () => {
298
	test('get last format', () => {
299
		const inputTransformations: Transformation[] = [
300
			['toFormat', 'jpg', { quality: 80 }],
301
			['toFormat', 'webp', { quality: 80 }],
302
		];
303

304
		const output = maybeExtractFormat(inputTransformations);
305

306
		expect(output).toBe('webp');
307
	});
308

309
	test('get undefined', () => {
310
		const inputTransformations: Transformation[] = [];
311

312
		const output = maybeExtractFormat(inputTransformations);
313

314
		expect(output).toBe(undefined);
315
	});
316
});
317

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.