@shopify/ui-extensions-tester 0.0.1-alpha.0 → 2026.4.0-rc.3
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/README.md +64 -14
- package/admin.esnext +1 -0
- package/admin.js +1 -0
- package/admin.mjs +1 -0
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +15 -0
- package/build/cjs/admin/factories.js +323 -0
- package/build/cjs/admin/index.js +70 -0
- package/build/cjs/api-version.js +22 -0
- package/build/cjs/checkout/factories.js +412 -0
- package/build/cjs/checkout/index.js +162 -0
- package/build/cjs/customer-account/factories.js +235 -0
- package/build/cjs/customer-account/index.js +89 -0
- package/build/cjs/fetch-polyfills.js +193 -0
- package/build/cjs/index.js +467 -0
- package/build/cjs/mocks/i18n.js +21 -0
- package/build/cjs/mocks/money.js +16 -0
- package/build/cjs/mocks/signals.js +34 -0
- package/build/cjs/mocks/target-apis.js +37 -0
- package/build/cjs/navigation.js +56 -0
- package/build/cjs/point-of-sale/factories.js +510 -0
- package/build/cjs/point-of-sale/index.js +85 -0
- package/build/cjs/targets.js +36 -0
- package/build/esm/_virtual/_rollupPluginBabelHelpers.mjs +10 -0
- package/build/esm/admin/factories.mjs +318 -0
- package/build/esm/admin/index.mjs +65 -0
- package/build/esm/api-version.mjs +18 -0
- package/build/esm/checkout/factories.mjs +408 -0
- package/build/esm/checkout/index.mjs +153 -0
- package/build/esm/customer-account/factories.mjs +231 -0
- package/build/esm/customer-account/index.mjs +83 -0
- package/build/esm/fetch-polyfills.mjs +188 -0
- package/build/esm/index.mjs +440 -0
- package/build/esm/mocks/i18n.mjs +17 -0
- package/build/esm/mocks/money.mjs +12 -0
- package/build/esm/mocks/signals.mjs +29 -0
- package/build/esm/mocks/target-apis.mjs +33 -0
- package/build/esm/navigation.mjs +51 -0
- package/build/esm/point-of-sale/factories.mjs +506 -0
- package/build/esm/point-of-sale/index.mjs +79 -0
- package/build/esm/targets.mjs +29 -0
- package/build/esnext/_virtual/_rollupPluginBabelHelpers.esnext +10 -0
- package/build/esnext/admin/factories.esnext +318 -0
- package/build/esnext/admin/index.esnext +65 -0
- package/build/esnext/api-version.esnext +18 -0
- package/build/esnext/checkout/factories.esnext +408 -0
- package/build/esnext/checkout/index.esnext +153 -0
- package/build/esnext/customer-account/factories.esnext +231 -0
- package/build/esnext/customer-account/index.esnext +83 -0
- package/build/esnext/fetch-polyfills.esnext +188 -0
- package/build/esnext/index.esnext +440 -0
- package/build/esnext/mocks/i18n.esnext +17 -0
- package/build/esnext/mocks/money.esnext +12 -0
- package/build/esnext/mocks/signals.esnext +29 -0
- package/build/esnext/mocks/target-apis.esnext +33 -0
- package/build/esnext/navigation.esnext +51 -0
- package/build/esnext/point-of-sale/factories.esnext +506 -0
- package/build/esnext/point-of-sale/index.esnext +79 -0
- package/build/esnext/targets.esnext +29 -0
- package/build/ts/admin/factories.d.ts +19 -0
- package/build/ts/admin/factories.d.ts.map +1 -0
- package/build/ts/admin/index.d.ts +31 -0
- package/build/ts/admin/index.d.ts.map +1 -0
- package/build/ts/api-version.d.ts +11 -0
- package/build/ts/api-version.d.ts.map +1 -0
- package/build/ts/checkout/factories.d.ts +10 -0
- package/build/ts/checkout/factories.d.ts.map +1 -0
- package/build/ts/checkout/index.d.ts +53 -0
- package/build/ts/checkout/index.d.ts.map +1 -0
- package/build/ts/customer-account/factories.d.ts +8 -0
- package/build/ts/customer-account/factories.d.ts.map +1 -0
- package/build/ts/customer-account/index.d.ts +21 -0
- package/build/ts/customer-account/index.d.ts.map +1 -0
- package/build/ts/disposable.d.ts +20 -0
- package/build/ts/fetch-polyfills.d.ts +19 -0
- package/build/ts/fetch-polyfills.d.ts.map +1 -0
- package/build/ts/index.d.ts +138 -0
- package/build/ts/index.d.ts.map +1 -0
- package/build/ts/mocks/i18n.d.ts +14 -0
- package/build/ts/mocks/i18n.d.ts.map +1 -0
- package/build/ts/mocks/money.d.ts +9 -0
- package/build/ts/mocks/money.d.ts.map +1 -0
- package/build/ts/mocks/signals.d.ts +19 -0
- package/build/ts/mocks/signals.d.ts.map +1 -0
- package/build/ts/mocks/target-apis.d.ts +15 -0
- package/build/ts/mocks/target-apis.d.ts.map +1 -0
- package/build/ts/navigation.d.ts +41 -0
- package/build/ts/navigation.d.ts.map +1 -0
- package/build/ts/point-of-sale/factories.d.ts +20 -0
- package/build/ts/point-of-sale/factories.d.ts.map +1 -0
- package/build/ts/point-of-sale/index.d.ts +30 -0
- package/build/ts/point-of-sale/index.d.ts.map +1 -0
- package/build/ts/targets.d.ts +27 -0
- package/build/ts/targets.d.ts.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/checkout.esnext +1 -0
- package/checkout.js +1 -0
- package/checkout.mjs +1 -0
- package/customer-account.esnext +1 -0
- package/customer-account.js +1 -0
- package/customer-account.mjs +1 -0
- package/index.esnext +1 -0
- package/index.js +1 -0
- package/index.mjs +1 -0
- package/package.json +84 -2
- package/point-of-sale.esnext +1 -0
- package/point-of-sale.js +1 -0
- package/point-of-sale.mjs +1 -0
- package/src/admin/README.md +78 -0
- package/src/admin/factories.ts +380 -0
- package/src/admin/index.ts +85 -0
- package/src/api-version.ts +23 -0
- package/src/checkout/README.md +152 -0
- package/src/checkout/factories.ts +482 -0
- package/src/checkout/index.ts +174 -0
- package/src/customer-account/README.md +86 -0
- package/src/customer-account/factories.ts +272 -0
- package/src/customer-account/index.ts +90 -0
- package/src/disposable.d.ts +20 -0
- package/src/fetch-polyfills.ts +222 -0
- package/src/index.ts +551 -0
- package/src/mocks/i18n.ts +15 -0
- package/src/mocks/money.ts +7 -0
- package/src/mocks/signals.ts +37 -0
- package/src/mocks/target-apis.ts +56 -0
- package/src/navigation.ts +72 -0
- package/src/point-of-sale/README.md +100 -0
- package/src/point-of-sale/factories.ts +581 -0
- package/src/point-of-sale/index.ts +92 -0
- package/src/targets.ts +68 -0
- package/src/tests/admin-factories.test.ts +31 -0
- package/src/tests/fetch.test.ts +139 -0
- package/src/tests/fixtures/test-module.ts +1 -0
- package/src/tests/getExtension.test.ts +259 -0
- package/src/tests/helpers.ts +140 -0
- package/src/tests/navigation.test.ts +130 -0
- package/src/tests/setUpExtension.test.ts +52 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ This testing library provides strongly typed mocks of the extension API--like th
|
|
|
14
14
|
## 📋 Recommendations
|
|
15
15
|
|
|
16
16
|
- **TypeScript** — we recommend TypeScript to enforce API compliance against mock objects
|
|
17
|
+
- **Node.js ≥ 22.0.0** and **TypeScript ≥ 5.2** — to use ([Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management))
|
|
17
18
|
- **@testing-library/preact** — if your extension uses [Preact](https://preactjs.com/), we recommend installing [`@testing-library/preact`](https://preactjs.com/guide/v10/preact-testing-library/) for its `fireEvent` and `waitFor` helpers
|
|
18
19
|
|
|
19
20
|
## 📦 Installation
|
|
@@ -72,7 +73,7 @@ Your extension's own `package.json` (inside `extensions/my-extension/`) already
|
|
|
72
73
|
"devDependencies": {
|
|
73
74
|
"@shopify/ui-extensions-tester": "latest",
|
|
74
75
|
"@testing-library/preact": "^3.2.0",
|
|
75
|
-
"typescript": "^5.
|
|
76
|
+
"typescript": "^5.2.0",
|
|
76
77
|
"vitest": "^3.0.0"
|
|
77
78
|
}
|
|
78
79
|
}
|
|
@@ -144,7 +145,34 @@ The path must match the target you pass to `getExtension()`.
|
|
|
144
145
|
|
|
145
146
|
## 🏊♀️ Getting started
|
|
146
147
|
|
|
147
|
-
Every test file follows the same pattern:
|
|
148
|
+
Every test file follows the same pattern:
|
|
149
|
+
create an extension harness, set it up before
|
|
150
|
+
each test, and tear it down after.
|
|
151
|
+
|
|
152
|
+
### Quick start with `using` (Node ≥ 22.0.0)
|
|
153
|
+
|
|
154
|
+
If your runtime supports
|
|
155
|
+
[Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management),
|
|
156
|
+
use `setUpExtension` for zero-boilerplate
|
|
157
|
+
setup and automatic teardown:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import {setUpExtension} from '@shopify/ui-extensions-tester';
|
|
161
|
+
|
|
162
|
+
test('rendering the extension', async () => {
|
|
163
|
+
using extension = setUpExtension(
|
|
164
|
+
'purchase.checkout.block.render',
|
|
165
|
+
);
|
|
166
|
+
await extension.render();
|
|
167
|
+
// tearDown() is called automatically at the end of the block
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Classic setup
|
|
172
|
+
|
|
173
|
+
Alternatively, create the harness once and
|
|
174
|
+
manage the lifecycle with `beforeEach` /
|
|
175
|
+
`afterEach`:
|
|
148
176
|
|
|
149
177
|
```ts
|
|
150
178
|
import {getExtension} from '@shopify/ui-extensions-tester';
|
|
@@ -339,25 +367,31 @@ Each surface exports some helpers:
|
|
|
339
367
|
|
|
340
368
|
Exports from `@shopify/ui-extensions-tester`:
|
|
341
369
|
|
|
342
|
-
### `
|
|
370
|
+
### `setUpExtension(target, options?)`
|
|
371
|
+
|
|
372
|
+
Sets up an extension for testing and returns a
|
|
373
|
+
disposable object that supports automatic
|
|
374
|
+
teardown with the `using` keyword:
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
test('example', async () => {
|
|
378
|
+
using extension = setUpExtension(
|
|
379
|
+
'purchase.checkout.block.render',
|
|
380
|
+
);
|
|
381
|
+
await extension.render();
|
|
382
|
+
// tearDown() called automatically
|
|
383
|
+
});
|
|
384
|
+
```
|
|
343
385
|
|
|
344
|
-
|
|
386
|
+
It reads `shopify.extension.toml`, finds the module for the given target, and provides helpers to mock the environment and render the extension. It locates `shopify.extension.toml` by walking up from the calling test file's directory, and falls back to searching `extensions/` under the current working directory. Results are cached: calling `getExtension` twice with the same target and the same resolved TOML returns the same instance.
|
|
345
387
|
|
|
346
388
|
| Option | Type | Default | Description |
|
|
347
389
|
| ----------------- | -------- | ----------------------------- | ---------------------------------------------------------- |
|
|
348
390
|
| `configSearchDir` | `string` | calling test file's directory | Directory to start searching for `shopify.extension.toml`. |
|
|
349
391
|
|
|
350
|
-
By default
|
|
351
|
-
|
|
352
|
-
**Returns** an `Extension<T>` object with the following members:
|
|
392
|
+
By default, it walks up from the test file's directory to find `shopify.extension.toml`.
|
|
353
393
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
Sets up an extension environment for testing. Creates a mock `shopify` global with some defaults.
|
|
357
|
-
|
|
358
|
-
#### `extension.tearDown()`
|
|
359
|
-
|
|
360
|
-
Tears down the extension environment. Resets the `shopify` global and clears `document.body`.
|
|
394
|
+
**Returns** an `Extension` object with the following members:
|
|
361
395
|
|
|
362
396
|
#### `extension.render()`
|
|
363
397
|
|
|
@@ -402,6 +436,22 @@ extension.navigation.currentEntry =
|
|
|
402
436
|
|
|
403
437
|
Assigning to `extension.navigation` also updates `globalThis.navigation`, so extension code that calls `navigation.navigate()` directly will use the mock.
|
|
404
438
|
|
|
439
|
+
### `getExtension(target, options?)`
|
|
440
|
+
|
|
441
|
+
> ⚠️ Prefer [`setUpExtension`](#setupextensiontarget-options) on Node ≥ 22.0.0. Use `getExtension` only if your runtime does not support [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management).
|
|
442
|
+
|
|
443
|
+
Accepts the same arguments as `setUpExtension`. You must call `extension.setUp()` and `extension.tearDown()` explicitly.
|
|
444
|
+
|
|
445
|
+
**Returns** an `Extension` object with the following additional members:
|
|
446
|
+
|
|
447
|
+
#### `extension.setUp()`
|
|
448
|
+
|
|
449
|
+
Sets up an extension environment for testing. Creates a mock `shopify` global with some defaults.
|
|
450
|
+
|
|
451
|
+
#### `extension.tearDown()`
|
|
452
|
+
|
|
453
|
+
Tears down the extension environment. Resets the `shopify` global and clears `document.body`.
|
|
454
|
+
|
|
405
455
|
### `createNavigationHistoryEntry(options?)`
|
|
406
456
|
|
|
407
457
|
Creates a [`NavigationHistoryEntry`](https://developer.mozilla.org/en-US/docs/Web/API/NavigationHistoryEntry) for mocking `navigation.currentEntry` or other navigation values.
|
package/admin.esnext
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./build/esnext/admin/index.esnext";
|
package/admin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require("./build/cjs/admin/index.js");
|
package/admin.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./build/esm/admin/index.mjs";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
function _classPrivateFieldLooseBase(e, t) {
|
|
6
|
+
if (!{}.hasOwnProperty.call(e, t)) throw new TypeError("attempted to use private field on non-instance");
|
|
7
|
+
return e;
|
|
8
|
+
}
|
|
9
|
+
var id = 0;
|
|
10
|
+
function _classPrivateFieldLooseKey(e) {
|
|
11
|
+
return "__private_" + id++ + "_" + e;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
exports.classPrivateFieldLooseBase = _classPrivateFieldLooseBase;
|
|
15
|
+
exports.classPrivateFieldLooseKey = _classPrivateFieldLooseKey;
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var signals = require('../mocks/signals.js');
|
|
6
|
+
var i18n = require('../mocks/i18n.js');
|
|
7
|
+
var index = require('./index.js');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extracts the API type for a given admin extension target directly from the
|
|
11
|
+
* implementation's `ExtensionTargets` interface.
|
|
12
|
+
*
|
|
13
|
+
* Properties prefixed with `__` are private internal APIs and are excluded
|
|
14
|
+
* from the mock type so they cannot be relied on in test suites.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Derived types — not directly exported from the admin surface barrel
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
function gidFromTarget(target) {
|
|
22
|
+
const resource = target.split('.')[1].replace(/-details$|-index$|-fulfilled-card$|-purchase-option$/, '').split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
|
|
23
|
+
return `gid://shopify/${resource}/1`;
|
|
24
|
+
}
|
|
25
|
+
function createData(selected = []) {
|
|
26
|
+
return {
|
|
27
|
+
selected
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function createNavigation() {
|
|
31
|
+
return {
|
|
32
|
+
navigate: () => {}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createConfigApp() {
|
|
36
|
+
return {
|
|
37
|
+
launchUrl: 'https://mock-app.test/launch',
|
|
38
|
+
applicationUrl: 'https://mock-app.test'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function createMockStandardApi(target) {
|
|
42
|
+
return {
|
|
43
|
+
extension: {
|
|
44
|
+
target
|
|
45
|
+
},
|
|
46
|
+
auth: {
|
|
47
|
+
idToken: async () => 'mock-id-token'
|
|
48
|
+
},
|
|
49
|
+
i18n: i18n.createMockI18n(),
|
|
50
|
+
intents: {
|
|
51
|
+
launchUrl: undefined,
|
|
52
|
+
invoke: async () => ({
|
|
53
|
+
complete: Promise.resolve({
|
|
54
|
+
code: 'closed'
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
storage: index.createStorage(),
|
|
59
|
+
query: async () => ({
|
|
60
|
+
data: undefined
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function createMockStandardRenderingApi(target) {
|
|
65
|
+
return {
|
|
66
|
+
...createMockStandardApi(target),
|
|
67
|
+
resourcePicker: async () => undefined,
|
|
68
|
+
picker: async () => ({
|
|
69
|
+
selected: Promise.resolve(undefined)
|
|
70
|
+
})
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function createMockBlockApi(target) {
|
|
74
|
+
return {
|
|
75
|
+
...createMockStandardRenderingApi(target),
|
|
76
|
+
data: createData([{
|
|
77
|
+
id: gidFromTarget(target)
|
|
78
|
+
}]),
|
|
79
|
+
navigation: createNavigation()
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function createMockActionApi(target) {
|
|
83
|
+
return {
|
|
84
|
+
...createMockStandardRenderingApi(target),
|
|
85
|
+
close: () => {},
|
|
86
|
+
data: createData([{
|
|
87
|
+
id: gidFromTarget(target)
|
|
88
|
+
}])
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Group factory functions — each composes the correct API for a target group
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
function createPrintActionMock(target) {
|
|
97
|
+
return {
|
|
98
|
+
...createMockStandardRenderingApi(target),
|
|
99
|
+
data: createData()
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function createShouldRenderMock(target) {
|
|
103
|
+
return {
|
|
104
|
+
...createMockStandardApi(target),
|
|
105
|
+
data: createData()
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function createProductDetailsConfigMock(target) {
|
|
109
|
+
return {
|
|
110
|
+
...createMockBlockApi(target),
|
|
111
|
+
data: {
|
|
112
|
+
selected: [],
|
|
113
|
+
product: {
|
|
114
|
+
id: 'gid://shopify/Product/1',
|
|
115
|
+
title: 'Mock Product',
|
|
116
|
+
handle: 'mock-product',
|
|
117
|
+
status: 'ACTIVE',
|
|
118
|
+
totalVariants: 1,
|
|
119
|
+
totalInventory: 10,
|
|
120
|
+
hasOnlyDefaultVariant: true,
|
|
121
|
+
onlineStoreUrl: 'https://mock-shop.myshopify.com/products/mock-product',
|
|
122
|
+
options: [],
|
|
123
|
+
productType: '',
|
|
124
|
+
productComponents: []
|
|
125
|
+
},
|
|
126
|
+
app: createConfigApp()
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function createProductVariantDetailsConfigMock(target) {
|
|
131
|
+
return {
|
|
132
|
+
...createMockBlockApi(target),
|
|
133
|
+
data: {
|
|
134
|
+
selected: [],
|
|
135
|
+
variant: {
|
|
136
|
+
id: 'gid://shopify/ProductVariant/1',
|
|
137
|
+
sku: 'MOCK-SKU',
|
|
138
|
+
barcode: '',
|
|
139
|
+
title: 'Default',
|
|
140
|
+
displayName: 'Mock Product - Default',
|
|
141
|
+
price: '0.00',
|
|
142
|
+
compareAtPrice: '0.00',
|
|
143
|
+
taxable: true,
|
|
144
|
+
taxCode: '',
|
|
145
|
+
weight: 0,
|
|
146
|
+
selectedOptions: [],
|
|
147
|
+
productVariantComponents: []
|
|
148
|
+
},
|
|
149
|
+
app: createConfigApp()
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function createDiscountFunctionSettingsMock(target) {
|
|
154
|
+
return {
|
|
155
|
+
...createMockStandardRenderingApi(target),
|
|
156
|
+
navigation: createNavigation(),
|
|
157
|
+
applyMetafieldChange: async () => index.createResult('applyMetafieldChange'),
|
|
158
|
+
data: {
|
|
159
|
+
id: 'gid://shopify/DiscountAutomaticApp/1',
|
|
160
|
+
metafields: []
|
|
161
|
+
},
|
|
162
|
+
discounts: {
|
|
163
|
+
discountClasses: signals.createReadonlySignalLike([]),
|
|
164
|
+
updateDiscountClasses: () => index.createResult('updateDiscountClasses'),
|
|
165
|
+
discountMethod: signals.createReadonlySignalLike('automatic')
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function createOrderRoutingRuleMock(target) {
|
|
170
|
+
return {
|
|
171
|
+
...createMockStandardRenderingApi(target),
|
|
172
|
+
applyMetafieldsChange: () => {},
|
|
173
|
+
data: {
|
|
174
|
+
rule: {
|
|
175
|
+
label: 'Mock Routing Rule',
|
|
176
|
+
description: 'A mock order routing rule',
|
|
177
|
+
id: 'gid://shopify/DeliveryCustomization/1',
|
|
178
|
+
metafields: []
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function createValidationSettingsMock(target) {
|
|
184
|
+
return {
|
|
185
|
+
...createMockStandardRenderingApi(target),
|
|
186
|
+
applyMetafieldChange: async () => index.createResult('applyMetafieldChange'),
|
|
187
|
+
data: {
|
|
188
|
+
validation: undefined,
|
|
189
|
+
shopifyFunction: {
|
|
190
|
+
id: 'gid://shopify/ShopifyFunction/1'
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function createPurchaseOptionsCardMock(target) {
|
|
196
|
+
return {
|
|
197
|
+
...createMockActionApi(target),
|
|
198
|
+
data: {
|
|
199
|
+
selected: []
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function createCustomerSegmentTemplateMock(target) {
|
|
204
|
+
return {
|
|
205
|
+
...createMockStandardApi(target)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Factory map — TypeScript verifies each entry against ApiForTarget<K>
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
|
|
213
|
+
const adminMockFactories = {
|
|
214
|
+
// Runnable targets
|
|
215
|
+
'admin.customers.segmentation-templates.data': createCustomerSegmentTemplateMock,
|
|
216
|
+
'admin.app.tools.data': createMockStandardApi,
|
|
217
|
+
// Block targets
|
|
218
|
+
'admin.product-details.block.render': createMockBlockApi,
|
|
219
|
+
'admin.order-details.block.render': createMockBlockApi,
|
|
220
|
+
'admin.customer-details.block.render': createMockBlockApi,
|
|
221
|
+
'admin.collection-details.block.render': createMockBlockApi,
|
|
222
|
+
'admin.draft-order-details.block.render': createMockBlockApi,
|
|
223
|
+
'admin.abandoned-checkout-details.block.render': createMockBlockApi,
|
|
224
|
+
'admin.catalog-details.block.render': createMockBlockApi,
|
|
225
|
+
'admin.company-details.block.render': createMockBlockApi,
|
|
226
|
+
'admin.company-location-details.block.render': createMockBlockApi,
|
|
227
|
+
'admin.gift-card-details.block.render': createMockBlockApi,
|
|
228
|
+
'admin.product-variant-details.block.render': createMockBlockApi,
|
|
229
|
+
'admin.product-details.reorder.render': createMockBlockApi,
|
|
230
|
+
// Action targets
|
|
231
|
+
'admin.product-details.action.render': createMockActionApi,
|
|
232
|
+
'admin.catalog-details.action.render': createMockActionApi,
|
|
233
|
+
'admin.company-details.action.render': createMockActionApi,
|
|
234
|
+
'admin.gift-card-details.action.render': createMockActionApi,
|
|
235
|
+
'admin.order-details.action.render': createMockActionApi,
|
|
236
|
+
'admin.customer-details.action.render': createMockActionApi,
|
|
237
|
+
'admin.customer-segment-details.action.render': createMockActionApi,
|
|
238
|
+
'admin.product-index.action.render': createMockActionApi,
|
|
239
|
+
'admin.order-index.action.render': createMockActionApi,
|
|
240
|
+
'admin.customer-index.action.render': createMockActionApi,
|
|
241
|
+
'admin.discount-index.action.render': createMockActionApi,
|
|
242
|
+
'admin.collection-details.action.render': createMockActionApi,
|
|
243
|
+
'admin.collection-index.action.render': createMockActionApi,
|
|
244
|
+
'admin.abandoned-checkout-details.action.render': createMockActionApi,
|
|
245
|
+
'admin.product-variant-details.action.render': createMockActionApi,
|
|
246
|
+
'admin.draft-order-details.action.render': createMockActionApi,
|
|
247
|
+
'admin.draft-order-index.action.render': createMockActionApi,
|
|
248
|
+
'admin.discount-details.action.render': createMockActionApi,
|
|
249
|
+
'admin.order-fulfilled-card.action.render': createMockActionApi,
|
|
250
|
+
// Bulk action targets
|
|
251
|
+
'admin.product-index.selection-action.render': createMockActionApi,
|
|
252
|
+
'admin.order-index.selection-action.render': createMockActionApi,
|
|
253
|
+
'admin.customer-index.selection-action.render': createMockActionApi,
|
|
254
|
+
'admin.draft-order-index.selection-action.render': createMockActionApi,
|
|
255
|
+
'admin.discount-index.selection-action.render': createMockActionApi,
|
|
256
|
+
// Purchase options card action targets
|
|
257
|
+
'admin.product-purchase-option.action.render': createPurchaseOptionsCardMock,
|
|
258
|
+
'admin.product-variant-purchase-option.action.render': createPurchaseOptionsCardMock,
|
|
259
|
+
// Print action targets
|
|
260
|
+
'admin.order-details.print-action.render': createPrintActionMock,
|
|
261
|
+
'admin.product-details.print-action.render': createPrintActionMock,
|
|
262
|
+
'admin.order-index.selection-print-action.render': createPrintActionMock,
|
|
263
|
+
'admin.product-index.selection-print-action.render': createPrintActionMock,
|
|
264
|
+
// Configuration targets
|
|
265
|
+
'admin.product-details.configuration.render': createProductDetailsConfigMock,
|
|
266
|
+
'admin.product-variant-details.configuration.render': createProductVariantDetailsConfigMock,
|
|
267
|
+
// Function settings targets
|
|
268
|
+
'admin.discount-details.function-settings.render': createDiscountFunctionSettingsMock,
|
|
269
|
+
'admin.settings.internal-order-routing-rule.render': createOrderRoutingRuleMock,
|
|
270
|
+
'admin.settings.order-routing-rule.render': createOrderRoutingRuleMock,
|
|
271
|
+
'admin.settings.validation.render': createValidationSettingsMock,
|
|
272
|
+
// Should-render targets (action)
|
|
273
|
+
'admin.product-details.action.should-render': createShouldRenderMock,
|
|
274
|
+
'admin.catalog-details.action.should-render': createShouldRenderMock,
|
|
275
|
+
'admin.company-details.action.should-render': createShouldRenderMock,
|
|
276
|
+
'admin.gift-card-details.action.should-render': createShouldRenderMock,
|
|
277
|
+
'admin.order-details.action.should-render': createShouldRenderMock,
|
|
278
|
+
'admin.customer-details.action.should-render': createShouldRenderMock,
|
|
279
|
+
'admin.customer-segment-details.action.should-render': createShouldRenderMock,
|
|
280
|
+
'admin.product-index.action.should-render': createShouldRenderMock,
|
|
281
|
+
'admin.order-index.action.should-render': createShouldRenderMock,
|
|
282
|
+
'admin.customer-index.action.should-render': createShouldRenderMock,
|
|
283
|
+
'admin.discount-index.action.should-render': createShouldRenderMock,
|
|
284
|
+
'admin.collection-details.action.should-render': createShouldRenderMock,
|
|
285
|
+
'admin.collection-index.action.should-render': createShouldRenderMock,
|
|
286
|
+
'admin.abandoned-checkout-details.action.should-render': createShouldRenderMock,
|
|
287
|
+
'admin.product-variant-details.action.should-render': createShouldRenderMock,
|
|
288
|
+
'admin.draft-order-details.action.should-render': createShouldRenderMock,
|
|
289
|
+
'admin.draft-order-index.action.should-render': createShouldRenderMock,
|
|
290
|
+
'admin.discount-details.action.should-render': createShouldRenderMock,
|
|
291
|
+
'admin.order-fulfilled-card.action.should-render': createShouldRenderMock,
|
|
292
|
+
// Should-render targets (bulk action)
|
|
293
|
+
'admin.product-index.selection-action.should-render': createShouldRenderMock,
|
|
294
|
+
'admin.order-index.selection-action.should-render': createShouldRenderMock,
|
|
295
|
+
'admin.customer-index.selection-action.should-render': createShouldRenderMock,
|
|
296
|
+
'admin.draft-order-index.selection-action.should-render': createShouldRenderMock,
|
|
297
|
+
'admin.discount-index.selection-action.should-render': createShouldRenderMock,
|
|
298
|
+
// Should-render targets (print action)
|
|
299
|
+
'admin.order-details.print-action.should-render': createShouldRenderMock,
|
|
300
|
+
'admin.product-details.print-action.should-render': createShouldRenderMock,
|
|
301
|
+
'admin.order-index.selection-print-action.should-render': createShouldRenderMock,
|
|
302
|
+
'admin.product-index.selection-print-action.should-render': createShouldRenderMock
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// Main factory
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Creates a complete mock API for an admin extension target.
|
|
311
|
+
* Each entry in the factory map is type-checked by TypeScript against
|
|
312
|
+
* the concrete API type for that target.
|
|
313
|
+
*/
|
|
314
|
+
function createMockAdminTargetApi(target) {
|
|
315
|
+
const factory = adminMockFactories[target];
|
|
316
|
+
if (!factory) {
|
|
317
|
+
throw new Error(`Unsupported admin target: "${target}". ` + 'Add an entry for this target in adminMockFactories.');
|
|
318
|
+
}
|
|
319
|
+
return factory(target);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
exports.createMockAdminTargetApi = createMockAdminTargetApi;
|
|
323
|
+
exports.gidFromTarget = gidFromTarget;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a mock `Storage` instance.
|
|
7
|
+
*
|
|
8
|
+
* Optionally accepts a `Record<string, unknown>` of initial entries.
|
|
9
|
+
*/
|
|
10
|
+
function createStorage(initialEntries) {
|
|
11
|
+
const store = new Map(initialEntries ? Object.entries(initialEntries) : []);
|
|
12
|
+
return {
|
|
13
|
+
set: async (key, value) => {
|
|
14
|
+
store.set(key, value);
|
|
15
|
+
},
|
|
16
|
+
setMany: async entries => {
|
|
17
|
+
for (const [entryKey, entryValue] of Object.entries(entries)) {
|
|
18
|
+
store.set(entryKey, entryValue);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
get: async key => store.get(key),
|
|
22
|
+
getMany: async keys => keys.map(entry => store.get(entry)),
|
|
23
|
+
clear: async () => {
|
|
24
|
+
store.clear();
|
|
25
|
+
},
|
|
26
|
+
delete: async key => store.delete(key),
|
|
27
|
+
deleteMany: async keys => {
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const entry of keys) {
|
|
30
|
+
result[entry] = store.delete(entry);
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
},
|
|
34
|
+
entries: async () => store.entries()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Maps each admin mutation API name to its result type.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const adminMutationDefaults = {
|
|
43
|
+
applyMetafieldChange: () => ({
|
|
44
|
+
type: 'success'
|
|
45
|
+
}),
|
|
46
|
+
updateDiscountClasses: () => ({
|
|
47
|
+
success: true,
|
|
48
|
+
value: []
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates a typed mock result for an admin mutation API.
|
|
54
|
+
*
|
|
55
|
+
* @param mutation - The mutation API name (e.g. `'applyMetafieldChange'`).
|
|
56
|
+
* @param result - Optional partial override merged with the default.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* createResult('applyMetafieldChange');
|
|
60
|
+
* createResult('updateDiscountClasses', {value: ['ORDER']});
|
|
61
|
+
*/
|
|
62
|
+
function createResult(mutation, result) {
|
|
63
|
+
return {
|
|
64
|
+
...adminMutationDefaults[mutation](),
|
|
65
|
+
...result
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.createResult = createResult;
|
|
70
|
+
exports.createStorage = createStorage;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The API version supported by this version of the library.
|
|
7
|
+
*
|
|
8
|
+
* At build time, `"2026.4.0-rc.3"` is replaced by rollup with the
|
|
9
|
+
* raw NPM version string from package.json (e.g. `"2026.4.0-rc.1"`).
|
|
10
|
+
*
|
|
11
|
+
* When running from source (e.g. in tests), the placeholder is still
|
|
12
|
+
* present, so we fall back to reading package.json via require.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const npmVersion = "2026.4.0-rc.3";
|
|
16
|
+
function npmVersionToApiVersion(version) {
|
|
17
|
+
const [year, minor] = version.split('.');
|
|
18
|
+
return `${year}-${minor.padStart(2, '0')}`;
|
|
19
|
+
}
|
|
20
|
+
const API_VERSION = npmVersionToApiVersion(npmVersion);
|
|
21
|
+
|
|
22
|
+
exports.API_VERSION = API_VERSION;
|