@baseline-ui/test-utils 3.7.0 → 3.9.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/dist/index.d.mts CHANGED
@@ -72,13 +72,18 @@ declare const expect: playwright_test.Expect<{
72
72
  message: () => string;
73
73
  pass: false;
74
74
  }>;
75
- toBeCalled(this: playwright_test.ExpectMatcherState, fn: SinonSpy): {
76
- message: () => string;
77
- pass: true;
78
- } | {
75
+ /**
76
+ * Calls arrive from the browser asynchronously. Negated, waits
77
+ * `NEGATED_SPY_WINDOW_MS` for a late call before passing: "none observed in
78
+ * the window", not "none ever". Always await it: an un-awaited failure
79
+ * rejects after the test body and lands on whichever test is then running.
80
+ */
81
+ toBeCalled(this: {
82
+ isNot?: boolean;
83
+ }, fn: SinonSpy): Promise<{
79
84
  message: () => string;
80
- pass: false;
81
- };
85
+ pass: boolean;
86
+ }>;
82
87
  toBeCalledTimes(this: playwright_test.ExpectMatcherState, fn: SinonSpy, times: number): Promise<{
83
88
  message: () => string;
84
89
  pass: true;
@@ -325,12 +330,18 @@ interface EditorTester {
325
330
  * rare case a consumer renders a custom one.
326
331
  *
327
332
  * `variant` mirrors the component's `variant` prop and only affects how the
328
- * upload `button` is resolved: in the `dropzone` variant the whole drop area is
329
- * the focusable trigger (`data-testid="file-uploader-dropzone"`, `role="button"`),
330
- * while the `button` variant renders a single `role="button"` inside the root.
333
+ * upload `button` is resolved: in the dropzone variants it is the focusable
334
+ * trigger inside the drop area (`data-testid="file-uploader-trigger"`); the
335
+ * `button` variant renders `data-testid="file-uploader-button"`.
331
336
  */
332
337
  interface FileUploaderTesterOptions extends BaseTesterOptions {
333
- variant?: "dropzone" | "button";
338
+ /**
339
+ * `"dropzone"` is deprecated, like the component's `variant="dropzone"`; use
340
+ * `"dropzone-box"`.
341
+ *
342
+ * @default "dropzone-box"
343
+ */
344
+ variant?: "dropzone-box" | "dropzone-inline" | "dropzone-compact" | "button" | "dropzone";
334
345
  }
335
346
  /**
336
347
  * Driver for a `<FileUploader>` in Playwright component tests. Construct with
@@ -344,7 +355,7 @@ interface FileUploaderTester {
344
355
  /** The hidden native file input. Prefer {@link upload} to set files on it. */
345
356
  readonly input: Locator;
346
357
  /**
347
- * The drop area (dropzone variant only). Use with `locator.drop({ files })`
358
+ * The drop area (dropzone variants only). Use with `locator.drop({ files })`
348
359
  * to simulate a drag-and-drop. Not attached in the `button` variant.
349
360
  */
350
361
  readonly dropzone: Locator;
package/dist/index.d.ts CHANGED
@@ -72,13 +72,18 @@ declare const expect: playwright_test.Expect<{
72
72
  message: () => string;
73
73
  pass: false;
74
74
  }>;
75
- toBeCalled(this: playwright_test.ExpectMatcherState, fn: SinonSpy): {
76
- message: () => string;
77
- pass: true;
78
- } | {
75
+ /**
76
+ * Calls arrive from the browser asynchronously. Negated, waits
77
+ * `NEGATED_SPY_WINDOW_MS` for a late call before passing: "none observed in
78
+ * the window", not "none ever". Always await it: an un-awaited failure
79
+ * rejects after the test body and lands on whichever test is then running.
80
+ */
81
+ toBeCalled(this: {
82
+ isNot?: boolean;
83
+ }, fn: SinonSpy): Promise<{
79
84
  message: () => string;
80
- pass: false;
81
- };
85
+ pass: boolean;
86
+ }>;
82
87
  toBeCalledTimes(this: playwright_test.ExpectMatcherState, fn: SinonSpy, times: number): Promise<{
83
88
  message: () => string;
84
89
  pass: true;
@@ -325,12 +330,18 @@ interface EditorTester {
325
330
  * rare case a consumer renders a custom one.
326
331
  *
327
332
  * `variant` mirrors the component's `variant` prop and only affects how the
328
- * upload `button` is resolved: in the `dropzone` variant the whole drop area is
329
- * the focusable trigger (`data-testid="file-uploader-dropzone"`, `role="button"`),
330
- * while the `button` variant renders a single `role="button"` inside the root.
333
+ * upload `button` is resolved: in the dropzone variants it is the focusable
334
+ * trigger inside the drop area (`data-testid="file-uploader-trigger"`); the
335
+ * `button` variant renders `data-testid="file-uploader-button"`.
331
336
  */
332
337
  interface FileUploaderTesterOptions extends BaseTesterOptions {
333
- variant?: "dropzone" | "button";
338
+ /**
339
+ * `"dropzone"` is deprecated, like the component's `variant="dropzone"`; use
340
+ * `"dropzone-box"`.
341
+ *
342
+ * @default "dropzone-box"
343
+ */
344
+ variant?: "dropzone-box" | "dropzone-inline" | "dropzone-compact" | "button" | "dropzone";
334
345
  }
335
346
  /**
336
347
  * Driver for a `<FileUploader>` in Playwright component tests. Construct with
@@ -344,7 +355,7 @@ interface FileUploaderTester {
344
355
  /** The hidden native file input. Prefer {@link upload} to set files on it. */
345
356
  readonly input: Locator;
346
357
  /**
347
- * The drop area (dropzone variant only). Use with `locator.drop({ files })`
358
+ * The drop area (dropzone variants only). Use with `locator.drop({ files })`
348
359
  * to simulate a drag-and-drop. Not attached in the `button` variant.
349
360
  */
350
361
  readonly dropzone: Locator;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var test=require('@playwright/test'),j=require('axe-core'),promises=require('fs/promises'),F=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var j__default=/*#__PURE__*/_interopDefault(j);var F__default=/*#__PURE__*/_interopDefault(F);/**
1
+ 'use strict';var test=require('@playwright/test'),j=require('axe-core'),promises=require('fs/promises'),F=require('path'),promises$1=require('timers/promises');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var j__default=/*#__PURE__*/_interopDefault(j);var F__default=/*#__PURE__*/_interopDefault(F);/**
2
2
  * Copyright (c) 2023-2024 PSPDFKit GmbH. All rights reserved.
3
3
  *
4
4
  * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
@@ -7,15 +7,15 @@
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:r=false}=t,n=Array.isArray(o)?o:[o];function s(c){return c.split(/[-_]/).some(u=>u.length>=5&&/^[a-z\d]+$/.test(u)&&/[a-z]/.test(u)&&/\d/.test(u))}function l(c){return [...c.classList].filter(u=>n.some(m=>u.startsWith(m))&&(!r||!s(u)))}function p(c,u=false){let m=[],h=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of h){let b=u||f.getAttribute("aria-hidden")==="true",x=l(f),w=p(f,b);x.length>0?m.push({classes:x,children:w,hidden:b}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let b=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",_=m?"":u+(x?" ":"\u2502 "),W=b.classes.join(", ");h.push(u+w+W+(b.hidden?" [aria-hidden]":""),...d(b.children,_));}return h}let a=l(e),i=p(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
10
+ var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:r=false}=t,n=Array.isArray(o)?o:[o];function s(c){return c.split(/[-_]/).some(u=>u.length>=5&&/^[a-z\d]+$/.test(u)&&/[a-z]/.test(u)&&/\d/.test(u))}function l(c){return [...c.classList].filter(u=>n.some(m=>u.startsWith(m))&&(!r||!s(u)))}function p(c,u=false){let m=[],h=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of h){let b=u||f.getAttribute("aria-hidden")==="true",x=l(f),w=p(f,b);x.length>0?m.push({classes:x,children:w,hidden:b}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let b=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",$=m?"":u+(x?" ":"\u2502 "),W=b.classes.join(", ");h.push(u+w+W+(b.hidden?" [aria-hidden]":""),...d(b.children,$));}return h}let a=l(e),i=p(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
11
11
  `):d(i,"",true).join(`
12
- `)}var B=e=>{if(e instanceof Error)return e.message;if(typeof e=="string")return e;if(e==null)return "unknown error";try{return JSON.stringify(e)}catch{return "unstringifiable error"}},V=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let r=e;return await r.first().evaluate(s=>s.tagName?.toLowerCase()==="iframe").catch(()=>false)?r.contentFrame().locator("body"):r},G=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},j__default.default.source);},q=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],J=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},K=async(e,t,o)=>{let r=await e.count();if(r===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await G(e);let n=I(t.include),s=I(t.exclude);return r===1?await e.evaluate(async(l,p)=>{let d=window,a={include:[l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o}):await e.evaluateAll(async(l,p)=>{let d=window,a={include:[...l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function X(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function Q(e){return (Array.isArray(e)?e:[e]).join("+")}function Y(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!X(r)&&s.push(S(Q(r))),n&&s.push("ignoreHashed"),F__default.default.join(e,`${s.join("--")}.txt`)}var T=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},Z=test.expect.extend({toBeWithinDelta(e,t,o){let r=Math.abs(e-t);if(Number.isNaN(r)||Number.isNaN(Number(o))||o<0)throw new TypeError(`toBeWithinDelta: cannot compare ${e} with ${t} within ${o}; expected numbers and a non-negative delta.`);return r<=o?{message:()=>`expected ${e} not to be within ${o} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${o} of ${t}`,pass:false}},async toBeCalledOnce(e){T(e,"toBeCalledOnce");try{return await test.expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTwice(e){T(e,"toBeCalledTwice");try{return await test.expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledThrice(e){T(e,"toBeCalledThrice");try{return await test.expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledWith(e,...t){T(e,"toBeCalledWith");try{return await test.expect.poll(()=>({called:e.called,args:t.map((o,r)=>e.lastCall?.args[r])})).toStrictEqual({called:!0,args:t}),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalledWithExactly(e,...t){T(e,"toBeCalledWithExactly");try{return await test.expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},toBeCalled(e){T(e,"toBeCalled");try{return test.expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTimes(e,t){if(T(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");try{return await test.expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeAccessible(e,t={}){let o=await V(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=J(t,r?q:[]),s,l=async()=>{let i=await K(o,t,n),c=t.treatIncompleteAsViolationIds??E,u=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return s={result:i,violations:u},u},p;try{if(t.timeout&&t.timeout>0){let i=test.expect.poll(l,{timeout:t.timeout});await(this.isNot?i.not.toHaveLength(0):i.toHaveLength(0));}else await l();}catch(i){p=i;}if(!s)throw new Error(`toBeAccessible: axe scan never completed.
12
+ `)}var B=e=>{if(e instanceof Error)return e.message;if(typeof e=="string")return e;if(e==null)return "unknown error";try{return JSON.stringify(e)}catch{return "unstringifiable error"}},V=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let r=e;return await r.first().evaluate(s=>s.tagName?.toLowerCase()==="iframe").catch(()=>false)?r.contentFrame().locator("body"):r},q=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},j__default.default.source);},J=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],K=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},Y=async(e,t,o)=>{let r=await e.count();if(r===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await q(e);let n=I(t.include),s=I(t.exclude);return r===1?await e.evaluate(async(l,p)=>{let d=window,a={include:[l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o}):await e.evaluateAll(async(l,p)=>{let d=window,a={include:[...l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function X(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function Q(e){return (Array.isArray(e)?e:[e]).join("+")}function Z(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!X(r)&&s.push(S(Q(r))),n&&s.push("ignoreHashed"),F__default.default.join(e,`${s.join("--")}.txt`)}var ee=300,te=25,T=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},oe=test.expect.extend({toBeWithinDelta(e,t,o){let r=Math.abs(e-t);if(Number.isNaN(r)||Number.isNaN(Number(o))||o<0)throw new TypeError(`toBeWithinDelta: cannot compare ${e} with ${t} within ${o}; expected numbers and a non-negative delta.`);return r<=o?{message:()=>`expected ${e} not to be within ${o} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${o} of ${t}`,pass:false}},async toBeCalledOnce(e){T(e,"toBeCalledOnce");try{return await test.expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTwice(e){T(e,"toBeCalledTwice");try{return await test.expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledThrice(e){T(e,"toBeCalledThrice");try{return await test.expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledWith(e,...t){T(e,"toBeCalledWith");try{return await test.expect.poll(()=>({called:e.called,args:t.map((o,r)=>e.lastCall?.args[r])})).toStrictEqual({called:!0,args:t}),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalledWithExactly(e,...t){T(e,"toBeCalledWithExactly");try{return await test.expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalled(e){if(T(e,"toBeCalled"),this.isNot){let t=Date.now()+ee;for(;e.callCount===0&&Date.now()<t;)await promises$1.setTimeout(te);return {message:()=>`Expected function not to be called, but it was called ${e.callCount} time(s).`,pass:e.callCount>0}}try{return await test.expect.poll(()=>e.called).toBe(!0),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTimes(e,t){if(T(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");try{return await test.expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeAccessible(e,t={}){let o=await V(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=K(t,r?J:[]),s,l=async()=>{let i=await Y(o,t,n),c=t.treatIncompleteAsViolationIds??E,u=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return s={result:i,violations:u},u},p;try{if(t.timeout&&t.timeout>0){let i=test.expect.poll(l,{timeout:t.timeout});await(this.isNot?i.not.toHaveLength(0):i.toHaveLength(0));}else await l();}catch(i){p=i;}if(!s)throw new Error(`toBeAccessible: axe scan never completed.
13
13
  ${B(p)}`);if(s.violations.length===0)return {message:()=>"Expected accessibility violations but found none.",pass:true};this.isNot||await test.test.info().attach(t.attachmentName??"accessibility-scan-results",{body:JSON.stringify(s.result,null,2),contentType:"application/json"});let d=s.violations.map(i=>{let c=i.nodes.map(u=>Array.isArray(u.target)?u.target.join(" "):String(u.target)).join(`
14
14
  `);return ` \u2022 [${i.id}] ${i.help}
15
15
  ${c}
16
16
  ${i.helpUrl??""}`}).join(`
17
17
  `),a=s.violations.length;return {message:()=>`Found ${a} accessibility violation${a===1?"":"s"}:
18
18
  ${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=A,ignoreHashed:n=false}=o,s=await e.evaluate(C,{prefix:r,ignoreHashed:n});if(!s){let u=Array.isArray(r)?r.map(m=>`${m}*`).join(" / "):`${r}*`;throw new Error(`No ${u} classes found in the DOM tree.`)}let l=`${s}
19
- `,p=test.test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Y(p.project.snapshotDir,p.titlePath,t,r,n),i=p.config.updateSnapshots,c;try{c=await promises.readFile(a,"utf8");}catch(u){let m=u.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await promises.mkdir(F__default.default.dirname(a),{recursive:true}),await promises.writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw u}if(c!==l){if(!this.isNot&&(i==="all"||i==="changed"))return await promises.writeFile(a,l),{message:()=>"Class tree snapshot updated.",pass:true};try{test.expect(l).toBe(c);}catch(u){return {message:()=>`Class tree snapshot mismatch at ${a}
19
+ `,p=test.test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Z(p.project.snapshotDir,p.titlePath,t,r,n),i=p.config.updateSnapshots,c;try{c=await promises.readFile(a,"utf8");}catch(u){let m=u.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await promises.mkdir(F__default.default.dirname(a),{recursive:true}),await promises.writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw u}if(c!==l){if(!this.isNot&&(i==="all"||i==="changed"))return await promises.writeFile(a,l),{message:()=>"Class tree snapshot updated.",pass:true};try{test.expect(l).toBe(c);}catch(u){return {message:()=>`Class tree snapshot mismatch at ${a}
20
20
 
21
- ${u.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function v({frame:e,name:t}){let o=e.locator(".BaselineUI-Breadcrumbs"),r=t===void 0?o:o.and(e.getByRole("navigation",{name:t,exact:typeof t=="string"}));return {root:r,current:r.locator('[aria-current="page"]'),separators:r.getByTestId("breadcrumbs-separator"),item:n=>r.getByRole("link",{name:n,exact:typeof n=="string"})}}function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let n=e.locator("[aria-expanded]").first();return await n.count()>0?n:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(n="click")=>{if(await o())return;if(n==="click"){await e.click();return}await(await t()).press(n);}}}function D({frame:e,trigger:t,toggleButton:o}){let r=t??e.getByRole("combobox",{includeHidden:true}),n=o??e.getByTestId("combobox-toggle-button"),s=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:p}=g(r),d=async(a="click")=>{if(!await l()){if(a==="click"){await n.click();return}await p(a);}};return {input:r,toggleButton:n,listbox:e.getByRole("listbox"),option:s,isOpen:l,open:d,async selectOption(a){await d(),await s(a).click();},async filter(a){await r.fill(a);}}}function P({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),r=o.getByTestId("editor-font-color-button"),n=o.getByTestId("editor-background-color-button"),s=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),p=o.getByTestId("editor-mention-button"),d=o.getByRole("combobox"),a=e.getByTestId("editor-mention-listbox"),i=e.getByTestId("editor-help-dialog-close-button"),c=e.getByRole("dialog").filter({has:i}),u=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:o,textbox:o.getByRole("textbox"),placeholder:o.getByTestId("editor-placeholder"),toolbar:o.getByRole("toolbar"),boldButton:o.getByTestId("editor-bold-button"),italicButton:o.getByTestId("editor-italic-button"),underlineButton:o.getByTestId("editor-underline-button"),fontColorButton:r,backgroundColorButton:n,openFontColorPicker:g(r).open,openBackgroundColorPicker:g(n).open,addLinkButton:s,linkDialog:u,linkInput:e.getByTestId("editor-link-input"),linkAddButton:e.getByTestId("editor-link-add-button"),linkEditButton:e.getByTestId("editor-link-edit-button"),linkRemoveButton:e.getByTestId("editor-link-remove-button"),linkCancelButton:e.getByTestId("editor-link-cancel-button"),linkSaveButton:e.getByTestId("editor-link-save-button"),openLinkDialog:g(s).open,saveButton:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:p,helpButton:l,helpDialog:c,helpDialogCloseButton:i,async openHelpDialog(){await c.isVisible()||await l.click();},mentionInput:d,mentionListbox:a,mentionOption:m=>a.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await p.click();}}}function U({frame:e,trigger:t,variant:o="dropzone"}){let r=e.getByTestId("file-uploader"),n=r.locator('input[type="file"]'),s=t??(o==="button"?r.getByRole("button"):e.getByTestId("file-uploader-dropzone"));return {root:r,button:s,input:n,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:r.getByRole("alert"),async upload(l){await n.setInputFiles(l);}}}function M(e,t,o){let r=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),n=l=>t.getByRole("group",{name:l}),{isOpen:s}=g(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=M(e,d,p),{open:i}=g(p);return {...a,trigger:p,open:async(c="Enter")=>i(c)}}}}function $({frame:e,trigger:t,longPress:o=false}){let r=t??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=M(e,n,r),{button:l,open:p,isOpen:d}=g(r),a=async(i="click")=>{if(!o)return p(i);if(i==="ArrowLeft"||i==="ArrowRight")throw new Error(`menuTester: cannot open a long-press menu with "${i}"; use "click", "Enter", "Space", "ArrowDown" or "ArrowUp"`);if(await d())return;let c=await l();if(i==="click"){await c.click({delay:800});return}await c.press(`Alt+${i}`);};return {...s,trigger:r,open:a,isOpen:d,async close(){await d()&&await r.press("Escape");},async selectItem(i){await a(),await s.item(i).click();}}}var N=(e=>{let o=ee(e);return e.multiple&&(o=te(o,e.frame)),e.autocomplete&&(o=oe(o,e.frame)),o});function ee({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function te(e,t){return {...e,selectAllButton:t.getByTestId("select-all-button"),clearButton:t.getByTestId("select-clear-button"),tag:o=>e.trigger.getByRole("row",{name:o}),removeTagButton:o=>e.trigger.getByRole("row",{name:o}).getByRole("button")}}function oe(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function re(e){return {select:((t={})=>N({frame:e,...t})),comboBox:(t={})=>D({frame:e,...t}),editor:(t={})=>P({frame:e,...t}),fileUploader:(t={})=>U({frame:e,...t}),menu:(t={})=>$({frame:e,...t}),breadcrumbs:(t={})=>v({frame:e,...t})}}exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=E;exports.DEFAULT_DISABLED_RULES=O;exports.DEFAULT_WCAG_TAGS=L;exports.expect=Z;exports.testers=re;
21
+ ${u.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function D({frame:e,name:t}){let o=e.locator(".BaselineUI-Breadcrumbs"),r=t===void 0?o:o.and(e.getByRole("navigation",{name:t,exact:typeof t=="string"}));return {root:r,current:r.locator('[aria-current="page"]'),separators:r.getByTestId("breadcrumbs-separator"),item:n=>r.getByRole("link",{name:n,exact:typeof n=="string"})}}function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let n=e.locator("[aria-expanded]").first();return await n.count()>0?n:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(n="click")=>{if(await o())return;if(n==="click"){await e.click();return}await(await t()).press(n);}}}function v({frame:e,trigger:t,toggleButton:o}){let r=t??e.getByRole("combobox",{includeHidden:true}),n=o??e.getByTestId("combobox-toggle-button"),s=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:p}=g(r),d=async(a="click")=>{if(!await l()){if(a==="click"){await n.click();return}await p(a);}};return {input:r,toggleButton:n,listbox:e.getByRole("listbox"),option:s,isOpen:l,open:d,async selectOption(a){await d(),await s(a).click();},async filter(a){await r.fill(a);}}}function P({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),r=o.getByTestId("editor-font-color-button"),n=o.getByTestId("editor-background-color-button"),s=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),p=o.getByTestId("editor-mention-button"),d=o.getByRole("combobox"),a=e.getByTestId("editor-mention-listbox"),i=e.getByTestId("editor-help-dialog-close-button"),c=e.getByRole("dialog").filter({has:i}),u=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:o,textbox:o.getByRole("textbox"),placeholder:o.getByTestId("editor-placeholder"),toolbar:o.getByRole("toolbar"),boldButton:o.getByTestId("editor-bold-button"),italicButton:o.getByTestId("editor-italic-button"),underlineButton:o.getByTestId("editor-underline-button"),fontColorButton:r,backgroundColorButton:n,openFontColorPicker:g(r).open,openBackgroundColorPicker:g(n).open,addLinkButton:s,linkDialog:u,linkInput:e.getByTestId("editor-link-input"),linkAddButton:e.getByTestId("editor-link-add-button"),linkEditButton:e.getByTestId("editor-link-edit-button"),linkRemoveButton:e.getByTestId("editor-link-remove-button"),linkCancelButton:e.getByTestId("editor-link-cancel-button"),linkSaveButton:e.getByTestId("editor-link-save-button"),openLinkDialog:g(s).open,saveButton:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:p,helpButton:l,helpDialog:c,helpDialogCloseButton:i,async openHelpDialog(){await c.isVisible()||await l.click();},mentionInput:d,mentionListbox:a,mentionOption:m=>a.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await p.click();}}}function U({frame:e,trigger:t,variant:o="dropzone-box"}){let r=e.getByTestId("file-uploader"),n=r.locator('input[type="file"]'),s=t??r.getByTestId(o==="button"?"file-uploader-button":"file-uploader-trigger");return {root:r,button:s,input:n,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:r.getByRole("alert"),async upload(l){await n.setInputFiles(l);}}}function M(e,t,o){let r=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),n=l=>t.getByRole("group",{name:l}),{isOpen:s}=g(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=M(e,d,p),{open:i}=g(p);return {...a,trigger:p,open:async(c="Enter")=>i(c)}}}}function N({frame:e,trigger:t,longPress:o=false}){let r=t??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=M(e,n,r),{button:l,open:p,isOpen:d}=g(r),a=async(i="click")=>{if(!o)return p(i);if(i==="ArrowLeft"||i==="ArrowRight")throw new Error(`menuTester: cannot open a long-press menu with "${i}"; use "click", "Enter", "Space", "ArrowDown" or "ArrowUp"`);if(await d())return;let c=await l();if(i==="click"){await c.click({delay:800});return}await c.press(`Alt+${i}`);};return {...s,trigger:r,open:a,isOpen:d,async close(){await d()&&await r.press("Escape");},async selectItem(i){await a(),await s.item(i).click();}}}var _=(e=>{let o=re(e);return e.multiple&&(o=ne(o,e.frame)),e.autocomplete&&(o=se(o,e.frame)),o});function re({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function ne(e,t){return {...e,selectAllButton:t.getByTestId("select-all-button"),clearButton:t.getByTestId("select-clear-button"),tag:o=>e.trigger.getByRole("row",{name:o}),removeTagButton:o=>e.trigger.getByRole("row",{name:o}).getByRole("button")}}function se(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function ie(e){return {select:((t={})=>_({frame:e,...t})),comboBox:(t={})=>v({frame:e,...t}),editor:(t={})=>P({frame:e,...t}),fileUploader:(t={})=>U({frame:e,...t}),menu:(t={})=>N({frame:e,...t}),breadcrumbs:(t={})=>D({frame:e,...t})}}exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=E;exports.DEFAULT_DISABLED_RULES=O;exports.DEFAULT_WCAG_TAGS=L;exports.expect=oe;exports.testers=ie;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {expect,test}from'@playwright/test';import j from'axe-core';import {readFile,mkdir,writeFile}from'fs/promises';import F from'path';/**
1
+ import {expect,test}from'@playwright/test';import j from'axe-core';import {readFile,mkdir,writeFile}from'fs/promises';import F from'path';import {setTimeout}from'timers/promises';/**
2
2
  * Copyright (c) 2023-2024 PSPDFKit GmbH. All rights reserved.
3
3
  *
4
4
  * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
@@ -7,15 +7,15 @@ import {expect,test}from'@playwright/test';import j from'axe-core';import {readF
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:r=false}=t,n=Array.isArray(o)?o:[o];function s(c){return c.split(/[-_]/).some(u=>u.length>=5&&/^[a-z\d]+$/.test(u)&&/[a-z]/.test(u)&&/\d/.test(u))}function l(c){return [...c.classList].filter(u=>n.some(m=>u.startsWith(m))&&(!r||!s(u)))}function p(c,u=false){let m=[],h=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of h){let b=u||f.getAttribute("aria-hidden")==="true",x=l(f),w=p(f,b);x.length>0?m.push({classes:x,children:w,hidden:b}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let b=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",_=m?"":u+(x?" ":"\u2502 "),W=b.classes.join(", ");h.push(u+w+W+(b.hidden?" [aria-hidden]":""),...d(b.children,_));}return h}let a=l(e),i=p(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
10
+ var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:r=false}=t,n=Array.isArray(o)?o:[o];function s(c){return c.split(/[-_]/).some(u=>u.length>=5&&/^[a-z\d]+$/.test(u)&&/[a-z]/.test(u)&&/\d/.test(u))}function l(c){return [...c.classList].filter(u=>n.some(m=>u.startsWith(m))&&(!r||!s(u)))}function p(c,u=false){let m=[],h=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of h){let b=u||f.getAttribute("aria-hidden")==="true",x=l(f),w=p(f,b);x.length>0?m.push({classes:x,children:w,hidden:b}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let b=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",$=m?"":u+(x?" ":"\u2502 "),W=b.classes.join(", ");h.push(u+w+W+(b.hidden?" [aria-hidden]":""),...d(b.children,$));}return h}let a=l(e),i=p(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
11
11
  `):d(i,"",true).join(`
12
- `)}var B=e=>{if(e instanceof Error)return e.message;if(typeof e=="string")return e;if(e==null)return "unknown error";try{return JSON.stringify(e)}catch{return "unstringifiable error"}},V=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let r=e;return await r.first().evaluate(s=>s.tagName?.toLowerCase()==="iframe").catch(()=>false)?r.contentFrame().locator("body"):r},G=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},j.source);},q=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],J=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},K=async(e,t,o)=>{let r=await e.count();if(r===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await G(e);let n=I(t.include),s=I(t.exclude);return r===1?await e.evaluate(async(l,p)=>{let d=window,a={include:[l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o}):await e.evaluateAll(async(l,p)=>{let d=window,a={include:[...l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function X(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function Q(e){return (Array.isArray(e)?e:[e]).join("+")}function Y(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!X(r)&&s.push(S(Q(r))),n&&s.push("ignoreHashed"),F.join(e,`${s.join("--")}.txt`)}var T=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},Z=expect.extend({toBeWithinDelta(e,t,o){let r=Math.abs(e-t);if(Number.isNaN(r)||Number.isNaN(Number(o))||o<0)throw new TypeError(`toBeWithinDelta: cannot compare ${e} with ${t} within ${o}; expected numbers and a non-negative delta.`);return r<=o?{message:()=>`expected ${e} not to be within ${o} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${o} of ${t}`,pass:false}},async toBeCalledOnce(e){T(e,"toBeCalledOnce");try{return await expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTwice(e){T(e,"toBeCalledTwice");try{return await expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledThrice(e){T(e,"toBeCalledThrice");try{return await expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledWith(e,...t){T(e,"toBeCalledWith");try{return await expect.poll(()=>({called:e.called,args:t.map((o,r)=>e.lastCall?.args[r])})).toStrictEqual({called:!0,args:t}),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalledWithExactly(e,...t){T(e,"toBeCalledWithExactly");try{return await expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},toBeCalled(e){T(e,"toBeCalled");try{return expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTimes(e,t){if(T(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");try{return await expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeAccessible(e,t={}){let o=await V(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=J(t,r?q:[]),s,l=async()=>{let i=await K(o,t,n),c=t.treatIncompleteAsViolationIds??E,u=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return s={result:i,violations:u},u},p;try{if(t.timeout&&t.timeout>0){let i=expect.poll(l,{timeout:t.timeout});await(this.isNot?i.not.toHaveLength(0):i.toHaveLength(0));}else await l();}catch(i){p=i;}if(!s)throw new Error(`toBeAccessible: axe scan never completed.
12
+ `)}var B=e=>{if(e instanceof Error)return e.message;if(typeof e=="string")return e;if(e==null)return "unknown error";try{return JSON.stringify(e)}catch{return "unstringifiable error"}},V=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let r=e;return await r.first().evaluate(s=>s.tagName?.toLowerCase()==="iframe").catch(()=>false)?r.contentFrame().locator("body"):r},q=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},j.source);},J=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],K=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},Y=async(e,t,o)=>{let r=await e.count();if(r===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await q(e);let n=I(t.include),s=I(t.exclude);return r===1?await e.evaluate(async(l,p)=>{let d=window,a={include:[l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o}):await e.evaluateAll(async(l,p)=>{let d=window,a={include:[...l,...p.userInclude??[]],exclude:p.userExclude??[]};return await d.axe.run(a,p.runOptions)},{userInclude:n,userExclude:s,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function X(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function Q(e){return (Array.isArray(e)?e:[e]).join("+")}function Z(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!X(r)&&s.push(S(Q(r))),n&&s.push("ignoreHashed"),F.join(e,`${s.join("--")}.txt`)}var ee=300,te=25,T=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},oe=expect.extend({toBeWithinDelta(e,t,o){let r=Math.abs(e-t);if(Number.isNaN(r)||Number.isNaN(Number(o))||o<0)throw new TypeError(`toBeWithinDelta: cannot compare ${e} with ${t} within ${o}; expected numbers and a non-negative delta.`);return r<=o?{message:()=>`expected ${e} not to be within ${o} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${o} of ${t}`,pass:false}},async toBeCalledOnce(e){T(e,"toBeCalledOnce");try{return await expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTwice(e){T(e,"toBeCalledTwice");try{return await expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledThrice(e){T(e,"toBeCalledThrice");try{return await expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledWith(e,...t){T(e,"toBeCalledWith");try{return await expect.poll(()=>({called:e.called,args:t.map((o,r)=>e.lastCall?.args[r])})).toStrictEqual({called:!0,args:t}),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalledWithExactly(e,...t){T(e,"toBeCalledWithExactly");try{return await expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeCalled(e){if(T(e,"toBeCalled"),this.isNot){let t=Date.now()+ee;for(;e.callCount===0&&Date.now()<t;)await setTimeout(te);return {message:()=>`Expected function not to be called, but it was called ${e.callCount} time(s).`,pass:e.callCount>0}}try{return await expect.poll(()=>e.called).toBe(!0),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>B(t),pass:false}}},async toBeCalledTimes(e,t){if(T(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");try{return await expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>B(o),pass:false}}},async toBeAccessible(e,t={}){let o=await V(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=K(t,r?J:[]),s,l=async()=>{let i=await Y(o,t,n),c=t.treatIncompleteAsViolationIds??E,u=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return s={result:i,violations:u},u},p;try{if(t.timeout&&t.timeout>0){let i=expect.poll(l,{timeout:t.timeout});await(this.isNot?i.not.toHaveLength(0):i.toHaveLength(0));}else await l();}catch(i){p=i;}if(!s)throw new Error(`toBeAccessible: axe scan never completed.
13
13
  ${B(p)}`);if(s.violations.length===0)return {message:()=>"Expected accessibility violations but found none.",pass:true};this.isNot||await test.info().attach(t.attachmentName??"accessibility-scan-results",{body:JSON.stringify(s.result,null,2),contentType:"application/json"});let d=s.violations.map(i=>{let c=i.nodes.map(u=>Array.isArray(u.target)?u.target.join(" "):String(u.target)).join(`
14
14
  `);return ` \u2022 [${i.id}] ${i.help}
15
15
  ${c}
16
16
  ${i.helpUrl??""}`}).join(`
17
17
  `),a=s.violations.length;return {message:()=>`Found ${a} accessibility violation${a===1?"":"s"}:
18
18
  ${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=A,ignoreHashed:n=false}=o,s=await e.evaluate(C,{prefix:r,ignoreHashed:n});if(!s){let u=Array.isArray(r)?r.map(m=>`${m}*`).join(" / "):`${r}*`;throw new Error(`No ${u} classes found in the DOM tree.`)}let l=`${s}
19
- `,p=test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Y(p.project.snapshotDir,p.titlePath,t,r,n),i=p.config.updateSnapshots,c;try{c=await readFile(a,"utf8");}catch(u){let m=u.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await mkdir(F.dirname(a),{recursive:true}),await writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw u}if(c!==l){if(!this.isNot&&(i==="all"||i==="changed"))return await writeFile(a,l),{message:()=>"Class tree snapshot updated.",pass:true};try{expect(l).toBe(c);}catch(u){return {message:()=>`Class tree snapshot mismatch at ${a}
19
+ `,p=test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Z(p.project.snapshotDir,p.titlePath,t,r,n),i=p.config.updateSnapshots,c;try{c=await readFile(a,"utf8");}catch(u){let m=u.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await mkdir(F.dirname(a),{recursive:true}),await writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw u}if(c!==l){if(!this.isNot&&(i==="all"||i==="changed"))return await writeFile(a,l),{message:()=>"Class tree snapshot updated.",pass:true};try{expect(l).toBe(c);}catch(u){return {message:()=>`Class tree snapshot mismatch at ${a}
20
20
 
21
- ${u.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function v({frame:e,name:t}){let o=e.locator(".BaselineUI-Breadcrumbs"),r=t===void 0?o:o.and(e.getByRole("navigation",{name:t,exact:typeof t=="string"}));return {root:r,current:r.locator('[aria-current="page"]'),separators:r.getByTestId("breadcrumbs-separator"),item:n=>r.getByRole("link",{name:n,exact:typeof n=="string"})}}function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let n=e.locator("[aria-expanded]").first();return await n.count()>0?n:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(n="click")=>{if(await o())return;if(n==="click"){await e.click();return}await(await t()).press(n);}}}function D({frame:e,trigger:t,toggleButton:o}){let r=t??e.getByRole("combobox",{includeHidden:true}),n=o??e.getByTestId("combobox-toggle-button"),s=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:p}=g(r),d=async(a="click")=>{if(!await l()){if(a==="click"){await n.click();return}await p(a);}};return {input:r,toggleButton:n,listbox:e.getByRole("listbox"),option:s,isOpen:l,open:d,async selectOption(a){await d(),await s(a).click();},async filter(a){await r.fill(a);}}}function P({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),r=o.getByTestId("editor-font-color-button"),n=o.getByTestId("editor-background-color-button"),s=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),p=o.getByTestId("editor-mention-button"),d=o.getByRole("combobox"),a=e.getByTestId("editor-mention-listbox"),i=e.getByTestId("editor-help-dialog-close-button"),c=e.getByRole("dialog").filter({has:i}),u=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:o,textbox:o.getByRole("textbox"),placeholder:o.getByTestId("editor-placeholder"),toolbar:o.getByRole("toolbar"),boldButton:o.getByTestId("editor-bold-button"),italicButton:o.getByTestId("editor-italic-button"),underlineButton:o.getByTestId("editor-underline-button"),fontColorButton:r,backgroundColorButton:n,openFontColorPicker:g(r).open,openBackgroundColorPicker:g(n).open,addLinkButton:s,linkDialog:u,linkInput:e.getByTestId("editor-link-input"),linkAddButton:e.getByTestId("editor-link-add-button"),linkEditButton:e.getByTestId("editor-link-edit-button"),linkRemoveButton:e.getByTestId("editor-link-remove-button"),linkCancelButton:e.getByTestId("editor-link-cancel-button"),linkSaveButton:e.getByTestId("editor-link-save-button"),openLinkDialog:g(s).open,saveButton:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:p,helpButton:l,helpDialog:c,helpDialogCloseButton:i,async openHelpDialog(){await c.isVisible()||await l.click();},mentionInput:d,mentionListbox:a,mentionOption:m=>a.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await p.click();}}}function U({frame:e,trigger:t,variant:o="dropzone"}){let r=e.getByTestId("file-uploader"),n=r.locator('input[type="file"]'),s=t??(o==="button"?r.getByRole("button"):e.getByTestId("file-uploader-dropzone"));return {root:r,button:s,input:n,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:r.getByRole("alert"),async upload(l){await n.setInputFiles(l);}}}function M(e,t,o){let r=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),n=l=>t.getByRole("group",{name:l}),{isOpen:s}=g(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=M(e,d,p),{open:i}=g(p);return {...a,trigger:p,open:async(c="Enter")=>i(c)}}}}function $({frame:e,trigger:t,longPress:o=false}){let r=t??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=M(e,n,r),{button:l,open:p,isOpen:d}=g(r),a=async(i="click")=>{if(!o)return p(i);if(i==="ArrowLeft"||i==="ArrowRight")throw new Error(`menuTester: cannot open a long-press menu with "${i}"; use "click", "Enter", "Space", "ArrowDown" or "ArrowUp"`);if(await d())return;let c=await l();if(i==="click"){await c.click({delay:800});return}await c.press(`Alt+${i}`);};return {...s,trigger:r,open:a,isOpen:d,async close(){await d()&&await r.press("Escape");},async selectItem(i){await a(),await s.item(i).click();}}}var N=(e=>{let o=ee(e);return e.multiple&&(o=te(o,e.frame)),e.autocomplete&&(o=oe(o,e.frame)),o});function ee({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function te(e,t){return {...e,selectAllButton:t.getByTestId("select-all-button"),clearButton:t.getByTestId("select-clear-button"),tag:o=>e.trigger.getByRole("row",{name:o}),removeTagButton:o=>e.trigger.getByRole("row",{name:o}).getByRole("button")}}function oe(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function re(e){return {select:((t={})=>N({frame:e,...t})),comboBox:(t={})=>D({frame:e,...t}),editor:(t={})=>P({frame:e,...t}),fileUploader:(t={})=>U({frame:e,...t}),menu:(t={})=>$({frame:e,...t}),breadcrumbs:(t={})=>v({frame:e,...t})}}export{E as DEFAULT_CRITICAL_INCOMPLETE_RULES,O as DEFAULT_DISABLED_RULES,L as DEFAULT_WCAG_TAGS,Z as expect,re as testers};
21
+ ${u.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function D({frame:e,name:t}){let o=e.locator(".BaselineUI-Breadcrumbs"),r=t===void 0?o:o.and(e.getByRole("navigation",{name:t,exact:typeof t=="string"}));return {root:r,current:r.locator('[aria-current="page"]'),separators:r.getByTestId("breadcrumbs-separator"),item:n=>r.getByRole("link",{name:n,exact:typeof n=="string"})}}function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let n=e.locator("[aria-expanded]").first();return await n.count()>0?n:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(n="click")=>{if(await o())return;if(n==="click"){await e.click();return}await(await t()).press(n);}}}function v({frame:e,trigger:t,toggleButton:o}){let r=t??e.getByRole("combobox",{includeHidden:true}),n=o??e.getByTestId("combobox-toggle-button"),s=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:p}=g(r),d=async(a="click")=>{if(!await l()){if(a==="click"){await n.click();return}await p(a);}};return {input:r,toggleButton:n,listbox:e.getByRole("listbox"),option:s,isOpen:l,open:d,async selectOption(a){await d(),await s(a).click();},async filter(a){await r.fill(a);}}}function P({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),r=o.getByTestId("editor-font-color-button"),n=o.getByTestId("editor-background-color-button"),s=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),p=o.getByTestId("editor-mention-button"),d=o.getByRole("combobox"),a=e.getByTestId("editor-mention-listbox"),i=e.getByTestId("editor-help-dialog-close-button"),c=e.getByRole("dialog").filter({has:i}),u=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:o,textbox:o.getByRole("textbox"),placeholder:o.getByTestId("editor-placeholder"),toolbar:o.getByRole("toolbar"),boldButton:o.getByTestId("editor-bold-button"),italicButton:o.getByTestId("editor-italic-button"),underlineButton:o.getByTestId("editor-underline-button"),fontColorButton:r,backgroundColorButton:n,openFontColorPicker:g(r).open,openBackgroundColorPicker:g(n).open,addLinkButton:s,linkDialog:u,linkInput:e.getByTestId("editor-link-input"),linkAddButton:e.getByTestId("editor-link-add-button"),linkEditButton:e.getByTestId("editor-link-edit-button"),linkRemoveButton:e.getByTestId("editor-link-remove-button"),linkCancelButton:e.getByTestId("editor-link-cancel-button"),linkSaveButton:e.getByTestId("editor-link-save-button"),openLinkDialog:g(s).open,saveButton:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:p,helpButton:l,helpDialog:c,helpDialogCloseButton:i,async openHelpDialog(){await c.isVisible()||await l.click();},mentionInput:d,mentionListbox:a,mentionOption:m=>a.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await p.click();}}}function U({frame:e,trigger:t,variant:o="dropzone-box"}){let r=e.getByTestId("file-uploader"),n=r.locator('input[type="file"]'),s=t??r.getByTestId(o==="button"?"file-uploader-button":"file-uploader-trigger");return {root:r,button:s,input:n,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:r.getByRole("alert"),async upload(l){await n.setInputFiles(l);}}}function M(e,t,o){let r=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),n=l=>t.getByRole("group",{name:l}),{isOpen:s}=g(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=M(e,d,p),{open:i}=g(p);return {...a,trigger:p,open:async(c="Enter")=>i(c)}}}}function N({frame:e,trigger:t,longPress:o=false}){let r=t??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=M(e,n,r),{button:l,open:p,isOpen:d}=g(r),a=async(i="click")=>{if(!o)return p(i);if(i==="ArrowLeft"||i==="ArrowRight")throw new Error(`menuTester: cannot open a long-press menu with "${i}"; use "click", "Enter", "Space", "ArrowDown" or "ArrowUp"`);if(await d())return;let c=await l();if(i==="click"){await c.click({delay:800});return}await c.press(`Alt+${i}`);};return {...s,trigger:r,open:a,isOpen:d,async close(){await d()&&await r.press("Escape");},async selectItem(i){await a(),await s.item(i).click();}}}var _=(e=>{let o=re(e);return e.multiple&&(o=ne(o,e.frame)),e.autocomplete&&(o=se(o,e.frame)),o});function re({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function ne(e,t){return {...e,selectAllButton:t.getByTestId("select-all-button"),clearButton:t.getByTestId("select-clear-button"),tag:o=>e.trigger.getByRole("row",{name:o}),removeTagButton:o=>e.trigger.getByRole("row",{name:o}).getByRole("button")}}function se(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function ie(e){return {select:((t={})=>_({frame:e,...t})),comboBox:(t={})=>v({frame:e,...t}),editor:(t={})=>P({frame:e,...t}),fileUploader:(t={})=>U({frame:e,...t}),menu:(t={})=>N({frame:e,...t}),breadcrumbs:(t={})=>D({frame:e,...t})}}export{E as DEFAULT_CRITICAL_INCOMPLETE_RULES,O as DEFAULT_DISABLED_RULES,L as DEFAULT_WCAG_TAGS,oe as expect,ie as testers};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baseline-ui/test-utils",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "description": "A collection of test utilities for Baseline UI",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -52,7 +52,7 @@
52
52
  "dependencies": {
53
53
  "axe-core": "^4.11.4",
54
54
  "react-frame-component": "^5.3.2",
55
- "@baseline-ui/core": "3.7.0"
55
+ "@baseline-ui/core": "3.9.0"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsup",
package/sbom.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.6",
5
- "serialNumber": "urn:uuid:af24b70e-d501-463f-9d2c-c1ddfbfd9082",
5
+ "serialNumber": "urn:uuid:f5fcc4fe-ebcb-4c1a-8e14-68389e505126",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-23T17:52:32.929Z",
8
+ "timestamp": "2026-10-29T18:49:17.165Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "pre-build"
@@ -23,9 +23,9 @@
23
23
  "component": {
24
24
  "type": "library",
25
25
  "name": "@baseline-ui/test-utils",
26
- "version": "3.7.0",
27
- "purl": "pkg:npm/@baseline-ui/test-utils@3.7.0",
28
- "bom-ref": "pkg:npm/@baseline-ui/test-utils@3.7.0",
26
+ "version": "3.9.0",
27
+ "purl": "pkg:npm/@baseline-ui/test-utils@3.9.0",
28
+ "bom-ref": "pkg:npm/@baseline-ui/test-utils@3.9.0",
29
29
  "licenses": [
30
30
  {
31
31
  "license": {
@@ -500,7 +500,7 @@
500
500
  ],
501
501
  "dependencies": [
502
502
  {
503
- "ref": "pkg:npm/@baseline-ui/test-utils@3.7.0",
503
+ "ref": "pkg:npm/@baseline-ui/test-utils@3.9.0",
504
504
  "dependsOn": [
505
505
  "pkg:npm/%40neondatabase/serverless@1.1.0",
506
506
  "pkg:npm/%40playwright/test@1.62.1",