@designcrowd/library.brand-page 6.2.5 → 6.2.6
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/lib/src/{CreatedOnBrandCrowd-de-de-CkJM0rEy.js → CreatedOnBrandCrowd-de-de-DpeSEnwP.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-CKOotMQK.js → CreatedOnBrandCrowd-en-us-CxYv3NzT.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-mrDI8AaY.js → CreatedOnBrandCrowd-es-es-CzQ1HRHw.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-DtmVXezM.js → CreatedOnBrandCrowd-fr-ca-J77YZaT1.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-DtmVXezM.js → CreatedOnBrandCrowd-fr-fr-J77YZaT1.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-C8Cy74df.js → CreatedOnBrandCrowd-pt-br-1vh4Smqt.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-C8Cy74df.js → CreatedOnBrandCrowd-pt-pt-1vh4Smqt.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-FVl5OqQM.js → CreatedOnDcom-de-de-CXX6W_29.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-e0s7gZGG.js → CreatedOnDcom-en-us-D78BmX6f.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-BXMekiTg.js → CreatedOnDcom-es-es-FfbPM2vD.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-74Vm0wzS.js → CreatedOnDcom-fr-ca-C6L60rxJ.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-C6TT73Rw.js → CreatedOnDcom-fr-fr-BEDnW9w-.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-Drg2eaLk.js → CreatedOnDcom-pt-br-CZXVvc1n.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-BgsEIMfv.js → CreatedOnDcom-pt-pt-IQq744nb.js} +1 -1
- package/lib/src/brand-page/utils/logo.util.js +2 -2
- package/lib/src/brand-page/utils/migration/migration-07.js +3 -2
- package/lib/src/brand-page/utils/migration/migration-08.js +3 -2
- package/lib/src/clients/fabric-render-client.d.ts +20 -0
- package/lib/src/clients/fabric-render-client.js +43 -0
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib--ZDYWLFf.js → lib-CyVd3FMn.js} +3399 -3361
- package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +1 -1
- package/package.json +1 -1
- package/src/brand-page/utils/logo.util.recalculate.test.ts +204 -0
- package/src/brand-page/utils/logo.util.ts +2 -2
- package/src/brand-page/utils/migration/migration-07.dimension.test.ts +274 -0
- package/src/brand-page/utils/migration/migration-07.ts +3 -2
- package/src/brand-page/utils/migration/migration-08.test.ts +181 -22
- package/src/brand-page/utils/migration/migration-08.ts +3 -2
- package/src/clients/fabric-render-client.test.ts +198 -0
- package/src/clients/fabric-render-client.ts +85 -0
|
@@ -8,8 +8,102 @@ import { FabricRenderClient } from '../../../clients/fabric-render-client';
|
|
|
8
8
|
const mockFabricClientInstance = {
|
|
9
9
|
getLogoSvgUrlByLogoImageAsync: vi.fn(),
|
|
10
10
|
getLogoSvgUrlByLogoTemplateImageAsync: vi.fn(),
|
|
11
|
+
getLogoDimensionsByLogoImageAsync: vi.fn(),
|
|
12
|
+
getLogoDimensionsByLogoTemplateImageAsync: vi.fn(),
|
|
11
13
|
};
|
|
12
14
|
|
|
15
|
+
const expectNoDrawingRequest = () => {
|
|
16
|
+
expect(
|
|
17
|
+
mockFabricClientInstance.getLogoSvgUrlByLogoImageAsync,
|
|
18
|
+
).not.toHaveBeenCalled();
|
|
19
|
+
expect(
|
|
20
|
+
mockFabricClientInstance.getLogoSvgUrlByLogoTemplateImageAsync,
|
|
21
|
+
).not.toHaveBeenCalled();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type Size = { width?: number; height?: number } | undefined;
|
|
25
|
+
|
|
26
|
+
// The drawing and size-only lookups answer alike, so these pins hold before and after the switch (R3).
|
|
27
|
+
const answerBoth = (
|
|
28
|
+
template: (token: string) => Size,
|
|
29
|
+
draft: (token: string) => Size,
|
|
30
|
+
) => {
|
|
31
|
+
const withData = (size: Size) =>
|
|
32
|
+
size && { data: 'data:image/svg+xml;base64,', ...size };
|
|
33
|
+
|
|
34
|
+
mockFabricClientInstance.getLogoDimensionsByLogoTemplateImageAsync.mockImplementation(
|
|
35
|
+
async ({ logoTemplateToken }) => template(logoTemplateToken),
|
|
36
|
+
);
|
|
37
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync.mockImplementation(
|
|
38
|
+
async ({ logoDraftToken }) => draft(logoDraftToken),
|
|
39
|
+
);
|
|
40
|
+
mockFabricClientInstance.getLogoSvgUrlByLogoTemplateImageAsync.mockImplementation(
|
|
41
|
+
async ({ logoTemplateToken }) => withData(template(logoTemplateToken)),
|
|
42
|
+
);
|
|
43
|
+
mockFabricClientInstance.getLogoSvgUrlByLogoImageAsync.mockImplementation(
|
|
44
|
+
async ({ logoDraftToken }) => withData(draft(logoDraftToken)),
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const sizeFor = (token: string): Size =>
|
|
49
|
+
token.endsWith('-wide')
|
|
50
|
+
? { width: 300, height: 100 }
|
|
51
|
+
: { width: 100, height: 300 };
|
|
52
|
+
|
|
53
|
+
// Two pages of logo contents: a template on the first, a draft on the second.
|
|
54
|
+
const createTwoPageData = (brandPageType: string) =>
|
|
55
|
+
createTestBrandPageData({
|
|
56
|
+
brandPageType,
|
|
57
|
+
pages: [
|
|
58
|
+
{
|
|
59
|
+
title: 'Home',
|
|
60
|
+
slug: 'home',
|
|
61
|
+
contents: [
|
|
62
|
+
{
|
|
63
|
+
id: '1',
|
|
64
|
+
type: 'logo',
|
|
65
|
+
logoTemplateImage: {
|
|
66
|
+
logoTemplateToken: 'template-wide',
|
|
67
|
+
logoTemplateText: 'Acme',
|
|
68
|
+
logoTemplateVersion: 3,
|
|
69
|
+
},
|
|
70
|
+
logoImageWidth: '12rem',
|
|
71
|
+
logoImageHeight: '9rem',
|
|
72
|
+
isLogoVisible: true,
|
|
73
|
+
backgroundStyle: {},
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'About',
|
|
79
|
+
slug: 'about',
|
|
80
|
+
contents: [
|
|
81
|
+
{
|
|
82
|
+
id: '2',
|
|
83
|
+
type: 'logo',
|
|
84
|
+
logoImage: { logoDraftToken: 'draft-tall', logoVariation: 1 },
|
|
85
|
+
logoImageWidth: '9rem',
|
|
86
|
+
logoImageHeight: '10rem',
|
|
87
|
+
isLogoVisible: true,
|
|
88
|
+
backgroundStyle: {},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const logoSizes = (result: MigrationData) =>
|
|
96
|
+
result.brandPageModel.pages.map((page) => {
|
|
97
|
+
const logo = page.contents[0] as LogoContent;
|
|
98
|
+
|
|
99
|
+
return [logo.logoImageWidth, logo.logoImageHeight];
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const ORIGINAL_SIZES = [
|
|
103
|
+
['12rem', '9rem'],
|
|
104
|
+
['9rem', '10rem'],
|
|
105
|
+
];
|
|
106
|
+
|
|
13
107
|
// Mock FabricRenderClient
|
|
14
108
|
vi.mock('../../../clients/fabric-render-client', () => ({
|
|
15
109
|
FabricRenderClient: {
|
|
@@ -101,11 +195,12 @@ describe('migration08', () => {
|
|
|
101
195
|
const migrationData = createMigrationData(brandPageData);
|
|
102
196
|
|
|
103
197
|
// Mock the fabric client response
|
|
104
|
-
mockFabricClientInstance.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
198
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync.mockResolvedValue(
|
|
199
|
+
{
|
|
200
|
+
width: 120,
|
|
201
|
+
height: 80,
|
|
202
|
+
},
|
|
203
|
+
);
|
|
109
204
|
|
|
110
205
|
const result = await migration08(migrationData, {
|
|
111
206
|
isServerRender: false,
|
|
@@ -114,11 +209,12 @@ describe('migration08', () => {
|
|
|
114
209
|
|
|
115
210
|
expect(result.useOldLogoRenderSize).toBe(false);
|
|
116
211
|
expect(
|
|
117
|
-
mockFabricClientInstance.
|
|
212
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync,
|
|
118
213
|
).toHaveBeenCalledWith({
|
|
119
214
|
logoDraftToken: 'test-token',
|
|
120
215
|
logoVariation: 0,
|
|
121
216
|
});
|
|
217
|
+
expectNoDrawingRequest();
|
|
122
218
|
});
|
|
123
219
|
|
|
124
220
|
test('should skip brandSite type (brandSite does not have logo content)', async () => {
|
|
@@ -170,11 +266,12 @@ describe('migration08', () => {
|
|
|
170
266
|
|
|
171
267
|
// Fabric client should not have been called
|
|
172
268
|
expect(
|
|
173
|
-
mockFabricClientInstance.
|
|
269
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync,
|
|
174
270
|
).not.toHaveBeenCalled();
|
|
175
271
|
expect(
|
|
176
|
-
mockFabricClientInstance.
|
|
272
|
+
mockFabricClientInstance.getLogoDimensionsByLogoTemplateImageAsync,
|
|
177
273
|
).not.toHaveBeenCalled();
|
|
274
|
+
expectNoDrawingRequest();
|
|
178
275
|
});
|
|
179
276
|
|
|
180
277
|
test('should handle brandContact type with logo content', async () => {
|
|
@@ -206,6 +303,13 @@ describe('migration08', () => {
|
|
|
206
303
|
});
|
|
207
304
|
|
|
208
305
|
expect(result.useOldLogoRenderSize).toBe(false);
|
|
306
|
+
expect(
|
|
307
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync,
|
|
308
|
+
).toHaveBeenCalledWith({
|
|
309
|
+
logoDraftToken: 'test-token',
|
|
310
|
+
logoVariation: 0,
|
|
311
|
+
});
|
|
312
|
+
expectNoDrawingRequest();
|
|
209
313
|
});
|
|
210
314
|
|
|
211
315
|
test('should handle multiple pages with logo content', async () => {
|
|
@@ -249,13 +353,12 @@ describe('migration08', () => {
|
|
|
249
353
|
// Mock the fabric client response
|
|
250
354
|
const mockFabricClient = FabricRenderClient.getInstance();
|
|
251
355
|
|
|
252
|
-
vi.mocked(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
);
|
|
356
|
+
vi.mocked(
|
|
357
|
+
mockFabricClient.getLogoDimensionsByLogoImageAsync,
|
|
358
|
+
).mockResolvedValue({
|
|
359
|
+
width: 120,
|
|
360
|
+
height: 80,
|
|
361
|
+
});
|
|
259
362
|
|
|
260
363
|
const result = await migration08(migrationData, {
|
|
261
364
|
isServerRender: false,
|
|
@@ -264,8 +367,9 @@ describe('migration08', () => {
|
|
|
264
367
|
|
|
265
368
|
expect(result.useOldLogoRenderSize).toBe(false);
|
|
266
369
|
expect(
|
|
267
|
-
mockFabricClient.
|
|
370
|
+
mockFabricClient.getLogoDimensionsByLogoImageAsync,
|
|
268
371
|
).toHaveBeenCalledTimes(2);
|
|
372
|
+
expectNoDrawingRequest();
|
|
269
373
|
});
|
|
270
374
|
|
|
271
375
|
test('should handle logo content without logo tokens', async () => {
|
|
@@ -305,6 +409,13 @@ describe('migration08', () => {
|
|
|
305
409
|
(result.brandPageModel.pages[0].contents[0] as LogoContent)
|
|
306
410
|
.logoImageWidth,
|
|
307
411
|
).toBe('15rem');
|
|
412
|
+
expect(
|
|
413
|
+
mockFabricClientInstance.getLogoDimensionsByLogoImageAsync,
|
|
414
|
+
).not.toHaveBeenCalled();
|
|
415
|
+
expect(
|
|
416
|
+
mockFabricClientInstance.getLogoDimensionsByLogoTemplateImageAsync,
|
|
417
|
+
).not.toHaveBeenCalled();
|
|
418
|
+
expectNoDrawingRequest();
|
|
308
419
|
});
|
|
309
420
|
|
|
310
421
|
test('should handle logo template images', async () => {
|
|
@@ -334,11 +445,10 @@ describe('migration08', () => {
|
|
|
334
445
|
const mockFabricClient = FabricRenderClient.getInstance();
|
|
335
446
|
|
|
336
447
|
vi.mocked(
|
|
337
|
-
mockFabricClient.
|
|
448
|
+
mockFabricClient.getLogoDimensionsByLogoTemplateImageAsync,
|
|
338
449
|
).mockResolvedValue({
|
|
339
450
|
width: 200,
|
|
340
451
|
height: 100,
|
|
341
|
-
data: 'test-template-svg-data',
|
|
342
452
|
});
|
|
343
453
|
|
|
344
454
|
const _result = await migration08(migrationData, {
|
|
@@ -347,10 +457,11 @@ describe('migration08', () => {
|
|
|
347
457
|
});
|
|
348
458
|
|
|
349
459
|
expect(
|
|
350
|
-
mockFabricClient.
|
|
460
|
+
mockFabricClient.getLogoDimensionsByLogoTemplateImageAsync,
|
|
351
461
|
).toHaveBeenCalledWith({
|
|
352
462
|
logoTemplateToken: 'template-token',
|
|
353
463
|
});
|
|
464
|
+
expectNoDrawingRequest();
|
|
354
465
|
});
|
|
355
466
|
|
|
356
467
|
test('should handle error gracefully', async () => {
|
|
@@ -379,9 +490,9 @@ describe('migration08', () => {
|
|
|
379
490
|
// Mock the fabric client to throw an error
|
|
380
491
|
const mockFabricClient = FabricRenderClient.getInstance();
|
|
381
492
|
|
|
382
|
-
vi.mocked(
|
|
383
|
-
|
|
384
|
-
);
|
|
493
|
+
vi.mocked(
|
|
494
|
+
mockFabricClient.getLogoDimensionsByLogoImageAsync,
|
|
495
|
+
).mockRejectedValue(new Error('API Error'));
|
|
385
496
|
|
|
386
497
|
const result = await migration08(migrationData, {
|
|
387
498
|
isServerRender: false,
|
|
@@ -423,4 +534,52 @@ describe('migration08', () => {
|
|
|
423
534
|
expect(result.useOldLogoRenderSize).toBe(false);
|
|
424
535
|
expect(result.brandPageModel.pages[0].contents.length).toBe(2);
|
|
425
536
|
});
|
|
537
|
+
|
|
538
|
+
test.each([BRAND_PAGE_TYPES.default, BRAND_PAGE_TYPES.brandContact])(
|
|
539
|
+
'same sizes: pins each %s logo content from the reply',
|
|
540
|
+
async (brandPageType) => {
|
|
541
|
+
answerBoth(sizeFor, sizeFor);
|
|
542
|
+
|
|
543
|
+
const result = await migration08(
|
|
544
|
+
createMigrationData(createTwoPageData(brandPageType)),
|
|
545
|
+
{ isServerRender: false, isUserDraft: false },
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
expect(result.useOldLogoRenderSize).toBe(false);
|
|
549
|
+
expect(logoSizes(result)).toEqual([
|
|
550
|
+
['4rem', '4rem'],
|
|
551
|
+
['10rem', '10rem'],
|
|
552
|
+
]);
|
|
553
|
+
},
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
test('not OK: an empty reply leaves every size unchanged', async () => {
|
|
557
|
+
answerBoth(
|
|
558
|
+
() => undefined,
|
|
559
|
+
() => undefined,
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
const result = await migration08(
|
|
563
|
+
createMigrationData(createTwoPageData(BRAND_PAGE_TYPES.default)),
|
|
564
|
+
{ isServerRender: false, isUserDraft: false },
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
expect(result.useOldLogoRenderSize).toBe(false);
|
|
568
|
+
expect(logoSizes(result)).toEqual(ORIGINAL_SIZES);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
test('missing size: a zero or absent dimension leaves every size unchanged', async () => {
|
|
572
|
+
answerBoth(
|
|
573
|
+
() => ({ width: 0, height: 100 }),
|
|
574
|
+
() => ({ width: 120 }),
|
|
575
|
+
);
|
|
576
|
+
|
|
577
|
+
const result = await migration08(
|
|
578
|
+
createMigrationData(createTwoPageData(BRAND_PAGE_TYPES.default)),
|
|
579
|
+
{ isServerRender: false, isUserDraft: false },
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
expect(result.useOldLogoRenderSize).toBe(false);
|
|
583
|
+
expect(logoSizes(result)).toEqual(ORIGINAL_SIZES);
|
|
584
|
+
});
|
|
426
585
|
});
|
|
@@ -45,10 +45,11 @@ export const migration08 = async (
|
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
// Size-only lookups, by recorded exception: 0031-released-logo-size-migrations-may-use-a-size-only-address.md
|
|
48
49
|
const logoDataPromises = logoContents.map(async ({ content }) => {
|
|
49
50
|
if (content.logoTemplateImage?.logoTemplateToken) {
|
|
50
51
|
const logoData =
|
|
51
|
-
await fabricClient.
|
|
52
|
+
await fabricClient.getLogoDimensionsByLogoTemplateImageAsync(
|
|
52
53
|
content.logoTemplateImage,
|
|
53
54
|
);
|
|
54
55
|
|
|
@@ -56,7 +57,7 @@ export const migration08 = async (
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
if (content.logoImage?.logoDraftToken) {
|
|
59
|
-
const logoData = await fabricClient.
|
|
60
|
+
const logoData = await fabricClient.getLogoDimensionsByLogoImageAsync({
|
|
60
61
|
logoDraftToken: content.logoImage.logoDraftToken,
|
|
61
62
|
logoVariation: content.logoImage.logoVariation,
|
|
62
63
|
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { FabricRenderClient } from './fabric-render-client';
|
|
3
|
+
|
|
4
|
+
const BASE_URL = 'https://fabric.test';
|
|
5
|
+
|
|
6
|
+
const TEMPLATE_IMAGE = {
|
|
7
|
+
logoTemplateToken: 'template-token',
|
|
8
|
+
logoTemplateText: 'A & B',
|
|
9
|
+
logoTemplateVersion: 3,
|
|
10
|
+
layout: 'stacked',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const LOGO_IMAGE = {
|
|
14
|
+
logoDraftToken: 'draft-token',
|
|
15
|
+
logoVariation: 2,
|
|
16
|
+
logoLastUpdate: '99',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const jsonReply = (body: unknown, status = 200) =>
|
|
20
|
+
new Response(JSON.stringify(body), {
|
|
21
|
+
status,
|
|
22
|
+
headers: { 'Content-Type': 'application/json' },
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// A size request goes to the drawing address plus `/dimensions`, with the drawing's query minus outputFormat.
|
|
26
|
+
const expectSizeRequestFor = (requested: unknown, drawingUrl: string) => {
|
|
27
|
+
const size = new URL(String(requested));
|
|
28
|
+
const drawing = new URL(drawingUrl);
|
|
29
|
+
|
|
30
|
+
drawing.searchParams.delete('outputFormat');
|
|
31
|
+
|
|
32
|
+
expect(`${size.origin}${size.pathname}`).toBe(
|
|
33
|
+
`${drawing.origin}${drawing.pathname}/dimensions`,
|
|
34
|
+
);
|
|
35
|
+
expect([...size.searchParams]).toEqual([...drawing.searchParams]);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const createClient = (): FabricRenderClient => {
|
|
39
|
+
FabricRenderClient.overrideInstance(undefined);
|
|
40
|
+
FabricRenderClient.setInstance({ baseUrl: BASE_URL });
|
|
41
|
+
|
|
42
|
+
return FabricRenderClient.getInstance();
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe('FabricRenderClient logo lookups', () => {
|
|
46
|
+
let client: FabricRenderClient;
|
|
47
|
+
let fetchMock: ReturnType<typeof vi.fn>;
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
client = createClient();
|
|
51
|
+
fetchMock = vi.fn();
|
|
52
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
vi.unstubAllGlobals();
|
|
57
|
+
FabricRenderClient.overrideInstance(undefined);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('drawing requests unchanged', () => {
|
|
61
|
+
test('the template drawing still fetches base64svgjson and returns data, width and height', async () => {
|
|
62
|
+
fetchMock.mockResolvedValue(
|
|
63
|
+
jsonReply({ data: 'data:svg', width: 300, height: 100 }),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const result =
|
|
67
|
+
await client.getLogoSvgUrlByLogoTemplateImageAsync(TEMPLATE_IMAGE);
|
|
68
|
+
|
|
69
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
70
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
71
|
+
`${BASE_URL}/asset/logotemplate/brand-page/template-token?dimensionsType=preview_image_transparent_no_buffer&outputFormat=base64svgjson&logoTemplateVersion=3&text=A%20%26%20B&layout=stacked`,
|
|
72
|
+
);
|
|
73
|
+
expect(result).toEqual({ data: 'data:svg', width: 300, height: 100 });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('the draft drawing still fetches base64svgjson and returns data, width and height', async () => {
|
|
77
|
+
fetchMock.mockResolvedValue(
|
|
78
|
+
jsonReply({ data: 'data:svg', width: 100, height: 300 }),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const result = await client.getLogoSvgUrlByLogoImageAsync(LOGO_IMAGE);
|
|
82
|
+
|
|
83
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
84
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
85
|
+
`${BASE_URL}/asset/logodraft/brand-page/draft-token?v=99&outputFormat=base64svgjson&dimensionsType=preview_image_transparent_no_buffer&variation=icontransparentbackgroundonly`,
|
|
86
|
+
);
|
|
87
|
+
expect(result).toEqual({ data: 'data:svg', width: 100, height: 300 });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('template size request: asks the /dimensions companion and returns only width and height', async () => {
|
|
92
|
+
fetchMock.mockResolvedValue(jsonReply({ width: 300, height: 100 }));
|
|
93
|
+
|
|
94
|
+
const result =
|
|
95
|
+
await client.getLogoDimensionsByLogoTemplateImageAsync(TEMPLATE_IMAGE);
|
|
96
|
+
|
|
97
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
98
|
+
expect(String(fetchMock.mock.calls[0][0])).toMatch(
|
|
99
|
+
`${BASE_URL}/asset/logotemplate/brand-page/template-token/dimensions?`,
|
|
100
|
+
);
|
|
101
|
+
expectSizeRequestFor(
|
|
102
|
+
fetchMock.mock.calls[0][0],
|
|
103
|
+
client.getLogoTemplateUrlByLogoTemplateImage(
|
|
104
|
+
TEMPLATE_IMAGE,
|
|
105
|
+
'base64svgjson',
|
|
106
|
+
),
|
|
107
|
+
);
|
|
108
|
+
expect(result).toStrictEqual({ width: 300, height: 100 });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('draft size request: asks the /dimensions companion and returns only width and height', async () => {
|
|
112
|
+
fetchMock.mockResolvedValue(jsonReply({ width: 100, height: 300 }));
|
|
113
|
+
|
|
114
|
+
const result = await client.getLogoDimensionsByLogoImageAsync(LOGO_IMAGE);
|
|
115
|
+
|
|
116
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
117
|
+
expect(String(fetchMock.mock.calls[0][0])).toMatch(
|
|
118
|
+
`${BASE_URL}/asset/logodraft/brand-page/draft-token/dimensions?`,
|
|
119
|
+
);
|
|
120
|
+
expectSizeRequestFor(
|
|
121
|
+
fetchMock.mock.calls[0][0],
|
|
122
|
+
client.getLogoVariationUrlByLogoImage(LOGO_IMAGE, 'base64svgjson') ?? '',
|
|
123
|
+
);
|
|
124
|
+
expect(result).toStrictEqual({ width: 100, height: 300 });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('not deployed: a 404 from the companion answers undefined after one request, never the drawing', async () => {
|
|
128
|
+
fetchMock.mockImplementation(async () => jsonReply({}, 404));
|
|
129
|
+
|
|
130
|
+
await expect(
|
|
131
|
+
client.getLogoDimensionsByLogoTemplateImageAsync(TEMPLATE_IMAGE),
|
|
132
|
+
).resolves.toBeUndefined();
|
|
133
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
134
|
+
|
|
135
|
+
await expect(
|
|
136
|
+
client.getLogoDimensionsByLogoImageAsync(LOGO_IMAGE),
|
|
137
|
+
).resolves.toBeUndefined();
|
|
138
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
139
|
+
expect(
|
|
140
|
+
fetchMock.mock.calls.every(
|
|
141
|
+
([url]) =>
|
|
142
|
+
new URL(String(url)).pathname.endsWith('/dimensions') &&
|
|
143
|
+
!String(url).includes('outputFormat'),
|
|
144
|
+
),
|
|
145
|
+
).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('no logo reference', () => {
|
|
149
|
+
test('an empty draft token answers undefined without a request', async () => {
|
|
150
|
+
await expect(
|
|
151
|
+
client.getLogoDimensionsByLogoImageAsync({
|
|
152
|
+
logoDraftToken: '',
|
|
153
|
+
logoVariation: 0,
|
|
154
|
+
}),
|
|
155
|
+
).resolves.toBeUndefined();
|
|
156
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('an undefined logo image throws a TypeError, as its drawing twin does', async () => {
|
|
160
|
+
const missing = undefined as unknown as typeof LOGO_IMAGE;
|
|
161
|
+
|
|
162
|
+
await expect(
|
|
163
|
+
client.getLogoDimensionsByLogoImageAsync(missing),
|
|
164
|
+
).rejects.toBeInstanceOf(TypeError);
|
|
165
|
+
await expect(
|
|
166
|
+
client.getLogoSvgUrlByLogoImageAsync(missing),
|
|
167
|
+
).rejects.toBeInstanceOf(TypeError);
|
|
168
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('unreadable reply: a 200 PNG rejects after one request, with no fallback to the drawing', async () => {
|
|
173
|
+
fetchMock.mockImplementation(
|
|
174
|
+
async () =>
|
|
175
|
+
new Response(new Uint8Array([0x89, 0x50, 0x4e, 0x47]), {
|
|
176
|
+
status: 200,
|
|
177
|
+
headers: { 'Content-Type': 'image/png' },
|
|
178
|
+
}),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
await expect(
|
|
182
|
+
client.getLogoDimensionsByLogoTemplateImageAsync(TEMPLATE_IMAGE),
|
|
183
|
+
).rejects.toThrow();
|
|
184
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
185
|
+
|
|
186
|
+
await expect(
|
|
187
|
+
client.getLogoDimensionsByLogoImageAsync(LOGO_IMAGE),
|
|
188
|
+
).rejects.toThrow();
|
|
189
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
190
|
+
expect(
|
|
191
|
+
fetchMock.mock.calls.every(
|
|
192
|
+
([url]) =>
|
|
193
|
+
new URL(String(url)).pathname.endsWith('/dimensions') &&
|
|
194
|
+
!String(url).includes('outputFormat'),
|
|
195
|
+
),
|
|
196
|
+
).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -317,4 +317,89 @@ export class FabricRenderClient {
|
|
|
317
317
|
|
|
318
318
|
return { data, width, height };
|
|
319
319
|
}
|
|
320
|
+
|
|
321
|
+
// Released migrations 07/08 call the two size methods: 0031-released-logo-size-migrations-may-use-a-size-only-address.md
|
|
322
|
+
async getLogoDimensionsByLogoTemplateImageAsync(logoTemplateImage: {
|
|
323
|
+
logoTemplateToken: string;
|
|
324
|
+
logoTemplateText: string;
|
|
325
|
+
logoTemplateVersion: number;
|
|
326
|
+
layout?: string;
|
|
327
|
+
}): Promise<{ width: number; height: number } | undefined> {
|
|
328
|
+
return this.fetchLogoDimensionsAsync(
|
|
329
|
+
this.getLogoTemplateDimensionsUrl(logoTemplateImage),
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async getLogoDimensionsByLogoImageAsync(logoImage: {
|
|
334
|
+
logoDraftToken: string;
|
|
335
|
+
logoVariation: number;
|
|
336
|
+
logoLastUpdate?: string;
|
|
337
|
+
}): Promise<{ width: number; height: number } | undefined> {
|
|
338
|
+
return this.fetchLogoDimensionsAsync(
|
|
339
|
+
this.getLogoDraftDimensionsUrl(logoImage),
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Each brand-page address has a size-only companion at `/dimensions`, which reads only what these two builders send.
|
|
344
|
+
// extract if this grows: this repeats getLogoTemplateUrlByLogoTemplateImage's query.
|
|
345
|
+
private getLogoTemplateDimensionsUrl(logoTemplateImage: {
|
|
346
|
+
logoTemplateToken: string;
|
|
347
|
+
logoTemplateText: string;
|
|
348
|
+
logoTemplateVersion: number;
|
|
349
|
+
layout?: string;
|
|
350
|
+
}): string {
|
|
351
|
+
const url = `${this.baseUrl}/asset/logotemplate/brand-page/${logoTemplateImage.logoTemplateToken}/dimensions?dimensionsType=preview_image_transparent_no_buffer&logoTemplateVersion=${logoTemplateImage.logoTemplateVersion}&text=${encodeURIComponent(logoTemplateImage.logoTemplateText)}`;
|
|
352
|
+
|
|
353
|
+
return logoTemplateImage.layout
|
|
354
|
+
? `${url}&layout=${logoTemplateImage.layout}`
|
|
355
|
+
: url;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
private getLogoDraftDimensionsUrl(logoImage: {
|
|
359
|
+
logoDraftToken: string;
|
|
360
|
+
logoVariation: number;
|
|
361
|
+
logoLastUpdate?: string;
|
|
362
|
+
}): string | undefined {
|
|
363
|
+
if (!logoImage.logoDraftToken) {
|
|
364
|
+
console.warn('getLogoDraftDimensionsUrl: invalid logo draft token');
|
|
365
|
+
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const definition =
|
|
370
|
+
LogoVariationDefinitions[
|
|
371
|
+
typeof logoImage.logoVariation === 'number'
|
|
372
|
+
? logoImage.logoVariation
|
|
373
|
+
: 0
|
|
374
|
+
];
|
|
375
|
+
|
|
376
|
+
if (!definition) {
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const variationQuery = Object.entries(definition)
|
|
381
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
382
|
+
.join('&');
|
|
383
|
+
|
|
384
|
+
return `${this.baseUrl}/asset/logodraft/brand-page/${logoImage.logoDraftToken}/dimensions?v=${logoImage.logoLastUpdate || ''}&${variationQuery}`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// extract if this grows: the four logo JSON fetches repeat this shape.
|
|
388
|
+
private async fetchLogoDimensionsAsync(
|
|
389
|
+
url: string | undefined,
|
|
390
|
+
): Promise<{ width: number; height: number } | undefined> {
|
|
391
|
+
if (!url) {
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const response = await fetch(url);
|
|
396
|
+
|
|
397
|
+
if (response.status !== 200) {
|
|
398
|
+
return undefined;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const { width, height } = await response.json();
|
|
402
|
+
|
|
403
|
+
return { width, height };
|
|
404
|
+
}
|
|
320
405
|
}
|