@baseline-ui/test-utils 3.3.0 → 3.5.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.js CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var core=require('@baseline-ui/core'),m=require('react'),C=require('react-dom/client'),F=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 C__default=/*#__PURE__*/_interopDefault(C);var F__default=/*#__PURE__*/_interopDefault(F);/**
1
+ 'use strict';var core=require('@baseline-ui/core'),c=require('react'),F=require('react-dom/client'),w=require('react-frame-component'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var c__default=/*#__PURE__*/_interopDefault(c);var F__default=/*#__PURE__*/_interopDefault(F);var w__default=/*#__PURE__*/_interopDefault(w);/**
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,5 +7,5 @@
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- function R(){let r=[],t=document;for(let o=0;o<t.styleSheets.length;o++){let n=t.styleSheets[o];if(n.cssRules){let c=n.cssRules;for(let a of c)r.push(a.cssText);}}return r.join(`
11
- `)}var b=m__default.default.forwardRef(({head:r=jsxRuntime.jsx("style",{children:R()}),...t},o)=>jsxRuntime.jsx(F__default.default,{style:{width:"100vw",height:"100vh",border:"none"},ref:o,...t,head:r}));b.displayName="IFrame";var w=m__default.default.forwardRef(({children:r,style:t},o)=>{let n=core.useObjectRef(o),c=m__default.default.useRef(null),a=m__default.default.useRef(null),u=m__default.default.useRef(null),l=m__default.default.useRef(false),f=m__default.default.useMemo(()=>R(),[]);return m.useEffect(()=>{if(l.current=false,n.current&&!c.current){let e=n.current.attachShadow({mode:"open"});c.current=e;let i=document.createElement("style");i.textContent=f,e.append(i);let p=document.createElement("div");p.className="content-container",e.append(p);let s=document.createElement("div");s.className="overlay-portal",e.append(s),u.current=s;let h=C__default.default.createRoot(p);a.current=h;}return ()=>{l.current=true;let e=a.current;e&&(queueMicrotask(()=>{e.unmount();}),a.current=null),c.current=null,u.current=null;}},[f,n]),m.useEffect(()=>{if(l.current)return;let e=a.current,i=u.current;e&&i&&e.render(jsxRuntime.jsx(core.PortalContainerProvider,{portalContainer:i,children:r}));},[r]),jsxRuntime.jsx("div",{style:t,ref:n})});w.displayName="ShadowRoot";var G=({children:r,locale:t,theme:o,themeStyle:n,disableThemeProvider:c=false,disableFrameProvider:a=false,messages:u})=>{let[l,f]=m.useState(null),{document:e}=F.useFrame(),i=t==="ar"||t==="he";m.useLayoutEffect(()=>{i?e?.documentElement.setAttribute("dir","rtl"):e?.documentElement.removeAttribute("dir");},[i,e]);let p=l?.ownerDocument.body,s=r;return a||(s=jsxRuntime.jsx(core.FrameProvider,{container:p,portalContainer:l,children:s})),c||(s=jsxRuntime.jsx(core.ThemeProvider,{theme:o,style:n,children:s})),jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(core.I18nProvider,{locale:t,messages:u,children:s}),jsxRuntime.jsx("div",{id:"portal-container",ref:f})]})};exports.IFrame=b;exports.ProvidersContainer=G;exports.ShadowRoot=w;exports.getRootStyles=R;
10
+ function R(){let t=[],r=document;for(let n=0;n<r.styleSheets.length;n++){let s=r.styleSheets[n];try{for(let a of s.cssRules)t.push(a.cssText);}catch{}}return t.join(`
11
+ `)}var b=c__default.default.forwardRef(({head:t=jsxRuntime.jsx("style",{children:R()}),...r},n)=>jsxRuntime.jsx(w__default.default,{style:{width:"100vw",height:"100vh",border:"none"},ref:n,...r,head:t}));b.displayName="IFrame";var E=c__default.default.forwardRef(({children:t,style:r},n)=>{let s=core.useObjectRef(n),a=c__default.default.useRef(null),i=c__default.default.useRef(null),m=c__default.default.useRef(null),l=c__default.default.useRef(false),u=c__default.default.useMemo(()=>R(),[]);return c.useEffect(()=>{if(l.current=false,s.current&&!a.current){let e=s.current.shadowRoot??s.current.attachShadow({mode:"open"});e.replaceChildren(),a.current=e;let o=document.createElement("style");o.textContent=u,e.append(o);let f=document.createElement("div");f.className="content-container",e.append(f);let P=document.createElement("div");P.className="overlay-portal",e.append(P),m.current=P;let y=F__default.default.createRoot(f);i.current=y;}return ()=>{l.current=true;let e=i.current;e&&(queueMicrotask(()=>{e.unmount();}),i.current=null),a.current=null,m.current=null;}},[u,s]),c.useEffect(()=>{if(l.current)return;let e=i.current,o=m.current;e&&o&&e.render(jsxRuntime.jsx(core.PortalContainerProvider,{portalContainer:o,children:t}));},[t]),jsxRuntime.jsx("div",{style:r,ref:s})});E.displayName="ShadowRoot";var H=()=>{let{direction:t}=core.useLocale(),{document:r}=w.useFrame();return c.useLayoutEffect(()=>{t==="rtl"?r?.documentElement.setAttribute("dir","rtl"):r?.documentElement.removeAttribute("dir");},[t,r]),null},K=({children:t,locale:r,theme:n,themeStyle:s,disableThemeProvider:a=false,disableFrameProvider:i=false,messages:m})=>{let[l,u]=c.useState(null),e=l?.ownerDocument.body,o=t;return i||(o=jsxRuntime.jsx(core.FrameProvider,{container:e,portalContainer:l,children:o})),a||(o=jsxRuntime.jsx(core.ThemeProvider,{theme:n,style:s,children:o})),jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs(core.I18nProvider,{locale:r,messages:m,children:[jsxRuntime.jsx(H,{}),o]}),jsxRuntime.jsx("div",{id:"portal-container",ref:u})]})};exports.IFrame=b;exports.ProvidersContainer=K;exports.ShadowRoot=E;exports.getRootStyles=R;
package/client/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {useObjectRef,PortalContainerProvider,FrameProvider,ThemeProvider,I18nProvider}from'@baseline-ui/core';import m,{useEffect,useState,useLayoutEffect}from'react';import C from'react-dom/client';import F,{useFrame}from'react-frame-component';import {jsx,jsxs,Fragment}from'react/jsx-runtime';/**
1
+ import {useObjectRef,PortalContainerProvider,FrameProvider,ThemeProvider,I18nProvider,useLocale}from'@baseline-ui/core';import c,{useEffect,useState,useLayoutEffect}from'react';import F from'react-dom/client';import w,{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
@@ -7,5 +7,5 @@ import {useObjectRef,PortalContainerProvider,FrameProvider,ThemeProvider,I18nPro
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- function R(){let r=[],t=document;for(let o=0;o<t.styleSheets.length;o++){let n=t.styleSheets[o];if(n.cssRules){let c=n.cssRules;for(let a of c)r.push(a.cssText);}}return r.join(`
11
- `)}var b=m.forwardRef(({head:r=jsx("style",{children:R()}),...t},o)=>jsx(F,{style:{width:"100vw",height:"100vh",border:"none"},ref:o,...t,head:r}));b.displayName="IFrame";var w=m.forwardRef(({children:r,style:t},o)=>{let n=useObjectRef(o),c=m.useRef(null),a=m.useRef(null),u=m.useRef(null),l=m.useRef(false),f=m.useMemo(()=>R(),[]);return useEffect(()=>{if(l.current=false,n.current&&!c.current){let e=n.current.attachShadow({mode:"open"});c.current=e;let i=document.createElement("style");i.textContent=f,e.append(i);let p=document.createElement("div");p.className="content-container",e.append(p);let s=document.createElement("div");s.className="overlay-portal",e.append(s),u.current=s;let h=C.createRoot(p);a.current=h;}return ()=>{l.current=true;let e=a.current;e&&(queueMicrotask(()=>{e.unmount();}),a.current=null),c.current=null,u.current=null;}},[f,n]),useEffect(()=>{if(l.current)return;let e=a.current,i=u.current;e&&i&&e.render(jsx(PortalContainerProvider,{portalContainer:i,children:r}));},[r]),jsx("div",{style:t,ref:n})});w.displayName="ShadowRoot";var G=({children:r,locale:t,theme:o,themeStyle:n,disableThemeProvider:c=false,disableFrameProvider:a=false,messages:u})=>{let[l,f]=useState(null),{document:e}=useFrame(),i=t==="ar"||t==="he";useLayoutEffect(()=>{i?e?.documentElement.setAttribute("dir","rtl"):e?.documentElement.removeAttribute("dir");},[i,e]);let p=l?.ownerDocument.body,s=r;return a||(s=jsx(FrameProvider,{container:p,portalContainer:l,children:s})),c||(s=jsx(ThemeProvider,{theme:o,style:n,children:s})),jsxs(Fragment,{children:[jsx(I18nProvider,{locale:t,messages:u,children:s}),jsx("div",{id:"portal-container",ref:f})]})};export{b as IFrame,G as ProvidersContainer,w as ShadowRoot,R as getRootStyles};
10
+ function R(){let t=[],r=document;for(let n=0;n<r.styleSheets.length;n++){let s=r.styleSheets[n];try{for(let a of s.cssRules)t.push(a.cssText);}catch{}}return t.join(`
11
+ `)}var b=c.forwardRef(({head:t=jsx("style",{children:R()}),...r},n)=>jsx(w,{style:{width:"100vw",height:"100vh",border:"none"},ref:n,...r,head:t}));b.displayName="IFrame";var E=c.forwardRef(({children:t,style:r},n)=>{let s=useObjectRef(n),a=c.useRef(null),i=c.useRef(null),m=c.useRef(null),l=c.useRef(false),u=c.useMemo(()=>R(),[]);return useEffect(()=>{if(l.current=false,s.current&&!a.current){let e=s.current.shadowRoot??s.current.attachShadow({mode:"open"});e.replaceChildren(),a.current=e;let o=document.createElement("style");o.textContent=u,e.append(o);let f=document.createElement("div");f.className="content-container",e.append(f);let P=document.createElement("div");P.className="overlay-portal",e.append(P),m.current=P;let y=F.createRoot(f);i.current=y;}return ()=>{l.current=true;let e=i.current;e&&(queueMicrotask(()=>{e.unmount();}),i.current=null),a.current=null,m.current=null;}},[u,s]),useEffect(()=>{if(l.current)return;let e=i.current,o=m.current;e&&o&&e.render(jsx(PortalContainerProvider,{portalContainer:o,children:t}));},[t]),jsx("div",{style:r,ref:s})});E.displayName="ShadowRoot";var H=()=>{let{direction:t}=useLocale(),{document:r}=useFrame();return useLayoutEffect(()=>{t==="rtl"?r?.documentElement.setAttribute("dir","rtl"):r?.documentElement.removeAttribute("dir");},[t,r]),null},K=({children:t,locale:r,theme:n,themeStyle:s,disableThemeProvider:a=false,disableFrameProvider:i=false,messages:m})=>{let[l,u]=useState(null),e=l?.ownerDocument.body,o=t;return i||(o=jsx(FrameProvider,{container:e,portalContainer:l,children:o})),a||(o=jsx(ThemeProvider,{theme:n,style:s,children:o})),jsxs(Fragment,{children:[jsxs(I18nProvider,{locale:r,messages:m,children:[jsx(H,{}),o]}),jsx("div",{id:"portal-container",ref:u})]})};export{b as IFrame,K as ProvidersContainer,E as ShadowRoot,R as getRootStyles};
package/dist/index.d.mts CHANGED
@@ -99,11 +99,17 @@ declare const expect: playwright_test.Expect<{
99
99
  prefix?: string | string[];
100
100
  ignoreHashed?: boolean;
101
101
  }): Promise<{
102
+ message: () => string;
103
+ pass: true;
104
+ shouldNotRetryTest?: undefined;
105
+ } | {
102
106
  message: () => string;
103
107
  pass: false;
108
+ shouldNotRetryTest: boolean;
104
109
  } | {
105
110
  message: () => string;
106
- pass: true;
111
+ pass: false;
112
+ shouldNotRetryTest?: undefined;
107
113
  }>;
108
114
  }>;
109
115
 
@@ -325,7 +331,16 @@ interface FileUploaderTester {
325
331
  * `trigger` when the Menu renders a custom trigger via `renderTrigger` that
326
332
  * doesn't carry that test id.
327
333
  */
