aria-ease 5.0.0 → 5.0.1

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/bin/cli.cjs CHANGED
@@ -13330,10 +13330,11 @@ async function runContractTestsPlaywright(componentName, url) {
13330
13330
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
13331
13331
  },
13332
13332
  componentContract.selectors.trigger,
13333
- { timeout: 6e3 }
13333
+ { timeout: 1e4 }
13334
13334
  ).catch(() => {
13335
13335
  console.warn("Menu initialization signal not detected, continuing with tests...");
13336
13336
  });
13337
+ await page.waitForTimeout(300);
13337
13338
  }
13338
13339
  async function resolveRelativeTarget(selector, relative) {
13339
13340
  const items = await page.locator(selector).all();
@@ -13411,18 +13412,84 @@ async function runContractTestsPlaywright(componentName, url) {
13411
13412
  const popupElement = page.locator(popupSelector).first();
13412
13413
  const isPopupVisible = await popupElement.isVisible();
13413
13414
  if (isPopupVisible) {
13414
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
13415
+ let menuClosed = false;
13416
+ let closeSelector = componentContract.selectors.input;
13417
+ if (!closeSelector && componentContract.selectors.focusable) {
13418
+ closeSelector = componentContract.selectors.focusable;
13419
+ } else if (!closeSelector) {
13420
+ closeSelector = componentContract.selectors.trigger;
13421
+ }
13415
13422
  if (closeSelector) {
13416
13423
  const closeElement = page.locator(closeSelector).first();
13417
13424
  await closeElement.focus();
13418
- await page.keyboard.press("Escape");
13419
13425
  await page.waitForTimeout(200);
13420
- if (componentContract.selectors.input) {
13421
- const inputElement = page.locator(componentContract.selectors.input).first();
13422
- await inputElement.clear();
13423
- await page.waitForTimeout(100);
13426
+ await page.keyboard.press("Escape");
13427
+ menuClosed = await page.waitForFunction(
13428
+ (selector) => {
13429
+ const popup = document.querySelector(selector);
13430
+ return popup && getComputedStyle(popup).display === "none";
13431
+ },
13432
+ popupSelector,
13433
+ { timeout: 3e3 }
13434
+ ).then(() => true).catch(() => false);
13435
+ }
13436
+ if (!menuClosed && componentContract.selectors.trigger) {
13437
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
13438
+ await triggerElement.click();
13439
+ await page.waitForTimeout(500);
13440
+ menuClosed = await page.waitForFunction(
13441
+ (selector) => {
13442
+ const popup = document.querySelector(selector);
13443
+ return popup && getComputedStyle(popup).display === "none";
13444
+ },
13445
+ popupSelector,
13446
+ { timeout: 3e3 }
13447
+ ).then(() => true).catch(() => false);
13448
+ }
13449
+ if (!menuClosed) {
13450
+ await page.mouse.click(10, 10);
13451
+ await page.waitForTimeout(500);
13452
+ menuClosed = await page.waitForFunction(
13453
+ (selector) => {
13454
+ const popup = document.querySelector(selector);
13455
+ return popup && getComputedStyle(popup).display === "none";
13456
+ },
13457
+ popupSelector,
13458
+ { timeout: 3e3 }
13459
+ ).then(() => true).catch(() => false);
13460
+ if (menuClosed) {
13461
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
13424
13462
  }
13425
13463
  }
13464
+ if (!menuClosed) {
13465
+ throw new Error(
13466
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
13467
+ 1. Escape key
13468
+ 2. Clicking trigger
13469
+ 3. Clicking outside
13470
+ This indicates a problem with the menu component's close functionality.`
13471
+ );
13472
+ }
13473
+ if (componentName === "menu" && componentContract.selectors.trigger) {
13474
+ await page.waitForFunction(
13475
+ (selector) => {
13476
+ const trigger = document.querySelector(selector);
13477
+ return document.activeElement === trigger;
13478
+ },
13479
+ componentContract.selectors.trigger,
13480
+ { timeout: 2e3 }
13481
+ ).catch(async () => {
13482
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
13483
+ await triggerElement.focus();
13484
+ await page.waitForTimeout(200);
13485
+ });
13486
+ }
13487
+ await page.waitForTimeout(500);
13488
+ if (componentContract.selectors.input) {
13489
+ const inputElement = page.locator(componentContract.selectors.input).first();
13490
+ await inputElement.clear();
13491
+ await page.waitForTimeout(100);
13492
+ }
13426
13493
  }
13427
13494
  }
13428
13495
  let shouldSkipTest = false;
@@ -13491,7 +13558,7 @@ async function runContractTestsPlaywright(componentName, url) {
13491
13558
  continue;
13492
13559
  }
13493
13560
  await relativeElement.click();
13494
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
13561
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
13495
13562
  } else {
13496
13563
  const actionSelector = componentContract.selectors[act.target];
13497
13564
  if (!actionSelector) {
@@ -13499,7 +13566,7 @@ async function runContractTestsPlaywright(componentName, url) {
13499
13566
  continue;
13500
13567
  }
13501
13568
  await page.locator(actionSelector).first().click();
13502
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
13569
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
13503
13570
  }
13504
13571
  }
13505
13572
  if (act.type === "keypress" && act.key) {
@@ -13522,9 +13589,9 @@ async function runContractTestsPlaywright(componentName, url) {
13522
13589
  keyValue = keyValue.replace(/ /g, "");
13523
13590
  }
13524
13591
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
13525
- await page.waitForTimeout(100);
13592
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
13526
13593
  await page.keyboard.press(keyValue);
13527
- await page.waitForTimeout(100);
13594
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
13528
13595
  } else {
13529
13596
  const keypressSelector = componentContract.selectors[act.target];
13530
13597
  if (!keypressSelector) {
@@ -13564,8 +13631,9 @@ async function runContractTestsPlaywright(componentName, url) {
13564
13631
  await page.waitForTimeout(100);
13565
13632
  }
13566
13633
  }
13567
- await page.waitForTimeout(100);
13634
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
13568
13635
  }
13636
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
13569
13637
  for (const assertion of assertions) {
13570
13638
  let target;
13571
13639
  if (assertion.target === "relative") {
@@ -13663,7 +13731,11 @@ async function runContractTestsPlaywright(componentName, url) {
13663
13731
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
13664
13732
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
13665
13733
  } catch {
13666
- failures.push(`${assertion.failureMessage}`);
13734
+ const actualFocus = await page.evaluate(() => {
13735
+ const focused = document.activeElement;
13736
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
13737
+ });
13738
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
13667
13739
  }
13668
13740
  }
13669
13741
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
package/bin/cli.js CHANGED
@@ -204,7 +204,7 @@ program.command("audit").description("Run axe-core powered accessibility audit o
204
204
  console.log(chalk.green("\n\u{1F389} All audits completed."));
205
205
  });
206
206
  program.command("test").description("Run core a11y accessibility standard tests on UI components").action(async () => {
207
- const { runTest } = await import("./test-45KMD4F4.js");
207
+ const { runTest } = await import("./test-TAH4VGZV.js");
208
208
  runTest();
209
209
  });
210
210
  program.command("help").description("Display help information").action(() => {
@@ -57,10 +57,11 @@ async function runContractTestsPlaywright(componentName, url) {
57
57
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
58
58
  },
59
59
  componentContract.selectors.trigger,
60
- { timeout: 6e3 }
60
+ { timeout: 1e4 }
61
61
  ).catch(() => {
62
62
  console.warn("Menu initialization signal not detected, continuing with tests...");
63
63
  });
64
+ await page.waitForTimeout(300);
64
65
  }
65
66
  async function resolveRelativeTarget(selector, relative) {
66
67
  const items = await page.locator(selector).all();
@@ -138,18 +139,84 @@ async function runContractTestsPlaywright(componentName, url) {
138
139
  const popupElement = page.locator(popupSelector).first();
139
140
  const isPopupVisible = await popupElement.isVisible();
140
141
  if (isPopupVisible) {
141
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
142
+ let menuClosed = false;
143
+ let closeSelector = componentContract.selectors.input;
144
+ if (!closeSelector && componentContract.selectors.focusable) {
145
+ closeSelector = componentContract.selectors.focusable;
146
+ } else if (!closeSelector) {
147
+ closeSelector = componentContract.selectors.trigger;
148
+ }
142
149
  if (closeSelector) {
143
150
  const closeElement = page.locator(closeSelector).first();
144
151
  await closeElement.focus();
145
- await page.keyboard.press("Escape");
146
152
  await page.waitForTimeout(200);
147
- if (componentContract.selectors.input) {
148
- const inputElement = page.locator(componentContract.selectors.input).first();
149
- await inputElement.clear();
150
- await page.waitForTimeout(100);
153
+ await page.keyboard.press("Escape");
154
+ menuClosed = await page.waitForFunction(
155
+ (selector) => {
156
+ const popup = document.querySelector(selector);
157
+ return popup && getComputedStyle(popup).display === "none";
158
+ },
159
+ popupSelector,
160
+ { timeout: 3e3 }
161
+ ).then(() => true).catch(() => false);
162
+ }
163
+ if (!menuClosed && componentContract.selectors.trigger) {
164
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
165
+ await triggerElement.click();
166
+ await page.waitForTimeout(500);
167
+ menuClosed = await page.waitForFunction(
168
+ (selector) => {
169
+ const popup = document.querySelector(selector);
170
+ return popup && getComputedStyle(popup).display === "none";
171
+ },
172
+ popupSelector,
173
+ { timeout: 3e3 }
174
+ ).then(() => true).catch(() => false);
175
+ }
176
+ if (!menuClosed) {
177
+ await page.mouse.click(10, 10);
178
+ await page.waitForTimeout(500);
179
+ menuClosed = await page.waitForFunction(
180
+ (selector) => {
181
+ const popup = document.querySelector(selector);
182
+ return popup && getComputedStyle(popup).display === "none";
183
+ },
184
+ popupSelector,
185
+ { timeout: 3e3 }
186
+ ).then(() => true).catch(() => false);
187
+ if (menuClosed) {
188
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
151
189
  }
152
190
  }
191
+ if (!menuClosed) {
192
+ throw new Error(
193
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
194
+ 1. Escape key
195
+ 2. Clicking trigger
196
+ 3. Clicking outside
197
+ This indicates a problem with the menu component's close functionality.`
198
+ );
199
+ }
200
+ if (componentName === "menu" && componentContract.selectors.trigger) {
201
+ await page.waitForFunction(
202
+ (selector) => {
203
+ const trigger = document.querySelector(selector);
204
+ return document.activeElement === trigger;
205
+ },
206
+ componentContract.selectors.trigger,
207
+ { timeout: 2e3 }
208
+ ).catch(async () => {
209
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
210
+ await triggerElement.focus();
211
+ await page.waitForTimeout(200);
212
+ });
213
+ }
214
+ await page.waitForTimeout(500);
215
+ if (componentContract.selectors.input) {
216
+ const inputElement = page.locator(componentContract.selectors.input).first();
217
+ await inputElement.clear();
218
+ await page.waitForTimeout(100);
219
+ }
153
220
  }
154
221
  }
155
222
  let shouldSkipTest = false;
@@ -218,7 +285,7 @@ async function runContractTestsPlaywright(componentName, url) {
218
285
  continue;
219
286
  }
220
287
  await relativeElement.click();
221
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
288
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
222
289
  } else {
223
290
  const actionSelector = componentContract.selectors[act.target];
224
291
  if (!actionSelector) {
@@ -226,7 +293,7 @@ async function runContractTestsPlaywright(componentName, url) {
226
293
  continue;
227
294
  }
228
295
  await page.locator(actionSelector).first().click();
229
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
296
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
230
297
  }
231
298
  }
232
299
  if (act.type === "keypress" && act.key) {
@@ -249,9 +316,9 @@ async function runContractTestsPlaywright(componentName, url) {
249
316
  keyValue = keyValue.replace(/ /g, "");
250
317
  }
251
318
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
252
- await page.waitForTimeout(100);
319
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
253
320
  await page.keyboard.press(keyValue);
254
- await page.waitForTimeout(100);
321
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
255
322
  } else {
256
323
  const keypressSelector = componentContract.selectors[act.target];
257
324
  if (!keypressSelector) {
@@ -291,8 +358,9 @@ async function runContractTestsPlaywright(componentName, url) {
291
358
  await page.waitForTimeout(100);
292
359
  }
293
360
  }
294
- await page.waitForTimeout(100);
361
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
295
362
  }
363
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
296
364
  for (const assertion of assertions) {
297
365
  let target;
298
366
  if (assertion.target === "relative") {
@@ -390,7 +458,11 @@ async function runContractTestsPlaywright(componentName, url) {
390
458
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
391
459
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
392
460
  } catch {
393
- failures.push(`${assertion.failureMessage}`);
461
+ const actualFocus = await page.evaluate(() => {
462
+ const focused = document.activeElement;
463
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
464
+ });
465
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
394
466
  }
395
467
  }
396
468
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
@@ -12776,7 +12776,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
12776
12776
  URL must include protocol (e.g., "http://localhost:5173/test")`
12777
12777
  );
12778
12778
  }
12779
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-EZLNNJV5.js");
12779
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-YPBTKJP7.js");
12780
12780
  contract = await runContractTestsPlaywright(componentName, url);
12781
12781
  } else {
12782
12782
  console.log(`\u{1F9EA} Running jsdom tests (limited event handling)`);
@@ -55,10 +55,11 @@ async function runContractTestsPlaywright(componentName, url) {
55
55
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
56
56
  },
57
57
  componentContract.selectors.trigger,
58
- { timeout: 6e3 }
58
+ { timeout: 1e4 }
59
59
  ).catch(() => {
60
60
  console.warn("Menu initialization signal not detected, continuing with tests...");
61
61
  });
62
+ await page.waitForTimeout(300);
62
63
  }
63
64
  async function resolveRelativeTarget(selector, relative) {
64
65
  const items = await page.locator(selector).all();
@@ -136,18 +137,84 @@ async function runContractTestsPlaywright(componentName, url) {
136
137
  const popupElement = page.locator(popupSelector).first();
137
138
  const isPopupVisible = await popupElement.isVisible();
138
139
  if (isPopupVisible) {
139
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
140
+ let menuClosed = false;
141
+ let closeSelector = componentContract.selectors.input;
142
+ if (!closeSelector && componentContract.selectors.focusable) {
143
+ closeSelector = componentContract.selectors.focusable;
144
+ } else if (!closeSelector) {
145
+ closeSelector = componentContract.selectors.trigger;
146
+ }
140
147
  if (closeSelector) {
141
148
  const closeElement = page.locator(closeSelector).first();
142
149
  await closeElement.focus();
143
- await page.keyboard.press("Escape");
144
150
  await page.waitForTimeout(200);
145
- if (componentContract.selectors.input) {
146
- const inputElement = page.locator(componentContract.selectors.input).first();
147
- await inputElement.clear();
148
- await page.waitForTimeout(100);
151
+ await page.keyboard.press("Escape");
152
+ menuClosed = await page.waitForFunction(
153
+ (selector) => {
154
+ const popup = document.querySelector(selector);
155
+ return popup && getComputedStyle(popup).display === "none";
156
+ },
157
+ popupSelector,
158
+ { timeout: 3e3 }
159
+ ).then(() => true).catch(() => false);
160
+ }
161
+ if (!menuClosed && componentContract.selectors.trigger) {
162
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
163
+ await triggerElement.click();
164
+ await page.waitForTimeout(500);
165
+ menuClosed = await page.waitForFunction(
166
+ (selector) => {
167
+ const popup = document.querySelector(selector);
168
+ return popup && getComputedStyle(popup).display === "none";
169
+ },
170
+ popupSelector,
171
+ { timeout: 3e3 }
172
+ ).then(() => true).catch(() => false);
173
+ }
174
+ if (!menuClosed) {
175
+ await page.mouse.click(10, 10);
176
+ await page.waitForTimeout(500);
177
+ menuClosed = await page.waitForFunction(
178
+ (selector) => {
179
+ const popup = document.querySelector(selector);
180
+ return popup && getComputedStyle(popup).display === "none";
181
+ },
182
+ popupSelector,
183
+ { timeout: 3e3 }
184
+ ).then(() => true).catch(() => false);
185
+ if (menuClosed) {
186
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
149
187
  }
150
188
  }
189
+ if (!menuClosed) {
190
+ throw new Error(
191
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
192
+ 1. Escape key
193
+ 2. Clicking trigger
194
+ 3. Clicking outside
195
+ This indicates a problem with the menu component's close functionality.`
196
+ );
197
+ }
198
+ if (componentName === "menu" && componentContract.selectors.trigger) {
199
+ await page.waitForFunction(
200
+ (selector) => {
201
+ const trigger = document.querySelector(selector);
202
+ return document.activeElement === trigger;
203
+ },
204
+ componentContract.selectors.trigger,
205
+ { timeout: 2e3 }
206
+ ).catch(async () => {
207
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
208
+ await triggerElement.focus();
209
+ await page.waitForTimeout(200);
210
+ });
211
+ }
212
+ await page.waitForTimeout(500);
213
+ if (componentContract.selectors.input) {
214
+ const inputElement = page.locator(componentContract.selectors.input).first();
215
+ await inputElement.clear();
216
+ await page.waitForTimeout(100);
217
+ }
151
218
  }
