@contrail/flexplm 1.4.0 → 1.5.0-alpha.14a4f1b

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 (112) hide show
  1. package/lib/cli/commands/compile.d.ts +4 -0
  2. package/lib/cli/commands/compile.js +73 -0
  3. package/lib/cli/commands/compile.spec.d.ts +1 -0
  4. package/lib/cli/commands/compile.spec.js +80 -0
  5. package/lib/cli/commands/create.d.ts +5 -0
  6. package/lib/cli/commands/create.js +77 -0
  7. package/lib/cli/commands/create.spec.d.ts +1 -0
  8. package/lib/cli/commands/create.spec.js +78 -0
  9. package/lib/cli/commands/upload.d.ts +17 -0
  10. package/lib/cli/commands/upload.js +228 -0
  11. package/lib/cli/commands/upload.spec.d.ts +1 -0
  12. package/lib/cli/commands/upload.spec.js +88 -0
  13. package/lib/cli/index.d.ts +5 -0
  14. package/lib/cli/index.js +70 -0
  15. package/lib/cli/index.spec.d.ts +1 -0
  16. package/lib/cli/index.spec.js +85 -0
  17. package/lib/cli/template/mapping-template.ts.template +62 -0
  18. package/lib/entity-processor/base-entity-processor.d.ts +65 -0
  19. package/lib/entity-processor/base-entity-processor.js +71 -0
  20. package/lib/entity-processor/base-entity-processor.spec.js +1 -0
  21. package/lib/index.d.ts +1 -0
  22. package/lib/index.js +1 -0
  23. package/lib/interfaces/mapping-file.d.ts +460 -0
  24. package/lib/interfaces/mapping-file.js +2 -0
  25. package/lib/publish/base-process-publish-assortment.d.ts +25 -0
  26. package/lib/publish/base-process-publish-assortment.js +60 -6
  27. package/lib/publish/base-process-publish-assortment.spec.js +22 -4
  28. package/lib/publish/mockData.js +5 -0
  29. package/lib/transform/identifier-conversion-spec-mockData.js +34 -6
  30. package/lib/transform/identifier-conversion.d.ts +36 -0
  31. package/lib/transform/identifier-conversion.js +37 -1
  32. package/lib/transform/identifier-conversion.spec.js +35 -0
  33. package/lib/util/config-defaults.d.ts +18 -0
  34. package/lib/util/config-defaults.js +25 -15
  35. package/lib/util/config-defaults.spec.js +56 -0
  36. package/lib/util/data-converter-spec-mockData.js +17 -3
  37. package/lib/util/data-converter.d.ts +102 -0
  38. package/lib/util/data-converter.js +195 -34
  39. package/lib/util/data-converter.spec.js +430 -0
  40. package/lib/util/error-response-object.d.ts +5 -0
  41. package/lib/util/error-response-object.js +7 -0
  42. package/lib/util/event-short-message-status.js +1 -0
  43. package/lib/util/federation.js +8 -0
  44. package/lib/util/flexplm-connect.d.ts +7 -0
  45. package/lib/util/flexplm-connect.js +14 -0
  46. package/lib/util/logger-config.js +1 -0
  47. package/lib/util/map-util-spec-mockData.js +17 -3
  48. package/lib/util/map-utils.d.ts +27 -0
  49. package/lib/util/map-utils.js +27 -0
  50. package/lib/util/thumbnail-util.d.ts +21 -0
  51. package/lib/util/thumbnail-util.js +28 -1
  52. package/lib/util/thumbnail-util.spec.js +6 -0
  53. package/lib/util/type-conversion-utils-spec-mockData.js +3 -3
  54. package/lib/util/type-conversion-utils.d.ts +151 -0
  55. package/lib/util/type-conversion-utils.js +154 -0
  56. package/lib/util/type-defaults.d.ts +69 -0
  57. package/lib/util/type-defaults.js +98 -4
  58. package/lib/util/type-defaults.spec.js +114 -4
  59. package/lib/util/type-utils.d.ts +21 -0
  60. package/lib/util/type-utils.js +23 -0
  61. package/lib/util/type-utils.spec.js +2 -0
  62. package/package.json +21 -6
  63. package/scripts/copy-template.js +10 -0
  64. package/.github/pull_request_template.md +0 -31
  65. package/.github/workflows/flexplm-lib.yml +0 -27
  66. package/.github/workflows/publish-to-npm.yml +0 -121
  67. package/CHANGELOG.md +0 -40
  68. package/publish.bat +0 -5
  69. package/publish.sh +0 -5
  70. package/src/entity-processor/base-entity-processor.spec.ts +0 -689
  71. package/src/entity-processor/base-entity-processor.ts +0 -583
  72. package/src/flexplm-request.ts +0 -28
  73. package/src/flexplm-utils.spec.ts +0 -27
  74. package/src/flexplm-utils.ts +0 -29
  75. package/src/index.ts +0 -22
  76. package/src/interfaces/interfaces.ts +0 -122
  77. package/src/interfaces/item-family-changes.ts +0 -67
  78. package/src/interfaces/publish-change-data.ts +0 -43
  79. package/src/publish/base-process-publish-assortment-callback.ts +0 -50
  80. package/src/publish/base-process-publish-assortment.spec.ts +0 -1992
  81. package/src/publish/base-process-publish-assortment.ts +0 -1134
  82. package/src/publish/mockData.ts +0 -4561
  83. package/src/transform/identifier-conversion-spec-mockData.ts +0 -496
  84. package/src/transform/identifier-conversion.spec.ts +0 -354
  85. package/src/transform/identifier-conversion.ts +0 -282
  86. package/src/util/config-defaults.spec.ts +0 -392
  87. package/src/util/config-defaults.ts +0 -97
  88. package/src/util/data-converter-spec-mockData.ts +0 -231
  89. package/src/util/data-converter.spec.ts +0 -1120
  90. package/src/util/data-converter.ts +0 -766
  91. package/src/util/error-response-object.spec.ts +0 -116
  92. package/src/util/error-response-object.ts +0 -50
  93. package/src/util/event-short-message-status.ts +0 -22
  94. package/src/util/federation.ts +0 -172
  95. package/src/util/flexplm-connect.spec.ts +0 -132
  96. package/src/util/flexplm-connect.ts +0 -208
  97. package/src/util/logger-config.ts +0 -20
  98. package/src/util/map-util-spec-mockData.ts +0 -231
  99. package/src/util/map-utils.spec.ts +0 -103
  100. package/src/util/map-utils.ts +0 -41
  101. package/src/util/mockData.ts +0 -101
  102. package/src/util/thumbnail-util.spec.ts +0 -508
  103. package/src/util/thumbnail-util.ts +0 -272
  104. package/src/util/type-conversion-utils-spec-mockData.ts +0 -272
  105. package/src/util/type-conversion-utils.spec.ts +0 -1031
  106. package/src/util/type-conversion-utils.ts +0 -490
  107. package/src/util/type-defaults.spec.ts +0 -669
  108. package/src/util/type-defaults.ts +0 -281
  109. package/src/util/type-utils.spec.ts +0 -227
  110. package/src/util/type-utils.ts +0 -144
  111. package/tsconfig.json +0 -24
  112. package/tslint.json +0 -57