328
- type MenuTesterOptions = BaseTesterOptions;
334
+ interface MenuTesterOptions extends BaseTesterOptions {
335
+ /**
336
+ * For a Menu with `trigger="longPress"`. `open()` then holds the pointer
337
+ * instead of clicking, and keyboard opens press the key with `Alt` held, the
338
+ * long-press menu's keyboard opener.
339
+ *
340
+ * @default false
341
+ */
342
+ longPress?: boolean;
343
+ }
329
344
  /**
330
345
  * Locators + verbs shared by a menu and each of its submenus. A submenu is
331
346
  * itself a menu opened from a `menuitem`, so the recursive surface (items,
@@ -337,7 +352,10 @@ type MenuTesterOptions = BaseTesterOptions;
337
352
  interface MenuLevelTester {
338
353
  /** The `role="menu"` element for this level. Only attached while open. */
339
354
  readonly menu: Locator;
340
- /** A `menuitem` within this level, by accessible name. */
355
+ /**
356
+ * A `menuitem`, `menuitemradio` or `menuitemcheckbox` within this level, by
357
+ * accessible name. Selection menus render radio/checkbox items.
358
+ */
341
359
  item: (name: string | RegExp) => Locator;
342
360
  /** A `role="group"` section within this level, by accessible name. */
