aria-ease 7.2.0 → 7.3.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/README.md CHANGED
@@ -693,8 +693,6 @@ Aria-Ease includes a built-in testing framework for automated accessibility vali
693
693
  ```javascript
694
694
  import { describe, test, afterAll } from "vitest";
695
695
  import { testUiComponent, cleanupTests } from "aria-ease/test";
696
- import { render } from "@testing-library/react";
697
- import ShopifyUserMenu from "../src/components/menus/ShopifyUserMenu";
698
696
 
699
697
  afterAll(async () => {
700
698
  await cleanupTests();
@@ -703,17 +701,8 @@ afterAll(async () => {
703
701
  describe("Shopify User Menu Accessibility Test", () => {
704
702
  test("renders Shopify user menu without accessibility violation(s)", async () => {
705
703
  await testUiComponent(
706
- "menu",
707
- null,
708
- "http://localhost:5173/test-harness?component=menu",
709
- ); // For full component interaction test. Uses Playwright to test interaction and behaviors
710
- });
711
- });
712
-
713
- describe("Shopify User Menu Accessibility Test", () => {
714
- test("renders Shopify user menu without accessibility violation(s)", async () => {
715
- const { container } = render(<ShopifyUserMenu />);
716
- await testUiComponent("menu", container, null); // For fast limited static tests. Doesn't test for interaction and behaviors
704
+ "menu", "http://localhost:5173/test-harness?component=menu",
705
+ );
717
706
  });
718
707
  });
719
708
  ```
@@ -0,0 +1 @@
1
+ import{a as o}from"./chunk-SM6ZKEDR.js";import"./chunk-CNU4N4AY.js";var n=class{constructor(t,e,i=400,s=400){this.mainSelector=t;this.selectors=e;this.actionTimeoutMs=i;this.assertionTimeoutMs=s}async resetState(t){if(!this.selectors.panel||!this.selectors.trigger)return;let e=this.selectors.trigger,i=this.selectors.panel;if(!e||!i)return;let s=await t.locator(e).all();for(let r of s){let c=await r.getAttribute("aria-expanded")==="true",a=await r.getAttribute("aria-controls");if(c&&a){await r.click({timeout:this.actionTimeoutMs});let l=t.locator(`#${a}`);await(0,o.expect)(l).toBeHidden({timeout:this.assertionTimeoutMs}).catch(()=>{})}}}async shouldSkipTest(){return!1}getMainSelector(){return this.mainSelector}};export{n as AccordionComponentStrategy};
@@ -0,0 +1,13 @@
1
+ import"./chunk-CNU4N4AY.js";import g from"path";import v from"fs-extra";import{glob as q}from"fs/promises";import l from"chalk";function E(f){let e=[];if(!f||typeof f!="object")return{valid:!1,errors:[{path:"$",message:"Contract must be an object"}]};let t=f;if(!t.selectors)e.push({path:"$.selectors",message:"selectors is required"});else if(typeof t.selectors!="object"||t.selectors===null||Array.isArray(t.selectors))e.push({path:"$.selectors",message:"selectors must be an object"});else{let o=t.selectors;Object.entries(o).forEach(([s,n])=>{typeof n!="string"&&e.push({path:`$.selectors['${s}']`,message:"All selectors must be strings"})})}return Array.isArray(t.static)?t.static.forEach((o,s)=>{if(typeof o!="object"||o===null){e.push({path:`$.static[${s}]`,message:"static item must be an object"});return}let n=o;typeof n.target!="string"&&e.push({path:`$.static[${s}].target`,message:"target is required and must be a string"}),typeof n.attribute!="string"&&e.push({path:`$.static[${s}].attribute`,message:"attribute is required and must be a string"}),typeof n.failureMessage!="string"&&e.push({path:`$.static[${s}].failureMessage`,message:"failureMessage is required and must be a string"}),n.level!==void 0&&!["required","recommended","optional"].includes(n.level)&&e.push({path:`$.static[${s}].level`,message:"level must be one of: required, recommended, optional"})}):e.push({path:"$.static",message:"static must be an array"}),Array.isArray(t.dynamic)?t.dynamic.forEach((o,s)=>{if(typeof o!="object"||o===null){e.push({path:`$.dynamic[${s}]`,message:"dynamic item must be an object"});return}let n=o;typeof n.description!="string"&&e.push({path:`$.dynamic[${s}].description`,message:"description is required and must be a string"}),Array.isArray(n.action)?n.action.forEach((a,i)=>{if(typeof a!="object"||a===null){e.push({path:`$.dynamic[${s}].action[${i}]`,message:"action item must be an object"});return}let r=a;typeof r.type!="string"&&e.push({path:`$.dynamic[${s}].action[${i}].type`,message:"type is required and must be a string"}),typeof r.target!="string"&&e.push({path:`$.dynamic[${s}].action[${i}].target`,message:"target is required and must be a string"})}):e.push({path:`$.dynamic[${s}].action`,message:"action is required and must be an array"}),Array.isArray(n.assertions)?n.assertions.forEach((a,i)=>{if(typeof a!="object"||a===null){e.push({path:`$.dynamic[${s}].assertions[${i}]`,message:"assertion must be an object"});return}let r=a;typeof r.target!="string"&&e.push({path:`$.dynamic[${s}].assertions[${i}].target`,message:"target is required and must be a string"}),typeof r.assertion!="string"&&e.push({path:`$.dynamic[${s}].assertions[${i}].assertion`,message:"assertion is required and must be a string"}),r.level!==void 0&&!["required","recommended","optional"].includes(r.level)&&e.push({path:`$.dynamic[${s}].assertions[${i}].level`,message:"level must be one of: required, recommended, optional"})}):e.push({path:`$.dynamic[${s}].assertions`,message:"assertions is required and must be an array"})}):e.push({path:"$.dynamic",message:"dynamic must be an array"}),t.relationships!==void 0&&(Array.isArray(t.relationships)?t.relationships.forEach((o,s)=>{if(typeof o!="object"||o===null){e.push({path:`$.relationships[${s}]`,message:"relationship must be an object"});return}let n=o,a=n.type;["aria-reference","contains"].includes(a)||e.push({path:`$.relationships[${s}].type`,message:"type must be one of: aria-reference, contains"}),a==="aria-reference"?(typeof n.from!="string"&&e.push({path:`$.relationships[${s}].from`,message:"from is required for aria-reference and must be a string"}),typeof n.attribute!="string"&&e.push({path:`$.relationships[${s}].attribute`,message:"attribute is required for aria-reference and must be a string"}),typeof n.to!="string"&&e.push({path:`$.relationships[${s}].to`,message:"to is required for aria-reference and must be a string"})):a==="contains"&&(typeof n.parent!="string"&&e.push({path:`$.relationships[${s}].parent`,message:"parent is required for contains and must be a string"}),typeof n.child!="string"&&e.push({path:`$.relationships[${s}].child`,message:"child is required for contains and must be a string"}))}):e.push({path:"$.relationships",message:"relationships must be an array"})),{valid:e.length===0,errors:e}}function R(f,e){let t=[];if(!f||typeof f!="object")return t;let s=f.relationships;return Array.isArray(s)&&s.forEach((n,a)=>{let i=n.type;if(i==="aria-reference"){let r=n.from,c=n.to;r&&!e.has(r)&&t.push({path:`$.relationships[${a}].from`,message:`Selector '${r}' not found in selectors`}),c&&!e.has(c)&&t.push({path:`$.relationships[${a}].to`,message:`Selector '${c}' not found in selectors`})}else if(i==="contains"){let r=n.parent,c=n.child;r&&!e.has(r)&&t.push({path:`$.relationships[${a}].parent`,message:`Selector '${r}' not found in selectors`}),c&&!e.has(c)&&t.push({path:`$.relationships[${a}].child`,message:`Selector '${c}' not found in selectors`})}}),t}function k(f,e){let t=[];if(!f||typeof f!="object")return t;let o=f,s=o.static;Array.isArray(s)&&s.forEach((a,i)=>{let r=a.assertions;Array.isArray(r)&&r.forEach((c,h)=>{let p=c.target;p&&!e.has(p)&&t.push({path:`$.static[${i}].assertions[${h}].target`,message:`Selector '${p}' not found in selectors`})})});let n=o.dynamic;return Array.isArray(n)&&n.forEach((a,i)=>{let r=a.action;Array.isArray(r)&&r.forEach((h,p)=>{let u=h.target;u&&u!=="document"&&!e.has(u)&&t.push({path:`$.dynamic[${i}].action[${p}].target`,message:`Selector '${u}' not found in selectors (or use 'document')`})});let c=a.assertions;Array.isArray(c)&&c.forEach((h,p)=>{let u=h.target;u&&u!=="relative"&&!e.has(u)&&t.push({path:`$.dynamic[${i}].assertions[${p}].target`,message:`Selector '${u}' not found in selectors (or use 'relative')`})})}),t}async function F(f,e){let t=[],o=[];if(!e.contracts||e.contracts.length===0)return console.log(l.yellow('\u2139\uFE0F No contracts configured. Add "contracts" array to ariaease.config.js')),{success:!0,built:o,errors:t};try{console.log(l.cyanBright(`
2
+ \u{1F3D7}\uFE0F Building contracts...
3
+ `));for(let s of e.contracts){let n=g.resolve(f,s.src),a=s.out?g.resolve(f,s.out):void 0;console.log(l.gray(` Pattern: ${s.src}`)),console.log(a?l.gray(` Output: ${s.out}
4
+ `):l.gray(` Output: Same directory as source
5
+ `));let i=[];for await(let r of q(n,{cwd:f}))i.push(r);if(i.length===0){console.log(l.yellow(`\u26A0\uFE0F No contract files found matching pattern: ${s.src}`));continue}a&&await v.ensureDir(a);for(let r of i)try{let c=r.startsWith("/")?r:g.resolve(f,r),h=await import(`file://${c}`),p=h.default;if(!p){let d=Object.entries(h).find(([,m])=>m&&typeof m=="object"&&"toJSON"in m);d&&(p=d[1])}if(!p||typeof p.toJSON!="function"){t.push(`${g.basename(r)}: No contract with toJSON() method found`);continue}let u=p.toJSON(),A=E(u);if(!A.valid){let m=`Schema validation failed:
6
+ ${A.errors.map($=>` ${l.red("\u2717")} ${$.path}: ${$.message}`).join(`
7
+ `)}`;t.push(`${g.basename(r)}: ${m}`),console.log(l.red(`\u274C ${g.basename(r)}`)),console.log(l.red(` ${m}`));continue}let y=new Set;if(u&&typeof u=="object"&&"selectors"in u){let d=u.selectors;Object.keys(d).forEach(m=>y.add(m))}let j=[...R(u,y),...k(u,y)];if(j.length>0){let m=`Reference validation failed:
8
+ ${j.map($=>` ${l.red("\u2717")} ${$.path}: ${$.message}`).join(`
9
+ `)}`;t.push(`${g.basename(r)}: ${m}`),console.log(l.red(`\u274C ${g.basename(r)}`)),console.log(l.red(` ${m}`));continue}let w=g.basename(r,g.extname(r)),b=a?g.join(a,`${w}.json`):g.join(g.dirname(c),`${w}.json`);await v.writeFile(b,JSON.stringify(u,null,2)+`
10
+ `,"utf-8");let S=g.relative(f,b);o.push(S),console.log(l.green(`\u2705 ${g.basename(r)} \u2192 ${g.basename(b)}`))}catch(c){let h=c instanceof Error?c.message:String(c),p=g.basename(r);t.push(`${p}: ${h}`),console.log(l.red(`\u274C ${p}`)),console.log(l.red(` Error: ${h}`))}}return console.log(""),t.length===0?(console.log(l.green(`\u2705 Built ${o.length} contract${o.length!==1?"s":""} successfully
11
+ `)),{success:!0,built:o,errors:t}):(console.log(l.yellow(`\u26A0\uFE0F Built ${o.length} contracts with ${t.length} error${t.length!==1?"s":""}
12
+ `)),{success:!1,built:o,errors:t})}catch(s){let a=`Failed to build contracts: ${s instanceof Error?s.message:String(s)}`;return t.push(a),console.log(l.red(`\u274C ${a}
13
+ `)),{success:!1,built:o,errors:t}}}export{F as buildContracts};
package/dist/cli.cjs CHANGED
@@ -107,7 +107,7 @@
107
107
  1. Escape key
108
108
  2. Clicking trigger
109
109
  3. Clicking outside
110
- This indicates a problem with the menu component's close functionality.`);this.selectors.input&&await e.locator(this.selectors.input).first().clear(),this.selectors.main&&await e.locator(this.selectors.main).first().focus()}async shouldSkipTest(e,t){if(!(e.action.some(n=>n.target==="submenu"||n.target==="submenuTrigger"||n.target==="submenuItems")||e.assertions.some(n=>n.target==="submenu"||n.target==="submenuTrigger"||n.target==="submenuItems")))return!1;let s=this.selectors.submenuTrigger;return s?await t.locator(s).count()===0:!0}getMainSelector(){return this.mainSelector}}});var Mt={};X(Mt,{AccordionComponentStrategy:()=>rt});var rt,Pt=j(()=>{"use strict";Se();rt=class{constructor(e,t,r=400,s=400){this.mainSelector=e;this.selectors=t;this.actionTimeoutMs=r;this.assertionTimeoutMs=s}async resetState(e){if(!this.selectors.panel||!this.selectors.trigger||this.selectors.popup)return;let t=this.selectors.trigger,r=this.selectors.panel;if(!t||!r)return;let s=await e.locator(t).all();for(let i of s){let n=await i.getAttribute("aria-expanded")==="true",a=await i.getAttribute("aria-controls");if(n&&a){await i.click({timeout:this.actionTimeoutMs});let l=e.locator(`#${a}`);await(0,F.expect)(l).toBeHidden({timeout:this.assertionTimeoutMs}).catch(()=>{})}}}async shouldSkipTest(){return!1}getMainSelector(){return this.mainSelector}}});var Bt={};X(Bt,{ComboboxComponentStrategy:()=>it});var it,Lt=j(()=>{"use strict";Se();it=class{constructor(e,t,r=400,s=400){this.mainSelector=e;this.selectors=t;this.actionTimeoutMs=r;this.assertionTimeoutMs=s}async resetState(e){if(!this.selectors.popup)return;let t=this.selectors.popup,r=e.locator(t).first();if(!await r.isVisible().catch(()=>!1))return;let i=!1,n=this.selectors.main;if(n&&(await e.locator(n).first().focus(),await e.keyboard.press("Escape"),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),!i&&this.selectors.button&&(await e.locator(this.selectors.button).first().click({timeout:this.actionTimeoutMs}),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),i||(await e.mouse.click(10,10),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),!i)throw new Error(`\u274C FATAL: Cannot close combobox popup between tests. Popup remains visible after trying:
110
+ This indicates a problem with the menu component's close functionality.`);this.selectors.input&&await e.locator(this.selectors.input).first().clear(),this.selectors.main&&await e.locator(this.selectors.main).first().focus()}async shouldSkipTest(e,t){if(!(e.action.some(n=>n.target==="submenu"||n.target==="submenuTrigger"||n.target==="submenuItems")||e.assertions.some(n=>n.target==="submenu"||n.target==="submenuTrigger"||n.target==="submenuItems")))return!1;let s=this.selectors.submenuTrigger;return s?await t.locator(s).count()===0:!0}getMainSelector(){return this.mainSelector}}});var Mt={};X(Mt,{AccordionComponentStrategy:()=>rt});var rt,Pt=j(()=>{"use strict";Se();rt=class{constructor(e,t,r=400,s=400){this.mainSelector=e;this.selectors=t;this.actionTimeoutMs=r;this.assertionTimeoutMs=s}async resetState(e){if(!this.selectors.panel||!this.selectors.trigger)return;let t=this.selectors.trigger,r=this.selectors.panel;if(!t||!r)return;let s=await e.locator(t).all();for(let i of s){let n=await i.getAttribute("aria-expanded")==="true",a=await i.getAttribute("aria-controls");if(n&&a){await i.click({timeout:this.actionTimeoutMs});let l=e.locator(`#${a}`);await(0,F.expect)(l).toBeHidden({timeout:this.assertionTimeoutMs}).catch(()=>{})}}}async shouldSkipTest(){return!1}getMainSelector(){return this.mainSelector}}});var Bt={};X(Bt,{ComboboxComponentStrategy:()=>it});var it,Lt=j(()=>{"use strict";Se();it=class{constructor(e,t,r=400,s=400){this.mainSelector=e;this.selectors=t;this.actionTimeoutMs=r;this.assertionTimeoutMs=s}async resetState(e){if(!this.selectors.popup)return;let t=this.selectors.popup,r=e.locator(t).first();if(!await r.isVisible().catch(()=>!1))return;let i=!1,n=this.selectors.main;if(n&&(await e.locator(n).first().focus(),await e.keyboard.press("Escape"),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),!i&&this.selectors.button&&(await e.locator(this.selectors.button).first().click({timeout:this.actionTimeoutMs}),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),i||(await e.mouse.click(10,10),i=await(0,F.expect)(r).toBeHidden({timeout:this.assertionTimeoutMs}).then(()=>!0).catch(()=>!1)),!i)throw new Error(`\u274C FATAL: Cannot close combobox popup between tests. Popup remains visible after trying:
111
111
  1. Escape key
112
112
  2. Clicking button
113
113
  3. Clicking outside
@@ -132,13 +132,13 @@ ${"\u2550".repeat(60)}`),this.log(`\u{1F4CA} Summary
132
132
  `),a>0?(this.log("\u{1F527} Next Steps:"),this.log(" 1. Review the failures above"),this.log(" 2. Fix ARIA attributes and keyboard handlers"),this.log(` 3. Re-run tests to verify fixes
133
133
  `)):!this.isPlaywright&&this.skipped>0&&this.log(`\u2728 Optional: Run Playwright tests for complete validation
134
134
  `),{passes:n,failures:a,skipped:this.skipped,duration:t}}error(e,t){this.log(`
