aria-ease 6.12.0 → 6.12.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.
Files changed (25) hide show
  1. package/README.md +2 -2
  2. package/dist/{ComboboxComponentStrategy-OGRVZXAF.js → ComboboxComponentStrategy-DU342VMB.js} +7 -7
  3. package/dist/RelativeTargetResolver-DJAITO6D.js +7 -0
  4. package/dist/{audit-RM6TCZ5C.js → audit-JYEPKLHR.js} +5 -0
  5. package/dist/{chunk-FZ7GMIJB.js → chunk-4DU5Z5BR.js} +0 -2
  6. package/dist/chunk-GLT43UVH.js +43 -0
  7. package/dist/cli.cjs +121 -21
  8. package/dist/cli.js +3 -3
  9. package/dist/{contractTestRunnerPlaywright-EWAWQVHT.js → contractTestRunnerPlaywright-H24LQ45R.js} +109 -53
  10. package/dist/{contractTestRunnerPlaywright-DIXP5DQ3.js → contractTestRunnerPlaywright-NL3JNJYH.js} +109 -53
  11. package/dist/index.cjs +216 -46
  12. package/dist/index.js +103 -28
  13. package/dist/src/combobox/index.cjs +1 -0
  14. package/dist/src/combobox/index.js +1 -0
  15. package/dist/src/utils/test/{ComboboxComponentStrategy-5AECQSRN.js → ComboboxComponentStrategy-XKQ72RFD.js} +7 -7
  16. package/dist/src/utils/test/RelativeTargetResolver-G2XDN2VV.js +1 -0
  17. package/dist/src/utils/test/{chunk-FZ7GMIJB.js → chunk-4DU5Z5BR.js} +0 -2
  18. package/dist/src/utils/test/chunk-GLT43UVH.js +41 -0
  19. package/dist/src/utils/test/{contractTestRunnerPlaywright-CIZOXYRW.js → contractTestRunnerPlaywright-5FT6K2WN.js} +107 -53
  20. package/dist/src/utils/test/dsl/index.cjs +99 -25
  21. package/dist/src/utils/test/dsl/index.js +99 -25
  22. package/dist/src/utils/test/index.cjs +116 -21
  23. package/dist/src/utils/test/index.js +3 -3
  24. package/dist/{test-HBPCSYH5.js → test-FYSJXQWO.js} +3 -3
  25. package/package.json +2 -2