343
361
  section: (name: string | RegExp) => Locator;
@@ -359,7 +377,11 @@ interface MenuTester extends MenuLevelTester {
359
377
  readonly trigger: Locator;
360
378
  /**
361
379
  * Opens the root menu if it isn't already open. Idempotent (checks
362
- * `aria-expanded`). Defaults to `"click"`.
380
+ * `aria-expanded`). Defaults to `"click"`. With `longPress`, `"click"` holds
381
+ * the pointer on the trigger's button and a key is pressed with `Alt` held;
382
+ * `"ArrowLeft"` and `"ArrowRight"` throw, since they never open a long-press
383
+ * menu and `open()` would otherwise do nothing. (`Alt` with either is also
384
+ * Back/Forward in desktop browsers on Windows and Linux.)
363
385
  */
364
386
  open: (how?: DisclosureOpenWith) => Promise<void>;
365
387
  /** Closes the menu if open, via `Escape`. Idempotent. */
package/dist/index.d.ts CHANGED
@@ -99,11 +99,17 @@ declare const expect: playwright_test.Expect<{
99
99
  prefix?: string | string[];
100
100
  ignoreHashed?: boolean;
101
101
  }): Promise<{
102
+ message: () => string;
103
+ pass: true;
104
+ shouldNotRetryTest?: undefined;
105
+ } | {
102
106
  message: () => string;
103
107
  pass: false;
108
+ shouldNotRetryTest: boolean;
104
109
  } | {
105
110
  message: () => string;
106
- pass: true;
111
+ pass: false;
112
+ shouldNotRetryTest?: undefined;
107
113
  }>;
108
114
  }>;
109
115
 
