@baseline-ui/test-utils 1.1.0 → 2.0.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/client/index.d.mts +2 -2
- package/client/index.d.ts +2 -2
- package/client/index.js +2 -2
- package/client/index.mjs +2 -2
- package/dist/index.d.mts +148 -17
- package/dist/index.d.ts +148 -17
- package/dist/index.js +12 -12
- package/dist/index.mjs +12 -12
- package/package.json +2 -2
- package/sbom.json +6 -6
package/client/index.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { StylingProps, I18nProviderProps, ThemeProviderProps } from '@baseline-ui/core';
|
|
3
3
|
import { FrameComponentProps } from 'react-frame-component';
|
|
4
4
|
|
|
5
|
-
declare const IFrame: React.ForwardRefExoticComponent<IFrameProps & React.RefAttributes<HTMLIFrameElement>>;
|
|
6
|
-
interface IFrameProps extends FrameComponentProps, StylingProps {
|
|
5
|
+
declare const IFrame: React.ForwardRefExoticComponent<Omit<IFrameProps, "ref"> & React.RefAttributes<HTMLIFrameElement>>;
|
|
6
|
+
interface IFrameProps extends FrameComponentProps, Omit<React.IframeHTMLAttributes<HTMLIFrameElement>, keyof FrameComponentProps>, StylingProps {
|
|
7
7
|
}
|
|
8
8
|
declare const ShadowRoot: React.ForwardRefExoticComponent<ShadowRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
9
|
interface ShadowRootProps {
|
package/client/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { StylingProps, I18nProviderProps, ThemeProviderProps } from '@baseline-ui/core';
|
|
3
3
|
import { FrameComponentProps } from 'react-frame-component';
|
|
4
4
|
|
|
5
|
-
declare const IFrame: React.ForwardRefExoticComponent<IFrameProps & React.RefAttributes<HTMLIFrameElement>>;
|
|
6
|
-
interface IFrameProps extends FrameComponentProps, StylingProps {
|
|
5
|
+
declare const IFrame: React.ForwardRefExoticComponent<Omit<IFrameProps, "ref"> & React.RefAttributes<HTMLIFrameElement>>;
|
|
6
|
+
interface IFrameProps extends FrameComponentProps, Omit<React.IframeHTMLAttributes<HTMLIFrameElement>, keyof FrameComponentProps>, StylingProps {
|
|
7
7
|
}
|
|
8
8
|
declare const ShadowRoot: React.ForwardRefExoticComponent<ShadowRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
9
|
interface ShadowRootProps {
|
package/client/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var core=require('@baseline-ui/core'),
|
|
1
|
+
'use strict';var core=require('@baseline-ui/core'),m=require('react'),w=require('react-dom/client'),E=require('react-frame-component'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);var w__default=/*#__PURE__*/_interopDefault(w);var E__default=/*#__PURE__*/_interopDefault(E);/**
|
|
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
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
10
|
function h(){let t=[],r=document;for(let o=0;o<r.styleSheets.length;o++){let n=r.styleSheets[o];if(n.cssRules){let i=n.cssRules;for(let s of i)t.push(s.cssText);}}return t.join(`
|
|
11
|
-
`)}var
|
|
11
|
+
`)}var T=m__default.default.forwardRef(({head:t=jsxRuntime.jsx("style",{children:h()}),...r},o)=>jsxRuntime.jsx(E__default.default,{style:{width:"100vw",height:"100vh",border:"none"},ref:o,...r,head:t}));T.displayName="IFrame";var x=m__default.default.forwardRef(({children:t,style:r},o)=>{let n=core.useObjectRef(o),i=m__default.default.useRef(null),s=m__default.default.useRef(null),d=m__default.default.useRef(null),l=m__default.default.useRef(false),P=m__default.default.useMemo(()=>h(),[]);return m.useEffect(()=>{if(l.current=false,n.current&&!i.current){let e=n.current.attachShadow({mode:"open"});i.current=e;let a=document.createElement("style");a.textContent=P,e.append(a);let u=document.createElement("div");u.className="content-container",e.append(u);let p=document.createElement("div");p.className="overlay-portal",e.append(p),d.current=p;let y=w__default.default.createRoot(u);s.current=y;}return ()=>{l.current=true;let e=s.current;e&&(queueMicrotask(()=>{e.unmount();}),s.current=null),i.current=null,d.current=null;}},[P,n]),m.useEffect(()=>{if(l.current)return;let e=s.current,a=d.current;e&&a&&e.render(jsxRuntime.jsx(core.PortalContainerProvider,{portalContainer:a,children:t}));},[t]),jsxRuntime.jsx("div",{style:r,ref:n})});x.displayName="ShadowRoot";var Q=({children:t,locale:r,theme:o,themeStyle:n,disableThemeProvider:i=false,disableFrameProvider:s=false,messages:d})=>{let[l,P]=m.useState(),{document:e}=E.useFrame(),a=r==="ar"||r==="he";m.useLayoutEffect(()=>{a?e?.documentElement.setAttribute("dir","rtl"):e?.documentElement.removeAttribute("dir");},[a,e]);let u=l?.ownerDocument?.body,p=[i?void 0:({children:c})=>jsxRuntime.jsx(core.ThemeProvider,{theme:o,style:n,children:c}),s?void 0:({children:c})=>jsxRuntime.jsx(core.FrameProvider,{container:u,portalContainer:l,children:c})].filter(Boolean);return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(core.I18nProvider,{locale:r,messages:d,children:jsxRuntime.jsx(({children:c})=>{let v=c;for(let C of [...p].toReversed())v=C?.({children:v});return v},{children:t})}),jsxRuntime.jsx("div",{id:"portal-container",ref:c=>{P(c??void 0);}})]})};exports.IFrame=T;exports.ProvidersContainer=Q;exports.ShadowRoot=x;exports.getRootStyles=h;
|
package/client/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useObjectRef,PortalContainerProvider,I18nProvider,ThemeProvider,FrameProvider}from'@baseline-ui/core';import
|
|
1
|
+
import {useObjectRef,PortalContainerProvider,I18nProvider,ThemeProvider,FrameProvider}from'@baseline-ui/core';import m,{useEffect,useState,useLayoutEffect}from'react';import w from'react-dom/client';import E,{useFrame}from'react-frame-component';import {jsx,jsxs,Fragment}from'react/jsx-runtime';/**
|
|
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
|
|
@@ -8,4 +8,4 @@ import {useObjectRef,PortalContainerProvider,I18nProvider,ThemeProvider,FramePro
|
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
10
|
function h(){let t=[],r=document;for(let o=0;o<r.styleSheets.length;o++){let n=r.styleSheets[o];if(n.cssRules){let i=n.cssRules;for(let s of i)t.push(s.cssText);}}return t.join(`
|
|
11
|
-
`)}var
|
|
11
|
+
`)}var T=m.forwardRef(({head:t=jsx("style",{children:h()}),...r},o)=>jsx(E,{style:{width:"100vw",height:"100vh",border:"none"},ref:o,...r,head:t}));T.displayName="IFrame";var x=m.forwardRef(({children:t,style:r},o)=>{let n=useObjectRef(o),i=m.useRef(null),s=m.useRef(null),d=m.useRef(null),l=m.useRef(false),P=m.useMemo(()=>h(),[]);return useEffect(()=>{if(l.current=false,n.current&&!i.current){let e=n.current.attachShadow({mode:"open"});i.current=e;let a=document.createElement("style");a.textContent=P,e.append(a);let u=document.createElement("div");u.className="content-container",e.append(u);let p=document.createElement("div");p.className="overlay-portal",e.append(p),d.current=p;let y=w.createRoot(u);s.current=y;}return ()=>{l.current=true;let e=s.current;e&&(queueMicrotask(()=>{e.unmount();}),s.current=null),i.current=null,d.current=null;}},[P,n]),useEffect(()=>{if(l.current)return;let e=s.current,a=d.current;e&&a&&e.render(jsx(PortalContainerProvider,{portalContainer:a,children:t}));},[t]),jsx("div",{style:r,ref:n})});x.displayName="ShadowRoot";var Q=({children:t,locale:r,theme:o,themeStyle:n,disableThemeProvider:i=false,disableFrameProvider:s=false,messages:d})=>{let[l,P]=useState(),{document:e}=useFrame(),a=r==="ar"||r==="he";useLayoutEffect(()=>{a?e?.documentElement.setAttribute("dir","rtl"):e?.documentElement.removeAttribute("dir");},[a,e]);let u=l?.ownerDocument?.body,p=[i?void 0:({children:c})=>jsx(ThemeProvider,{theme:o,style:n,children:c}),s?void 0:({children:c})=>jsx(FrameProvider,{container:u,portalContainer:l,children:c})].filter(Boolean);return jsxs(Fragment,{children:[jsx(I18nProvider,{locale:r,messages:d,children:jsx(({children:c})=>{let v=c;for(let C of [...p].toReversed())v=C?.({children:v});return v},{children:t})}),jsx("div",{id:"portal-container",ref:c=>{P(c??void 0);}})]})};export{T as IFrame,Q as ProvidersContainer,x as ShadowRoot,h as getRootStyles};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as playwright_test from 'playwright/test';
|
|
2
2
|
import { Page, Locator, FrameLocator } from '@playwright/test';
|
|
3
3
|
import { SinonSpy } from 'sinon';
|
|
4
4
|
|
|
@@ -29,57 +29,57 @@ interface ToBeAccessibleOptions {
|
|
|
29
29
|
attachmentName?: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
declare const expect:
|
|
33
|
-
toBeWithinDelta(this:
|
|
32
|
+
declare const expect: playwright_test.Expect<{
|
|
33
|
+
toBeWithinDelta(this: playwright_test.ExpectMatcherState, received: number, expected: number, delta: number): {
|
|
34
34
|
message: () => string;
|
|
35
35
|
pass: true;
|
|
36
36
|
} | {
|
|
37
37
|
message: () => string;
|
|
38
38
|
pass: false;
|
|
39
39
|
};
|
|
40
|
-
toBeCalledOnce(this:
|
|
40
|
+
toBeCalledOnce(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
41
41
|
message: () => string;
|
|
42
42
|
pass: true;
|
|
43
43
|
} | {
|
|
44
44
|
message: () => string;
|
|
45
45
|
pass: false;
|
|
46
46
|
}>;
|
|
47
|
-
toBeCalledTwice(this:
|
|
47
|
+
toBeCalledTwice(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
48
48
|
message: () => string;
|
|
49
49
|
pass: true;
|
|
50
50
|
} | {
|
|
51
51
|
message: () => string;
|
|
52
52
|
pass: false;
|
|
53
53
|
}>;
|
|
54
|
-
toBeCalledThrice(this:
|
|
54
|
+
toBeCalledThrice(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
55
55
|
message: () => string;
|
|
56
56
|
pass: true;
|
|
57
57
|
} | {
|
|
58
58
|
message: () => string;
|
|
59
59
|
pass: false;
|
|
60
60
|
}>;
|
|
61
|
-
toBeCalledWith(this:
|
|
61
|
+
toBeCalledWith(this: playwright_test.ExpectMatcherState, fn: SinonSpy, ...args: unknown[]): Promise<{
|
|
62
62
|
message: () => string;
|
|
63
63
|
pass: true;
|
|
64
64
|
} | {
|
|
65
65
|
message: () => string;
|
|
66
66
|
pass: false;
|
|
67
67
|
}>;
|
|
68
|
-
toBeCalledWithExactly(this:
|
|
68
|
+
toBeCalledWithExactly(this: playwright_test.ExpectMatcherState, fn: SinonSpy, ...args: unknown[]): Promise<{
|
|
69
69
|
message: () => string;
|
|
70
70
|
pass: true;
|
|
71
71
|
} | {
|
|
72
72
|
message: () => string;
|
|
73
73
|
pass: false;
|
|
74
74
|
}>;
|
|
75
|
-
toBeCalled(this:
|
|
75
|
+
toBeCalled(this: playwright_test.ExpectMatcherState, fn: SinonSpy): {
|
|
76
76
|
message: () => string;
|
|
77
77
|
pass: true;
|
|
78
78
|
} | {
|
|
79
79
|
message: () => string;
|
|
80
80
|
pass: false;
|
|
81
81
|
};
|
|
82
|
-
toBeCalledTimes(this:
|
|
82
|
+
toBeCalledTimes(this: playwright_test.ExpectMatcherState, fn: SinonSpy, times: number): Promise<{
|
|
83
83
|
message: () => string;
|
|
84
84
|
pass: true;
|
|
85
85
|
} | {
|
|
@@ -95,7 +95,7 @@ declare const expect: _playwright_test.Expect<{
|
|
|
95
95
|
message: () => string;
|
|
96
96
|
pass: false;
|
|
97
97
|
}>;
|
|
98
|
-
toMatchClassTree(this:
|
|
98
|
+
toMatchClassTree(this: playwright_test.ExpectMatcherState, locator: Locator, snapshotName?: string, options?: {
|
|
99
99
|
prefix?: string | string[];
|
|
100
100
|
ignoreHashed?: boolean;
|
|
101
101
|
}): Promise<{
|
|
@@ -133,11 +133,69 @@ interface BaseTesterOptions {
|
|
|
133
133
|
/**
|
|
134
134
|
* Keys recognised by {@link disclosure}'s `open(how)`. The same set covers
|
|
135
135
|
* Select, Menu, Combobox and DatePicker — disclosure-style components whose
|
|
136
|
-
* trigger expands a popover.
|
|
137
|
-
*
|
|
138
|
-
*
|
|
136
|
+
* trigger expands a popover. `ArrowRight`/`ArrowLeft` additionally cover Menu
|
|
137
|
+
* submenu triggers (which expand toward the inline-end in LTR). Components that
|
|
138
|
+
* only open via click (e.g. a Dialog with no keyboard activation other than
|
|
139
|
+
* Enter) can ignore the keyboard paths and simply call `open("click")`.
|
|
139
140
|
*/
|
|
140
|
-
type DisclosureOpenWith = "click" | "Space" | "Enter" | "ArrowDown" | "ArrowUp";
|
|
141
|
+
type DisclosureOpenWith = "click" | "Space" | "Enter" | "ArrowDown" | "ArrowUp" | "ArrowRight" | "ArrowLeft";
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* How to open a ComboBox from the keyboard. `Space` and `Enter` are excluded
|
|
145
|
+
* from {@link DisclosureOpenWith}: the input is a text field, so `Space` would
|
|
146
|
+
* type a character and `Enter` submits rather than opening.
|
|
147
|
+
*/
|
|
148
|
+
type ComboBoxOpenWith = Extract<DisclosureOpenWith, "click" | "ArrowDown" | "ArrowUp">;
|
|
149
|
+
/**
|
|
150
|
+
* Options for {@link comboBoxTester}. Unlike Select, a ComboBox has two
|
|
151
|
+
* distinct interactive surfaces: the text input (which carries
|
|
152
|
+
* `aria-expanded`, so it is the disclosure host) and the chevron toggle
|
|
153
|
+
* button. Override both together when the consumer renders a custom trigger
|
|
154
|
+
* whose parts the defaults do not reach.
|
|
155
|
+
*/
|
|
156
|
+
interface ComboBoxTesterOptions extends BaseTesterOptions {
|
|
157
|
+
/**
|
|
158
|
+
* The chevron button. Defaults to `data-testid="combobox-toggle-button"`.
|
|
159
|
+
* Pass this alongside `trigger` for a custom trigger — otherwise `open()`
|
|
160
|
+
* clicks a test id the custom markup does not render.
|
|
161
|
+
*/
|
|
162
|
+
toggleButton?: Locator;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Driver for a `<ComboBox>` in Playwright component tests.
|
|
166
|
+
* Construct with {@link comboBoxTester}.
|
|
167
|
+
*/
|
|
168
|
+
interface ComboBoxTester {
|
|
169
|
+
/** The text input. Located by `role="combobox"`, which carries `aria-expanded`. */
|
|
170
|
+
readonly input: Locator;
|
|
171
|
+
/** The chevron button that opens the popover. */
|
|
172
|
+
readonly toggleButton: Locator;
|
|
173
|
+
/** The popover listbox. Only attached while the ComboBox is open. */
|
|
174
|
+
readonly listbox: Locator;
|
|
175
|
+
/**
|
|
176
|
+
* Locator for a single option by accessible name. A string matches the
|
|
177
|
+
* full name exactly (case-sensitive, whitespace-trimmed); pass a RegExp
|
|
178
|
+
* for partial matching.
|
|
179
|
+
*/
|
|
180
|
+
option: (name: string | RegExp) => Locator;
|
|
181
|
+
/** Whether the ComboBox reports `aria-expanded="true"`. */
|
|
182
|
+
isOpen: () => Promise<boolean>;
|
|
183
|
+
/**
|
|
184
|
+
* Opens the ComboBox if it isn't already open. Idempotent.
|
|
185
|
+
*
|
|
186
|
+
* @param how How to open. Defaults to `"click"`, which presses the toggle
|
|
187
|
+
* button. Arrow keys focus the input and press the key — matching how a
|
|
188
|
+
* keyboard user reaches the listbox.
|
|
189
|
+
*/
|
|
190
|
+
open: (how?: ComboBoxOpenWith) => Promise<void>;
|
|
191
|
+
/** Opens the ComboBox (if needed) and clicks the option matching `name`. */
|
|
192
|
+
selectOption: (name: string | RegExp) => Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Types into the input to filter options, replacing any existing value.
|
|
195
|
+
* Opens the listbox as a side effect under the default `menuTrigger`.
|
|
196
|
+
*/
|
|
197
|
+
filter: (text: string) => Promise<void>;
|
|
198
|
+
}
|
|
141
199
|
|
|
142
200
|
/**
|
|
143
201
|
* Options for {@link editorTester}. The Editor has no single disclosure
|
|
@@ -261,6 +319,71 @@ interface FileUploaderTester {
|
|
|
261
319
|
upload: (files: Parameters<Locator["setInputFiles"]>[0]) => Promise<void>;
|
|
262
320
|
}
|
|
263
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Options for {@link menuTester}. Defaults the trigger to
|
|
324
|
+
* `frame.getByTestId("menu-trigger")` (the default `<Menu>` trigger). Pass
|
|
325
|
+
* `trigger` when the Menu renders a custom trigger via `renderTrigger` that
|
|
326
|
+
* doesn't carry that test id.
|
|
327
|
+
*/
|
|
328
|
+
type MenuTesterOptions = BaseTesterOptions;
|
|
329
|
+
/**
|
|
330
|
+
* Locators + verbs shared by a menu and each of its submenus. A submenu is
|
|
331
|
+
* itself a menu opened from a `menuitem`, so the recursive surface (items,
|
|
332
|
+
* sections, nested submenus) is identical — only how you *open* it differs
|
|
333
|
+
* (root: click/keyboard the trigger button; submenu: hover/arrow the
|
|
334
|
+
* `menuitem` trigger). Both are modelled through {@link disclosure} on their
|
|
335
|
+
* respective `aria-expanded` trigger.
|
|
336
|
+
*/
|
|
337
|
+
interface MenuLevelTester {
|
|
338
|
+
/** The `role="menu"` element for this level. Only attached while open. */
|
|
339
|
+
readonly menu: Locator;
|
|
340
|
+
/** A `menuitem` within this level, by accessible name. */
|
|
341
|
+
item: (name: string | RegExp) => Locator;
|
|
342
|
+
/** A `role="group"` section within this level, by accessible name. */
|
|
343
|
+
section: (name: string | RegExp) => Locator;
|
|
344
|
+
/** Whether this level's trigger reports `aria-expanded="true"`. */
|
|
345
|
+
isOpen: () => Promise<boolean>;
|
|
346
|
+
/**
|
|
347
|
+
* Scopes into a submenu opened from the `menuitem` matching `triggerName`.
|
|
348
|
+
* Returns a {@link MenuSubmenuTester} whose `item`/`section` are scoped to
|
|
349
|
+
* the nested menu, so identically-named items across levels don't collide.
|
|
350
|
+
*/
|
|
351
|
+
submenu: (triggerName: string | RegExp) => MenuSubmenuTester;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Driver for a `<Menu>` in Playwright component tests. Construct via
|
|
355
|
+
* `testers(frame).menu()`.
|
|
356
|
+
*/
|
|
357
|
+
interface MenuTester extends MenuLevelTester {
|
|
358
|
+
/** The trigger button that opens the root menu. */
|
|
359
|
+
readonly trigger: Locator;
|
|
360
|
+
/**
|
|
361
|
+
* Opens the root menu if it isn't already open. Idempotent (checks
|
|
362
|
+
* `aria-expanded`). Defaults to `"click"`.
|
|
363
|
+
*/
|
|
364
|
+
open: (how?: DisclosureOpenWith) => Promise<void>;
|
|
365
|
+
/** Closes the menu if open, via `Escape`. Idempotent. */
|
|
366
|
+
close: () => Promise<void>;
|
|
367
|
+
/** Opens the root menu (if needed) and clicks the leaf item `name`. */
|
|
368
|
+
selectItem: (name: string | RegExp) => Promise<void>;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* A submenu level. Adds the `menuitem` trigger and an `open()` that expands it
|
|
372
|
+
* (submenu triggers open on hover or `ArrowRight`/`Enter`).
|
|
373
|
+
*/
|
|
374
|
+
interface MenuSubmenuTester extends MenuLevelTester {
|
|
375
|
+
/** The `menuitem` that expands this submenu. */
|
|
376
|
+
readonly trigger: Locator;
|
|
377
|
+
/**
|
|
378
|
+
* Expands this submenu if it isn't already open. Idempotent (checks the
|
|
379
|
+
* trigger's `aria-expanded`). Defaults to `"Enter"`, which opens the submenu
|
|
380
|
+
* in both LTR and RTL (the expand arrow is direction-dependent:
|
|
381
|
+
* `ArrowRight` in LTR, `ArrowLeft` in RTL). Pass `"click"` to activate by
|
|
382
|
+
* pointer, or an explicit arrow key to test direction-specific behavior.
|
|
383
|
+
*/
|
|
384
|
+
open: (how?: DisclosureOpenWith) => Promise<void>;
|
|
385
|
+
}
|
|
386
|
+
|
|
264
387
|
/**
|
|
265
388
|
* Options for {@link selectTester}. Defaults the trigger to
|
|
266
389
|
* `frame.getByTestId("select-button")` (the convention for both single- and
|
|
@@ -290,7 +413,11 @@ interface SelectTester {
|
|
|
290
413
|
readonly trigger: Locator;
|
|
291
414
|
/** The popover listbox. Only attached while the Select is open. */
|
|
292
415
|
readonly listbox: Locator;
|
|
293
|
-
/**
|
|
416
|
+
/**
|
|
417
|
+
* Locator for a single option by accessible name. A string matches the
|
|
418
|
+
* full name exactly (case-sensitive, whitespace-trimmed); pass a RegExp
|
|
419
|
+
* for partial matching.
|
|
420
|
+
*/
|
|
294
421
|
option: (name: string | RegExp) => Locator;
|
|
295
422
|
/**
|
|
296
423
|
* Opens the Select if it isn't already open. Idempotent — checks
|
|
@@ -394,8 +521,10 @@ interface SelectTesterFactoryFor<O extends {
|
|
|
394
521
|
}
|
|
395
522
|
|
|
396
523
|
type BoundSelectOptions = Omit<SelectTesterOptions, "frame">;
|
|
524
|
+
type BoundComboBoxOptions = Omit<ComboBoxTesterOptions, "frame">;
|
|
397
525
|
type BoundEditorOptions = Omit<EditorTesterOptions, "frame">;
|
|
398
526
|
type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
527
|
+
type BoundMenuOptions = Omit<MenuTesterOptions, "frame">;
|
|
399
528
|
/**
|
|
400
529
|
* The frame-bound tester factory. Methods are flat — one per component — so
|
|
401
530
|
* IDE autocomplete on `t.` lists the full surface in one place. Variants of a
|
|
@@ -407,8 +536,10 @@ type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
|
407
536
|
*/
|
|
408
537
|
interface Testers {
|
|
409
538
|
select: SelectTesterFactoryFor<BoundSelectOptions>;
|
|
539
|
+
comboBox: (options?: BoundComboBoxOptions) => ComboBoxTester;
|
|
410
540
|
editor: (options?: BoundEditorOptions) => EditorTester;
|
|
411
541
|
fileUploader: (options?: BoundFileUploaderOptions) => FileUploaderTester;
|
|
542
|
+
menu: (options?: BoundMenuOptions) => MenuTester;
|
|
412
543
|
}
|
|
413
544
|
/**
|
|
414
545
|
* Build a frame-bound tester factory. Construct once per test and pick the
|
|
@@ -426,4 +557,4 @@ interface Testers {
|
|
|
426
557
|
*/
|
|
427
558
|
declare function testers(frame: Frame): Testers;
|
|
428
559
|
|
|
429
|
-
export { type AutocompleteTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileUploaderTester, type Frame, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, expect, testers };
|
|
560
|
+
export { type AutocompleteTester, 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as playwright_test from 'playwright/test';
|
|
2
2
|
import { Page, Locator, FrameLocator } from '@playwright/test';
|
|
3
3
|
import { SinonSpy } from 'sinon';
|
|
4
4
|
|
|
@@ -29,57 +29,57 @@ interface ToBeAccessibleOptions {
|
|
|
29
29
|
attachmentName?: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
declare const expect:
|
|
33
|
-
toBeWithinDelta(this:
|
|
32
|
+
declare const expect: playwright_test.Expect<{
|
|
33
|
+
toBeWithinDelta(this: playwright_test.ExpectMatcherState, received: number, expected: number, delta: number): {
|
|
34
34
|
message: () => string;
|
|
35
35
|
pass: true;
|
|
36
36
|
} | {
|
|
37
37
|
message: () => string;
|
|
38
38
|
pass: false;
|
|
39
39
|
};
|
|
40
|
-
toBeCalledOnce(this:
|
|
40
|
+
toBeCalledOnce(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
41
41
|
message: () => string;
|
|
42
42
|
pass: true;
|
|
43
43
|
} | {
|
|
44
44
|
message: () => string;
|
|
45
45
|
pass: false;
|
|
46
46
|
}>;
|
|
47
|
-
toBeCalledTwice(this:
|
|
47
|
+
toBeCalledTwice(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
48
48
|
message: () => string;
|
|
49
49
|
pass: true;
|
|
50
50
|
} | {
|
|
51
51
|
message: () => string;
|
|
52
52
|
pass: false;
|
|
53
53
|
}>;
|
|
54
|
-
toBeCalledThrice(this:
|
|
54
|
+
toBeCalledThrice(this: playwright_test.ExpectMatcherState, fn: SinonSpy): Promise<{
|
|
55
55
|
message: () => string;
|
|
56
56
|
pass: true;
|
|
57
57
|
} | {
|
|
58
58
|
message: () => string;
|
|
59
59
|
pass: false;
|
|
60
60
|
}>;
|
|
61
|
-
toBeCalledWith(this:
|
|
61
|
+
toBeCalledWith(this: playwright_test.ExpectMatcherState, fn: SinonSpy, ...args: unknown[]): Promise<{
|
|
62
62
|
message: () => string;
|
|
63
63
|
pass: true;
|
|
64
64
|
} | {
|
|
65
65
|
message: () => string;
|
|
66
66
|
pass: false;
|
|
67
67
|
}>;
|
|
68
|
-
toBeCalledWithExactly(this:
|
|
68
|
+
toBeCalledWithExactly(this: playwright_test.ExpectMatcherState, fn: SinonSpy, ...args: unknown[]): Promise<{
|
|
69
69
|
message: () => string;
|
|
70
70
|
pass: true;
|
|
71
71
|
} | {
|
|
72
72
|
message: () => string;
|
|
73
73
|
pass: false;
|
|
74
74
|
}>;
|
|
75
|
-
toBeCalled(this:
|
|
75
|
+
toBeCalled(this: playwright_test.ExpectMatcherState, fn: SinonSpy): {
|
|
76
76
|
message: () => string;
|
|
77
77
|
pass: true;
|
|
78
78
|
} | {
|
|
79
79
|
message: () => string;
|
|
80
80
|
pass: false;
|
|
81
81
|
};
|
|
82
|
-
toBeCalledTimes(this:
|
|
82
|
+
toBeCalledTimes(this: playwright_test.ExpectMatcherState, fn: SinonSpy, times: number): Promise<{
|
|
83
83
|
message: () => string;
|
|
84
84
|
pass: true;
|
|
85
85
|
} | {
|
|
@@ -95,7 +95,7 @@ declare const expect: _playwright_test.Expect<{
|
|
|
95
95
|
message: () => string;
|
|
96
96
|
pass: false;
|
|
97
97
|
}>;
|
|
98
|
-
toMatchClassTree(this:
|
|
98
|
+
toMatchClassTree(this: playwright_test.ExpectMatcherState, locator: Locator, snapshotName?: string, options?: {
|
|
99
99
|
prefix?: string | string[];
|
|
100
100
|
ignoreHashed?: boolean;
|
|
101
101
|
}): Promise<{
|
|
@@ -133,11 +133,69 @@ interface BaseTesterOptions {
|
|
|
133
133
|
/**
|
|
134
134
|
* Keys recognised by {@link disclosure}'s `open(how)`. The same set covers
|
|
135
135
|
* Select, Menu, Combobox and DatePicker — disclosure-style components whose
|
|
136
|
-
* trigger expands a popover.
|
|
137
|
-
*
|
|
138
|
-
*
|
|
136
|
+
* trigger expands a popover. `ArrowRight`/`ArrowLeft` additionally cover Menu
|
|
137
|
+
* submenu triggers (which expand toward the inline-end in LTR). Components that
|
|
138
|
+
* only open via click (e.g. a Dialog with no keyboard activation other than
|
|
139
|
+
* Enter) can ignore the keyboard paths and simply call `open("click")`.
|
|
139
140
|
*/
|
|
140
|
-
type DisclosureOpenWith = "click" | "Space" | "Enter" | "ArrowDown" | "ArrowUp";
|
|
141
|
+
type DisclosureOpenWith = "click" | "Space" | "Enter" | "ArrowDown" | "ArrowUp" | "ArrowRight" | "ArrowLeft";
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* How to open a ComboBox from the keyboard. `Space` and `Enter` are excluded
|
|
145
|
+
* from {@link DisclosureOpenWith}: the input is a text field, so `Space` would
|
|
146
|
+
* type a character and `Enter` submits rather than opening.
|
|
147
|
+
*/
|
|
148
|
+
type ComboBoxOpenWith = Extract<DisclosureOpenWith, "click" | "ArrowDown" | "ArrowUp">;
|
|
149
|
+
/**
|
|
150
|
+
* Options for {@link comboBoxTester}. Unlike Select, a ComboBox has two
|
|
151
|
+
* distinct interactive surfaces: the text input (which carries
|
|
152
|
+
* `aria-expanded`, so it is the disclosure host) and the chevron toggle
|
|
153
|
+
* button. Override both together when the consumer renders a custom trigger
|
|
154
|
+
* whose parts the defaults do not reach.
|
|
155
|
+
*/
|
|
156
|
+
interface ComboBoxTesterOptions extends BaseTesterOptions {
|
|
157
|
+
/**
|
|
158
|
+
* The chevron button. Defaults to `data-testid="combobox-toggle-button"`.
|
|
159
|
+
* Pass this alongside `trigger` for a custom trigger — otherwise `open()`
|
|
160
|
+
* clicks a test id the custom markup does not render.
|
|
161
|
+
*/
|
|
162
|
+
toggleButton?: Locator;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Driver for a `<ComboBox>` in Playwright component tests.
|
|
166
|
+
* Construct with {@link comboBoxTester}.
|
|
167
|
+
*/
|
|
168
|
+
interface ComboBoxTester {
|
|
169
|
+
/** The text input. Located by `role="combobox"`, which carries `aria-expanded`. */
|
|
170
|
+
readonly input: Locator;
|
|
171
|
+
/** The chevron button that opens the popover. */
|
|
172
|
+
readonly toggleButton: Locator;
|
|
173
|
+
/** The popover listbox. Only attached while the ComboBox is open. */
|
|
174
|
+
readonly listbox: Locator;
|
|
175
|
+
/**
|
|
176
|
+
* Locator for a single option by accessible name. A string matches the
|
|
177
|
+
* full name exactly (case-sensitive, whitespace-trimmed); pass a RegExp
|
|
178
|
+
* for partial matching.
|
|
179
|
+
*/
|
|
180
|
+
option: (name: string | RegExp) => Locator;
|
|
181
|
+
/** Whether the ComboBox reports `aria-expanded="true"`. */
|
|
182
|
+
isOpen: () => Promise<boolean>;
|
|
183
|
+
/**
|
|
184
|
+
* Opens the ComboBox if it isn't already open. Idempotent.
|
|
185
|
+
*
|
|
186
|
+
* @param how How to open. Defaults to `"click"`, which presses the toggle
|
|
187
|
+
* button. Arrow keys focus the input and press the key — matching how a
|
|
188
|
+
* keyboard user reaches the listbox.
|
|
189
|
+
*/
|
|
190
|
+
open: (how?: ComboBoxOpenWith) => Promise<void>;
|
|
191
|
+
/** Opens the ComboBox (if needed) and clicks the option matching `name`. */
|
|
192
|
+
selectOption: (name: string | RegExp) => Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Types into the input to filter options, replacing any existing value.
|
|
195
|
+
* Opens the listbox as a side effect under the default `menuTrigger`.
|
|
196
|
+
*/
|
|
197
|
+
filter: (text: string) => Promise<void>;
|
|
198
|
+
}
|
|
141
199
|
|
|
142
200
|
/**
|
|
143
201
|
* Options for {@link editorTester}. The Editor has no single disclosure
|
|
@@ -261,6 +319,71 @@ interface FileUploaderTester {
|
|
|
261
319
|
upload: (files: Parameters<Locator["setInputFiles"]>[0]) => Promise<void>;
|
|
262
320
|
}
|
|
263
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Options for {@link menuTester}. Defaults the trigger to
|
|
324
|
+
* `frame.getByTestId("menu-trigger")` (the default `<Menu>` trigger). Pass
|
|
325
|
+
* `trigger` when the Menu renders a custom trigger via `renderTrigger` that
|
|
326
|
+
* doesn't carry that test id.
|
|
327
|
+
*/
|
|
328
|
+
type MenuTesterOptions = BaseTesterOptions;
|
|
329
|
+
/**
|
|
330
|
+
* Locators + verbs shared by a menu and each of its submenus. A submenu is
|
|
331
|
+
* itself a menu opened from a `menuitem`, so the recursive surface (items,
|
|
332
|
+
* sections, nested submenus) is identical — only how you *open* it differs
|
|
333
|
+
* (root: click/keyboard the trigger button; submenu: hover/arrow the
|
|
334
|
+
* `menuitem` trigger). Both are modelled through {@link disclosure} on their
|
|
335
|
+
* respective `aria-expanded` trigger.
|
|
336
|
+
*/
|
|
337
|
+
interface MenuLevelTester {
|
|
338
|
+
/** The `role="menu"` element for this level. Only attached while open. */
|
|
339
|
+
readonly menu: Locator;
|
|
340
|
+
/** A `menuitem` within this level, by accessible name. */
|
|
341
|
+
item: (name: string | RegExp) => Locator;
|
|
342
|
+
/** A `role="group"` section within this level, by accessible name. */
|
|
343
|
+
section: (name: string | RegExp) => Locator;
|
|
344
|
+
/** Whether this level's trigger reports `aria-expanded="true"`. */
|
|
345
|
+
isOpen: () => Promise<boolean>;
|
|
346
|
+
/**
|
|
347
|
+
* Scopes into a submenu opened from the `menuitem` matching `triggerName`.
|
|
348
|
+
* Returns a {@link MenuSubmenuTester} whose `item`/`section` are scoped to
|
|
349
|
+
* the nested menu, so identically-named items across levels don't collide.
|
|
350
|
+
*/
|
|
351
|
+
submenu: (triggerName: string | RegExp) => MenuSubmenuTester;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Driver for a `<Menu>` in Playwright component tests. Construct via
|
|
355
|
+
* `testers(frame).menu()`.
|
|
356
|
+
*/
|
|
357
|
+
interface MenuTester extends MenuLevelTester {
|
|
358
|
+
/** The trigger button that opens the root menu. */
|
|
359
|
+
readonly trigger: Locator;
|
|
360
|
+
/**
|
|
361
|
+
* Opens the root menu if it isn't already open. Idempotent (checks
|
|
362
|
+
* `aria-expanded`). Defaults to `"click"`.
|
|
363
|
+
*/
|
|
364
|
+
open: (how?: DisclosureOpenWith) => Promise<void>;
|
|
365
|
+
/** Closes the menu if open, via `Escape`. Idempotent. */
|
|
366
|
+
close: () => Promise<void>;
|
|
367
|
+
/** Opens the root menu (if needed) and clicks the leaf item `name`. */
|
|
368
|
+
selectItem: (name: string | RegExp) => Promise<void>;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* A submenu level. Adds the `menuitem` trigger and an `open()` that expands it
|
|
372
|
+
* (submenu triggers open on hover or `ArrowRight`/`Enter`).
|
|
373
|
+
*/
|
|
374
|
+
interface MenuSubmenuTester extends MenuLevelTester {
|
|
375
|
+
/** The `menuitem` that expands this submenu. */
|
|
376
|
+
readonly trigger: Locator;
|
|
377
|
+
/**
|
|
378
|
+
* Expands this submenu if it isn't already open. Idempotent (checks the
|
|
379
|
+
* trigger's `aria-expanded`). Defaults to `"Enter"`, which opens the submenu
|
|
380
|
+
* in both LTR and RTL (the expand arrow is direction-dependent:
|
|
381
|
+
* `ArrowRight` in LTR, `ArrowLeft` in RTL). Pass `"click"` to activate by
|
|
382
|
+
* pointer, or an explicit arrow key to test direction-specific behavior.
|
|
383
|
+
*/
|
|
384
|
+
open: (how?: DisclosureOpenWith) => Promise<void>;
|
|
385
|
+
}
|
|
386
|
+
|
|
264
387
|
/**
|
|
265
388
|
* Options for {@link selectTester}. Defaults the trigger to
|
|
266
389
|
* `frame.getByTestId("select-button")` (the convention for both single- and
|
|
@@ -290,7 +413,11 @@ interface SelectTester {
|
|
|
290
413
|
readonly trigger: Locator;
|
|
291
414
|
/** The popover listbox. Only attached while the Select is open. */
|
|
292
415
|
readonly listbox: Locator;
|
|
293
|
-
/**
|
|
416
|
+
/**
|
|
417
|
+
* Locator for a single option by accessible name. A string matches the
|
|
418
|
+
* full name exactly (case-sensitive, whitespace-trimmed); pass a RegExp
|
|
419
|
+
* for partial matching.
|
|
420
|
+
*/
|
|
294
421
|
option: (name: string | RegExp) => Locator;
|
|
295
422
|
/**
|
|
296
423
|
* Opens the Select if it isn't already open. Idempotent — checks
|
|
@@ -394,8 +521,10 @@ interface SelectTesterFactoryFor<O extends {
|
|
|
394
521
|
}
|
|
395
522
|
|
|
396
523
|
type BoundSelectOptions = Omit<SelectTesterOptions, "frame">;
|
|
524
|
+
type BoundComboBoxOptions = Omit<ComboBoxTesterOptions, "frame">;
|
|
397
525
|
type BoundEditorOptions = Omit<EditorTesterOptions, "frame">;
|
|
398
526
|
type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
527
|
+
type BoundMenuOptions = Omit<MenuTesterOptions, "frame">;
|
|
399
528
|
/**
|
|
400
529
|
* The frame-bound tester factory. Methods are flat — one per component — so
|
|
401
530
|
* IDE autocomplete on `t.` lists the full surface in one place. Variants of a
|
|
@@ -407,8 +536,10 @@ type BoundFileUploaderOptions = Omit<FileUploaderTesterOptions, "frame">;
|
|
|
407
536
|
*/
|
|
408
537
|
interface Testers {
|
|
409
538
|
select: SelectTesterFactoryFor<BoundSelectOptions>;
|
|
539
|
+
comboBox: (options?: BoundComboBoxOptions) => ComboBoxTester;
|
|
410
540
|
editor: (options?: BoundEditorOptions) => EditorTester;
|
|
411
541
|
fileUploader: (options?: BoundFileUploaderOptions) => FileUploaderTester;
|
|
542
|
+
menu: (options?: BoundMenuOptions) => MenuTester;
|
|
412
543
|
}
|
|
413
544
|
/**
|
|
414
545
|
* Build a frame-bound tester factory. Construct once per test and pick the
|
|
@@ -426,4 +557,4 @@ interface Testers {
|
|
|
426
557
|
*/
|
|
427
558
|
declare function testers(frame: Frame): Testers;
|
|
428
559
|
|
|
429
|
-
export { type AutocompleteTester, DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type EditorTester, type FileUploaderTester, type Frame, type MultiSelectTester, type SelectTester, type Testers, type ToBeAccessibleOptions, expect, testers };
|
|
560
|
+
export { type AutocompleteTester, 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 };
|
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'),W=require('axe-core'),promises=require('fs/promises'),I=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var W__default=/*#__PURE__*/_interopDefault(W);var I__default=/*#__PURE__*/_interopDefault(I);/**
|
|
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 w=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],
|
|
11
|
-
`):d(
|
|
12
|
-
`)}var
|
|
13
|
-
${
|
|
14
|
-
`);return ` \u2022 [${
|
|
15
|
-
${
|
|
16
|
-
${
|
|
17
|
-
`),
|
|
18
|
-
${d}`,pass:false}},async toMatchClassTree(e,o,t={}){let{prefix:n=
|
|
19
|
-
`,
|
|
10
|
+
var w=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],O=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function A(e,o={}){let{prefix:t="BaselineUI-",ignoreHashed:n=false}=o,s=Array.isArray(t)?t:[t];function r(u){return u.split(/[-_]/).some(p=>p.length>=5&&/^[a-z\d]+$/.test(p)&&/[a-z]/.test(p)&&/\d/.test(p))}function i(u){return [...u.classList].filter(p=>s.some(m=>p.startsWith(m))&&(!n||!r(p)))}function a(u,p=false){let m=[],h=u.shadowRoot?u.shadowRoot.children:u.children;for(let T of h){let x=p||T.getAttribute("aria-hidden")==="true",B=i(T),b=a(T,x);B.length>0?m.push({classes:B,children:b,hidden:x}):m.push(...b);}return m}function d(u,p="",m=false){let h=[];for(let T=0;T<u.length;T++){let x=u[T],B=T===u.length-1,b=m?"":B?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",_=m?"":p+(B?" ":"\u2502 "),$=x.classes.join(", ");h.push(p+b+$+(x.hidden?" [aria-hidden]":""),...d(x.children,_));}return h}let l=i(e),c=a(e);return l.length===0&&c.length===0?"":l.length>0?d([{classes:l,children:c,hidden:false}],"",true).join(`
|
|
11
|
+
`):d(c,"",true).join(`
|
|
12
|
+
`)}var f=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"}},H=async e=>{let o=typeof e.goto=="function",t=!o&&typeof e.owner=="function";if(o||t)return e.locator("body");let n=e;return await n.first().evaluate(r=>r.tagName?.toLowerCase()==="iframe").catch(()=>false)?n.contentFrame().locator("body"):n},z=async e=>{await e.first().evaluate((o,t)=>{if(window.axe)return;let s=document.createElement("script");s.textContent=t,document.head.append(s);},W__default.default.source);},V=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],G=(e,o=[])=>{let t=new Set([...L,...o,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??w]},rules:Object.fromEntries([...t].map(n=>[n,{enabled:false}]))}},k=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},q=async(e,o,t)=>{let n=await e.count();if(n===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await z(e);let s=k(o.include),r=k(o.exclude);return n===1?await e.evaluate(async(i,a)=>{let d=window,l={include:[i,...a.userInclude??[]],exclude:a.userExclude??[]};return await d.axe.run(l,a.runOptions)},{userInclude:s,userExclude:r,runOptions:t}):await e.evaluateAll(async(i,a)=>{let d=window,l={include:[...i,...a.userInclude??[]],exclude:a.userExclude??[]};return await d.axe.run(l,a.runOptions)},{userInclude:s,userExclude:r,runOptions:t})},S="BaselineUI-";function E(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function J(e){return Array.isArray(e)?e.length===1&&e[0]===S:e===S}function K(e){return (Array.isArray(e)?e:[e]).join("+")}function X(e,o,t,n,s){let r=o.slice(1).map(i=>E(i));return t&&r.push(E(t)),n!==void 0&&!J(n)&&r.push(E(K(n))),s&&r.push("ignoreHashed"),I__default.default.join(e,`${r.join("--")}.txt`)}var Q=test.expect.extend({toBeWithinDelta(e,o,t){return Math.abs(e-o)<=t?{message:()=>`expected ${e} not to be within ${t} of ${o}`,pass:true}:{message:()=>`expected ${e} to be within ${t} of ${o}`,pass:false}},async toBeCalledOnce(e){try{return await test.expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledTwice(e){try{return await test.expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledThrice(e){try{return await test.expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledWith(e,...o){try{return await test.expect(()=>{for(let[t,n]of o.entries())test.expect(e.lastCall?.args?.[t]).toStrictEqual(n);}).toPass(),{message:()=>`Expected function to be called with ${o.join(", ")}.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},async toBeCalledWithExactly(e,...o){try{return await test.expect.poll(()=>e.lastCall?.args).toStrictEqual(o),{message:()=>`Expected function to be called with exactly ${o.join(", ")}.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},toBeCalled(e){try{return test.expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledTimes(e,o){try{return await test.expect.poll(()=>e.callCount).toBe(o),{message:()=>`Expected function to be called ${o} times.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},async toBeAccessible(e,o={}){let t=await H(e),n=await t.first().evaluate(c=>{let u=c.ownerDocument?.defaultView;return u!==null&&u!==window.top}).catch(()=>false),s=G(o,n?V:[]),r,i=async()=>{let c=await q(t,o,s),u=o.treatIncompleteAsViolationIds??O,p=[...c.violations,...c.incomplete.filter(m=>u.includes(m.id))];return r={result:c,violations:p},p},a;try{if(o.timeout&&o.timeout>0){let c=test.expect.poll(i,{timeout:o.timeout});await(this.isNot?c.not.toHaveLength(0):c.toHaveLength(0));}else await i();}catch(c){a=c;}if(!r)throw new Error(`toBeAccessible: axe scan never completed.
|
|
13
|
+
${f(a)}`);if(r.violations.length===0)return {message:()=>"Expected accessibility violations but found none.",pass:true};this.isNot||await test.test.info().attach(o.attachmentName??"accessibility-scan-results",{body:JSON.stringify(r.result,null,2),contentType:"application/json"});let d=r.violations.map(c=>{let u=c.nodes.map(p=>Array.isArray(p.target)?p.target.join(" "):String(p.target)).join(`
|
|
14
|
+
`);return ` \u2022 [${c.id}] ${c.help}
|
|
15
|
+
${u}
|
|
16
|
+
${c.helpUrl??""}`}).join(`
|
|
17
|
+
`),l=r.violations.length;return {message:()=>`Found ${l} accessibility violation${l===1?"":"s"}:
|
|
18
|
+
${d}`,pass:false}},async toMatchClassTree(e,o,t={}){let{prefix:n=S,ignoreHashed:s=false}=t,r=await e.evaluate(A,{prefix:n,ignoreHashed:s});if(!r){let i=Array.isArray(n)?n.map(a=>`${a}*`).join(" / "):`${n}*`;return {message:()=>`No ${i} classes found in the DOM tree.`,pass:false}}try{let i=`${r}
|
|
19
|
+
`,a=test.test.info();if(a.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:!0};let l=X(a.project.snapshotDir,a.titlePath,o,n,s),c=a.config.updateSnapshots;await promises.mkdir(I__default.default.dirname(l),{recursive:!0});let u;try{u=await promises.readFile(l,"utf8");}catch(p){if(p.code==="ENOENT"&&c!=="none")return await promises.writeFile(l,i),{message:()=>"Class tree snapshot created.",pass:!0};throw p}if(u!==i){if(c==="all"||c==="changed")return await promises.writeFile(l,i),{message:()=>"Class tree snapshot updated.",pass:!0};try{test.expect(i).toBe(u);}catch(p){return {message:()=>`Class tree snapshot mismatch at ${l}
|
|
20
20
|
|
|
21
|
-
${
|
|
21
|
+
${p.message}`,pass:!1}}}return {message:()=>"Class tree matched snapshot.",pass:!0}}catch(i){return {message:()=>f(i),pass:false}}}});function g(e){let o=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let s=e.locator("[aria-expanded]").first();return await s.count()>0?s:e},t=async()=>await(await o()).getAttribute("aria-expanded")==="true";return {isOpen:t,open:async(s="click")=>{if(await t())return;if(s==="click"){await e.click();return}await(await o()).press(s);}}}function F({frame:e,trigger:o,toggleButton:t}){let n=o??e.getByRole("combobox",{includeHidden:true}),s=t??e.getByTestId("combobox-toggle-button"),r=l=>e.getByRole("option",{name:l,exact:typeof l=="string"}),{isOpen:i,open:a}=g(n),d=async(l="click")=>{if(!await i()){if(l==="click"){await s.click();return}await a(l);}};return {input:n,toggleButton:s,listbox:e.getByRole("listbox"),option:r,isOpen:i,open:d,async selectOption(l){await d(),await r(l).click();},async filter(l){await n.fill(l);}}}function v({frame:e,root:o}){let t=o??e.locator(".BaselineUI-Editor"),n=t.getByTestId("editor-font-color-button"),s=t.getByTestId("editor-background-color-button"),r=t.getByTestId("editor-add-link-button"),i=t.getByTestId("editor-help-button"),a=t.getByTestId("editor-mention-button"),d=t.getByRole("combobox"),l=e.getByTestId("editor-mention-listbox"),c=e.getByTestId("editor-help-dialog-close-button"),u=e.getByRole("dialog").filter({has:c}),p=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:t,textbox:t.getByRole("textbox"),placeholder:t.getByTestId("editor-placeholder"),toolbar:t.getByRole("toolbar"),boldButton:t.getByTestId("editor-bold-button"),italicButton:t.getByTestId("editor-italic-button"),underlineButton:t.getByTestId("editor-underline-button"),fontColorButton:n,backgroundColorButton:s,openFontColorPicker:g(n).open,openBackgroundColorPicker:g(s).open,addLinkButton:r,linkDialog:p,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(r).open,saveButton:t.getByTestId("editor-save-button"),cancelButton:t.getByTestId("editor-cancel-button"),mentionButton:a,helpButton:i,helpDialog:u,helpDialogCloseButton:c,async openHelpDialog(){await u.isVisible()||await i.click();},mentionInput:d,mentionListbox:l,mentionOption:m=>l.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await a.click();}}}function D({frame:e,trigger:o,variant:t="dropzone"}){let n=e.getByTestId("file-uploader"),s=n.locator('input[type="file"]'),r=o??(t==="button"?n.getByRole("button"):e.getByTestId("file-uploader-dropzone"));return {root:n,button:r,input:s,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:n.getByRole("alert"),async upload(i){await s.setInputFiles(i);}}}function P(e,o,t){let n=i=>o.getByRole("menuitem",{name:i}),s=i=>o.getByRole("group",{name:i}),{isOpen:r}=g(t);return {menu:o,item:n,section:s,isOpen:r,submenu(i){let a=n(i),d=e.getByRole("menu",{name:i}),l=P(e,d,a),{open:c}=g(a);return {...l,trigger:a,open:async(u="Enter")=>c(u)}}}}function U({frame:e,trigger:o}){let t=o??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=P(e,n,t),{open:r,isOpen:i}=g(t);return {...s,trigger:t,open:r,isOpen:i,async close(){await i()&&await t.press("Escape");},async selectItem(a){await r(),await s.item(a).click();}}}var M=(e=>{let t=Y(e);return e.multiple&&(t=Z(t,e.frame)),e.autocomplete&&(t=ee(t,e.frame)),t});function Y({frame:e,trigger:o}){let t=o??e.getByTestId("select-button"),n=r=>e.getByRole("option",{name:r,exact:typeof r=="string"}),{open:s}=g(t);return {trigger:t,listbox:e.getByRole("listbox"),option:n,open:s,async selectOption(r){await s(),await n(r).click();}}}function Z(e,o){return {...e,selectAllButton:o.getByTestId("select-all-button"),clearButton:o.getByTestId("select-clear-button"),tag:t=>e.trigger.getByRole("row",{name:t}),removeTagButton:t=>e.trigger.getByRole("row",{name:t}).getByRole("button")}}function ee(e,o){let t=o.getByRole("searchbox");return {...e,searchbox:t,async filter(n){await t.fill(n);}}}function te(e){return {select:((o={})=>M({frame:e,...o})),comboBox:(o={})=>F({frame:e,...o}),editor:(o={})=>v({frame:e,...o}),fileUploader:(o={})=>D({frame:e,...o}),menu:(o={})=>U({frame:e,...o})}}exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=O;exports.DEFAULT_DISABLED_RULES=L;exports.DEFAULT_WCAG_TAGS=w;exports.expect=Q;exports.testers=te;
|
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 W from'axe-core';import {mkdir,readFile,writeFile}from'fs/promises';import I from'path';/**
|
|
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 _ from'axe-core';import {mkdir
|
|
|
7
7
|
* This notice may not be removed from this file.
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
|
-
var w=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],
|
|
11
|
-
`):d(
|
|
12
|
-
`)}var
|
|
13
|
-
${
|
|
14
|
-
`);return ` \u2022 [${
|
|
15
|
-
${
|
|
16
|
-
${
|
|
17
|
-
`),
|
|
18
|
-
${d}`,pass:false}},async toMatchClassTree(e,o,t={}){let{prefix:n=
|
|
19
|
-
`,
|
|
10
|
+
var w=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],L=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],O=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function A(e,o={}){let{prefix:t="BaselineUI-",ignoreHashed:n=false}=o,s=Array.isArray(t)?t:[t];function r(u){return u.split(/[-_]/).some(p=>p.length>=5&&/^[a-z\d]+$/.test(p)&&/[a-z]/.test(p)&&/\d/.test(p))}function i(u){return [...u.classList].filter(p=>s.some(m=>p.startsWith(m))&&(!n||!r(p)))}function a(u,p=false){let m=[],h=u.shadowRoot?u.shadowRoot.children:u.children;for(let T of h){let x=p||T.getAttribute("aria-hidden")==="true",B=i(T),b=a(T,x);B.length>0?m.push({classes:B,children:b,hidden:x}):m.push(...b);}return m}function d(u,p="",m=false){let h=[];for(let T=0;T<u.length;T++){let x=u[T],B=T===u.length-1,b=m?"":B?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",_=m?"":p+(B?" ":"\u2502 "),$=x.classes.join(", ");h.push(p+b+$+(x.hidden?" [aria-hidden]":""),...d(x.children,_));}return h}let l=i(e),c=a(e);return l.length===0&&c.length===0?"":l.length>0?d([{classes:l,children:c,hidden:false}],"",true).join(`
|
|
11
|
+
`):d(c,"",true).join(`
|
|
12
|
+
`)}var f=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"}},H=async e=>{let o=typeof e.goto=="function",t=!o&&typeof e.owner=="function";if(o||t)return e.locator("body");let n=e;return await n.first().evaluate(r=>r.tagName?.toLowerCase()==="iframe").catch(()=>false)?n.contentFrame().locator("body"):n},z=async e=>{await e.first().evaluate((o,t)=>{if(window.axe)return;let s=document.createElement("script");s.textContent=t,document.head.append(s);},W.source);},V=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],G=(e,o=[])=>{let t=new Set([...L,...o,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??w]},rules:Object.fromEntries([...t].map(n=>[n,{enabled:false}]))}},k=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},q=async(e,o,t)=>{let n=await e.count();if(n===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await z(e);let s=k(o.include),r=k(o.exclude);return n===1?await e.evaluate(async(i,a)=>{let d=window,l={include:[i,...a.userInclude??[]],exclude:a.userExclude??[]};return await d.axe.run(l,a.runOptions)},{userInclude:s,userExclude:r,runOptions:t}):await e.evaluateAll(async(i,a)=>{let d=window,l={include:[...i,...a.userInclude??[]],exclude:a.userExclude??[]};return await d.axe.run(l,a.runOptions)},{userInclude:s,userExclude:r,runOptions:t})},S="BaselineUI-";function E(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function J(e){return Array.isArray(e)?e.length===1&&e[0]===S:e===S}function K(e){return (Array.isArray(e)?e:[e]).join("+")}function X(e,o,t,n,s){let r=o.slice(1).map(i=>E(i));return t&&r.push(E(t)),n!==void 0&&!J(n)&&r.push(E(K(n))),s&&r.push("ignoreHashed"),I.join(e,`${r.join("--")}.txt`)}var Q=expect.extend({toBeWithinDelta(e,o,t){return Math.abs(e-o)<=t?{message:()=>`expected ${e} not to be within ${t} of ${o}`,pass:true}:{message:()=>`expected ${e} to be within ${t} of ${o}`,pass:false}},async toBeCalledOnce(e){try{return await expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledTwice(e){try{return await expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledThrice(e){try{return await expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledWith(e,...o){try{return await expect(()=>{for(let[t,n]of o.entries())expect(e.lastCall?.args?.[t]).toStrictEqual(n);}).toPass(),{message:()=>`Expected function to be called with ${o.join(", ")}.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},async toBeCalledWithExactly(e,...o){try{return await expect.poll(()=>e.lastCall?.args).toStrictEqual(o),{message:()=>`Expected function to be called with exactly ${o.join(", ")}.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},toBeCalled(e){try{return expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(o){return {message:()=>f(o),pass:false}}},async toBeCalledTimes(e,o){try{return await expect.poll(()=>e.callCount).toBe(o),{message:()=>`Expected function to be called ${o} times.`,pass:!0}}catch(t){return {message:()=>f(t),pass:false}}},async toBeAccessible(e,o={}){let t=await H(e),n=await t.first().evaluate(c=>{let u=c.ownerDocument?.defaultView;return u!==null&&u!==window.top}).catch(()=>false),s=G(o,n?V:[]),r,i=async()=>{let c=await q(t,o,s),u=o.treatIncompleteAsViolationIds??O,p=[...c.violations,...c.incomplete.filter(m=>u.includes(m.id))];return r={result:c,violations:p},p},a;try{if(o.timeout&&o.timeout>0){let c=expect.poll(i,{timeout:o.timeout});await(this.isNot?c.not.toHaveLength(0):c.toHaveLength(0));}else await i();}catch(c){a=c;}if(!r)throw new Error(`toBeAccessible: axe scan never completed.
|
|
13
|
+
${f(a)}`);if(r.violations.length===0)return {message:()=>"Expected accessibility violations but found none.",pass:true};this.isNot||await test.info().attach(o.attachmentName??"accessibility-scan-results",{body:JSON.stringify(r.result,null,2),contentType:"application/json"});let d=r.violations.map(c=>{let u=c.nodes.map(p=>Array.isArray(p.target)?p.target.join(" "):String(p.target)).join(`
|
|
14
|
+
`);return ` \u2022 [${c.id}] ${c.help}
|
|
15
|
+
${u}
|
|
16
|
+
${c.helpUrl??""}`}).join(`
|
|
17
|
+
`),l=r.violations.length;return {message:()=>`Found ${l} accessibility violation${l===1?"":"s"}:
|
|
18
|
+
${d}`,pass:false}},async toMatchClassTree(e,o,t={}){let{prefix:n=S,ignoreHashed:s=false}=t,r=await e.evaluate(A,{prefix:n,ignoreHashed:s});if(!r){let i=Array.isArray(n)?n.map(a=>`${a}*`).join(" / "):`${n}*`;return {message:()=>`No ${i} classes found in the DOM tree.`,pass:false}}try{let i=`${r}
|
|
19
|
+
`,a=test.info();if(a.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:!0};let l=X(a.project.snapshotDir,a.titlePath,o,n,s),c=a.config.updateSnapshots;await mkdir(I.dirname(l),{recursive:!0});let u;try{u=await readFile(l,"utf8");}catch(p){if(p.code==="ENOENT"&&c!=="none")return await writeFile(l,i),{message:()=>"Class tree snapshot created.",pass:!0};throw p}if(u!==i){if(c==="all"||c==="changed")return await writeFile(l,i),{message:()=>"Class tree snapshot updated.",pass:!0};try{expect(i).toBe(u);}catch(p){return {message:()=>`Class tree snapshot mismatch at ${l}
|
|
20
20
|
|
|
21
|
-
${
|
|
21
|
+
${p.message}`,pass:!1}}}return {message:()=>"Class tree matched snapshot.",pass:!0}}catch(i){return {message:()=>f(i),pass:false}}}});function g(e){let o=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let s=e.locator("[aria-expanded]").first();return await s.count()>0?s:e},t=async()=>await(await o()).getAttribute("aria-expanded")==="true";return {isOpen:t,open:async(s="click")=>{if(await t())return;if(s==="click"){await e.click();return}await(await o()).press(s);}}}function F({frame:e,trigger:o,toggleButton:t}){let n=o??e.getByRole("combobox",{includeHidden:true}),s=t??e.getByTestId("combobox-toggle-button"),r=l=>e.getByRole("option",{name:l,exact:typeof l=="string"}),{isOpen:i,open:a}=g(n),d=async(l="click")=>{if(!await i()){if(l==="click"){await s.click();return}await a(l);}};return {input:n,toggleButton:s,listbox:e.getByRole("listbox"),option:r,isOpen:i,open:d,async selectOption(l){await d(),await r(l).click();},async filter(l){await n.fill(l);}}}function v({frame:e,root:o}){let t=o??e.locator(".BaselineUI-Editor"),n=t.getByTestId("editor-font-color-button"),s=t.getByTestId("editor-background-color-button"),r=t.getByTestId("editor-add-link-button"),i=t.getByTestId("editor-help-button"),a=t.getByTestId("editor-mention-button"),d=t.getByRole("combobox"),l=e.getByTestId("editor-mention-listbox"),c=e.getByTestId("editor-help-dialog-close-button"),u=e.getByRole("dialog").filter({has:c}),p=e.getByRole("dialog").filter({has:e.getByTestId(/^editor-link-/)});return {root:t,textbox:t.getByRole("textbox"),placeholder:t.getByTestId("editor-placeholder"),toolbar:t.getByRole("toolbar"),boldButton:t.getByTestId("editor-bold-button"),italicButton:t.getByTestId("editor-italic-button"),underlineButton:t.getByTestId("editor-underline-button"),fontColorButton:n,backgroundColorButton:s,openFontColorPicker:g(n).open,openBackgroundColorPicker:g(s).open,addLinkButton:r,linkDialog:p,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(r).open,saveButton:t.getByTestId("editor-save-button"),cancelButton:t.getByTestId("editor-cancel-button"),mentionButton:a,helpButton:i,helpDialog:u,helpDialogCloseButton:c,async openHelpDialog(){await u.isVisible()||await i.click();},mentionInput:d,mentionListbox:l,mentionOption:m=>l.getByRole("option",{name:m}),async startMention(){await d.isVisible()||await a.click();}}}function D({frame:e,trigger:o,variant:t="dropzone"}){let n=e.getByTestId("file-uploader"),s=n.locator('input[type="file"]'),r=o??(t==="button"?n.getByRole("button"):e.getByTestId("file-uploader-dropzone"));return {root:n,button:r,input:s,dropzone:e.getByTestId("file-uploader-dropzone"),errorMessage:n.getByRole("alert"),async upload(i){await s.setInputFiles(i);}}}function P(e,o,t){let n=i=>o.getByRole("menuitem",{name:i}),s=i=>o.getByRole("group",{name:i}),{isOpen:r}=g(t);return {menu:o,item:n,section:s,isOpen:r,submenu(i){let a=n(i),d=e.getByRole("menu",{name:i}),l=P(e,d,a),{open:c}=g(a);return {...l,trigger:a,open:async(u="Enter")=>c(u)}}}}function U({frame:e,trigger:o}){let t=o??e.getByTestId("menu-trigger"),n=e.getByRole("menu").first(),s=P(e,n,t),{open:r,isOpen:i}=g(t);return {...s,trigger:t,open:r,isOpen:i,async close(){await i()&&await t.press("Escape");},async selectItem(a){await r(),await s.item(a).click();}}}var M=(e=>{let t=Y(e);return e.multiple&&(t=Z(t,e.frame)),e.autocomplete&&(t=ee(t,e.frame)),t});function Y({frame:e,trigger:o}){let t=o??e.getByTestId("select-button"),n=r=>e.getByRole("option",{name:r,exact:typeof r=="string"}),{open:s}=g(t);return {trigger:t,listbox:e.getByRole("listbox"),option:n,open:s,async selectOption(r){await s(),await n(r).click();}}}function Z(e,o){return {...e,selectAllButton:o.getByTestId("select-all-button"),clearButton:o.getByTestId("select-clear-button"),tag:t=>e.trigger.getByRole("row",{name:t}),removeTagButton:t=>e.trigger.getByRole("row",{name:t}).getByRole("button")}}function ee(e,o){let t=o.getByRole("searchbox");return {...e,searchbox:t,async filter(n){await t.fill(n);}}}function te(e){return {select:((o={})=>M({frame:e,...o})),comboBox:(o={})=>F({frame:e,...o}),editor:(o={})=>v({frame:e,...o}),fileUploader:(o={})=>D({frame:e,...o}),menu:(o={})=>U({frame:e,...o})}}export{O as DEFAULT_CRITICAL_INCOMPLETE_RULES,L as DEFAULT_DISABLED_RULES,w as DEFAULT_WCAG_TAGS,Q as expect,te as testers};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baseline-ui/test-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.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": "
|
|
55
|
+
"@baseline-ui/core": "2.0.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:e6a7f190-97e2-4f95-8c2e-03bdb13563ff",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-
|
|
8
|
+
"timestamp": "2026-08-06T07:08:44.495Z",
|
|
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": "
|
|
27
|
-
"purl": "pkg:npm/@baseline-ui/test-utils@
|
|
28
|
-
"bom-ref": "pkg:npm/@baseline-ui/test-utils@
|
|
26
|
+
"version": "2.0.0",
|
|
27
|
+
"purl": "pkg:npm/@baseline-ui/test-utils@2.0.0",
|
|
28
|
+
"bom-ref": "pkg:npm/@baseline-ui/test-utils@2.0.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@
|
|
503
|
+
"ref": "pkg:npm/@baseline-ui/test-utils@2.0.0",
|
|
504
504
|
"dependsOn": [
|
|
505
505
|
"pkg:npm/%40neondatabase/serverless@1.1.0",
|
|
506
506
|
"pkg:npm/%40playwright/test@1.60.0",
|