@@ -346,9 +346,7 @@ async function getOrCreateContext() {
346
346
  if (!sharedContext) {
347
347
  const browser = await getOrCreateBrowser();
348
348
  sharedContext = await browser.newContext({
349
- // Isolated context - no permissions, no geolocation, etc.
350
349
  permissions: [],
351
- // Ignore HTTPS errors for local dev servers
352
350
  ignoreHTTPSErrors: true
353
351
  });
354
352
  }
@@ -709,7 +707,7 @@ var init_ComboboxComponentStrategy = __esm({
709
707
  const popupElement = page.locator(popupSelector).first();
710
708
  const isPopupVisible = await popupElement.isVisible().catch(() => false);
711
709
  if (!isPopupVisible) return;
712
- let listBoxClosed = false;
710
+ let popupClosed = false;
713
711
  let closeSelector = this.selectors.input;
714
712
  if (!closeSelector && this.selectors.focusable) {
715
713
  closeSelector = this.selectors.focusable;
@@ -720,18 +718,18 @@ var init_ComboboxComponentStrategy = __esm({
720
718
  const closeElement = page.locator(closeSelector).first();
721
719
  await closeElement.focus();
722
720
  await page.keyboard.press("Escape");
723
- listBoxClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
721
+ popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
724
722
  }
725
- if (!listBoxClosed && this.selectors.button) {
723
+ if (!popupClosed && this.selectors.button) {
726
724
  const buttonElement = page.locator(this.selectors.button).first();
727
725
  await buttonElement.click({ timeout: this.actionTimeoutMs });
728
- listBoxClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
726
+ popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
729
727
  }
730
- if (!listBoxClosed) {
728
+ if (!popupClosed) {
731
729
  await page.mouse.click(10, 10);
732
- listBoxClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
730
+ popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
733
731
  }
734
- if (!listBoxClosed) {
732
+ if (!popupClosed) {
735
733
  throw new Error(
736
734
  `\u274C FATAL: Cannot close combobox popup between tests. Popup remains visible after trying:
737
735
  1. Escape key
@@ -939,6 +937,10 @@ var init_ComponentDetector = __esm({
939
937
  });
940
938
 
941
939
  // src/utils/test/src/RelativeTargetResolver.ts
940
+ var RelativeTargetResolver_exports = {};
941
+ __export(RelativeTargetResolver_exports, {
942
+ RelativeTargetResolver: () => RelativeTargetResolver
943
+ });
942
944
  var RelativeTargetResolver;
943
945
  var init_RelativeTargetResolver = __esm({
944
946
  "src/utils/test/src/RelativeTargetResolver.ts"() {
@@ -1012,16 +1014,16 @@ var init_ActionExecutor = __esm({
1012
1014
  async focus(target, relativeTarget, virtualId) {
1013
1015
  try {
1014
1016
  if (target === "virtual" && virtualId) {
1015
- const inputSelector = this.selectors.input;
1016
- if (!inputSelector) {
1017
- return { success: false, error: `Input selector not defined for virtual focus.` };
1017
+ const mainSelector = this.selectors.main;
1018
+ if (!mainSelector) {
1019
+ return { success: false, error: `Main selector not defined for virtual focus.` };
1018
1020
  }
1019
- const input = this.page.locator(inputSelector).first();
1020
- const exists = await input.count();
1021
+ const main = this.page.locator(mainSelector).first();
1022
+ const exists = await main.count();
1021
1023
  if (!exists) {
1022
- return { success: false, error: `Input element not found for virtual focus.` };
1024
+ return { success: false, error: `Main element not found for virtual focus.` };
1023
1025
  }
1024
- await input.evaluate((el, id) => {
1026
+ await main.evaluate((el, id) => {
1025
1027
  el.setAttribute("aria-activedescendant", id);
1026
1028
  }, virtualId);
1027
1029
  return { success: true };
@@ -1319,6 +1321,10 @@ var init_AssertionRunner = __esm({
1319
1321
  };
1320
1322
  }
1321
1323
  }
1324
+ if (typeof expectedValue !== "string") {
1325
+ console.error("[AssertionRunner] expectedValue is not a string:", expectedValue);
1326
+ throw new Error(`AssertionRunner: expectedValue for attribute assertion must be a string, but got: ${JSON.stringify(expectedValue)}`);
1327
+ }
1322
1328
  const expectedValues = expectedValue.split(" | ").map((v) => v.trim());
1323
1329
  const attributeValue = await target.getAttribute(attribute);
1324
1330
  if (attributeValue !== null && expectedValues.includes(attributeValue)) {
@@ -1751,6 +1757,52 @@ This usually means:
1751
1757
  reporter.reportStaticTest(relDescription, "pass", void 0, relationshipLevel);
1752
1758
  }
1753
1759
  }
1760
+ async function resolveExpectedValue(expectedValue, selectors, page2, context = {}) {
1761
+ if (!expectedValue || typeof expectedValue !== "object" || !("ref" in expectedValue)) return expectedValue;
1762
+ let refSelector;
1763
+ if (expectedValue.ref === "relative") {
1764
+ if (!expectedValue.relativeTarget || !context.relativeBaseSelector) return void 0;
1765
+ const baseLocator = page2.locator(context.relativeBaseSelector);
1766
+ const count = await baseLocator.count();
1767
+ let idx = 0;
1768
+ if (expectedValue.relativeTarget === "first") idx = 0;
1769
+ else if (expectedValue.relativeTarget === "second") idx = 1;
1770
+ else if (expectedValue.relativeTarget === "last") idx = count - 1;
1771
+ else if (!isNaN(Number(expectedValue.relativeTarget))) idx = Number(expectedValue.relativeTarget);
1772
+ else idx = 0;
1773
+ if (idx < 0 || idx >= count) return void 0;
1774
+ const relElem = baseLocator.nth(idx);
1775
+ return await getPropertyFromLocator(relElem, expectedValue.property || expectedValue.attribute);
1776
+ } else {
1777
+ refSelector = selectors[expectedValue.ref];
1778
+ if (!refSelector) throw new Error(`Selector for ref '${expectedValue.ref}' not found in contract selectors.`);
1779
+ const refLocator = page2.locator(refSelector).first();
1780
+ return await getPropertyFromLocator(refLocator, expectedValue.property || expectedValue.attribute);
1781
+ }
1782
+ }
1783
+ async function getPropertyFromLocator(locator, property) {
1784
+ if (!locator) return void 0;
1785
+ if (!property || property === "id") {
1786
+ return await locator.getAttribute("id") ?? void 0;
1787
+ } else if (property === "class") {
1788
+ return await locator.getAttribute("class") ?? void 0;
1789
+ } else if (property === "textContent") {
1790
+ return await locator.evaluate((el) => el.textContent ?? void 0);
1791
+ } else if (property.startsWith("aria-")) {
1792
+ return await locator.getAttribute(property) ?? void 0;
1793
+ } else if (property.endsWith("*")) {
1794
+ const attrs = await locator.evaluate((el) => {
1795
+ const out = [];
1796
+ for (const attr of Array.from(el.attributes)) {
1797
+ if (attr.name.startsWith("aria-")) out.push(`${attr.name}=${attr.value}`);
1798
+ }
1799
+ return out.join(";");
1800
+ });
1801
+ return attrs;
1802
+ } else {
1803
+ return await locator.getAttribute(property) ?? void 0;
1804
+ }
1805
+ }
1754
1806
  const staticAssertionRunner = new AssertionRunner(page, componentContract.selectors, assertionTimeoutMs);
1755
1807
  for (const test of componentContract.static[0]?.assertions || []) {
1756
1808
  if (test.target === "relative") continue;
@@ -1793,6 +1845,22 @@ This usually means:
1793
1845
  }
1794
1846
  return false;
1795
1847
  };
1848
+ let expectedValue = test.expectedValue;
1849
+ if (test.expectedValue && typeof test.expectedValue === "object" && "ref" in test.expectedValue) {
1850
+ const context = {};
1851
+ const relTarget = test.relativeTarget;
1852
+ if (test.expectedValue.ref === "relative" && test.target === "relative" && relTarget) {
1853
+ const baseSel = componentContract.selectors[relTarget];
1854
+ if (!baseSel) throw new Error(`Selector for relativeTarget '${relTarget}' not found in contract selectors.`);
1855
+ context.relativeBaseSelector = baseSel;
1856
+ } else if (test.expectedValue.ref === "relative" && relTarget) {
1857
+ const baseSel = componentContract.selectors[relTarget];
1858
+ if (!baseSel) throw new Error(`Selector for relativeTarget '${relTarget}' not found in contract selectors.`);
1859
+ context.relativeBaseSelector = baseSel;
1860
+ }
1861
+ expectedValue = await resolveExpectedValue(test.expectedValue, componentContract.selectors, page, context);
1862
+ console.log("Expected value in static check", expectedValue);
1863
+ }
1796
1864
  if (!test.expectedValue) {
1797
1865
  const attributes = test.attribute.split(" | ");
1798
1866
  let hasAny = false;
@@ -1826,16 +1894,17 @@ This usually means:
1826
1894
  reporter.reportStaticTest(staticDescription, "pass", void 0, staticLevel);
1827
1895
  }
1828
1896
  } else {
1829
- if (isRedundantCheck(targetSelector, test.attribute, test.expectedValue)) {
1830
- passes.push(`${test.attribute}="${test.expectedValue}" on ${test.target} verified by selector (already present in: ${targetSelector}).`);
1897
+ if (isRedundantCheck(targetSelector, test.attribute, typeof expectedValue === "string" ? expectedValue : void 0)) {
1898
+ passes.push(`${test.attribute}="${expectedValue}" on ${test.target} verified by selector (already present in: ${targetSelector}).`);
1831
1899
  staticPassed += 1;
1832
1900
  reporter.reportStaticTest(staticDescription, "pass", void 0, staticLevel);
1833
1901
  } else {
1902
+ const valueToCheck = expectedValue ?? "";
1834
1903
  const result = await staticAssertionRunner.validateAttribute(
1835
1904
  target,
1836
1905
  test.target,
1837
1906
  test.attribute,
1838
- test.expectedValue,
1907
+ valueToCheck,
1839
1908
  test.failureMessage,
1840
1909
  "Static ARIA Test"
1841
1910
  );
@@ -1953,7 +2022,33 @@ This usually means:
1953
2022
  continue;
1954
2023
  }
1955
2024
  for (const assertion of assertions) {
1956
- const result = await assertionRunner.validate(assertion, dynamicTest.description);
2025
+ let expectedValue;
2026
+ if (assertion.expectedValue && typeof assertion.expectedValue === "object" && "ref" in assertion.expectedValue) {
2027
+ if (assertion.expectedValue.ref === "relative") {
2028
+ const { RelativeTargetResolver: RelativeTargetResolver2 } = await Promise.resolve().then(() => (init_RelativeTargetResolver(), RelativeTargetResolver_exports));
2029
+ const relativeSelector = componentContract.selectors.relative;
2030
+ if (!relativeSelector) throw new Error("Relative selector not defined in contract selectors.");
2031
+ const relTarget = assertion.relativeTarget || "first";
2032
+ const relElem = await RelativeTargetResolver2.resolve(page, relativeSelector, relTarget);
2033
+ if (!relElem) throw new Error(`Could not resolve relative target '${relTarget}' for expectedValue.`);
2034
+ const prop = assertion.expectedValue.property || assertion.expectedValue.attribute || "id";
2035
+ if (prop === "textContent") {
2036
+ expectedValue = await relElem.evaluate((el) => el.textContent ?? void 0);
2037
+ } else {
2038
+ const attr = await relElem.getAttribute(prop);
2039
+ expectedValue = attr === null ? void 0 : attr;
2040
+ }
2041
+ } else {
2042
+ expectedValue = await resolveExpectedValue(assertion.expectedValue, componentContract.selectors, page, {});
2043
+ }
2044
+ } else if (typeof assertion.expectedValue === "string" || typeof assertion.expectedValue === "undefined") {
2045
+ expectedValue = assertion.expectedValue;
2046
+ } else {
2047
+ expectedValue = "";
2048
+ }
2049
+ const assertionToRun = { ...assertion, expectedValue };
2050
+ const valueToCheck = expectedValue ?? "";
2051
+ const result = await assertionRunner.validate({ ...assertionToRun, expectedValue: valueToCheck }, dynamicTest.description);
1957
2052
  if (result.success && result.passMessage) {
1958
2053
  passes.push(result.passMessage);
1959
2054
  } else if (!result.success && result.failMessage) {
@@ -2287,7 +2382,7 @@ async function runContractTests(contractPath, componentName, component, strictne
2287
2382
  staticPassed += 1;
2288
2383
  reporter.reportStaticTest(`${test.target} has ${test.attribute}`, "pass", void 0, staticLevel);
2289
2384
  }
2290
- } else if (!attributeValue || !test.expectedValue.split(" | ").includes(attributeValue)) {
2385
+ } else if (!attributeValue || typeof test.expectedValue === "string" && !test.expectedValue.split(" | ").includes(attributeValue)) {
2291
2386
  const outcome = classifyFailure(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`, test.level);
2292
2387
  if (outcome.status === "fail") staticFailed += 1;
2293
2388
  if (outcome.status === "warn") staticWarnings += 1;
@@ -1,4 +1,4 @@
1
- import { normalizeStrictness, closeSharedBrowser, ContractReporter, normalizeLevel, resolveEnforcement } from './chunk-FZ7GMIJB.js';
1
+ import { normalizeStrictness, closeSharedBrowser, ContractReporter, normalizeLevel, resolveEnforcement } from './chunk-4DU5Z5BR.js';
2
2
  import { axe } from 'jest-axe';
3
3
  import fs from 'fs/promises';
4
4
  import path from 'path';
@@ -144,7 +144,7 @@ async function runContractTests(contractPath, componentName, component, strictne
144
144
  staticPassed += 1;
145
145
  reporter.reportStaticTest(`${test.target} has ${test.attribute}`, "pass", void 0, staticLevel);
146
146
  }
147
- } else if (!attributeValue || !test.expectedValue.split(" | ").includes(attributeValue)) {
147
+ } else if (!attributeValue || typeof test.expectedValue === "string" && !test.expectedValue.split(" | ").includes(attributeValue)) {
148
148
  const outcome = classifyFailure(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`, test.level);
149
149
  if (outcome.status === "fail") staticFailed += 1;
150
150
  if (outcome.status === "warn") staticWarnings += 1;
@@ -228,7 +228,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
228
228
  const devServerUrl = await checkDevServer(url);
229
229
  if (devServerUrl) {
230
230
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
231
- const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-CIZOXYRW.js');
231
+ const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-5FT6K2WN.js');
232
232
  contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness, config, configBaseDir);
233
233
  } else {
234
234
  throw new Error(
@@ -4,7 +4,7 @@ import {
4
4
  normalizeLevel,
5
5
  normalizeStrictness,
6
6
  resolveEnforcement
7
- } from "./chunk-FZ7GMIJB.js";
7
+ } from "./chunk-4DU5Z5BR.js";
8
8
  import "./chunk-I2KLQ2HA.js";
9
9
 
10
10
  // src/utils/test/src/test.ts
@@ -153,7 +153,7 @@ async function runContractTests(contractPath, componentName, component, strictne
153
153
  staticPassed += 1;
154
154
  reporter.reportStaticTest(`${test.target} has ${test.attribute}`, "pass", void 0, staticLevel);
155
155
  }
156
- } else if (!attributeValue || !test.expectedValue.split(" | ").includes(attributeValue)) {
156
+ } else if (!attributeValue || typeof test.expectedValue === "string" && !test.expectedValue.split(" | ").includes(attributeValue)) {
157
157
  const outcome = classifyFailure(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`, test.level);
158
158
  if (outcome.status === "fail") staticFailed += 1;
159
159
  if (outcome.status === "warn") staticWarnings += 1;
@@ -240,7 +240,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
240
240
  const devServerUrl = await checkDevServer(url);
241
241
  if (devServerUrl) {
242
242
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
243
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-EWAWQVHT.js");
243
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-H24LQ45R.js");
244
244
  contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness, config, configBaseDir);
245
245
  } else {
246
246
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aria-ease",
3
- "version": "6.12.0",
3
+ "version": "6.12.1",
4
4
  "description": "Accessibility infrastructure for the entire frontend engineering lifecycle. Build accessible patterns, run automated audits, verify component interactions, and gate deployments — all in one system.",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "module",
@@ -46,7 +46,7 @@
46
46
  "bugs": {
47
47
  "url": "https://github.com/aria-ease/aria-ease/issues"
48
48
  },
49
- "homepage": "https://ariaease.site/docs",
49
+ "homepage": "https://ariaease.site/",
50
50
  "devDependencies": {
51
51
  "@axe-core/playwright": "^4.11.0",
52
52
  "@playwright/test": "^1.57.0",