@@ -325,7 +331,16 @@ interface FileUploaderTester {
325
331
  * `trigger` when the Menu renders a custom trigger via `renderTrigger` that
326
332
  * doesn't carry that test id.
327
333
  */
328
- type MenuTesterOptions = BaseTesterOptions;
334
+ interface MenuTesterOptions extends BaseTesterOptions {
335
+ /**
336
+ * For a Menu with `trigger="longPress"`. `open()` then holds the pointer
337
+ * instead of clicking, and keyboard opens press the key with `Alt` held, the
338
+ * long-press menu's keyboard opener.
339
+ *
340
+ * @default false
341
+ */
342
+ longPress?: boolean;
343
+ }
329
344
  /**
330
345
  * Locators + verbs shared by a menu and each of its submenus. A submenu is
331
346
  * itself a menu opened from a `menuitem`, so the recursive surface (items,
@@ -337,7 +352,10 @@ type MenuTesterOptions = BaseTesterOptions;
337
352
  interface MenuLevelTester {
338
353
  /** The `role="menu"` element for this level. Only attached while open. */
339
354
  readonly menu: Locator;
340
- /** A `menuitem` within this level, by accessible name. */
355
+ /**
356
+ * A `menuitem`, `menuitemradio` or `menuitemcheckbox` within this level, by
357
+ * accessible name. Selection menus render radio/checkbox items.
358
+ */
341
359
  item: (name: string | RegExp) => Locator;
342
360
  /** A `role="group"` section within this level, by accessible name. */
343
361
  section: (name: string | RegExp) => Locator;
@@ -359,7 +377,11 @@ interface MenuTester extends MenuLevelTester {
359
377
  readonly trigger: Locator;
360
378
  /**
361
379
  * Opens the root menu if it isn't already open. Idempotent (checks
362
- * `aria-expanded`). Defaults to `"click"`.
380
+ * `aria-expanded`). Defaults to `"click"`. With `longPress`, `"click"` holds
381
+ * the pointer on the trigger's button and a key is pressed with `Alt` held;
382
+ * `"ArrowLeft"` and `"ArrowRight"` throw, since they never open a long-press
383
+ * menu and `open()` would otherwise do nothing. (`Alt` with either is also
384
+ * Back/Forward in desktop browsers on Windows and Linux.)
363
385
  */
364
386
  open: (how?: DisclosureOpenWith) => Promise<void>;
365
387
  /** Closes the menu if open, via `Escape`. Idempotent. */
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
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);/**
1
+ 'use strict';var test=require('@playwright/test'),W=require('axe-core'),promises=require('fs/promises'),F=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var W__default=/*#__PURE__*/_interopDefault(W);var F__default=/*#__PURE__*/_interopDefault(F);/**
2
2
  * Copyright (c) 2023-2024 PSPDFKit GmbH. All rights reserved.
3
3
  *
4
4
  * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
@@ -7,15 +7,15 @@
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- var 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}
10
+ var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:n=false}=t,s=Array.isArray(o)?o:[o];function r(c){return c.split(/[-_]/).some(p=>p.length>=5&&/^[a-z\d]+$/.test(p)&&/[a-z]/.test(p)&&/\d/.test(p))}function l(c){return [...c.classList].filter(p=>s.some(m=>p.startsWith(m))&&(!n||!r(p)))}function u(c,p=false){let m=[],b=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of b){let h=p||f.getAttribute("aria-hidden")==="true",x=l(f),w=u(f,h);x.length>0?m.push({classes:x,children:w,hidden:h}):m.push(...w);}return m}function d(c,p="",m=false){let b=[];for(let f=0;f<c.length;f++){let h=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",N=m?"":p+(x?" ":"\u2502 "),_=h.classes.join(", ");b.push(p+w+_+(h.hidden?" [aria-hidden]":""),...d(h.children,N));}return b}let a=l(e),i=u(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
11
+ `):d(i,"",true).join(`
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"}},z=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let n=e;return await n.first().evaluate(r=>r.tagName?.toLowerCase()==="iframe").catch(()=>false)?n.contentFrame().locator("body"):n},V=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let s=document.createElement("script");s.textContent=o,document.head.append(s);},W__default.default.source);},G=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],q=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(n=>[n,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},J=async(e,t,o)=>{let n=await e.count();if(n===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await V(e);let s=I(t.include),r=I(t.exclude);return n===1?await e.evaluate(async(l,u)=>{let d=window,a={include:[l,...u.userInclude??[]],exclude:u.userExclude??[]};return await d.axe.run(a,u.runOptions)},{userInclude:s,userExclude:r,runOptions:o}):await e.evaluateAll(async(l,u)=>{let d=window,a={include:[...l,...u.userInclude??[]],exclude:u.userExclude??[]};return await d.axe.run(a,u.runOptions)},{userInclude:s,userExclude:r,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function K(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function X(e){return (Array.isArray(e)?e:[e]).join("+")}function Q(e,t,o,n,s){let r=t.slice(1).map(l=>S(l));return o&&r.push(S(o)),n!==void 0&&!K(n)&&r.push(S(X(n))),s&&r.push("ignoreHashed"),F__default.default.join(e,`${r.join("--")}.txt`)}var B=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},Y=test.expect.extend({toBeWithinDelta(e,t,o){let n=Math.abs(e-t);if(Number.isNaN(n)||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 n<=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,n)=>e.lastCall?.args[n])})).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}}},toBeCalled(e){B(e,"toBeCalled");try{return test.expect(e.called).toBeTruthy(),{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.");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 z(e),n=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),s=q(t,n?G:[]),r,l=async()=>{let i=await J(o,t,s),c=t.treatIncompleteAsViolationIds??E,p=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return r={result:i,violations:p},p},u;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){u=i;}if(!r)throw new Error(`toBeAccessible: axe scan never completed.
13
+ ${T(u)}`);if(r.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(r.result,null,2),contentType:"application/json"});let d=r.violations.map(i=>{let c=i.nodes.map(p=>Array.isArray(p.target)?p.target.join(" "):String(p.target)).join(`
14
+ `);return ` \u2022 [${i.id}] ${i.help}
15
+ ${c}
16
+ ${i.helpUrl??""}`}).join(`
17
+ `),a=r.violations.length;return {message:()=>`Found ${a} accessibility violation${a===1?"":"s"}:
18
+ ${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:n=A,ignoreHashed:s=false}=o,r=await e.evaluate(C,{prefix:n,ignoreHashed:s});if(!r){let p=Array.isArray(n)?n.map(m=>`${m}*`).join(" / "):`${n}*`;throw new Error(`No ${p} classes found in the DOM tree.`)}let l=`${r}
19
+ `,u=test.test.info();if(u.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Q(u.project.snapshotDir,u.titlePath,t,n,s),i=u.config.updateSnapshots,c;try{c=await promises.readFile(a,"utf8");}catch(p){let m=p.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await promises.mkdir(F__default.default.dirname(a),{recursive:true}),await promises.writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw p}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(p){return {message:()=>`Class tree snapshot mismatch at ${a}
20
20
 
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;
21
+ ${p.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let s=e.locator("[aria-expanded]").first();return await s.count()>0?s:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(s="click")=>{if(await o())return;if(s==="click"){await e.click();return}await(await t()).press(s);}}}function v({frame:e,trigger:t,toggleButton:o}){let n=t??e.getByRole("combobox",{includeHidden:true}),s=o??e.getByTestId("combobox-toggle-button"),r=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:u}=g(n),d=async(a="click")=>{if(!await l()){if(a==="click"){await s.click();return}await u(a);}};return {input:n,toggleButton:s,listbox:e.getByRole("listbox"),option:r,isOpen:l,open:d,async selectOption(a){await d(),await r(a).click();},async filter(a){await n.fill(a);}}}function D({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),n=o.getByTestId("editor-font-color-button"),s=o.getByTestId("editor-background-color-button"),r=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),u=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}),p=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: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:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:u,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 u.click();}}}function P({frame:e,trigger:t,variant:o="dropzone"}){let n=e.getByTestId("file-uploader"),s=n.locator('input[type="file"]'),r=t??(o==="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(l){await s.setInputFiles(l);}}}function U(e,t,o){let n=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),s=l=>t.getByRole("group",{name:l}),{isOpen:r}=g(o);return {menu:t,item:n,section:s,isOpen:r,submenu(l){let u=n(l),d=e.getByRole("menu",{name:l}),a=U(e,d,u),{open:i}=g(u);return {...a,trigger:u,open:async(c="Enter")=>i(c)}}}}function M({frame:e,trigger:t,longPress:o=false}){let n=t??e.getByTestId("menu-trigger"),s=e.getByRole("menu").first(),r=U(e,s,n),{button:l,open:u,isOpen:d}=g(n),a=async(i="click")=>{if(!o)return u(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 {...r,trigger:n,open:a,isOpen:d,async close(){await d()&&await n.press("Escape");},async selectItem(i){await a(),await r.item(i).click();}}}var $=(e=>{let o=Z(e);return e.multiple&&(o=ee(o,e.frame)),e.autocomplete&&(o=te(o,e.frame)),o});function Z({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),n=r=>e.getByRole("option",{name:r,exact:typeof r=="string"}),{open:s}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:n,open:s,async selectOption(r){await s(),await n(r).click();}}}function ee(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 te(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(n){await o.fill(n);}}}function oe(e){return {select:((t={})=>$({frame:e,...t})),comboBox:(t={})=>v({frame:e,...t}),editor:(t={})=>D({frame:e,...t}),fileUploader:(t={})=>P({frame:e,...t}),menu:(t={})=>M({frame:e,...t})}}exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=E;exports.DEFAULT_DISABLED_RULES=O;exports.DEFAULT_WCAG_TAGS=L;exports.expect=Y;exports.testers=oe;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {expect,test}from'@playwright/test';import W from'axe-core';import {mkdir,readFile,writeFile}from'fs/promises';import I from'path';/**
1
+ import {expect,test}from'@playwright/test';import W from'axe-core';import {readFile,mkdir,writeFile}from'fs/promises';import F 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 W 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"],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}
10
+ var L=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],O=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],E=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function C(e,t={}){let{prefix:o="BaselineUI-",ignoreHashed:n=false}=t,s=Array.isArray(o)?o:[o];function r(c){return c.split(/[-_]/).some(p=>p.length>=5&&/^[a-z\d]+$/.test(p)&&/[a-z]/.test(p)&&/\d/.test(p))}function l(c){return [...c.classList].filter(p=>s.some(m=>p.startsWith(m))&&(!n||!r(p)))}function u(c,p=false){let m=[],b=c.shadowRoot?c.shadowRoot.children:c.children;for(let f of b){let h=p||f.getAttribute("aria-hidden")==="true",x=l(f),w=u(f,h);x.length>0?m.push({classes:x,children:w,hidden:h}):m.push(...w);}return m}function d(c,p="",m=false){let b=[];for(let f=0;f<c.length;f++){let h=c[f],x=f===c.length-1,w=m?"":x?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",N=m?"":p+(x?" ":"\u2502 "),_=h.classes.join(", ");b.push(p+w+_+(h.hidden?" [aria-hidden]":""),...d(h.children,N));}return b}let a=l(e),i=u(e);return a.length===0&&i.length===0?"":a.length>0?d([{classes:a,children:i,hidden:false}],"",true).join(`
11
+ `):d(i,"",true).join(`
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"}},z=async e=>{let t=typeof e.goto=="function",o=!t&&typeof e.owner=="function";if(t||o)return e.locator("body");let n=e;return await n.first().evaluate(r=>r.tagName?.toLowerCase()==="iframe").catch(()=>false)?n.contentFrame().locator("body"):n},V=async e=>{await e.first().evaluate((t,o)=>{if(window.axe)return;let s=document.createElement("script");s.textContent=o,document.head.append(s);},W.source);},G=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],q=(e,t=[])=>{let o=new Set([...O,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??L]},rules:Object.fromEntries([...o].map(n=>[n,{enabled:false}]))}},I=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},J=async(e,t,o)=>{let n=await e.count();if(n===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await V(e);let s=I(t.include),r=I(t.exclude);return n===1?await e.evaluate(async(l,u)=>{let d=window,a={include:[l,...u.userInclude??[]],exclude:u.userExclude??[]};return await d.axe.run(a,u.runOptions)},{userInclude:s,userExclude:r,runOptions:o}):await e.evaluateAll(async(l,u)=>{let d=window,a={include:[...l,...u.userInclude??[]],exclude:u.userExclude??[]};return await d.axe.run(a,u.runOptions)},{userInclude:s,userExclude:r,runOptions:o})},A="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function K(e){return Array.isArray(e)?e.length===1&&e[0]===A:e===A}function X(e){return (Array.isArray(e)?e:[e]).join("+")}function Q(e,t,o,n,s){let r=t.slice(1).map(l=>S(l));return o&&r.push(S(o)),n!==void 0&&!K(n)&&r.push(S(X(n))),s&&r.push("ignoreHashed"),F.join(e,`${r.join("--")}.txt`)}var B=(e,t)=>{if(typeof e?.callCount!="number")throw new TypeError(`${t}: expected a sinon spy.`)},Y=expect.extend({toBeWithinDelta(e,t,o){let n=Math.abs(e-t);if(Number.isNaN(n)||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 n<=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,n)=>e.lastCall?.args[n])})).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}}},toBeCalled(e){B(e,"toBeCalled");try{return expect(e.called).toBeTruthy(),{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.");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 z(e),n=await o.first().evaluate(i=>{let c=i.ownerDocument?.defaultView;return c!==null&&c!==window.top}).catch(()=>false),s=q(t,n?G:[]),r,l=async()=>{let i=await J(o,t,s),c=t.treatIncompleteAsViolationIds??E,p=[...i.violations,...i.incomplete.filter(m=>c.includes(m.id))];return r={result:i,violations:p},p},u;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){u=i;}if(!r)throw new Error(`toBeAccessible: axe scan never completed.
13
+ ${T(u)}`);if(r.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(r.result,null,2),contentType:"application/json"});let d=r.violations.map(i=>{let c=i.nodes.map(p=>Array.isArray(p.target)?p.target.join(" "):String(p.target)).join(`
14
+ `);return ` \u2022 [${i.id}] ${i.help}
15
+ ${c}
16
+ ${i.helpUrl??""}`}).join(`
17
+ `),a=r.violations.length;return {message:()=>`Found ${a} accessibility violation${a===1?"":"s"}:
18
+ ${d}`,pass:false}},async toMatchClassTree(e,t,o={}){let{prefix:n=A,ignoreHashed:s=false}=o,r=await e.evaluate(C,{prefix:n,ignoreHashed:s});if(!r){let p=Array.isArray(n)?n.map(m=>`${m}*`).join(" / "):`${n}*`;throw new Error(`No ${p} classes found in the DOM tree.`)}let l=`${r}
19
+ `,u=test.info();if(u.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:true};let a=Q(u.project.snapshotDir,u.titlePath,t,n,s),i=u.config.updateSnapshots,c;try{c=await readFile(a,"utf8");}catch(p){let m=p.code;if(m==="ENOENT"&&this.isNot)return {message:()=>`A class tree snapshot doesn't exist at ${a}, matchers using ".not" won't write them automatically.`,pass:true};if(m==="ENOENT"&&i!=="none")return await mkdir(F.dirname(a),{recursive:true}),await writeFile(a,l),i==="missing"?{message:()=>`A class tree snapshot doesn't exist at ${a}, writing actual.`,pass:false,shouldNotRetryTest:true}:{message:()=>"Class tree snapshot created.",pass:true};throw p}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(p){return {message:()=>`Class tree snapshot mismatch at ${a}
20
20
 
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};
21
+ ${p.message}`,pass:false}}}return {message:()=>"Class tree matched snapshot.",pass:true}}});function g(e){let t=async()=>{if(await e.getAttribute("aria-expanded")!==null)return e;let s=e.locator("[aria-expanded]").first();return await s.count()>0?s:e},o=async()=>await(await t()).getAttribute("aria-expanded")==="true";return {button:t,isOpen:o,open:async(s="click")=>{if(await o())return;if(s==="click"){await e.click();return}await(await t()).press(s);}}}function v({frame:e,trigger:t,toggleButton:o}){let n=t??e.getByRole("combobox",{includeHidden:true}),s=o??e.getByTestId("combobox-toggle-button"),r=a=>e.getByRole("option",{name:a,exact:typeof a=="string"}),{isOpen:l,open:u}=g(n),d=async(a="click")=>{if(!await l()){if(a==="click"){await s.click();return}await u(a);}};return {input:n,toggleButton:s,listbox:e.getByRole("listbox"),option:r,isOpen:l,open:d,async selectOption(a){await d(),await r(a).click();},async filter(a){await n.fill(a);}}}function D({frame:e,root:t}){let o=t??e.locator(".BaselineUI-Editor"),n=o.getByTestId("editor-font-color-button"),s=o.getByTestId("editor-background-color-button"),r=o.getByTestId("editor-add-link-button"),l=o.getByTestId("editor-help-button"),u=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}),p=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: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:o.getByTestId("editor-save-button"),cancelButton:o.getByTestId("editor-cancel-button"),mentionButton:u,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 u.click();}}}function P({frame:e,trigger:t,variant:o="dropzone"}){let n=e.getByTestId("file-uploader"),s=n.locator('input[type="file"]'),r=t??(o==="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(l){await s.setInputFiles(l);}}}function U(e,t,o){let n=l=>t.getByRole("menuitem",{name:l}).or(t.getByRole("menuitemradio",{name:l})).or(t.getByRole("menuitemcheckbox",{name:l})),s=l=>t.getByRole("group",{name:l}),{isOpen:r}=g(o);return {menu:t,item:n,section:s,isOpen:r,submenu(l){let u=n(l),d=e.getByRole("menu",{name:l}),a=U(e,d,u),{open:i}=g(u);return {...a,trigger:u,open:async(c="Enter")=>i(c)}}}}function M({frame:e,trigger:t,longPress:o=false}){let n=t??e.getByTestId("menu-trigger"),s=e.getByRole("menu").first(),r=U(e,s,n),{button:l,open:u,isOpen:d}=g(n),a=async(i="click")=>{if(!o)return u(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 {...r,trigger:n,open:a,isOpen:d,async close(){await d()&&await n.press("Escape");},async selectItem(i){await a(),await r.item(i).click();}}}var $=(e=>{let o=Z(e);return e.multiple&&(o=ee(o,e.frame)),e.autocomplete&&(o=te(o,e.frame)),o});function Z({frame:e,trigger:t}){let o=t??e.getByTestId("select-button"),n=r=>e.getByRole("option",{name:r,exact:typeof r=="string"}),{open:s}=g(o);return {trigger:o,listbox:e.getByRole("listbox"),option:n,open:s,async selectOption(r){await s(),await n(r).click();}}}function ee(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 te(e,t){let o=t.getByRole("searchbox");return {...e,searchbox:o,async filter(n){await o.fill(n);}}}function oe(e){return {select:((t={})=>$({frame:e,...t})),comboBox:(t={})=>v({frame:e,...t}),editor:(t={})=>D({frame:e,...t}),fileUploader:(t={})=>P({frame:e,...t}),menu:(t={})=>M({frame:e,...t})}}export{E as DEFAULT_CRITICAL_INCOMPLETE_RULES,O as DEFAULT_DISABLED_RULES,L as DEFAULT_WCAG_TAGS,Y as expect,oe as testers};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baseline-ui/test-utils",
3
- "version": "3.3.0",
3
+ "version": "3.5.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.3.0"
55
+ "@baseline-ui/core": "3.5.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:154f47c5-a0e3-44e0-a561-31f800701e86",
5
+ "serialNumber": "urn:uuid:a99b0318-3c2d-44e5-b08d-a0b18a942c5c",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-12T15:06:03.025Z",
8
+ "timestamp": "2026-10-20T10:29:02.909Z",
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.3.0",
27
- "purl": "pkg:npm/@baseline-ui/test-utils@3.3.0",
28
- "bom-ref": "pkg:npm/@baseline-ui/test-utils@3.3.0",
26
+ "version": "3.5.0",
27
+ "purl": "pkg:npm/@baseline-ui/test-utils@3.5.0",
28
+ "bom-ref": "pkg:npm/@baseline-ui/test-utils@3.5.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.3.0",
503
+ "ref": "pkg:npm/@baseline-ui/test-utils@3.5.0",
504
504
  "dependsOn": [
505
505
  "pkg:npm/%40neondatabase/serverless@1.1.0",
506
506
  "pkg:npm/%40playwright/test@1.62.1",
@@ -2,6 +2,7 @@ import { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
2
2
 
3
3
  declare class FlakyReporter implements Reporter {
4
4
  private flakyTests;
5
+ private recordedTests;
5
6
  private browsers;
6
7
  private project;
7
8
  private variant;
@@ -13,7 +14,7 @@ declare class FlakyReporter implements Reporter {
13
14
  private detectProjectFromGit;
14
15
  private formatError;
15
16
  private stripAnsi;
16
- onTestEnd(test: TestCase, result: TestResult): void;
17
+ onTestEnd(test: TestCase, _result: TestResult): void;
17
18
  onEnd(): Promise<void>;
18
19
  }
19
20
 
@@ -2,6 +2,7 @@ import { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
2
2
 
3
3
  declare class FlakyReporter implements Reporter {
4
4
  private flakyTests;
5
+ private recordedTests;
5
6
  private browsers;
6
7
  private project;
7
8
  private variant;
@@ -13,7 +14,7 @@ declare class FlakyReporter implements Reporter {
13
14
  private detectProjectFromGit;
14
15
  private formatError;
15
16
  private stripAnsi;
16
- onTestEnd(test: TestCase, result: TestResult): void;
17
+ onTestEnd(test: TestCase, _result: TestResult): void;
17
18
  onEnd(): Promise<void>;
18
19
  }
19
20
 
@@ -7,7 +7,7 @@
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- var p=[`CREATE TABLE IF NOT EXISTS ci_runs (
10
+ var f=[`CREATE TABLE IF NOT EXISTS ci_runs (
11
11
  id BIGSERIAL PRIMARY KEY,
12
12
  project TEXT NOT NULL,
13
13
  browser TEXT NOT NULL,
@@ -28,19 +28,19 @@ var p=[`CREATE TABLE IF NOT EXISTS ci_runs (
28
28
  UNIQUE (test_name, project, browser, variant, run_date)
29
29
  )`,`CREATE INDEX IF NOT EXISTS idx_flaky_tests_date
30
30
  ON flaky_tests (run_date)`,`CREATE INDEX IF NOT EXISTS idx_flaky_tests_identity_date
31
- ON flaky_tests (test_name, project, browser, variant, run_date)`],E=`
31
+ ON flaky_tests (test_name, project, browser, variant, run_date)`],A=`
32
32
  INSERT INTO ci_runs (project, browser, variant, run_date, run_count)
33
33
  VALUES ($1, $2, $3, CURRENT_DATE, 1)
34
34
  ON CONFLICT (project, browser, variant, run_date) DO UPDATE SET
35
35
  run_count = ci_runs.run_count + 1
36
- `,_=`
36
+ `,N=`
37
37
  INSERT INTO flaky_tests (test_name, file_path, project, browser, variant, run_date, flaky_count, error_message)
38
38
  SELECT unnest($1::text[]), unnest($2::text[]), unnest($3::text[]), unnest($4::text[]), unnest($5::text[]),
39
- CURRENT_DATE, 1, unnest($6::text[])
39
+ CURRENT_DATE, unnest($7::int[]), unnest($6::text[])
40
40
  ON CONFLICT (test_name, project, browser, variant, run_date) DO UPDATE SET
41
41
  file_path = EXCLUDED.file_path,
42
- flaky_count = flaky_tests.flaky_count + 1,
42
+ flaky_count = flaky_tests.flaky_count + EXCLUDED.flaky_count,
43
43
  error_message = COALESCE(EXCLUDED.error_message, flaky_tests.error_message)
44
- `,i=class{flakyTests=[];browsers=new Set;project;variant;databaseUrl;rootDir;constructor(){this.databaseUrl=process.env.TEST_DASHBOARD_DATABASE_URL,this.rootDir=this.detectRootDir(),this.project=process.env.PROJECT??this.detectProjectFromGit(),this.variant=this.deriveVariant();}deriveVariant(){return process.env.METADATA_SHADOW_DOM==="true"?"shadow-dom":process.env.METADATA_IFRAME==="true"?"iframe":"default"}detectRootDir(){if(process.env.TEST_ROOT_DIR)return process.env.TEST_ROOT_DIR;try{return child_process.execSync("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return console.debug("[flaky-reporter] Could not detect git root, falling back to cwd."),process.cwd()}}detectProjectFromGit(){try{let t=child_process.execSync("git remote get-url origin",{encoding:"utf8"}).trim(),r=/[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/.exec(t);if(r)return `${r[1]}/${r[2]}`}catch{console.debug("[flaky-reporter] Could not detect project from git remote.");}return "unknown"}formatError(t){if(!t)return null;let r=[];if(t.message&&r.push(t.message),t.snippet&&r.push(t.snippet),t.stack){let s=t.message?t.stack.replace(t.message,"").trim():t.stack;s&&r.push(s);}return this.stripAnsi(r.join(`
44
+ `,u=class{flakyTests=[];recordedTests=new Set;browsers=new Set;project;variant;databaseUrl;rootDir;constructor(){this.databaseUrl=process.env.TEST_DASHBOARD_DATABASE_URL,this.rootDir=this.detectRootDir(),this.project=process.env.PROJECT??this.detectProjectFromGit(),this.variant=this.deriveVariant();}deriveVariant(){return process.env.METADATA_VARIANT?process.env.METADATA_VARIANT:process.env.METADATA_SHADOW_DOM==="true"?"shadow-dom":process.env.METADATA_IFRAME==="true"?"iframe":"default"}detectRootDir(){if(process.env.TEST_ROOT_DIR)return process.env.TEST_ROOT_DIR;try{return child_process.execSync("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return console.debug("[flaky-reporter] Could not detect git root, falling back to cwd."),process.cwd()}}detectProjectFromGit(){try{let e=child_process.execSync("git remote get-url origin",{encoding:"utf8"}).trim(),r=/[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/.exec(e);if(r)return `${r[1]}/${r[2]}`}catch{console.debug("[flaky-reporter] Could not detect project from git remote.");}return "unknown"}formatError(e){if(!e)return null;let r=[];if(e.message&&r.push(e.message),e.snippet&&r.push(e.snippet),e.stack){let s=e.message?e.stack.replace(e.message,"").trim():e.stack;s&&r.push(s);}return this.stripAnsi(r.join(`
45
45
 
46
- `))||null}stripAnsi(t){return t.replaceAll(/\u001B\[[0-9;]*m/g,"")}onTestEnd(t,r){if(!this.databaseUrl)return;let s=t.parent.project()?.name??"unknown";if(this.browsers.add(s),!(r.status==="passed"&&t.results.length>1&&t.results.some(a=>a.status==="failed")))return;let n=t.results.find(a=>a.status==="failed");this.flakyTests.push({test_name:t.titlePath().filter(Boolean).join(" > "),file_path:t.location.file.replace(this.rootDir+"/",""),browser:s,error_message:this.formatError(n?.error)});}async onEnd(){if(!this.databaseUrl)return;let t="@neondatabase/serverless",r;try{({neon:r}=await import(t));}catch{console.error("[flaky-reporter] @neondatabase/serverless is not installed. Skipping.");return}let s=r(this.databaseUrl);try{for(let e of p)await s.query(e);}catch(e){console.error("[flaky-reporter] CRITICAL: Failed to initialize database tables. No flaky test data was recorded. Check TEST_DASHBOARD_DATABASE_URL and database permissions.",e);return}try{for(let e of this.browsers)await s.query(E,[this.project,e,this.variant]);}catch(e){console.error("[flaky-reporter] Failed to record CI run:",e);}if(this.flakyTests.length===0){console.log("[flaky-reporter] No flaky tests detected.");return}let o=[],n=[],a=[],l=[],c=[],T=[];for(let e of this.flakyTests)o.push(e.test_name),n.push(e.file_path),a.push(this.project),l.push(e.browser),c.push(this.variant),T.push(e.error_message);try{await s.query(_,[o,n,a,l,c,T]),console.log(`[flaky-reporter] Reported ${this.flakyTests.length} flaky test(s) to database.`);}catch(e){console.error("[flaky-reporter] Failed to write to database:",e);}}},N=i;module.exports=N;
46
+ `))||null}stripAnsi(e){return e.replaceAll(/\u001B\[[0-9;]*m/g,"")}onTestEnd(e,r){if(!this.databaseUrl)return;let s=e.parent.project()?.name??"unknown";if(this.browsers.add(s),e.outcome()!=="flaky"||this.recordedTests.has(e))return;this.recordedTests.add(e);let o=e.results.find(n=>n.status!==e.expectedStatus&&n.status!=="skipped"&&n.status!=="interrupted");this.flakyTests.push({test_name:e.titlePath().filter(Boolean).join(" > "),file_path:e.location.file.replace(this.rootDir+"/",""),browser:s,error_message:this.formatError(o?.error)});}async onEnd(){if(!this.databaseUrl)return;let e="@neondatabase/serverless",r;try{({neon:r}=await import(e));}catch{console.error("[flaky-reporter] @neondatabase/serverless is not installed. Skipping.");return}let s=r(this.databaseUrl);try{for(let t of f)await s.query(t);}catch(t){console.error("[flaky-reporter] CRITICAL: Failed to initialize database tables. No flaky test data was recorded. Check TEST_DASHBOARD_DATABASE_URL and database permissions.",t);return}try{for(let t of this.browsers)await s.query(A,[this.project,t,this.variant]);}catch(t){console.error("[flaky-reporter] Failed to record CI run:",t);}if(this.flakyTests.length===0){console.log("[flaky-reporter] No flaky tests detected.");return}let o=[],n=[],T=[],l=[],p=[],d=[],_=[],a=new Map;for(let t of this.flakyTests){let i=`${t.test_name}\0${t.browser}`,c=a.get(i);c?(c.count++,c.record.error_message=t.error_message??c.record.error_message):a.set(i,{record:{...t},count:1});}for(let{record:t,count:i}of a.values())o.push(t.test_name),n.push(t.file_path),T.push(this.project),l.push(t.browser),p.push(this.variant),d.push(t.error_message),_.push(i);try{await s.query(N,[o,n,T,l,p,d,_]),console.log(`[flaky-reporter] Reported ${a.size} flaky test(s) to database.`);}catch(t){console.error("[flaky-reporter] Failed to write to database:",t);}}},m=u;module.exports=m;
@@ -7,7 +7,7 @@ import {execSync}from'child_process';/**
7
7
  * This notice may not be removed from this file.
8
8
  *
9
9
  */
10
- var p=[`CREATE TABLE IF NOT EXISTS ci_runs (
10
+ var f=[`CREATE TABLE IF NOT EXISTS ci_runs (
11
11
  id BIGSERIAL PRIMARY KEY,
12
12
  project TEXT NOT NULL,
13
13
  browser TEXT NOT NULL,
@@ -28,19 +28,19 @@ var p=[`CREATE TABLE IF NOT EXISTS ci_runs (
28
28
  UNIQUE (test_name, project, browser, variant, run_date)
29
29
  )`,`CREATE INDEX IF NOT EXISTS idx_flaky_tests_date
30
30
  ON flaky_tests (run_date)`,`CREATE INDEX IF NOT EXISTS idx_flaky_tests_identity_date
31
- ON flaky_tests (test_name, project, browser, variant, run_date)`],E=`
31
+ ON flaky_tests (test_name, project, browser, variant, run_date)`],A=`
32
32
  INSERT INTO ci_runs (project, browser, variant, run_date, run_count)
33
33
  VALUES ($1, $2, $3, CURRENT_DATE, 1)
34
34
  ON CONFLICT (project, browser, variant, run_date) DO UPDATE SET
35
35
  run_count = ci_runs.run_count + 1
36
- `,_=`
36
+ `,N=`
37
37
  INSERT INTO flaky_tests (test_name, file_path, project, browser, variant, run_date, flaky_count, error_message)
38
38
  SELECT unnest($1::text[]), unnest($2::text[]), unnest($3::text[]), unnest($4::text[]), unnest($5::text[]),
39
- CURRENT_DATE, 1, unnest($6::text[])
39
+ CURRENT_DATE, unnest($7::int[]), unnest($6::text[])
40
40
  ON CONFLICT (test_name, project, browser, variant, run_date) DO UPDATE SET
41
41
  file_path = EXCLUDED.file_path,
42
- flaky_count = flaky_tests.flaky_count + 1,
42
+ flaky_count = flaky_tests.flaky_count + EXCLUDED.flaky_count,
43
43
  error_message = COALESCE(EXCLUDED.error_message, flaky_tests.error_message)
44
- `,i=class{flakyTests=[];browsers=new Set;project;variant;databaseUrl;rootDir;constructor(){this.databaseUrl=process.env.TEST_DASHBOARD_DATABASE_URL,this.rootDir=this.detectRootDir(),this.project=process.env.PROJECT??this.detectProjectFromGit(),this.variant=this.deriveVariant();}deriveVariant(){return process.env.METADATA_SHADOW_DOM==="true"?"shadow-dom":process.env.METADATA_IFRAME==="true"?"iframe":"default"}detectRootDir(){if(process.env.TEST_ROOT_DIR)return process.env.TEST_ROOT_DIR;try{return execSync("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return console.debug("[flaky-reporter] Could not detect git root, falling back to cwd."),process.cwd()}}detectProjectFromGit(){try{let t=execSync("git remote get-url origin",{encoding:"utf8"}).trim(),r=/[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/.exec(t);if(r)return `${r[1]}/${r[2]}`}catch{console.debug("[flaky-reporter] Could not detect project from git remote.");}return "unknown"}formatError(t){if(!t)return null;let r=[];if(t.message&&r.push(t.message),t.snippet&&r.push(t.snippet),t.stack){let s=t.message?t.stack.replace(t.message,"").trim():t.stack;s&&r.push(s);}return this.stripAnsi(r.join(`
44
+ `,u=class{flakyTests=[];recordedTests=new Set;browsers=new Set;project;variant;databaseUrl;rootDir;constructor(){this.databaseUrl=process.env.TEST_DASHBOARD_DATABASE_URL,this.rootDir=this.detectRootDir(),this.project=process.env.PROJECT??this.detectProjectFromGit(),this.variant=this.deriveVariant();}deriveVariant(){return process.env.METADATA_VARIANT?process.env.METADATA_VARIANT:process.env.METADATA_SHADOW_DOM==="true"?"shadow-dom":process.env.METADATA_IFRAME==="true"?"iframe":"default"}detectRootDir(){if(process.env.TEST_ROOT_DIR)return process.env.TEST_ROOT_DIR;try{return execSync("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return console.debug("[flaky-reporter] Could not detect git root, falling back to cwd."),process.cwd()}}detectProjectFromGit(){try{let e=execSync("git remote get-url origin",{encoding:"utf8"}).trim(),r=/[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/.exec(e);if(r)return `${r[1]}/${r[2]}`}catch{console.debug("[flaky-reporter] Could not detect project from git remote.");}return "unknown"}formatError(e){if(!e)return null;let r=[];if(e.message&&r.push(e.message),e.snippet&&r.push(e.snippet),e.stack){let s=e.message?e.stack.replace(e.message,"").trim():e.stack;s&&r.push(s);}return this.stripAnsi(r.join(`
45
45
 
46
- `))||null}stripAnsi(t){return t.replaceAll(/\u001B\[[0-9;]*m/g,"")}onTestEnd(t,r){if(!this.databaseUrl)return;let s=t.parent.project()?.name??"unknown";if(this.browsers.add(s),!(r.status==="passed"&&t.results.length>1&&t.results.some(a=>a.status==="failed")))return;let n=t.results.find(a=>a.status==="failed");this.flakyTests.push({test_name:t.titlePath().filter(Boolean).join(" > "),file_path:t.location.file.replace(this.rootDir+"/",""),browser:s,error_message:this.formatError(n?.error)});}async onEnd(){if(!this.databaseUrl)return;let t="@neondatabase/serverless",r;try{({neon:r}=await import(t));}catch{console.error("[flaky-reporter] @neondatabase/serverless is not installed. Skipping.");return}let s=r(this.databaseUrl);try{for(let e of p)await s.query(e);}catch(e){console.error("[flaky-reporter] CRITICAL: Failed to initialize database tables. No flaky test data was recorded. Check TEST_DASHBOARD_DATABASE_URL and database permissions.",e);return}try{for(let e of this.browsers)await s.query(E,[this.project,e,this.variant]);}catch(e){console.error("[flaky-reporter] Failed to record CI run:",e);}if(this.flakyTests.length===0){console.log("[flaky-reporter] No flaky tests detected.");return}let o=[],n=[],a=[],l=[],c=[],T=[];for(let e of this.flakyTests)o.push(e.test_name),n.push(e.file_path),a.push(this.project),l.push(e.browser),c.push(this.variant),T.push(e.error_message);try{await s.query(_,[o,n,a,l,c,T]),console.log(`[flaky-reporter] Reported ${this.flakyTests.length} flaky test(s) to database.`);}catch(e){console.error("[flaky-reporter] Failed to write to database:",e);}}},N=i;export{N as default};
46
+ `))||null}stripAnsi(e){return e.replaceAll(/\u001B\[[0-9;]*m/g,"")}onTestEnd(e,r){if(!this.databaseUrl)return;let s=e.parent.project()?.name??"unknown";if(this.browsers.add(s),e.outcome()!=="flaky"||this.recordedTests.has(e))return;this.recordedTests.add(e);let o=e.results.find(n=>n.status!==e.expectedStatus&&n.status!=="skipped"&&n.status!=="interrupted");this.flakyTests.push({test_name:e.titlePath().filter(Boolean).join(" > "),file_path:e.location.file.replace(this.rootDir+"/",""),browser:s,error_message:this.formatError(o?.error)});}async onEnd(){if(!this.databaseUrl)return;let e="@neondatabase/serverless",r;try{({neon:r}=await import(e));}catch{console.error("[flaky-reporter] @neondatabase/serverless is not installed. Skipping.");return}let s=r(this.databaseUrl);try{for(let t of f)await s.query(t);}catch(t){console.error("[flaky-reporter] CRITICAL: Failed to initialize database tables. No flaky test data was recorded. Check TEST_DASHBOARD_DATABASE_URL and database permissions.",t);return}try{for(let t of this.browsers)await s.query(A,[this.project,t,this.variant]);}catch(t){console.error("[flaky-reporter] Failed to record CI run:",t);}if(this.flakyTests.length===0){console.log("[flaky-reporter] No flaky tests detected.");return}let o=[],n=[],T=[],l=[],p=[],d=[],_=[],a=new Map;for(let t of this.flakyTests){let i=`${t.test_name}\0${t.browser}`,c=a.get(i);c?(c.count++,c.record.error_message=t.error_message??c.record.error_message):a.set(i,{record:{...t},count:1});}for(let{record:t,count:i}of a.values())o.push(t.test_name),n.push(t.file_path),T.push(this.project),l.push(t.browser),p.push(this.variant),d.push(t.error_message),_.push(i);try{await s.query(N,[o,n,T,l,p,d,_]),console.log(`[flaky-reporter] Reported ${a.size} flaky test(s) to database.`);}catch(t){console.error("[flaky-reporter] Failed to write to database:",t);}}},m=u;export{m as default};