@vendure/dashboard 3.3.6-master-202506290242 → 3.3.6-master-202507010731
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/package.json +4 -4
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +7 -2
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +16 -0
- package/src/app/routes/_authenticated/_collections/collections.tsx +16 -2
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_collections/components/assign-collections-to-channel-dialog.tsx +110 -0
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +99 -0
- package/src/app/routes/_authenticated/_countries/countries.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +9 -5
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +8 -5
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +5 -2
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +184 -0
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +62 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +33 -3
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +14 -3
- package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +67 -36
- package/src/app/routes/_authenticated/_products/components/assign-to-channel-dialog.tsx +28 -17
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +12 -2
- package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +74 -55
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +6 -1
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +6 -2
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +9 -5
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +8 -4
- package/src/app/routes/_authenticated/_zones/zones.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -4
- package/src/lib/components/shared/detail-page-button.tsx +3 -1
- package/src/lib/components/shared/paginated-list-data-table.tsx +6 -4
- package/src/lib/framework/data-table/data-table-extensions.ts +14 -0
- package/src/lib/framework/document-extension/extend-detail-form-query.ts +50 -0
- package/src/lib/framework/document-extension/extend-document.spec.ts +884 -0
- package/src/lib/framework/document-extension/extend-document.ts +159 -0
- package/src/lib/framework/document-introspection/add-custom-fields.ts +48 -0
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +33 -2
- package/src/lib/framework/extension-api/extension-api-types.ts +21 -2
- package/src/lib/framework/form-engine/custom-form-component-extensions.ts +13 -3
- package/src/lib/framework/layout-engine/page-layout.tsx +1 -0
- package/src/lib/framework/page/detail-page-route-loader.tsx +22 -4
- package/src/lib/framework/page/use-detail-page.ts +11 -2
- package/src/lib/framework/registry/registry-types.ts +3 -0
- package/src/lib/graphql/graphql-env.d.ts +8 -6
- package/src/lib/hooks/use-extended-detail-query.ts +37 -0
- package/src/lib/hooks/use-extended-list-query.ts +73 -0
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
import { graphql } from '@/graphql/graphql.js';
|
|
2
|
+
import { print } from 'graphql';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import { extendDocument, gqlExtend } from './extend-document.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Helper to strip indentation and normalize GraphQL SDL for comparison.
|
|
9
|
+
* Allows the expected result to be indented naturally in the code.
|
|
10
|
+
*/
|
|
11
|
+
function expectedSDL(str: string): string {
|
|
12
|
+
const lines = str.split('\n');
|
|
13
|
+
// Find the minimum indentation (excluding empty lines)
|
|
14
|
+
let minIndent = Infinity;
|
|
15
|
+
for (const line of lines) {
|
|
16
|
+
if (line.trim() === '') continue;
|
|
17
|
+
const indent = line.match(/^\s*/)?.[0].length || 0;
|
|
18
|
+
minIndent = Math.min(minIndent, indent);
|
|
19
|
+
}
|
|
20
|
+
// Remove the minimum indentation from all lines and normalize
|
|
21
|
+
return lines
|
|
22
|
+
.map(line => line.slice(minIndent).trim())
|
|
23
|
+
.filter(line => line.length > 0)
|
|
24
|
+
.join('\n');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('extendDocument', () => {
|
|
28
|
+
const baseDocument = graphql(`
|
|
29
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
30
|
+
productVariants(options: $options) {
|
|
31
|
+
items {
|
|
32
|
+
id
|
|
33
|
+
name
|
|
34
|
+
sku
|
|
35
|
+
price
|
|
36
|
+
}
|
|
37
|
+
totalItems
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`);
|
|
41
|
+
|
|
42
|
+
it('should add new fields to existing query', () => {
|
|
43
|
+
const extended = extendDocument(
|
|
44
|
+
baseDocument,
|
|
45
|
+
`
|
|
46
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
47
|
+
productVariants(options: $options) {
|
|
48
|
+
items {
|
|
49
|
+
reviewRating
|
|
50
|
+
customField
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const printed = print(extended);
|
|
58
|
+
|
|
59
|
+
expect(expectedSDL(printed)).toBe(
|
|
60
|
+
expectedSDL(`
|
|
61
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
62
|
+
productVariants(options: $options) {
|
|
63
|
+
items {
|
|
64
|
+
id
|
|
65
|
+
name
|
|
66
|
+
sku
|
|
67
|
+
price
|
|
68
|
+
reviewRating
|
|
69
|
+
customField
|
|
70
|
+
}
|
|
71
|
+
totalItems
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`),
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should merge nested selection sets', () => {
|
|
79
|
+
const extended = extendDocument(
|
|
80
|
+
baseDocument,
|
|
81
|
+
`
|
|
82
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
83
|
+
productVariants(options: $options) {
|
|
84
|
+
items {
|
|
85
|
+
featuredAsset {
|
|
86
|
+
id
|
|
87
|
+
name
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
`,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const printed = print(extended);
|
|
96
|
+
|
|
97
|
+
expect(expectedSDL(printed)).toBe(
|
|
98
|
+
expectedSDL(`
|
|
99
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
100
|
+
productVariants(options: $options) {
|
|
101
|
+
items {
|
|
102
|
+
id
|
|
103
|
+
name
|
|
104
|
+
sku
|
|
105
|
+
price
|
|
106
|
+
featuredAsset {
|
|
107
|
+
id
|
|
108
|
+
name
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
totalItems
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
`),
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should handle multiple operations', () => {
|
|
119
|
+
const multiOpDocument = graphql(`
|
|
120
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
121
|
+
productVariants(options: $options) {
|
|
122
|
+
items {
|
|
123
|
+
id
|
|
124
|
+
name
|
|
125
|
+
}
|
|
126
|
+
totalItems
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
query ProductVariantDetail($id: ID!) {
|
|
131
|
+
productVariant(id: $id) {
|
|
132
|
+
id
|
|
133
|
+
name
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
`);
|
|
137
|
+
|
|
138
|
+
const extended = extendDocument(
|
|
139
|
+
multiOpDocument,
|
|
140
|
+
`
|
|
141
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
142
|
+
productVariants(options: $options) {
|
|
143
|
+
items {
|
|
144
|
+
sku
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
query ProductVariantDetail($id: ID!) {
|
|
150
|
+
productVariant(id: $id) {
|
|
151
|
+
sku
|
|
152
|
+
price
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
`,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const printed = print(extended);
|
|
159
|
+
|
|
160
|
+
expect(expectedSDL(printed)).toBe(
|
|
161
|
+
expectedSDL(`
|
|
162
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
163
|
+
productVariants(options: $options) {
|
|
164
|
+
items {
|
|
165
|
+
id
|
|
166
|
+
name
|
|
167
|
+
sku
|
|
168
|
+
}
|
|
169
|
+
totalItems
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
query ProductVariantDetail($id: ID!) {
|
|
173
|
+
productVariant(id: $id) {
|
|
174
|
+
id
|
|
175
|
+
name
|
|
176
|
+
sku
|
|
177
|
+
price
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
`),
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should preserve fragments', () => {
|
|
185
|
+
const fragmentDocument = graphql(`
|
|
186
|
+
fragment ProductVariantFields on ProductVariant {
|
|
187
|
+
id
|
|
188
|
+
name
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
192
|
+
productVariants(options: $options) {
|
|
193
|
+
items {
|
|
194
|
+
...ProductVariantFields
|
|
195
|
+
}
|
|
196
|
+
totalItems
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
`);
|
|
200
|
+
|
|
201
|
+
const extended = extendDocument(
|
|
202
|
+
fragmentDocument,
|
|
203
|
+
`
|
|
204
|
+
fragment ProductVariantFields on ProductVariant {
|
|
205
|
+
sku
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
209
|
+
productVariants(options: $options) {
|
|
210
|
+
items {
|
|
211
|
+
price
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
`,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const printed = print(extended);
|
|
219
|
+
|
|
220
|
+
expect(expectedSDL(printed)).toBe(
|
|
221
|
+
expectedSDL(`
|
|
222
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
223
|
+
productVariants(options: $options) {
|
|
224
|
+
items {
|
|
225
|
+
...ProductVariantFields
|
|
226
|
+
price
|
|
227
|
+
}
|
|
228
|
+
totalItems
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
fragment ProductVariantFields on ProductVariant {
|
|
232
|
+
id
|
|
233
|
+
name
|
|
234
|
+
}
|
|
235
|
+
fragment ProductVariantFields on ProductVariant {
|
|
236
|
+
sku
|
|
237
|
+
}
|
|
238
|
+
`),
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should work with template string interpolation', () => {
|
|
243
|
+
const fieldName = 'reviewRating';
|
|
244
|
+
const extended = extendDocument(
|
|
245
|
+
baseDocument,
|
|
246
|
+
`
|
|
247
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
248
|
+
productVariants(options: $options) {
|
|
249
|
+
items {
|
|
250
|
+
${fieldName}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
`,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const printed = print(extended);
|
|
258
|
+
|
|
259
|
+
expect(expectedSDL(printed)).toBe(
|
|
260
|
+
expectedSDL(`
|
|
261
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
262
|
+
productVariants(options: $options) {
|
|
263
|
+
items {
|
|
264
|
+
id
|
|
265
|
+
name
|
|
266
|
+
sku
|
|
267
|
+
price
|
|
268
|
+
reviewRating
|
|
269
|
+
}
|
|
270
|
+
totalItems
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
`),
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('should handle the gqlExtend utility function', () => {
|
|
278
|
+
const extender = gqlExtend`
|
|
279
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
280
|
+
productVariants(options: $options) {
|
|
281
|
+
items {
|
|
282
|
+
reviewRating
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
`;
|
|
287
|
+
|
|
288
|
+
const extended = extender(baseDocument);
|
|
289
|
+
const printed = print(extended);
|
|
290
|
+
|
|
291
|
+
expect(expectedSDL(printed)).toBe(
|
|
292
|
+
expectedSDL(`
|
|
293
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
294
|
+
productVariants(options: $options) {
|
|
295
|
+
items {
|
|
296
|
+
id
|
|
297
|
+
name
|
|
298
|
+
sku
|
|
299
|
+
price
|
|
300
|
+
reviewRating
|
|
301
|
+
}
|
|
302
|
+
totalItems
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
`),
|
|
306
|
+
);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('should not duplicate existing fields', () => {
|
|
310
|
+
const extended = extendDocument(
|
|
311
|
+
baseDocument,
|
|
312
|
+
`
|
|
313
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
314
|
+
productVariants(options: $options) {
|
|
315
|
+
items {
|
|
316
|
+
id
|
|
317
|
+
name
|
|
318
|
+
reviewRating
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
`,
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
const printed = print(extended);
|
|
326
|
+
|
|
327
|
+
expect(expectedSDL(printed)).toBe(
|
|
328
|
+
expectedSDL(`
|
|
329
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
330
|
+
productVariants(options: $options) {
|
|
331
|
+
items {
|
|
332
|
+
id
|
|
333
|
+
name
|
|
334
|
+
sku
|
|
335
|
+
price
|
|
336
|
+
reviewRating
|
|
337
|
+
}
|
|
338
|
+
totalItems
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
`),
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('should merge nested selection sets for existing fields', () => {
|
|
346
|
+
const baseWithNested = graphql(`
|
|
347
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
348
|
+
productVariants(options: $options) {
|
|
349
|
+
items {
|
|
350
|
+
id
|
|
351
|
+
featuredAsset {
|
|
352
|
+
id
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
totalItems
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
`);
|
|
359
|
+
|
|
360
|
+
const extended = extendDocument(
|
|
361
|
+
baseWithNested,
|
|
362
|
+
`
|
|
363
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
364
|
+
productVariants(options: $options) {
|
|
365
|
+
items {
|
|
366
|
+
featuredAsset {
|
|
367
|
+
name
|
|
368
|
+
preview
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
`,
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
const printed = print(extended);
|
|
377
|
+
|
|
378
|
+
expect(expectedSDL(printed)).toBe(
|
|
379
|
+
expectedSDL(`
|
|
380
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
381
|
+
productVariants(options: $options) {
|
|
382
|
+
items {
|
|
383
|
+
id
|
|
384
|
+
featuredAsset {
|
|
385
|
+
id
|
|
386
|
+
name
|
|
387
|
+
preview
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
totalItems
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
`),
|
|
394
|
+
);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('should ignore different query names and merge by top-level field', () => {
|
|
398
|
+
const extended = extendDocument(
|
|
399
|
+
baseDocument,
|
|
400
|
+
`
|
|
401
|
+
query DifferentQueryName($options: ProductVariantListOptions) {
|
|
402
|
+
productVariants(options: $options) {
|
|
403
|
+
items {
|
|
404
|
+
reviewRating
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
`,
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
const printed = print(extended);
|
|
412
|
+
|
|
413
|
+
expect(expectedSDL(printed)).toBe(
|
|
414
|
+
expectedSDL(`
|
|
415
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
416
|
+
productVariants(options: $options) {
|
|
417
|
+
items {
|
|
418
|
+
id
|
|
419
|
+
name
|
|
420
|
+
sku
|
|
421
|
+
price
|
|
422
|
+
reviewRating
|
|
423
|
+
}
|
|
424
|
+
totalItems
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
`),
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should ignore different variables and merge by top-level field', () => {
|
|
432
|
+
const extended = extendDocument(
|
|
433
|
+
baseDocument,
|
|
434
|
+
`
|
|
435
|
+
query ProductVariantList($differentOptions: ProductVariantListOptions) {
|
|
436
|
+
productVariants(options: $differentOptions) {
|
|
437
|
+
items {
|
|
438
|
+
reviewRating
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
`,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
const printed = print(extended);
|
|
446
|
+
|
|
447
|
+
expect(expectedSDL(printed)).toBe(
|
|
448
|
+
expectedSDL(`
|
|
449
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
450
|
+
productVariants(options: $options) {
|
|
451
|
+
items {
|
|
452
|
+
id
|
|
453
|
+
name
|
|
454
|
+
sku
|
|
455
|
+
price
|
|
456
|
+
reviewRating
|
|
457
|
+
}
|
|
458
|
+
totalItems
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
`),
|
|
462
|
+
);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
it('should throw error when top-level field differs', () => {
|
|
466
|
+
expect(() => {
|
|
467
|
+
extendDocument(
|
|
468
|
+
baseDocument,
|
|
469
|
+
`
|
|
470
|
+
query CompletelyDifferentQuery($id: ID!) {
|
|
471
|
+
product(id: $id) {
|
|
472
|
+
id
|
|
473
|
+
name
|
|
474
|
+
description
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
`,
|
|
478
|
+
);
|
|
479
|
+
}).toThrow("The query extension must extend the 'productVariants' query. Got 'product' instead.");
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
it('should merge anonymous query by top-level field', () => {
|
|
483
|
+
const extended = extendDocument(
|
|
484
|
+
baseDocument,
|
|
485
|
+
`
|
|
486
|
+
{
|
|
487
|
+
productVariants {
|
|
488
|
+
items {
|
|
489
|
+
reviewRating
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
`,
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
const printed = print(extended);
|
|
497
|
+
|
|
498
|
+
expect(expectedSDL(printed)).toBe(
|
|
499
|
+
expectedSDL(`
|
|
500
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
501
|
+
productVariants(options: $options) {
|
|
502
|
+
items {
|
|
503
|
+
id
|
|
504
|
+
name
|
|
505
|
+
sku
|
|
506
|
+
price
|
|
507
|
+
reviewRating
|
|
508
|
+
}
|
|
509
|
+
totalItems
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
`),
|
|
513
|
+
);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('should accept DocumentNode as extension parameter', () => {
|
|
517
|
+
const extensionDocument = graphql(`
|
|
518
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
519
|
+
productVariants(options: $options) {
|
|
520
|
+
items {
|
|
521
|
+
reviewRating
|
|
522
|
+
customField
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
`);
|
|
527
|
+
|
|
528
|
+
const extended = extendDocument(baseDocument, extensionDocument);
|
|
529
|
+
const printed = print(extended);
|
|
530
|
+
|
|
531
|
+
expect(expectedSDL(printed)).toBe(
|
|
532
|
+
expectedSDL(`
|
|
533
|
+
query ProductVariantList($options: ProductVariantListOptions) {
|
|
534
|
+
productVariants(options: $options) {
|
|
535
|
+
items {
|
|
536
|
+
id
|
|
537
|
+
name
|
|
538
|
+
sku
|
|
539
|
+
price
|
|
540
|
+
reviewRating
|
|
541
|
+
customField
|
|
542
|
+
}
|
|
543
|
+
totalItems
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
`),
|
|
547
|
+
);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('should extend detail query with fragments', () => {
|
|
551
|
+
const detailDocument = graphql(`
|
|
552
|
+
fragment ProductDetail on Product {
|
|
553
|
+
id
|
|
554
|
+
name
|
|
555
|
+
slug
|
|
556
|
+
description
|
|
557
|
+
featuredAsset {
|
|
558
|
+
id
|
|
559
|
+
preview
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
query ProductDetail($id: ID!) {
|
|
564
|
+
product(id: $id) {
|
|
565
|
+
...ProductDetail
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
`);
|
|
569
|
+
|
|
570
|
+
const extended = extendDocument(
|
|
571
|
+
detailDocument as any,
|
|
572
|
+
`
|
|
573
|
+
fragment ProductDetail on Product {
|
|
574
|
+
enabled
|
|
575
|
+
createdAt
|
|
576
|
+
updatedAt
|
|
577
|
+
assets {
|
|
578
|
+
id
|
|
579
|
+
preview
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
query ProductDetail($id: ID!) {
|
|
584
|
+
product(id: $id) {
|
|
585
|
+
customFields
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
`,
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
const printed = print(extended);
|
|
592
|
+
|
|
593
|
+
expect(expectedSDL(printed)).toBe(
|
|
594
|
+
expectedSDL(`
|
|
595
|
+
query ProductDetail($id: ID!) {
|
|
596
|
+
product(id: $id) {
|
|
597
|
+
...ProductDetail
|
|
598
|
+
customFields
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
fragment ProductDetail on Product {
|
|
602
|
+
id
|
|
603
|
+
name
|
|
604
|
+
slug
|
|
605
|
+
description
|
|
606
|
+
featuredAsset {
|
|
607
|
+
id
|
|
608
|
+
preview
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
fragment ProductDetail on Product {
|
|
612
|
+
enabled
|
|
613
|
+
createdAt
|
|
614
|
+
updatedAt
|
|
615
|
+
assets {
|
|
616
|
+
id
|
|
617
|
+
preview
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
`),
|
|
621
|
+
);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('should extend detail query with nested translations', () => {
|
|
625
|
+
const detailDocument = graphql(`
|
|
626
|
+
query ProductDetail($id: ID!) {
|
|
627
|
+
product(id: $id) {
|
|
628
|
+
id
|
|
629
|
+
name
|
|
630
|
+
slug
|
|
631
|
+
translations {
|
|
632
|
+
id
|
|
633
|
+
languageCode
|
|
634
|
+
name
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
`);
|
|
639
|
+
|
|
640
|
+
const extended = extendDocument(
|
|
641
|
+
detailDocument as any,
|
|
642
|
+
`
|
|
643
|
+
query ProductDetail($id: ID!) {
|
|
644
|
+
product(id: $id) {
|
|
645
|
+
translations {
|
|
646
|
+
slug
|
|
647
|
+
description
|
|
648
|
+
}
|
|
649
|
+
facetValues {
|
|
650
|
+
id
|
|
651
|
+
name
|
|
652
|
+
code
|
|
653
|
+
facet {
|
|
654
|
+
id
|
|
655
|
+
name
|
|
656
|
+
code
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
`,
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
const printed = print(extended);
|
|
665
|
+
|
|
666
|
+
expect(expectedSDL(printed)).toBe(
|
|
667
|
+
expectedSDL(`
|
|
668
|
+
query ProductDetail($id: ID!) {
|
|
669
|
+
product(id: $id) {
|
|
670
|
+
id
|
|
671
|
+
name
|
|
672
|
+
slug
|
|
673
|
+
translations {
|
|
674
|
+
id
|
|
675
|
+
languageCode
|
|
676
|
+
name
|
|
677
|
+
slug
|
|
678
|
+
description
|
|
679
|
+
}
|
|
680
|
+
facetValues {
|
|
681
|
+
id
|
|
682
|
+
name
|
|
683
|
+
code
|
|
684
|
+
facet {
|
|
685
|
+
id
|
|
686
|
+
name
|
|
687
|
+
code
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
`),
|
|
693
|
+
);
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
it('should extend detail query with asset fragments', () => {
|
|
697
|
+
const detailDocument = graphql(`
|
|
698
|
+
fragment Asset on Asset {
|
|
699
|
+
id
|
|
700
|
+
preview
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
query ProductDetail($id: ID!) {
|
|
704
|
+
product(id: $id) {
|
|
705
|
+
id
|
|
706
|
+
featuredAsset {
|
|
707
|
+
...Asset
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
`);
|
|
712
|
+
|
|
713
|
+
const extended = extendDocument(
|
|
714
|
+
detailDocument as any,
|
|
715
|
+
`
|
|
716
|
+
fragment Asset on Asset {
|
|
717
|
+
name
|
|
718
|
+
source
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
query ProductDetail($id: ID!) {
|
|
722
|
+
product(id: $id) {
|
|
723
|
+
assets {
|
|
724
|
+
...Asset
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
`,
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
const printed = print(extended);
|
|
732
|
+
|
|
733
|
+
expect(expectedSDL(printed)).toBe(
|
|
734
|
+
expectedSDL(`
|
|
735
|
+
query ProductDetail($id: ID!) {
|
|
736
|
+
product(id: $id) {
|
|
737
|
+
id
|
|
738
|
+
featuredAsset {
|
|
739
|
+
...Asset
|
|
740
|
+
}
|
|
741
|
+
assets {
|
|
742
|
+
...Asset
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
fragment Asset on Asset {
|
|
747
|
+
id
|
|
748
|
+
preview
|
|
749
|
+
}
|
|
750
|
+
fragment Asset on Asset {
|
|
751
|
+
name
|
|
752
|
+
source
|
|
753
|
+
}
|
|
754
|
+
`),
|
|
755
|
+
);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it('should extend detail query with custom fields', () => {
|
|
759
|
+
const detailDocument = graphql(`
|
|
760
|
+
query ProductDetail($id: ID!) {
|
|
761
|
+
product(id: $id) {
|
|
762
|
+
id
|
|
763
|
+
name
|
|
764
|
+
customFields
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
`);
|
|
768
|
+
|
|
769
|
+
const extended = extendDocument(
|
|
770
|
+
detailDocument as any,
|
|
771
|
+
`
|
|
772
|
+
query ProductDetail($id: ID!) {
|
|
773
|
+
product(id: $id) {
|
|
774
|
+
enabled
|
|
775
|
+
createdAt
|
|
776
|
+
updatedAt
|
|
777
|
+
customFields
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
`,
|
|
781
|
+
);
|
|
782
|
+
|
|
783
|
+
const printed = print(extended);
|
|
784
|
+
|
|
785
|
+
expect(expectedSDL(printed)).toBe(
|
|
786
|
+
expectedSDL(`
|
|
787
|
+
query ProductDetail($id: ID!) {
|
|
788
|
+
product(id: $id) {
|
|
789
|
+
id
|
|
790
|
+
name
|
|
791
|
+
customFields
|
|
792
|
+
enabled
|
|
793
|
+
createdAt
|
|
794
|
+
updatedAt
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
`),
|
|
798
|
+
);
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
it('should extend detail query with complex nested structure', () => {
|
|
802
|
+
const detailDocument = graphql(`
|
|
803
|
+
query ProductDetail($id: ID!) {
|
|
804
|
+
product(id: $id) {
|
|
805
|
+
id
|
|
806
|
+
name
|
|
807
|
+
featuredAsset {
|
|
808
|
+
id
|
|
809
|
+
preview
|
|
810
|
+
}
|
|
811
|
+
facetValues {
|
|
812
|
+
id
|
|
813
|
+
name
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
`);
|
|
818
|
+
|
|
819
|
+
const extended = extendDocument(
|
|
820
|
+
detailDocument as any,
|
|
821
|
+
`
|
|
822
|
+
query ProductDetail($id: ID!) {
|
|
823
|
+
product(id: $id) {
|
|
824
|
+
featuredAsset {
|
|
825
|
+
name
|
|
826
|
+
source
|
|
827
|
+
}
|
|
828
|
+
facetValues {
|
|
829
|
+
code
|
|
830
|
+
facet {
|
|
831
|
+
id
|
|
832
|
+
name
|
|
833
|
+
code
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
translations {
|
|
837
|
+
id
|
|
838
|
+
languageCode
|
|
839
|
+
name
|
|
840
|
+
slug
|
|
841
|
+
description
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
`,
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
const printed = print(extended);
|
|
849
|
+
|
|
850
|
+
expect(expectedSDL(printed)).toBe(
|
|
851
|
+
expectedSDL(`
|
|
852
|
+
query ProductDetail($id: ID!) {
|
|
853
|
+
product(id: $id) {
|
|
854
|
+
id
|
|
855
|
+
name
|
|
856
|
+
featuredAsset {
|
|
857
|
+
id
|
|
858
|
+
preview
|
|
859
|
+
name
|
|
860
|
+
source
|
|
861
|
+
}
|
|
862
|
+
facetValues {
|
|
863
|
+
id
|
|
864
|
+
name
|
|
865
|
+
code
|
|
866
|
+
facet {
|
|
867
|
+
id
|
|
868
|
+
name
|
|
869
|
+
code
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
translations {
|
|
873
|
+
id
|
|
874
|
+
languageCode
|
|
875
|
+
name
|
|
876
|
+
slug
|
|
877
|
+
description
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
`),
|
|
882
|
+
);
|
|
883
|
+
});
|
|
884
|
+
});
|