152
219
  }
153
220
  let shouldSkipTest = false;
@@ -216,7 +283,7 @@ async function runContractTestsPlaywright(componentName, url) {
216
283
  continue;
217
284
  }
218
285
  await relativeElement.click();
219
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
286
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
220
287
  } else {
221
288
  const actionSelector = componentContract.selectors[act.target];
222
289
  if (!actionSelector) {
@@ -224,7 +291,7 @@ async function runContractTestsPlaywright(componentName, url) {
224
291
  continue;
225
292
  }
226
293
  await page.locator(actionSelector).first().click();
227
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
294
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
228
295
  }
229
296
  }
230
297
  if (act.type === "keypress" && act.key) {
@@ -247,9 +314,9 @@ async function runContractTestsPlaywright(componentName, url) {
247
314
  keyValue = keyValue.replace(/ /g, "");
248
315
  }
249
316
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
250
- await page.waitForTimeout(100);
317
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
251
318
  await page.keyboard.press(keyValue);
252
- await page.waitForTimeout(100);
319
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
253
320
  } else {
254
321
  const keypressSelector = componentContract.selectors[act.target];
255
322
  if (!keypressSelector) {
@@ -289,8 +356,9 @@ async function runContractTestsPlaywright(componentName, url) {
289
356
  await page.waitForTimeout(100);
290
357
  }
291
358
  }
292
- await page.waitForTimeout(100);
359
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
293
360
  }
