@stencil/vitest 0.0.1-dev.20260109124515.90fb962

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +296 -0
  2. package/dist/bin/stencil-test.d.ts +3 -0
  3. package/dist/bin/stencil-test.d.ts.map +1 -0
  4. package/dist/bin/stencil-test.js +341 -0
  5. package/dist/config.d.ts +73 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +302 -0
  8. package/dist/environments/env/happy-dom.d.ts +4 -0
  9. package/dist/environments/env/happy-dom.d.ts.map +1 -0
  10. package/dist/environments/env/happy-dom.js +15 -0
  11. package/dist/environments/env/jsdom.d.ts +4 -0
  12. package/dist/environments/env/jsdom.d.ts.map +1 -0
  13. package/dist/environments/env/jsdom.js +32 -0
  14. package/dist/environments/env/mock-doc.d.ts +4 -0
  15. package/dist/environments/env/mock-doc.d.ts.map +1 -0
  16. package/dist/environments/env/mock-doc.js +14 -0
  17. package/dist/environments/stencil.d.ts +28 -0
  18. package/dist/environments/stencil.d.ts.map +1 -0
  19. package/dist/environments/stencil.js +71 -0
  20. package/dist/environments/types.d.ts +6 -0
  21. package/dist/environments/types.d.ts.map +1 -0
  22. package/dist/environments/types.js +1 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +5 -0
  26. package/dist/setup/config-loader.d.ts +19 -0
  27. package/dist/setup/config-loader.d.ts.map +1 -0
  28. package/dist/setup/config-loader.js +92 -0
  29. package/dist/setup/happy-dom-setup.d.ts +12 -0
  30. package/dist/setup/happy-dom-setup.d.ts.map +1 -0
  31. package/dist/setup/happy-dom-setup.js +16 -0
  32. package/dist/setup/jsdom-setup.d.ts +30 -0
  33. package/dist/setup/jsdom-setup.d.ts.map +1 -0
  34. package/dist/setup/jsdom-setup.js +95 -0
  35. package/dist/setup/mock-doc-setup.d.ts +17 -0
  36. package/dist/setup/mock-doc-setup.d.ts.map +1 -0
  37. package/dist/setup/mock-doc-setup.js +90 -0
  38. package/dist/testing/html-serializer.d.ts +27 -0
  39. package/dist/testing/html-serializer.d.ts.map +1 -0
  40. package/dist/testing/html-serializer.js +152 -0
  41. package/dist/testing/matchers.d.ts +181 -0
  42. package/dist/testing/matchers.d.ts.map +1 -0
  43. package/dist/testing/matchers.js +460 -0
  44. package/dist/testing/render.d.ts +11 -0
  45. package/dist/testing/render.d.ts.map +1 -0
  46. package/dist/testing/render.js +118 -0
  47. package/dist/testing/snapshot-serializer.d.ts +17 -0
  48. package/dist/testing/snapshot-serializer.d.ts.map +1 -0
  49. package/dist/testing/snapshot-serializer.js +50 -0
  50. package/dist/types.d.ts +81 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +1 -0
  53. package/package.json +133 -0
