@baseline-ui/test-utils 3.10.1 → 3.11.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 +62 -1
- package/dist/index.d.ts +62 -1
- package/dist/index.js +7 -7
- package/dist/index.mjs +7 -7
- package/package.json +2 -2
- package/sbom.json +6 -6
package/dist/index.d.mts
CHANGED
|
@@ -323,6 +323,26 @@ interface EditorTester {
|
|
|
323
323
|
startMention: () => Promise<void>;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
interface FileInputTesterOptions extends Omit<BaseTesterOptions, "trigger"> {
|
|
327
|
+
/**
|
|
328
|
+
* The `<FileInput>` root element, not a wrapper around it, to pick one when
|
|
329
|
+
* a page renders several. A `data-testid` passed to `<FileInput>` lands on it.
|
|
330
|
+
*/
|
|
331
|
+
root?: Locator;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Driver for a `<FileInput>` in Playwright component tests. Construct with
|
|
335
|
+
* {@link fileInputTester} (or `testers(frame).fileInput()`).
|
|
336
|
+
*/
|
|
337
|
+
interface FileInputTester {
|
|
338
|
+
/** The root element. */
|
|
339
|
+
readonly root: Locator;
|
|
340
|
+
/** The button that opens the native file picker. */
|
|
341
|
+
readonly button: Locator;
|
|
342
|
+
/** The hidden native file input. */
|
|
343
|
+
readonly input: Locator;
|
|
344
|
+
}
|
|
345
|
+
|
|
326
346
|
/**
|
|
327
347
|
* Options for {@link fileUploaderTester}. The root is always resolved from the
|
|
328
348
|
* stable `data-testid="file-uploader"`; `trigger` overrides the upload
|
|
@@ -582,12 +602,51 @@ interface SelectTesterFactoryFor<O extends {
|
|
|
582
602
|
(options?: O): SelectTester;
|
|
583
603
|
}
|
|
584
604
|
|
|
605
|
+
interface VideoPlayerTesterOptions extends Omit<BaseTesterOptions, "trigger"> {
|
|
606
|
+
/** The accessible name of the player, to pick one when a page has several. */
|
|
607
|
+
name?: string | RegExp;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Driver for a `<VideoPlayer>` in Playwright component tests. Construct with
|
|
611
|
+
* {@link videoPlayerTester} (or `testers(frame).videoPlayer()`).
|
|
612
|
+
*
|
|
613
|
+
* While the video plays, the controls fade out and stop taking pointer input
|
|
614
|
+
* after `controlsHideDelay`; they still count as visible to `toBeVisible()`.
|
|
615
|
+
* Hover `root` to bring them back before clicking one, and assert on
|
|
616
|
+
* `data-controls-visible` rather than visibility.
|
|
617
|
+
*/
|
|
618
|
+
interface VideoPlayerTester {
|
|
619
|
+
/** The player's `group`. Carries `data-state` and `data-controls-visible`. */
|
|
620
|
+
readonly root: Locator;
|
|
621
|
+
/** The native `<video>` element. */
|
|
622
|
+
readonly video: Locator;
|
|
623
|
+
/** The play/pause toggle. Its accessible name flips with the playback state. */
|
|
624
|
+
readonly playButton: Locator;
|
|
625
|
+
/** The timeline slider used to seek. */
|
|
626
|
+
readonly timeline: Locator;
|
|
627
|
+
/** The elapsed-time label. */
|
|
628
|
+
readonly currentTime: Locator;
|
|
629
|
+
/** The duration label. */
|
|
630
|
+
readonly duration: Locator;
|
|
631
|
+
/** The mute/unmute toggle. Its accessible name flips with the muted state. */
|
|
632
|
+
readonly muteButton: Locator;
|
|
633
|
+
/**
|
|
634
|
+
* The enter/exit full screen toggle. Matches nothing where the browser does
|
|
635
|
+
* not allow full screen.
|
|
636
|
+
*/
|
|
637
|
+
readonly fullScreenButton: Locator;
|
|
638
|
+
/** The spinner shown until the video's metadata has loaded. */
|
|
639
|
+
readonly loadingIndicator: Locator;
|
|
640
|
+
}
|
|
641
|
+
|
|
585
642
|
type BoundSelectOptions = Omit<SelectTesterOptions, "frame">;
|
|
586
643
|
type BoundComboBoxOptions = Omit<ComboBoxTesterOptions, "frame">;
|
|
587
644
|
type BoundEditorOptions = Omit<EditorTesterOptions, "frame">;
|
|
645
|
+
type BoundFileInputOptions = Omit<FileInputTesterOptions, "frame">;
|
|
588
646
|
type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
589
647
|
type BoundMenuOptions = Omit<MenuTesterOptions, "frame">;
|
|
590
648
|
type BoundBreadcrumbsOptions = Omit<BreadcrumbsTesterOptions, "frame">;
|
|
649
|
+
type BoundVideoPlayerOptions = Omit<VideoPlayerTesterOptions, "frame">;
|
|
591
650
|
/**
|
|
592
651
|
* The frame-bound tester factory. Methods are flat — one per component — so
|
|
593
652
|
* IDE autocomplete on `t.` lists the full surface in one place. Variants of a
|
|
@@ -601,9 +660,11 @@ interface Testers {
|
|
|
601
660
|
select: SelectTesterFactoryFor<BoundSelectOptions>;
|
|
602
661
|
comboBox: (options?: BoundComboBoxOptions) => ComboBoxTester;
|
|
603
662
|
editor: (options?: BoundEditorOptions) => EditorTester;
|
|
663
|
+
fileInput: (options?: BoundFileInputOptions) => FileInputTester;
|
|
604
664
|
fileUploader: (options?: BoundFileUploaderOptions) => FileUploaderTester;
|
|
605
665
|
menu: (options?: BoundMenuOptions) => MenuTester;
|
|
606
666
|
breadcrumbs: (options?: BoundBreadcrumbsOptions) => BreadcrumbsTester;
|
|
667
|
+
videoPlayer: (options?: BoundVideoPlayerOptions) => VideoPlayerTester;
|
|
607
668
|
}
|
|
608
669
|
/**
|
|
609
670
|
* Build a frame-bound tester factory. Construct once per test and pick the
|
|
@@ -621,4 +682,4 @@ interface Testers {
|
|
|
621
682
|
*/
|
|
622
683
|
declare function testers(frame: Frame): Testers;
|
|
623
684
|
|
|
624
|
-
export { type AutocompleteTester, type BreadcrumbsTester, type ComboBoxTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileUploaderTester, type Frame, type MenuSubmenuTester, type MenuTester, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, expect, testers };
|
|
685
|
+
export { type AutocompleteTester, type BreadcrumbsTester, type ComboBoxTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileInputTester, type FileUploaderTester, type Frame, type MenuSubmenuTester, type MenuTester, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, type VideoPlayerTester, expect, testers };
|
package/dist/index.d.ts
CHANGED
|
@@ -323,6 +323,26 @@ interface EditorTester {
|
|
|
323
323
|
startMention: () => Promise<void>;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
interface FileInputTesterOptions extends Omit<BaseTesterOptions, "trigger"> {
|
|
327
|
+
/**
|
|
328
|
+
* The `<FileInput>` root element, not a wrapper around it, to pick one when
|
|
329
|
+
* a page renders several. A `data-testid` passed to `<FileInput>` lands on it.
|
|
330
|
+
*/
|
|
331
|
+
root?: Locator;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Driver for a `<FileInput>` in Playwright component tests. Construct with
|
|
335
|
+
* {@link fileInputTester} (or `testers(frame).fileInput()`).
|
|
336
|
+
*/
|
|
337
|
+
interface FileInputTester {
|
|
338
|
+
/** The root element. */
|
|
339
|
+
readonly root: Locator;
|
|
340
|
+
/** The button that opens the native file picker. */
|
|
341
|
+
readonly button: Locator;
|
|
342
|
+
/** The hidden native file input. */
|
|
343
|
+
readonly input: Locator;
|
|
344
|
+
}
|
|
345
|
+
|
|
326
346
|
/**
|
|
327
347
|
* Options for {@link fileUploaderTester}. The root is always resolved from the
|
|
328
348
|
* stable `data-testid="file-uploader"`; `trigger` overrides the upload
|
|
@@ -582,12 +602,51 @@ interface SelectTesterFactoryFor<O extends {
|
|
|
582
602
|
(options?: O): SelectTester;
|
|
583
603
|
}
|
|
584
604
|
|
|
605
|
+
interface VideoPlayerTesterOptions extends Omit<BaseTesterOptions, "trigger"> {
|
|
606
|
+
/** The accessible name of the player, to pick one when a page has several. */
|
|
607
|
+
name?: string | RegExp;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Driver for a `<VideoPlayer>` in Playwright component tests. Construct with
|
|
611
|
+
* {@link videoPlayerTester} (or `testers(frame).videoPlayer()`).
|
|
612
|
+
*
|
|
613
|
+
* While the video plays, the controls fade out and stop taking pointer input
|
|
614
|
+
* after `controlsHideDelay`; they still count as visible to `toBeVisible()`.
|
|
615
|
+
* Hover `root` to bring them back before clicking one, and assert on
|
|
616
|
+
* `data-controls-visible` rather than visibility.
|
|
617
|
+
*/
|
|
618
|
+
interface VideoPlayerTester {
|
|
619
|
+
/** The player's `group`. Carries `data-state` and `data-controls-visible`. */
|
|
620
|
+
readonly root: Locator;
|
|
621
|
+
/** The native `<video>` element. */
|
|
622
|
+
readonly video: Locator;
|
|
623
|
+
/** The play/pause toggle. Its accessible name flips with the playback state. */
|
|
624
|
+
readonly playButton: Locator;
|
|
625
|
+
/** The timeline slider used to seek. */
|
|
626
|
+
readonly timeline: Locator;
|
|
627
|
+
/** The elapsed-time label. */
|
|
628
|
+
readonly currentTime: Locator;
|
|
629
|
+
/** The duration label. */
|
|
630
|
+
readonly duration: Locator;
|
|
631
|
+
/** The mute/unmute toggle. Its accessible name flips with the muted state. */
|
|
632
|
+
readonly muteButton: Locator;
|
|
633
|
+
/**
|
|
634
|
+
* The enter/exit full screen toggle. Matches nothing where the browser does
|
|
635
|
+
* not allow full screen.
|
|
636
|
+
*/
|
|
637
|
+
readonly fullScreenButton: Locator;
|
|
638
|
+
/** The spinner shown until the video's metadata has loaded. */
|
|
639
|
+
readonly loadingIndicator: Locator;
|
|
640
|
+
}
|
|
641
|
+
|
|
585
642
|
type BoundSelectOptions = Omit<SelectTesterOptions, "frame">;
|
|
586
643
|
type BoundComboBoxOptions = Omit<ComboBoxTesterOptions, "frame">;
|
|
587
644
|
type BoundEditorOptions = Omit<EditorTesterOptions, "frame">;
|
|
645
|
+
type BoundFileInputOptions = Omit<FileInputTesterOptions, "frame">;
|
|
588
646
|
type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
589
647
|
type BoundMenuOptions = Omit<MenuTesterOptions, "frame">;
|
|
590
648
|
type BoundBreadcrumbsOptions = Omit<BreadcrumbsTesterOptions, "frame">;
|
|
649
|
+
type BoundVideoPlayerOptions = Omit<VideoPlayerTesterOptions, "frame">;
|
|
591
650
|
/**
|
|
592
651
|
* The frame-bound tester factory. Methods are flat — one per component — so
|
|
593
652
|
* IDE autocomplete on `t.` lists the full surface in one place. Variants of a
|
|
@@ -601,9 +660,11 @@ interface Testers {
|
|
|
601
660
|
select: SelectTesterFactoryFor<BoundSelectOptions>;
|
|
602
661
|
comboBox: (options?: BoundComboBoxOptions) => ComboBoxTester;
|
|
603
662
|
editor: (options?: BoundEditorOptions) => EditorTester;
|
|
663
|
+
fileInput: (options?: BoundFileInputOptions) => FileInputTester;
|
|
604
664
|
fileUploader: (options?: BoundFileUploaderOptions) => FileUploaderTester;
|
|
605
665
|
menu: (options?: BoundMenuOptions) => MenuTester;
|
|
606
666
|
breadcrumbs: (options?: BoundBreadcrumbsOptions) => BreadcrumbsTester;
|
|
667
|
+
videoPlayer: (options?: BoundVideoPlayerOptions) => VideoPlayerTester;
|
|
607
668
|
}
|
|
608
669
|
/**
|
|
609
670
|
* Build a frame-bound tester factory. Construct once per test and pick the
|
|
@@ -621,4 +682,4 @@ interface Testers {
|
|
|
621
682
|
*/
|
|
622
683
|
declare function testers(frame: Frame): Testers;
|
|
623
684
|
|
|
624
|
-
export { type AutocompleteTester, type BreadcrumbsTester, type ComboBoxTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileUploaderTester, type Frame, type MenuSubmenuTester, type MenuTester, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, expect, testers };
|
|
685
|
+
export { type AutocompleteTester, type BreadcrumbsTester, type ComboBoxTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileInputTester, type FileUploaderTester, type Frame, type MenuSubmenuTester, type MenuTester, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, type VideoPlayerTester, expect, testers };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var test=require('@playwright/test'),
|
|
1
|
+
'use strict';var test=require('@playwright/test'),H=require('axe-core'),promises=require('fs/promises'),P=require('path'),promises$1=require('timers/promises');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var H__default=/*#__PURE__*/_interopDefault(H);var P__default=/*#__PURE__*/_interopDefault(P);/**
|
|
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
|
|
10
|
+
var O=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["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 A(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 x=u||f.getAttribute("aria-hidden")==="true",b=l(f),w=p(f,x);b.length>0?m.push({classes:b,children:w,hidden:x}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let x=c[f],b=f===c.length-1,w=m?"":b?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",j=m?"":u+(b?" ":"\u2502 "),z=x.classes.join(", ");h.push(u+w+z+(x.hidden?" [aria-hidden]":""),...d(x.children,j));}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
|
|
13
|
-
${
|
|
12
|
+
`)}var T=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"}},K=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},Y=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},H__default.default.source);},X=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],Q=(e,t=[])=>{let o=new Set([...L,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??O]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},F=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},Z=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 Y(e);let n=F(t.include),s=F(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})},I="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function ee(e){return Array.isArray(e)?e.length===1&&e[0]===I:e===I}function te(e){return (Array.isArray(e)?e:[e]).join("+")}function oe(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!ee(r)&&s.push(S(te(r))),n&&s.push("ignoreHashed"),P__default.default.join(e,`${s.join("--")}.txt`)}var re=300,ne=25,B=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},k=async e=>{let t=Date.now()+re;for(;e.callCount===0&&Date.now()<t;)await promises$1.setTimeout(ne);},se=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){B(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:()=>T(t),pass:false}}},async toBeCalledTwice(e){B(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:()=>T(t),pass:false}}},async toBeCalledThrice(e){B(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:()=>T(t),pass:false}}},async toBeCalledWith(e,...t){B(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:()=>T(o),pass:false}}},async toBeCalledWithExactly(e,...t){B(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:()=>T(o),pass:false}}},async toBeCalled(e){if(B(e,"toBeCalled"),this.isNot)return await k(e),{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:()=>T(t),pass:false}}},async toBeCalledTimes(e,t){if(B(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");if(t===0)return await k(e),e.callCount===0?{message:()=>"Expected function to be called.",pass:true}:{message:()=>`Expected function not to be called, but it was called ${e.callCount} time(s).`,pass:false};try{return await test.expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>T(o),pass:false}}},async toBeAccessible(e,t={}){let o=await K(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=Q(t,r?X:[]),s,l=async()=>{let i=await Z(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
|
+
${T(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
|
-
${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=
|
|
19
|
-
`,p=test.test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=
|
|
18
|
+
${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=I,ignoreHashed:n=false}=o,s=await e.evaluate(A,{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=oe(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(P__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
|
|
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 y(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}=y(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 U({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:y(r).open,openBackgroundColorPicker:y(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:y(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 M({frame:e,root:t}){let o=t??e.locator(".BaselineUI-FileInput");return {root:o,button:o.getByTestId("file-input-button"),input:o.locator('xpath=following-sibling::input[@type="file"][1]')}}function N({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 _(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}=y(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=_(e,d,p),{open:i}=y(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=_(e,n,r),{button:l,open:p,isOpen:d}=y(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 W=(e=>{let o=ie(e);return e.multiple&&(o=ae(o,e.frame)),e.autocomplete&&(o=le(o,e.frame)),o});function ie({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=y(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function ae(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 le(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function V({frame:e,name:t}){let o=e.locator(".BaselineUI-VideoPlayer"),r=t===void 0?o:o.and(e.getByRole("group",{name:t,exact:typeof t=="string"}));return {root:r,video:r.locator("video"),playButton:r.getByTestId("video-player-play-button"),timeline:r.getByRole("slider"),currentTime:r.getByTestId("video-player-current-time"),duration:r.getByTestId("video-player-duration"),muteButton:r.getByTestId("video-player-mute-button"),fullScreenButton:r.getByTestId("video-player-full-screen-button"),loadingIndicator:r.getByRole("progressbar")}}function ce(e){return {select:((t={})=>W({frame:e,...t})),comboBox:(t={})=>D({frame:e,...t}),editor:(t={})=>U({frame:e,...t}),fileInput:(t={})=>M({frame:e,...t}),fileUploader:(t={})=>N({frame:e,...t}),menu:(t={})=>$({frame:e,...t}),breadcrumbs:(t={})=>v({frame:e,...t}),videoPlayer:(t={})=>V({frame:e,...t})}}exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=E;exports.DEFAULT_DISABLED_RULES=L;exports.DEFAULT_WCAG_TAGS=O;exports.expect=se;exports.testers=ce;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {expect,test}from'@playwright/test';import
|
|
1
|
+
import {expect,test}from'@playwright/test';import H from'axe-core';import {readFile,mkdir,writeFile}from'fs/promises';import P 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
|
|
10
|
+
var O=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["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 A(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 x=u||f.getAttribute("aria-hidden")==="true",b=l(f),w=p(f,x);b.length>0?m.push({classes:b,children:w,hidden:x}):m.push(...w);}return m}function d(c,u="",m=false){let h=[];for(let f=0;f<c.length;f++){let x=c[f],b=f===c.length-1,w=m?"":b?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",j=m?"":u+(b?" ":"\u2502 "),z=x.classes.join(", ");h.push(u+w+z+(x.hidden?" [aria-hidden]":""),...d(x.children,j));}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
|
|
13
|
-
${
|
|
12
|
+
`)}var T=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"}},K=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},Y=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let n=document.createElement("script");n.textContent=o,document.head.append(n);},H.source);},X=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],Q=(e,t=[])=>{let o=new Set([...L,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??O]},rules:Object.fromEntries([...o].map(r=>[r,{enabled:false}]))}},F=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},Z=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 Y(e);let n=F(t.include),s=F(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})},I="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function ee(e){return Array.isArray(e)?e.length===1&&e[0]===I:e===I}function te(e){return (Array.isArray(e)?e:[e]).join("+")}function oe(e,t,o,r,n){let s=t.slice(1).map(l=>S(l));return o&&s.push(S(o)),r!==void 0&&!ee(r)&&s.push(S(te(r))),n&&s.push("ignoreHashed"),P.join(e,`${s.join("--")}.txt`)}var re=300,ne=25,B=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},k=async e=>{let t=Date.now()+re;for(;e.callCount===0&&Date.now()<t;)await setTimeout(ne);},se=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){B(e,"toBeCalledOnce");try{return await expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>T(t),pass:false}}},async toBeCalledTwice(e){B(e,"toBeCalledTwice");try{return await expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>T(t),pass:false}}},async toBeCalledThrice(e){B(e,"toBeCalledThrice");try{return await expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>T(t),pass:false}}},async toBeCalledWith(e,...t){B(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:()=>T(o),pass:false}}},async toBeCalledWithExactly(e,...t){B(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:()=>T(o),pass:false}}},async toBeCalled(e){if(B(e,"toBeCalled"),this.isNot)return await k(e),{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:()=>T(t),pass:false}}},async toBeCalledTimes(e,t){if(B(e,"toBeCalledTimes"),!Number.isInteger(t)||t<0)throw new TypeError("toBeCalledTimes: times must be a non-negative integer.");if(t===0)return await k(e),e.callCount===0?{message:()=>"Expected function to be called.",pass:true}:{message:()=>`Expected function not to be called, but it was called ${e.callCount} time(s).`,pass:false};try{return await expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(o){return {message:()=>T(o),pass:false}}},async toBeAccessible(e,t={}){let o=await K(e),r=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),n=Q(t,r?X:[]),s,l=async()=>{let i=await Z(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
|
+
${T(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
|
-
${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=
|
|
19
|
-
`,p=test.info();if(p.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=
|
|
18
|
+
${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:r=I,ignoreHashed:n=false}=o,s=await e.evaluate(A,{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=oe(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(P.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
|
|
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 y(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}=y(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 U({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:y(r).open,openBackgroundColorPicker:y(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:y(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 M({frame:e,root:t}){let o=t??e.locator(".BaselineUI-FileInput");return {root:o,button:o.getByTestId("file-input-button"),input:o.locator('xpath=following-sibling::input[@type="file"][1]')}}function N({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 _(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}=y(o);return {menu:t,item:r,section:n,isOpen:s,submenu(l){let p=r(l),d=e.getByRole("menu",{name:l}),a=_(e,d,p),{open:i}=y(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=_(e,n,r),{button:l,open:p,isOpen:d}=y(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 W=(e=>{let o=ie(e);return e.multiple&&(o=ae(o,e.frame)),e.autocomplete&&(o=le(o,e.frame)),o});function ie({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),r=s=>e.getByRole("option",{name:s,exact:typeof s=="string"}),{open:n}=y(o);return {trigger:o,listbox:e.getByRole("listbox"),option:r,open:n,async selectOption(s){await n(),await r(s).click();}}}function ae(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 le(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(r){await o.fill(r);}}}function V({frame:e,name:t}){let o=e.locator(".BaselineUI-VideoPlayer"),r=t===void 0?o:o.and(e.getByRole("group",{name:t,exact:typeof t=="string"}));return {root:r,video:r.locator("video"),playButton:r.getByTestId("video-player-play-button"),timeline:r.getByRole("slider"),currentTime:r.getByTestId("video-player-current-time"),duration:r.getByTestId("video-player-duration"),muteButton:r.getByTestId("video-player-mute-button"),fullScreenButton:r.getByTestId("video-player-full-screen-button"),loadingIndicator:r.getByRole("progressbar")}}function ce(e){return {select:((t={})=>W({frame:e,...t})),comboBox:(t={})=>D({frame:e,...t}),editor:(t={})=>U({frame:e,...t}),fileInput:(t={})=>M({frame:e,...t}),fileUploader:(t={})=>N({frame:e,...t}),menu:(t={})=>$({frame:e,...t}),breadcrumbs:(t={})=>v({frame:e,...t}),videoPlayer:(t={})=>V({frame:e,...t})}}export{E as DEFAULT_CRITICAL_INCOMPLETE_RULES,L as DEFAULT_DISABLED_RULES,O as DEFAULT_WCAG_TAGS,se as expect,ce as testers};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baseline-ui/test-utils",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.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.
|
|
55
|
+
"@baseline-ui/core": "3.11.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:
|
|
5
|
+
"serialNumber": "urn:uuid:6eb8daef-325e-4fb2-aacd-4455f6457452",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-11-
|
|
8
|
+
"timestamp": "2026-11-06T09:09:14.944Z",
|
|
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.
|
|
27
|
-
"purl": "pkg:npm/@baseline-ui/test-utils@3.
|
|
28
|
-
"bom-ref": "pkg:npm/@baseline-ui/test-utils@3.
|
|
26
|
+
"version": "3.11.0",
|
|
27
|
+
"purl": "pkg:npm/@baseline-ui/test-utils@3.11.0",
|
|
28
|
+
"bom-ref": "pkg:npm/@baseline-ui/test-utils@3.11.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.
|
|
503
|
+
"ref": "pkg:npm/@baseline-ui/test-utils@3.11.0",
|
|
504
504
|
"dependsOn": [
|
|
505
505
|
"pkg:npm/%40neondatabase/serverless@1.1.0",
|
|
506
506
|
"pkg:npm/%40playwright/test@1.62.1",
|