@testforgejs/vue-test-core 1.0.0-beta.0
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/LICENSE +8 -0
- package/README.md +121 -0
- package/dist/index.cjs +864 -0
- package/dist/index.d.cts +194 -0
- package/dist/index.d.ts +194 -0
- package/dist/index.js +831 -0
- package/package.json +67 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
// src/utils/mergeComponentData.ts
|
|
2
|
+
function mergeComponentData({
|
|
3
|
+
defaultMountData = {},
|
|
4
|
+
defaultData = {},
|
|
5
|
+
mountData = {},
|
|
6
|
+
directData = {},
|
|
7
|
+
skipDefault = false,
|
|
8
|
+
skipOptions = false
|
|
9
|
+
}) {
|
|
10
|
+
const level1 = skipDefault ? {} : {
|
|
11
|
+
...!skipOptions ? defaultMountData : {},
|
|
12
|
+
...defaultData
|
|
13
|
+
};
|
|
14
|
+
const level2 = {
|
|
15
|
+
...mountData,
|
|
16
|
+
...directData
|
|
17
|
+
};
|
|
18
|
+
return { ...level1, ...level2 };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/constants/constants.ts
|
|
22
|
+
var FRAMEWORK_NAME = "TestForge";
|
|
23
|
+
var ERROR_PREFIX = `[${FRAMEWORK_NAME}]`;
|
|
24
|
+
var DEFAULT_PRESET_NAME = "default";
|
|
25
|
+
|
|
26
|
+
// src/validators/validatePreset.ts
|
|
27
|
+
function validatePreset(name, preset) {
|
|
28
|
+
if (!preset) {
|
|
29
|
+
throw new Error(`${ERROR_PREFIX} Preset "${name}" is null or undefined.`);
|
|
30
|
+
}
|
|
31
|
+
if (!Array.isArray(preset.manifest)) {
|
|
32
|
+
throw new Error(`${ERROR_PREFIX} Preset "${name}" must have a "manifest" array.`);
|
|
33
|
+
}
|
|
34
|
+
const manifestPluginNames = /* @__PURE__ */ new Set();
|
|
35
|
+
preset.manifest.forEach((entry, index) => {
|
|
36
|
+
const { module, enabled } = entry;
|
|
37
|
+
if (!module || typeof module.getName !== "function") {
|
|
38
|
+
throw new Error(`${ERROR_PREFIX} Invalid module at manifest[${index}] in preset "${name}".`);
|
|
39
|
+
}
|
|
40
|
+
const pluginName = module.getName();
|
|
41
|
+
if (manifestPluginNames.has(pluginName)) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`${ERROR_PREFIX} Duplicate plugin "${pluginName}" in manifest of preset "${name}".`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (typeof enabled !== "boolean") {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`${ERROR_PREFIX} Plugin "${pluginName}" in preset "${name}" must have a boolean "enabled" flag.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
manifestPluginNames.add(pluginName);
|
|
52
|
+
});
|
|
53
|
+
if (preset.defaults) {
|
|
54
|
+
const defaultKeys = Object.keys(preset.defaults);
|
|
55
|
+
defaultKeys.forEach((key) => {
|
|
56
|
+
if (!manifestPluginNames.has(key)) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`${ERROR_PREFIX} Preset "${name}" contains defaults for unknown plugin "${key}". This plugin is not present in the manifest.`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
const value = preset.defaults[key];
|
|
62
|
+
const isObject = value !== null && typeof value === "object" && !Array.isArray(value);
|
|
63
|
+
if (!isObject) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`${ERROR_PREFIX} Invalid default configuration for plugin "${key}" in preset "${name}". Expected Object, but received ${typeof value}.`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/utils/getActivePreset.ts
|
|
73
|
+
function getActivePreset(presets = {}, extraOptions) {
|
|
74
|
+
const requestedPresetName = extraOptions?.preset?.trim();
|
|
75
|
+
const activeName = requestedPresetName || DEFAULT_PRESET_NAME;
|
|
76
|
+
const preset = presets[activeName];
|
|
77
|
+
if (requestedPresetName && !preset) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`[withPreset] Requested preset "${requestedPresetName}" not found in available presets.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
if (preset) {
|
|
83
|
+
validatePreset(activeName, preset);
|
|
84
|
+
}
|
|
85
|
+
return preset;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/utils/getPresetManifest.ts
|
|
89
|
+
function getPresetManifest(preset) {
|
|
90
|
+
return preset?.manifest ?? [];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/utils/createSupportedPluginsState.ts
|
|
94
|
+
function createSupportedPluginsState(preset) {
|
|
95
|
+
const map = {};
|
|
96
|
+
for (const { module, enabled } of getPresetManifest(preset)) {
|
|
97
|
+
if (typeof enabled !== "boolean") {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`[TestForge] Plugin "${module.getName()}" has invalid "enabled" value: ${String(enabled)}. Expected boolean.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
map[module.getName()] = enabled;
|
|
103
|
+
}
|
|
104
|
+
return map;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/pipeline/core/createPipelineContext.ts
|
|
108
|
+
function createPipelineContext(params) {
|
|
109
|
+
const { defaultMountOptions = {}, mountOptions = {}, extraOptions = {}, presets = {} } = params;
|
|
110
|
+
const activePreset = getActivePreset(presets, extraOptions);
|
|
111
|
+
const supportedPlugins = createSupportedPluginsState(activePreset);
|
|
112
|
+
return {
|
|
113
|
+
defaultMountOptions,
|
|
114
|
+
mountOptions,
|
|
115
|
+
extraOptions,
|
|
116
|
+
supportedPlugins,
|
|
117
|
+
preset: activePreset,
|
|
118
|
+
result: {
|
|
119
|
+
mountOptions: {},
|
|
120
|
+
global: {},
|
|
121
|
+
pluginDefaultsState: {},
|
|
122
|
+
plugins: {}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/pipeline/core/runPipeline.ts
|
|
128
|
+
function runPipeline(ctx, middlewares) {
|
|
129
|
+
let context = ctx;
|
|
130
|
+
for (const middleware of middlewares) {
|
|
131
|
+
const result = middleware(context);
|
|
132
|
+
if (result) {
|
|
133
|
+
context = result;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return context;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/pipeline/core/createPipeline.ts
|
|
140
|
+
function createPipeline(middlewares) {
|
|
141
|
+
return {
|
|
142
|
+
/*
|
|
143
|
+
* Runs the middleware chain sequentially.
|
|
144
|
+
*/
|
|
145
|
+
run(ctx) {
|
|
146
|
+
return runPipeline(ctx, middlewares);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/pipeline/middleware/typeGuards/assertIsObject.ts
|
|
152
|
+
function assertIsObject(val, name) {
|
|
153
|
+
if (val !== null && typeof val === "object" && !Array.isArray(val)) return;
|
|
154
|
+
throw new Error(
|
|
155
|
+
`${ERROR_PREFIX} Critical error: "${name}" must be an Object. Received ${Array.isArray(val) ? "array" : typeof val} (${val}).`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/pipeline/middleware/validation/assertConfigurationShape.ts
|
|
160
|
+
var assertConfigurationShape = (ctx) => {
|
|
161
|
+
assertIsObject(ctx.defaultMountOptions, "defaultMountOptions");
|
|
162
|
+
assertIsObject(ctx.mountOptions, "mountOptions");
|
|
163
|
+
assertIsObject(ctx.extraOptions, "extraOptions");
|
|
164
|
+
return ctx;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// src/pipeline/plugins/logic/resolveExtraOptions.ts
|
|
168
|
+
function resolveExtraOptions(extraOptions) {
|
|
169
|
+
return extraOptions;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/pipeline/middleware/validation/validators/assertUnsupportedPlugins.ts
|
|
173
|
+
var assertUnsupportedPlugins = (plugins, supported) => {
|
|
174
|
+
for (const name of Object.keys(plugins)) {
|
|
175
|
+
if (!supported.has(name)) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`${ERROR_PREFIX} Plugin "${name}" is configured but not supported by the active preset.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/pipeline/middleware/validation/validators/assertExtraOptionUnsupportedPlugins.ts
|
|
184
|
+
var assertExtraOptionUnsupportedPlugins = (extraOptions, supported) => {
|
|
185
|
+
assertUnsupportedPlugins(extraOptions.plugins ?? {}, supported);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/pipeline/middleware/typeGuards/assertPluginValue.ts
|
|
189
|
+
function assertPluginValue(val, name, source) {
|
|
190
|
+
const isObject = val !== null && typeof val === "object" && !Array.isArray(val);
|
|
191
|
+
const isValid = val === void 0 || val === false || isObject;
|
|
192
|
+
if (!isValid) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`${ERROR_PREFIX} Invalid configuration for plugin "${name}" in ${source}. Expected Object or Boolean (false), but received ${typeof val} (${val}).`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/pipeline/middleware/validation/validators/assertResolvedPluginValues.ts
|
|
200
|
+
var assertResolvedPluginValues = (plugins) => {
|
|
201
|
+
for (const [name, value] of Object.entries(plugins)) {
|
|
202
|
+
assertPluginValue(value, name, "plugins");
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// src/pipeline/middleware/validation/validators/assertExtraOptionPluginValues.ts
|
|
207
|
+
var assertExtraOptionPluginValues = (extraOptions, supported) => {
|
|
208
|
+
const plugins = extraOptions.plugins ?? {};
|
|
209
|
+
for (const name of supported) {
|
|
210
|
+
if (Object.prototype.hasOwnProperty.call(plugins, name)) {
|
|
211
|
+
assertPluginValue(plugins[name], name, "extraOptions");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/pipeline/middleware/validation/assertPluginOptions.ts
|
|
217
|
+
var assertPluginOptions = (ctx) => {
|
|
218
|
+
const { supportedPlugins, extraOptions } = ctx;
|
|
219
|
+
const { plugins } = ctx.result;
|
|
220
|
+
const supported = new Set(Object.keys(supportedPlugins));
|
|
221
|
+
assertUnsupportedPlugins(plugins || {}, supported);
|
|
222
|
+
assertExtraOptionUnsupportedPlugins(resolveExtraOptions(extraOptions), supported);
|
|
223
|
+
assertResolvedPluginValues(plugins);
|
|
224
|
+
assertExtraOptionPluginValues(resolveExtraOptions(extraOptions), supported);
|
|
225
|
+
return ctx;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/pipeline/middleware/validation/assertResultShape.ts
|
|
229
|
+
function validateResult(ctx) {
|
|
230
|
+
const { result } = ctx;
|
|
231
|
+
assertIsObject(result, "result");
|
|
232
|
+
assertIsObject(result.mountOptions, "result.mountOptions");
|
|
233
|
+
assertIsObject(result.global, "result.global");
|
|
234
|
+
assertIsObject(result.plugins, "result.plugins");
|
|
235
|
+
}
|
|
236
|
+
var assertResultShape = (ctx) => {
|
|
237
|
+
validateResult(ctx);
|
|
238
|
+
return ctx;
|
|
239
|
+
};
|
|
240
|
+
var assertFinalResultShape = (ctx) => {
|
|
241
|
+
validateResult(ctx);
|
|
242
|
+
return ctx;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// src/pipeline/state/mergeRecord.ts
|
|
246
|
+
function mergeRecord(base, patch) {
|
|
247
|
+
if (!patch) return base;
|
|
248
|
+
const result = { ...base };
|
|
249
|
+
for (const key in patch) {
|
|
250
|
+
const value = patch[key];
|
|
251
|
+
if (value !== void 0) {
|
|
252
|
+
result[key] = value;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/pipeline/state/patchResultState.ts
|
|
259
|
+
function patchResultState(ctx, patch) {
|
|
260
|
+
if (patch.mountOptions) {
|
|
261
|
+
ctx.result.mountOptions = mergeRecord(ctx.result.mountOptions, patch.mountOptions);
|
|
262
|
+
}
|
|
263
|
+
if (patch.plugins) {
|
|
264
|
+
ctx.result.plugins = mergeRecord(ctx.result.plugins, patch.plugins);
|
|
265
|
+
}
|
|
266
|
+
if (patch.pluginDefaultsState) {
|
|
267
|
+
ctx.result.pluginDefaultsState = mergeRecord(
|
|
268
|
+
ctx.result.pluginDefaultsState,
|
|
269
|
+
patch.pluginDefaultsState
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
if (patch.global) {
|
|
273
|
+
ctx.result.global = mergeRecord(ctx.result.global, patch.global);
|
|
274
|
+
}
|
|
275
|
+
return ctx;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/pipeline/middleware/transformers/withBaseMountOptions.ts
|
|
279
|
+
var withBaseMountOptions = (ctx) => {
|
|
280
|
+
const { defaultMountOptions, mountOptions, extraOptions } = ctx;
|
|
281
|
+
const {
|
|
282
|
+
global: _dg,
|
|
283
|
+
plugins: _dp,
|
|
284
|
+
attrs: _da,
|
|
285
|
+
props: _dpr,
|
|
286
|
+
slots: _ds,
|
|
287
|
+
...flatDefaults
|
|
288
|
+
} = defaultMountOptions;
|
|
289
|
+
const {
|
|
290
|
+
global: _mg,
|
|
291
|
+
plugins: _mp,
|
|
292
|
+
attrs: _ma,
|
|
293
|
+
props: _mpr,
|
|
294
|
+
slots: _ms,
|
|
295
|
+
...flatOverrides
|
|
296
|
+
} = mountOptions;
|
|
297
|
+
return patchResultState(ctx, {
|
|
298
|
+
mountOptions: extraOptions.skipDefaultOptions ? mergeRecord(flatOverrides) : mergeRecord(flatDefaults, flatOverrides)
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/guards/isPlainObject.ts
|
|
303
|
+
function isPlainObject(item) {
|
|
304
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
const prototype = Object.getPrototypeOf(item);
|
|
308
|
+
return prototype === Object.prototype || prototype === null;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/utils/mergeConfigs.ts
|
|
312
|
+
function mergeConfigs(target, source) {
|
|
313
|
+
const arrays = Array.isArray(target) && Array.isArray(source);
|
|
314
|
+
const objects = isPlainObject(target) && isPlainObject(source);
|
|
315
|
+
if (arrays) {
|
|
316
|
+
return [.../* @__PURE__ */ new Set([...target, ...source])];
|
|
317
|
+
}
|
|
318
|
+
if (objects) {
|
|
319
|
+
const output = { ...target };
|
|
320
|
+
for (const key of Object.keys(source)) {
|
|
321
|
+
const targetValue = target[key];
|
|
322
|
+
const sourceValue = source[key];
|
|
323
|
+
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
|
|
324
|
+
output[key] = [.../* @__PURE__ */ new Set([...targetValue, ...sourceValue])];
|
|
325
|
+
} else if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
|
|
326
|
+
output[key] = mergeConfigs(targetValue, sourceValue);
|
|
327
|
+
} else {
|
|
328
|
+
output[key] = sourceValue;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return output;
|
|
332
|
+
}
|
|
333
|
+
throw new Error(`${ERROR_PREFIX} mergeConfigs() expects two plain objects or two arrays.`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/pipeline/middleware/transformers/withGlobal.ts
|
|
337
|
+
var withGlobal = (ctx) => {
|
|
338
|
+
const { defaultMountOptions, mountOptions, extraOptions } = ctx;
|
|
339
|
+
return patchResultState(ctx, {
|
|
340
|
+
global: mergeConfigs(
|
|
341
|
+
extraOptions.skipDefaultOptions ? {} : defaultMountOptions.global || {},
|
|
342
|
+
mountOptions.global || {}
|
|
343
|
+
)
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/pipeline/middleware/transformers/withAttrs.ts
|
|
348
|
+
var withAttrs = (ctx) => {
|
|
349
|
+
const { defaultMountOptions, mountOptions, extraOptions } = ctx;
|
|
350
|
+
const attrs = mergeRecord(
|
|
351
|
+
extraOptions.skipDefaultOptions ? {} : defaultMountOptions.attrs || {},
|
|
352
|
+
mountOptions.attrs || {}
|
|
353
|
+
);
|
|
354
|
+
return patchResultState(ctx, {
|
|
355
|
+
mountOptions: Object.keys(attrs).length > 0 ? { attrs } : {}
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// src/pipeline/plugins/logic/filterSupportedPlugins.ts
|
|
360
|
+
function filterSupportedPlugins(plugins = {}, supported) {
|
|
361
|
+
return Object.fromEntries(
|
|
362
|
+
Object.entries(plugins).filter(([name]) => supported[name] !== void 0)
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/pipeline/middleware/transformers/withPluginsBase.ts
|
|
367
|
+
var withPluginsBase = (ctx) => {
|
|
368
|
+
const { defaultMountOptions, mountOptions, extraOptions, supportedPlugins } = ctx;
|
|
369
|
+
return patchResultState(ctx, {
|
|
370
|
+
plugins: {
|
|
371
|
+
...extraOptions.skipDefaultOptions ? {} : filterSupportedPlugins(defaultMountOptions.plugins ?? {}, supportedPlugins),
|
|
372
|
+
...mountOptions.plugins || {}
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// src/pipeline/middleware/transformers/withPluginsManifest.ts
|
|
378
|
+
var withPluginsManifest = (ctx) => {
|
|
379
|
+
const plugins = Object.fromEntries(
|
|
380
|
+
Object.entries(ctx.supportedPlugins).map(([name, enabled]) => [name, enabled ? {} : false])
|
|
381
|
+
);
|
|
382
|
+
return patchResultState(ctx, {
|
|
383
|
+
plugins
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// src/pipeline/middleware/transformers/withPreset.ts
|
|
388
|
+
var withPreset = (ctx) => {
|
|
389
|
+
const { preset } = ctx;
|
|
390
|
+
if (!preset?.defaults) return ctx;
|
|
391
|
+
return patchResultState(ctx, {
|
|
392
|
+
pluginDefaultsState: { ...preset.defaults }
|
|
393
|
+
});
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// src/pipeline/middleware/typeGuards/isPluginOverlayObject.ts
|
|
397
|
+
function isPluginOverlayObject(val) {
|
|
398
|
+
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// src/pipeline/plugins/logic/getExtraPluginOptions.ts
|
|
402
|
+
var getExtraPluginOptions = (extraOptions, name) => {
|
|
403
|
+
return extraOptions.plugins?.[name];
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// src/pipeline/plugins/logic/getPluginConfig.ts
|
|
407
|
+
function getPluginConfig(ctx, name) {
|
|
408
|
+
const base = ctx.result.plugins[name];
|
|
409
|
+
const extraOptions = resolveExtraOptions(ctx.extraOptions);
|
|
410
|
+
const overlay = getExtraPluginOptions(extraOptions, name);
|
|
411
|
+
const isEnabled = overlay !== void 0 ? overlay !== false : base !== false && base !== void 0;
|
|
412
|
+
if (!isEnabled) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
const current = isPluginOverlayObject(base) ? base : {};
|
|
416
|
+
const extra = isPluginOverlayObject(overlay) ? overlay : {};
|
|
417
|
+
return {
|
|
418
|
+
...current,
|
|
419
|
+
...extra
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/pipeline/plugins/logic/patchPluginState.ts
|
|
424
|
+
function patchPluginState(ctx, name, config) {
|
|
425
|
+
const current = ctx.result.plugins[name];
|
|
426
|
+
const currentObj = isPluginOverlayObject(current) ? current : {};
|
|
427
|
+
return patchResultState(ctx, {
|
|
428
|
+
plugins: {
|
|
429
|
+
[name]: {
|
|
430
|
+
...currentObj,
|
|
431
|
+
...config
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/pipeline/plugins/logic/resolveRuntimePluginState.ts
|
|
438
|
+
function resolveRuntimePluginState(config, overlay) {
|
|
439
|
+
const runtimeConfig = {
|
|
440
|
+
...config
|
|
441
|
+
};
|
|
442
|
+
if (isPluginOverlayObject(overlay)) {
|
|
443
|
+
const meta = overlay.__meta;
|
|
444
|
+
if (meta?.instance) {
|
|
445
|
+
runtimeConfig.__sharedInstance = meta.instance;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
delete runtimeConfig.__meta;
|
|
449
|
+
return runtimeConfig;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/pipeline/plugins/adapters/createPluginMiddleware.ts
|
|
453
|
+
function createPluginMiddleware(name) {
|
|
454
|
+
return (ctx) => {
|
|
455
|
+
const config = getPluginConfig(ctx, name);
|
|
456
|
+
if (!config) return ctx;
|
|
457
|
+
const extraOptions = resolveExtraOptions(ctx.extraOptions);
|
|
458
|
+
const runtimeConfig = resolveRuntimePluginState(
|
|
459
|
+
config,
|
|
460
|
+
getExtraPluginOptions(extraOptions, name)
|
|
461
|
+
);
|
|
462
|
+
return patchPluginState(ctx, name, runtimeConfig);
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/pipeline/plugins/builders/createPluginsMiddlewares.ts
|
|
467
|
+
function createPluginsMiddlewares(supportedPlugins) {
|
|
468
|
+
return Object.keys(supportedPlugins).map(
|
|
469
|
+
(name) => createPluginMiddleware(name)
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/pipeline/plugins/logic/mergePluginDefaults.ts
|
|
474
|
+
function mergePluginDefaults(ctx, name) {
|
|
475
|
+
const { result } = ctx;
|
|
476
|
+
const current = result.plugins[name];
|
|
477
|
+
if (current === false) {
|
|
478
|
+
return ctx;
|
|
479
|
+
}
|
|
480
|
+
result.plugins[name] = {
|
|
481
|
+
...result.pluginDefaultsState[name] ?? {},
|
|
482
|
+
...current ?? {}
|
|
483
|
+
};
|
|
484
|
+
return ctx;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/pipeline/plugins/adapters/createPluginMergeMiddleware.ts
|
|
488
|
+
function createPluginMergeMiddleware(name) {
|
|
489
|
+
return (ctx) => {
|
|
490
|
+
return mergePluginDefaults(ctx, name);
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// src/pipeline/plugins/builders/createPluginsMergeMiddlewares.ts
|
|
495
|
+
function createPluginsMergeMiddlewares(supportedPlugins) {
|
|
496
|
+
return Object.keys(supportedPlugins).map(
|
|
497
|
+
(name) => createPluginMergeMiddleware(name)
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/pipeline/mount/createMountPipeline.ts
|
|
502
|
+
function createMountPipeline(ctx) {
|
|
503
|
+
return [
|
|
504
|
+
assertConfigurationShape,
|
|
505
|
+
assertResultShape,
|
|
506
|
+
withPreset,
|
|
507
|
+
withPluginsManifest,
|
|
508
|
+
withBaseMountOptions,
|
|
509
|
+
withGlobal,
|
|
510
|
+
withAttrs,
|
|
511
|
+
withPluginsBase,
|
|
512
|
+
assertPluginOptions,
|
|
513
|
+
...createPluginsMiddlewares(ctx.supportedPlugins),
|
|
514
|
+
...createPluginsMergeMiddlewares(ctx.supportedPlugins),
|
|
515
|
+
assertFinalResultShape
|
|
516
|
+
];
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/core/mountWithPlugins.ts
|
|
520
|
+
import { mount, shallowMount } from "@vue/test-utils";
|
|
521
|
+
|
|
522
|
+
// src/pluginsRegistry/createPluginRegistry.ts
|
|
523
|
+
function createPluginRegistry(manifest = []) {
|
|
524
|
+
const map = /* @__PURE__ */ new Map();
|
|
525
|
+
const register = (entry) => {
|
|
526
|
+
const { module } = entry;
|
|
527
|
+
if (!module) return;
|
|
528
|
+
const name = module.getName();
|
|
529
|
+
const definition = module.getDefinition();
|
|
530
|
+
map.set(name, definition);
|
|
531
|
+
};
|
|
532
|
+
manifest.forEach(register);
|
|
533
|
+
return {
|
|
534
|
+
register,
|
|
535
|
+
get: (name) => map.get(name),
|
|
536
|
+
has: (name) => map.has(name),
|
|
537
|
+
entries: () => map.entries(),
|
|
538
|
+
getNames: () => Array.from(map.keys())
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// src/pluginsRegistry/createPlugins.ts
|
|
543
|
+
function createPlugins(options = {}, ctx) {
|
|
544
|
+
const plugins = [];
|
|
545
|
+
const { preset } = ctx;
|
|
546
|
+
const registry = createPluginRegistry(preset?.manifest);
|
|
547
|
+
for (const [name, definition] of registry.entries()) {
|
|
548
|
+
let pluginOptions = options[name];
|
|
549
|
+
if (pluginOptions !== false && pluginOptions && typeof pluginOptions === "object") {
|
|
550
|
+
if (definition.beforeCreate) {
|
|
551
|
+
pluginOptions = definition.beforeCreate(ctx, pluginOptions);
|
|
552
|
+
}
|
|
553
|
+
const pluginInstance = definition.create(pluginOptions);
|
|
554
|
+
if (definition.afterCreate) {
|
|
555
|
+
definition.afterCreate(pluginInstance, ctx);
|
|
556
|
+
}
|
|
557
|
+
plugins.push(pluginInstance);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return plugins;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/core/mountWithPlugins.ts
|
|
564
|
+
function mountWithPlugins(component, ctx, overrides = {}, runtimeOptions = {
|
|
565
|
+
shallowByDefault: false
|
|
566
|
+
}) {
|
|
567
|
+
const { result } = ctx;
|
|
568
|
+
const mergedOptions = {
|
|
569
|
+
...result.mountOptions,
|
|
570
|
+
...overrides,
|
|
571
|
+
plugins: result.plugins
|
|
572
|
+
};
|
|
573
|
+
const {
|
|
574
|
+
shallow,
|
|
575
|
+
plugins = {},
|
|
576
|
+
skipManagedPlugins = false,
|
|
577
|
+
global: overrideGlobal,
|
|
578
|
+
...restOptions
|
|
579
|
+
} = mergedOptions;
|
|
580
|
+
const shouldUseShallow = shallow ?? runtimeOptions.shallowByDefault;
|
|
581
|
+
const mountFunction = shouldUseShallow ? shallowMount : mount;
|
|
582
|
+
const globalPlugins = skipManagedPlugins ? [] : createPlugins(plugins, ctx);
|
|
583
|
+
const finalGlobal = {
|
|
584
|
+
...result.global,
|
|
585
|
+
...overrideGlobal
|
|
586
|
+
};
|
|
587
|
+
if (globalPlugins.length > 0) {
|
|
588
|
+
finalGlobal.plugins = [...finalGlobal.plugins || [], ...globalPlugins];
|
|
589
|
+
}
|
|
590
|
+
return mountFunction(component, {
|
|
591
|
+
...restOptions,
|
|
592
|
+
global: finalGlobal
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/validators/validatePresets.ts
|
|
597
|
+
function validatePresets(presets = {}) {
|
|
598
|
+
if (!isPlainObject(presets)) {
|
|
599
|
+
throw new Error(`${ERROR_PREFIX} Presets must be a plain object.`);
|
|
600
|
+
}
|
|
601
|
+
Object.entries(presets).forEach(([name, preset]) => {
|
|
602
|
+
validatePreset(name, preset);
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// src/assertions/assertIsPlainObject.ts
|
|
607
|
+
function assertIsPlainObject(value, name = "value") {
|
|
608
|
+
if (!isPlainObject(value)) {
|
|
609
|
+
throw new Error(`${name} must be a plain object.`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// src/validators/validateCreateTestFrameworkOptions.ts
|
|
614
|
+
function validateCreateTestFrameworkOptions(options = {}) {
|
|
615
|
+
assertIsPlainObject(options, "createTestFramework options");
|
|
616
|
+
const { shallowByDefault, presets } = options;
|
|
617
|
+
if (presets !== void 0) {
|
|
618
|
+
validatePresets(presets);
|
|
619
|
+
}
|
|
620
|
+
if (shallowByDefault !== void 0 && typeof shallowByDefault !== "boolean") {
|
|
621
|
+
throw new Error(`${ERROR_PREFIX} "shallowByDefault" must be a boolean.`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// src/validators/validatePlainObjectArgument.ts
|
|
626
|
+
function validatePlainObjectArgument(value, name) {
|
|
627
|
+
if (!isPlainObject(value)) {
|
|
628
|
+
throw new Error(`${ERROR_PREFIX} "${name}" must be a plain object.`);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/validators/validateBooleanOption.ts
|
|
633
|
+
function validateBooleanOption(value, name) {
|
|
634
|
+
if (value !== void 0 && typeof value !== "boolean") {
|
|
635
|
+
throw new Error(`${ERROR_PREFIX} "${name}" must be a boolean.`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/utils/getSupportedPluginNames.ts
|
|
640
|
+
function getSupportedPluginNames(presets = {}, extraOptions) {
|
|
641
|
+
const activePreset = getActivePreset(presets, extraOptions);
|
|
642
|
+
return getPresetManifest(activePreset).map((entry) => entry.module.getName());
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// src/utils/warnRootPluginOption.ts
|
|
646
|
+
function warnRootPluginOption(pluginName, context) {
|
|
647
|
+
console.warn(
|
|
648
|
+
[
|
|
649
|
+
`${ERROR_PREFIX} Detected plugin option "${pluginName}" at the root of "${context}".`,
|
|
650
|
+
"",
|
|
651
|
+
"Plugin options must be placed under:",
|
|
652
|
+
"",
|
|
653
|
+
"{",
|
|
654
|
+
" plugins: {",
|
|
655
|
+
` ${pluginName}: { ... }`,
|
|
656
|
+
" }",
|
|
657
|
+
"}",
|
|
658
|
+
"",
|
|
659
|
+
`Did you mean to use "${context}.plugins.${pluginName}"?`
|
|
660
|
+
].join("\n")
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// src/validators/warnRootPluginOptions.ts
|
|
665
|
+
function warnRootPluginOptions(options, context, presets = {}, extraOptions) {
|
|
666
|
+
const pluginNames = getSupportedPluginNames(presets, extraOptions);
|
|
667
|
+
pluginNames.forEach((pluginName) => {
|
|
668
|
+
const pluginAlreadyConfigured = options.plugins && pluginName in options.plugins;
|
|
669
|
+
if (Object.hasOwn(options, pluginName) && !pluginAlreadyConfigured) {
|
|
670
|
+
warnRootPluginOption(pluginName, context);
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// src/validators/validateComponentFactoryOptions.ts
|
|
676
|
+
function validateComponentFactoryOptions(options, context, presets = {}, extraOptions) {
|
|
677
|
+
validatePlainObjectArgument(options, context);
|
|
678
|
+
validateBooleanOption(options.skipManagedPlugins, "skipManagedPlugins");
|
|
679
|
+
warnRootPluginOptions(options, context, presets, extraOptions);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/validators/validateTestComponentFactoryArguments.ts
|
|
683
|
+
function validateTestComponentFactoryArguments(component, defaultProps, defaultMountOptions, defaultSlots, presets) {
|
|
684
|
+
const isComponent = component !== null && (typeof component === "object" || typeof component === "function");
|
|
685
|
+
if (!isComponent) {
|
|
686
|
+
throw new Error(`${ERROR_PREFIX} testComponentFactory() requires a valid Vue component.`);
|
|
687
|
+
}
|
|
688
|
+
validatePlainObjectArgument(defaultProps, "defaultProps");
|
|
689
|
+
validateComponentFactoryOptions(
|
|
690
|
+
defaultMountOptions,
|
|
691
|
+
"defaultMountOptions",
|
|
692
|
+
presets
|
|
693
|
+
);
|
|
694
|
+
validatePlainObjectArgument(defaultSlots, "defaultSlots");
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/validators/validateComponentFactoryExtraOptions.ts
|
|
698
|
+
function validateComponentFactoryExtraOptions(options, presets = {}) {
|
|
699
|
+
validatePlainObjectArgument(options, "extraOptions");
|
|
700
|
+
validateBooleanOption(options.skipDefaultProps, "skipDefaultProps");
|
|
701
|
+
validateBooleanOption(options.skipDefaultSlots, "skipDefaultSlots");
|
|
702
|
+
validateBooleanOption(options.skipDefaultOptions, "skipDefaultOptions");
|
|
703
|
+
warnRootPluginOptions(options, "extraOptions", presets, options);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// src/validators/validateComponentFactoryArguments.ts
|
|
707
|
+
function validateComponentFactoryArguments(props, mountOptions, slots, extraOptions, presets = {}) {
|
|
708
|
+
validatePlainObjectArgument(props, "props");
|
|
709
|
+
validateComponentFactoryOptions(
|
|
710
|
+
mountOptions,
|
|
711
|
+
"mountOptions",
|
|
712
|
+
presets,
|
|
713
|
+
extraOptions
|
|
714
|
+
);
|
|
715
|
+
validatePlainObjectArgument(slots, "slots");
|
|
716
|
+
validateComponentFactoryExtraOptions(extraOptions, presets);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/core/createTestFramework.ts
|
|
720
|
+
function createTestFramework(options = {}) {
|
|
721
|
+
validateCreateTestFrameworkOptions(options);
|
|
722
|
+
const { presets = {}, shallowByDefault = false } = options;
|
|
723
|
+
const testComponentFactory = (component, defaultProps = {}, defaultMountOptions = {}, defaultSlots = {}) => {
|
|
724
|
+
validateTestComponentFactoryArguments(
|
|
725
|
+
component,
|
|
726
|
+
defaultProps,
|
|
727
|
+
defaultMountOptions,
|
|
728
|
+
defaultSlots,
|
|
729
|
+
presets
|
|
730
|
+
);
|
|
731
|
+
return (props = {}, mountOptions = {}, slots = {}, extraOptions = {}) => {
|
|
732
|
+
validateComponentFactoryArguments(props, mountOptions, slots, extraOptions, presets);
|
|
733
|
+
const {
|
|
734
|
+
skipDefaultProps = false,
|
|
735
|
+
skipDefaultSlots = false,
|
|
736
|
+
skipDefaultOptions = false
|
|
737
|
+
} = extraOptions;
|
|
738
|
+
const finalProps = mergeComponentData({
|
|
739
|
+
defaultMountData: defaultMountOptions.props,
|
|
740
|
+
defaultData: defaultProps,
|
|
741
|
+
mountData: mountOptions.props,
|
|
742
|
+
directData: props,
|
|
743
|
+
skipDefault: skipDefaultProps,
|
|
744
|
+
skipOptions: skipDefaultOptions
|
|
745
|
+
});
|
|
746
|
+
const finalSlots = mergeComponentData({
|
|
747
|
+
defaultMountData: defaultMountOptions.slots,
|
|
748
|
+
defaultData: defaultSlots,
|
|
749
|
+
mountData: mountOptions.slots,
|
|
750
|
+
directData: slots,
|
|
751
|
+
skipDefault: skipDefaultSlots,
|
|
752
|
+
skipOptions: skipDefaultOptions
|
|
753
|
+
});
|
|
754
|
+
const ctx = createPipelineContext({
|
|
755
|
+
defaultMountOptions,
|
|
756
|
+
mountOptions,
|
|
757
|
+
extraOptions,
|
|
758
|
+
presets
|
|
759
|
+
});
|
|
760
|
+
const pipeline = createPipeline(createMountPipeline(ctx));
|
|
761
|
+
const readyCtx = pipeline.run(ctx);
|
|
762
|
+
const mountRuntimeOptions = {
|
|
763
|
+
shallowByDefault
|
|
764
|
+
};
|
|
765
|
+
return mountWithPlugins(
|
|
766
|
+
component,
|
|
767
|
+
readyCtx,
|
|
768
|
+
{
|
|
769
|
+
props: finalProps,
|
|
770
|
+
slots: finalSlots
|
|
771
|
+
},
|
|
772
|
+
mountRuntimeOptions
|
|
773
|
+
);
|
|
774
|
+
};
|
|
775
|
+
};
|
|
776
|
+
return { testComponentFactory };
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/pluginsRegistry/helpers/exposeInstance.ts
|
|
780
|
+
function exposeInstance(instance, options) {
|
|
781
|
+
if (typeof options?.expose === "function") {
|
|
782
|
+
options.expose(instance);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// src/pluginsRegistry/factory/createPluginInstance.ts
|
|
787
|
+
function createPluginInstance(factory, options) {
|
|
788
|
+
const instance = options.__sharedInstance ?? factory(options);
|
|
789
|
+
exposeInstance(instance, options);
|
|
790
|
+
return instance;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/pluginsRegistry/factory/createVuePlugin.ts
|
|
794
|
+
function createVuePlugin(plugin, options) {
|
|
795
|
+
if (options.__sharedInstance) {
|
|
796
|
+
throw new Error(
|
|
797
|
+
`${ERROR_PREFIX} __sharedInstance is not supported for non-instance Vue plugins. Shared instances are only supported for stateful plugin factories such as Router, Pinia or vue-i18n.`
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
if (options.expose) {
|
|
801
|
+
throw new Error(
|
|
802
|
+
`${ERROR_PREFIX} expose() is not supported for non-instance Vue plugins because they do not produce a runtime instance. The expose callback is only available for stateful plugin factories such as Router, Pinia or vue-i18n.`
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
return [plugin, options];
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// src/utils/captureInstance.ts
|
|
809
|
+
function captureInstance() {
|
|
810
|
+
let instance;
|
|
811
|
+
return {
|
|
812
|
+
expose(ins) {
|
|
813
|
+
instance = ins;
|
|
814
|
+
},
|
|
815
|
+
get instance() {
|
|
816
|
+
return instance;
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/index.ts
|
|
822
|
+
var Types = {};
|
|
823
|
+
export {
|
|
824
|
+
Types,
|
|
825
|
+
captureInstance,
|
|
826
|
+
createPluginInstance,
|
|
827
|
+
createTestFramework,
|
|
828
|
+
createVuePlugin,
|
|
829
|
+
validatePreset,
|
|
830
|
+
validatePresets
|
|
831
|
+
};
|