@@ -0,0 +1,73 @@
1
+ import { type ViteUserConfig } from 'vitest/config';
2
+ import type { Config as StencilConfig } from '@stencil/core/internal';
3
+ /**
4
+ * Define a Vitest configuration for Stencil component testing
5
+ *
6
+ * Accepts standard Vitest config with optional Stencil enhancements.
7
+ * Automatically applies Stencil-specific defaults:
8
+ * - JSX configuration (h, Fragment)
9
+ * - Resolve aliases from Stencil config (@, @components, @utils)
10
+ * - Coverage configuration based on srcDir
11
+ * - Exclude patterns for build outputs
12
+ * - Auto-injects jsdom-setup for environment: 'jsdom'
13
+ * - Auto-injects happy-dom-setup for environment: 'happy-dom'
14
+ * - Custom 'stencil' environment handles its own setup
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { defineVitestConfig } from '@stencil/vitest/config';
19
+ *
20
+ * export default defineVitestConfig({
21
+ * test: {
22
+ * projects: [
23
+ * {
24
+ * test: {
25
+ * name: 'stencil',
26
+ * include: ['**\/*.spec.tsx'],
27
+ * environment: 'stencil',
28
+ * setupFiles: ['./vitest-setup.ts'],
29
+ * // environmentOptions: {
30
+ * // stencil: {
31
+ * // domEnvironment: 'happy-dom' // 'jsdom' | 'mock-doc' (default), Make sure to install relevant packages
32
+ * // },
33
+ * // },
34
+ * },
35
+ * },
36
+ * {
37
+ * test: {
38
+ * name: 'jsdom',
39
+ * include: ['**\/*.jsdom.spec.tsx'],
40
+ * environment: 'jsdom',
41
+ * setupFiles: ['./vitest-setup.ts'],
42
+ * },
43
+ * },
44
+ * {
45
+ * test: {
46
+ * name: 'happy-dom',
47
+ * include: ['**\/*.happy.spec.tsx'],
48
+ * environment: 'happy-dom',
49
+ * setupFiles: ['./vitest-setup.ts'],
50
+ * },
51
+ * },
52
+ * {
53
+ * test: {
54
+ * name: 'browser',
55
+ * include: ['**\/*.e2e.tsx'],
56
+ * browser: {
57
+ * enabled: true,
58
+ * provider: 'playwright',
59
+ * instances: [
60
+ * { browser: 'chromium' }
61
+ * ],
62
+ * },
63
+ * },
64
+ * },
65
+ * ],
66
+ * },
67
+ * });
68
+ * ```
69
+ */
70
+ export declare function defineVitestConfig(config?: ViteUserConfig & {
71
+ stencilConfig?: string | StencilConfig;
72
+ }): Promise<ViteUserConfig>;
73
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAOlE,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,GAAE,cAAc,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,GAAG,aAAa,CAAA;CAAO,GACvE,OAAO,CAAC,cAAc,CAAC,CAqBzB"}
package/dist/config.js ADDED
@@ -0,0 +1,302 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import { loadStencilConfig, getStencilSrcDir, getStencilOutputDirs, getStencilResolveAliases, } from './setup/config-loader.js';
3
+ /**
4
+ * Define a Vitest configuration for Stencil component testing
5
+ *
6
+ * Accepts standard Vitest config with optional Stencil enhancements.
7
+ * Automatically applies Stencil-specific defaults:
8
+ * - JSX configuration (h, Fragment)
9
+ * - Resolve aliases from Stencil config (@, @components, @utils)
10
+ * - Coverage configuration based on srcDir
11
+ * - Exclude patterns for build outputs
12
+ * - Auto-injects jsdom-setup for environment: 'jsdom'
13
+ * - Auto-injects happy-dom-setup for environment: 'happy-dom'
14
+ * - Custom 'stencil' environment handles its own setup
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { defineVitestConfig } from '@stencil/vitest/config';
19
+ *
20
+ * export default defineVitestConfig({
21
+ * test: {
22
+ * projects: [
23
+ * {
24
+ * test: {
25
+ * name: 'stencil',
26
+ * include: ['**\/*.spec.tsx'],
27
+ * environment: 'stencil',
28
+ * setupFiles: ['./vitest-setup.ts'],
29
+ * // environmentOptions: {
30
+ * // stencil: {
31
+ * // domEnvironment: 'happy-dom' // 'jsdom' | 'mock-doc' (default), Make sure to install relevant packages
32
+ * // },
33
+ * // },
34
+ * },
35
+ * },
36
+ * {
37
+ * test: {
38
+ * name: 'jsdom',
39
+ * include: ['**\/*.jsdom.spec.tsx'],
40
+ * environment: 'jsdom',
41
+ * setupFiles: ['./vitest-setup.ts'],
42
+ * },
43
+ * },
44
+ * {
45
+ * test: {
46
+ * name: 'happy-dom',
47
+ * include: ['**\/*.happy.spec.tsx'],
48
+ * environment: 'happy-dom',
49
+ * setupFiles: ['./vitest-setup.ts'],
50
+ * },
51
+ * },
52
+ * {
53
+ * test: {
54
+ * name: 'browser',
55
+ * include: ['**\/*.e2e.tsx'],
56
+ * browser: {
57
+ * enabled: true,
58
+ * provider: 'playwright',
59
+ * instances: [
60
+ * { browser: 'chromium' }
61
+ * ],
62
+ * },
63
+ * },
64
+ * },
65
+ * ],
66
+ * },
67
+ * });
68
+ * ```
69
+ */
70
+ export async function defineVitestConfig(config = {}) {
71
+ // Load Stencil config if provided (optional)
72
+ let stencilConfig;
73
+ if (typeof config.stencilConfig === 'string') {
74
+ try {
75
+ stencilConfig = await loadStencilConfig(config.stencilConfig);
76
+ }
77
+ catch {
78
+ // loading is optional
79
+ }
80
+ }
81
+ else if (config.stencilConfig) {
82
+ stencilConfig = config.stencilConfig;
83
+ }
84
+ // Remove stencilConfig from the final config (destructure to exclude it)
85
+ const { stencilConfig: _stencilConfig, ...vitestConfig } = config;
86
+ // Apply Stencil-specific defaults
87
+ const enhancedConfig = applyStencilDefaults(vitestConfig, stencilConfig);
88
+ return defineConfig(enhancedConfig);
89
+ }
90
+ /**
91
+ * Generate coverage exclude patterns from test include patterns
92
+ */
93
+ function generateCoverageExcludes(testIncludes, srcDir) {
94
+ const excludes = [];
95
+ for (const include of testIncludes) {
96
+ // Convert test include patterns to coverage exclude patterns
97
+ // Examples:
98
+ // "src/**/*.spec.{ts,tsx}" -> "src/**/*.spec.{ts,tsx}"
99
+ // "**/*.spec.{ts,tsx}" -> "src/**/*.spec.{ts,tsx}" (assuming srcDir is "src")
100
+ // "components/**/*.test.tsx" -> "src/components/**/*.test.tsx"
101
+ let excludePattern = include;
102
+ // If pattern doesn't start with srcDir, prepend it
103
+ if (!excludePattern.startsWith(`${srcDir}/`)) {
104
+ // Handle patterns that start with **/ by replacing with srcDir
105
+ if (excludePattern.startsWith('**/')) {
106
+ excludePattern = excludePattern.replace('**/', `${srcDir}/`);
107
+ }
108
+ else {
109
+ // For other patterns, prepend srcDir
110
+ excludePattern = `${srcDir}/${excludePattern}`;
111
+ }
112
+ }
113
+ excludes.push(excludePattern);
114
+ }
115
+ return excludes;
116
+ }
117
+ /**
118
+ * Apply Stencil-specific defaults to Vitest config
119
+ */
120
+ function applyStencilDefaults(config, stencilConfig) {
121
+ // Start with the user's config
122
+ const result = { ...config };
123
+ // Add esbuild JSX config if not present
124
+ if (!result.esbuild) {
125
+ result.esbuild = {
126
+ jsxFactory: 'h',
127
+ jsxFragment: 'Fragment',
128
+ };
129
+ }
130
+ // Add resolve aliases from Stencil config if not present
131
+ if (!result.resolve) {
132
+ result.resolve = {};
133
+ }
134
+ if (!result.resolve.alias) {
135
+ result.resolve.alias = getStencilResolveAliases(stencilConfig);
136
+ }
137
+ else if (typeof result.resolve.alias === 'object' && !Array.isArray(result.resolve.alias)) {
138
+ // Merge with existing aliases, user's aliases take precedence
139
+ result.resolve.alias = {
140
+ ...getStencilResolveAliases(stencilConfig),
141
+ ...result.resolve.alias,
142
+ };
143
+ }
144
+ // Configure Vite server to watch Stencil output directories
145
+ // This allows Vitest to automatically re-run tests when Stencil rebuilds components
146
+ if (!result.server) {
147
+ result.server = {};
148
+ }
149
+ if (!result.server.watch) {
150
+ result.server.watch = {};
151
+ }
152
+ // Ensure test config exists
153
+ if (!result.test) {
154
+ result.test = {};
155
+ }
156
+ // Enable forceRerunTriggers to watch output directories
157
+ // This ensures Vitest re-runs tests when Stencil rebuilds components
158
+ const outputDirs = getStencilOutputDirs(stencilConfig);
159
+ if (!result.test.forceRerunTriggers) {
160
+ result.test.forceRerunTriggers = [];
161
+ }
162
+ // Add output directories to force rerun triggers
163
+ const existingTriggers = Array.isArray(result.test.forceRerunTriggers)
164
+ ? result.test.forceRerunTriggers
165
+ : [result.test.forceRerunTriggers];
166
+ const outputDirTriggers = outputDirs.map((dir) => `**/${dir}/**`);
167
+ result.test.forceRerunTriggers = [...new Set([...existingTriggers, ...outputDirTriggers])];
168
+ // Add globals if not set
169
+ if (result.test.globals === undefined) {
170
+ result.test.globals = true;
171
+ }
172
+ // Add coverage config at root level if not present
173
+ // This applies to all projects in multi-project mode
174
+ if (!result.test.coverage) {
175
+ const srcDir = getStencilSrcDir(stencilConfig);
176
+ const outputDirs = getStencilOutputDirs(stencilConfig);
177
+ // Collect all test include patterns from projects
178
+ const testIncludes = [];
179
+ if (result.test.projects) {
180
+ // Multi-project mode
181
+ for (const project of result.test.projects) {
182
+ if (project.test?.include) {
183
+ const includes = Array.isArray(project.test.include) ? project.test.include : [project.test.include];
184
+ testIncludes.push(...includes);
185
+ }
186
+ }
187
+ }
188
+ else if (result.test.include) {
189
+ // Single project mode
190
+ const includes = Array.isArray(result.test.include) ? result.test.include : [result.test.include];
191
+ testIncludes.push(...includes);
192
+ }
193
+ // Generate coverage excludes from test includes
194
+ const coverageExcludes = testIncludes.length > 0
195
+ ? generateCoverageExcludes(testIncludes, srcDir)
196
+ : [`${srcDir}/**/*.spec.{ts,tsx}`, `${srcDir}/**/*.e2e.{ts,tsx}`, `${srcDir}/**/*.test.{ts,tsx}`];
197
+ result.test.coverage = {
198
+ provider: 'v8',
199
+ reporter: ['text', 'json', 'html'],
200
+ include: [`${srcDir}/**/*.{ts,tsx}`],
201
+ exclude: [...coverageExcludes, ...outputDirs.map((dir) => `${dir}/**`)],
202
+ };
203
+ }
204
+ // If there are projects, enhance each one
205
+ if (result.test.projects) {
206
+ result.test.projects = result.test.projects.map((project) => enhanceProject(project, stencilConfig));
207
+ }
208
+ else {
209
+ // Single project mode - enhance the test config directly
210
+ result.test = enhanceTestConfig(result.test, stencilConfig);
211
+ }
212
+ if (result.test.onConsoleLog === undefined) {
213
+ result.test.onConsoleLog = (log) => {
214
+ if (log?.includes('Running in development mode.'))
215
+ return false;
216
+ return true;
217
+ };
218
+ }
219
+ return result;
220
+ }
221
+ /**
222
+ * Enhance test config with Stencil defaults
223
+ */
224
+ function enhanceTestConfig(testConfig, stencilConfig) {
225
+ const enhanced = { ...testConfig };
226
+ // Get output directories from Stencil config
227
+ const outputDirs = getStencilOutputDirs(stencilConfig);
228
+ const defaultExcludes = ['**/node_modules/**', ...outputDirs.map((dir) => `**/${dir}/**`)];
229
+ // Add default excludes if not present
230
+ if (!enhanced.exclude) {
231
+ enhanced.exclude = defaultExcludes;
232
+ }
233
+ else {
234
+ // Merge with existing excludes
235
+ const existingExcludes = Array.isArray(enhanced.exclude) ? enhanced.exclude : [enhanced.exclude];
236
+ enhanced.exclude = [
237
+ ...defaultExcludes,
238
+ ...existingExcludes.filter((pattern) => !defaultExcludes.includes(pattern)),
239
+ ];
240
+ }
241
+ // Add coverage config based on Stencil srcDir if not present
242
+ if (!enhanced.coverage) {
243
+ const srcDir = getStencilSrcDir(stencilConfig);
244
+ enhanced.coverage = {
245
+ provider: 'v8',
246
+ reporter: ['text', 'json', 'html'],
247
+ include: [`${srcDir}/**/*.{ts,tsx}`],
248
+ exclude: [
249
+ `${srcDir}/**/*.spec.{ts,tsx}`,
250
+ `${srcDir}/**/*.e2e.{ts,tsx}`,
251
+ `${srcDir}/**/*.test.{ts,tsx}`,
252
+ ...outputDirs.map((dir) => `${dir}/**`),
253
+ ],
254
+ };
255
+ }
256
+ return enhanced;
257
+ }
258
+ /**
259
+ * Enhance a single project with Stencil defaults
260
+ */
261
+ function enhanceProject(project, stencilConfig) {
262
+ const enhanced = { ...project };
263
+ // Get output directories from Stencil config
264
+ const outputDirs = getStencilOutputDirs(stencilConfig);
265
+ const defaultExcludes = ['**/node_modules/**', ...outputDirs.map((dir) => `**/${dir}/**`)];
266
+ // Merge default excludes with user-provided excludes
267
+ if (enhanced.test) {
268
+ if (!enhanced.test.exclude) {
269
+ enhanced.test.exclude = defaultExcludes;
270
+ }
271
+ else {
272
+ // Merge defaults with existing excludes, avoiding duplicates
273
+ const existingExcludes = Array.isArray(enhanced.test.exclude) ? enhanced.test.exclude : [enhanced.test.exclude];
274
+ enhanced.test.exclude = [
275
+ ...defaultExcludes,
276
+ ...existingExcludes.filter((pattern) => !defaultExcludes.includes(pattern)),
277
+ ];
278
+ }
279
+ // Auto-inject setup files based on environment
280
+ const setupFiles = enhanced.test.setupFiles || [];
281
+ const setupFilesArray = Array.isArray(setupFiles) ? setupFiles : [setupFiles];
282
+ const environment = enhanced.test.environment?.toLowerCase();
283
+ // Auto-inject setup files based on environment type
284
+ // This provides automatic polyfills based on the environment being used
285
+ // Auto-inject jsdom-setup for jsdom environment
286
+ if (environment === 'jsdom') {
287
+ if (!setupFilesArray.includes('@stencil/vitest/jsdom-setup')) {
288
+ enhanced.test.setupFiles = ['@stencil/vitest/jsdom-setup', ...setupFilesArray];
289
+ }
290
+ }
291
+ // Auto-inject happy-dom-setup for happy-dom environment
292
+ if (environment === 'happy-dom') {
293
+ if (!setupFilesArray.includes('@stencil/vitest/happy-dom-setup')) {
294
+ enhanced.test.setupFiles = ['@stencil/vitest/happy-dom-setup', ...setupFilesArray];
295
+ }
296
+ }
297
+ // Note: The 'stencil' custom environment handles its own setup internally
298
+ // and doesn't need auto-injection
299
+ // Note: coverage config is applied at the root test level, not per-project
300
+ }
301
+ return enhanced;
302
+ }
@@ -0,0 +1,4 @@
1
+ import type { EnvironmentStencil } from '../types.js';
2
+ declare const _default: EnvironmentStencil;
3
+ export default _default;
4
+ //# sourceMappingURL=happy-dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"happy-dom.d.ts","sourceRoot":"","sources":["../../../src/environments/env/happy-dom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;wBAEtC,kBAAkB;AAAlC,wBAgBE"}
@@ -0,0 +1,15 @@
1
+ import { importModule } from 'local-pkg';
2
+ export default (async function (global, options) {
3
+ const { Window, GlobalWindow } = (await importModule('happy-dom'));
4
+ const happyDomOptions = {
5
+ url: 'http://localhost:3000',
6
+ ...options.happyDom,
7
+ };
8
+ const window = new (GlobalWindow || Window)(happyDomOptions);
9
+ return {
10
+ window,
11
+ teardown() {
12
+ window.happyDOM.abort();
13
+ },
14
+ };
15
+ });
@@ -0,0 +1,4 @@
1
+ import type { EnvironmentStencil } from '../types.js';
2
+ declare const _default: EnvironmentStencil;
3
+ export default _default;
4
+ //# sourceMappingURL=jsdom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsdom.d.ts","sourceRoot":"","sources":["../../../src/environments/env/jsdom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;wBAGtC,kBAAkB;AAAlC,wBAoCE"}
@@ -0,0 +1,32 @@
1
+ import { importModule } from 'local-pkg';
2
+ import { applyJsdomPolyfills } from '../../setup/jsdom-setup.js';
3
+ export default (async function (global, options) {
4
+ const { JSDOM, ResourceLoader, VirtualConsole, CookieJar } = (await importModule('jsdom'));
5
+ const jsdomOptions = {
6
+ html: '<!DOCTYPE html>',
7
+ url: 'http://localhost:3000',
8
+ contentType: 'text/html',
9
+ pretendToBeVisual: true,
10
+ includeNodeLocations: false,
11
+ runScripts: 'dangerously',
12
+ console: false,
13
+ cookieJar: false,
14
+ ...options.jsdom,
15
+ };
16
+ const virtualConsole = jsdomOptions.console && global.console ? new VirtualConsole().sendTo(global.console) : undefined;
17
+ const window = new JSDOM(jsdomOptions.html, {
18
+ ...jsdomOptions,
19
+ resources: jsdomOptions.resources ??
20
+ (jsdomOptions.userAgent ? new ResourceLoader({ userAgent: jsdomOptions.userAgent }) : undefined),
21
+ virtualConsole,
22
+ cookieJar: jsdomOptions.cookieJar ? new CookieJar() : undefined,
23
+ }).window;
24
+ // Apply all polyfills using shared logic
25
+ applyJsdomPolyfills(window);
26
+ return {
27
+ window,
28
+ teardown() {
29
+ window.close();
30
+ },
31
+ };
32
+ });
@@ -0,0 +1,4 @@
1
+ import type { EnvironmentStencil } from '../types.js';
2
+ declare const _default: EnvironmentStencil;
3
+ export default _default;
4
+ //# sourceMappingURL=mock-doc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-doc.d.ts","sourceRoot":"","sources":["../../../src/environments/env/mock-doc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;wBAGtC,kBAAkB;AAAlC,wBAaE"}
@@ -0,0 +1,14 @@
1
+ import { applyMockDocPolyfills } from '../../setup/mock-doc-setup.js';
2
+ export default (async function (_global, _options) {
3
+ const mockDoc = await import('@stencil/core/mock-doc');
4
+ const win = new mockDoc.MockWindow('http://localhost:3000/');
5
+ applyMockDocPolyfills(win);
6
+ return {
7
+ window: win,
8
+ teardown() {
9
+ if (typeof mockDoc.teardownGlobal === 'function') {
10
+ mockDoc.teardownGlobal(win);
11
+ }
12
+ },
13
+ };
14
+ });
@@ -0,0 +1,28 @@
1
+ import type { Environment } from 'vitest/environments';
2
+ export interface StencilEnvironmentOptions {
3
+ /**
4
+ * The DOM environment to use for testing
5
+ * @default 'mock-doc'
6
+ */
7
+ domEnvironment?: 'mock-doc' | 'happy-dom' | 'jsdom';
8
+ }
9
+ /**
10
+ * Custom Vitest environment for Stencil component testing
11
+ *
12
+ * Usage in vitest.config.ts:
13
+ * ```ts
14
+ * export default defineConfig({
15
+ * test: {
16
+ * environment: 'stencil',
17
+ * environmentOptions: {
18
+ * stencil: {
19
+ * domEnvironment: 'mock-doc' // or 'happy-dom' or 'jsdom'
20
+ * }
21
+ * }
22
+ * }
23
+ * })
24
+ * ```
25
+ */
26
+ declare const _default: Environment;
27
+ export default _default;
28
+ //# sourceMappingURL=stencil.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stencil.d.ts","sourceRoot":"","sources":["../../src/environments/stencil.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOvD,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,cAAc,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;CACrD;AAQD;;;;;;;;;;;;;;;;GAgBG;wBACa,WAAW;AAA3B,wBAqDE"}
@@ -0,0 +1,71 @@
1
+ import { populateGlobal } from 'vitest/environments';
2
+ import happyDom from './env/happy-dom.js';
3
+ import jsdom from './env/jsdom.js';
4
+ import mockDoc from './env/mock-doc.js';
5
+ const environmentMap = {
6
+ 'happy-dom': happyDom,
7
+ jsdom: jsdom,
8
+ 'mock-doc': mockDoc,
9
+ };
10
+ /**
11
+ * Custom Vitest environment for Stencil component testing
12
+ *
13
+ * Usage in vitest.config.ts:
14
+ * ```ts
15
+ * export default defineConfig({
16
+ * test: {
17
+ * environment: 'stencil',
18
+ * environmentOptions: {
19
+ * stencil: {
20
+ * domEnvironment: 'mock-doc' // or 'happy-dom' or 'jsdom'
21
+ * }
22
+ * }
23
+ * }
24
+ * })
25
+ * ```
26
+ */
27
+ export default {
28
+ name: 'stencil',
29
+ viteEnvironment: 'ssr',
30
+ async setup(global, options) {
31
+ const { stencil = {} } = options;
32
+ const domEnvironment = stencil.domEnvironment || 'mock-doc';
33
+ const environment = environmentMap[domEnvironment] || environmentMap['mock-doc'];
34
+ if (!environment) {
35
+ throw new Error(`Unknown domEnvironment: ${domEnvironment}. Must be 'mock-doc', 'happy-dom', or 'jsdom'`);
36
+ }
37
+ // Setup the environment and get the window
38
+ const { window: win, teardown: envTeardown } = await environment(global, options);
39
+ // Stub MessageEvent on global before populateGlobal to prevent Node's undici from loading
40
+ // This prevents "Class extends value undefined" errors from undici's WebSocket implementation
41
+ if (!global.MessageEvent && win.MessageEvent) {
42
+ Object.defineProperty(global, 'MessageEvent', {
43
+ value: win.MessageEvent,
44
+ writable: true,
45
+ configurable: true,
46
+ });
47
+ }
48
+ // Set NODE_ENV to test if not already set
49
+ if (!win.process?.env) {
50
+ win.process = { env: {} };
51
+ }
52
+ if (!win.process.env.NODE_ENV) {
53
+ win.process.env.NODE_ENV = 'test';
54
+ }
55
+ // Populate global with window properties
56
+ const { keys, originals } = populateGlobal(global, win, {
57
+ bindFunctions: true,
58
+ });
59
+ return {
60
+ teardown(global) {
61
+ // Teardown the environment first (e.g., window.close())
62
+ // This needs to happen while globals are still populated
63
+ // because disconnectedCallback may use RAF and other polyfills
64
+ envTeardown();
65
+ // Then clean up populated globals
66
+ keys.forEach((key) => delete global[key]);
67
+ originals.forEach((v, k) => (global[k] = v));
68
+ },
69
+ };
70
+ },
71
+ };
@@ -0,0 +1,6 @@
1
+ export interface EnvironmentReturn {
2
+ window: Window & typeof globalThis;
3
+ teardown: () => void;
4
+ }
5
+ export type EnvironmentStencil = (global: typeof globalThis, options: any) => Promise<EnvironmentReturn>;
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/environments/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,OAAO,UAAU,CAAC;IACnC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,OAAO,UAAU,EAAE,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import './testing/matchers.js';
2
+ import './testing/snapshot-serializer.js';
3
+ export { h } from '@stencil/core';
4
+ export { render } from './testing/render.js';
5
+ export type { RenderOptions, RenderResult } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,kCAAkC,CAAC;AAE1C,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // install custom matchers and snapshot serializer
2
+ import './testing/matchers.js';
3
+ import './testing/snapshot-serializer.js';
4
+ export { h } from '@stencil/core';
5
+ export { render } from './testing/render.js';
@@ -0,0 +1,19 @@
1
+ import type { Config as StencilConfig } from '@stencil/core/internal';
2
+ /**
3
+ * Load Stencil configuration from a file path
4
+ * Uses jiti to handle TypeScript files in Node.js
5
+ */
6
+ export declare function loadStencilConfig(configPath: string): Promise<StencilConfig | undefined>;
7
+ /**
8
+ * Get the source directory from Stencil config
9
+ */
10
+ export declare function getStencilSrcDir(config?: StencilConfig): string;
11
+ /**
12
+ * Get all output directories from Stencil config for exclusion
13
+ */
14
+ export declare function getStencilOutputDirs(config?: StencilConfig): string[];
15
+ /**
16
+ * Create resolve aliases from Stencil config
17
+ */
18
+ export declare function getStencilResolveAliases(config?: StencilConfig): Record<string, string>;
19
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/setup/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAItE;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAsB9F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAyCrE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBvF"}