@@ -1,508 +0,0 @@
1
- import { FCConfig } from '../interfaces/interfaces';
2
- import { ThumbnailUtil } from './thumbnail-util';
3
-
4
- import { empty_custom_sizes, four_custom_sizes, thumbnail_content_entity } from './mockData';
5
-
6
- const mockEntitiesGet = jest.fn();
7
- const mockEntitiesUpdate = jest.fn();
8
- const mockEntitiesDelete = jest.fn();
9
- const mockContentCreate = jest.fn();
10
-
11
- jest.mock('@contrail/sdk', () => {
12
- return {
13
- Entities: jest.fn().mockImplementation(() => ({
14
- get: mockEntitiesGet,
15
- update: mockEntitiesUpdate,
16
- delete: mockEntitiesDelete,
17
- })),
18
- Content: jest.fn().mockImplementation(() => ({
19
- create: mockContentCreate,
20
- })),
21
- };
22
- });
23
-
24
- const mockGetRequest = jest.fn();
25
- jest.mock('./flexplm-connect', () => {
26
- return {
27
- FlexPLMConnect: jest.fn().mockImplementation(() => ({
28
- getRequest: mockGetRequest,
29
- })),
30
- };
31
- });
32
-
33
- describe('ThumbnailUtil Tests', () =>{
34
- const config = {} as FCConfig;
35
- describe('setOutboundThumbnail()', () =>{
36
- const tu = new ThumbnailUtil(config);
37
- beforeEach(() =>{
38
- jest.clearAllMocks();
39
- });
40
-
41
- it('no data', async () =>{
42
- const data = {};
43
- const event = {};
44
- const results = await tu.setOutboundThumbnail(data, event);
45
- const keys = Object.keys(results);
46
-
47
- expect(results).toEqual(data);
48
- expect(keys.length).toEqual(0);
49
- });
50
-
51
- it('remove thumbnail', async () =>{
52
- const data = {};
53
- const event = {
54
- propertyDiffs: {
55
- largeViewableDownloadUrl: {
56
- oldValue: '123',
57
- newValue: null
58
- }
59
- }
60
- };
61
- const results = await tu.setOutboundThumbnail(data, event);
62
- const keys = Object.keys(results);
63
-
64
- expect(keys.length).toEqual(1);
65
- expect(keys[0]).toEqual(ThumbnailUtil.NEW_THUMBNAIL_ID);
66
- expect(results[ThumbnailUtil.NEW_THUMBNAIL_ID]).toEqual(ThumbnailUtil.REMOVE_THUMBNAIL);
67
-
68
- });
69
-
70
- it('calling getFileId - new thumbnail', async () =>{
71
- const data = {};
72
- const newDownloadUrl = 'https://api.vibeiq.com/dev/api/files/downloadUrl/w3ckfeGAD8ViOZj-%2Fcontent:E1iBQuWbr74lcdcw%2F9e30ds9o-d34b-451e-ae59-b4km36018d5a.png';
73
- const oldDownloadUrl = 'xxx';
74
- const thumbnailId = 'Eey3ZOiqdrUA84F8';
75
- const event = {
76
- newData: {
77
- primaryViewableId: 'm5bJa4RtTLUtKBP5',
78
- largeViewableDownloadUrl: newDownloadUrl
79
- },
80
- propertyDiffs: {
81
- largeViewableDownloadUrl :{
82
- newValue: newDownloadUrl,
83
- oldValue: oldDownloadUrl
84
- }
85
- }
86
- };
87
-
88
- const spyCustomSizes = jest.spyOn(tu, 'getCustomSizes');
89
- spyCustomSizes.mockReturnValue(Promise.resolve(empty_custom_sizes));
90
- const spyGetFileId = jest.spyOn(tu, 'getFileId');
91
- spyGetFileId.mockReturnValue(Promise.resolve(thumbnailId));
92
- const results = await tu.setOutboundThumbnail(data, event);
93
- const keys = Object.keys(results);
94
- expect(keys.length).toEqual(1);
95
- expect(keys[0]).toEqual(ThumbnailUtil.NEW_THUMBNAIL_ID);
96
- const thumbnailValue = results[ThumbnailUtil.NEW_THUMBNAIL_ID];
97
- expect(thumbnailValue).toEqual(thumbnailId);
98
- });
99
-
100
- it('calling getFileId - existing thumbnail', async () =>{
101
- const data = {};
102
- const newDownloadUrl = 'https://api.vibeiq.com/dev/api/files/downloadUrl/w3ckfeGAD8ViOZj-%2Fcontent:E1iBQuWbr74lcdcw%2F9e30ds9o-d34b-451e-ae59-b4km36018d5a.png';
103
- const thumbnailId = 'Eey3ZOiqdrUA84F8';
104
- const event = {
105
- newData: {
106
- primaryViewableId: 'm5bJa4RtTLUtKBP5',
107
- largeViewableDownloadUrl: newDownloadUrl
108
- },
109
- propertyDiffs: {}
110
- };
111
-
112
- const spyCustomSizes = jest.spyOn(tu, 'getCustomSizes');
113
- spyCustomSizes.mockReturnValue(Promise.resolve(empty_custom_sizes));
114
- const spyGetFileId = jest.spyOn(tu, 'getFileId');
115
- spyGetFileId.mockReturnValue(Promise.resolve(thumbnailId));
116
- const results = await tu.setOutboundThumbnail(data, event);
117
- const keys = Object.keys(results);
118
- expect(keys.length).toEqual(1);
119
- expect(keys[0]).toEqual(ThumbnailUtil.EXISTING_THUMBNAIL_ID);
120
- const thumbnailValue = results[ThumbnailUtil.EXISTING_THUMBNAIL_ID];
121
- expect(thumbnailValue).toEqual(thumbnailId);
122
- });
123
- });
124
-
125
- describe('getFileId', () =>{
126
- const primaryFileId = 'yn2d5oHD4rXHRzyB';
127
- beforeEach(() =>{
128
- jest.clearAllMocks();
129
- });
130
- it('no custom sizes, default max_thumbnail_size - result large', async () =>{
131
- const tu = new ThumbnailUtil(config);
132
- const spyCustomSizes = jest.spyOn(tu, 'getCustomSizes');
133
- spyCustomSizes.mockReturnValue(Promise.resolve(empty_custom_sizes));
134
- const spyContentEntity = jest.spyOn(tu, 'getContentEntity');
135
- const content = JSON.parse(JSON.stringify(thumbnail_content_entity));
136
-
137
- spyContentEntity.mockReturnValue(Promise.resolve(content));
138
-
139
- const results = await tu.getFileId(primaryFileId);
140
- expect(results).toEqual('vo4N4mCd-tFrw101');
141
- });
142
-
143
- it('no custom sizes, 750 * 1_024 max_thumbnail_size - result medium', async () =>{
144
- const config1 = {
145
- max_thumbnail_size: 750 * 1_024
146
- } as any as FCConfig;
147
- const tu = new ThumbnailUtil(config1);
148
- const spyCustomSizes = jest.spyOn(tu, 'getCustomSizes');
149
- spyCustomSizes.mockReturnValue(Promise.resolve(empty_custom_sizes));
150
- const spyContentEntity = jest.spyOn(tu, 'getContentEntity');
151
- const content = thumbnail_content_entity;
152
- spyContentEntity.mockReturnValue(Promise.resolve(content));
153
-
154
- const results = await tu.getFileId(primaryFileId);
155
- expect(results).toEqual('AsRvJenpeqxksUNW');
156
- });
157
-
158
- it('custom sizes, 750 * 1_024 max_thumbnail_size - result CS_500Id', async () =>{
159
- const config1 = {
160
- max_thumbnail_size: 750 * 1_024
161
- } as any as FCConfig;
162
- const tu = new ThumbnailUtil(config1);
163
- const spyCustomSizes = jest.spyOn(tu, 'getCustomSizes');
164
- spyCustomSizes.mockReturnValue(Promise.resolve(four_custom_sizes));
165
- const spyContentEntity = jest.spyOn(tu, 'getContentEntity');
166
- const content = thumbnail_content_entity;
167
- spyContentEntity.mockReturnValue(Promise.resolve(content));
168
-
169
- const results = await tu.getFileId(primaryFileId);
170
- expect(results).toEqual('rBaHc1J2xdOWdbhI');
171
- });
172
-
173
- });
174
-
175
- describe('Test isThumbnailNew', () =>{
176
- const tu = new ThumbnailUtil(config);
177
- it('no propertyDiffs', () =>{
178
- const event = {
179
- newData: {
180
- name: 'Test'
181
- },
182
- oldData:{
183
- name: 'Test'
184
- }
185
- };
186
- const results = tu.isThumbnailNew(event, undefined);
187
- expect(results).toBeFalsy();
188
- });
189
-
190
- it('empty propertyDiffs', () =>{
191
- const event = {
192
- newData: {
193
- name: 'Test'
194
- },
195
- oldData:{
196
- name: 'Test'
197
- },
198
- propertyDiffs: {}
199
- };
200
- const results = tu.isThumbnailNew(event, undefined);
201
- expect(results).toBeFalsy();
202
- });
203
-
204
- it('propertyDiffs diff property', () =>{
205
- const event = {
206
- newData: {
207
- name: 'Test1'
208
- },
209
- oldData:{
210
- name: 'Test'
211
- },
212
- propertyDiffs: {
213
- name: {
214
- propertyName: 'name',
215
- oldValue: 'Test',
216
- newValue: 'Test1'
217
- }
218
- }
219
- };
220
- const results = tu.isThumbnailNew(event, undefined);
221
- expect(results).toBeFalsy();
222
- });
223
-
224
- it('propertyDiffs OOB property', () =>{
225
- const event = {
226
- newData: {
227
- name: 'Test1'
228
- },
229
- oldData:{
230
- name: 'Test'
231
- },
232
- propertyDiffs: {
233
- mediumLargeViewableDownloadUrl: {
234
- propertyName: 'mediumLargeViewableDownloadUrl',
235
- oldValue: '',
236
- newValue: 'Test1'
237
- }
238
- }
239
- };
240
- const results = tu.isThumbnailNew(event, undefined);
241
- expect(results).toBeTruthy();
242
- });
243
-
244
- it('propertyDiffs custom property', () =>{
245
- const event = {
246
- newData: {
247
- name: 'Test1'
248
- },
249
- oldData:{
250
- name: 'Test'
251
- },
252
- propertyDiffs: {
253
- RL_1000Url: {
254
- propertyName: 'RL_1000Url',
255
- oldValue: '',
256
- newValue: 'Test1'
257
- }
258
- }
259
- };
260
- const results = tu.isThumbnailNew(event, [{slug: 'RL_1000'}]);
261
- expect(results).toBeTruthy();
262
- });
263
- });
264
-
265
- describe('logContentResults', () =>{
266
- it('no content - doesnt error', () =>{
267
- const tu = new ThumbnailUtil(config);
268
- const content = undefined;
269
- const relations = [];
270
- tu.logContentResults(content, relations);
271
- });
272
- it('no relations - doesnt error', () =>{
273
- const tu = new ThumbnailUtil(config);
274
- const content = undefined;
275
- const relations = undefined;
276
- tu.logContentResults(content, relations);
277
- });
278
-
279
- it('content and relations - logs', () =>{
280
- const tu = new ThumbnailUtil(config);
281
- const content = {
282
- id: '123',
283
- name: 'Test',
284
- primaryFile: { id:'file123'}
285
- };
286
- const relations = ['primaryFile'];
287
- tu.logContentResults(content, relations);
288
-
289
- expect(Object.keys(content)).toHaveLength(3);
290
- expect(content).toHaveProperty('primaryFile');
291
- expect(content.primaryFile).toHaveProperty('id');
292
- expect(content.primaryFile.id).toEqual('file123');
293
- });
294
-
295
- });
296
-
297
- describe('syncThumbnailToVibeIQ', () => {
298
- let tu: ThumbnailUtil;
299
-
300
- beforeEach(() => {
301
- jest.clearAllMocks();
302
- tu = new ThumbnailUtil(config);
303
- mockEntitiesGet.mockImplementation((opts) => {
304
- if (opts.entityName === 'content-custom-size') return Promise.resolve([]);
305
- return Promise.resolve({});
306
- });
307
- mockEntitiesUpdate.mockImplementation((opts) => Promise.resolve({ id: opts.id }));
308
- mockEntitiesDelete.mockImplementation((opts) => Promise.resolve({ id: opts.id }));
309
- });
310
-
311
- it('does not update when no thumbnail IDs in event data', async () => {
312
- const event = { data: {} };
313
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'color' });
314
-
315
- expect(mockEntitiesUpdate).not.toHaveBeenCalled();
316
- expect(mockEntitiesDelete).not.toHaveBeenCalled();
317
- expect(mockContentCreate).not.toHaveBeenCalled();
318
- });
319
-
320
- it('does not update when event.data is undefined', async () => {
321
- const event = {};
322
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'color' });
323
-
324
- expect(mockEntitiesUpdate).not.toHaveBeenCalled();
325
- expect(mockEntitiesDelete).not.toHaveBeenCalled();
326
- });
327
-
328
- it('REMOVE_THUMBNAIL with existing primaryViewableId deletes content and updates entity', async () => {
329
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: ThumbnailUtil.REMOVE_THUMBNAIL } };
330
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', primaryViewableId: 'pv1', event, entityName: 'color' });
331
-
332
- expect(mockEntitiesDelete).toHaveBeenCalledWith({ entityName: 'content', id: 'pv1' });
333
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(expect.objectContaining({ entityName: 'color', id: 'entity1' }));
334
- });
335
-
336
- it('REMOVE_THUMBNAIL with no primaryViewableId updates entity without deleting', async () => {
337
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: ThumbnailUtil.REMOVE_THUMBNAIL } };
338
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'item' });
339
-
340
- expect(mockEntitiesDelete).not.toHaveBeenCalled();
341
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(expect.objectContaining({ entityName: 'item', id: 'entity1' }));
342
- });
343
-
344
- it('creates new content when no primaryViewableId exists and updates entity', async () => {
345
- const mockResponse = {
346
- arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(8)),
347
- headers: { get: jest.fn().mockReturnValue('image/png') },
348
- };
349
- mockGetRequest.mockResolvedValue(mockResponse);
350
-
351
- const createdContent = {
352
- id: 'newContent1',
353
- contentType: 'image/png',
354
- fileName: 'thumb.png',
355
- primaryFileUrl: 'https://files/primary.png',
356
- largeViewableUrl: 'https://files/large.png',
357
- mediumLargeViewableUrl: null,
358
- mediumViewableUrl: null,
359
- smallViewableUrl: null,
360
- tinyViewableUrl: null,
361
- };
362
- mockContentCreate.mockResolvedValue(createdContent);
363
-
364
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: '/rest/thumbnail/thumb.png' } };
365
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'color' });
366
-
367
- expect(mockGetRequest).toHaveBeenCalledWith({ urlPath: '/rest/thumbnail/thumb.png', includeUrlContext: false, returnFullResponse: true });
368
- expect(mockContentCreate).toHaveBeenCalledWith(
369
- expect.objectContaining({
370
- fileName: 'thumb.png',
371
- contentType: 'image/png',
372
- contentHolderReference: 'color:entity1',
373
- }),
374
- );
375
- // Updates content with flexplmThumbnailUrl
376
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(
377
- expect.objectContaining({
378
- entityName: 'content',
379
- id: 'newContent1',
380
- object: { flexplmThumbnailUrl: '/rest/thumbnail/thumb.png' },
381
- }),
382
- );
383
- // Updates the main entity
384
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(
385
- expect.objectContaining({
386
- entityName: 'color',
387
- id: 'entity1',
388
- }),
389
- );
390
- });
391
-
392
- it('encodes URL path segments with special characters', async () => {
393
- const mockResponse = {
394
- arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(8)),
395
- headers: { get: jest.fn().mockReturnValue('image/png') },
396
- };
397
- mockGetRequest.mockResolvedValue(mockResponse);
398
- mockContentCreate.mockResolvedValue({
399
- id: 'c1', contentType: 'image/png', fileName: 'my image.png',
400
- primaryFileUrl: 'https://files/primary.png', largeViewableUrl: null,
401
- mediumLargeViewableUrl: null, mediumViewableUrl: null, smallViewableUrl: null, tinyViewableUrl: null,
402
- });
403
-
404
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: '/rest/thumbnail/my image.png' } };
405
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'color' });
406
-
407
- expect(mockGetRequest).toHaveBeenCalledWith({
408
- urlPath: '/rest/thumbnail/my%20image.png',
409
- includeUrlContext: false,
410
- returnFullResponse: true,
411
- });
412
- expect(mockContentCreate).toHaveBeenCalledWith(
413
- expect.objectContaining({ fileName: 'my image.png' }),
414
- );
415
- });
416
-
417
- it('encodes URL path segments with unicode characters', async () => {
418
- const mockResponse = {
419
- arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(8)),
420
- headers: { get: jest.fn().mockReturnValue('image/jpeg') },
421
- };
422
- mockGetRequest.mockResolvedValue(mockResponse);
423
- mockContentCreate.mockResolvedValue({
424
- id: 'c2', contentType: 'image/jpeg', fileName: 'café-logo.jpg',
425
- primaryFileUrl: 'https://files/primary.jpg', largeViewableUrl: null,
426
- mediumLargeViewableUrl: null, mediumViewableUrl: null, smallViewableUrl: null, tinyViewableUrl: null,
427
- });
428
-
429
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: '/rest/thumbnail/café-logo.jpg' } };
430
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', event, entityName: 'item' });
431
-
432
- expect(mockGetRequest).toHaveBeenCalledWith({
433
- urlPath: '/rest/thumbnail/caf%C3%A9-logo.jpg',
434
- includeUrlContext: false,
435
- returnFullResponse: true,
436
- });
437
- expect(mockContentCreate).toHaveBeenCalledWith(
438
- expect.objectContaining({ fileName: 'café-logo.jpg' }),
439
- );
440
- });
441
-
442
- it('replaces content when primaryViewable.flexplmThumbnailUrl differs and updates entity', async () => {
443
- mockEntitiesGet.mockImplementation((opts) => {
444
- if (opts.entityName === 'content-custom-size') return Promise.resolve([]);
445
- if (opts.entityName === 'content' && opts.id === 'oldPv') {
446
- return Promise.resolve({ id: 'oldPv', flexplmThumbnailUrl: '/rest/thumbnail/old.png' });
447
- }
448
- return Promise.resolve({});
449
- });
450
-
451
- const mockResponse = {
452
- arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(8)),
453
- headers: { get: jest.fn().mockReturnValue('image/jpeg') },
454
- };
455
- mockGetRequest.mockResolvedValue(mockResponse);
456
-
457
- const createdContent = {
458
- id: 'newContent2',
459
- contentType: 'image/jpeg',
460
- fileName: 'new.jpg',
461
- primaryFileUrl: 'https://files/new-primary.jpg',
462
- largeViewableUrl: null,
463
- mediumLargeViewableUrl: null,
464
- mediumViewableUrl: null,
465
- smallViewableUrl: null,
466
- tinyViewableUrl: null,
467
- };
468
- mockContentCreate.mockResolvedValue(createdContent);
469
-
470
- const event = { data: { [ThumbnailUtil.NEW_THUMBNAIL_ID]: '/rest/thumbnail/new.jpg' } };
471
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', primaryViewableId: 'oldPv', event, entityName: 'item' });
472
-
473
- // Creates new content
474
- expect(mockContentCreate).toHaveBeenCalled();
475
- // Updates new content with flexplmThumbnailUrl
476
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(
477
- expect.objectContaining({
478
- entityName: 'content',
479
- id: 'newContent2',
480
- object: { flexplmThumbnailUrl: '/rest/thumbnail/new.jpg' },
481
- }),
482
- );
483
- // Updates the main entity
484
- expect(mockEntitiesUpdate).toHaveBeenCalledWith(
485
- expect.objectContaining({ entityName: 'item', id: 'entity1' }),
486
- );
487
- // Deletes old content
488
- expect(mockEntitiesDelete).toHaveBeenCalledWith({ entityName: 'content', id: 'oldPv' });
489
- });
490
-
491
- it('does not update when primaryViewable.flexplmThumbnailUrl matches', async () => {
492
- const thumbnailUrl = '/rest/thumbnail/same.png';
493
- mockEntitiesGet.mockImplementation((opts) => {
494
- if (opts.entityName === 'content-custom-size') return Promise.resolve([]);
495
- if (opts.entityName === 'content' && opts.id === 'pv1') {
496
- return Promise.resolve({ id: 'pv1', flexplmThumbnailUrl: thumbnailUrl });
497
- }
498
- return Promise.resolve({});
499
- });
500
-
501
- const event = { data: { [ThumbnailUtil.EXISTING_THUMBNAIL_ID]: thumbnailUrl } };
502
- await tu.syncThumbnailToVibeIQ({ entityId: 'entity1', primaryViewableId: 'pv1', event, entityName: 'color' });
503
- expect(mockContentCreate).not.toHaveBeenCalled();
504
- expect(mockEntitiesUpdate).not.toHaveBeenCalled();
505
- expect(mockEntitiesDelete).not.toHaveBeenCalled();
506
- });
507
- });
508
- });