361
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
294
362
  for (const assertion of assertions) {
295
363
  let target;
296
364
  if (assertion.target === "relative") {
@@ -388,7 +456,11 @@ async function runContractTestsPlaywright(componentName, url) {
388
456
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
389
457
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
390
458
  } catch {
391
- failures.push(`${assertion.failureMessage}`);
459
+ const actualFocus = await page.evaluate(() => {
460
+ const focused = document.activeElement;
461
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
462
+ });
463
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
392
464
  }
393
465
  }
394
466
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
package/dist/index.cjs CHANGED
@@ -9455,10 +9455,11 @@ async function runContractTestsPlaywright(componentName, url) {
9455
9455
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
9456
9456
  },
9457
9457
  componentContract.selectors.trigger,
9458
- { timeout: 6e3 }
9458
+ { timeout: 1e4 }
9459
9459
  ).catch(() => {
9460
9460
  console.warn("Menu initialization signal not detected, continuing with tests...");
9461
9461
  });
9462
+ await page.waitForTimeout(300);
9462
9463
  }
9463
9464
  async function resolveRelativeTarget(selector, relative) {
9464
9465
  const items = await page.locator(selector).all();
@@ -9536,18 +9537,84 @@ async function runContractTestsPlaywright(componentName, url) {
9536
9537
  const popupElement = page.locator(popupSelector).first();
9537
9538
  const isPopupVisible = await popupElement.isVisible();
9538
9539
  if (isPopupVisible) {
9539
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
9540
+ let menuClosed = false;
9541
+ let closeSelector = componentContract.selectors.input;
9542
+ if (!closeSelector && componentContract.selectors.focusable) {
9543
+ closeSelector = componentContract.selectors.focusable;
9544
+ } else if (!closeSelector) {
9545
+ closeSelector = componentContract.selectors.trigger;
9546
+ }
9540
9547
  if (closeSelector) {
9541
9548
  const closeElement = page.locator(closeSelector).first();
9542
9549
  await closeElement.focus();
9543
- await page.keyboard.press("Escape");
9544
9550
  await page.waitForTimeout(200);
9545
- if (componentContract.selectors.input) {
9546
- const inputElement = page.locator(componentContract.selectors.input).first();
9547
- await inputElement.clear();
9548
- await page.waitForTimeout(100);
9551
+ await page.keyboard.press("Escape");
9552
+ menuClosed = await page.waitForFunction(
9553
+ (selector) => {
9554
+ const popup = document.querySelector(selector);
9555
+ return popup && getComputedStyle(popup).display === "none";
9556
+ },
9557
+ popupSelector,
9558
+ { timeout: 3e3 }
9559
+ ).then(() => true).catch(() => false);
9560
+ }
9561
+ if (!menuClosed && componentContract.selectors.trigger) {
9562
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
9563
+ await triggerElement.click();
9564
+ await page.waitForTimeout(500);
9565
+ menuClosed = await page.waitForFunction(
9566
+ (selector) => {
9567
+ const popup = document.querySelector(selector);
9568
+ return popup && getComputedStyle(popup).display === "none";
9569
+ },
9570
+ popupSelector,
9571
+ { timeout: 3e3 }
9572
+ ).then(() => true).catch(() => false);
9573
+ }
9574
+ if (!menuClosed) {
9575
+ await page.mouse.click(10, 10);
9576
+ await page.waitForTimeout(500);
9577
+ menuClosed = await page.waitForFunction(
9578
+ (selector) => {
9579
+ const popup = document.querySelector(selector);
9580
+ return popup && getComputedStyle(popup).display === "none";
9581
+ },
9582
+ popupSelector,
9583
+ { timeout: 3e3 }
9584
+ ).then(() => true).catch(() => false);
9585
+ if (menuClosed) {
9586
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
9549
9587
  }
9550
9588
  }
9589
+ if (!menuClosed) {
9590
+ throw new Error(
9591
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
9592
+ 1. Escape key
9593
+ 2. Clicking trigger
9594
+ 3. Clicking outside
9595
+ This indicates a problem with the menu component's close functionality.`
9596
+ );
9597
+ }
9598
+ if (componentName === "menu" && componentContract.selectors.trigger) {
9599
+ await page.waitForFunction(
9600
+ (selector) => {
9601
+ const trigger = document.querySelector(selector);
9602
+ return document.activeElement === trigger;
9603
+ },
9604
+ componentContract.selectors.trigger,
9605
+ { timeout: 2e3 }
9606
+ ).catch(async () => {
9607
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
9608
+ await triggerElement.focus();
9609
+ await page.waitForTimeout(200);
9610
+ });
9611
+ }
9612
+ await page.waitForTimeout(500);
9613
+ if (componentContract.selectors.input) {
9614
+ const inputElement = page.locator(componentContract.selectors.input).first();
9615
+ await inputElement.clear();
9616
+ await page.waitForTimeout(100);
9617
+ }
9551
9618
  }
9552
9619
  }
9553
9620
  let shouldSkipTest = false;
@@ -9616,7 +9683,7 @@ async function runContractTestsPlaywright(componentName, url) {
9616
9683
  continue;
9617
9684
  }
9618
9685
  await relativeElement.click();
9619
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
9686
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
9620
9687
  } else {
9621
9688
  const actionSelector = componentContract.selectors[act.target];
9622
9689
  if (!actionSelector) {
@@ -9624,7 +9691,7 @@ async function runContractTestsPlaywright(componentName, url) {
9624
9691
  continue;
9625
9692
  }
9626
9693
  await page.locator(actionSelector).first().click();
9627
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
9694
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
9628
9695
  }
9629
9696
  }
9630
9697
  if (act.type === "keypress" && act.key) {
@@ -9647,9 +9714,9 @@ async function runContractTestsPlaywright(componentName, url) {
9647
9714
  keyValue = keyValue.replace(/ /g, "");
9648
9715
  }
9649
9716
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
9650
- await page.waitForTimeout(100);
9717
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
9651
9718
  await page.keyboard.press(keyValue);
9652
- await page.waitForTimeout(100);
9719
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
9653
9720
  } else {
9654
9721
  const keypressSelector = componentContract.selectors[act.target];
9655
9722
  if (!keypressSelector) {
@@ -9689,8 +9756,9 @@ async function runContractTestsPlaywright(componentName, url) {
9689
9756
  await page.waitForTimeout(100);
9690
9757
  }
9691
9758
  }
9692
- await page.waitForTimeout(100);
9759
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
9693
9760
  }
9761
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
9694
9762
  for (const assertion of assertions) {
9695
9763
  let target;
9696
9764
  if (assertion.target === "relative") {
@@ -9788,7 +9856,11 @@ async function runContractTestsPlaywright(componentName, url) {
9788
9856
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
9789
9857
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
9790
9858
  } catch {
9791
- failures.push(`${assertion.failureMessage}`);
9859
+ const actualFocus = await page.evaluate(() => {
9860
+ const focused = document.activeElement;
9861
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
9862
+ });
9863
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
9792
9864
  }
9793
9865
  }
9794
9866
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
package/dist/index.js CHANGED
@@ -13939,7 +13939,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
13939
13939
  URL must include protocol (e.g., "http://localhost:5173/test")`
13940
13940
  );
13941
13941
  }
13942
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-UQQI5MYS.js");
13942
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-45CFWUOD.js");
13943
13943
  contract = await runContractTestsPlaywright(componentName, url);
13944
13944
  } else {
13945
13945
  console.log(`\u{1F9EA} Running jsdom tests (limited event handling)`);
@@ -46,10 +46,11 @@ async function runContractTestsPlaywright(componentName, url) {
46
46
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
47
47
  },
48
48
  componentContract.selectors.trigger,
49
- { timeout: 6e3 }
49
+ { timeout: 1e4 }
50
50
  ).catch(() => {
51
51
  console.warn("Menu initialization signal not detected, continuing with tests...");
52
52
  });
53
+ await page.waitForTimeout(300);
53
54
  }
54
55
  async function resolveRelativeTarget(selector, relative) {
55
56
  const items = await page.locator(selector).all();
@@ -127,18 +128,84 @@ async function runContractTestsPlaywright(componentName, url) {
127
128
  const popupElement = page.locator(popupSelector).first();
128
129
  const isPopupVisible = await popupElement.isVisible();
129
130
  if (isPopupVisible) {
130
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
131
+ let menuClosed = false;
132
+ let closeSelector = componentContract.selectors.input;
133
+ if (!closeSelector && componentContract.selectors.focusable) {
134
+ closeSelector = componentContract.selectors.focusable;
135
+ } else if (!closeSelector) {
136
+ closeSelector = componentContract.selectors.trigger;
137
+ }
131
138
  if (closeSelector) {
132
139
  const closeElement = page.locator(closeSelector).first();
133
140
  await closeElement.focus();
134
- await page.keyboard.press("Escape");
135
141
  await page.waitForTimeout(200);
136
- if (componentContract.selectors.input) {
137
- const inputElement = page.locator(componentContract.selectors.input).first();
138
- await inputElement.clear();
139
- await page.waitForTimeout(100);
142
+ await page.keyboard.press("Escape");
143
+ menuClosed = await page.waitForFunction(
144
+ (selector) => {
145
+ const popup = document.querySelector(selector);
146
+ return popup && getComputedStyle(popup).display === "none";
147
+ },
148
+ popupSelector,
149
+ { timeout: 3e3 }
150
+ ).then(() => true).catch(() => false);
151
+ }
152
+ if (!menuClosed && componentContract.selectors.trigger) {
153
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
154
+ await triggerElement.click();
155
+ await page.waitForTimeout(500);
156
+ menuClosed = await page.waitForFunction(
157
+ (selector) => {
158
+ const popup = document.querySelector(selector);
159
+ return popup && getComputedStyle(popup).display === "none";
160
+ },
161
+ popupSelector,
162
+ { timeout: 3e3 }
163
+ ).then(() => true).catch(() => false);
164
+ }
165
+ if (!menuClosed) {
166
+ await page.mouse.click(10, 10);
167
+ await page.waitForTimeout(500);
168
+ menuClosed = await page.waitForFunction(
169
+ (selector) => {
170
+ const popup = document.querySelector(selector);
171
+ return popup && getComputedStyle(popup).display === "none";
172
+ },
173
+ popupSelector,
174
+ { timeout: 3e3 }
175
+ ).then(() => true).catch(() => false);
176
+ if (menuClosed) {
177
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
140
178
  }
141
179
  }
180
+ if (!menuClosed) {
181
+ throw new Error(
182
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
183
+ 1. Escape key
184
+ 2. Clicking trigger
185
+ 3. Clicking outside
186
+ This indicates a problem with the menu component's close functionality.`
187
+ );
188
+ }
189
+ if (componentName === "menu" && componentContract.selectors.trigger) {
190
+ await page.waitForFunction(
191
+ (selector) => {
192
+ const trigger = document.querySelector(selector);
193
+ return document.activeElement === trigger;
194
+ },
195
+ componentContract.selectors.trigger,
196
+ { timeout: 2e3 }
197
+ ).catch(async () => {
198
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
199
+ await triggerElement.focus();
200
+ await page.waitForTimeout(200);
201
+ });
202
+ }
203
+ await page.waitForTimeout(500);
204
+ if (componentContract.selectors.input) {
205
+ const inputElement = page.locator(componentContract.selectors.input).first();
206
+ await inputElement.clear();
207
+ await page.waitForTimeout(100);
208
+ }
142
209
  }
