@baseline-ui/test-utils 0.57.1 → 0.58.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/Acknowledgements.md +4095 -786
- package/dist/index.d.mts +42 -3
- package/dist/index.d.ts +42 -3
- package/dist/index.js +13 -5
- package/dist/index.mjs +13 -5
- package/package.json +3 -2
- package/sbom.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import * as _playwright_test from '@playwright/test';
|
|
2
|
-
import { Locator } from '@playwright/test';
|
|
2
|
+
import { Page, Locator, FrameLocator } from '@playwright/test';
|
|
3
3
|
import { SinonSpy } from 'sinon';
|
|
4
4
|
|
|
5
|
+
declare const DEFAULT_WCAG_TAGS: readonly ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice"];
|
|
6
|
+
declare const DEFAULT_DISABLED_RULES: readonly ["landmark-one-main", "page-has-heading-one", "region", "aria-allowed-role", "duplicate-id", "scrollable-region-focusable"];
|
|
7
|
+
declare const DEFAULT_CRITICAL_INCOMPLETE_RULES: readonly ["aria-valid-attr-value", "aria-valid-attr", "aria-required-attr"];
|
|
8
|
+
interface ToBeAccessibleOptions {
|
|
9
|
+
/** Axe tag set to run (e.g. `wcag2aa`). Defaults to `DEFAULT_WCAG_TAGS`. */
|
|
10
|
+
tags?: readonly string[];
|
|
11
|
+
/** Axe rule IDs to skip, merged with `DEFAULT_DISABLED_RULES`. */
|
|
12
|
+
disableRules?: readonly string[];
|
|
13
|
+
/** CSS selector(s) to include in the scan (in addition to any auto-scoping). */
|
|
14
|
+
include?: string | readonly string[];
|
|
15
|
+
/** CSS selector(s) to exclude from the scan. */
|
|
16
|
+
exclude?: string | readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Axe rule IDs whose `incomplete` results should be treated as violations.
|
|
19
|
+
* Replaces (does not extend) `DEFAULT_CRITICAL_INCOMPLETE_RULES` when set.
|
|
20
|
+
*/
|
|
21
|
+
treatIncompleteAsViolationIds?: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* When `> 0`, retries the scan via `expect.poll` until it finds no
|
|
24
|
+
* violations or the timeout (ms) elapses. Falsy / `0` / negative values
|
|
25
|
+
* run the scan exactly once.
|
|
26
|
+
*/
|
|
27
|
+
timeout?: number;
|
|
28
|
+
/** Filename used when attaching the axe report to the Playwright report on failure. */
|
|
29
|
+
attachmentName?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
declare const expect: _playwright_test.Expect<{
|
|
6
33
|
toBeWithinDelta(this: _playwright_test.ExpectMatcherState, received: number, expected: number, delta: number): {
|
|
7
34
|
message: () => string;
|
|
@@ -59,7 +86,19 @@ declare const expect: _playwright_test.Expect<{
|
|
|
59
86
|
message: () => string;
|
|
60
87
|
pass: false;
|
|
61
88
|
}>;
|
|
62
|
-
|
|
89
|
+
toBeAccessible(this: {
|
|
90
|
+
isNot?: boolean;
|
|
91
|
+
}, target: Page | Locator | FrameLocator, options?: ToBeAccessibleOptions): Promise<{
|
|
92
|
+
message: () => string;
|
|
93
|
+
pass: true;
|
|
94
|
+
} | {
|
|
95
|
+
message: () => string;
|
|
96
|
+
pass: false;
|
|
97
|
+
}>;
|
|
98
|
+
toMatchClassTree(this: _playwright_test.ExpectMatcherState, locator: Locator, snapshotName?: string, options?: {
|
|
99
|
+
prefix?: string | string[];
|
|
100
|
+
ignoreHashed?: boolean;
|
|
101
|
+
}): Promise<{
|
|
63
102
|
message: () => string;
|
|
64
103
|
pass: false;
|
|
65
104
|
} | {
|
|
@@ -68,4 +107,4 @@ declare const expect: _playwright_test.Expect<{
|
|
|
68
107
|
}>;
|
|
69
108
|
}>;
|
|
70
109
|
|
|
71
|
-
export { expect };
|
|
110
|
+
export { DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type ToBeAccessibleOptions, expect };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import * as _playwright_test from '@playwright/test';
|
|
2
|
-
import { Locator } from '@playwright/test';
|
|
2
|
+
import { Page, Locator, FrameLocator } from '@playwright/test';
|
|
3
3
|
import { SinonSpy } from 'sinon';
|
|
4
4
|
|
|
5
|
+
declare const DEFAULT_WCAG_TAGS: readonly ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice"];
|
|
6
|
+
declare const DEFAULT_DISABLED_RULES: readonly ["landmark-one-main", "page-has-heading-one", "region", "aria-allowed-role", "duplicate-id", "scrollable-region-focusable"];
|
|
7
|
+
declare const DEFAULT_CRITICAL_INCOMPLETE_RULES: readonly ["aria-valid-attr-value", "aria-valid-attr", "aria-required-attr"];
|
|
8
|
+
interface ToBeAccessibleOptions {
|
|
9
|
+
/** Axe tag set to run (e.g. `wcag2aa`). Defaults to `DEFAULT_WCAG_TAGS`. */
|
|
10
|
+
tags?: readonly string[];
|
|
11
|
+
/** Axe rule IDs to skip, merged with `DEFAULT_DISABLED_RULES`. */
|
|
12
|
+
disableRules?: readonly string[];
|
|
13
|
+
/** CSS selector(s) to include in the scan (in addition to any auto-scoping). */
|
|
14
|
+
include?: string | readonly string[];
|
|
15
|
+
/** CSS selector(s) to exclude from the scan. */
|
|
16
|
+
exclude?: string | readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Axe rule IDs whose `incomplete` results should be treated as violations.
|
|
19
|
+
* Replaces (does not extend) `DEFAULT_CRITICAL_INCOMPLETE_RULES` when set.
|
|
20
|
+
*/
|
|
21
|
+
treatIncompleteAsViolationIds?: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* When `> 0`, retries the scan via `expect.poll` until it finds no
|
|
24
|
+
* violations or the timeout (ms) elapses. Falsy / `0` / negative values
|
|
25
|
+
* run the scan exactly once.
|
|
26
|
+
*/
|
|
27
|
+
timeout?: number;
|
|
28
|
+
/** Filename used when attaching the axe report to the Playwright report on failure. */
|
|
29
|
+
attachmentName?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
declare const expect: _playwright_test.Expect<{
|
|
6
33
|
toBeWithinDelta(this: _playwright_test.ExpectMatcherState, received: number, expected: number, delta: number): {
|
|
7
34
|
message: () => string;
|
|
@@ -59,7 +86,19 @@ declare const expect: _playwright_test.Expect<{
|
|
|
59
86
|
message: () => string;
|
|
60
87
|
pass: false;
|
|
61
88
|
}>;
|
|
62
|
-
|
|
89
|
+
toBeAccessible(this: {
|
|
90
|
+
isNot?: boolean;
|
|
91
|
+
}, target: Page | Locator | FrameLocator, options?: ToBeAccessibleOptions): Promise<{
|
|
92
|
+
message: () => string;
|
|
93
|
+
pass: true;
|
|
94
|
+
} | {
|
|
95
|
+
message: () => string;
|
|
96
|
+
pass: false;
|
|
97
|
+
}>;
|
|
98
|
+
toMatchClassTree(this: _playwright_test.ExpectMatcherState, locator: Locator, snapshotName?: string, options?: {
|
|
99
|
+
prefix?: string | string[];
|
|
100
|
+
ignoreHashed?: boolean;
|
|
101
|
+
}): Promise<{
|
|
63
102
|
message: () => string;
|
|
64
103
|
pass: false;
|
|
65
104
|
} | {
|
|
@@ -68,4 +107,4 @@ declare const expect: _playwright_test.Expect<{
|
|
|
68
107
|
}>;
|
|
69
108
|
}>;
|
|
70
109
|
|
|
71
|
-
export { expect };
|
|
110
|
+
export { DEFAULT_CRITICAL_INCOMPLETE_RULES, DEFAULT_DISABLED_RULES, DEFAULT_WCAG_TAGS, type ToBeAccessibleOptions, expect };
|
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'),F=require('axe-core'),promises=require('fs/promises'),R=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var F__default=/*#__PURE__*/_interopDefault(F);var R__default=/*#__PURE__*/_interopDefault(R);/**
|
|
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,7 +7,15 @@
|
|
|
7
7
|
* This notice may not be removed from this file.
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
|
-
function
|
|
11
|
-
`):
|
|
12
|
-
`)}var C=test.expect.extend({toBeWithinDelta(
|
|
13
|
-
`)
|
|
10
|
+
var A=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],b=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],L=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function T(e,t={}){let{prefix:n="BaselineUI-",ignoreHashed:s=false}=t,d=Array.isArray(n)?n:[n];function i(o){return o.split(/[-_]/).some(a=>a.length>=5&&/^[a-z\d]+$/.test(a)&&/[a-z]/.test(a)&&/\d/.test(a))}function c(o){return [...o.classList].filter(a=>d.some(p=>a.startsWith(p))&&(!s||!i(a)))}function l(o,a=false){let p=[],x=o.shadowRoot?o.shadowRoot.children:o.children;for(let h of x){let w=a||h.getAttribute("aria-hidden")==="true",y=c(h),E=l(h,w);y.length>0?p.push({classes:y,children:E,hidden:w}):p.push(...E);}return p}function g(o,a="",p=false){let x=[];for(let h=0;h<o.length;h++){let w=o[h],y=h===o.length-1,E=p?"":y?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",I=p?"":a+(y?" ":"\u2502 "),$=w.classes.join(", ");x.push(a+E+$+(w.hidden?" [aria-hidden]":""),...g(w.children,I));}return x}let u=c(e),r=l(e);return u.length===0&&r.length===0?"":u.length>0?g([{classes:u,children:r,hidden:false}],"",true).join(`
|
|
11
|
+
`):g(r,"",true).join(`
|
|
12
|
+
`)}var m=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"}},U=async e=>{let t=typeof e.goto=="function",n=!t&&typeof e.owner=="function";if(t||n)return e.locator("body");let s=e;return await s.first().evaluate(i=>i.tagName?.toLowerCase()==="iframe").catch(()=>false)?s.contentFrame().locator("body"):s},j=async e=>{await e.first().evaluate((t,n)=>{if(window.axe)return;let d=document.createElement("script");d.textContent=n,document.head.append(d);},F__default.default.source);},k=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],N=(e,t=[])=>{let n=new Set([...b,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??A]},rules:Object.fromEntries([...n].map(s=>[s,{enabled:false}]))}},_=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},v=async(e,t,n)=>{let s=await e.count();if(s===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await j(e);let d=_(t.include),i=_(t.exclude);return s===1?await e.evaluate(async(c,l)=>{let g=window,u={include:[c,...l.userInclude??[]],exclude:l.userExclude??[]};return await g.axe.run(u,l.runOptions)},{userInclude:d,userExclude:i,runOptions:n}):await e.evaluateAll(async(c,l)=>{let g=window,u={include:[...c,...l.userInclude??[]],exclude:l.userExclude??[]};return await g.axe.run(u,l.runOptions)},{userInclude:d,userExclude:i,runOptions:n})},C="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function W(e){return Array.isArray(e)?e.length===1&&e[0]===C:e===C}function H(e){return (Array.isArray(e)?e:[e]).join("+")}function G(e,t,n,s,d){let i=t.slice(1).map(c=>S(c));return n&&i.push(S(n)),s!==void 0&&!W(s)&&i.push(S(H(s))),d&&i.push("ignoreHashed"),R__default.default.join(e,`${i.join("--")}.txt`)}var M=test.expect.extend({toBeWithinDelta(e,t,n){return Math.abs(e-t)<=n?{message:()=>`expected ${e} not to be within ${n} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${n} of ${t}`,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(t){return {message:()=>m(t),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(t){return {message:()=>m(t),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(t){return {message:()=>m(t),pass:false}}},async toBeCalledWith(e,...t){try{return await test.expect(()=>{for(let[n,s]of t.entries())test.expect(e.lastCall?.args?.[n]).toStrictEqual(s);}).toPass(),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},async toBeCalledWithExactly(e,...t){try{return await test.expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},toBeCalled(e){try{return test.expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>m(t),pass:false}}},async toBeCalledTimes(e,t){try{return await test.expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},async toBeAccessible(e,t={}){let n=await U(e),s=await n.first().evaluate(r=>{let o=r.ownerDocument?.defaultView;return o!==null&&o!==window.top}).catch(()=>false),d=N(t,s?k:[]),i,c=async()=>{let r=await v(n,t,d),o=t.treatIncompleteAsViolationIds??L,a=[...r.violations,...r.incomplete.filter(p=>o.includes(p.id))];return i={result:r,violations:a},a},l;try{if(t.timeout&&t.timeout>0){let r=test.expect.poll(c,{timeout:t.timeout});await(this.isNot?r.not.toHaveLength(0):r.toHaveLength(0));}else await c();}catch(r){l=r;}if(!i)throw new Error(`toBeAccessible: axe scan never completed.
|
|
13
|
+
${m(l)}`);if(i.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(i.result,null,2),contentType:"application/json"});let g=i.violations.map(r=>{let o=r.nodes.map(a=>Array.isArray(a.target)?a.target.join(" "):String(a.target)).join(`
|
|
14
|
+
`);return ` \u2022 [${r.id}] ${r.help}
|
|
15
|
+
${o}
|
|
16
|
+
${r.helpUrl??""}`}).join(`
|
|
17
|
+
`),u=i.violations.length;return {message:()=>`Found ${u} accessibility violation${u===1?"":"s"}:
|
|
18
|
+
${g}`,pass:false}},async toMatchClassTree(e,t,n={}){let{prefix:s=C,ignoreHashed:d=false}=n,i=await e.evaluate(T,{prefix:s,ignoreHashed:d});if(!i){let c=Array.isArray(s)?s.map(l=>`${l}*`).join(" / "):`${s}*`;return {message:()=>`No ${c} classes found in the DOM tree.`,pass:false}}try{let c=`${i}
|
|
19
|
+
`,l=test.test.info();if(l.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:!0};let u=G(l.project.snapshotDir,l.titlePath,t,s,d),r=l.config.updateSnapshots;await promises.mkdir(R__default.default.dirname(u),{recursive:!0});let o;try{o=await promises.readFile(u,"utf8");}catch(a){if(a.code==="ENOENT"&&r!=="none")return await promises.writeFile(u,c),{message:()=>"Class tree snapshot created.",pass:!0};throw a}if(o!==c){if(r==="all"||r==="changed")return await promises.writeFile(u,c),{message:()=>"Class tree snapshot updated.",pass:!0};try{test.expect(c).toBe(o);}catch(a){return {message:()=>`Class tree snapshot mismatch at ${u}
|
|
20
|
+
|
|
21
|
+
${a.message}`,pass:!1}}}return {message:()=>"Class tree matched snapshot.",pass:!0}}catch(c){return {message:()=>m(c),pass:false}}}});exports.DEFAULT_CRITICAL_INCOMPLETE_RULES=L;exports.DEFAULT_DISABLED_RULES=b;exports.DEFAULT_WCAG_TAGS=A;exports.expect=M;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {expect}from'@playwright/test';/**
|
|
1
|
+
import {expect,test}from'@playwright/test';import F from'axe-core';import {mkdir,readFile,writeFile}from'fs/promises';import R 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,7 +7,15 @@ import {expect}from'@playwright/test';/**
|
|
|
7
7
|
* This notice may not be removed from this file.
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
|
-
function
|
|
11
|
-
`):
|
|
12
|
-
`)}var C=expect.extend({toBeWithinDelta(
|
|
13
|
-
`)
|
|
10
|
+
var A=["wcag2a","wcag2aa","wcag21a","wcag21aa","best-practice"],b=["landmark-one-main","page-has-heading-one","region","aria-allowed-role","duplicate-id","scrollable-region-focusable"],L=["aria-valid-attr-value","aria-valid-attr","aria-required-attr"];function T(e,t={}){let{prefix:n="BaselineUI-",ignoreHashed:s=false}=t,d=Array.isArray(n)?n:[n];function i(o){return o.split(/[-_]/).some(a=>a.length>=5&&/^[a-z\d]+$/.test(a)&&/[a-z]/.test(a)&&/\d/.test(a))}function c(o){return [...o.classList].filter(a=>d.some(p=>a.startsWith(p))&&(!s||!i(a)))}function l(o,a=false){let p=[],x=o.shadowRoot?o.shadowRoot.children:o.children;for(let h of x){let w=a||h.getAttribute("aria-hidden")==="true",y=c(h),E=l(h,w);y.length>0?p.push({classes:y,children:E,hidden:w}):p.push(...E);}return p}function g(o,a="",p=false){let x=[];for(let h=0;h<o.length;h++){let w=o[h],y=h===o.length-1,E=p?"":y?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",I=p?"":a+(y?" ":"\u2502 "),$=w.classes.join(", ");x.push(a+E+$+(w.hidden?" [aria-hidden]":""),...g(w.children,I));}return x}let u=c(e),r=l(e);return u.length===0&&r.length===0?"":u.length>0?g([{classes:u,children:r,hidden:false}],"",true).join(`
|
|
11
|
+
`):g(r,"",true).join(`
|
|
12
|
+
`)}var m=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"}},U=async e=>{let t=typeof e.goto=="function",n=!t&&typeof e.owner=="function";if(t||n)return e.locator("body");let s=e;return await s.first().evaluate(i=>i.tagName?.toLowerCase()==="iframe").catch(()=>false)?s.contentFrame().locator("body"):s},j=async e=>{await e.first().evaluate((t,n)=>{if(window.axe)return;let d=document.createElement("script");d.textContent=n,document.head.append(d);},F.source);},k=["document-title","html-has-lang","html-lang-valid","html-xml-lang-mismatch"],N=(e,t=[])=>{let n=new Set([...b,...t,...e.disableRules??[]]);return {runOnly:{type:"tag",values:[...e.tags??A]},rules:Object.fromEntries([...n].map(s=>[s,{enabled:false}]))}},_=e=>{if(e!==void 0)return typeof e=="string"?[e]:[...e]},v=async(e,t,n)=>{let s=await e.count();if(s===0)throw new Error("toBeAccessible: locator resolved to zero elements; nothing to scan.");await j(e);let d=_(t.include),i=_(t.exclude);return s===1?await e.evaluate(async(c,l)=>{let g=window,u={include:[c,...l.userInclude??[]],exclude:l.userExclude??[]};return await g.axe.run(u,l.runOptions)},{userInclude:d,userExclude:i,runOptions:n}):await e.evaluateAll(async(c,l)=>{let g=window,u={include:[...c,...l.userInclude??[]],exclude:l.userExclude??[]};return await g.axe.run(u,l.runOptions)},{userInclude:d,userExclude:i,runOptions:n})},C="BaselineUI-";function S(e){return e.replaceAll(/\W+/g,"-").replaceAll(/^-|-$/g,"")}function W(e){return Array.isArray(e)?e.length===1&&e[0]===C:e===C}function H(e){return (Array.isArray(e)?e:[e]).join("+")}function G(e,t,n,s,d){let i=t.slice(1).map(c=>S(c));return n&&i.push(S(n)),s!==void 0&&!W(s)&&i.push(S(H(s))),d&&i.push("ignoreHashed"),R.join(e,`${i.join("--")}.txt`)}var M=expect.extend({toBeWithinDelta(e,t,n){return Math.abs(e-t)<=n?{message:()=>`expected ${e} not to be within ${n} of ${t}`,pass:true}:{message:()=>`expected ${e} to be within ${n} of ${t}`,pass:false}},async toBeCalledOnce(e){try{return await expect.poll(()=>e.callCount).toBe(1),{message:()=>"Expected function to be called once.",pass:!0}}catch(t){return {message:()=>m(t),pass:false}}},async toBeCalledTwice(e){try{return await expect.poll(()=>e.callCount).toBe(2),{message:()=>"Expected function to be called twice.",pass:!0}}catch(t){return {message:()=>m(t),pass:false}}},async toBeCalledThrice(e){try{return await expect.poll(()=>e.callCount).toBe(3),{message:()=>"Expected function to be called thrice.",pass:!0}}catch(t){return {message:()=>m(t),pass:false}}},async toBeCalledWith(e,...t){try{return await expect(()=>{for(let[n,s]of t.entries())expect(e.lastCall?.args?.[n]).toStrictEqual(s);}).toPass(),{message:()=>`Expected function to be called with ${t.join(", ")}.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},async toBeCalledWithExactly(e,...t){try{return await expect.poll(()=>e.lastCall?.args).toStrictEqual(t),{message:()=>`Expected function to be called with exactly ${t.join(", ")}.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},toBeCalled(e){try{return expect(e.called).toBeTruthy(),{message:()=>"Expected function to be called.",pass:!0}}catch(t){return {message:()=>m(t),pass:false}}},async toBeCalledTimes(e,t){try{return await expect.poll(()=>e.callCount).toBe(t),{message:()=>`Expected function to be called ${t} times.`,pass:!0}}catch(n){return {message:()=>m(n),pass:false}}},async toBeAccessible(e,t={}){let n=await U(e),s=await n.first().evaluate(r=>{let o=r.ownerDocument?.defaultView;return o!==null&&o!==window.top}).catch(()=>false),d=N(t,s?k:[]),i,c=async()=>{let r=await v(n,t,d),o=t.treatIncompleteAsViolationIds??L,a=[...r.violations,...r.incomplete.filter(p=>o.includes(p.id))];return i={result:r,violations:a},a},l;try{if(t.timeout&&t.timeout>0){let r=expect.poll(c,{timeout:t.timeout});await(this.isNot?r.not.toHaveLength(0):r.toHaveLength(0));}else await c();}catch(r){l=r;}if(!i)throw new Error(`toBeAccessible: axe scan never completed.
|
|
13
|
+
${m(l)}`);if(i.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(i.result,null,2),contentType:"application/json"});let g=i.violations.map(r=>{let o=r.nodes.map(a=>Array.isArray(a.target)?a.target.join(" "):String(a.target)).join(`
|
|
14
|
+
`);return ` \u2022 [${r.id}] ${r.help}
|
|
15
|
+
${o}
|
|
16
|
+
${r.helpUrl??""}`}).join(`
|
|
17
|
+
`),u=i.violations.length;return {message:()=>`Found ${u} accessibility violation${u===1?"":"s"}:
|
|
18
|
+
${g}`,pass:false}},async toMatchClassTree(e,t,n={}){let{prefix:s=C,ignoreHashed:d=false}=n,i=await e.evaluate(T,{prefix:s,ignoreHashed:d});if(!i){let c=Array.isArray(s)?s.map(l=>`${l}*`).join(" / "):`${s}*`;return {message:()=>`No ${c} classes found in the DOM tree.`,pass:false}}try{let c=`${i}
|
|
19
|
+
`,l=test.info();if(l.config.ignoreSnapshots)return {message:()=>"Class tree snapshot check skipped.",pass:!0};let u=G(l.project.snapshotDir,l.titlePath,t,s,d),r=l.config.updateSnapshots;await mkdir(R.dirname(u),{recursive:!0});let o;try{o=await readFile(u,"utf8");}catch(a){if(a.code==="ENOENT"&&r!=="none")return await writeFile(u,c),{message:()=>"Class tree snapshot created.",pass:!0};throw a}if(o!==c){if(r==="all"||r==="changed")return await writeFile(u,c),{message:()=>"Class tree snapshot updated.",pass:!0};try{expect(c).toBe(o);}catch(a){return {message:()=>`Class tree snapshot mismatch at ${u}
|
|
20
|
+
|
|
21
|
+
${a.message}`,pass:!1}}}return {message:()=>"Class tree matched snapshot.",pass:!0}}catch(c){return {message:()=>m(c),pass:false}}}});export{L as DEFAULT_CRITICAL_INCOMPLETE_RULES,b as DEFAULT_DISABLED_RULES,A as DEFAULT_WCAG_TAGS,M as expect};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baseline-ui/test-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "A collection of test utilities for Baseline UI",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -50,8 +50,9 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"axe-core": "^4.11.0",
|
|
53
54
|
"react-frame-component": "^5.2.7",
|
|
54
|
-
"@baseline-ui/core": "0.
|
|
55
|
+
"@baseline-ui/core": "0.58.0"
|
|
55
56
|
},
|
|
56
57
|
"scripts": {
|
|
57
58
|
"build": "tsup",
|