@vitest/browser 5.0.0-beta.3 → 5.0.0-beta.5
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/dist/client/.vite/manifest.json +6 -6
- package/dist/client/__vitest_browser__/{defineProperty-C3k2g8Sk.js → defineProperty-WHpdAQXR.js} +44 -1
- package/dist/client/__vitest_browser__/{orchestrator-B44yH1M4.js → orchestrator-bDJB3Bid.js} +44 -31
- package/dist/client/__vitest_browser__/tester-C1kIlbPd.js +2099 -0
- package/dist/client/orchestrator.html +2 -2
- package/dist/client/tester/tester.html +2 -2
- package/dist/client/tester/trace.d.ts +1 -1
- package/dist/expect-element.js +3 -3
- package/dist/index.js +83 -32
- package/dist/{locators-DUkyvRhY.js → locators-CPBpJv8y.js} +1 -1
- package/dist/locators.js +1 -1
- package/dist/state.js +1 -0
- package/dist/types.d.ts +5 -2
- package/jest-dom.d.ts +25 -6
- package/package.json +7 -7
- package/dist/client/__vitest__/assets/index-BlLo6Q_D.css +0 -1
- package/dist/client/__vitest__/assets/index-O8gheoYf.js +0 -89
- package/dist/client/__vitest__/favicon.ico +0 -0
- package/dist/client/__vitest__/favicon.svg +0 -50
- package/dist/client/__vitest__/index.html +0 -32
- package/dist/client/__vitest_browser__/tester-Byk-s_d6.js +0 -5088
|
@@ -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-
|
|
30
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-
|
|
29
|
+
<script type="module" crossorigin src="/__vitest_browser__/orchestrator-bDJB3Bid.js"></script>
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-WHpdAQXR.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-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-
|
|
8
|
+
<script type="module" crossorigin src="/__vitest_browser__/tester-C1kIlbPd.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/__vitest_browser__/defineProperty-WHpdAQXR.js">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
</body>
|
package/dist/expect-element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Snapshots as e,recordArtifact as t,expect as n,chai as r}from"vitest";import{getType as i}from"vitest/internal/browser";import{b as a,e as o,i as s,g as c,n as l,a as u,k as d,c as f,d as ee,f as te,h as ne,j as re,l as ie,m as ae,o as oe,p as se,q as ce,r as le,s as ue,t as p,_ as m,u as h,L as g,v as de,w as fe,x as pe,y as me,z as he,A as ge,B as _e,C as ve,D as ye,E as be}from"./locators-
|
|
1
|
+
import{Snapshots as e,recordArtifact as t,expect as n,chai as r}from"vitest";import{getType as i}from"vitest/internal/browser";import{b as a,e as o,i as s,g as c,n as l,a as u,k as d,c as f,d as ee,f as te,h as ne,j as re,l as ie,m as ae,o as oe,p as se,q as ce,r as le,s as ue,t as p,_ as m,u as h,L as g,v as de,w as fe,x as pe,y as me,z as he,A as ge,B as _e,C as ve,D as ye,E as be}from"./locators-CPBpJv8y.js";import{server as xe}from"vitest/browser";var Se=Object.defineProperty,Ce=(e,t)=>{let n={};for(var r in e)Se(n,r,{get:e[r],enumerable:!0});return Se(n,Symbol.toStringTag,{value:`Module`}),n};function we(e,t,n={}){let r=Te(e,t,n);if(r.errors.length)throw Error(r.errors[0].message);return r.fragment}function Te(e,t,n={}){let r=new e.LineCounter,i={keepSourceTokens:!0,lineCounter:r,...n},a=e.parseDocument(t,i),o=[],s=e=>[r.linePos(e[0]),r.linePos(e[1])],c=e=>{o.push({message:e.message,range:[r.linePos(e.pos[0]),r.linePos(e.pos[1])]})},l=(t,n)=>{for(let r of n.items){if(r instanceof e.Scalar&&typeof r.value==`string`){let e=v.parse(r,i,o);e&&(t.children=t.children||[],t.children.push(e));continue}if(r instanceof e.YAMLMap){u(t,r);continue}o.push({message:`Sequence items should be strings or maps`,range:s(r.range||n.range)})}},u=(t,n)=>{for(let r of n.items){if(t.children=t.children||[],!(r.key instanceof e.Scalar&&typeof r.key.value==`string`)){o.push({message:`Only string keys are supported`,range:s(r.key.range||n.range)});continue}let a=r.key,c=r.value;if(a.value===`text`){if(!(c instanceof e.Scalar&&typeof c.value==`string`)){o.push({message:`Text value should be a string`,range:s(r.value.range||n.range)});continue}t.children.push({kind:`text`,text:_(c.value)});continue}if(a.value===`/children`){if(!(c instanceof e.Scalar&&typeof c.value==`string`)||c.value!==`contain`&&c.value!==`equal`&&c.value!==`deep-equal`){o.push({message:`Strict value should be "contain", "equal" or "deep-equal"`,range:s(r.value.range||n.range)});continue}t.containerMode=c.value;continue}if(a.value.startsWith(`/`)){if(!(c instanceof e.Scalar&&typeof c.value==`string`)){o.push({message:`Property value should be a string`,range:s(r.value.range||n.range)});continue}t.props=t.props??{},t.props[a.value.slice(1)]=_(c.value);continue}let u=v.parse(a,i,o);if(u){if(c instanceof e.Scalar){let e=typeof c.value;if(e!==`string`&&e!==`number`&&e!==`boolean`){o.push({message:`Node value should be a string or a sequence`,range:s(r.value.range||n.range)});continue}t.children.push({...u,children:[{kind:`text`,text:_(String(c.value))}]});continue}if(c instanceof e.YAMLSeq){t.children.push(u),l(u,c);continue}o.push({message:`Map values should be strings or sequences`,range:s(r.value.range||n.range)})}}},d={kind:`role`,role:`fragment`};return a.errors.forEach(c),o.length?{errors:o,fragment:d}:a.contents?(a.contents instanceof e.YAMLSeq||o.push({message:`Aria snapshot must be a YAML sequence, elements starting with " -"`,range:s(a.contents.range)}),o.length?{errors:o,fragment:d}:(l(d,a.contents),o.length?{errors:o,fragment:Ee}:d.children?.length===1&&(!d.containerMode||d.containerMode===`contain`)?{fragment:d.children[0],errors:[]}:{fragment:d,errors:[]})):{fragment:d,errors:[]}}const Ee={kind:`role`,role:`fragment`};function De(e){return e.replace(/[\u200b\u00ad]/g,``).replace(/[\r\n\s\t]+/g,` `).trim()}function _(e){return{raw:e,normalized:De(e)}}var v=class e{static parse(t,n,r){try{return new e(t.value)._parse()}catch(e){if(e instanceof y){let i=n.prettyErrors===!1?e.message:`${e.message}:\n\n${t.value}\n${` `.repeat(e.pos)}^\n`;return r.push({message:i,range:[n.lineCounter.linePos(t.range[0]),n.lineCounter.linePos(t.range[0]+e.pos)]}),null}throw e}}constructor(e){m(this,`_input`,void 0),m(this,`_pos`,void 0),m(this,`_length`,void 0),this._input=e,this._pos=0,this._length=e.length}_peek(){return this._input[this._pos]||``}_next(){return this._pos<this._length?this._input[this._pos++]:null}_eof(){return this._pos>=this._length}_isWhitespace(){return!this._eof()&&/\s/.test(this._peek())}_skipWhitespace(){for(;this._isWhitespace();)this._pos++}_readIdentifier(e){this._eof()&&this._throwError(`Unexpected end of input when expecting ${e}`);let t=this._pos;for(;!this._eof()&&/[a-zA-Z]/.test(this._peek());)this._pos++;return this._input.slice(t,this._pos)}_readString(){let e=``,t=!1;for(;!this._eof();){let n=this._next();if(t)e+=n,t=!1;else if(n===`\\`)t=!0;else if(n===`"`)return e;else e+=n}this._throwError(`Unterminated string`)}_throwError(e,t=0){throw new y(e,t||this._pos)}_readRegex(){let e=``,t=!1,n=!1;for(;!this._eof();){let r=this._next();if(t)e+=r,t=!1;else if(r===`\\`)t=!0,e+=r;else if(r===`/`&&!n)return{pattern:e};else r===`[`?(n=!0,e+=r):r===`]`&&n?(e+=r,n=!1):e+=r}this._throwError(`Unterminated regex`)}_readStringOrRegex(){let e=this._peek();return e===`"`?(this._next(),De(this._readString())):e===`/`?(this._next(),this._readRegex()):null}_readAttributes(e){let t=this._pos;for(;this._skipWhitespace(),this._peek()===`[`;){this._next(),this._skipWhitespace(),t=this._pos;let n=this._readIdentifier(`attribute`);this._skipWhitespace();let r=``;if(this._peek()===`=`)for(this._next(),this._skipWhitespace(),t=this._pos;this._peek()!==`]`&&!this._isWhitespace()&&!this._eof();)r+=this._next();this._skipWhitespace(),this._peek()!==`]`&&this._throwError(`Expected ]`),this._next(),this._applyAttribute(e,n,r||`true`,t)}}_parse(){this._skipWhitespace();let e=this._readIdentifier(`role`);e===`fragment`&&this._throwError(`Invalid role "fragment"`),this._skipWhitespace();let t={kind:`role`,role:e,name:this._readStringOrRegex()||void 0};return this._readAttributes(t),this._skipWhitespace(),this._eof()||this._throwError(`Unexpected input`),t}_applyAttribute(e,t,n,r){if(t===`checked`){this._assert(n===`true`||n===`false`||n===`mixed`,`Value of "checked" attribute must be a boolean or "mixed"`,r),e.checked=n===`true`?!0:n===`false`?!1:`mixed`;return}if(t===`disabled`){this._assert(n===`true`||n===`false`,`Value of "disabled" attribute must be a boolean`,r),e.disabled=n===`true`;return}if(t===`expanded`){this._assert(n===`true`||n===`false`,`Value of "expanded" attribute must be a boolean`,r),e.expanded=n===`true`;return}if(t===`active`){this._assert(n===`true`||n===`false`,`Value of "active" attribute must be a boolean`,r),e.active=n===`true`;return}if(t===`level`){this._assert(!Number.isNaN(Number(n)),`Value of "level" attribute must be a number`,r),e.level=Number(n);return}if(t===`pressed`){this._assert(n===`true`||n===`false`||n===`mixed`,`Value of "pressed" attribute must be a boolean or "mixed"`,r),e.pressed=n===`true`?!0:n===`false`?!1:`mixed`;return}if(t===`selected`){this._assert(n===`true`||n===`false`,`Value of "selected" attribute must be a boolean`,r),e.selected=n===`true`;return}this._assert(!1,`Unsupported attribute [${t}]`,r)}_assert(e,t,n){e||this._throwError(t||`Assertion error`,n)}},y=class extends Error{constructor(e,t){super(e),m(this,`pos`,void 0),this.pos=t}};function b(e,t){return t?e?typeof t==`string`?e===t:!!e.match(new RegExp(t.pattern)):!1:!0}function x(e,t){if(!t?.normalized)return!0;if(!e)return!1;if(e===t.normalized||e===t.raw)return!0;let n=C(t);return n?!!e.match(n):!1}const S=Symbol(`cachedRegex`);function C(e){if(e[S]!==void 0)return e[S];let{raw:t}=e,n=t.startsWith(`/`)&&t.endsWith(`/`)&&t.length>1,r;try{r=n?new RegExp(t.slice(1,-1)):null}catch{r=null}return e[S]=r,r}function w(e,t,n){if(typeof e==`string`&&t.kind===`text`)return x(e,t.text);if(typeof e!=`object`||!e||t.kind!==`role`||t.role!==`fragment`&&t.role!==e.role||t.checked!==void 0&&t.checked!==e.checked||t.disabled!==void 0&&t.disabled!==e.disabled||t.expanded!==void 0&&t.expanded!==e.expanded||t.level!==void 0&&t.level!==e.level||t.pressed!==void 0&&t.pressed!==e.pressed||t.selected!==void 0&&t.selected!==e.selected||!b(e.name,t.name))return!1;if(t.props){for(let[n,r]of Object.entries(t.props))if(!x(e.props[n]||``,r))return!1}return t.containerMode===`contain`?E(e.children||[],t.children||[]):t.containerMode===`equal`?T(e.children||[],t.children||[],!1):t.containerMode===`deep-equal`||n?T(e.children||[],t.children||[],!0):E(e.children||[],t.children||[])}function T(e,t,n){if(t.length!==e.length)return!1;for(let r=0;r<t.length;++r)if(!w(e[r],t[r],n))return!1;return!0}function E(e,t){if(t.length>e.length)return!1;let n=e.slice(),r=t.slice();for(let e of r){let t=n.shift();for(;t&&!w(t,e,!1);)t=n.shift();if(!t)return!1}return!0}var Oe=Ce({LineCounter:()=>ke,Scalar:()=>D,YAMLError:()=>A,YAMLMap:()=>O,YAMLSeq:()=>k,parseDocument:()=>Ae}),D=class{constructor(e,t=[0,0,0]){m(this,`value`,void 0),m(this,`range`,void 0),this.value=e,this.range=t}},O=class{constructor(e=[0,0,0]){m(this,`items`,void 0),m(this,`range`,void 0),this.items=[],this.range=e}},k=class{constructor(e=[0,0,0]){m(this,`items`,void 0),m(this,`range`,void 0),this.items=[],this.range=e}},ke=class{constructor(){m(this,`lineStarts`,[0])}addNewLine(e){e>this.lineStarts[this.lineStarts.length-1]&&this.lineStarts.push(e)}linePos(e){let t=0,n=this.lineStarts.length-1;for(;t<n;){let r=t+n+1>>1;this.lineStarts[r]<=e?t=r:n=r-1}return{line:t+1,col:e-this.lineStarts[t]+1}}},A=class extends Error{constructor(e,t){super(e),m(this,`pos`,void 0),this.pos=t}};function Ae(e,t={}){let n=t.lineCounter,r=[];if(n)for(let t=0;t<e.length;t++)e[t]===`
|
|
2
2
|
`&&n.addNewLine(t+1);try{return{contents:new je(e,r).parseRoot(),errors:r}}catch(e){if(e instanceof A)return r.push(e),{contents:null,errors:r};throw e}}var je=class{constructor(e,t){m(this,`lines`,void 0),m(this,`pos`,void 0),m(this,`text`,void 0),m(this,`errors`,void 0),this.text=e,this.errors=t,this.lines=[],this.pos=0;let n=0,r=e.split(`
|
|
3
3
|
`);for(let e of r){let t=e.replace(/\r$/,``),r=t.replace(/^\s+/,``),i=t.length-r.length;this.lines.push({indent:i,content:r,offset:n+i,lineOffset:n,raw:t}),n+=e.length+1}for(;this.lines.length>0&&this.lines[this.lines.length-1].content===``;)this.lines.pop()}parseRoot(){if(this.lines.length===0)return null;let e=this.parseNode(0);if(this.skipEmpty(),this.pos<this.lines.length){let e=this.currentLine();this.addError(`Unexpected scalar at node end`,e.offset)}return e}currentLine(){return this.lines[this.pos]}parseNode(e){this.skipEmpty();let t=this.currentLine();return!t||t.indent<e?null:t.content.startsWith(`- `)||t.content===`-`?this.parseSequence(t.indent):this.isMapEntry(t.content)?this.parseMap(t.indent):(this.pos++,this.parseScalarValue(t.content,t.offset,t))}parseSequence(e){let t=this.currentLine(),n=new k([t.offset-t.indent,0,0]),r=t.offset;for(;this.pos<this.lines.length;){this.skipEmpty();let t=this.currentLine();if(!t||t.indent<e)break;if(t.indent>e){this.addError(`Bad indentation of a sequence entry`,t.offset);break}if(!t.content.startsWith(`- `)&&t.content!==`-`)break;let i=t.content===`-`?1:2,a=t.content.slice(i),o=t.offset+i;if(this.pos++,a===``||a.trim()===``){let t=this.parseNode(e+1);t&&(n.items.push(t),r=this.peekLastOffset())}else if(this.isMapEntry(a)){let s=this.parseInlineMap(a,o,e+i,t);n.items.push(s),r=s.range[2]}else{let e=this.parseScalarValue(a,o,t);n.items.push(e),r=e.range[2]}}return n.range[1]=r,n.range[2]=r,n}parseMap(e){let t=this.currentLine(),n=new O([t.offset-t.indent,0,0]),r=t.offset;for(;this.pos<this.lines.length;){this.skipEmpty();let t=this.currentLine();if(!t||t.indent<e)break;if(t.indent>e){this.addError(`Bad indentation of a mapping entry`,t.offset);break}if(!this.isMapEntry(t.content))break;let{key:i,valueStr:a,colonOffset:o,valueOffset:s}=this.splitMapEntry(t.content,t.offset),c=new D(i,[t.offset,t.offset+i.length,o]);this.pos++;let l;l=a===``?this.parseMapValue(e,o):this.parseScalarValue(a.trim(),s,t),n.items.push({key:c,value:l}),r=l?this.getNodeEnd(l):o+1}return n.range[1]=r,n.range[2]=r,n}parseInlineMap(e,t,n,r){let i=new O([t,0,0]),a=t,{key:o,valueStr:s,colonOffset:c,valueOffset:l}=this.splitMapEntry(e,t),u=new D(o,[t,t+o.length,c]),d;for(d=s===``?this.parseMapValue(n,c):this.parseScalarValue(s.trim(),l,r),i.items.push({key:u,value:d}),a=d?this.getNodeEnd(d):c+1;this.pos<this.lines.length;){this.skipEmpty();let e=this.currentLine();if(!e||e.indent<n||e.indent>n||!this.isMapEntry(e.content)||e.content.startsWith(`- `))break;let t=this.splitMapEntry(e.content,e.offset),r=new D(t.key,[e.offset,e.offset+t.key.length,t.colonOffset]);this.pos++;let o;o=t.valueStr===``?this.parseMapValue(n,t.colonOffset):this.parseScalarValue(t.valueStr.trim(),t.valueOffset,e),i.items.push({key:r,value:o}),a=o?this.getNodeEnd(o):t.colonOffset+1}return i.range[1]=a,i.range[2]=a,i}parseMapValue(e,t){this.skipEmpty();let n=this.currentLine();return!n||n.indent<e?new D(null,[t+1,t+1,t+1]):n.indent===e&&(n.content.startsWith(`- `)||n.content===`-`)?this.parseNode(e):n.indent>e?this.parseNode(e+1):new D(null,[t+1,t+1,t+1])}getNodeEnd(e){return e.range[2]}peekLastOffset(){if(this.pos>0&&this.pos<=this.lines.length){let e=this.lines[this.pos-1];return e.lineOffset+e.raw.length}return this.text.length}parseScalarValue(e,t,n){let r=e.trim(),i=t+e.indexOf(r),a=i+r.length,o=n.lineOffset+n.raw.length;return r.startsWith(`"`)?this.parseQuotedScalar(r,i,o):r===`true`||r===`false`?new D(r===`true`,[i,a,o]):r===`null`||r===`~`?new D(null,[i,a,o]):r!==``&&Me(r)?new D(Number(r),[i,a,o]):new D(r,[i,a,o])}parseQuotedScalar(e,t,n){let r=``,i=1;for(;i<e.length;){let a=e[i];if(a===`\\`){if(i++,i>=e.length){this.addError(`Unterminated double-quoted string`,t+i);break}let n=e[i];switch(n){case`n`:r+=`
|
|
4
4
|
`;break;case`t`:r+=` `;break;case`r`:r+=`\r`;break;case`"`:r+=`"`;break;case`\\`:r+=`\\`;break;case`/`:r+=`/`;break;default:r+=n}}else if(a===`"`){let e=t+i+1;return new D(r,[t,e,n])}else r+=a;i++}return this.addError(`Unterminated double-quoted string`,t),new D(r,[t,t+e.length,n])}skipEmpty(){for(;this.pos<this.lines.length&&this.lines[this.pos].content===``;)this.pos++}isMapEntry(e){return this.findMapColon(e)>=0}findMapColon(e){let t=!1,n=!1;for(let r=0;r<e.length;r++){let i=e[r];if(n){n=!1;continue}if(i===`\\`&&t){n=!0;continue}if(i===`"`){t=!t;continue}if(!t&&i===`:`&&(r+1>=e.length||e[r+1]===` `))return r}return-1}splitMapEntry(e,t){let n=this.findMapColon(e),r=e.slice(0,n).trim(),i=t+n,a=e.slice(n+1),o=a.trimStart(),s=i+1+(a.length-a.trimStart().length);return r.startsWith(`"`)&&r.endsWith(`"`)?{key:r.slice(1,-1),valueStr:o,colonOffset:i,valueOffset:s}:{key:r,valueStr:o,colonOffset:i,valueOffset:s}}addError(e,t){this.errors.push(new A(e,[t,t+1]))}};function Me(e){return e===``||e===`-`||e===`+`?!1:/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(e)}function j(e){return Ne(e)?`"`+e.replace(/[\\"\x00-\x1f\x7f-\x9f]/g,e=>{switch(e){case`\\`:return`\\\\`;case`"`:return`\\"`;case`\b`:return`\\b`;case`\f`:return`\\f`;case`
|
|
@@ -30,5 +30,5 @@ import{Snapshots as e,recordArtifact as t,expect as n,chai as r}from"vitest";imp
|
|
|
30
30
|
`)}}}function pn(e){let t=``;for(let n of e){if(t&&t!==n.type)throw Error(`Multiple form elements with the same name must be of the same type`);t=n.type}switch(t){case`radio`:{let t=e.find(e=>e.checked);return t?t.value:void 0}case`checkbox`:return e.filter(e=>e.checked).map(e=>e.value);default:return e.map(e=>e.value)}}function mn(e,t){let n=[...e.querySelectorAll(`[name="${me(t)}"]`)];if(n.length!==0)switch(n.length){case 1:return mt(n[0]);default:return pn(n)}}function hn(e){return/\[\]$/.test(e)?e.slice(0,-2):e}function gn(e){let t={};for(let n of e.elements){if(!(`name`in n))continue;let r=n.name;t[hn(r)]=mn(e,r)}return t}function _n(e,t){let n=H(e,_n,this);a();let r=c(n);return o(),{pass:r===t,message:()=>{let e=this.isNot?`not to`:`to`;return U(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveRole`,`element`,``),`Expected element ${e} have role`,t,`Received`,r)}}}function vn(e,t){let n=H(e,vn,this),r=t!==void 0;if(r&&typeof t!=`string`)throw Error(`expected selection must be a string or undefined`);let i=yn(n);return{pass:r?this.equals(i,t,[q,...this.customTesters]):!!i,message:()=>{let e=this.isNot?`not to`:`to`,n=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveSelection`,`element`,t);return U(this,n,`Expected the element ${e} have selection`,r?t:`(any)`,`Received`,i)}}}function yn(e){let t=e.ownerDocument.getSelection();if(!t)return``;if([`INPUT`,`TEXTAREA`].includes(G(e))){let t=e;return[`radio`,`checkbox`].includes(t.type)||t.selectionStart==null||t.selectionEnd==null?``:t.value.toString().substring(t.selectionStart,t.selectionEnd)}if(t.anchorNode===null||t.focusNode===null)return``;let n=t.getRangeAt(0),r=e.ownerDocument.createRange();if(t.containsNode(e,!1))r.selectNodeContents(e),t.removeAllRanges(),t.addRange(r);else if(!(e.contains(t.anchorNode)&&e.contains(t.focusNode))){let i=e===n.startContainer||e.contains(n.startContainer),a=e===n.endContainer||e.contains(n.endContainer);t.removeAllRanges(),(i||a)&&(r.selectNodeContents(e),i&&r.setStart(n.startContainer,n.startOffset),a&&r.setEnd(n.endContainer,n.endOffset),t.addRange(r))}let i=t.toString();return t.removeAllRanges(),t.addRange(n),i}const Z=xe.config.browser.name,Q=new Set(`backgroundPosition.background-position.bottom.left.right.top.height.width.margin-bottom.marginBottom.margin-left.marginLeft.margin-right.marginRight.margin-top.marginTop.min-height.minHeight.min-width.minWidth.padding-bottom.padding-left.padding-right.padding-top.text-indent.paddingBottom.paddingLeft.paddingRight.paddingTop.textIndent`.split(`.`));function bn(e,t){let n=H(e,bn,this),{getComputedStyle:r}=n.ownerDocument.defaultView,i=typeof t==`object`?xn(t):Sn(t),a=r(n),o=new Set(Array.from(n.style));return{pass:wn(i,n,a,o),message:()=>{let e=`${this.isNot?`.not`:``}.toHaveStyle`,t=new Set(Object.keys(i)),r=Cn(Array.from(a).filter(e=>t.has(e)).reduce((e,t)=>(e[t]=(o.has(t)&&Q.has(t)?n.style:a)[t],e),{})),s=r===``?`Expected styles could not be parsed by the browser. Did you make a typo?`:this.utils.diff(Cn(i),r);return[this.utils.matcherHint(e,`element`,``),s].join(`
|
|
31
31
|
|
|
32
32
|
`)}}}function xn(e){let t=Z===`chrome`||Z===`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=(Q.has(e)?n.style:a)[e];t!=null&&(i[e]=t)}),n.remove(),i}function Sn(e){let t=Z===`chrome`||Z===`chromium`||Z===`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]=Q.has(t)?n.style.getPropertyValue(t):r.getPropertyValue(t),e),{});return n.remove(),i}function Cn(e){return Object.keys(e).sort().map(t=>`${t}: ${e[t]};`).join(`
|
|
33
|
-
`)}function wn(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)&&Q.has(i)?t.style:n;return o[e]===a||o.getPropertyValue(e)===a})}):!1}function Tn(e,t,n={normalizeWhitespace:!0}){let r=at(e,Tn,this),i=n.normalizeWhitespace?yt(r.textContent||``):(r.textContent||``).replace(/\u00A0/g,` `),a=
|
|
34
|
-
`),meta:{outcome:d.outcome}}}function
|
|
33
|
+
`)}function wn(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)&&Q.has(i)?t.style:n;return o[e]===a||o.getPropertyValue(e)===a})}):!1}function Tn(e,t,n={normalizeWhitespace:!0}){let r=at(e,Tn,this),i=n.normalizeWhitespace?yt(r.textContent||``):(r.textContent||``).replace(/\u00A0/g,` `),a=String(t);return{pass:i===a,message:()=>{let e=this.isNot?`not to`:`to`;return U(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveTextContent`,`element`,``),`Expected element ${e} have text content`,a,`Received`,i)}}}function En(e,t){let n=H(e,En,this);if(K(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=mt(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,[q,...this.customTesters]):!!r,message:()=>{let e=this.isNot?`not to`:`to`,n=this.utils.matcherHint(`${this.isNot?`.not`:``}.toHaveValue`,`element`,t);return U(this,n,`Expected the element ${e} have value`,i?a:`(any)`,`Received`,o)}}}const Dn=new Map([]);async function On(e,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=Dn.get(i);a===void 0&&(a={current:0},Dn.set(i,a)),a.current+=1;let o=typeof n==`string`?n:`${this.currentTestName} ${a.current}`,s=kn(e),[c,...l]=await Promise.all([s?void 0:he(e,r),...r.screenshotOptions&&`mask`in r.screenshotOptions?r.screenshotOptions.mask.map(e=>he(e,r)):[]]),u=r.screenshotOptions&&`mask`in r.screenshotOptions?{...r,screenshotOptions:{...r.screenshotOptions,mask:l}}:r,d=await h().commands.triggerCommand(`__vitest_screenshotMatcher`,[o,this.currentTestName,{element:c,target:s?`page`:`element`,...u}]);if(d.pass===!1){let e=[];d.reference&&e.push({name:`reference`,...d.reference}),d.actual&&e.push({name:`actual`,...d.actual}),d.diff&&e.push({name:`diff`,...d.diff}),e.length>0&&await t(this.task,{type:`internal:toMatchScreenshot`,kind:`visual-regression`,message:d.message,attachments:e})}return{pass:d.pass,message:()=>d.pass?``:[this.utils.matcherHint(`toMatchScreenshot`,s?`page`:`element`,``),``,d.message,d.reference?`\nReference screenshot:\n ${this.utils.EXPECTED_COLOR(d.reference.path)}`:null,d.actual?`\nActual screenshot:\n ${this.utils.RECEIVED_COLOR(d.actual.path)}`:null,d.diff?this.utils.DIM_COLOR(`\nDiff image:\n ${d.diff.path}`):null,``].filter(e=>e!==null).join(`
|
|
34
|
+
`),meta:{outcome:d.outcome}}}function kn(e){return!!e&&typeof e==`object`&&`viewport`in e&&typeof e.viewport==`function`}function $(e,t,n={normalizeWhitespace:!0}){let r=at(e,$,this),i=n.normalizeWhitespace?yt(r.textContent||``):(r.textContent||``).replace(/\u00A0/g,` `),a=i!==``&&t===``;return{pass:!a&&bt(i,t),message:()=>{let e=this.isNot?`not to`:`to`;return U(this,this.utils.matcherHint(`${this.isNot?`.not`:``}.toMatchTextContent`,`element`,``),a?`Checking with empty string will always match, use .toBeEmptyDOMElement() instead`:`Expected element ${e} match text content`,t,`Received`,i)}}}const An={toBeDisabled:Et,toBeEnabled:Dt,toBeEmptyDOMElement:wt,toBeInTheDocument:kt,toBeInViewport:Ft,toBeInvalid:J,toBeRequired:Kt,toBeValid:Pt,toBeVisible:qt,toContainElement:Y,toContainHTML:Zt,toHaveAccessibleDescription:Qt,toHaveAccessibleErrorMessage:$t,toHaveAccessibleName:X,toHaveAttribute:en,toHaveClass:rn,toHaveFocus:dn,toHaveFormValues:fn,toHaveStyle:bn,toHaveTextContent:Tn,toMatchTextContent:$,toHaveValue:En,toHaveDisplayValue:cn,toBeChecked:St,toBePartiallyChecked:Lt,toHaveRole:_n,toHaveSelection:vn,toMatchScreenshot:On},jn=Symbol.for(`$$vitest:locator`);function Mn(e,t){if(e!=null&&!(e instanceof HTMLElement)&&!(e instanceof SVGElement)&&!(jn in e))throw Error(`Invalid element or locator: ${e}. Expected an instance of HTMLElement, SVGElement or Locator, received ${i(e)}`);let a=ge(t),o=a?.timeout?_e()+a.timeout:void 0,s=n.poll(async function(){if(e instanceof Element||e==null)return e;let t=r.util.flag(this,`negate`),n=r.util.flag(this,`_name`);return t&&n===`toBeInTheDocument`?e.query():n===`toHaveLength`?e.elements():e.findElement({...a,timeout:o?Math.max(o-_e(),0):void 0})},a);r.util.flag(s,`_poll.element`,!0);let c=ve().current,l=!!c&&h().activeTraceTaskIds.has(c.id),u=!!c&&h().browserTraceAttempts.has(c.id);if(c&&(l||u)){let t=Error(`__vitest_mark_trace__`),n=u?ye():void 0,i=()=>!e||e instanceof Element?void 0:e.serialize(),a=(e,t)=>{let n=r.util.flag(e,`negate`),i=r.util.flag(e,`_name`)||`<unknown>`,a=`${n?`not.`:``}${i}`;return t===`fail`?`${a} [ERROR]`:a};r.util.flag(s,`_poll.onStart`,async e=>{u&&await be(c,{name:a(e.assertion),kind:`expect`,range:{id:n,phase:`start`},element:i(),stack:t.stack})}),r.util.flag(s,`_poll.onSettled`,async e=>{let r=a(e.assertion,e.status);u&&await be(c,{name:r,kind:`expect`,range:{id:n,phase:`end`},status:e.status,element:i(),stack:t.stack}),l&&await h().commands.triggerCommand(`__vitest_markTrace`,[{name:r,element:i(),stack:t.stack}],t)})}return s}n.extend(An),n.extend(nt),n.element=Mn;
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { isValidApiRequest, isFileServingAllowed, distDir, rolldownVersion, reso
|
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import fs, { readFileSync, createReadStream, promises, existsSync } from 'node:fs';
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
|
+
import { distClientRoot } from '@vitest/ui';
|
|
8
9
|
import { slash as slash$1, toArray, deepMerge } from '@vitest/utils/helpers';
|
|
9
10
|
import MagicString from 'magic-string';
|
|
10
11
|
import sirv from 'sirv';
|
|
@@ -18,7 +19,7 @@ import { PNG } from 'pngjs';
|
|
|
18
19
|
import { diff } from '@blazediff/core';
|
|
19
20
|
import { WebSocketServer } from 'ws';
|
|
20
21
|
|
|
21
|
-
var version = "5.0.0-beta.
|
|
22
|
+
var version = "5.0.0-beta.5";
|
|
22
23
|
|
|
23
24
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
24
25
|
function normalizeWindowsPath(input = "") {
|
|
@@ -676,21 +677,13 @@ function slash(path) {
|
|
|
676
677
|
}
|
|
677
678
|
|
|
678
679
|
async function resolveOrchestrator(globalServer, url, res) {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
if (!
|
|
682
|
-
const contexts = [...globalServer.children].flatMap((p) => [...p.state.orchestrators.keys()]);
|
|
683
|
-
sessionId = contexts.at(-1) ?? "none";
|
|
684
|
-
}
|
|
685
|
-
// it's ok to not have a session here, especially in the preview provider
|
|
686
|
-
// because the user could refresh the page which would remove the session id from the url
|
|
687
|
-
const session = globalServer.vitest._browserSessions.getSession(sessionId);
|
|
688
|
-
const browserProject = session?.project.browser || [...globalServer.children][0];
|
|
689
|
-
if (!browserProject) {
|
|
680
|
+
const sessionId = url.searchParams.get("sessionId");
|
|
681
|
+
const session = sessionId && globalServer.vitest._browserSessions.getSession(sessionId);
|
|
682
|
+
if (!session) {
|
|
690
683
|
return;
|
|
691
684
|
}
|
|
692
|
-
|
|
693
|
-
if (
|
|
685
|
+
const browserProject = session.project.browser;
|
|
686
|
+
if (!browserProject) {
|
|
694
687
|
return;
|
|
695
688
|
}
|
|
696
689
|
const injectorJs = typeof globalServer.injectorJs === "string" ? globalServer.injectorJs : await globalServer.injectorJs;
|
|
@@ -714,7 +707,7 @@ async function resolveOrchestrator(globalServer, url, res) {
|
|
|
714
707
|
for (const attr in script.attrs || {}) {
|
|
715
708
|
html += `${attr}="${script.attrs[attr]}" `;
|
|
716
709
|
}
|
|
717
|
-
html += `>${script.children}<\/script>`;
|
|
710
|
+
html += `>${escapeInlineScript(typeof script.children === "string" ? script.children : "")}<\/script>`;
|
|
718
711
|
return html;
|
|
719
712
|
}).join("\n");
|
|
720
713
|
}
|
|
@@ -735,11 +728,14 @@ async function resolveOrchestrator(globalServer, url, res) {
|
|
|
735
728
|
__VITEST_FAVICON__: globalServer.faviconUrl,
|
|
736
729
|
__VITEST_TITLE__: "Vitest Browser Runner",
|
|
737
730
|
__VITEST_SCRIPTS__: globalServer.orchestratorScripts,
|
|
738
|
-
__VITEST_INJECTOR__: `<script type="module">${injector}<\/script>`,
|
|
731
|
+
__VITEST_INJECTOR__: `<script type="module">${escapeInlineScript(injector)}<\/script>`,
|
|
739
732
|
__VITEST_ERROR_CATCHER__: `<script type="module" src="${globalServer.errorCatcherUrl}"><\/script>`,
|
|
740
733
|
__VITEST_SESSION_ID__: JSON.stringify(sessionId)
|
|
741
734
|
});
|
|
742
735
|
}
|
|
736
|
+
function escapeInlineScript(content) {
|
|
737
|
+
return content.replace(/<!--/g, "<\\!--").replace(/<\/(script)/gi, "</\\$1");
|
|
738
|
+
}
|
|
743
739
|
|
|
744
740
|
function disableCache(res) {
|
|
745
741
|
res.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate");
|
|
@@ -765,7 +761,10 @@ function createOrchestratorMiddleware(parentServer) {
|
|
|
765
761
|
allowIframes(res);
|
|
766
762
|
res.write(html, "utf-8");
|
|
767
763
|
res.end();
|
|
764
|
+
return;
|
|
768
765
|
}
|
|
766
|
+
res.statusCode = 404;
|
|
767
|
+
res.end("Not found");
|
|
769
768
|
};
|
|
770
769
|
}
|
|
771
770
|
|
|
@@ -776,8 +775,8 @@ async function resolveTester(globalServer, url, res, next) {
|
|
|
776
775
|
// but keep the rest of the CSP
|
|
777
776
|
res.setHeader("Content-Security-Policy", csp.replace(/frame-ancestors [^;]+/, "frame-ancestors *"));
|
|
778
777
|
}
|
|
779
|
-
const sessionId = url.searchParams.get("sessionId")
|
|
780
|
-
const session = globalServer.vitest._browserSessions.getSession(sessionId);
|
|
778
|
+
const sessionId = url.searchParams.get("sessionId");
|
|
779
|
+
const session = sessionId && globalServer.vitest._browserSessions.getSession(sessionId);
|
|
781
780
|
if (!session) {
|
|
782
781
|
res.statusCode = 400;
|
|
783
782
|
res.end("Invalid session ID");
|
|
@@ -1026,7 +1025,14 @@ var BrowserPlugin = (parentServer, base = "/") => {
|
|
|
1026
1025
|
// this plugin can be used in different projects, but all of them
|
|
1027
1026
|
// have the same `include` pattern, so it doesn't matter which project we use
|
|
1028
1027
|
const project = parentServer.project;
|
|
1029
|
-
|
|
1028
|
+
// only glob benchmarks when a browser-enabled bench project exists in
|
|
1029
|
+
// the workspace — keeps the optimizeDeps entries symmetrical across
|
|
1030
|
+
// the test/bench project clones so the optimizer doesn't re-scan when
|
|
1031
|
+
// the user switches modes
|
|
1032
|
+
const hasBrowserBenchProject = parentServer.vitest.projects.some((p) => p.config.browser.enabled && p.config.benchmark.enabled);
|
|
1033
|
+
const benchInclude = hasBrowserBenchProject ? project.config.benchmark.include : [];
|
|
1034
|
+
const dir = project.config.dir || project.config.root;
|
|
1035
|
+
const [{ testFiles: browserTestFiles }, browserBenchFiles] = await Promise.all([project.globTestFiles(), benchInclude.length > 0 ? project.globFiles(benchInclude, project.config.benchmark.exclude ?? project.config.exclude, dir) : []]);
|
|
1030
1036
|
const setupFiles = toArray(project.config.setupFiles);
|
|
1031
1037
|
// replace env values - cannot be reassign at runtime
|
|
1032
1038
|
const define = {};
|
|
@@ -1035,7 +1041,7 @@ var BrowserPlugin = (parentServer, base = "/") => {
|
|
|
1035
1041
|
define[`import.meta.env.${env}`] = stringValue;
|
|
1036
1042
|
}
|
|
1037
1043
|
const entries = [
|
|
1038
|
-
...browserTestFiles,
|
|
1044
|
+
...new Set([...browserTestFiles, ...browserBenchFiles]),
|
|
1039
1045
|
...setupFiles,
|
|
1040
1046
|
resolve(distDir, "index.js"),
|
|
1041
1047
|
resolve(distDir, "browser.js"),
|
|
@@ -1053,7 +1059,6 @@ var BrowserPlugin = (parentServer, base = "/") => {
|
|
|
1053
1059
|
"@vitest/browser/client",
|
|
1054
1060
|
"@vitest/utils",
|
|
1055
1061
|
"@vitest/utils/source-map",
|
|
1056
|
-
"@vitest/runner",
|
|
1057
1062
|
"@vitest/spy",
|
|
1058
1063
|
"@vitest/utils/error",
|
|
1059
1064
|
"std-env",
|
|
@@ -1152,7 +1157,7 @@ var BrowserPlugin = (parentServer, base = "/") => {
|
|
|
1152
1157
|
{
|
|
1153
1158
|
name: "vitest:browser:assets",
|
|
1154
1159
|
configureServer(server) {
|
|
1155
|
-
server.middlewares.use("/__vitest__", sirv(
|
|
1160
|
+
server.middlewares.use("/__vitest__", sirv(distClientRoot));
|
|
1156
1161
|
},
|
|
1157
1162
|
resolveId(id) {
|
|
1158
1163
|
if (id.startsWith("/__vitest_browser__/")) {
|
|
@@ -1434,6 +1439,19 @@ class BrowserServerCDPHandler {
|
|
|
1434
1439
|
}
|
|
1435
1440
|
}
|
|
1436
1441
|
|
|
1442
|
+
const _startV8Coverage = async (context) => {
|
|
1443
|
+
const session = await context.__ensureCDPHandler();
|
|
1444
|
+
await session.send("Profiler.enable");
|
|
1445
|
+
await session.send("Profiler.startPreciseCoverage", {
|
|
1446
|
+
callCount: true,
|
|
1447
|
+
detailed: true
|
|
1448
|
+
});
|
|
1449
|
+
};
|
|
1450
|
+
const _takeV8Coverage = async (context) => {
|
|
1451
|
+
const session = await context.__ensureCDPHandler();
|
|
1452
|
+
return session.send("Profiler.takePreciseCoverage");
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1437
1455
|
const types = {
|
|
1438
1456
|
'application/andrew-inset': ['ez'],
|
|
1439
1457
|
'application/appinstaller': ['appinstaller'],
|
|
@@ -2580,6 +2598,8 @@ var builtinCommands = {
|
|
|
2580
2598
|
readFile,
|
|
2581
2599
|
removeFile,
|
|
2582
2600
|
writeFile,
|
|
2601
|
+
__vitest_startV8Coverage: _startV8Coverage,
|
|
2602
|
+
__vitest_takeV8Coverage: _takeV8Coverage,
|
|
2583
2603
|
__vitest_markTrace: _markTrace,
|
|
2584
2604
|
__vitest_groupTraceStart: _groupTraceStart,
|
|
2585
2605
|
__vitest_groupTraceEnd: _groupTraceEnd,
|
|
@@ -2717,7 +2737,6 @@ class ParentBrowserProject {
|
|
|
2717
2737
|
this.sourceMapCache.set(id, extracted?.map);
|
|
2718
2738
|
return extracted?.map;
|
|
2719
2739
|
}
|
|
2720
|
-
this.sourceMapCache.set(id, result?.map);
|
|
2721
2740
|
return result?.map;
|
|
2722
2741
|
},
|
|
2723
2742
|
getUrlId: (id) => {
|
|
@@ -2756,7 +2775,7 @@ class ParentBrowserProject {
|
|
|
2756
2775
|
this.manifest = (async () => {
|
|
2757
2776
|
return JSON.parse(await readFile$1(`${distRoot}/client/.vite/manifest.json`, "utf8"));
|
|
2758
2777
|
})().then((manifest) => this.manifest = manifest);
|
|
2759
|
-
this.orchestratorHtml = (project.config.browser.ui ? readFile$1(resolve(
|
|
2778
|
+
this.orchestratorHtml = (project.config.browser.ui ? readFile$1(resolve(distClientRoot, "index.html"), "utf8") : readFile$1(resolve(distRoot, "client/orchestrator.html"), "utf8")).then((html) => this.orchestratorHtml = html);
|
|
2760
2779
|
this.injectorJs = readFile$1(resolve(distRoot, "client/esm-client-injector.js"), "utf8").then((js) => this.injectorJs = js);
|
|
2761
2780
|
this.errorCatcherUrl = join("/@fs/", resolve(distRoot, "client/error-catcher.js"));
|
|
2762
2781
|
this.matchersUrl = join("/@fs/", distRoot, "expect-element.js");
|
|
@@ -3095,7 +3114,8 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3095
3114
|
}
|
|
3096
3115
|
if (type === "orchestrator") {
|
|
3097
3116
|
const session = sessions.getSession(sessionId);
|
|
3098
|
-
// it's possible the session was already resolved by the preview provider
|
|
3117
|
+
// it's possible the session was already resolved by the preview provider,
|
|
3118
|
+
// but we still mark the websocket connection when the page reconnects
|
|
3099
3119
|
session?.connected();
|
|
3100
3120
|
}
|
|
3101
3121
|
const project = vitest.getProjectByName(projectName);
|
|
@@ -3104,7 +3124,7 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3104
3124
|
}
|
|
3105
3125
|
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
3106
3126
|
wss.emit("connection", ws, request);
|
|
3107
|
-
const { rpc, offCancel } = setupClient(project, rpcId, ws);
|
|
3127
|
+
const { rpc, offCancel } = setupClient(project, rpcId, ws, { sessionId });
|
|
3108
3128
|
const state = project.browser.state;
|
|
3109
3129
|
const clients = type === "tester" ? state.testers : state.orchestrators;
|
|
3110
3130
|
clients.set(rpcId, rpc);
|
|
@@ -3135,10 +3155,22 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3135
3155
|
function canWrite(project) {
|
|
3136
3156
|
return project.config.browser.api.allowWrite && project.vitest.config.browser.api.allowWrite && project.config.api.allowWrite && project.vitest.config.api.allowWrite;
|
|
3137
3157
|
}
|
|
3138
|
-
function
|
|
3158
|
+
function isCdpAllowed(project) {
|
|
3159
|
+
return project.config.api.allowExec && project.config.browser.api.allowExec && project.vitest.config.api.allowExec && project.vitest.config.browser.api.allowExec && project.config.api.allowWrite && project.config.browser.api.allowWrite && project.vitest.config.api.allowWrite && project.vitest.config.browser.api.allowWrite;
|
|
3160
|
+
}
|
|
3161
|
+
function assertCdpAllowed(project) {
|
|
3162
|
+
if (!isCdpAllowed(project)) {
|
|
3163
|
+
throw new Error(`Cannot use CDP because browser API write or exec operations are disabled. See https://vitest.dev/config/browser/api.`);
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
function setupClient(project, rpcId, ws, options) {
|
|
3139
3167
|
const mockResolver = new ServerMockResolver(globalServer.vite, { moduleDirectories: project.config?.deps?.moduleDirectories });
|
|
3140
3168
|
const mocker = project.browser?.provider.mocker;
|
|
3141
3169
|
const rpc = createBirpc({
|
|
3170
|
+
onOrchestratorReady() {
|
|
3171
|
+
const sessions = vitest._browserSessions;
|
|
3172
|
+
sessions.getSession(options.sessionId)?.ready();
|
|
3173
|
+
},
|
|
3142
3174
|
async onUnhandledError(error, type) {
|
|
3143
3175
|
if (error && typeof error === "object") {
|
|
3144
3176
|
const _error = error;
|
|
@@ -3175,6 +3207,21 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3175
3207
|
}
|
|
3176
3208
|
return vitest._testRun.recordArtifact(id, artifact);
|
|
3177
3209
|
},
|
|
3210
|
+
async onTestBenchmark(testId, benchmark) {
|
|
3211
|
+
return vitest._testRun.recordBenchmark(testId, benchmark);
|
|
3212
|
+
},
|
|
3213
|
+
async readBenchmarkResult(relativePath) {
|
|
3214
|
+
checkFileAccess(project.benchmark.resolve(relativePath));
|
|
3215
|
+
return project.benchmark.readResult(relativePath);
|
|
3216
|
+
},
|
|
3217
|
+
async writeBenchmarkResult(relativePath, data) {
|
|
3218
|
+
if (!canWrite(project)) {
|
|
3219
|
+
vitest.logger.error(`[vitest] Cannot write benchmark artifact "${relativePath}" because file writing is disabled. See https://vitest.dev/config/browser/api.`);
|
|
3220
|
+
return;
|
|
3221
|
+
}
|
|
3222
|
+
checkFileAccess(project.benchmark.resolve(relativePath));
|
|
3223
|
+
return project.benchmark.writeResult(relativePath, data);
|
|
3224
|
+
},
|
|
3178
3225
|
async onTaskUpdate(method, packs, events) {
|
|
3179
3226
|
if (method === "collect") {
|
|
3180
3227
|
vitest.state.updateTasks(packs);
|
|
@@ -3283,7 +3330,8 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3283
3330
|
},
|
|
3284
3331
|
triggerCommand: (name, ...args) => {
|
|
3285
3332
|
return project.browser.triggerCommand(name, context, ...args);
|
|
3286
|
-
}
|
|
3333
|
+
},
|
|
3334
|
+
__ensureCDPHandler: () => globalServer.ensureCDPHandler(sessionId, rpcId)
|
|
3287
3335
|
}, provider.getCommandsContext(sessionId));
|
|
3288
3336
|
return await project.browser.triggerCommand(command, context, ...payload);
|
|
3289
3337
|
},
|
|
@@ -3345,10 +3393,12 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3345
3393
|
return mocker.delete(sessionId, id);
|
|
3346
3394
|
},
|
|
3347
3395
|
async sendCdpEvent(sessionId, event, payload) {
|
|
3396
|
+
assertCdpAllowed(project);
|
|
3348
3397
|
const cdp = await globalServer.ensureCDPHandler(sessionId, rpcId);
|
|
3349
3398
|
return cdp.send(event, payload);
|
|
3350
3399
|
},
|
|
3351
3400
|
async trackCdpEvent(sessionId, type, event, listenerId) {
|
|
3401
|
+
assertCdpAllowed(project);
|
|
3352
3402
|
const cdp = await globalServer.ensureCDPHandler(sessionId, rpcId);
|
|
3353
3403
|
cdp[type](event, listenerId);
|
|
3354
3404
|
}
|
|
@@ -3371,10 +3421,11 @@ function setupBrowserRpc(globalServer, defaultMockerRegistry) {
|
|
|
3371
3421
|
function cloneByOwnProperties(value) {
|
|
3372
3422
|
// Clones the value's properties into a new Object. The simpler approach of
|
|
3373
3423
|
// Object.assign() won't work in the case that properties are not enumerable.
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
[prop]
|
|
3377
|
-
}
|
|
3424
|
+
const clone = {};
|
|
3425
|
+
for (const prop of Object.getOwnPropertyNames(value)) {
|
|
3426
|
+
clone[prop] = value[prop];
|
|
3427
|
+
}
|
|
3428
|
+
return clone;
|
|
3378
3429
|
}
|
|
3379
3430
|
/**
|
|
3380
3431
|
* Replacer function for serialization methods such as JS.stringify() or
|