@vitest/browser 4.1.0 → 4.1.2

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.
@@ -31,7 +31,7 @@ function catchWindowErrors(errorEvent, prop, cb) {
31
31
  cb(e)
32
32
  }
33
33
  else {
34
- // `ErrorEvent` doesn't necessary have `ErrotEvent.error` defined
34
+ // `ErrorEvent` doesn't necessary have `ErrorEvent.error` defined
35
35
  // but some has `ErrorEvent.message` defined, e.g. ResizeObserver error.
36
36
  // https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent/error
37
37
  // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
@@ -50,6 +50,9 @@
50
50
  if (config.testNamePattern)
51
51
  config.testNamePattern = parseRegexp(config.testNamePattern);
52
52
 
53
+ if (config.retry?.condition)
54
+ config.retry.condition = parseRegexp(config.retry.condition);
55
+
53
56
  function parseRegexp(input) {
54
57
  // Parse input
55
58
  const m = input.match(/(\/?)(.+)\1([a-z]*)/i);
@@ -26,8 +26,8 @@
26
26
  {__VITEST_INJECTOR__}
27
27
  {__VITEST_ERROR_CATCHER__}
28
28
  {__VITEST_SCRIPTS__}
29
- <script type="module" crossorigin src="/__vitest_browser__/orchestrator-CXs6qrFe.js"></script>
30
- <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-C2ISqq1C.js">
29
+ <script type="module" crossorigin src="/__vitest_browser__/orchestrator-BNCEhPrv.js"></script>
30
+ <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-DCeMntTS.js">
31
31
  </head>
32
32
  <body>
33
33
  <div id="vitest-tester"></div>
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" href="{__VITEST_FAVICON__}" type="image/svg+xml">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Vitest Browser Tester</title>
8
- <script type="module" crossorigin src="/__vitest_browser__/tester-K5NNxh1O.js"></script>
9
- <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-C2ISqq1C.js">
8
+ <script type="module" crossorigin src="/__vitest_browser__/tester-CuvoYKLr.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/__vitest_browser__/utils-DCeMntTS.js">
10
10
  </head>
11
11
  <body>
12
12
  </body>
package/dist/client.js CHANGED
@@ -231,7 +231,7 @@ const resolver = (input, lazy, parsed, $) => output => {
231
231
  const k = ke[y];
232
232
  const value = output[k];
233
233
  if (value instanceof Primitive) {
234
- const tmp = input[value];
234
+ const tmp = input[+value];
235
235
  if (typeof tmp === object && !parsed.has(tmp)) {
236
236
  parsed.add(tmp);
237
237
  output[k] = ignore;
package/dist/context.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest';
1
2
  import { __INTERNAL, stringify } from 'vitest/internal/browser';
2
3
 
3
4
  function ensureAwaited(promise) {
@@ -304,7 +305,10 @@ function createUserEvent(__tl_user_event_base__, options) {
304
305
  return userEvent;
305
306
  }
306
307
  function createPreviewUserEvent(userEventBase, options) {
307
- let userEvent = userEventBase.setup(options);
308
+ let userEvent = userEventBase.setup({
309
+ advanceTimers: (delay) => vi.advanceTimersByTimeAsync(delay),
310
+ ...options
311
+ });
308
312
  let clipboardData;
309
313
  function toElement(element) {
310
314
  return element instanceof Element ? element : element.element();
@@ -314,7 +318,10 @@ function createPreviewUserEvent(userEventBase, options) {
314
318
  return createPreviewUserEvent(userEventBase, options);
315
319
  },
316
320
  async cleanup() {
317
- userEvent = userEventBase.setup(options ?? {});
321
+ userEvent = userEventBase.setup({
322
+ advanceTimers: (delay) => vi.advanceTimersByTimeAsync(delay),
323
+ ...options
324
+ });
318
325
  },
319
326
  async click(element) {
320
327
  await userEvent.click(toElement(element));
@@ -24,4 +24,4 @@ import{recordArtifact as e,expect as t,chai as n}from"vitest";import{getType as
24
24
 
25
25
  `)}}}function Xe(e){let t=X===`chrome`||X===`chromium`?document:document.implementation.createHTMLDocument(``),n=t.createElement(`div`);t.body.appendChild(n);let r=Object.keys(e);r.forEach(t=>{n.style[t]=e[t]});let i={},a=window.getComputedStyle(n);return r.forEach(e=>{let t=(Z.has(e)?n.style:a)[e];t!=null&&(i[e]=t)}),n.remove(),i}function Ze(e){let t=X===`chrome`||X===`chromium`||X===`webkit`?document:document.implementation.createHTMLDocument(``),n=t.createElement(`div`);n.setAttribute(`style`,e.replace(/\n/g,``)),t.body.appendChild(n);let r=window.getComputedStyle(n),i=Array.from(n.style).reduce((e,t)=>(e[t]=Z.has(t)?n.style.getPropertyValue(t):r.getPropertyValue(t),e),{});return n.remove(),i}function Qe(e){return Object.keys(e).sort().map(t=>`${t}: ${e[t]};`).join(`
26
26
  `)}function $e(e,t,n,r){let i=Object.keys(e);return i.length?i.every(i=>{let a=e[i],o=i.startsWith(`--`),s=[i];return o||s.push(i.toLowerCase()),s.some(e=>{let o=r.has(i)&&Z.has(i)?t.style:n;return o[e]===a||o.getPropertyValue(e)===a})}):!1}function et(e,t,n={normalizeWhitespace:!0}){let r=le(e,et,this),i=n.normalizeWhitespace?be(r.textContent||``):(r.textContent||``).replace(/\u00A0/g,` `),a=i!==``&&t===``;return{pass:!a&&xe(i,t),message:()=>{let e=this.isNot?`not to`:`to`;return h(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveTextContent`,`element`,``),a?`Checking with empty string will always match, use .toBeEmptyDOMElement() instead`:`Expected element ${e} have text content`,t,`Received`,i)}}}function tt(e,t){let n=m(e,tt,this);if(b(n)&&[`checkbox`,`radio`].includes(n.type))throw Error(`input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead`);let r=x(n),i=t!==void 0,a=t,o=r;return t==r&&t!==r&&(a=`${t} (${typeof t})`,o=`${r} (${typeof r})`),{pass:i?this.equals(r,t,[S,...this.customTesters]):!!r,message:()=>{let e=this.isNot?`not to`:`to`,n=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveValue`,`element`,t);return h(this,n,`Expected the element ${e} have value`,i?a:`(any)`,`Received`,o)}}}const $=new Map([]);async function nt(t,n,r=typeof n==`object`?n:{}){if(this.isNot)throw Error(`'toMatchScreenshot' cannot be used with "not"`);if(this.task===void 0||this.currentTestName===void 0)throw Error(`'toMatchScreenshot' cannot be used without test context`);let i=`${this.task.result?.repeatCount??0}${this.testPath}${this.currentTestName}`,a=$.get(i);a===void 0&&(a={current:0},$.set(i,a)),a.current+=1;let o=typeof n==`string`?n:`${this.currentTestName} ${a.current}`,[s,...c]=await Promise.all([d(t,r),...r.screenshotOptions&&`mask`in r.screenshotOptions?r.screenshotOptions.mask.map(e=>d(e,r)):[]]),l=r.screenshotOptions&&`mask`in r.screenshotOptions?{...r,screenshotOptions:{...r.screenshotOptions,mask:c}}:r,u=await f().commands.triggerCommand(`__vitest_screenshotMatcher`,[o,this.currentTestName,{element:s,...l}]);if(u.pass===!1){let t=[];u.reference&&t.push({name:`reference`,...u.reference}),u.actual&&t.push({name:`actual`,...u.actual}),u.diff&&t.push({name:`diff`,...u.diff}),t.length>0&&await e(this.task,{type:`internal:toMatchScreenshot`,kind:`visual-regression`,message:u.message,attachments:t})}return{pass:u.pass,message:()=>u.pass?``:[this.utils.matcherHint(`toMatchScreenshot`,`element`,``),``,u.message,u.reference?`\nReference screenshot:\n ${this.utils.EXPECTED_COLOR(u.reference.path)}`:null,u.actual?`\nActual screenshot:\n ${this.utils.RECEIVED_COLOR(u.actual.path)}`:null,u.diff?this.utils.DIM_COLOR(`\nDiff image:\n ${u.diff.path}`):null,``].filter(e=>e!==null).join(`
27
- `)}}const rt={toBeDisabled:E,toBeEnabled:D,toBeEmptyDOMElement:T,toBeInTheDocument:k,toBeInViewport:M,toBeInvalid:j,toBeRequired:P,toBeValid:De,toBeVisible:Le,toContainElement:F,toContainHTML:I,toHaveAccessibleDescription:L,toHaveAccessibleErrorMessage:R,toHaveAccessibleName:z,toHaveAttribute:B,toHaveClass:H,toHaveFocus:K,toHaveFormValues:q,toHaveStyle:Q,toHaveTextContent:et,toHaveValue:tt,toHaveDisplayValue:G,toBeChecked:w,toBePartiallyChecked:N,toHaveRole:J,toHaveSelection:Y,toMatchScreenshot:nt},it=Symbol.for(`$$vitest:locator`);function at(e,i){if(e!=null&&!(e instanceof HTMLElement)&&!(e instanceof SVGElement)&&!(it in e))throw Error(`Invalid element or locator: ${e}. Expected an instance of HTMLElement, SVGElement or Locator, received ${r(e)}`);let a=t.poll(function(){if(e instanceof Element||e==null)return e;let t=n.util.flag(this,`negate`),r=n.util.flag(this,`_name`);if(t&&r===`toBeInTheDocument`)return e.query();if(r===`toHaveLength`)return e.elements();if(r===`toMatchScreenshot`&&!n.util.flag(this,`_poll.assert_once`)&&n.util.flag(this,`_poll.assert_once`,!0),n.util.flag(this,`_isLastPollAttempt`))return e.element();let i=e.query();if(!i)throw Error(`Cannot find element with locator: ${JSON.stringify(e)}`);return i},ae(i));n.util.flag(a,`_poll.element`,!0);let o=oe().current;if(o&&f().activeTraceTaskIds.has(o.id)){let t=Error(`__vitest_mark_trace__`);n.util.flag(a,`_poll.onSettled`,async r=>{let i=n.util.flag(r.assertion,`negate`),a=n.util.flag(r.assertion,`_name`)||`<unknown>`,o=`expect.element().${i?`not.`:``}${a}`,s=r.status===`fail`?`${o} [ERROR]`:o,c=!e||e instanceof Element?void 0:e.selector;await f().commands.triggerCommand(`__vitest_markTrace`,[{name:s,selector:c,stack:t.stack}],t)})}return a}t.extend(rt),t.element=at;
27
+ `),meta:{outcome:u.outcome}}}const rt={toBeDisabled:E,toBeEnabled:D,toBeEmptyDOMElement:T,toBeInTheDocument:k,toBeInViewport:M,toBeInvalid:j,toBeRequired:P,toBeValid:De,toBeVisible:Le,toContainElement:F,toContainHTML:I,toHaveAccessibleDescription:L,toHaveAccessibleErrorMessage:R,toHaveAccessibleName:z,toHaveAttribute:B,toHaveClass:H,toHaveFocus:K,toHaveFormValues:q,toHaveStyle:Q,toHaveTextContent:et,toHaveValue:tt,toHaveDisplayValue:G,toBeChecked:w,toBePartiallyChecked:N,toHaveRole:J,toHaveSelection:Y,toMatchScreenshot:nt},it=Symbol.for(`$$vitest:locator`);function at(e,i){if(e!=null&&!(e instanceof HTMLElement)&&!(e instanceof SVGElement)&&!(it in e))throw Error(`Invalid element or locator: ${e}. Expected an instance of HTMLElement, SVGElement or Locator, received ${r(e)}`);let a=t.poll(function(){if(e instanceof Element||e==null)return e;let t=n.util.flag(this,`negate`),r=n.util.flag(this,`_name`);if(t&&r===`toBeInTheDocument`)return e.query();if(r===`toHaveLength`)return e.elements();if(r===`toMatchScreenshot`&&!n.util.flag(this,`_poll.assert_once`)&&n.util.flag(this,`_poll.assert_once`,!0),n.util.flag(this,`_isLastPollAttempt`))return e.element();let i=e.query();if(!i)throw Error(`Cannot find element with locator: ${JSON.stringify(e)}`);return i},ae(i));n.util.flag(a,`_poll.element`,!0);let o=oe().current;if(o&&f().activeTraceTaskIds.has(o.id)){let t=Error(`__vitest_mark_trace__`);n.util.flag(a,`_poll.onSettled`,async r=>{let i=n.util.flag(r.assertion,`negate`),a=n.util.flag(r.assertion,`_name`)||`<unknown>`,o=`expect.element().${i?`not.`:``}${a}`,s=r.status===`fail`?`${o} [ERROR]`:o,c=!e||e instanceof Element?void 0:e.selector;await f().commands.triggerCommand(`__vitest_markTrace`,[{name:s,selector:c,stack:t.stack}],t)})}return a}t.extend(rt),t.element=at;
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { PNG } from 'pngjs';
18
18
  import { diff } from '@blazediff/core';
19
19
  import { WebSocketServer } from 'ws';
20
20
 
21
- var version = "4.1.0";
21
+ var version = "4.1.2";
22
22
 
23
23
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
24
24
  function normalizeWindowsPath(input = "") {
@@ -241,7 +241,7 @@ const resolver = (input, lazy, parsed, $) => output => {
241
241
  const k = ke[y];
242
242
  const value = output[k];
243
243
  if (value instanceof Primitive) {
244
- const tmp = input[value];
244
+ const tmp = input[+value];
245
245
  if (typeof tmp === object && !parsed.has(tmp)) {
246
246
  parsed.add(tmp);
247
247
  output[k] = ignore;
@@ -1161,7 +1161,7 @@ var BrowserPlugin = (parentServer, base = "/") => {
1161
1161
  },
1162
1162
  transform(code, id) {
1163
1163
  if (id.includes(parentServer.vite.config.cacheDir) && id.includes("loupe.js")) {
1164
- // loupe bundle has a nastry require('util') call that leaves a warning in the console
1164
+ // loupe bundle has a nasty require('util') call that leaves a warning in the console
1165
1165
  const utilRequire = "nodeUtil = require_util();";
1166
1166
  return code.replace(utilRequire, " ".repeat(utilRequire.length));
1167
1167
  }
@@ -2346,6 +2346,7 @@ function buildOutput(outcome, timeout) {
2346
2346
  switch (outcome.type) {
2347
2347
  case "unstable-screenshot": return {
2348
2348
  pass: false,
2349
+ outcome: outcome.type,
2349
2350
  reference: outcome.reference && {
2350
2351
  path: outcome.reference.path,
2351
2352
  width: outcome.reference.image.metadata.width,
@@ -2358,6 +2359,7 @@ function buildOutput(outcome, timeout) {
2358
2359
  case "missing-reference": {
2359
2360
  return {
2360
2361
  pass: false,
2362
+ outcome: outcome.type,
2361
2363
  reference: {
2362
2364
  path: outcome.reference.path,
2363
2365
  width: outcome.reference.image.metadata.width,
@@ -2370,9 +2372,13 @@ function buildOutput(outcome, timeout) {
2370
2372
  }
2371
2373
  case "update-reference":
2372
2374
  case "matched-immediately":
2373
- case "matched-after-comparison": return { pass: true };
2375
+ case "matched-after-comparison": return {
2376
+ pass: true,
2377
+ outcome: outcome.type
2378
+ };
2374
2379
  case "mismatch": return {
2375
2380
  pass: false,
2381
+ outcome: outcome.type,
2376
2382
  reference: {
2377
2383
  path: outcome.reference.path,
2378
2384
  width: outcome.reference.image.metadata.width,
@@ -2393,6 +2399,7 @@ function buildOutput(outcome, timeout) {
2393
2399
  default: {
2394
2400
  return {
2395
2401
  pass: false,
2402
+ outcome: null,
2396
2403
  actual: null,
2397
2404
  reference: null,
2398
2405
  diff: null,
@@ -2573,10 +2580,14 @@ class ProjectBrowser {
2573
2580
  }
2574
2581
  }
2575
2582
  function wrapConfig(config) {
2576
- return {
2577
- ...config,
2578
- testNamePattern: config.testNamePattern ? config.testNamePattern.toString() : undefined
2579
- };
2583
+ config = { ...config };
2584
+ // workaround RegExp serialization
2585
+ config.testNamePattern &&= config.testNamePattern.toString();
2586
+ // workaround RegExp serialization
2587
+ if (typeof config.retry === "object") {
2588
+ config.retry.condition &&= config.retry.condition.toString();
2589
+ }
2590
+ return config;
2580
2591
  }
2581
2592
 
2582
2593
  class ParentBrowserProject {
@@ -12,11 +12,13 @@ interface ScreenshotData {
12
12
  }
13
13
  export type ScreenshotMatcherOutput = Promise<{
14
14
  pass: false;
15
+ outcome: "unstable-screenshot" | "missing-reference" | "mismatch";
15
16
  reference: ScreenshotData | null;
16
17
  actual: ScreenshotData | null;
17
18
  diff: ScreenshotData | null;
18
19
  message: string;
19
20
  } | {
20
21
  pass: true;
22
+ outcome: "update-reference" | "matched-immediately" | "matched-after-comparison";
21
23
  }>;
22
24
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/browser",
3
3
  "type": "module",
4
- "version": "4.1.0",
4
+ "version": "4.1.2",
5
5
  "description": "Browser running for Vitest",
6
6
  "license": "MIT",
7
7
  "funding": "https://opencollective.com/vitest",
@@ -57,17 +57,17 @@
57
57
  "providers"
58
58
  ],
59
59
  "peerDependencies": {
60
- "vitest": "4.1.0"
60
+ "vitest": "4.1.2"
61
61
  },
62
62
  "dependencies": {
63
63
  "@blazediff/core": "1.9.1",
64
64
  "magic-string": "^0.30.21",
65
65
  "pngjs": "^7.0.0",
66
66
  "sirv": "^3.0.2",
67
- "tinyrainbow": "^3.0.3",
67
+ "tinyrainbow": "^3.1.0",
68
68
  "ws": "^8.19.0",
69
- "@vitest/mocker": "4.1.0",
70
- "@vitest/utils": "4.1.0"
69
+ "@vitest/mocker": "4.1.2",
70
+ "@vitest/utils": "4.1.2"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@opentelemetry/api": "^1.9.0",
@@ -75,12 +75,12 @@
75
75
  "@types/pngjs": "^6.0.5",
76
76
  "@types/ws": "^8.18.1",
77
77
  "birpc": "^4.0.0",
78
- "flatted": "3.4.0",
78
+ "flatted": "^3.4.2",
79
79
  "ivya": "^1.7.1",
80
80
  "mime": "^4.1.0",
81
81
  "pathe": "^2.0.3",
82
- "vitest": "4.1.0",
83
- "@vitest/runner": "4.1.0"
82
+ "@vitest/runner": "4.1.2",
83
+ "vitest": "4.1.2"
84
84
  },
85
85
  "scripts": {
86
86
  "typecheck": "tsc -p ./src/client/tsconfig.json --noEmit",