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.
- package/README.md +2 -2
- package/dist/{ComboboxComponentStrategy-OGRVZXAF.js → ComboboxComponentStrategy-DU342VMB.js} +7 -7
- package/dist/RelativeTargetResolver-DJAITO6D.js +7 -0
- package/dist/{audit-RM6TCZ5C.js → audit-JYEPKLHR.js} +5 -0
- package/dist/{chunk-FZ7GMIJB.js → chunk-4DU5Z5BR.js} +0 -2
- package/dist/chunk-GLT43UVH.js +43 -0
- package/dist/cli.cjs +121 -21
- package/dist/cli.js +3 -3
- package/dist/{contractTestRunnerPlaywright-EWAWQVHT.js → contractTestRunnerPlaywright-H24LQ45R.js} +109 -53
- package/dist/{contractTestRunnerPlaywright-DIXP5DQ3.js → contractTestRunnerPlaywright-NL3JNJYH.js} +109 -53
- package/dist/index.cjs +216 -46
- package/dist/index.js +103 -28
- package/dist/src/combobox/index.cjs +1 -0
- package/dist/src/combobox/index.js +1 -0
- package/dist/src/utils/test/{ComboboxComponentStrategy-5AECQSRN.js → ComboboxComponentStrategy-XKQ72RFD.js} +7 -7
- package/dist/src/utils/test/RelativeTargetResolver-G2XDN2VV.js +1 -0
- package/dist/src/utils/test/{chunk-FZ7GMIJB.js → chunk-4DU5Z5BR.js} +0 -2
- package/dist/src/utils/test/chunk-GLT43UVH.js +41 -0
- package/dist/src/utils/test/{contractTestRunnerPlaywright-CIZOXYRW.js → contractTestRunnerPlaywright-5FT6K2WN.js} +107 -53
- package/dist/src/utils/test/dsl/index.cjs +99 -25
- package/dist/src/utils/test/dsl/index.js +99 -25
- package/dist/src/utils/test/index.cjs +116 -21
- package/dist/src/utils/test/index.js +3 -3
- package/dist/{test-HBPCSYH5.js → test-FYSJXQWO.js} +3 -3
- 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
|
|
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
|
-
|
|
721
|
+
popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
724
722
|
}
|
|
725
|
-
if (!
|
|
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
|
-
|
|
726
|
+
popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
729
727
|
}
|
|
730
|
-
if (!
|
|
728
|
+
if (!popupClosed) {
|
|
731
729
|
await page.mouse.click(10, 10);
|
|
732
|
-
|
|
730
|
+
popupClosed = await test.expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
733
731
|
}
|
|
734
|
-
if (!
|
|
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
|
|
1016
|
-
if (!
|
|
1017
|
-
return { success: false, error: `
|
|
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
|
|
1020
|
-
const exists = await
|
|
1021
|
+
const main = this.page.locator(mainSelector).first();
|
|
1022
|
+
const exists = await main.count();
|
|
1021
1023
|
if (!exists) {
|
|
1022
|
-
return { success: false, error: `
|
|
1024
|
+
return { success: false, error: `Main element not found for virtual focus.` };
|
|
1023
1025
|
}
|
|
1024
|
-
await
|
|
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,
|
|
1830
|
-
passes.push(`${test.attribute}="${
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
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/
|
|
49
|
+
"homepage": "https://ariaease.site/",
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@axe-core/playwright": "^4.11.0",
|
|
52
52
|
"@playwright/test": "^1.57.0",
|