143
210
  }
144
211
  let shouldSkipTest = false;
@@ -207,7 +274,7 @@ async function runContractTestsPlaywright(componentName, url) {
207
274
  continue;
208
275
  }
209
276
  await relativeElement.click();
210
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
277
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
211
278
  } else {
212
279
  const actionSelector = componentContract.selectors[act.target];
213
280
  if (!actionSelector) {
@@ -215,7 +282,7 @@ async function runContractTestsPlaywright(componentName, url) {
215
282
  continue;
216
283
  }
217
284
  await page.locator(actionSelector).first().click();
218
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
285
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
219
286
  }
220
287
  }
221
288
  if (act.type === "keypress" && act.key) {
@@ -238,9 +305,9 @@ async function runContractTestsPlaywright(componentName, url) {
238
305
  keyValue = keyValue.replace(/ /g, "");
239
306
  }
240
307
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
241
- await page.waitForTimeout(100);
308
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
242
309
  await page.keyboard.press(keyValue);
243
- await page.waitForTimeout(100);
310
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
244
311
  } else {
245
312
  const keypressSelector = componentContract.selectors[act.target];
246
313
  if (!keypressSelector) {
@@ -280,8 +347,9 @@ async function runContractTestsPlaywright(componentName, url) {
280
347
  await page.waitForTimeout(100);
281
348
  }
282
349
  }
283
- await page.waitForTimeout(100);
350
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
284
351
  }
