@stencil/vitest 1.6.1 → 1.7.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/README.md CHANGED
@@ -166,8 +166,10 @@ expect(element).toHaveAttribute('aria-label', 'Close');
166
166
  expect(element).toEqualAttribute('type', 'button');
167
167
  expect(element).toEqualAttributes({ type: 'button', disabled: true });
168
168
  expect(element).toHaveProperty('value', 'test');
169
- expect(element).toHaveTextContent('Hello World');
170
- expect(element).toEqualText('Exact text match');
169
+ expect(element).toHaveTextContent('Hello World'); // includes shadow DOM text
170
+ expect(element).toHaveLightTextContent('Hello World'); // light DOM only
171
+ expect(element).toEqualText('Exact text match'); // includes shadow DOM text
172
+ expect(element).toEqualLightText('Exact text match'); // light DOM only
171
173
 
172
174
  // Shadow DOM
173
175
  expect(element).toHaveShadowRoot();
package/dist/config.js CHANGED
@@ -170,7 +170,7 @@ function applyStencilDefaults(config, stencilConfig) {
170
170
  const ignoredArray = Array.isArray(result.server.watch.ignored)
171
171
  ? result.server.watch.ignored
172
172
  : [result.server.watch.ignored];
173
- const mapIgnorePatterns = ['**/*.map', '**/*.map.js'];
173
+ const mapIgnorePatterns = ['**/*.map', '**/*.map.js', '**/dist/**/*.d.ts'];
174
174
  result.server.watch.ignored = [...new Set([...ignoredArray, ...mapIgnorePatterns])];
175
175
  // Ensure test config exists
176
176
  if (!result.test) {
@@ -205,7 +205,7 @@ function applyStencilDefaults(config, stencilConfig) {
205
205
  const existingTriggers = Array.isArray(result.test.forceRerunTriggers)
206
206
  ? result.test.forceRerunTriggers
207
207
  : [result.test.forceRerunTriggers];
208
- const outputDirTriggers = outputDirs.map((dir) => `**/${dir}/**`);
208
+ const outputDirTriggers = outputDirs.map((dir) => `**/${dir}/**/*.js`);
209
209
  result.test.forceRerunTriggers = [...new Set([...existingTriggers, ...outputDirTriggers])];
210
210
  // Add globals if not set
211
211
  if (result.test.globals === undefined) {
@@ -21,10 +21,14 @@ interface CustomMatchers<R = unknown> {
21
21
  toEqualAttributes(expectedAttrs: Record<string, string>): R;
22
22
  /** Asserts element has the property, optionally with a specific value. */
23
23
  toHaveProperty(property: string, value?: any): R;
24
- /** Asserts element's text content contains the specified text. */
24
+ /** Asserts element's text content (including shadow DOM) contains the specified text. */
25
25
  toHaveTextContent(text: string): R;
26
- /** Asserts element's trimmed text content equals the expected text exactly. */
26
+ /** Asserts element's light DOM text content contains the specified text. */
27
+ toHaveLightTextContent(text: string): R;
28
+ /** Asserts element's trimmed text content (including shadow DOM) equals the expected text exactly. */
27
29
  toEqualText(expectedText: string): R;
30
+ /** Asserts element's trimmed light DOM text content (excluding shadow DOM) equals the expected text exactly. */
31
+ toEqualLightText(expectedText: string): R;
28
32
  /** Asserts element has an attached shadow root. */
29
33
  toHaveShadowRoot(): R;
30
34
  /** Asserts element's serialized HTML (including shadow DOM) matches expected HTML. */
@@ -1 +1 @@
1
- {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/testing/matchers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,UAAU,cAAc,CAAC,CAAC,GAAG,OAAO;IAClC,mDAAmD;IACnD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC;IAClC,qDAAqD;IACrD,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,gFAAgF;IAChF,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,2EAA2E;IAC3E,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;IACtD,mEAAmE;IACnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IACtD,sEAAsE;IACtE,iBAAiB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5D,0EAA0E;IAC1E,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;IACjD,kEAAkE;IAClE,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;IACnC,+EAA+E;IAC/E,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IACrC,mDAAmD;IACnD,gBAAgB,IAAI,CAAC,CAAC;IACtB,sFAAsF;IACtF,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IACrC,+FAA+F;IAC/F,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IAC1C,yDAAyD;IACzD,mBAAmB,IAAI,CAAC,CAAC;IACzB,6EAA6E;IAC7E,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IAC3C,uEAAuE;IACvE,yBAAyB,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC1C,wEAAwE;IACxE,8BAA8B,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC/C,uEAAuE;IACvE,6BAA6B,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC9C,kFAAkF;IAClF,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;CAC7D;AAGD,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,SAAS,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;KAAG;IACzD,UAAU,4BAA6B,SAAQ,cAAc;KAAG;CACjE;AAyiBD,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/testing/matchers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,UAAU,cAAc,CAAC,CAAC,GAAG,OAAO;IAClC,mDAAmD;IACnD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC;IAClC,qDAAqD;IACrD,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACvC,gFAAgF;IAChF,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,2EAA2E;IAC3E,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;IACtD,mEAAmE;IACnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IACtD,sEAAsE;IACtE,iBAAiB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5D,0EAA0E;IAC1E,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;IACjD,yFAAyF;IACzF,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;IACnC,4EAA4E;IAC5E,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;IACxC,sGAAsG;IACtG,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IACrC,gHAAgH;IAChH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IAC1C,mDAAmD;IACnD,gBAAgB,IAAI,CAAC,CAAC;IACtB,sFAAsF;IACtF,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IACrC,+FAA+F;IAC/F,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC;IAC1C,yDAAyD;IACzD,mBAAmB,IAAI,CAAC,CAAC;IACzB,6EAA6E;IAC7E,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IAC3C,uEAAuE;IACvE,yBAAyB,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC1C,wEAAwE;IACxE,8BAA8B,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC/C,uEAAuE;IACvE,6BAA6B,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;IAC9C,kFAAkF;IAClF,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;CAC7D;AAGD,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,SAAS,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;KAAG;IACzD,UAAU,4BAA6B,SAAQ,cAAc;KAAG;CACjE;AAioBD,OAAO,EAAE,CAAC"}
@@ -147,10 +147,54 @@ function toHaveProperty(received, property, value) {
147
147
  };
148
148
  }
149
149
  /**
150
- * Check if element has text content
150
+ * Recursively get text content including shadow DOM and Stencil slot polyfill
151
+ */
152
+ function getTextContentWithShadow(element) {
153
+ let text = '';
154
+ if (element.nodeType === 1) {
155
+ const el = element;
156
+ // Traverse shadow root first (real or Stencil polyfill)
157
+ if (el.shadowRoot) {
158
+ text += getTextContentWithShadow(el.shadowRoot);
159
+ }
160
+ // For Stencil non-shadow components with slot polyfill, use __childNodes
161
+ const stencilElem = el;
162
+ const childNodes = stencilElem.__childNodes ?? el.childNodes;
163
+ for (const node of Array.from(childNodes)) {
164
+ if (node.nodeType === 3) {
165
+ // Text node
166
+ text += node.textContent || '';
167
+ }
168
+ else if (node.nodeType === 1) {
169
+ const tag = node.tagName?.toLowerCase();
170
+ if (tag !== 'style' && tag !== 'script') {
171
+ text += getTextContentWithShadow(node);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ // DocumentFragment or ShadowRoot - iterate child nodes directly
178
+ for (const node of Array.from(element.childNodes)) {
179
+ if (node.nodeType === 3) {
180
+ // Text node
181
+ text += node.textContent || '';
182
+ }
183
+ else if (node.nodeType === 1) {
184
+ const tag = node.tagName?.toLowerCase();
185
+ if (tag !== 'style' && tag !== 'script') {
186
+ text += getTextContentWithShadow(node);
187
+ }
188
+ }
189
+ }
190
+ }
191
+ return text;
192
+ }
193
+ /**
194
+ * Check if element has text content (including shadow DOM)
151
195
  */
152
196
  function toHaveTextContent(received, text) {
153
- const actualText = received.textContent || '';
197
+ const actualText = getTextContentWithShadow(received);
154
198
  const pass = actualText.includes(text);
155
199
  return {
156
200
  pass,
@@ -160,10 +204,23 @@ function toHaveTextContent(received, text) {
160
204
  };
161
205
  }
162
206
  /**
163
- * Check if element's text content exactly matches (after trimming)
207
+ * Check if element's light DOM has text content (excludes shadow DOM)
208
+ */
209
+ function toHaveLightTextContent(received, text) {
210
+ const actualText = received.textContent || '';
211
+ const pass = actualText.includes(text);
212
+ return {
213
+ pass,
214
+ message: () => pass
215
+ ? `Expected element light DOM not to have text content "${text}"`
216
+ : `Expected element light DOM to have text content "${text}", but got "${actualText}"`,
217
+ };
218
+ }
219
+ /**
220
+ * Check if element's text content exactly matches (after trimming), including shadow DOM
164
221
  */
165
222
  function toEqualText(received, expectedText) {
166
- const actualText = (received.textContent || '').trim();
223
+ const actualText = getTextContentWithShadow(received).trim();
167
224
  const trimmedExpected = expectedText.trim();
168
225
  const pass = actualText === trimmedExpected;
169
226
  return {
@@ -173,6 +230,20 @@ function toEqualText(received, expectedText) {
173
230
  : `Expected element text to equal "${trimmedExpected}", but got "${actualText}"`,
174
231
  };
175
232
  }
233
+ /**
234
+ * Check if element's light DOM text content exactly matches (after trimming), excludes shadow DOM
235
+ */
236
+ function toEqualLightText(received, expectedText) {
237
+ const actualText = (received.textContent || '').trim();
238
+ const trimmedExpected = expectedText.trim();
239
+ const pass = actualText === trimmedExpected;
240
+ return {
241
+ pass,
242
+ message: () => pass
243
+ ? `Expected element light DOM text not to equal "${trimmedExpected}"`
244
+ : `Expected element light DOM text to equal "${trimmedExpected}", but got "${actualText}"`,
245
+ };
246
+ }
176
247
  /**
177
248
  * Check if element has shadow root
178
249
  */
@@ -445,7 +516,9 @@ function installMatchers() {
445
516
  toEqualAttributes,
446
517
  toHaveProperty,
447
518
  toHaveTextContent,
519
+ toHaveLightTextContent,
448
520
  toEqualText,
521
+ toEqualLightText,
449
522
  toHaveShadowRoot,
450
523
  toEqualHtml,
451
524
  toEqualLightHtml,
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/stenciljs/vitest"
6
6
  },
7
- "version": "1.6.1",
7
+ "version": "1.7.0",
8
8
  "description": "First-class testing utilities for Stencil design systems with Vitest",
9
9
  "license": "MIT",
10
10
  "type": "module",
@@ -97,7 +97,7 @@
97
97
  "dependencies": {
98
98
  "jiti": "^2.6.1",
99
99
  "local-pkg": "^1.1.2",
100
- "vitest-environment-stencil": "1.6.1"
100
+ "vitest-environment-stencil": "1.7.0"
101
101
  },
102
102
  "devDependencies": {
103
103
  "@eslint/js": "^9.39.2",