135
- \u274C Error: ${e}`),t&&this.log(` Context: ${t}`),this.log("")}}});var qt={};X(qt,{RelativeTargetResolver:()=>se});var se,je=j(()=>{"use strict";se=class{static async resolve(e,t,r){let s=await e.locator(t).all();if(typeof r=="number")return s[r-1];switch(r){case"first":return s[0];case"second":return s[1];case"last":return s[s.length-1];case"next":{let n=(await e.evaluate(([a])=>Array.from(document.querySelectorAll(a)).indexOf(document.activeElement),[t])+1)%s.length;return s[n]}case"previous":{let n=(await e.evaluate(([a])=>Array.from(document.querySelectorAll(a)).indexOf(document.activeElement),[t])-1+s.length)%s.length;return s[n]}default:return null}}}});var we,Ot=j(()=>{"use strict";je();we=class{constructor(e,t,r=400){this.page=e;this.selectors=t;this.timeoutMs=r}isBrowserClosedError(e){return e instanceof Error&&e.message.includes("Target page, context or browser has been closed")}async focus(e,t,r){try{if(e==="virtual"&&r){let i=this.selectors.main;if(!i)return{success:!1,error:"Main selector not defined for virtual focus."};let n=this.page.locator(i).first();return await n.count()?(await n.evaluate((l,u)=>{l.setAttribute("aria-activedescendant",u)},r),{success:!0}):{success:!1,error:"Main element not found for virtual focus."}}if(e==="relative"&&t){let i=this.selectors.relative;if(!i)return{success:!1,error:"Relative selector not defined for focus action."};let n=await se.resolve(this.page,i,t);return n?(await n.focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for focus.`}}let s=this.selectors[e];return s?(await this.page.locator(s).first().focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for focus target ${e} not found.`}}catch(s){return this.isBrowserClosedError(s)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to focus ${e}: ${s instanceof Error?s.message:String(s)}`}}}async type(e,t){try{let r=this.selectors[e];return r?(await this.page.locator(r).first().fill(t,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for type target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to type into ${e}: ${r instanceof Error?r.message:String(r)}`}}}async click(e,t){try{if(e==="document")return await this.page.mouse.click(10,10),{success:!0};if(e==="relative"&&t){let s=this.selectors.relative;if(!s)return{success:!1,error:"Relative selector not defined for click action."};let i=await se.resolve(this.page,s,t);return i?(await i.click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for click.`}}let r=this.selectors[e];return r?(await this.page.locator(r).first().click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for action target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to click ${e}: ${r instanceof Error?r.message:String(r)}`}}}async keypress(e,t,r){try{let i={Space:"Space",Enter:"Enter",Escape:"Escape","Arrow Up":"ArrowUp","Arrow Down":"ArrowDown","Arrow Left":"ArrowLeft","Arrow Right":"ArrowRight",Home:"Home",End:"End",Tab:"Tab"}[t]||t;if(i==="Space"?i=" ":i.includes(" ")&&(i=i.replace(/ /g,"")),e==="relative"){if(r==null)return{success:!1,error:"relativeTarget must be provided for relative keypress."};let u=this.selectors.relative;if(!u)return{success:!1,error:"Relative selector not defined for keypress action."};let f=await se.resolve(this.page,u,r);return f?(await f.press(i,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${r} for keypress.`}}let n=this.selectors[e];if(!n)return{success:!1,error:`Selector for keypress target ${e} not found.`};let a=this.page.locator(n).first();return await a.count()===0?{success:!1,error:`${e} element not found.`,shouldBreak:!0}:(await a.press(i,{timeout:this.timeoutMs}),{success:!0})}catch(s){return this.isBrowserClosedError(s)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to press ${t} on ${e}: ${s instanceof Error?s.message:String(s)}`}}}async hover(e,t){try{if(e==="relative"&&t){let s=this.selectors.relative;if(!s)return{success:!1,error:"Relative selector not defined for hover action."};let i=await se.resolve(this.page,s,t);return i?(await i.hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for hover.`}}let r=this.selectors[e];return r?(await this.page.locator(r).first().hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for hover target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to hover ${e}: ${r instanceof Error?r.message:String(r)}`}}}}});var Te,Ht=j(()=>{"use strict";Se();je();Te=class{constructor(e,t,r=400){this.page=e;this.selectors=t;this.timeoutMs=r}async resolveTarget(e,t,r){try{if(e==="relative"){let i=r?this.selectors[r]:this.selectors.relative;if(!i)return{target:null,error:"Relative selector is not defined in the contract."};if(!t)return{target:null,error:"Relative target or expected value is not defined."};let n=await se.resolve(this.page,i,t);return n?{target:n}:{target:null,error:`Target ${e} not found.`}}let s=this.selectors[e];return s?{target:this.page.locator(s).first()}:{target:null,error:`Selector for assertion target ${e} not found.`}}catch(s){return{target:null,error:`Failed to resolve target ${e}: ${s instanceof Error?s.message:String(s)}`}}}async validateVisibility(e,t,r,s,i){try{return r?(await(0,F.expect)(e).toBeVisible({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} is visible as expected. Test: "${i}".`}):(await(0,F.expect)(e).toBeHidden({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} is not visible as expected. Test: "${i}".`})}catch{let n=this.selectors[t]||"",a=await this.page.evaluate(l=>{let u=l?document.querySelector(l):null;if(!u)return"element not found";let f=window.getComputedStyle(u);return`display:${f.display}, visibility:${f.visibility}, opacity:${f.opacity}`},n);return r?{success:!1,failMessage:`${s} (actual: ${a})`}:{success:!1,failMessage:`${s} ${t} is still visible (actual: ${a}).`}}}async validateAttribute(e,t,r,s,i,n){if(s==="!empty"){let u=await e.getAttribute(r);return u&&u.trim()!==""?{success:!0,passMessage:`${t} has non-empty "${r}". Test: "${n}".`}:{success:!1,failMessage:`${i} ${t} "${r}" should not be empty, found "${u}".`}}if(typeof s!="string")throw console.error("[AssertionRunner] expectedValue is not a string:",s),new Error(`AssertionRunner: expectedValue for attribute assertion must be a string, but got: ${JSON.stringify(s)}`);let a=s.split(" | ").map(u=>u.trim()),l=await e.getAttribute(r);return l!==null&&a.includes(l)?{success:!0,passMessage:`${t} has expected "${r}". Test: "${n}".`}:{success:!1,failMessage:`${i} ${t} "${r}" should be "${s}", found "${l}".`}}async validateValue(e,t,r,s,i){let n=await e.inputValue().catch(()=>"");return r==="!empty"?n&&n.trim()!==""?{success:!0,passMessage:`${t} has non-empty value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should not be empty, found "${n}".`}:r===""?n===""?{success:!0,passMessage:`${t} has empty value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should be empty, found "${n}".`}:n===r?{success:!0,passMessage:`${t} has expected value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should be "${r}", found "${n}".`}}async validateFocus(e,t,r,s,i){try{return r?(await(0,F.expect)(e).toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} has focus as expected. Test: "${i}".`}):(await(0,F.expect)(e).not.toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} does not have focus as expected. Test: "${i}".`})}catch{let n=await this.page.evaluate(()=>{let a=document.activeElement;return a?`${a.tagName}#${a.id||"no-id"}.${a.className||"no-class"}`:"no element focused"});return{success:!1,failMessage:`${s} (actual focus: ${n})`}}}async validateRole(e,t,r,s,i){let n=await e.getAttribute("role");return n===r?{success:!0,passMessage:`${t} has role "${r}". Test: "${i}".`}:{success:!1,failMessage:`${s} Expected role "${r}", found "${n}".`}}async validate(e,t){if(this.page.isClosed())return{success:!1,failMessage:"CRITICAL: Browser/page closed before completing all tests. Increase test timeout or reduce test complexity."};let r=null,s;if(e.controlledBy){let i=e.controlledBy,n=this.selectors[i.target];if(!n)return{success:!1,failMessage:`Selector for controlledBy.target '${i.target}' not found.`,target:null};let a=null;if(i.relativeTarget?a=await se.resolve(this.page,n,i.relativeTarget):a=this.page.locator(n).first(),!a)return{success:!1,failMessage:"Controlling element for controlledBy not found.",target:null};let l=i.attribute||"aria-controls",u=await a.getAttribute(l);if(!u)return{success:!1,failMessage:`Controlling element does not have attribute '${l}'.`,target:null};if(r=this.page.locator(`#${u}`),!r||await r.count()===0)return{success:!1,failMessage:`Controlled element with id '${u}' not found.`,target:null}}else{let i=await this.resolveTarget(e.target,e.relativeTarget||e.expectedValue,e.selectorKey);if(r=i.target,s=i.error,s||!r)return{success:!1,failMessage:s||`Target ${e.target} not found.`,target:null}}if(e.target==="input"&&e.attribute==="aria-activedescendant"&&e.expectedValue==="!empty"&&e.relativeTarget&&e.selectorKey){let i=await se.resolve(this.page,this.selectors[e.selectorKey],e.relativeTarget),n=i?await i.getAttribute("id"):null,a=await r.getAttribute("aria-activedescendant");return n&&a===n?{success:!0,passMessage:`input[aria-activedescendant] matches id of ${e.relativeTarget}(${e.selectorKey}). Test: "${t}".`}:{success:!1,failMessage:`input[aria-activedescendant] should match id of ${e.relativeTarget}(${e.selectorKey}), found "${a}".`}}switch(e.assertion){case"toBeVisible":return this.validateVisibility(r,e.target,!0,e.failureMessage||"",t);case"notToBeVisible":return this.validateVisibility(r,e.target,!1,e.failureMessage||"",t);case"toHaveAttribute":return e.attribute&&e.expectedValue!==void 0?this.validateAttribute(r,e.target,e.attribute,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing attribute or expectedValue for toHaveAttribute assertion"};case"toHaveValue":return e.expectedValue!==void 0?this.validateValue(r,e.target,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing expectedValue for toHaveValue assertion"};case"toHaveFocus":return this.validateFocus(r,e.target,!0,e.failureMessage||"",t);case"notToHaveFocus":return this.validateFocus(r,e.target,!1,e.failureMessage||"",t);case"toHaveRole":return e.expectedValue!==void 0?this.validateRole(r,e.target,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing expectedValue for toHaveRole assertion"};default:return{success:!1,failMessage:`Unknown assertion type: ${e.assertion}`}}}}});var Nt={};X(Nt,{runContractTestsPlaywright:()=>Ts});async function Ts(c,e,t,r,s){let i=r?.test?.components?.find(S=>S.name===c),n=!!i?.contractPath,a=new Le(!0,n),l={actionTimeoutMs:400,assertionTimeoutMs:400,navigationTimeoutMs:3e4,componentReadyTimeoutMs:5e3},u=r?.test?.disableTimeouts===!0,h=i?.disableTimeouts===!0||u,y=(S,ie,oe)=>{if(h)return 0;let ee=S??ie;return typeof ee!="number"||!Number.isFinite(ee)||ee<0?oe:ee},L=y(i?.actionTimeoutMs,r?.test?.actionTimeoutMs,l.actionTimeoutMs),H=y(i?.assertionTimeoutMs,r?.test?.assertionTimeoutMs,l.assertionTimeoutMs),M=y(i?.navigationTimeoutMs,r?.test?.navigationTimeoutMs,l.navigationTimeoutMs),U=y(i?.componentReadyTimeoutMs,r?.test?.componentReadyTimeoutMs,l.componentReadyTimeoutMs),W=$e(t),J=i?.contractPath;if(!J)throw new Error(`Contract path not found for component: ${c}`);let G=(()=>{if(Fe.default.isAbsolute(J))return J;if(s){let ie=Fe.default.resolve(s,J);try{return(0,Ie.readFileSync)(ie,"utf-8"),ie}catch{}}let S=Fe.default.resolve(process.cwd(),J);try{return(0,Ie.readFileSync)(S,"utf-8"),S}catch{return new URL(J,Cs.url).pathname}})(),Y=(0,Ie.readFileSync)(G,"utf-8"),v=JSON.parse(Y),Ce=(v.relationships?.length||0)+(v.static[0]?.assertions.length||0)+v.dynamic.length,Ue=v.meta?.source?.apg,Z=[],ae=[],ce=[],N=[],A=null,q=(S,ie)=>{let oe=fe(ie),ee=At(oe,W);if(ee==="error")return Z.push(S),{status:"fail",level:oe,detail:S};if(ee==="warning")return ae.push(S),{status:"warn",level:oe,detail:S};let ne=`${S} (ignored by strictness=${W}, level=${oe})`;return N.push(ne),{status:"skip",level:oe,detail:ne}};try{if(A=await Ct(),e){try{await A.goto(e,{waitUntil:"domcontentloaded",timeout:M})}catch(o){throw new Error(`Failed to navigate to ${e}. Ensure dev server is running and accessible. Original error: ${o instanceof Error?o.message:String(o)}`)}await A.addStyleTag({content:"* { transition: none !important; animation: none !important; }"})}let S=await Be.detect(c,i,L,H,s);if(!S)throw new Error(`Unsupported component: ${c}`);let ie=S.getMainSelector();if(!ie)throw new Error(`CRITICAL: No selector found in contract for ${c}`);try{await A.locator(ie).first().waitFor({state:"attached",timeout:U})}catch(o){throw new Error(`
135
+ \u274C Error: ${e}`),t&&this.log(` Context: ${t}`),this.log("")}}});var qt={};X(qt,{RelativeTargetResolver:()=>se});var se,je=j(()=>{"use strict";se=class{static async resolve(e,t,r){let s=await e.locator(t).all();if(typeof r=="number")return s[r-1];switch(r){case"first":return s[0];case"second":return s[1];case"last":return s[s.length-1];case"next":{let n=(await e.evaluate(([a])=>Array.from(document.querySelectorAll(a)).indexOf(document.activeElement),[t])+1)%s.length;return s[n]}case"previous":{let n=(await e.evaluate(([a])=>Array.from(document.querySelectorAll(a)).indexOf(document.activeElement),[t])-1+s.length)%s.length;return s[n]}default:return null}}}});var we,Ot=j(()=>{"use strict";je();we=class{constructor(e,t,r=400){this.page=e;this.selectors=t;this.timeoutMs=r}isBrowserClosedError(e){return e instanceof Error&&e.message.includes("Target page, context or browser has been closed")}async focus(e,t,r){try{if(e==="virtual"&&r){let i=this.selectors.main;if(!i)return{success:!1,error:"Main selector not defined for virtual focus."};let n=this.page.locator(i).first();return await n.count()?(await n.evaluate((l,u)=>{l.setAttribute("aria-activedescendant",u)},r),{success:!0}):{success:!1,error:"Main element not found for virtual focus."}}if(e==="relative"&&t){let i=this.selectors.relative;if(!i)return{success:!1,error:"Relative selector not defined for focus action."};let n=await se.resolve(this.page,i,t);return n?(await n.focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for focus.`}}let s=this.selectors[e];return s?(await this.page.locator(s).first().focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for focus target ${e} not found.`}}catch(s){return this.isBrowserClosedError(s)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to focus ${e}: ${s instanceof Error?s.message:String(s)}`}}}async type(e,t){try{let r=this.selectors[e];return r?(await this.page.locator(r).first().fill(t,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for type target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to type into ${e}: ${r instanceof Error?r.message:String(r)}`}}}async click(e,t){try{if(e==="document")return await this.page.mouse.click(10,10),{success:!0};if(e==="relative"&&t){let s=this.selectors.relative;if(!s)return{success:!1,error:"Relative selector not defined for click action."};let i=await se.resolve(this.page,s,t);return i?(await i.click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for click.`}}let r=this.selectors[e];return r?(await this.page.locator(r).first().click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for action target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to click ${e}: ${r instanceof Error?r.message:String(r)}`}}}async keypress(e,t,r){try{let i={Space:"Space",Enter:"Enter",Escape:"Escape","Arrow Up":"ArrowUp","Arrow Down":"ArrowDown","Arrow Left":"ArrowLeft","Arrow Right":"ArrowRight",Home:"Home",End:"End",Tab:"Tab"}[t]||t;if(i==="Space"?i=" ":i.includes(" ")&&(i=i.replace(/ /g,"")),e==="relative"){if(r==null)return{success:!1,error:"relativeTarget must be provided for relative keypress."};let u=this.selectors.relative;if(!u)return{success:!1,error:"Relative selector not defined for keypress action."};let f=await se.resolve(this.page,u,r);return f?(await f.press(i,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${r} for keypress.`}}let n=this.selectors[e];if(!n)return{success:!1,error:`Selector for keypress target ${e} not found.`};let a=this.page.locator(n).first();return await a.count()===0?{success:!1,error:`${e} element not found.`,shouldBreak:!0}:(await a.press(i,{timeout:this.timeoutMs}),{success:!0})}catch(s){return this.isBrowserClosedError(s)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to press ${t} on ${e}: ${s instanceof Error?s.message:String(s)}`}}}async hover(e,t){try{if(e==="relative"&&t){let s=this.selectors.relative;if(!s)return{success:!1,error:"Relative selector not defined for hover action."};let i=await se.resolve(this.page,s,t);return i?(await i.hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${t} for hover.`}}let r=this.selectors[e];return r?(await this.page.locator(r).first().hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for hover target ${e} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to hover ${e}: ${r instanceof Error?r.message:String(r)}`}}}}});var Te,Ht=j(()=>{"use strict";Se();je();Te=class{constructor(e,t,r=400){this.page=e;this.selectors=t;this.timeoutMs=r}async resolveTarget(e,t,r){try{if(e==="relative"){let i=r?this.selectors[r]:this.selectors.relative;if(!i)return{target:null,error:"Relative selector is not defined in the contract."};if(!t)return{target:null,error:"Relative target or expected value is not defined."};let n=await se.resolve(this.page,i,t);return n?{target:n}:{target:null,error:`Target ${e} not found.`}}let s=this.selectors[e];return s?{target:this.page.locator(s).first()}:{target:null,error:`Selector for assertion target ${e} not found.`}}catch(s){return{target:null,error:`Failed to resolve target ${e}: ${s instanceof Error?s.message:String(s)}`}}}async validateVisibility(e,t,r,s,i){try{return r?(await(0,F.expect)(e).toBeVisible({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} is visible as expected. Test: "${i}".`}):(await(0,F.expect)(e).toBeHidden({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} is not visible as expected. Test: "${i}".`})}catch{let n=this.selectors[t]||"",a=await this.page.evaluate(l=>{let u=l?document.querySelector(l):null;if(!u)return"element not found";let f=window.getComputedStyle(u);return`display:${f.display}, visibility:${f.visibility}, opacity:${f.opacity}`},n);return r?{success:!1,failMessage:`${s} (actual: ${a})`}:{success:!1,failMessage:`${s} ${t} is still visible (actual: ${a}).`}}}async validateAttribute(e,t,r,s,i,n){if(s==="!empty"){let u=await e.getAttribute(r);return u&&u.trim()!==""?{success:!0,passMessage:`${t} has non-empty "${r}". Test: "${n}".`}:{success:!1,failMessage:`${i} ${t} "${r}" should not be empty, found "${u}".`}}if(typeof s!="string")throw console.error("[AssertionRunner] expectedValue is not a string:",s),new Error(`AssertionRunner: expectedValue for attribute assertion must be a string, but got: ${JSON.stringify(s)}`);let a=s.split(" | ").map(u=>u.trim()),l=await e.getAttribute(r);return l!==null&&a.includes(l)?{success:!0,passMessage:`${t} has expected "${r}". Test: "${n}".`}:{success:!1,failMessage:`${i} ${t} "${r}" should be "${s}", found "${l}".`}}async validateValue(e,t,r,s,i){let n=await e.inputValue().catch(()=>"");return r==="!empty"?n&&n.trim()!==""?{success:!0,passMessage:`${t} has non-empty value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should not be empty, found "${n}".`}:r===""?n===""?{success:!0,passMessage:`${t} has empty value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should be empty, found "${n}".`}:n===r?{success:!0,passMessage:`${t} has expected value. Test: "${i}".`}:{success:!1,failMessage:`${s} ${t} value should be "${r}", found "${n}".`}}async validateFocus(e,t,r,s,i){try{return r?(await(0,F.expect)(e).toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} has focus as expected. Test: "${i}".`}):(await(0,F.expect)(e).not.toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${t} does not have focus as expected. Test: "${i}".`})}catch{let n=await this.page.evaluate(()=>{let a=document.activeElement;return a?`${a.tagName}#${a.id||"no-id"}.${a.className||"no-class"}`:"no element focused"});return{success:!1,failMessage:`${s} (actual focus: ${n})`}}}async validateRole(e,t,r,s,i){let n=await e.getAttribute("role");return n===r?{success:!0,passMessage:`${t} has role "${r}". Test: "${i}".`}:{success:!1,failMessage:`${s} Expected role "${r}", found "${n}".`}}async validate(e,t){if(this.page.isClosed())return{success:!1,failMessage:"CRITICAL: Browser/page closed before completing all tests. Increase test timeout or reduce test complexity."};let r=null,s;if(e.controlledBy){let i=e.controlledBy,n=this.selectors[i.target];if(!n)return{success:!1,failMessage:`Selector for controlledBy.target '${i.target}' not found.`,target:null};let a=null;if(i.relativeTarget?a=await se.resolve(this.page,n,i.relativeTarget):a=this.page.locator(n).first(),!a)return{success:!1,failMessage:"Controlling element for controlledBy not found.",target:null};let l=i.attribute||"aria-controls",u=await a.getAttribute(l);if(!u)return{success:!1,failMessage:`Controlling element does not have attribute '${l}'.`,target:null};if(r=this.page.locator(`#${u}`),!r||await r.count()===0)return{success:!1,failMessage:`Controlled element with id '${u}' not found.`,target:null}}else{let i=await this.resolveTarget(e.target,e.relativeTarget||e.expectedValue,e.selectorKey);if(r=i.target,s=i.error,s||!r)return{success:!1,failMessage:s||`Target ${e.target} not found.`,target:null}}if(e.target==="input"&&e.attribute==="aria-activedescendant"&&e.expectedValue==="!empty"&&e.relativeTarget&&e.selectorKey){let i=await se.resolve(this.page,this.selectors[e.selectorKey],e.relativeTarget),n=i?await i.getAttribute("id"):null,a=await r.getAttribute("aria-activedescendant");return n&&a===n?{success:!0,passMessage:`input[aria-activedescendant] matches id of ${e.relativeTarget}(${e.selectorKey}). Test: "${t}".`}:{success:!1,failMessage:`input[aria-activedescendant] should match id of ${e.relativeTarget}(${e.selectorKey}), found "${a}".`}}switch(e.assertion){case"toBeVisible":return this.validateVisibility(r,e.target,!0,e.failureMessage||"",t);case"notToBeVisible":return this.validateVisibility(r,e.target,!1,e.failureMessage||"",t);case"toHaveAttribute":return e.attribute&&e.expectedValue!==void 0?this.validateAttribute(r,e.target,e.attribute,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing attribute or expectedValue for toHaveAttribute assertion"};case"toHaveValue":return e.expectedValue!==void 0?this.validateValue(r,e.target,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing expectedValue for toHaveValue assertion"};case"toHaveFocus":return this.validateFocus(r,e.target,!0,e.failureMessage||"",t);case"notToHaveFocus":return this.validateFocus(r,e.target,!1,e.failureMessage||"",t);case"toHaveRole":return e.expectedValue!==void 0?this.validateRole(r,e.target,e.expectedValue,e.failureMessage||"",t):{success:!1,failMessage:"Missing expectedValue for toHaveRole assertion"};default:return{success:!1,failMessage:`Unknown assertion type: ${e.assertion}`}}}}});var Nt={};X(Nt,{runContractTestsPlaywright:()=>Ts});async function Ts(c,e,t,r,s){let i=r?.test?.components?.find(S=>S.name===c),n=!!i?.contractPath,a=new Le(!0,n),l={actionTimeoutMs:400,assertionTimeoutMs:400,navigationTimeoutMs:3e4,componentReadyTimeoutMs:5e3},u=r?.test?.disableTimeouts===!0,h=i?.disableTimeouts===!0||u,y=(S,ie,oe)=>{if(h)return 0;let ee=S??ie;return typeof ee!="number"||!Number.isFinite(ee)||ee<0?oe:ee},L=y(i?.actionTimeoutMs,r?.test?.actionTimeoutMs,l.actionTimeoutMs),H=y(i?.assertionTimeoutMs,r?.test?.assertionTimeoutMs,l.assertionTimeoutMs),M=y(i?.navigationTimeoutMs,r?.test?.navigationTimeoutMs,l.navigationTimeoutMs),U=y(i?.componentReadyTimeoutMs,r?.test?.componentReadyTimeoutMs,l.componentReadyTimeoutMs),W=$e(t),J=i?.contractPath;if(!J)throw new Error(`Contract path not found for component: ${c}`);let G=(()=>{if(Fe.default.isAbsolute(J))return J;if(s){let ie=Fe.default.resolve(s,J);try{return(0,Ie.readFileSync)(ie,"utf-8"),ie}catch{}}let S=Fe.default.resolve(process.cwd(),J);try{return(0,Ie.readFileSync)(S,"utf-8"),S}catch{return new URL(J,Cs.url).pathname}})(),Y=(0,Ie.readFileSync)(G,"utf-8"),v=JSON.parse(Y),Ce=(v.relationships?.length||0)+(v.static.length||0)+v.dynamic.length,Ue=v.meta?.source?.apg,Z=[],ae=[],ce=[],N=[],A=null,q=(S,ie)=>{let oe=fe(ie),ee=At(oe,W);if(ee==="error")return Z.push(S),{status:"fail",level:oe,detail:S};if(ee==="warning")return ae.push(S),{status:"warn",level:oe,detail:S};let ne=`${S} (ignored by strictness=${W}, level=${oe})`;return N.push(ne),{status:"skip",level:oe,detail:ne}};try{if(A=await Ct(),e){try{await A.goto(e,{waitUntil:"domcontentloaded",timeout:M})}catch(o){throw new Error(`Failed to navigate to ${e}. Ensure dev server is running and accessible. Original error: ${o instanceof Error?o.message:String(o)}`)}await A.addStyleTag({content:"* { transition: none !important; animation: none !important; }"})}let S=await Be.detect(c,i,L,H,s);if(!S)throw new Error(`Unsupported component: ${c}`);let ie=S.getMainSelector();if(!ie)throw new Error(`CRITICAL: No selector found in contract for ${c}`);try{await A.locator(ie).first().waitFor({state:"attached",timeout:U})}catch(o){throw new Error(`
136
136
  \u274C CRITICAL: Component not found on page!
137
137
  This usually means:
138
138
  - The component didn't render
139
139
  - The URL is incorrect
140
140
  - The component selector '${ie}' in the contract is wrong
141
- - Original error: ${o}`)}a.start(c,Ce,Ue),c==="menu"&&v.selectors.main&&await A.locator(v.selectors.main).first().waitFor({state:"visible",timeout:U}).catch(()=>{});let oe=c==="menu"&&v.selectors.submenuTrigger?await A.locator(v.selectors.submenuTrigger).count()>0:!1,ee=o=>o.type==="aria-reference"&&[o.from,o.to].some(m=>["submenu","submenuTrigger","submenuItems"].includes(m||""))||o.type==="contains"&&[o.parent,o.child].some(m=>["submenu","submenuTrigger","submenuItems"].includes(m||"")),ne=0,_=0,z=0;for(let o of v.relationships||[]){if(S&&typeof S.resetState=="function")try{await S.resetState(A)}catch(w){ae.push(`Warning: resetState failed before relationship test: ${w instanceof Error?w.message:String(w)}`)}let m=fe(o.level);if(Array.isArray(o.setup)&&o.setup.length>0){let R=function(g){return T.includes(g)};var pt=R;let w=new we(A,v.selectors,L),P=o.type==="aria-reference"?`${o.from}.${o.attribute} references ${o.to}`:`${o.parent} contains ${o.child}`,T=["focus","type","click","keypress","hover"],C=g=>({...g,type:R(g.type)?g.type:"click"}),E=o.setup.map(C),B=await De(E,w,S,A,P,["submenu","submenuTrigger","submenuItems"]);if(B.skip){N.push(B.message||"Setup action skipped"),a.reportStaticTest(P,"skip",B.message,m);continue}if(!B.success){let g=`Relationship setup failed: ${B.error}`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(P,d.status,d.detail,d.level);continue}}if(c==="menu"&&!oe&&ee(o)){let P=o.type==="aria-reference"?`${o.from}.${o.attribute} references ${o.to}`:`${o.parent} contains ${o.child}`,T="Skipping submenu relationship assertion: no submenu capability detected in rendered component.";N.push(T),a.reportStaticTest(P,"skip",T,m);continue}if(o.type==="aria-reference"){let w=`${o.from}.${o.attribute} references ${o.to}`,P=v.selectors[o.from],T=v.selectors[o.to];if(!P||!T){let b=q(`Relationship selector missing: from="${o.from}" or to="${o.to}" not found in selectors.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}let R=A.locator(P).first(),C=A.locator(T).first(),E=await R.count()>0,B=await C.count()>0;if(!E||!B){if(c==="menu"&&ee(o)){let K="Skipping submenu relationship assertion in static phase: submenu elements are not present until submenu is opened.";N.push(K),a.reportStaticTest(w,"skip",K,m);continue}let b=q(`Relationship target not found: ${E?o.to:o.from}.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}let g=await R.getAttribute(o.attribute),d=await C.getAttribute("id");if(!d){let b=q(`Relationship target "${o.to}" must have an id for ${o.attribute} validation.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}if(!(g||"").split(/\s+/).filter(Boolean).includes(d)){let b=q(`Expected ${o.from} ${o.attribute} to reference id "${d}", found "${g||""}".`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}ce.push(`Relationship valid: ${o.from}.${o.attribute} -> ${o.to} (id=${d}).`),ne+=1,a.reportStaticTest(w,"pass",void 0,m);continue}if(o.type==="contains"){let w=`${o.parent} contains ${o.child}`,P=v.selectors[o.parent],T=v.selectors[o.child];if(!P||!T){let g=q(`Relationship selector missing: parent="${o.parent}" or child="${o.child}" not found in selectors.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}let R=A.locator(P).first();if(!(await R.count()>0)){if(c==="menu"&&ee(o)){let d="Skipping submenu relationship assertion in static phase: submenu container is not present until submenu is opened.";N.push(d),a.reportStaticTest(w,"skip",d,m);continue}let g=q(`Relationship parent target not found: ${o.parent}.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}if(await R.locator(T).count()<1){if(c==="menu"&&ee(o)){let d="Skipping submenu relationship assertion in static phase: submenu descendants are not present until submenu is opened.";N.push(d),a.reportStaticTest(w,"skip",d,m);continue}let g=q(`Expected ${o.parent} to contain descendant matching selector for ${o.child}.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}ce.push(`Relationship valid: ${o.parent} contains ${o.child}.`),ne+=1,a.reportStaticTest(w,"pass",void 0,m)}}async function ft(o,m,w,P={}){if(!o||typeof o!="object"||!("ref"in o))return o;let T;if(o.ref==="relative"){if(!o.relativeTarget||!P.relativeBaseSelector)return;let R=w.locator(P.relativeBaseSelector),C=await R.count(),E=0;if(o.relativeTarget==="first"?E=0:o.relativeTarget==="second"?E=1:o.relativeTarget==="last"?E=C-1:isNaN(Number(o.relativeTarget))?E=0:E=Number(o.relativeTarget),E<0||E>=C)return;let B=R.nth(E);return await dt(B,o.property||o.attribute)}else{if(T=m[o.ref],!T)throw new Error(`Selector for ref '${o.ref}' not found in contract selectors.`);let R=w.locator(T).first();return await dt(R,o.property||o.attribute)}}async function dt(o,m){if(o)return!m||m==="id"?await o.getAttribute("id")??void 0:m==="class"?await o.getAttribute("class")??void 0:m==="textContent"?await o.evaluate(w=>w.textContent??void 0):m.startsWith("aria-")?await o.getAttribute(m)??void 0:m.endsWith("*")?await o.evaluate(P=>{let T=[];for(let R of Array.from(P.attributes))R.name.startsWith("aria-")&&T.push(`${R.name}=${R.value}`);return T.join(";")}):await o.getAttribute(m)??void 0}let is=new Te(A,v.selectors,H);async function De(o,m,w,P,T,R=[]){if(!Array.isArray(o)||o.length===0)return{success:!0};w&&typeof w.resetState=="function"&&await w.resetState(P);for(let C of o){let E={success:!0};try{if(C.type==="focus")C.target==="relative"&&C.relativeTarget?E=await m.focus("relative",C.relativeTarget):E=await m.focus(C.target);else if(C.type==="type"&&C.value)E=await m.type(C.target,C.value);else if(C.type==="click")E=await m.click(C.target,C.relativeTarget);else if(C.type==="keypress"&&C.key)E=await m.keypress(C.target,C.key,C.relativeTarget);else if(C.type==="hover")E=await m.hover(C.target,C.relativeTarget);else continue}catch(B){E={success:!1,error:B instanceof Error?B.message:String(B)}}if(!E.success){let B=E.error||"Setup action failed";return R.some(d=>T.includes(d)||B.includes(d))?{success:!1,skip:!0,message:`Skipping test - capability not present: ${B}`}:{success:!1,error:B}}}return{success:!0}}for(let o of v.static[0]?.assertions||[]){if(S&&typeof S.resetState=="function")try{await S.resetState(A)}catch(g){ae.push(`Warning: resetState failed before static test: ${g instanceof Error?g.message:String(g)}`)}if(o.target==="relative")continue;let m=`${o.target}${o.attribute?` (${o.attribute})`:""}`,w=fe(o.level);if(c==="menu"&&o.target==="submenuTrigger"&&!oe){let g=`Skipping submenu static assertion for ${o.target}: no submenu capability detected in rendered component.`;N.push(g),a.reportStaticTest(m,"skip",g,w);continue}let P=[];if(o.target||P.push("target"),o.attribute||P.push("attribute"),typeof o.expectedValue>"u"&&P.push("expectedValue"),P.length>0){let g=`${o.target||""}${o.attribute?` (${o.attribute})`:""}`,d=`Static assertion missing required field(s): ${P.join(", ")}`,k=q(d,o.level);k.status==="fail"&&(_+=1),k.status==="warn"&&(z+=1),a.reportStaticTest(g,k.status,k.detail,k.level);continue}if(Array.isArray(o.setup)&&o.setup.length>0){let k=function(p){return d.includes(p)};var pt=k;let g=new we(A,v.selectors,L),d=["focus","type","click","keypress","hover"],te=p=>({...p,type:k(p.type)?p.type:"click"}),b=o.setup.map(te),K=await De(b,g,S,A,m,["submenu","submenuTrigger","submenuItems"]);if(K.skip){N.push(K.message||"Setup action skipped"),a.reportStaticTest(m,"skip",K.message,w);continue}if(!K.success){let p=`Static setup failed: ${K.error}`,x=q(p,o.level);x.status==="fail"&&(_+=1),x.status==="warn"&&(z+=1),a.reportStaticTest(m,x.status,x.detail,x.level);continue}}let T=v.selectors[o.target];if(!T){let g=`Selector for target ${o.target} not found.`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(m,d.status,d.detail,d.level);continue}let R=A.locator(T).first();if(!(await R.count()>0)){let g=`Target ${o.target} not found.`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(m,d.status,d.detail,d.level);continue}let E=(g,d,k)=>{let te=new RegExp(`\\[${d}(?:=["']?([^\\]"']+)["']?)?\\]`),b=g.match(te);if(!b)return!1;if(!k)return!0;let K=b[1];return K?k.split(" | ").includes(K):!1},B=o.expectedValue;if(o.expectedValue&&typeof o.expectedValue=="object"&&"ref"in o.expectedValue){let g={},d=o.relativeTarget;if(o.expectedValue.ref==="relative"&&o.target==="relative"&&d){let k=v.selectors[d];if(!k)throw new Error(`Selector for relativeTarget '${d}' not found in contract selectors.`);g.relativeBaseSelector=k}else if(o.expectedValue.ref==="relative"&&d){let k=v.selectors[d];if(!k)throw new Error(`Selector for relativeTarget '${d}' not found in contract selectors.`);g.relativeBaseSelector=k}B=await ft(o.expectedValue,v.selectors,A,g)}if(o.expectedValue)if(E(T,o.attribute,typeof B=="string"?B:void 0))ce.push(`${o.attribute}="${B}" on ${o.target} verified by selector (already present in: ${T}).`),ne+=1,a.reportStaticTest(m,"pass",void 0,w);else{let g=B??"",d=await is.validateAttribute(R,o.target,o.attribute,g,o.failureMessage,"Static ARIA Test");if(d.success&&d.passMessage)ce.push(d.passMessage),ne+=1,a.reportStaticTest(m,"pass",void 0,w);else if(!d.success&&d.failMessage){let k=q(d.failMessage,o.level);k.status==="fail"&&(_+=1),k.status==="warn"&&(z+=1),a.reportStaticTest(m,k.status,k.detail,k.level)}}else{let g=o.attribute.split(" | "),d=!1,k=!0;for(let te of g){let b=te.trim();if(E(T,b)){ce.push(`${b} on ${o.target} verified by selector (already present in: ${T}).`),d=!0;continue}if(k=!1,await R.getAttribute(b)!==null){d=!0;break}}if(!d&&!k){let te=o.failureMessage+` None of the attributes "${o.attribute}" are present.`,b=q(te,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(m,b.status,b.detail,b.level)}else!k&&d?(ce.push(`At least one of the attributes "${o.attribute}" exists on the element.`),ne+=1,a.reportStaticTest(m,"pass",void 0,w)):(ne+=1,a.reportStaticTest(m,"pass",void 0,w))}}for(let o of v.dynamic||[]){if(!o.assertions||o.assertions.length===0){let p="Skipping test - no assertions found for this dynamic test.";N.push(p),a.reportTest({description:o.description,level:fe(o.level)},"skip",p);continue}if(!A||A.isClosed()){console.warn(`
141
+ - Original error: ${o}`)}a.start(c,Ce,Ue),c==="menu"&&v.selectors.main&&await A.locator(v.selectors.main).first().waitFor({state:"visible",timeout:U}).catch(()=>{});let oe=c==="menu"&&v.selectors.submenuTrigger?await A.locator(v.selectors.submenuTrigger).count()>0:!1,ee=o=>o.type==="aria-reference"&&[o.from,o.to].some(m=>["submenu","submenuTrigger","submenuItems"].includes(m||""))||o.type==="contains"&&[o.parent,o.child].some(m=>["submenu","submenuTrigger","submenuItems"].includes(m||"")),ne=0,_=0,z=0;for(let o of v.relationships||[]){if(S&&typeof S.resetState=="function")try{await S.resetState(A)}catch(w){ae.push(`Warning: resetState failed before relationship test: ${w instanceof Error?w.message:String(w)}`)}let m=fe(o.level);if(Array.isArray(o.setup)&&o.setup.length>0){let R=function(g){return T.includes(g)};var pt=R;let w=new we(A,v.selectors,L),P=o.type==="aria-reference"?`${o.from}.${o.attribute} references ${o.to}`:`${o.parent} contains ${o.child}`,T=["focus","type","click","keypress","hover"],C=g=>({...g,type:R(g.type)?g.type:"click"}),E=o.setup.map(C),B=await De(E,w,S,A,P,["submenu","submenuTrigger","submenuItems"]);if(B.skip){N.push(B.message||"Setup action skipped"),a.reportStaticTest(P,"skip",B.message,m);continue}if(!B.success){let g=`Relationship setup failed: ${B.error}`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(P,d.status,d.detail,d.level);continue}}if(c==="menu"&&!oe&&ee(o)){let P=o.type==="aria-reference"?`${o.from}.${o.attribute} references ${o.to}`:`${o.parent} contains ${o.child}`,T="Skipping submenu relationship assertion: no submenu capability detected in rendered component.";N.push(T),a.reportStaticTest(P,"skip",T,m);continue}if(o.type==="aria-reference"){let w=`${o.from}.${o.attribute} references ${o.to}`,P=v.selectors[o.from],T=v.selectors[o.to];if(!P||!T){let b=q(`Relationship selector missing: from="${o.from}" or to="${o.to}" not found in selectors.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}let R=A.locator(P).first(),C=A.locator(T).first(),E=await R.count()>0,B=await C.count()>0;if(!E||!B){if(c==="menu"&&ee(o)){let K="Skipping submenu relationship assertion in static phase: submenu elements are not present until submenu is opened.";N.push(K),a.reportStaticTest(w,"skip",K,m);continue}let b=q(`Relationship target not found: ${E?o.to:o.from}.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}let g=await R.getAttribute(o.attribute),d=await C.getAttribute("id");if(!d){let b=q(`Relationship target "${o.to}" must have an id for ${o.attribute} validation.`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}if(!(g||"").split(/\s+/).filter(Boolean).includes(d)){let b=q(`Expected ${o.from} ${o.attribute} to reference id "${d}", found "${g||""}".`,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(w,b.status,b.detail,b.level);continue}ce.push(`Relationship valid: ${o.from}.${o.attribute} -> ${o.to} (id=${d}).`),ne+=1,a.reportStaticTest(w,"pass",void 0,m);continue}if(o.type==="contains"){let w=`${o.parent} contains ${o.child}`,P=v.selectors[o.parent],T=v.selectors[o.child];if(!P||!T){let g=q(`Relationship selector missing: parent="${o.parent}" or child="${o.child}" not found in selectors.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}let R=A.locator(P).first();if(!(await R.count()>0)){if(c==="menu"&&ee(o)){let d="Skipping submenu relationship assertion in static phase: submenu container is not present until submenu is opened.";N.push(d),a.reportStaticTest(w,"skip",d,m);continue}let g=q(`Relationship parent target not found: ${o.parent}.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}if(await R.locator(T).count()<1){if(c==="menu"&&ee(o)){let d="Skipping submenu relationship assertion in static phase: submenu descendants are not present until submenu is opened.";N.push(d),a.reportStaticTest(w,"skip",d,m);continue}let g=q(`Expected ${o.parent} to contain descendant matching selector for ${o.child}.`,o.level);g.status==="fail"&&(_+=1),g.status==="warn"&&(z+=1),a.reportStaticTest(w,g.status,g.detail,g.level);continue}ce.push(`Relationship valid: ${o.parent} contains ${o.child}.`),ne+=1,a.reportStaticTest(w,"pass",void 0,m)}}async function ft(o,m,w,P={}){if(!o||typeof o!="object"||!("ref"in o))return o;let T;if(o.ref==="relative"){if(!o.relativeTarget||!P.relativeBaseSelector)return;let R=w.locator(P.relativeBaseSelector),C=await R.count(),E=0;if(o.relativeTarget==="first"?E=0:o.relativeTarget==="second"?E=1:o.relativeTarget==="last"?E=C-1:isNaN(Number(o.relativeTarget))?E=0:E=Number(o.relativeTarget),E<0||E>=C)return;let B=R.nth(E);return await dt(B,o.property||o.attribute)}else{if(T=m[o.ref],!T)throw new Error(`Selector for ref '${o.ref}' not found in contract selectors.`);let R=w.locator(T).first();return await dt(R,o.property||o.attribute)}}async function dt(o,m){if(o)return!m||m==="id"?await o.getAttribute("id")??void 0:m==="class"?await o.getAttribute("class")??void 0:m==="textContent"?await o.evaluate(w=>w.textContent??void 0):m.startsWith("aria-")?await o.getAttribute(m)??void 0:m.endsWith("*")?await o.evaluate(P=>{let T=[];for(let R of Array.from(P.attributes))R.name.startsWith("aria-")&&T.push(`${R.name}=${R.value}`);return T.join(";")}):await o.getAttribute(m)??void 0}let is=new Te(A,v.selectors,H);async function De(o,m,w,P,T,R=[]){if(!Array.isArray(o)||o.length===0)return{success:!0};w&&typeof w.resetState=="function"&&await w.resetState(P);for(let C of o){let E={success:!0};try{if(C.type==="focus")C.target==="relative"&&C.relativeTarget?E=await m.focus("relative",C.relativeTarget):E=await m.focus(C.target);else if(C.type==="type"&&C.value)E=await m.type(C.target,C.value);else if(C.type==="click")E=await m.click(C.target,C.relativeTarget);else if(C.type==="keypress"&&C.key)E=await m.keypress(C.target,C.key,C.relativeTarget);else if(C.type==="hover")E=await m.hover(C.target,C.relativeTarget);else continue}catch(B){E={success:!1,error:B instanceof Error?B.message:String(B)}}if(!E.success){let B=E.error||"Setup action failed";return R.some(d=>T.includes(d)||B.includes(d))?{success:!1,skip:!0,message:`Skipping test - capability not present: ${B}`}:{success:!1,error:B}}}return{success:!0}}for(let o of v.static||[]){if(S&&typeof S.resetState=="function")try{await S.resetState(A)}catch(g){ae.push(`Warning: resetState failed before static test: ${g instanceof Error?g.message:String(g)}`)}if(o.target==="relative")continue;let m=`${o.target}${o.attribute?` (${o.attribute})`:""}`,w=fe(o.level);if(c==="menu"&&o.target==="submenuTrigger"&&!oe){let g=`Skipping submenu static assertion for ${o.target}: no submenu capability detected in rendered component.`;N.push(g),a.reportStaticTest(m,"skip",g,w);continue}let P=[];if(o.target||P.push("target"),o.attribute||P.push("attribute"),typeof o.expectedValue>"u"&&P.push("expectedValue"),P.length>0){let g=`${o.target||""}${o.attribute?` (${o.attribute})`:""}`,d=`Static assertion missing required field(s): ${P.join(", ")}`,k=q(d,o.level);k.status==="fail"&&(_+=1),k.status==="warn"&&(z+=1),a.reportStaticTest(g,k.status,k.detail,k.level);continue}if(Array.isArray(o.setup)&&o.setup.length>0){let k=function(p){return d.includes(p)};var pt=k;let g=new we(A,v.selectors,L),d=["focus","type","click","keypress","hover"],te=p=>({...p,type:k(p.type)?p.type:"click"}),b=o.setup.map(te),K=await De(b,g,S,A,m,["submenu","submenuTrigger","submenuItems"]);if(K.skip){N.push(K.message||"Setup action skipped"),a.reportStaticTest(m,"skip",K.message,w);continue}if(!K.success){let p=`Static setup failed: ${K.error}`,x=q(p,o.level);x.status==="fail"&&(_+=1),x.status==="warn"&&(z+=1),a.reportStaticTest(m,x.status,x.detail,x.level);continue}}let T=v.selectors[o.target];if(!T){let g=`Selector for target ${o.target} not found.`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(m,d.status,d.detail,d.level);continue}let R=A.locator(T).first();if(!(await R.count()>0)){let g=`Target ${o.target} not found.`,d=q(g,o.level);d.status==="fail"&&(_+=1),d.status==="warn"&&(z+=1),a.reportStaticTest(m,d.status,d.detail,d.level);continue}let E=(g,d,k)=>{let te=new RegExp(`\\[${d}(?:=["']?([^\\]"']+)["']?)?\\]`),b=g.match(te);if(!b)return!1;if(!k)return!0;let K=b[1];return K?k.split(" | ").includes(K):!1},B=o.expectedValue;if(o.expectedValue&&typeof o.expectedValue=="object"&&"ref"in o.expectedValue){let g={},d=o.relativeTarget;if(o.expectedValue.ref==="relative"&&o.target==="relative"&&d){let k=v.selectors[d];if(!k)throw new Error(`Selector for relativeTarget '${d}' not found in contract selectors.`);g.relativeBaseSelector=k}else if(o.expectedValue.ref==="relative"&&d){let k=v.selectors[d];if(!k)throw new Error(`Selector for relativeTarget '${d}' not found in contract selectors.`);g.relativeBaseSelector=k}B=await ft(o.expectedValue,v.selectors,A,g)}if(o.expectedValue)if(E(T,o.attribute,typeof B=="string"?B:void 0))ce.push(`${o.attribute}="${B}" on ${o.target} verified by selector (already present in: ${T}).`),ne+=1,a.reportStaticTest(m,"pass",void 0,w);else{let g=B??"",d=await is.validateAttribute(R,o.target,o.attribute,g,o.failureMessage,"Static ARIA Test");if(d.success&&d.passMessage)ce.push(d.passMessage),ne+=1,a.reportStaticTest(m,"pass",void 0,w);else if(!d.success&&d.failMessage){let k=q(d.failMessage,o.level);k.status==="fail"&&(_+=1),k.status==="warn"&&(z+=1),a.reportStaticTest(m,k.status,k.detail,k.level)}}else{let g=o.attribute.split(" | "),d=!1,k=!0;for(let te of g){let b=te.trim();if(E(T,b)){ce.push(`${b} on ${o.target} verified by selector (already present in: ${T}).`),d=!0;continue}if(k=!1,await R.getAttribute(b)!==null){d=!0;break}}if(!d&&!k){let te=o.failureMessage+` None of the attributes "${o.attribute}" are present.`,b=q(te,o.level);b.status==="fail"&&(_+=1),b.status==="warn"&&(z+=1),a.reportStaticTest(m,b.status,b.detail,b.level)}else!k&&d?(ce.push(`At least one of the attributes "${o.attribute}" exists on the element.`),ne+=1,a.reportStaticTest(m,"pass",void 0,w)):(ne+=1,a.reportStaticTest(m,"pass",void 0,w))}}for(let o of v.dynamic||[]){if(!o.assertions||o.assertions.length===0){let p="Skipping test - no assertions found for this dynamic test.";N.push(p),a.reportTest({description:o.description,level:fe(o.level)},"skip",p);continue}if(!A||A.isClosed()){console.warn(`
142
142
  \u26A0\uFE0F Browser closed - skipping remaining ${v.dynamic.length-v.dynamic.indexOf(o)} tests
143
143
  `),Z.push(`CRITICAL: Browser/page closed before completing all tests. ${v.dynamic.length-v.dynamic.indexOf(o)} tests skipped.`);break}try{await S.resetState(A)}catch(p){let x=p instanceof Error?p.message:String(p);throw a.error(x),p}let{setup:m=[],action:w,assertions:P}=o,T=fe(o.level),R=new we(A,v.selectors,L);if(Array.isArray(m)&&m.length>0){let x=function(Q){return p.includes(Q)};var pt=x;let p=["focus","type","click","keypress","hover"],ge=Q=>({...Q,type:x(Q.type)?Q.type:"click"}),qe=m.map(ge),re=await De(qe,R,S,A,o.description,["submenu","submenuTrigger","submenuItems"]);if(re.skip){N.push(re.message||"Setup action skipped"),a.reportTest({description:o.description,level:T},"skip",re.message);continue}if(!re.success){let Q=q(`Setup failed: ${re.error}`,o.level);a.reportTest({description:o.description,level:T},Q.status,Q.detail);continue}}let C=Z.length,E=ae.length,B=N.length;if(await S.shouldSkipTest(o,A)){let p="Skipping test - component-specific conditions not met";N.push(p),a.reportTest({description:o.description,level:T},"skip",p);continue}let d=new Te(A,v.selectors,H),k=!1,te=null;for(let p of w){if(!A||A.isClosed()){Z.push("CRITICAL: Browser/page closed during test execution. Remaining actions skipped."),k=!0;break}let x;if(p.type==="focus")p.target==="relative"&&p.relativeTarget?x=await R.focus("relative",p.relativeTarget):x=await R.focus(p.target);else if(p.type==="type"&&p.value)x=await R.type(p.target,p.value);else if(p.type==="click")x=await R.click(p.target,p.relativeTarget);else if(p.type==="keypress"&&p.key)x=await R.keypress(p.target,p.key,p.relativeTarget);else if(p.type==="hover")x=await R.hover(p.target,p.relativeTarget);else continue;if(!x.success){if(x.error){let ge=q(x.error,o.level);te={status:ge.status,detail:ge.detail}}k=!0;break}}if(k){a.reportTest({description:o.description,level:T},te?.status||"fail",te?.detail||Z[Z.length-1]);continue}for(let p of P){let x;if(p.expectedValue&&typeof p.expectedValue=="object"&&"ref"in p.expectedValue)if(p.expectedValue.ref==="relative"){let{RelativeTargetResolver:le}=await Promise.resolve().then(()=>(je(),qt)),Q=v.selectors.relative;if(!Q)throw new Error("Relative selector not defined in contract selectors.");let ve=p.relativeTarget||"first",ue=await le.resolve(A,Q,ve);if(!ue)throw new Error(`Could not resolve relative target '${ve}' for expectedValue.`);let mt=p.expectedValue.property||p.expectedValue.attribute||"id";if(mt==="textContent")x=await ue.evaluate(ke=>ke.textContent??void 0);else{let ke=await ue.getAttribute(mt);x=ke===null?void 0:ke}}else x=await ft(p.expectedValue,v.selectors,A,{});else typeof p.expectedValue=="string"||typeof p.expectedValue>"u"?x=p.expectedValue:x="";let ge={...p,expectedValue:x},qe=x??"",re=await d.validate({...ge,expectedValue:qe},o.description);if(re.success&&re.passMessage)ce.push(re.passMessage);else if(!re.success&&re.failMessage){let le=[];if(p.target||le.push("target"),p.assertion||le.push("assertion"),["toHaveAttribute","toHaveValue","toHaveRole"].includes(p.assertion)&&(typeof p.attribute>"u"&&p.assertion==="toHaveAttribute"&&le.push("attribute"),typeof p.expectedValue>"u"&&le.push("expectedValue")),le.length>0){let Q=fe(p.level||o.level),ve=`Dynamic assertion missing required field(s): ${le.join(", ")}`,ue=q(ve,Q);if(ue.status==="skip")continue;Z.push(ve),a.reportTest({description:o.description,level:Q},ue.status,ue.detail);continue}}}let b=Z.length,K=ae.length,gt=N.length;b>C?a.reportTest({description:o.description,level:T},"fail",Z[Z.length-1]):K>E?a.reportTest({description:o.description,level:T},"warn",ae[ae.length-1]):gt>B?a.reportTest({description:o.description,level:T},"skip",N[N.length-1]):a.reportTest({description:o.description,level:T},"pass")}a.reportStatic(ne,_,z),a.summary(Z)}catch(S){if(S instanceof Error)throw S.message.includes("Executable doesn't exist")||S.message.includes("browserType.launch")?new Error(`
144
144
  \u274C CRITICAL: Playwright browsers not found!
@@ -174,7 +174,7 @@ ${h}
174
174
  \u{1F4CB} Full details available in result.violations`)}return u}async function zt(){await kt()}var Jt,at,Gt=j(()=>{"use strict";et();tt();Jt=I(require("path"),1);at=async()=>({passes:[],failures:[],skipped:[]});typeof window>"u"&&(at=async()=>{console.log(`\u{1F680} Running component accessibility tests...
175
175
  `);let{exec:c}=await import("child_process"),e=(await import("chalk")).default;return new Promise((t,r)=>{c("npx vitest --run --reporter verbose",async(s,i,n)=>{if(console.log(i),n&&console.error(n),!s||s.code===0){try{let{displayBadgeInfo:l,promptAddBadge:u}=await Promise.resolve().then(()=>(Ke(),bt));l("component"),await u("component",process.cwd()),console.log(e.dim(`
176
176
  `+"\u2500".repeat(60))),console.log(e.cyan("\u{1F499} Found aria-ease helpful?")),console.log(e.white(" \u2022 Star us on GitHub: ")+e.blue.underline("https://github.com/aria-ease/aria-ease")),console.log(e.white(" \u2022 Share feedback: ")+e.blue.underline("https://github.com/aria-ease/aria-ease/discussions")),console.log(e.dim("\u2500".repeat(60)+`
177
- `))}catch(l){console.error("Warning: Could not display badge prompt:",l)}t({passes:[],failures:[],skipped:[]}),process.exit(0)}else{let l=s?.code||1;r(new Error(`Tests failed with code ${l}`)),process.exit(l)}})})})});var Yt={};X(Yt,{cleanupTests:()=>zt,runTest:()=>at,testUiComponent:()=>_t});var Kt=j(()=>{"use strict";Gt()});function Qt(c){let e=[];if(!c||typeof c!="object")return{valid:!1,errors:[{path:"$",message:"Contract must be an object"}]};let t=c;if(!t.selectors)e.push({path:"$.selectors",message:"selectors is required"});else if(typeof t.selectors!="object"||t.selectors===null||Array.isArray(t.selectors))e.push({path:"$.selectors",message:"selectors must be an object"});else{let r=t.selectors;Object.entries(r).forEach(([s,i])=>{typeof i!="string"&&e.push({path:`$.selectors['${s}']`,message:"All selectors must be strings"})})}return Array.isArray(t.static)?t.static.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.static[${s}]`,message:"static item must be an object"});return}let i=r;if(!Array.isArray(i.assertions)){e.push({path:`$.static[${s}].assertions`,message:"assertions must be an array"});return}i.assertions.forEach((n,a)=>{if(typeof n!="object"||n===null){e.push({path:`$.static[${s}].assertions[${a}]`,message:"assertion must be an object"});return}let l=n;typeof l.target!="string"&&e.push({path:`$.static[${s}].assertions[${a}].target`,message:"target is required and must be a string"}),typeof l.attribute!="string"&&e.push({path:`$.static[${s}].assertions[${a}].attribute`,message:"attribute is required and must be a string"}),typeof l.failureMessage!="string"&&e.push({path:`$.static[${s}].assertions[${a}].failureMessage`,message:"failureMessage is required and must be a string"}),l.level!==void 0&&!["required","recommended","optional"].includes(l.level)&&e.push({path:`$.static[${s}].assertions[${a}].level`,message:"level must be one of: required, recommended, optional"})})}):e.push({path:"$.static",message:"static must be an array"}),Array.isArray(t.dynamic)?t.dynamic.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.dynamic[${s}]`,message:"dynamic item must be an object"});return}let i=r;typeof i.description!="string"&&e.push({path:`$.dynamic[${s}].description`,message:"description is required and must be a string"}),Array.isArray(i.action)?i.action.forEach((n,a)=>{if(typeof n!="object"||n===null){e.push({path:`$.dynamic[${s}].action[${a}]`,message:"action item must be an object"});return}let l=n;typeof l.type!="string"&&e.push({path:`$.dynamic[${s}].action[${a}].type`,message:"type is required and must be a string"}),typeof l.target!="string"&&e.push({path:`$.dynamic[${s}].action[${a}].target`,message:"target is required and must be a string"})}):e.push({path:`$.dynamic[${s}].action`,message:"action is required and must be an array"}),Array.isArray(i.assertions)?i.assertions.forEach((n,a)=>{if(typeof n!="object"||n===null){e.push({path:`$.dynamic[${s}].assertions[${a}]`,message:"assertion must be an object"});return}let l=n;typeof l.target!="string"&&e.push({path:`$.dynamic[${s}].assertions[${a}].target`,message:"target is required and must be a string"}),typeof l.assertion!="string"&&e.push({path:`$.dynamic[${s}].assertions[${a}].assertion`,message:"assertion is required and must be a string"}),l.level!==void 0&&!["required","recommended","optional"].includes(l.level)&&e.push({path:`$.dynamic[${s}].assertions[${a}].level`,message:"level must be one of: required, recommended, optional"})}):e.push({path:`$.dynamic[${s}].assertions`,message:"assertions is required and must be an array"})}):e.push({path:"$.dynamic",message:"dynamic must be an array"}),t.relationships!==void 0&&(Array.isArray(t.relationships)?t.relationships.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.relationships[${s}]`,message:"relationship must be an object"});return}let i=r,n=i.type;["aria-reference","contains"].includes(n)||e.push({path:`$.relationships[${s}].type`,message:"type must be one of: aria-reference, contains"}),n==="aria-reference"?(typeof i.from!="string"&&e.push({path:`$.relationships[${s}].from`,message:"from is required for aria-reference and must be a string"}),typeof i.attribute!="string"&&e.push({path:`$.relationships[${s}].attribute`,message:"attribute is required for aria-reference and must be a string"}),typeof i.to!="string"&&e.push({path:`$.relationships[${s}].to`,message:"to is required for aria-reference and must be a string"})):n==="contains"&&(typeof i.parent!="string"&&e.push({path:`$.relationships[${s}].parent`,message:"parent is required for contains and must be a string"}),typeof i.child!="string"&&e.push({path:`$.relationships[${s}].child`,message:"child is required for contains and must be a string"}))}):e.push({path:"$.relationships",message:"relationships must be an array"})),{valid:e.length===0,errors:e}}function Xt(c,e){let t=[];if(!c||typeof c!="object")return t;let s=c.relationships;return Array.isArray(s)&&s.forEach((i,n)=>{let a=i.type;if(a==="aria-reference"){let l=i.from,u=i.to;l&&!e.has(l)&&t.push({path:`$.relationships[${n}].from`,message:`Selector '${l}' not found in selectors`}),u&&!e.has(u)&&t.push({path:`$.relationships[${n}].to`,message:`Selector '${u}' not found in selectors`})}else if(a==="contains"){let l=i.parent,u=i.child;l&&!e.has(l)&&t.push({path:`$.relationships[${n}].parent`,message:`Selector '${l}' not found in selectors`}),u&&!e.has(u)&&t.push({path:`$.relationships[${n}].child`,message:`Selector '${u}' not found in selectors`})}}),t}function Zt(c,e){let t=[];if(!c||typeof c!="object")return t;let r=c,s=r.static;Array.isArray(s)&&s.forEach((n,a)=>{let l=n.assertions;Array.isArray(l)&&l.forEach((u,f)=>{let h=u.target;h&&!e.has(h)&&t.push({path:`$.static[${a}].assertions[${f}].target`,message:`Selector '${h}' not found in selectors`})})});let i=r.dynamic;return Array.isArray(i)&&i.forEach((n,a)=>{let l=n.action;Array.isArray(l)&&l.forEach((f,h)=>{let y=f.target;y&&y!=="document"&&!e.has(y)&&t.push({path:`$.dynamic[${a}].action[${h}].target`,message:`Selector '${y}' not found in selectors (or use 'document')`})});let u=n.assertions;Array.isArray(u)&&u.forEach((f,h)=>{let y=f.target;y&&y!=="relative"&&!e.has(y)&&t.push({path:`$.dynamic[${a}].assertions[${h}].target`,message:`Selector '${y}' not found in selectors (or use 'relative')`})})}),t}var es=j(()=>{"use strict"});var ss={};X(ss,{buildContracts:()=>ks});async function ks(c,e){let t=[],r=[];if(!e.contracts||e.contracts.length===0)return console.log(V.default.yellow('\u2139\uFE0F No contracts configured. Add "contracts" array to ariaease.config.js')),{success:!0,built:r,errors:t};try{console.log(V.default.cyanBright(`
177
+ `))}catch(l){console.error("Warning: Could not display badge prompt:",l)}t({passes:[],failures:[],skipped:[]}),process.exit(0)}else{let l=s?.code||1;r(new Error(`Tests failed with code ${l}`)),process.exit(l)}})})})});var Yt={};X(Yt,{cleanupTests:()=>zt,runTest:()=>at,testUiComponent:()=>_t});var Kt=j(()=>{"use strict";Gt()});function Qt(c){let e=[];if(!c||typeof c!="object")return{valid:!1,errors:[{path:"$",message:"Contract must be an object"}]};let t=c;if(!t.selectors)e.push({path:"$.selectors",message:"selectors is required"});else if(typeof t.selectors!="object"||t.selectors===null||Array.isArray(t.selectors))e.push({path:"$.selectors",message:"selectors must be an object"});else{let r=t.selectors;Object.entries(r).forEach(([s,i])=>{typeof i!="string"&&e.push({path:`$.selectors['${s}']`,message:"All selectors must be strings"})})}return Array.isArray(t.static)?t.static.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.static[${s}]`,message:"static item must be an object"});return}let i=r;typeof i.target!="string"&&e.push({path:`$.static[${s}].target`,message:"target is required and must be a string"}),typeof i.attribute!="string"&&e.push({path:`$.static[${s}].attribute`,message:"attribute is required and must be a string"}),typeof i.failureMessage!="string"&&e.push({path:`$.static[${s}].failureMessage`,message:"failureMessage is required and must be a string"}),i.level!==void 0&&!["required","recommended","optional"].includes(i.level)&&e.push({path:`$.static[${s}].level`,message:"level must be one of: required, recommended, optional"})}):e.push({path:"$.static",message:"static must be an array"}),Array.isArray(t.dynamic)?t.dynamic.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.dynamic[${s}]`,message:"dynamic item must be an object"});return}let i=r;typeof i.description!="string"&&e.push({path:`$.dynamic[${s}].description`,message:"description is required and must be a string"}),Array.isArray(i.action)?i.action.forEach((n,a)=>{if(typeof n!="object"||n===null){e.push({path:`$.dynamic[${s}].action[${a}]`,message:"action item must be an object"});return}let l=n;typeof l.type!="string"&&e.push({path:`$.dynamic[${s}].action[${a}].type`,message:"type is required and must be a string"}),typeof l.target!="string"&&e.push({path:`$.dynamic[${s}].action[${a}].target`,message:"target is required and must be a string"})}):e.push({path:`$.dynamic[${s}].action`,message:"action is required and must be an array"}),Array.isArray(i.assertions)?i.assertions.forEach((n,a)=>{if(typeof n!="object"||n===null){e.push({path:`$.dynamic[${s}].assertions[${a}]`,message:"assertion must be an object"});return}let l=n;typeof l.target!="string"&&e.push({path:`$.dynamic[${s}].assertions[${a}].target`,message:"target is required and must be a string"}),typeof l.assertion!="string"&&e.push({path:`$.dynamic[${s}].assertions[${a}].assertion`,message:"assertion is required and must be a string"}),l.level!==void 0&&!["required","recommended","optional"].includes(l.level)&&e.push({path:`$.dynamic[${s}].assertions[${a}].level`,message:"level must be one of: required, recommended, optional"})}):e.push({path:`$.dynamic[${s}].assertions`,message:"assertions is required and must be an array"})}):e.push({path:"$.dynamic",message:"dynamic must be an array"}),t.relationships!==void 0&&(Array.isArray(t.relationships)?t.relationships.forEach((r,s)=>{if(typeof r!="object"||r===null){e.push({path:`$.relationships[${s}]`,message:"relationship must be an object"});return}let i=r,n=i.type;["aria-reference","contains"].includes(n)||e.push({path:`$.relationships[${s}].type`,message:"type must be one of: aria-reference, contains"}),n==="aria-reference"?(typeof i.from!="string"&&e.push({path:`$.relationships[${s}].from`,message:"from is required for aria-reference and must be a string"}),typeof i.attribute!="string"&&e.push({path:`$.relationships[${s}].attribute`,message:"attribute is required for aria-reference and must be a string"}),typeof i.to!="string"&&e.push({path:`$.relationships[${s}].to`,message:"to is required for aria-reference and must be a string"})):n==="contains"&&(typeof i.parent!="string"&&e.push({path:`$.relationships[${s}].parent`,message:"parent is required for contains and must be a string"}),typeof i.child!="string"&&e.push({path:`$.relationships[${s}].child`,message:"child is required for contains and must be a string"}))}):e.push({path:"$.relationships",message:"relationships must be an array"})),{valid:e.length===0,errors:e}}function Xt(c,e){let t=[];if(!c||typeof c!="object")return t;let s=c.relationships;return Array.isArray(s)&&s.forEach((i,n)=>{let a=i.type;if(a==="aria-reference"){let l=i.from,u=i.to;l&&!e.has(l)&&t.push({path:`$.relationships[${n}].from`,message:`Selector '${l}' not found in selectors`}),u&&!e.has(u)&&t.push({path:`$.relationships[${n}].to`,message:`Selector '${u}' not found in selectors`})}else if(a==="contains"){let l=i.parent,u=i.child;l&&!e.has(l)&&t.push({path:`$.relationships[${n}].parent`,message:`Selector '${l}' not found in selectors`}),u&&!e.has(u)&&t.push({path:`$.relationships[${n}].child`,message:`Selector '${u}' not found in selectors`})}}),t}function Zt(c,e){let t=[];if(!c||typeof c!="object")return t;let r=c,s=r.static;Array.isArray(s)&&s.forEach((n,a)=>{let l=n.assertions;Array.isArray(l)&&l.forEach((u,f)=>{let h=u.target;h&&!e.has(h)&&t.push({path:`$.static[${a}].assertions[${f}].target`,message:`Selector '${h}' not found in selectors`})})});let i=r.dynamic;return Array.isArray(i)&&i.forEach((n,a)=>{let l=n.action;Array.isArray(l)&&l.forEach((f,h)=>{let y=f.target;y&&y!=="document"&&!e.has(y)&&t.push({path:`$.dynamic[${a}].action[${h}].target`,message:`Selector '${y}' not found in selectors (or use 'document')`})});let u=n.assertions;Array.isArray(u)&&u.forEach((f,h)=>{let y=f.target;y&&y!=="relative"&&!e.has(y)&&t.push({path:`$.dynamic[${a}].assertions[${h}].target`,message:`Selector '${y}' not found in selectors (or use 'relative')`})})}),t}var es=j(()=>{"use strict"});var ss={};X(ss,{buildContracts:()=>ks});async function ks(c,e){let t=[],r=[];if(!e.contracts||e.contracts.length===0)return console.log(V.default.yellow('\u2139\uFE0F No contracts configured. Add "contracts" array to ariaease.config.js')),{success:!0,built:r,errors:t};try{console.log(V.default.cyanBright(`
178
178
  \u{1F3D7}\uFE0F Building contracts...
179
179
  `));for(let s of e.contracts){let i=D.default.resolve(c,s.src),n=s.out?D.default.resolve(c,s.out):void 0;console.log(V.default.gray(` Pattern: ${s.src}`)),console.log(n?V.default.gray(` Output: ${s.out}
180
180
  `):V.default.gray(` Output: Same directory as source
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import{a as x}from"./chunk-ZNQ5BXVJ.js";import{c as R,d as C}from"./chunk-52I3IN
13
13
  \u274C Accessibility violations found!`)),console.log(o.yellow(` ${$} violation${$!==1?"s":""} detected across ${r.length} page${r.length!==1?"s":""}.`)),console.log(o.gray(` Review the generated report for details.
14
14
  `)),console.log(o.dim(`
15
15
  `+"\u2500".repeat(60))),console.log(o.cyan("\u{1F499} Found aria-ease helpful?")),console.log(o.white(" \u2022 Star us on GitHub: ")+o.blue.underline("https://github.com/aria-ease/aria-ease")),console.log(o.white(" \u2022 Share feedback: ")+o.blue.underline("https://github.com/aria-ease/aria-ease/discussions")),console.log(o.dim("\u2500".repeat(60)+`
16
- `)),process.exit(1)});l.command("test").description("Run core a11y accessibility standard tests on UI components").action(async()=>{let{runTest:n}=await import("./test-PCRWMQUO.js");n()});l.command("build").description("Build accessibility artifacts").addCommand(new S("contracts").description("Build DSL contracts to JSON").action(async()=>{let{buildContracts:n}=await import("./buildContracts-T4XQZBDU.js"),{loadConfig:h}=await import("./configLoader-ZXTSCIP6.js"),f=process.cwd(),{config:c,configPath:s,errors:u}=await h(f);s?console.log(o.green(`\u2705 Loaded config from ${w.basename(s)}
16
+ `)),process.exit(1)});l.command("test").description("Run core a11y accessibility standard tests on UI components").action(async()=>{let{runTest:n}=await import("./test-2XAMHIKD.js");n()});l.command("build").description("Build accessibility artifacts").addCommand(new S("contracts").description("Build DSL contracts to JSON").action(async()=>{let{buildContracts:n}=await import("./buildContracts-NGEEUCN3.js"),{loadConfig:h}=await import("./configLoader-ZXTSCIP6.js"),f=process.cwd(),{config:c,configPath:s,errors:u}=await h(f);s?console.log(o.green(`\u2705 Loaded config from ${w.basename(s)}
17
17
  `)):u.length>0&&(console.log(o.red(`\u274C Config file has errors:
18
18
  `)),u.forEach(d=>console.log(o.red(` ${d}`))),console.log(""),process.exit(1));let i=await n(f,c);!i.success&&i.errors.length>0&&(console.log(o.red(`\u274C ${i.errors.length} error${i.errors.length!==1?"s":""} occurred during build
19
19
  `)),process.exit(1)),i.built.length===0&&(!c.contracts||c.contracts.length===0)&&process.exit(0),i.built.length===0&&(console.log(o.yellow(`\u26A0\uFE0F No contracts were built
@@ -1,4 +1,4 @@
1
- import{a as Te,c as Q,d as Se,e as ke}from"./chunk-APUMBDOT.js";import{a as N}from"./chunk-SM6ZKEDR.js";import{a as j}from"./chunk-WIWSYIGK.js";import"./chunk-CNU4N4AY.js";import{readFileSync as de}from"fs";import he from"path";import{readFileSync as fe}from"fs";import ge from"path";import Ce from"path";import{pathToFileURL as Pe}from"url";var oe=class{builtInStrategies=new Map;constructor(){this.registerBuiltInStrategies()}registerBuiltInStrategies(){this.builtInStrategies.set("menu",()=>import("./MenuComponentStrategy-L3QXLC6S.js").then(t=>t.MenuComponentStrategy)),this.builtInStrategies.set("accordion",()=>import("./AccordionComponentStrategy-2SWMNUR6.js").then(t=>t.AccordionComponentStrategy)),this.builtInStrategies.set("combobox",()=>import("./ComboboxComponentStrategy-DHZS4NW6.js").then(t=>t.ComboboxComponentStrategy)),this.builtInStrategies.set("tabs",()=>import("./TabsComponentStrategy-LKV6D2B7.js").then(t=>t.TabsComponentStrategy))}async loadStrategy(t,s,r){try{if(s)try{let n=Ce.isAbsolute(s)?s:Ce.resolve(r||process.cwd(),s),u=await import(Pe(n).href),i=u.default||u;if(!i)throw new Error(`No default export found in ${s}`);return i}catch(n){throw new Error(`Failed to load custom strategy from ${s}: ${n instanceof Error?n.message:String(n)}`)}let o=this.builtInStrategies.get(t);return o?o():null}catch(o){throw new Error(`Strategy loading failed for ${t}: ${o instanceof Error?o.message:String(o)}`)}}has(t,s){return!!s||this.builtInStrategies.has(t)}};var ae=class{static strategyRegistry=new oe;static isComponentConfig(t){return typeof t=="object"&&t!==null}static async detect(t,s,r=400,o=400,n){let u=this.isComponentConfig(s)?s:void 0,i=u?.contractPath;if(!i)throw new Error(`Contract path not found for component: ${t}`);let R=(()=>{if(ge.isAbsolute(i))return i;if(n){let ie=ge.resolve(n,i);try{return fe(ie,"utf-8"),ie}catch{}}let X=ge.resolve(process.cwd(),i);try{return fe(X,"utf-8"),X}catch{return new URL(i,import.meta.url).pathname}})(),C=fe(R,"utf-8"),te=JSON.parse(C).selectors,_=await this.strategyRegistry.loadStrategy(t,u?.strategyPath,n);if(!_)return null;let z=te.main;return t==="tabs"?new _(z,te):new _(z,te,r,o)}};var ce=class{startTime=0;componentName="";staticPasses=0;staticFailures=0;staticWarnings=0;dynamicResults=[];totalTests=0;skipped=0;warnings=0;isPlaywright=!1;isCustomContract=!1;apgUrl="https://www.w3.org/WAI/ARIA/apg/";hasPrintedStaticSection=!1;hasPrintedDynamicSection=!1;constructor(t=!1,s=!1){this.isPlaywright=t,this.isCustomContract=s}log(t){process.stderr.write(t+`
1
+ import{a as Te,c as Q,d as Se,e as ke}from"./chunk-APUMBDOT.js";import{a as N}from"./chunk-SM6ZKEDR.js";import{a as j}from"./chunk-WIWSYIGK.js";import"./chunk-CNU4N4AY.js";import{readFileSync as de}from"fs";import he from"path";import{readFileSync as fe}from"fs";import ge from"path";import Ce from"path";import{pathToFileURL as Pe}from"url";var oe=class{builtInStrategies=new Map;constructor(){this.registerBuiltInStrategies()}registerBuiltInStrategies(){this.builtInStrategies.set("menu",()=>import("./MenuComponentStrategy-L3QXLC6S.js").then(t=>t.MenuComponentStrategy)),this.builtInStrategies.set("accordion",()=>import("./AccordionComponentStrategy-T5YODP3A.js").then(t=>t.AccordionComponentStrategy)),this.builtInStrategies.set("combobox",()=>import("./ComboboxComponentStrategy-DHZS4NW6.js").then(t=>t.ComboboxComponentStrategy)),this.builtInStrategies.set("tabs",()=>import("./TabsComponentStrategy-LKV6D2B7.js").then(t=>t.TabsComponentStrategy))}async loadStrategy(t,s,r){try{if(s)try{let n=Ce.isAbsolute(s)?s:Ce.resolve(r||process.cwd(),s),u=await import(Pe(n).href),i=u.default||u;if(!i)throw new Error(`No default export found in ${s}`);return i}catch(n){throw new Error(`Failed to load custom strategy from ${s}: ${n instanceof Error?n.message:String(n)}`)}let o=this.builtInStrategies.get(t);return o?o():null}catch(o){throw new Error(`Strategy loading failed for ${t}: ${o instanceof Error?o.message:String(o)}`)}}has(t,s){return!!s||this.builtInStrategies.has(t)}};var ae=class{static strategyRegistry=new oe;static isComponentConfig(t){return typeof t=="object"&&t!==null}static async detect(t,s,r=400,o=400,n){let u=this.isComponentConfig(s)?s:void 0,i=u?.contractPath;if(!i)throw new Error(`Contract path not found for component: ${t}`);let R=(()=>{if(ge.isAbsolute(i))return i;if(n){let ie=ge.resolve(n,i);try{return fe(ie,"utf-8"),ie}catch{}}let X=ge.resolve(process.cwd(),i);try{return fe(X,"utf-8"),X}catch{return new URL(i,import.meta.url).pathname}})(),C=fe(R,"utf-8"),te=JSON.parse(C).selectors,_=await this.strategyRegistry.loadStrategy(t,u?.strategyPath,n);if(!_)return null;let z=te.main;return t==="tabs"?new _(z,te):new _(z,te,r,o)}};var ce=class{startTime=0;componentName="";staticPasses=0;staticFailures=0;staticWarnings=0;dynamicResults=[];totalTests=0;skipped=0;warnings=0;isPlaywright=!1;isCustomContract=!1;apgUrl="https://www.w3.org/WAI/ARIA/apg/";hasPrintedStaticSection=!1;hasPrintedDynamicSection=!1;constructor(t=!1,s=!1){this.isPlaywright=t,this.isCustomContract=s}log(t){process.stderr.write(t+`
2
2
  `)}start(t,s,r){this.startTime=Date.now(),this.componentName=t,this.totalTests=s,this.hasPrintedStaticSection=!1,this.hasPrintedDynamicSection=!1,r&&(this.apgUrl=r);let o="Playwright (Real Browser)";this.log(`
3
3
  ${"\u2550".repeat(60)}`),this.log(`\u{1F50D} Testing ${t.charAt(0).toUpperCase()+t.slice(1)} Component - ${o}`),this.log(`${"\u2550".repeat(60)}
4
4
  `)}reportStatic(t,s,r=0){this.staticPasses=t,this.staticFailures=s,this.staticWarnings=r}reportStaticTest(t,s,r,o){this.hasPrintedStaticSection||(this.log(`${"\u2500".repeat(60)}`),this.log("\u{1F9EA} Static Assertions"),this.log(`${"\u2500".repeat(60)}`),this.hasPrintedStaticSection=!0);let n=s==="pass"?"\u2713":s==="warn"?"\u26A0":s==="skip"?"\u25CB":"\u2717";this.log(` ${n} ${t}`),o&&this.log(` \u21B3 level=${o}`),(s==="fail"||s==="warn"||s==="skip")&&r&&this.log(` \u21B3 ${r}`)}reportTest(t,s,r){this.hasPrintedDynamicSection||(this.log(""),this.log(`${"\u2500".repeat(60)}`),this.log("\u2328\uFE0F Dynamic Interaction Tests"),this.log(`${"\u2500".repeat(60)}`),this.hasPrintedDynamicSection=!0);let o={description:t.description,status:s,failureMessage:r,level:t.level};s==="skip"&&(o.skipReason="Requires real browser (addEventListener events)"),this.dynamicResults.push(o);let n={pass:"\u2713",fail:"\u2717",warn:"\u26A0",skip:"\u25CB"},u=t.level?`[${t.level.toUpperCase()}] `:"";this.log(` ${n[s]} ${u}${t.description}`),s==="skip"&&!this.isPlaywright&&this.log(" \u21B3 Skipped (runs only in Playwright)"),s==="fail"&&r&&this.log(` \u21B3 ${r}`),s==="warn"&&r&&this.log(` \u21B3 ${r}`),s==="skip"&&r&&this.log(` \u21B3 ${r}`)}reportFailures(t){t.length!==0&&(this.log(`
@@ -19,13 +19,13 @@ ${"\u2550".repeat(60)}`),this.log(`\u{1F4CA} Summary
19
19
  `),i>0?(this.log("\u{1F527} Next Steps:"),this.log(" 1. Review the failures above"),this.log(" 2. Fix ARIA attributes and keyboard handlers"),this.log(` 3. Re-run tests to verify fixes
20
20
  `)):!this.isPlaywright&&this.skipped>0&&this.log(`\u2728 Optional: Run Playwright tests for complete validation
21
21
  `),{passes:u,failures:i,skipped:this.skipped,duration:s}}error(t,s){this.log(`
22
- \u274C Error: ${t}`),s&&this.log(` Context: ${s}`),this.log("")}};var ee=class{constructor(t,s,r=400){this.page=t;this.selectors=s;this.timeoutMs=r}isBrowserClosedError(t){return t instanceof Error&&t.message.includes("Target page, context or browser has been closed")}async focus(t,s,r){try{if(t==="virtual"&&r){let n=this.selectors.main;if(!n)return{success:!1,error:"Main selector not defined for virtual focus."};let u=this.page.locator(n).first();return await u.count()?(await u.evaluate((R,C)=>{R.setAttribute("aria-activedescendant",C)},r),{success:!0}):{success:!1,error:"Main element not found for virtual focus."}}if(t==="relative"&&s){let n=this.selectors.relative;if(!n)return{success:!1,error:"Relative selector not defined for focus action."};let u=await j.resolve(this.page,n,s);return u?(await u.focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for focus.`}}let o=this.selectors[t];return o?(await this.page.locator(o).first().focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for focus target ${t} not found.`}}catch(o){return this.isBrowserClosedError(o)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to focus ${t}: ${o instanceof Error?o.message:String(o)}`}}}async type(t,s){try{let r=this.selectors[t];return r?(await this.page.locator(r).first().fill(s,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for type target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to type into ${t}: ${r instanceof Error?r.message:String(r)}`}}}async click(t,s){try{if(t==="document")return await this.page.mouse.click(10,10),{success:!0};if(t==="relative"&&s){let o=this.selectors.relative;if(!o)return{success:!1,error:"Relative selector not defined for click action."};let n=await j.resolve(this.page,o,s);return n?(await n.click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for click.`}}let r=this.selectors[t];return r?(await this.page.locator(r).first().click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for action target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to click ${t}: ${r instanceof Error?r.message:String(r)}`}}}async keypress(t,s,r){try{let n={Space:"Space",Enter:"Enter",Escape:"Escape","Arrow Up":"ArrowUp","Arrow Down":"ArrowDown","Arrow Left":"ArrowLeft","Arrow Right":"ArrowRight",Home:"Home",End:"End",Tab:"Tab"}[s]||s;if(n==="Space"?n=" ":n.includes(" ")&&(n=n.replace(/ /g,"")),t==="relative"){if(r==null)return{success:!1,error:"relativeTarget must be provided for relative keypress."};let C=this.selectors.relative;if(!C)return{success:!1,error:"Relative selector not defined for keypress action."};let A=await j.resolve(this.page,C,r);return A?(await A.press(n,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${r} for keypress.`}}let u=this.selectors[t];if(!u)return{success:!1,error:`Selector for keypress target ${t} not found.`};let i=this.page.locator(u).first();return await i.count()===0?{success:!1,error:`${t} element not found.`,shouldBreak:!0}:(await i.press(n,{timeout:this.timeoutMs}),{success:!0})}catch(o){return this.isBrowserClosedError(o)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to press ${s} on ${t}: ${o instanceof Error?o.message:String(o)}`}}}async hover(t,s){try{if(t==="relative"&&s){let o=this.selectors.relative;if(!o)return{success:!1,error:"Relative selector not defined for hover action."};let n=await j.resolve(this.page,o,s);return n?(await n.hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for hover.`}}let r=this.selectors[t];return r?(await this.page.locator(r).first().hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for hover target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to hover ${t}: ${r instanceof Error?r.message:String(r)}`}}}};var re=class{constructor(t,s,r=400){this.page=t;this.selectors=s;this.timeoutMs=r}async resolveTarget(t,s,r){try{if(t==="relative"){let n=r?this.selectors[r]:this.selectors.relative;if(!n)return{target:null,error:"Relative selector is not defined in the contract."};if(!s)return{target:null,error:"Relative target or expected value is not defined."};let u=await j.resolve(this.page,n,s);return u?{target:u}:{target:null,error:`Target ${t} not found.`}}let o=this.selectors[t];return o?{target:this.page.locator(o).first()}:{target:null,error:`Selector for assertion target ${t} not found.`}}catch(o){return{target:null,error:`Failed to resolve target ${t}: ${o instanceof Error?o.message:String(o)}`}}}async validateVisibility(t,s,r,o,n){try{return r?(await(0,N.expect)(t).toBeVisible({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} is visible as expected. Test: "${n}".`}):(await(0,N.expect)(t).toBeHidden({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} is not visible as expected. Test: "${n}".`})}catch{let u=this.selectors[s]||"",i=await this.page.evaluate(R=>{let C=R?document.querySelector(R):null;if(!C)return"element not found";let A=window.getComputedStyle(C);return`display:${A.display}, visibility:${A.visibility}, opacity:${A.opacity}`},u);return r?{success:!1,failMessage:`${o} (actual: ${i})`}:{success:!1,failMessage:`${o} ${s} is still visible (actual: ${i}).`}}}async validateAttribute(t,s,r,o,n,u){if(o==="!empty"){let C=await t.getAttribute(r);return C&&C.trim()!==""?{success:!0,passMessage:`${s} has non-empty "${r}". Test: "${u}".`}:{success:!1,failMessage:`${n} ${s} "${r}" should not be empty, found "${C}".`}}if(typeof o!="string")throw console.error("[AssertionRunner] expectedValue is not a string:",o),new Error(`AssertionRunner: expectedValue for attribute assertion must be a string, but got: ${JSON.stringify(o)}`);let i=o.split(" | ").map(C=>C.trim()),R=await t.getAttribute(r);return R!==null&&i.includes(R)?{success:!0,passMessage:`${s} has expected "${r}". Test: "${u}".`}:{success:!1,failMessage:`${n} ${s} "${r}" should be "${o}", found "${R}".`}}async validateValue(t,s,r,o,n){let u=await t.inputValue().catch(()=>"");return r==="!empty"?u&&u.trim()!==""?{success:!0,passMessage:`${s} has non-empty value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should not be empty, found "${u}".`}:r===""?u===""?{success:!0,passMessage:`${s} has empty value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should be empty, found "${u}".`}:u===r?{success:!0,passMessage:`${s} has expected value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should be "${r}", found "${u}".`}}async validateFocus(t,s,r,o,n){try{return r?(await(0,N.expect)(t).toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} has focus as expected. Test: "${n}".`}):(await(0,N.expect)(t).not.toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} does not have focus as expected. Test: "${n}".`})}catch{let u=await this.page.evaluate(()=>{let i=document.activeElement;return i?`${i.tagName}#${i.id||"no-id"}.${i.className||"no-class"}`:"no element focused"});return{success:!1,failMessage:`${o} (actual focus: ${u})`}}}async validateRole(t,s,r,o,n){let u=await t.getAttribute("role");return u===r?{success:!0,passMessage:`${s} has role "${r}". Test: "${n}".`}:{success:!1,failMessage:`${o} Expected role "${r}", found "${u}".`}}async validate(t,s){if(this.page.isClosed())return{success:!1,failMessage:"CRITICAL: Browser/page closed before completing all tests. Increase test timeout or reduce test complexity."};let r=null,o;if(t.controlledBy){let n=t.controlledBy,u=this.selectors[n.target];if(!u)return{success:!1,failMessage:`Selector for controlledBy.target '${n.target}' not found.`,target:null};let i=null;if(n.relativeTarget?i=await j.resolve(this.page,u,n.relativeTarget):i=this.page.locator(u).first(),!i)return{success:!1,failMessage:"Controlling element for controlledBy not found.",target:null};let R=n.attribute||"aria-controls",C=await i.getAttribute(R);if(!C)return{success:!1,failMessage:`Controlling element does not have attribute '${R}'.`,target:null};if(r=this.page.locator(`#${C}`),!r||await r.count()===0)return{success:!1,failMessage:`Controlled element with id '${C}' not found.`,target:null}}else{let n=await this.resolveTarget(t.target,t.relativeTarget||t.expectedValue,t.selectorKey);if(r=n.target,o=n.error,o||!r)return{success:!1,failMessage:o||`Target ${t.target} not found.`,target:null}}if(t.target==="input"&&t.attribute==="aria-activedescendant"&&t.expectedValue==="!empty"&&t.relativeTarget&&t.selectorKey){let n=await j.resolve(this.page,this.selectors[t.selectorKey],t.relativeTarget),u=n?await n.getAttribute("id"):null,i=await r.getAttribute("aria-activedescendant");return u&&i===u?{success:!0,passMessage:`input[aria-activedescendant] matches id of ${t.relativeTarget}(${t.selectorKey}). Test: "${s}".`}:{success:!1,failMessage:`input[aria-activedescendant] should match id of ${t.relativeTarget}(${t.selectorKey}), found "${i}".`}}switch(t.assertion){case"toBeVisible":return this.validateVisibility(r,t.target,!0,t.failureMessage||"",s);case"notToBeVisible":return this.validateVisibility(r,t.target,!1,t.failureMessage||"",s);case"toHaveAttribute":return t.attribute&&t.expectedValue!==void 0?this.validateAttribute(r,t.target,t.attribute,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing attribute or expectedValue for toHaveAttribute assertion"};case"toHaveValue":return t.expectedValue!==void 0?this.validateValue(r,t.target,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing expectedValue for toHaveValue assertion"};case"toHaveFocus":return this.validateFocus(r,t.target,!0,t.failureMessage||"",s);case"notToHaveFocus":return this.validateFocus(r,t.target,!1,t.failureMessage||"",s);case"toHaveRole":return t.expectedValue!==void 0?this.validateRole(r,t.target,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing expectedValue for toHaveRole assertion"};default:return{success:!1,failMessage:`Unknown assertion type: ${t.assertion}`}}}};async function tt(M,t,s,r,o){let n=r?.test?.components?.find(d=>d.name===M),u=!!n?.contractPath,i=new ce(!0,u),R={actionTimeoutMs:400,assertionTimeoutMs:400,navigationTimeoutMs:3e4,componentReadyTimeoutMs:5e3},C=r?.test?.disableTimeouts===!0,te=n?.disableTimeouts===!0||C,_=(d,H,O)=>{if(te)return 0;let F=d??H;return typeof F!="number"||!Number.isFinite(F)||F<0?O:F},z=_(n?.actionTimeoutMs,r?.test?.actionTimeoutMs,R.actionTimeoutMs),X=_(n?.assertionTimeoutMs,r?.test?.assertionTimeoutMs,R.assertionTimeoutMs),ie=_(n?.navigationTimeoutMs,r?.test?.navigationTimeoutMs,R.navigationTimeoutMs),le=_(n?.componentReadyTimeoutMs,r?.test?.componentReadyTimeoutMs,R.componentReadyTimeoutMs),me=Se(s),Y=n?.contractPath;if(!Y)throw new Error(`Contract path not found for component: ${M}`);let Re=(()=>{if(he.isAbsolute(Y))return Y;if(o){let H=he.resolve(o,Y);try{return de(H,"utf-8"),H}catch{}}let d=he.resolve(process.cwd(),Y);try{return de(d,"utf-8"),d}catch{return new URL(Y,import.meta.url).pathname}})(),Ae=de(Re,"utf-8"),b=JSON.parse(Ae),Me=(b.relationships?.length||0)+(b.static[0]?.assertions.length||0)+b.dynamic.length,Ee=b.meta?.source?.apg,V=[],K=[],q=[],x=[],y=null,E=(d,H)=>{let O=Q(H),F=ke(O,me);if(F==="error")return V.push(d),{status:"fail",level:O,detail:d};if(F==="warning")return K.push(d),{status:"warn",level:O,detail:d};let D=`${d} (ignored by strictness=${me}, level=${O})`;return x.push(D),{status:"skip",level:O,detail:D}};try{if(y=await Te(),t){try{await y.goto(t,{waitUntil:"domcontentloaded",timeout:ie})}catch(e){throw new Error(`Failed to navigate to ${t}. Ensure dev server is running and accessible. Original error: ${e instanceof Error?e.message:String(e)}`)}await y.addStyleTag({content:"* { transition: none !important; animation: none !important; }"})}let d=await ae.detect(M,n,z,X,o);if(!d)throw new Error(`Unsupported component: ${M}`);let H=d.getMainSelector();if(!H)throw new Error(`CRITICAL: No selector found in contract for ${M}`);try{await y.locator(H).first().waitFor({state:"attached",timeout:le})}catch(e){throw new Error(`
22
+ \u274C Error: ${t}`),s&&this.log(` Context: ${s}`),this.log("")}};var ee=class{constructor(t,s,r=400){this.page=t;this.selectors=s;this.timeoutMs=r}isBrowserClosedError(t){return t instanceof Error&&t.message.includes("Target page, context or browser has been closed")}async focus(t,s,r){try{if(t==="virtual"&&r){let n=this.selectors.main;if(!n)return{success:!1,error:"Main selector not defined for virtual focus."};let u=this.page.locator(n).first();return await u.count()?(await u.evaluate((R,C)=>{R.setAttribute("aria-activedescendant",C)},r),{success:!0}):{success:!1,error:"Main element not found for virtual focus."}}if(t==="relative"&&s){let n=this.selectors.relative;if(!n)return{success:!1,error:"Relative selector not defined for focus action."};let u=await j.resolve(this.page,n,s);return u?(await u.focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for focus.`}}let o=this.selectors[t];return o?(await this.page.locator(o).first().focus({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for focus target ${t} not found.`}}catch(o){return this.isBrowserClosedError(o)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to focus ${t}: ${o instanceof Error?o.message:String(o)}`}}}async type(t,s){try{let r=this.selectors[t];return r?(await this.page.locator(r).first().fill(s,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for type target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to type into ${t}: ${r instanceof Error?r.message:String(r)}`}}}async click(t,s){try{if(t==="document")return await this.page.mouse.click(10,10),{success:!0};if(t==="relative"&&s){let o=this.selectors.relative;if(!o)return{success:!1,error:"Relative selector not defined for click action."};let n=await j.resolve(this.page,o,s);return n?(await n.click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for click.`}}let r=this.selectors[t];return r?(await this.page.locator(r).first().click({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for action target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to click ${t}: ${r instanceof Error?r.message:String(r)}`}}}async keypress(t,s,r){try{let n={Space:"Space",Enter:"Enter",Escape:"Escape","Arrow Up":"ArrowUp","Arrow Down":"ArrowDown","Arrow Left":"ArrowLeft","Arrow Right":"ArrowRight",Home:"Home",End:"End",Tab:"Tab"}[s]||s;if(n==="Space"?n=" ":n.includes(" ")&&(n=n.replace(/ /g,"")),t==="relative"){if(r==null)return{success:!1,error:"relativeTarget must be provided for relative keypress."};let C=this.selectors.relative;if(!C)return{success:!1,error:"Relative selector not defined for keypress action."};let A=await j.resolve(this.page,C,r);return A?(await A.press(n,{timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${r} for keypress.`}}let u=this.selectors[t];if(!u)return{success:!1,error:`Selector for keypress target ${t} not found.`};let i=this.page.locator(u).first();return await i.count()===0?{success:!1,error:`${t} element not found.`,shouldBreak:!0}:(await i.press(n,{timeout:this.timeoutMs}),{success:!0})}catch(o){return this.isBrowserClosedError(o)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to press ${s} on ${t}: ${o instanceof Error?o.message:String(o)}`}}}async hover(t,s){try{if(t==="relative"&&s){let o=this.selectors.relative;if(!o)return{success:!1,error:"Relative selector not defined for hover action."};let n=await j.resolve(this.page,o,s);return n?(await n.hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Could not resolve relative target ${s} for hover.`}}let r=this.selectors[t];return r?(await this.page.locator(r).first().hover({timeout:this.timeoutMs}),{success:!0}):{success:!1,error:`Selector for hover target ${t} not found.`}}catch(r){return this.isBrowserClosedError(r)?{success:!1,error:"CRITICAL: Browser/page closed during test execution. Remaining actions skipped.",shouldBreak:!0}:{success:!1,error:`Failed to hover ${t}: ${r instanceof Error?r.message:String(r)}`}}}};var re=class{constructor(t,s,r=400){this.page=t;this.selectors=s;this.timeoutMs=r}async resolveTarget(t,s,r){try{if(t==="relative"){let n=r?this.selectors[r]:this.selectors.relative;if(!n)return{target:null,error:"Relative selector is not defined in the contract."};if(!s)return{target:null,error:"Relative target or expected value is not defined."};let u=await j.resolve(this.page,n,s);return u?{target:u}:{target:null,error:`Target ${t} not found.`}}let o=this.selectors[t];return o?{target:this.page.locator(o).first()}:{target:null,error:`Selector for assertion target ${t} not found.`}}catch(o){return{target:null,error:`Failed to resolve target ${t}: ${o instanceof Error?o.message:String(o)}`}}}async validateVisibility(t,s,r,o,n){try{return r?(await(0,N.expect)(t).toBeVisible({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} is visible as expected. Test: "${n}".`}):(await(0,N.expect)(t).toBeHidden({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} is not visible as expected. Test: "${n}".`})}catch{let u=this.selectors[s]||"",i=await this.page.evaluate(R=>{let C=R?document.querySelector(R):null;if(!C)return"element not found";let A=window.getComputedStyle(C);return`display:${A.display}, visibility:${A.visibility}, opacity:${A.opacity}`},u);return r?{success:!1,failMessage:`${o} (actual: ${i})`}:{success:!1,failMessage:`${o} ${s} is still visible (actual: ${i}).`}}}async validateAttribute(t,s,r,o,n,u){if(o==="!empty"){let C=await t.getAttribute(r);return C&&C.trim()!==""?{success:!0,passMessage:`${s} has non-empty "${r}". Test: "${u}".`}:{success:!1,failMessage:`${n} ${s} "${r}" should not be empty, found "${C}".`}}if(typeof o!="string")throw console.error("[AssertionRunner] expectedValue is not a string:",o),new Error(`AssertionRunner: expectedValue for attribute assertion must be a string, but got: ${JSON.stringify(o)}`);let i=o.split(" | ").map(C=>C.trim()),R=await t.getAttribute(r);return R!==null&&i.includes(R)?{success:!0,passMessage:`${s} has expected "${r}". Test: "${u}".`}:{success:!1,failMessage:`${n} ${s} "${r}" should be "${o}", found "${R}".`}}async validateValue(t,s,r,o,n){let u=await t.inputValue().catch(()=>"");return r==="!empty"?u&&u.trim()!==""?{success:!0,passMessage:`${s} has non-empty value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should not be empty, found "${u}".`}:r===""?u===""?{success:!0,passMessage:`${s} has empty value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should be empty, found "${u}".`}:u===r?{success:!0,passMessage:`${s} has expected value. Test: "${n}".`}:{success:!1,failMessage:`${o} ${s} value should be "${r}", found "${u}".`}}async validateFocus(t,s,r,o,n){try{return r?(await(0,N.expect)(t).toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} has focus as expected. Test: "${n}".`}):(await(0,N.expect)(t).not.toBeFocused({timeout:this.timeoutMs}),{success:!0,passMessage:`${s} does not have focus as expected. Test: "${n}".`})}catch{let u=await this.page.evaluate(()=>{let i=document.activeElement;return i?`${i.tagName}#${i.id||"no-id"}.${i.className||"no-class"}`:"no element focused"});return{success:!1,failMessage:`${o} (actual focus: ${u})`}}}async validateRole(t,s,r,o,n){let u=await t.getAttribute("role");return u===r?{success:!0,passMessage:`${s} has role "${r}". Test: "${n}".`}:{success:!1,failMessage:`${o} Expected role "${r}", found "${u}".`}}async validate(t,s){if(this.page.isClosed())return{success:!1,failMessage:"CRITICAL: Browser/page closed before completing all tests. Increase test timeout or reduce test complexity."};let r=null,o;if(t.controlledBy){let n=t.controlledBy,u=this.selectors[n.target];if(!u)return{success:!1,failMessage:`Selector for controlledBy.target '${n.target}' not found.`,target:null};let i=null;if(n.relativeTarget?i=await j.resolve(this.page,u,n.relativeTarget):i=this.page.locator(u).first(),!i)return{success:!1,failMessage:"Controlling element for controlledBy not found.",target:null};let R=n.attribute||"aria-controls",C=await i.getAttribute(R);if(!C)return{success:!1,failMessage:`Controlling element does not have attribute '${R}'.`,target:null};if(r=this.page.locator(`#${C}`),!r||await r.count()===0)return{success:!1,failMessage:`Controlled element with id '${C}' not found.`,target:null}}else{let n=await this.resolveTarget(t.target,t.relativeTarget||t.expectedValue,t.selectorKey);if(r=n.target,o=n.error,o||!r)return{success:!1,failMessage:o||`Target ${t.target} not found.`,target:null}}if(t.target==="input"&&t.attribute==="aria-activedescendant"&&t.expectedValue==="!empty"&&t.relativeTarget&&t.selectorKey){let n=await j.resolve(this.page,this.selectors[t.selectorKey],t.relativeTarget),u=n?await n.getAttribute("id"):null,i=await r.getAttribute("aria-activedescendant");return u&&i===u?{success:!0,passMessage:`input[aria-activedescendant] matches id of ${t.relativeTarget}(${t.selectorKey}). Test: "${s}".`}:{success:!1,failMessage:`input[aria-activedescendant] should match id of ${t.relativeTarget}(${t.selectorKey}), found "${i}".`}}switch(t.assertion){case"toBeVisible":return this.validateVisibility(r,t.target,!0,t.failureMessage||"",s);case"notToBeVisible":return this.validateVisibility(r,t.target,!1,t.failureMessage||"",s);case"toHaveAttribute":return t.attribute&&t.expectedValue!==void 0?this.validateAttribute(r,t.target,t.attribute,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing attribute or expectedValue for toHaveAttribute assertion"};case"toHaveValue":return t.expectedValue!==void 0?this.validateValue(r,t.target,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing expectedValue for toHaveValue assertion"};case"toHaveFocus":return this.validateFocus(r,t.target,!0,t.failureMessage||"",s);case"notToHaveFocus":return this.validateFocus(r,t.target,!1,t.failureMessage||"",s);case"toHaveRole":return t.expectedValue!==void 0?this.validateRole(r,t.target,t.expectedValue,t.failureMessage||"",s):{success:!1,failMessage:"Missing expectedValue for toHaveRole assertion"};default:return{success:!1,failMessage:`Unknown assertion type: ${t.assertion}`}}}};async function tt(M,t,s,r,o){let n=r?.test?.components?.find(d=>d.name===M),u=!!n?.contractPath,i=new ce(!0,u),R={actionTimeoutMs:400,assertionTimeoutMs:400,navigationTimeoutMs:3e4,componentReadyTimeoutMs:5e3},C=r?.test?.disableTimeouts===!0,te=n?.disableTimeouts===!0||C,_=(d,H,O)=>{if(te)return 0;let F=d??H;return typeof F!="number"||!Number.isFinite(F)||F<0?O:F},z=_(n?.actionTimeoutMs,r?.test?.actionTimeoutMs,R.actionTimeoutMs),X=_(n?.assertionTimeoutMs,r?.test?.assertionTimeoutMs,R.assertionTimeoutMs),ie=_(n?.navigationTimeoutMs,r?.test?.navigationTimeoutMs,R.navigationTimeoutMs),le=_(n?.componentReadyTimeoutMs,r?.test?.componentReadyTimeoutMs,R.componentReadyTimeoutMs),me=Se(s),Y=n?.contractPath;if(!Y)throw new Error(`Contract path not found for component: ${M}`);let Re=(()=>{if(he.isAbsolute(Y))return Y;if(o){let H=he.resolve(o,Y);try{return de(H,"utf-8"),H}catch{}}let d=he.resolve(process.cwd(),Y);try{return de(d,"utf-8"),d}catch{return new URL(Y,import.meta.url).pathname}})(),Ae=de(Re,"utf-8"),b=JSON.parse(Ae),Me=(b.relationships?.length||0)+(b.static.length||0)+b.dynamic.length,Ee=b.meta?.source?.apg,V=[],K=[],q=[],x=[],y=null,E=(d,H)=>{let O=Q(H),F=ke(O,me);if(F==="error")return V.push(d),{status:"fail",level:O,detail:d};if(F==="warning")return K.push(d),{status:"warn",level:O,detail:d};let D=`${d} (ignored by strictness=${me}, level=${O})`;return x.push(D),{status:"skip",level:O,detail:D}};try{if(y=await Te(),t){try{await y.goto(t,{waitUntil:"domcontentloaded",timeout:ie})}catch(e){throw new Error(`Failed to navigate to ${t}. Ensure dev server is running and accessible. Original error: ${e instanceof Error?e.message:String(e)}`)}await y.addStyleTag({content:"* { transition: none !important; animation: none !important; }"})}let d=await ae.detect(M,n,z,X,o);if(!d)throw new Error(`Unsupported component: ${M}`);let H=d.getMainSelector();if(!H)throw new Error(`CRITICAL: No selector found in contract for ${M}`);try{await y.locator(H).first().waitFor({state:"attached",timeout:le})}catch(e){throw new Error(`
23
23
  \u274C CRITICAL: Component not found on page!
24
24
  This usually means:
25
25
  - The component didn't render
26
26
  - The URL is incorrect
27
27
  - The component selector '${H}' in the contract is wrong
28
- - Original error: ${e}`)}i.start(M,Me,Ee),M==="menu"&&b.selectors.main&&await y.locator(b.selectors.main).first().waitFor({state:"visible",timeout:le}).catch(()=>{});let O=M==="menu"&&b.selectors.submenuTrigger?await y.locator(b.selectors.submenuTrigger).count()>0:!1,F=e=>e.type==="aria-reference"&&[e.from,e.to].some(p=>["submenu","submenuTrigger","submenuItems"].includes(p||""))||e.type==="contains"&&[e.parent,e.child].some(p=>["submenu","submenuTrigger","submenuItems"].includes(p||"")),D=0,P=0,I=0;for(let e of b.relationships||[]){if(d&&typeof d.resetState=="function")try{await d.resetState(y)}catch(g){K.push(`Warning: resetState failed before relationship test: ${g instanceof Error?g.message:String(g)}`)}let p=Q(e.level);if(Array.isArray(e.setup)&&e.setup.length>0){let w=function(l){return h.includes(l)};var ve=w;let g=new ee(y,b.selectors,z),S=e.type==="aria-reference"?`${e.from}.${e.attribute} references ${e.to}`:`${e.parent} contains ${e.child}`,h=["focus","type","click","keypress","hover"],m=l=>({...l,type:w(l.type)?l.type:"click"}),$=e.setup.map(m),k=await ue($,g,d,y,S,["submenu","submenuTrigger","submenuItems"]);if(k.skip){x.push(k.message||"Setup action skipped"),i.reportStaticTest(S,"skip",k.message,p);continue}if(!k.success){let l=`Relationship setup failed: ${k.error}`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(S,c.status,c.detail,c.level);continue}}if(M==="menu"&&!O&&F(e)){let S=e.type==="aria-reference"?`${e.from}.${e.attribute} references ${e.to}`:`${e.parent} contains ${e.child}`,h="Skipping submenu relationship assertion: no submenu capability detected in rendered component.";x.push(h),i.reportStaticTest(S,"skip",h,p);continue}if(e.type==="aria-reference"){let g=`${e.from}.${e.attribute} references ${e.to}`,S=b.selectors[e.from],h=b.selectors[e.to];if(!S||!h){let f=E(`Relationship selector missing: from="${e.from}" or to="${e.to}" not found in selectors.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}let w=y.locator(S).first(),m=y.locator(h).first(),$=await w.count()>0,k=await m.count()>0;if(!$||!k){if(M==="menu"&&F(e)){let B="Skipping submenu relationship assertion in static phase: submenu elements are not present until submenu is opened.";x.push(B),i.reportStaticTest(g,"skip",B,p);continue}let f=E(`Relationship target not found: ${$?e.to:e.from}.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}let l=await w.getAttribute(e.attribute),c=await m.getAttribute("id");if(!c){let f=E(`Relationship target "${e.to}" must have an id for ${e.attribute} validation.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}if(!(l||"").split(/\s+/).filter(Boolean).includes(c)){let f=E(`Expected ${e.from} ${e.attribute} to reference id "${c}", found "${l||""}".`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}q.push(`Relationship valid: ${e.from}.${e.attribute} -> ${e.to} (id=${c}).`),D+=1,i.reportStaticTest(g,"pass",void 0,p);continue}if(e.type==="contains"){let g=`${e.parent} contains ${e.child}`,S=b.selectors[e.parent],h=b.selectors[e.child];if(!S||!h){let l=E(`Relationship selector missing: parent="${e.parent}" or child="${e.child}" not found in selectors.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}let w=y.locator(S).first();if(!(await w.count()>0)){if(M==="menu"&&F(e)){let c="Skipping submenu relationship assertion in static phase: submenu container is not present until submenu is opened.";x.push(c),i.reportStaticTest(g,"skip",c,p);continue}let l=E(`Relationship parent target not found: ${e.parent}.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}if(await w.locator(h).count()<1){if(M==="menu"&&F(e)){let c="Skipping submenu relationship assertion in static phase: submenu descendants are not present until submenu is opened.";x.push(c),i.reportStaticTest(g,"skip",c,p);continue}let l=E(`Expected ${e.parent} to contain descendant matching selector for ${e.child}.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}q.push(`Relationship valid: ${e.parent} contains ${e.child}.`),D+=1,i.reportStaticTest(g,"pass",void 0,p)}}async function ye(e,p,g,S={}){if(!e||typeof e!="object"||!("ref"in e))return e;let h;if(e.ref==="relative"){if(!e.relativeTarget||!S.relativeBaseSelector)return;let w=g.locator(S.relativeBaseSelector),m=await w.count(),$=0;if(e.relativeTarget==="first"?$=0:e.relativeTarget==="second"?$=1:e.relativeTarget==="last"?$=m-1:isNaN(Number(e.relativeTarget))?$=0:$=Number(e.relativeTarget),$<0||$>=m)return;let k=w.nth($);return await we(k,e.property||e.attribute)}else{if(h=p[e.ref],!h)throw new Error(`Selector for ref '${e.ref}' not found in contract selectors.`);let w=g.locator(h).first();return await we(w,e.property||e.attribute)}}async function we(e,p){if(e)return!p||p==="id"?await e.getAttribute("id")??void 0:p==="class"?await e.getAttribute("class")??void 0:p==="textContent"?await e.evaluate(g=>g.textContent??void 0):p.startsWith("aria-")?await e.getAttribute(p)??void 0:p.endsWith("*")?await e.evaluate(S=>{let h=[];for(let w of Array.from(S.attributes))w.name.startsWith("aria-")&&h.push(`${w.name}=${w.value}`);return h.join(";")}):await e.getAttribute(p)??void 0}let xe=new re(y,b.selectors,X);async function ue(e,p,g,S,h,w=[]){if(!Array.isArray(e)||e.length===0)return{success:!0};g&&typeof g.resetState=="function"&&await g.resetState(S);for(let m of e){let $={success:!0};try{if(m.type==="focus")m.target==="relative"&&m.relativeTarget?$=await p.focus("relative",m.relativeTarget):$=await p.focus(m.target);else if(m.type==="type"&&m.value)$=await p.type(m.target,m.value);else if(m.type==="click")$=await p.click(m.target,m.relativeTarget);else if(m.type==="keypress"&&m.key)$=await p.keypress(m.target,m.key,m.relativeTarget);else if(m.type==="hover")$=await p.hover(m.target,m.relativeTarget);else continue}catch(k){$={success:!1,error:k instanceof Error?k.message:String(k)}}if(!$.success){let k=$.error||"Setup action failed";return w.some(c=>h.includes(c)||k.includes(c))?{success:!1,skip:!0,message:`Skipping test - capability not present: ${k}`}:{success:!1,error:k}}}return{success:!0}}for(let e of b.static[0]?.assertions||[]){if(d&&typeof d.resetState=="function")try{await d.resetState(y)}catch(l){K.push(`Warning: resetState failed before static test: ${l instanceof Error?l.message:String(l)}`)}if(e.target==="relative")continue;let p=`${e.target}${e.attribute?` (${e.attribute})`:""}`,g=Q(e.level);if(M==="menu"&&e.target==="submenuTrigger"&&!O){let l=`Skipping submenu static assertion for ${e.target}: no submenu capability detected in rendered component.`;x.push(l),i.reportStaticTest(p,"skip",l,g);continue}let S=[];if(e.target||S.push("target"),e.attribute||S.push("attribute"),typeof e.expectedValue>"u"&&S.push("expectedValue"),S.length>0){let l=`${e.target||""}${e.attribute?` (${e.attribute})`:""}`,c=`Static assertion missing required field(s): ${S.join(", ")}`,v=E(c,e.level);v.status==="fail"&&(P+=1),v.status==="warn"&&(I+=1),i.reportStaticTest(l,v.status,v.detail,v.level);continue}if(Array.isArray(e.setup)&&e.setup.length>0){let v=function(a){return c.includes(a)};var ve=v;let l=new ee(y,b.selectors,z),c=["focus","type","click","keypress","hover"],U=a=>({...a,type:v(a.type)?a.type:"click"}),f=e.setup.map(U),B=await ue(f,l,d,y,p,["submenu","submenuTrigger","submenuItems"]);if(B.skip){x.push(B.message||"Setup action skipped"),i.reportStaticTest(p,"skip",B.message,g);continue}if(!B.success){let a=`Static setup failed: ${B.error}`,T=E(a,e.level);T.status==="fail"&&(P+=1),T.status==="warn"&&(I+=1),i.reportStaticTest(p,T.status,T.detail,T.level);continue}}let h=b.selectors[e.target];if(!h){let l=`Selector for target ${e.target} not found.`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(p,c.status,c.detail,c.level);continue}let w=y.locator(h).first();if(!(await w.count()>0)){let l=`Target ${e.target} not found.`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(p,c.status,c.detail,c.level);continue}let $=(l,c,v)=>{let U=new RegExp(`\\[${c}(?:=["']?([^\\]"']+)["']?)?\\]`),f=l.match(U);if(!f)return!1;if(!v)return!0;let B=f[1];return B?v.split(" | ").includes(B):!1},k=e.expectedValue;if(e.expectedValue&&typeof e.expectedValue=="object"&&"ref"in e.expectedValue){let l={},c=e.relativeTarget;if(e.expectedValue.ref==="relative"&&e.target==="relative"&&c){let v=b.selectors[c];if(!v)throw new Error(`Selector for relativeTarget '${c}' not found in contract selectors.`);l.relativeBaseSelector=v}else if(e.expectedValue.ref==="relative"&&c){let v=b.selectors[c];if(!v)throw new Error(`Selector for relativeTarget '${c}' not found in contract selectors.`);l.relativeBaseSelector=v}k=await ye(e.expectedValue,b.selectors,y,l)}if(e.expectedValue)if($(h,e.attribute,typeof k=="string"?k:void 0))q.push(`${e.attribute}="${k}" on ${e.target} verified by selector (already present in: ${h}).`),D+=1,i.reportStaticTest(p,"pass",void 0,g);else{let l=k??"",c=await xe.validateAttribute(w,e.target,e.attribute,l,e.failureMessage,"Static ARIA Test");if(c.success&&c.passMessage)q.push(c.passMessage),D+=1,i.reportStaticTest(p,"pass",void 0,g);else if(!c.success&&c.failMessage){let v=E(c.failMessage,e.level);v.status==="fail"&&(P+=1),v.status==="warn"&&(I+=1),i.reportStaticTest(p,v.status,v.detail,v.level)}}else{let l=e.attribute.split(" | "),c=!1,v=!0;for(let U of l){let f=U.trim();if($(h,f)){q.push(`${f} on ${e.target} verified by selector (already present in: ${h}).`),c=!0;continue}if(v=!1,await w.getAttribute(f)!==null){c=!0;break}}if(!c&&!v){let U=e.failureMessage+` None of the attributes "${e.attribute}" are present.`,f=E(U,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(p,f.status,f.detail,f.level)}else!v&&c?(q.push(`At least one of the attributes "${e.attribute}" exists on the element.`),D+=1,i.reportStaticTest(p,"pass",void 0,g)):(D+=1,i.reportStaticTest(p,"pass",void 0,g))}}for(let e of b.dynamic||[]){if(!e.assertions||e.assertions.length===0){let a="Skipping test - no assertions found for this dynamic test.";x.push(a),i.reportTest({description:e.description,level:Q(e.level)},"skip",a);continue}if(!y||y.isClosed()){console.warn(`
28
+ - Original error: ${e}`)}i.start(M,Me,Ee),M==="menu"&&b.selectors.main&&await y.locator(b.selectors.main).first().waitFor({state:"visible",timeout:le}).catch(()=>{});let O=M==="menu"&&b.selectors.submenuTrigger?await y.locator(b.selectors.submenuTrigger).count()>0:!1,F=e=>e.type==="aria-reference"&&[e.from,e.to].some(p=>["submenu","submenuTrigger","submenuItems"].includes(p||""))||e.type==="contains"&&[e.parent,e.child].some(p=>["submenu","submenuTrigger","submenuItems"].includes(p||"")),D=0,P=0,I=0;for(let e of b.relationships||[]){if(d&&typeof d.resetState=="function")try{await d.resetState(y)}catch(g){K.push(`Warning: resetState failed before relationship test: ${g instanceof Error?g.message:String(g)}`)}let p=Q(e.level);if(Array.isArray(e.setup)&&e.setup.length>0){let w=function(l){return h.includes(l)};var ve=w;let g=new ee(y,b.selectors,z),S=e.type==="aria-reference"?`${e.from}.${e.attribute} references ${e.to}`:`${e.parent} contains ${e.child}`,h=["focus","type","click","keypress","hover"],m=l=>({...l,type:w(l.type)?l.type:"click"}),$=e.setup.map(m),k=await ue($,g,d,y,S,["submenu","submenuTrigger","submenuItems"]);if(k.skip){x.push(k.message||"Setup action skipped"),i.reportStaticTest(S,"skip",k.message,p);continue}if(!k.success){let l=`Relationship setup failed: ${k.error}`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(S,c.status,c.detail,c.level);continue}}if(M==="menu"&&!O&&F(e)){let S=e.type==="aria-reference"?`${e.from}.${e.attribute} references ${e.to}`:`${e.parent} contains ${e.child}`,h="Skipping submenu relationship assertion: no submenu capability detected in rendered component.";x.push(h),i.reportStaticTest(S,"skip",h,p);continue}if(e.type==="aria-reference"){let g=`${e.from}.${e.attribute} references ${e.to}`,S=b.selectors[e.from],h=b.selectors[e.to];if(!S||!h){let f=E(`Relationship selector missing: from="${e.from}" or to="${e.to}" not found in selectors.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}let w=y.locator(S).first(),m=y.locator(h).first(),$=await w.count()>0,k=await m.count()>0;if(!$||!k){if(M==="menu"&&F(e)){let B="Skipping submenu relationship assertion in static phase: submenu elements are not present until submenu is opened.";x.push(B),i.reportStaticTest(g,"skip",B,p);continue}let f=E(`Relationship target not found: ${$?e.to:e.from}.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}let l=await w.getAttribute(e.attribute),c=await m.getAttribute("id");if(!c){let f=E(`Relationship target "${e.to}" must have an id for ${e.attribute} validation.`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}if(!(l||"").split(/\s+/).filter(Boolean).includes(c)){let f=E(`Expected ${e.from} ${e.attribute} to reference id "${c}", found "${l||""}".`,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(g,f.status,f.detail,f.level);continue}q.push(`Relationship valid: ${e.from}.${e.attribute} -> ${e.to} (id=${c}).`),D+=1,i.reportStaticTest(g,"pass",void 0,p);continue}if(e.type==="contains"){let g=`${e.parent} contains ${e.child}`,S=b.selectors[e.parent],h=b.selectors[e.child];if(!S||!h){let l=E(`Relationship selector missing: parent="${e.parent}" or child="${e.child}" not found in selectors.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}let w=y.locator(S).first();if(!(await w.count()>0)){if(M==="menu"&&F(e)){let c="Skipping submenu relationship assertion in static phase: submenu container is not present until submenu is opened.";x.push(c),i.reportStaticTest(g,"skip",c,p);continue}let l=E(`Relationship parent target not found: ${e.parent}.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}if(await w.locator(h).count()<1){if(M==="menu"&&F(e)){let c="Skipping submenu relationship assertion in static phase: submenu descendants are not present until submenu is opened.";x.push(c),i.reportStaticTest(g,"skip",c,p);continue}let l=E(`Expected ${e.parent} to contain descendant matching selector for ${e.child}.`,e.level);l.status==="fail"&&(P+=1),l.status==="warn"&&(I+=1),i.reportStaticTest(g,l.status,l.detail,l.level);continue}q.push(`Relationship valid: ${e.parent} contains ${e.child}.`),D+=1,i.reportStaticTest(g,"pass",void 0,p)}}async function ye(e,p,g,S={}){if(!e||typeof e!="object"||!("ref"in e))return e;let h;if(e.ref==="relative"){if(!e.relativeTarget||!S.relativeBaseSelector)return;let w=g.locator(S.relativeBaseSelector),m=await w.count(),$=0;if(e.relativeTarget==="first"?$=0:e.relativeTarget==="second"?$=1:e.relativeTarget==="last"?$=m-1:isNaN(Number(e.relativeTarget))?$=0:$=Number(e.relativeTarget),$<0||$>=m)return;let k=w.nth($);return await we(k,e.property||e.attribute)}else{if(h=p[e.ref],!h)throw new Error(`Selector for ref '${e.ref}' not found in contract selectors.`);let w=g.locator(h).first();return await we(w,e.property||e.attribute)}}async function we(e,p){if(e)return!p||p==="id"?await e.getAttribute("id")??void 0:p==="class"?await e.getAttribute("class")??void 0:p==="textContent"?await e.evaluate(g=>g.textContent??void 0):p.startsWith("aria-")?await e.getAttribute(p)??void 0:p.endsWith("*")?await e.evaluate(S=>{let h=[];for(let w of Array.from(S.attributes))w.name.startsWith("aria-")&&h.push(`${w.name}=${w.value}`);return h.join(";")}):await e.getAttribute(p)??void 0}let xe=new re(y,b.selectors,X);async function ue(e,p,g,S,h,w=[]){if(!Array.isArray(e)||e.length===0)return{success:!0};g&&typeof g.resetState=="function"&&await g.resetState(S);for(let m of e){let $={success:!0};try{if(m.type==="focus")m.target==="relative"&&m.relativeTarget?$=await p.focus("relative",m.relativeTarget):$=await p.focus(m.target);else if(m.type==="type"&&m.value)$=await p.type(m.target,m.value);else if(m.type==="click")$=await p.click(m.target,m.relativeTarget);else if(m.type==="keypress"&&m.key)$=await p.keypress(m.target,m.key,m.relativeTarget);else if(m.type==="hover")$=await p.hover(m.target,m.relativeTarget);else continue}catch(k){$={success:!1,error:k instanceof Error?k.message:String(k)}}if(!$.success){let k=$.error||"Setup action failed";return w.some(c=>h.includes(c)||k.includes(c))?{success:!1,skip:!0,message:`Skipping test - capability not present: ${k}`}:{success:!1,error:k}}}return{success:!0}}for(let e of b.static||[]){if(d&&typeof d.resetState=="function")try{await d.resetState(y)}catch(l){K.push(`Warning: resetState failed before static test: ${l instanceof Error?l.message:String(l)}`)}if(e.target==="relative")continue;let p=`${e.target}${e.attribute?` (${e.attribute})`:""}`,g=Q(e.level);if(M==="menu"&&e.target==="submenuTrigger"&&!O){let l=`Skipping submenu static assertion for ${e.target}: no submenu capability detected in rendered component.`;x.push(l),i.reportStaticTest(p,"skip",l,g);continue}let S=[];if(e.target||S.push("target"),e.attribute||S.push("attribute"),typeof e.expectedValue>"u"&&S.push("expectedValue"),S.length>0){let l=`${e.target||""}${e.attribute?` (${e.attribute})`:""}`,c=`Static assertion missing required field(s): ${S.join(", ")}`,v=E(c,e.level);v.status==="fail"&&(P+=1),v.status==="warn"&&(I+=1),i.reportStaticTest(l,v.status,v.detail,v.level);continue}if(Array.isArray(e.setup)&&e.setup.length>0){let v=function(a){return c.includes(a)};var ve=v;let l=new ee(y,b.selectors,z),c=["focus","type","click","keypress","hover"],U=a=>({...a,type:v(a.type)?a.type:"click"}),f=e.setup.map(U),B=await ue(f,l,d,y,p,["submenu","submenuTrigger","submenuItems"]);if(B.skip){x.push(B.message||"Setup action skipped"),i.reportStaticTest(p,"skip",B.message,g);continue}if(!B.success){let a=`Static setup failed: ${B.error}`,T=E(a,e.level);T.status==="fail"&&(P+=1),T.status==="warn"&&(I+=1),i.reportStaticTest(p,T.status,T.detail,T.level);continue}}let h=b.selectors[e.target];if(!h){let l=`Selector for target ${e.target} not found.`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(p,c.status,c.detail,c.level);continue}let w=y.locator(h).first();if(!(await w.count()>0)){let l=`Target ${e.target} not found.`,c=E(l,e.level);c.status==="fail"&&(P+=1),c.status==="warn"&&(I+=1),i.reportStaticTest(p,c.status,c.detail,c.level);continue}let $=(l,c,v)=>{let U=new RegExp(`\\[${c}(?:=["']?([^\\]"']+)["']?)?\\]`),f=l.match(U);if(!f)return!1;if(!v)return!0;let B=f[1];return B?v.split(" | ").includes(B):!1},k=e.expectedValue;if(e.expectedValue&&typeof e.expectedValue=="object"&&"ref"in e.expectedValue){let l={},c=e.relativeTarget;if(e.expectedValue.ref==="relative"&&e.target==="relative"&&c){let v=b.selectors[c];if(!v)throw new Error(`Selector for relativeTarget '${c}' not found in contract selectors.`);l.relativeBaseSelector=v}else if(e.expectedValue.ref==="relative"&&c){let v=b.selectors[c];if(!v)throw new Error(`Selector for relativeTarget '${c}' not found in contract selectors.`);l.relativeBaseSelector=v}k=await ye(e.expectedValue,b.selectors,y,l)}if(e.expectedValue)if($(h,e.attribute,typeof k=="string"?k:void 0))q.push(`${e.attribute}="${k}" on ${e.target} verified by selector (already present in: ${h}).`),D+=1,i.reportStaticTest(p,"pass",void 0,g);else{let l=k??"",c=await xe.validateAttribute(w,e.target,e.attribute,l,e.failureMessage,"Static ARIA Test");if(c.success&&c.passMessage)q.push(c.passMessage),D+=1,i.reportStaticTest(p,"pass",void 0,g);else if(!c.success&&c.failMessage){let v=E(c.failMessage,e.level);v.status==="fail"&&(P+=1),v.status==="warn"&&(I+=1),i.reportStaticTest(p,v.status,v.detail,v.level)}}else{let l=e.attribute.split(" | "),c=!1,v=!0;for(let U of l){let f=U.trim();if($(h,f)){q.push(`${f} on ${e.target} verified by selector (already present in: ${h}).`),c=!0;continue}if(v=!1,await w.getAttribute(f)!==null){c=!0;break}}if(!c&&!v){let U=e.failureMessage+` None of the attributes "${e.attribute}" are present.`,f=E(U,e.level);f.status==="fail"&&(P+=1),f.status==="warn"&&(I+=1),i.reportStaticTest(p,f.status,f.detail,f.level)}else!v&&c?(q.push(`At least one of the attributes "${e.attribute}" exists on the element.`),D+=1,i.reportStaticTest(p,"pass",void 0,g)):(D+=1,i.reportStaticTest(p,"pass",void 0,g))}}for(let e of b.dynamic||[]){if(!e.assertions||e.assertions.length===0){let a="Skipping test - no assertions found for this dynamic test.";x.push(a),i.reportTest({description:e.description,level:Q(e.level)},"skip",a);continue}if(!y||y.isClosed()){console.warn(`
29
29
  \u26A0\uFE0F Browser closed - skipping remaining ${b.dynamic.length-b.dynamic.indexOf(e)} tests
30
30
  `),V.push(`CRITICAL: Browser/page closed before completing all tests. ${b.dynamic.length-b.dynamic.indexOf(e)} tests skipped.`);break}try{await d.resetState(y)}catch(a){let T=a instanceof Error?a.message:String(a);throw i.error(T),a}let{setup:p=[],action:g,assertions:S}=e,h=Q(e.level),w=new ee(y,b.selectors,z);if(Array.isArray(p)&&p.length>0){let T=function(L){return a.includes(L)};var ve=T;let a=["focus","type","click","keypress","hover"],Z=L=>({...L,type:T(L.type)?L.type:"click"}),pe=p.map(Z),W=await ue(pe,w,d,y,e.description,["submenu","submenuTrigger","submenuItems"]);if(W.skip){x.push(W.message||"Setup action skipped"),i.reportTest({description:e.description,level:h},"skip",W.message);continue}if(!W.success){let L=E(`Setup failed: ${W.error}`,e.level);i.reportTest({description:e.description,level:h},L.status,L.detail);continue}}let m=V.length,$=K.length,k=x.length;if(await d.shouldSkipTest(e,y)){let a="Skipping test - component-specific conditions not met";x.push(a),i.reportTest({description:e.description,level:h},"skip",a);continue}let c=new re(y,b.selectors,X),v=!1,U=null;for(let a of g){if(!y||y.isClosed()){V.push("CRITICAL: Browser/page closed during test execution. Remaining actions skipped."),v=!0;break}let T;if(a.type==="focus")a.target==="relative"&&a.relativeTarget?T=await w.focus("relative",a.relativeTarget):T=await w.focus(a.target);else if(a.type==="type"&&a.value)T=await w.type(a.target,a.value);else if(a.type==="click")T=await w.click(a.target,a.relativeTarget);else if(a.type==="keypress"&&a.key)T=await w.keypress(a.target,a.key,a.relativeTarget);else if(a.type==="hover")T=await w.hover(a.target,a.relativeTarget);else continue;if(!T.success){if(T.error){let Z=E(T.error,e.level);U={status:Z.status,detail:Z.detail}}v=!0;break}}if(v){i.reportTest({description:e.description,level:h},U?.status||"fail",U?.detail||V[V.length-1]);continue}for(let a of S){let T;if(a.expectedValue&&typeof a.expectedValue=="object"&&"ref"in a.expectedValue)if(a.expectedValue.ref==="relative"){let{RelativeTargetResolver:J}=await import("./RelativeTargetResolver-PDJM3ZJI.js"),L=b.selectors.relative;if(!L)throw new Error("Relative selector not defined in contract selectors.");let se=a.relativeTarget||"first",G=await J.resolve(y,L,se);if(!G)throw new Error(`Could not resolve relative target '${se}' for expectedValue.`);let $e=a.expectedValue.property||a.expectedValue.attribute||"id";if($e==="textContent")T=await G.evaluate(ne=>ne.textContent??void 0);else{let ne=await G.getAttribute($e);T=ne===null?void 0:ne}}else T=await ye(a.expectedValue,b.selectors,y,{});else typeof a.expectedValue=="string"||typeof a.expectedValue>"u"?T=a.expectedValue:T="";let Z={...a,expectedValue:T},pe=T??"",W=await c.validate({...Z,expectedValue:pe},e.description);if(W.success&&W.passMessage)q.push(W.passMessage);else if(!W.success&&W.failMessage){let J=[];if(a.target||J.push("target"),a.assertion||J.push("assertion"),["toHaveAttribute","toHaveValue","toHaveRole"].includes(a.assertion)&&(typeof a.attribute>"u"&&a.assertion==="toHaveAttribute"&&J.push("attribute"),typeof a.expectedValue>"u"&&J.push("expectedValue")),J.length>0){let L=Q(a.level||e.level),se=`Dynamic assertion missing required field(s): ${J.join(", ")}`,G=E(se,L);if(G.status==="skip")continue;V.push(se),i.reportTest({description:e.description,level:L},G.status,G.detail);continue}}}let f=V.length,B=K.length,be=x.length;f>m?i.reportTest({description:e.description,level:h},"fail",V[V.length-1]):B>$?i.reportTest({description:e.description,level:h},"warn",K[K.length-1]):be>k?i.reportTest({description:e.description,level:h},"skip",x[x.length-1]):i.reportTest({description:e.description,level:h},"pass")}i.reportStatic(D,P,I),i.summary(V)}catch(d){if(d instanceof Error)throw d.message.includes("Executable doesn't exist")||d.message.includes("browserType.launch")?new Error(`
31
31
  \u274C CRITICAL: Playwright browsers not found!