352
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
285
353
  for (const assertion of assertions) {
286
354
  let target;
287
355
  if (assertion.target === "relative") {
@@ -379,7 +447,11 @@ async function runContractTestsPlaywright(componentName, url) {
379
447
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
380
448
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
381
449
  } catch {
382
- failures.push(`${assertion.failureMessage}`);
450
+ const actualFocus = await page.evaluate(() => {
451
+ const focused = document.activeElement;
452
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
453
+ });
454
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
383
455
  }
384
456
  }
385
457
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
@@ -9310,10 +9310,11 @@ async function runContractTestsPlaywright(componentName, url) {
9310
9310
  return trigger && trigger.getAttribute("data-menu-initialized") === "true";
9311
9311
  },
9312
9312
  componentContract.selectors.trigger,
9313
- { timeout: 6e3 }
9313
+ { timeout: 1e4 }
9314
9314
  ).catch(() => {
9315
9315
  console.warn("Menu initialization signal not detected, continuing with tests...");
9316
9316
  });
9317
+ await page.waitForTimeout(300);
9317
9318
  }
9318
9319
  async function resolveRelativeTarget(selector, relative) {
9319
9320
  const items = await page.locator(selector).all();
@@ -9391,18 +9392,84 @@ async function runContractTestsPlaywright(componentName, url) {
9391
9392
  const popupElement = page.locator(popupSelector).first();
9392
9393
  const isPopupVisible = await popupElement.isVisible();
9393
9394
  if (isPopupVisible) {
9394
- const closeSelector = componentContract.selectors.input || componentContract.selectors.trigger;
9395
+ let menuClosed = false;
9396
+ let closeSelector = componentContract.selectors.input;
9397
+ if (!closeSelector && componentContract.selectors.focusable) {
9398
+ closeSelector = componentContract.selectors.focusable;
9399
+ } else if (!closeSelector) {
9400
+ closeSelector = componentContract.selectors.trigger;
9401
+ }
9395
9402
  if (closeSelector) {
9396
9403
  const closeElement = page.locator(closeSelector).first();
9397
9404
  await closeElement.focus();
9398
- await page.keyboard.press("Escape");
9399
9405
  await page.waitForTimeout(200);
9400
- if (componentContract.selectors.input) {
9401
- const inputElement = page.locator(componentContract.selectors.input).first();
9402
- await inputElement.clear();
9403
- await page.waitForTimeout(100);
9406
+ await page.keyboard.press("Escape");
9407
+ menuClosed = await page.waitForFunction(
9408
+ (selector) => {
9409
+ const popup = document.querySelector(selector);
9410
+ return popup && getComputedStyle(popup).display === "none";
9411
+ },
9412
+ popupSelector,
9413
+ { timeout: 3e3 }
9414
+ ).then(() => true).catch(() => false);
9415
+ }
9416
+ if (!menuClosed && componentContract.selectors.trigger) {
9417
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
9418
+ await triggerElement.click();
9419
+ await page.waitForTimeout(500);
9420
+ menuClosed = await page.waitForFunction(
9421
+ (selector) => {
9422
+ const popup = document.querySelector(selector);
9423
+ return popup && getComputedStyle(popup).display === "none";
9424
+ },
9425
+ popupSelector,
9426
+ { timeout: 3e3 }
9427
+ ).then(() => true).catch(() => false);
9428
+ }
9429
+ if (!menuClosed) {
9430
+ await page.mouse.click(10, 10);
9431
+ await page.waitForTimeout(500);
9432
+ menuClosed = await page.waitForFunction(
9433
+ (selector) => {
9434
+ const popup = document.querySelector(selector);
9435
+ return popup && getComputedStyle(popup).display === "none";
9436
+ },
9437
+ popupSelector,
9438
+ { timeout: 3e3 }
9439
+ ).then(() => true).catch(() => false);
9440
+ if (menuClosed) {
9441
+ console.log("\u{1F3AF} Strategy 3 (Click outside) worked");
9404
9442
  }
9405
9443
  }
9444
+ if (!menuClosed) {
9445
+ throw new Error(
9446
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
9447
+ 1. Escape key
9448
+ 2. Clicking trigger
9449
+ 3. Clicking outside
9450
+ This indicates a problem with the menu component's close functionality.`
9451
+ );
9452
+ }
9453
+ if (componentName === "menu" && componentContract.selectors.trigger) {
9454
+ await page.waitForFunction(
9455
+ (selector) => {
9456
+ const trigger = document.querySelector(selector);
9457
+ return document.activeElement === trigger;
9458
+ },
9459
+ componentContract.selectors.trigger,
9460
+ { timeout: 2e3 }
9461
+ ).catch(async () => {
9462
+ const triggerElement = page.locator(componentContract.selectors.trigger).first();
9463
+ await triggerElement.focus();
9464
+ await page.waitForTimeout(200);
9465
+ });
9466
+ }
9467
+ await page.waitForTimeout(500);
9468
+ if (componentContract.selectors.input) {
9469
+ const inputElement = page.locator(componentContract.selectors.input).first();
9470
+ await inputElement.clear();
9471
+ await page.waitForTimeout(100);
9472
+ }
9406
9473
  }
9407
9474
  }
9408
9475
  let shouldSkipTest = false;
@@ -9471,7 +9538,7 @@ async function runContractTestsPlaywright(componentName, url) {
9471
9538
  continue;
9472
9539
  }
9473
9540
  await relativeElement.click();
9474
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
9541
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
9475
9542
  } else {
9476
9543
  const actionSelector = componentContract.selectors[act.target];
9477
9544
  if (!actionSelector) {
@@ -9479,7 +9546,7 @@ async function runContractTestsPlaywright(componentName, url) {
9479
9546
  continue;
9480
9547
  }
9481
9548
  await page.locator(actionSelector).first().click();
9482
- await page.waitForTimeout(componentName === "menu" ? 500 : 200);
9549
+ await page.waitForTimeout(componentName === "menu" ? 800 : 200);
9483
9550
  }
9484
9551
  }
9485
9552
  if (act.type === "keypress" && act.key) {
@@ -9502,9 +9569,9 @@ async function runContractTestsPlaywright(componentName, url) {
9502
9569
  keyValue = keyValue.replace(/ /g, "");
9503
9570
  }
9504
9571
  if (act.target === "focusable" && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Escape"].includes(keyValue)) {
9505
- await page.waitForTimeout(100);
9572
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
9506
9573
  await page.keyboard.press(keyValue);
9507
- await page.waitForTimeout(100);
9574
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
9508
9575
  } else {
9509
9576
  const keypressSelector = componentContract.selectors[act.target];
9510
9577
  if (!keypressSelector) {
@@ -9544,8 +9611,9 @@ async function runContractTestsPlaywright(componentName, url) {
9544
9611
  await page.waitForTimeout(100);
9545
9612
  }
9546
9613
  }
9547
- await page.waitForTimeout(100);
9614
+ await page.waitForTimeout(componentName === "menu" ? 200 : 100);
9548
9615
  }
9616
+ await page.waitForTimeout(componentName === "menu" ? 300 : 100);
9549
9617
  for (const assertion of assertions) {
9550
9618
  let target;
9551
9619
  if (assertion.target === "relative") {
@@ -9643,7 +9711,11 @@ async function runContractTestsPlaywright(componentName, url) {
9643
9711
  await (0, test_exports.expect)(target).toBeFocused({ timeout: 5e3 });
9644
9712
  passes.push(`${assertion.target} has focus as expected. Test: "${dynamicTest.description}".`);
9645
9713
  } catch {
9646
- failures.push(`${assertion.failureMessage}`);
9714
+ const actualFocus = await page.evaluate(() => {
9715
+ const focused = document.activeElement;
9716
+ return focused ? `${focused.tagName}#${focused.id || "no-id"}.${focused.className || "no-class"}` : "no element focused";
9717
+ });
9718
+ failures.push(`${assertion.failureMessage} (actual focus: ${actualFocus})`);
9647
9719
  }
9648
9720
  }
9649
9721
  if (assertion.assertion === "toHaveRole" && assertion.expectedValue) {
@@ -12580,7 +12580,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
12580
12580
  URL must include protocol (e.g., "http://localhost:5173/test")`
12581
12581
  );
12582
12582
  }
12583
- const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-UQQI5MYS.js');
12583
+ const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-45CFWUOD.js');
12584
12584
  contract = await runContractTestsPlaywright(componentName, url);
12585
12585
  } else {
12586
12586
  console.log(`\u{1F9EA} Running jsdom tests (limited event handling)`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aria-ease",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "Out-of-the-box accessibility utility package to develop production ready applications.",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "module",