aria-ease 6.11.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 +3 -3
- 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-XERMSYEH.js → chunk-4DU5Z5BR.js} +0 -23
- package/dist/{chunk-NI3MQCAS.js → chunk-GJGUY643.js} +2 -2
- package/dist/chunk-GLT43UVH.js +43 -0
- package/dist/cli.cjs +147 -84
- package/dist/cli.js +5 -5
- package/dist/{configLoader-DWHOHXHL.js → configLoader-Q7N5XV4P.js} +2 -2
- package/dist/{configLoader-UJZHQBYS.js → configLoader-REHK3S3Q.js} +1 -1
- package/dist/{contractTestRunnerPlaywright-QDXSK3FE.js → contractTestRunnerPlaywright-H24LQ45R.js} +113 -72
- package/dist/{contractTestRunnerPlaywright-WNWQYSXZ.js → contractTestRunnerPlaywright-NL3JNJYH.js} +113 -72
- package/dist/index.cjs +248 -112
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +124 -41
- 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-XERMSYEH.js → chunk-4DU5Z5BR.js} +1 -23
- package/dist/src/utils/test/chunk-GLT43UVH.js +41 -0
- package/dist/src/utils/test/{configLoader-SHJSRG2A.js → configLoader-NA7IBCS3.js} +2 -2
- package/dist/src/utils/test/{contractTestRunnerPlaywright-Z2AHXSNM.js → contractTestRunnerPlaywright-5FT6K2WN.js} +111 -71
- package/dist/src/utils/test/dsl/index.cjs +106 -29
- package/dist/src/utils/test/dsl/index.d.cts +3 -0
- package/dist/src/utils/test/dsl/index.d.ts +3 -0
- package/dist/src/utils/test/dsl/index.js +106 -29
- package/dist/src/utils/test/index.cjs +135 -76
- package/dist/src/utils/test/index.js +17 -11
- package/dist/{test-O3J4ZPQR.js → test-FYSJXQWO.js} +17 -12
- package/package.json +3 -4
- package/dist/src/utils/test/aria-contracts/accordion/accordion.contract.json +0 -290
- package/dist/src/utils/test/aria-contracts/combobox/combobox.listbox.contract.json +0 -463
- package/dist/src/utils/test/aria-contracts/menu/menu.contract.json +0 -562
- package/dist/src/utils/test/aria-contracts/tabs/tabs.contract.json +0 -361
package/dist/index.d.cts
CHANGED
|
@@ -288,10 +288,12 @@ declare class ContractBuilder {
|
|
|
288
288
|
ariaReference: (from: string, attribute: string, to: string) => {
|
|
289
289
|
required: () => void;
|
|
290
290
|
optional: () => void;
|
|
291
|
+
recommended: () => void;
|
|
291
292
|
};
|
|
292
293
|
contains: (parent: string, child: string) => {
|
|
293
294
|
required: () => void;
|
|
294
295
|
optional: () => void;
|
|
296
|
+
recommended: () => void;
|
|
295
297
|
};
|
|
296
298
|
}) => void): this;
|
|
297
299
|
static(fn: (s: {
|
|
@@ -299,6 +301,7 @@ declare class ContractBuilder {
|
|
|
299
301
|
has: (attribute: string, expectedValue: string) => {
|
|
300
302
|
required: () => void;
|
|
301
303
|
optional: () => void;
|
|
304
|
+
recommended: () => void;
|
|
302
305
|
};
|
|
303
306
|
};
|
|
304
307
|
}) => void): this;
|
package/dist/index.d.ts
CHANGED
|
@@ -288,10 +288,12 @@ declare class ContractBuilder {
|
|
|
288
288
|
ariaReference: (from: string, attribute: string, to: string) => {
|
|
289
289
|
required: () => void;
|
|
290
290
|
optional: () => void;
|
|
291
|
+
recommended: () => void;
|
|
291
292
|
};
|
|
292
293
|
contains: (parent: string, child: string) => {
|
|
293
294
|
required: () => void;
|
|
294
295
|
optional: () => void;
|
|
296
|
+
recommended: () => void;
|
|
295
297
|
};
|
|
296
298
|
}) => void): this;
|
|
297
299
|
static(fn: (s: {
|
|
@@ -299,6 +301,7 @@ declare class ContractBuilder {
|
|
|
299
301
|
has: (attribute: string, expectedValue: string) => {
|
|
300
302
|
required: () => void;
|
|
301
303
|
optional: () => void;
|
|
304
|
+
recommended: () => void;
|
|
302
305
|
};
|
|
303
306
|
};
|
|
304
307
|
}) => void): this;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ContractReporter,
|
|
3
3
|
closeSharedBrowser,
|
|
4
|
-
contract_default,
|
|
5
4
|
normalizeLevel,
|
|
6
5
|
normalizeStrictness,
|
|
7
6
|
resolveEnforcement
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4DU5Z5BR.js";
|
|
9
8
|
import "./chunk-I2KLQ2HA.js";
|
|
10
9
|
|
|
11
10
|
// src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
|
|
@@ -1118,6 +1117,7 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
|
|
|
1118
1117
|
} else if (comboboxInput.value) {
|
|
1119
1118
|
event.preventDefault();
|
|
1120
1119
|
comboboxInput.value = "";
|
|
1120
|
+
comboboxInput.setAttribute("aria-activedescendant", "");
|
|
1121
1121
|
const visibleItems2 = getVisibleItems();
|
|
1122
1122
|
visibleItems2.forEach((item) => {
|
|
1123
1123
|
if (item.getAttribute("aria-selected") === "true") item.setAttribute("aria-selected", "false");
|
|
@@ -1526,7 +1526,7 @@ function resolveSetup(setup, ctx) {
|
|
|
1526
1526
|
);
|
|
1527
1527
|
}
|
|
1528
1528
|
var COMBOBOX_STATES = {
|
|
1529
|
-
"
|
|
1529
|
+
"popup.open": {
|
|
1530
1530
|
setup: [
|
|
1531
1531
|
{
|
|
1532
1532
|
when: ["keyboard", "textInput"],
|
|
@@ -1543,7 +1543,7 @@ var COMBOBOX_STATES = {
|
|
|
1543
1543
|
],
|
|
1544
1544
|
assertion: isComboboxOpen
|
|
1545
1545
|
},
|
|
1546
|
-
"
|
|
1546
|
+
"popup.closed": {
|
|
1547
1547
|
setup: [
|
|
1548
1548
|
{
|
|
1549
1549
|
when: ["keyboard"],
|
|
@@ -1558,18 +1558,18 @@ var COMBOBOX_STATES = {
|
|
|
1558
1558
|
]
|
|
1559
1559
|
}
|
|
1560
1560
|
],
|
|
1561
|
-
assertion: isComboboxClosed
|
|
1561
|
+
assertion: [...isComboboxClosed(), ...isActiveDescendantEmpty()]
|
|
1562
1562
|
},
|
|
1563
|
-
"
|
|
1563
|
+
"main.focused": {
|
|
1564
1564
|
setup: [
|
|
1565
1565
|
{
|
|
1566
1566
|
when: ["keyboard"],
|
|
1567
1567
|
steps: () => [
|
|
1568
|
-
{ type: "focus", target: "
|
|
1568
|
+
{ type: "focus", target: "main" }
|
|
1569
1569
|
]
|
|
1570
1570
|
}
|
|
1571
1571
|
],
|
|
1572
|
-
assertion:
|
|
1572
|
+
assertion: isMainFocused
|
|
1573
1573
|
},
|
|
1574
1574
|
"input.filled": {
|
|
1575
1575
|
setup: [
|
|
@@ -1582,8 +1582,19 @@ var COMBOBOX_STATES = {
|
|
|
1582
1582
|
],
|
|
1583
1583
|
assertion: isInputFilled
|
|
1584
1584
|
},
|
|
1585
|
+
"input.notFilled": {
|
|
1586
|
+
setup: [
|
|
1587
|
+
{
|
|
1588
|
+
when: ["keyboard", "textInput"],
|
|
1589
|
+
steps: () => [
|
|
1590
|
+
{ type: "type", target: "input", value: "" }
|
|
1591
|
+
]
|
|
1592
|
+
}
|
|
1593
|
+
],
|
|
1594
|
+
assertion: isInputNotFilled
|
|
1595
|
+
},
|
|
1585
1596
|
"activeOption.first": {
|
|
1586
|
-
requires: ["
|
|
1597
|
+
requires: ["popup.open"],
|
|
1587
1598
|
setup: [
|
|
1588
1599
|
{
|
|
1589
1600
|
when: ["keyboard"],
|
|
@@ -1592,7 +1603,7 @@ var COMBOBOX_STATES = {
|
|
|
1592
1603
|
]
|
|
1593
1604
|
}
|
|
1594
1605
|
],
|
|
1595
|
-
assertion:
|
|
1606
|
+
assertion: isActiveDescendantFirst
|
|
1596
1607
|
},
|
|
1597
1608
|
"activeOption.last": {
|
|
1598
1609
|
requires: ["activeOption.first"],
|
|
@@ -1604,10 +1615,30 @@ var COMBOBOX_STATES = {
|
|
|
1604
1615
|
]
|
|
1605
1616
|
}
|
|
1606
1617
|
],
|
|
1618
|
+
assertion: isActiveDescendantLast
|
|
1619
|
+
},
|
|
1620
|
+
"activeDescendant.notEmpty": {
|
|
1621
|
+
requires: [],
|
|
1622
|
+
setup: [
|
|
1623
|
+
{
|
|
1624
|
+
when: ["keyboard"],
|
|
1625
|
+
steps: () => []
|
|
1626
|
+
}
|
|
1627
|
+
],
|
|
1607
1628
|
assertion: isActiveDescendantNotEmpty
|
|
1608
1629
|
},
|
|
1630
|
+
"activeDescendant.Empty": {
|
|
1631
|
+
requires: [],
|
|
1632
|
+
setup: [
|
|
1633
|
+
{
|
|
1634
|
+
when: ["keyboard"],
|
|
1635
|
+
steps: () => []
|
|
1636
|
+
}
|
|
1637
|
+
],
|
|
1638
|
+
assertion: isActiveDescendantEmpty
|
|
1639
|
+
},
|
|
1609
1640
|
"selectedOption.first": {
|
|
1610
|
-
requires: ["
|
|
1641
|
+
requires: ["popup.open"],
|
|
1611
1642
|
setup: [
|
|
1612
1643
|
{
|
|
1613
1644
|
when: ["pointer"],
|
|
@@ -1619,7 +1650,7 @@ var COMBOBOX_STATES = {
|
|
|
1619
1650
|
assertion: () => isAriaSelected("first")
|
|
1620
1651
|
},
|
|
1621
1652
|
"selectedOption.last": {
|
|
1622
|
-
requires: ["
|
|
1653
|
+
requires: ["popup.open"],
|
|
1623
1654
|
setup: [
|
|
1624
1655
|
{
|
|
1625
1656
|
when: ["pointer"],
|
|
@@ -1634,43 +1665,76 @@ var COMBOBOX_STATES = {
|
|
|
1634
1665
|
function isComboboxOpen() {
|
|
1635
1666
|
return [
|
|
1636
1667
|
{
|
|
1637
|
-
target: "
|
|
1668
|
+
target: "popup",
|
|
1638
1669
|
assertion: "toBeVisible",
|
|
1639
|
-
failureMessage: "Expected
|
|
1670
|
+
failureMessage: "Expected popup to be visible"
|
|
1640
1671
|
},
|
|
1641
1672
|
{
|
|
1642
|
-
target: "
|
|
1673
|
+
target: "main",
|
|
1643
1674
|
assertion: "toHaveAttribute",
|
|
1644
1675
|
attribute: "aria-expanded",
|
|
1645
1676
|
expectedValue: "true",
|
|
1646
|
-
failureMessage: "Expect combobox
|
|
1677
|
+
failureMessage: "Expect combobox main to have aria-expanded='true'."
|
|
1647
1678
|
}
|
|
1648
1679
|
];
|
|
1649
1680
|
}
|
|
1650
1681
|
function isComboboxClosed() {
|
|
1651
1682
|
return [
|
|
1652
1683
|
{
|
|
1653
|
-
target: "
|
|
1684
|
+
target: "popup",
|
|
1654
1685
|
assertion: "notToBeVisible",
|
|
1655
|
-
failureMessage: "Expected
|
|
1686
|
+
failureMessage: "Expected popup to be closed"
|
|
1656
1687
|
},
|
|
1657
1688
|
{
|
|
1658
|
-
target: "
|
|
1689
|
+
target: "main",
|
|
1659
1690
|
assertion: "toHaveAttribute",
|
|
1660
1691
|
attribute: "aria-expanded",
|
|
1661
1692
|
expectedValue: "false",
|
|
1662
|
-
failureMessage: "Expect combobox
|
|
1693
|
+
failureMessage: "Expect combobox main to have aria-expanded='false'."
|
|
1694
|
+
}
|
|
1695
|
+
];
|
|
1696
|
+
}
|
|
1697
|
+
function isActiveDescendantFirst() {
|
|
1698
|
+
return [
|
|
1699
|
+
{
|
|
1700
|
+
target: "main",
|
|
1701
|
+
assertion: "toHaveAttribute",
|
|
1702
|
+
attribute: "aria-activedescendant",
|
|
1703
|
+
expectedValue: { ref: "relative", relativeTarget: "first", property: "id" },
|
|
1704
|
+
failureMessage: "Expected aria-activedescendant on main to match the id of the first option."
|
|
1705
|
+
}
|
|
1706
|
+
];
|
|
1707
|
+
}
|
|
1708
|
+
function isActiveDescendantLast() {
|
|
1709
|
+
return [
|
|
1710
|
+
{
|
|
1711
|
+
target: "main",
|
|
1712
|
+
assertion: "toHaveAttribute",
|
|
1713
|
+
attribute: "aria-activedescendant",
|
|
1714
|
+
expectedValue: { ref: "relative", relativeTarget: "last", property: "id" },
|
|
1715
|
+
failureMessage: "Expected aria-activedescendant on main to match the id of the last option."
|
|
1663
1716
|
}
|
|
1664
1717
|
];
|
|
1665
1718
|
}
|
|
1666
1719
|
function isActiveDescendantNotEmpty() {
|
|
1667
1720
|
return [
|
|
1668
1721
|
{
|
|
1669
|
-
target: "
|
|
1722
|
+
target: "main",
|
|
1670
1723
|
assertion: "toHaveAttribute",
|
|
1671
1724
|
attribute: "aria-activedescendant",
|
|
1672
1725
|
expectedValue: "!empty",
|
|
1673
|
-
failureMessage: "Expected aria-activedescendant to not be empty"
|
|
1726
|
+
failureMessage: "Expected aria-activedescendant on main to not be empty."
|
|
1727
|
+
}
|
|
1728
|
+
];
|
|
1729
|
+
}
|
|
1730
|
+
function isActiveDescendantEmpty() {
|
|
1731
|
+
return [
|
|
1732
|
+
{
|
|
1733
|
+
target: "main",
|
|
1734
|
+
assertion: "toHaveAttribute",
|
|
1735
|
+
attribute: "aria-activedescendant",
|
|
1736
|
+
expectedValue: "",
|
|
1737
|
+
failureMessage: "Expected aria-activedescendant on main to be empty."
|
|
1674
1738
|
}
|
|
1675
1739
|
];
|
|
1676
1740
|
}
|
|
@@ -1682,16 +1746,16 @@ function isAriaSelected(index) {
|
|
|
1682
1746
|
assertion: "toHaveAttribute",
|
|
1683
1747
|
attribute: "aria-selected",
|
|
1684
1748
|
expectedValue: "true",
|
|
1685
|
-
failureMessage: `Expected ${index} option to have aria-selected='true'
|
|
1749
|
+
failureMessage: `Expected ${index} option to have aria-selected='true'.`
|
|
1686
1750
|
}
|
|
1687
1751
|
];
|
|
1688
1752
|
}
|
|
1689
|
-
function
|
|
1753
|
+
function isMainFocused() {
|
|
1690
1754
|
return [
|
|
1691
1755
|
{
|
|
1692
|
-
target: "
|
|
1756
|
+
target: "main",
|
|
1693
1757
|
assertion: "toHaveFocus",
|
|
1694
|
-
failureMessage: "Expected
|
|
1758
|
+
failureMessage: "Expected main to be focused."
|
|
1695
1759
|
}
|
|
1696
1760
|
];
|
|
1697
1761
|
}
|
|
@@ -1701,14 +1765,24 @@ function isInputFilled() {
|
|
|
1701
1765
|
target: "input",
|
|
1702
1766
|
assertion: "toHaveValue",
|
|
1703
1767
|
expectedValue: "test",
|
|
1704
|
-
failureMessage: "Expected input to have the value 'test'"
|
|
1768
|
+
failureMessage: "Expected input to have the value 'test'."
|
|
1769
|
+
}
|
|
1770
|
+
];
|
|
1771
|
+
}
|
|
1772
|
+
function isInputNotFilled() {
|
|
1773
|
+
return [
|
|
1774
|
+
{
|
|
1775
|
+
target: "input",
|
|
1776
|
+
assertion: "toHaveValue",
|
|
1777
|
+
expectedValue: "",
|
|
1778
|
+
failureMessage: "Expected input to have the value ''."
|
|
1705
1779
|
}
|
|
1706
1780
|
];
|
|
1707
1781
|
}
|
|
1708
1782
|
|
|
1709
1783
|
// src/utils/test/dsl/src/contractBuilder.ts
|
|
1710
1784
|
var STATE_PACKS = {
|
|
1711
|
-
"combobox
|
|
1785
|
+
"combobox": COMBOBOX_STATES
|
|
1712
1786
|
// Add more mappings as needed
|
|
1713
1787
|
};
|
|
1714
1788
|
var FluentContract = class {
|
|
@@ -1742,11 +1816,13 @@ var ContractBuilder = class {
|
|
|
1742
1816
|
const api = {
|
|
1743
1817
|
ariaReference: (from, attribute, to) => ({
|
|
1744
1818
|
required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required" }),
|
|
1745
|
-
optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" })
|
|
1819
|
+
optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" }),
|
|
1820
|
+
recommended: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "recommended" })
|
|
1746
1821
|
}),
|
|
1747
1822
|
contains: (parent, child) => ({
|
|
1748
1823
|
required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
|
|
1749
|
-
optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" })
|
|
1824
|
+
optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" }),
|
|
1825
|
+
recommended: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "recommended" })
|
|
1750
1826
|
})
|
|
1751
1827
|
};
|
|
1752
1828
|
fn(api);
|
|
@@ -1757,7 +1833,8 @@ var ContractBuilder = class {
|
|
|
1757
1833
|
target: (target) => ({
|
|
1758
1834
|
has: (attribute, expectedValue) => ({
|
|
1759
1835
|
required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
|
|
1760
|
-
optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" })
|
|
1836
|
+
optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" }),
|
|
1837
|
+
recommended: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "recommended" })
|
|
1761
1838
|
})
|
|
1762
1839
|
})
|
|
1763
1840
|
};
|
|
@@ -1899,16 +1976,13 @@ import { axe } from "jest-axe";
|
|
|
1899
1976
|
|
|
1900
1977
|
// src/utils/test/src/contractTestRunner.ts
|
|
1901
1978
|
import fs from "fs/promises";
|
|
1902
|
-
async function runContractTests(componentName, component, strictness) {
|
|
1979
|
+
async function runContractTests(contractPath, componentName, component, strictness) {
|
|
1903
1980
|
const reporter = new ContractReporter(false);
|
|
1904
1981
|
const strictnessMode = normalizeStrictness(strictness);
|
|
1905
|
-
const contractTyped = contract_default;
|
|
1906
|
-
const contractPath = contractTyped[componentName]?.path;
|
|
1907
1982
|
if (!contractPath) {
|
|
1908
|
-
throw new Error(`No contract
|
|
1983
|
+
throw new Error(`No contract path provided for component: ${componentName}`);
|
|
1909
1984
|
}
|
|
1910
|
-
const
|
|
1911
|
-
const contractData = await fs.readFile(resolvedPath, "utf-8");
|
|
1985
|
+
const contractData = await fs.readFile(contractPath, "utf-8");
|
|
1912
1986
|
const componentContract = JSON.parse(contractData);
|
|
1913
1987
|
const totalTests = (componentContract.relationships?.length || 0) + (componentContract.static[0]?.assertions.length || 0) + componentContract.dynamic.length;
|
|
1914
1988
|
reporter.start(componentName, totalTests);
|
|
@@ -2043,7 +2117,7 @@ async function runContractTests(componentName, component, strictness) {
|
|
|
2043
2117
|
staticPassed += 1;
|
|
2044
2118
|
reporter.reportStaticTest(`${test.target} has ${test.attribute}`, "pass", void 0, staticLevel);
|
|
2045
2119
|
}
|
|
2046
|
-
} else if (!attributeValue || !test.expectedValue.split(" | ").includes(attributeValue)) {
|
|
2120
|
+
} else if (!attributeValue || typeof test.expectedValue === "string" && !test.expectedValue.split(" | ").includes(attributeValue)) {
|
|
2047
2121
|
const outcome = classifyFailure(test.failureMessage + ` Attribute value does not match expected value. Expected: ${test.expectedValue}, Found: ${attributeValue}`, test.level);
|
|
2048
2122
|
if (outcome.status === "fail") staticFailed += 1;
|
|
2049
2123
|
if (outcome.status === "warn") staticWarnings += 1;
|
|
@@ -2108,7 +2182,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
2108
2182
|
let configBaseDir = typeof process !== "undefined" ? process.cwd() : "";
|
|
2109
2183
|
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
2110
2184
|
try {
|
|
2111
|
-
const { loadConfig } = await import("./configLoader-
|
|
2185
|
+
const { loadConfig } = await import("./configLoader-Q7N5XV4P.js");
|
|
2112
2186
|
const result2 = await loadConfig(process.cwd());
|
|
2113
2187
|
config = result2.config;
|
|
2114
2188
|
if (result2.configPath) {
|
|
@@ -2130,7 +2204,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
2130
2204
|
const devServerUrl = await checkDevServer(url);
|
|
2131
2205
|
if (devServerUrl) {
|
|
2132
2206
|
console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
|
|
2133
|
-
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-
|
|
2207
|
+
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-NL3JNJYH.js");
|
|
2134
2208
|
contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness, config, configBaseDir);
|
|
2135
2209
|
} else {
|
|
2136
2210
|
throw new Error(
|
|
@@ -2140,7 +2214,16 @@ Please start your dev server and try again.`
|
|
|
2140
2214
|
}
|
|
2141
2215
|
} else if (component) {
|
|
2142
2216
|
console.log(`\u{1F3AD} Running component contract tests in JSDOM mode`);
|
|
2143
|
-
|
|
2217
|
+
const contractPath = config.test?.components?.find((comp) => comp?.name === componentName)?.contractPath;
|
|
2218
|
+
if (!contractPath) {
|
|
2219
|
+
throw new Error(`\u274C No contract path found for component: ${componentName}`);
|
|
2220
|
+
}
|
|
2221
|
+
contract = await runContractTests(
|
|
2222
|
+
path.resolve(configBaseDir, contractPath),
|
|
2223
|
+
componentName,
|
|
2224
|
+
component,
|
|
2225
|
+
strictness
|
|
2226
|
+
);
|
|
2144
2227
|
} else {
|
|
2145
2228
|
throw new Error("\u274C Either component or URL must be provided");
|
|
2146
2229
|
}
|
|
@@ -130,6 +130,7 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
|
|
|
130
130
|
} else if (comboboxInput.value) {
|
|
131
131
|
event.preventDefault();
|
|
132
132
|
comboboxInput.value = "";
|
|
133
|
+
comboboxInput.setAttribute("aria-activedescendant", "");
|
|
133
134
|
const visibleItems2 = getVisibleItems();
|
|
134
135
|
visibleItems2.forEach((item) => {
|
|
135
136
|
if (item.getAttribute("aria-selected") === "true") item.setAttribute("aria-selected", "false");
|
|
@@ -128,6 +128,7 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
|
|
|
128
128
|
} else if (comboboxInput.value) {
|
|
129
129
|
event.preventDefault();
|
|
130
130
|
comboboxInput.value = "";
|
|
131
|
+
comboboxInput.setAttribute("aria-activedescendant", "");
|
|
131
132
|
const visibleItems2 = getVisibleItems();
|
|
132
133
|
visibleItems2.forEach((item) => {
|
|
133
134
|
if (item.getAttribute("aria-selected") === "true") item.setAttribute("aria-selected", "false");
|
|
@@ -14,7 +14,7 @@ var ComboboxComponentStrategy = class {
|
|
|
14
14
|
const popupElement = page.locator(popupSelector).first();
|
|
15
15
|
const isPopupVisible = await popupElement.isVisible().catch(() => false);
|
|
16
16
|
if (!isPopupVisible) return;
|
|
17
|
-
let
|
|
17
|
+
let popupClosed = false;
|
|
18
18
|
let closeSelector = this.selectors.input;
|
|
19
19
|
if (!closeSelector && this.selectors.focusable) {
|
|
20
20
|
closeSelector = this.selectors.focusable;
|
|
@@ -25,18 +25,18 @@ var ComboboxComponentStrategy = class {
|
|
|
25
25
|
const closeElement = page.locator(closeSelector).first();
|
|
26
26
|
await closeElement.focus();
|
|
27
27
|
await page.keyboard.press("Escape");
|
|
28
|
-
|
|
28
|
+
popupClosed = await expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
29
29
|
}
|
|
30
|
-
if (!
|
|
30
|
+
if (!popupClosed && this.selectors.button) {
|
|
31
31
|
const buttonElement = page.locator(this.selectors.button).first();
|
|
32
32
|
await buttonElement.click({ timeout: this.actionTimeoutMs });
|
|
33
|
-
|
|
33
|
+
popupClosed = await expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
34
34
|
}
|
|
35
|
-
if (!
|
|
35
|
+
if (!popupClosed) {
|
|
36
36
|
await page.mouse.click(10, 10);
|
|
37
|
-
|
|
37
|
+
popupClosed = await expect(popupElement).toBeHidden({ timeout: this.assertionTimeoutMs }).then(() => true).catch(() => false);
|
|
38
38
|
}
|
|
39
|
-
if (!
|
|
39
|
+
if (!popupClosed) {
|
|
40
40
|
throw new Error(
|
|
41
41
|
`\u274C FATAL: Cannot close combobox popup between tests. Popup remains visible after trying:
|
|
42
42
|
1. Escape key
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RelativeTargetResolver } from './chunk-GLT43UVH.js';
|
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
import { chromium } from 'playwright';
|
|
2
2
|
|
|
3
|
-
// src/utils/test/contract/contract.json
|
|
4
|
-
var contract_default = {
|
|
5
|
-
menu: {
|
|
6
|
-
path: "./aria-contracts/menu/menu.contract.json",
|
|
7
|
-
component: "menu"
|
|
8
|
-
},
|
|
9
|
-
"combobox.listbox": {
|
|
10
|
-
path: "./aria-contracts/combobox/combobox.listbox.contract.json",
|
|
11
|
-
component: "combobox.listbox"
|
|
12
|
-
},
|
|
13
|
-
accordion: {
|
|
14
|
-
path: "./aria-contracts/accordion/accordion.contract.json",
|
|
15
|
-
component: "accordion"
|
|
16
|
-
},
|
|
17
|
-
tabs: {
|
|
18
|
-
path: "./aria-contracts/tabs/tabs.contract.json",
|
|
19
|
-
component: "tabs"
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
3
|
// src/utils/test/src/ContractReporter.ts
|
|
24
4
|
var ContractReporter = class {
|
|
25
5
|
startTime = 0;
|
|
@@ -328,9 +308,7 @@ async function getOrCreateContext() {
|
|
|
328
308
|
if (!sharedContext) {
|
|
329
309
|
const browser = await getOrCreateBrowser();
|
|
330
310
|
sharedContext = await browser.newContext({
|
|
331
|
-
// Isolated context - no permissions, no geolocation, etc.
|
|
332
311
|
permissions: [],
|
|
333
|
-
// Ignore HTTPS errors for local dev servers
|
|
334
312
|
ignoreHTTPSErrors: true
|
|
335
313
|
});
|
|
336
314
|
}
|
|
@@ -351,4 +329,4 @@ async function closeSharedBrowser() {
|
|
|
351
329
|
}
|
|
352
330
|
}
|
|
353
331
|
|
|
354
|
-
export { ContractReporter, closeSharedBrowser,
|
|
332
|
+
export { ContractReporter, closeSharedBrowser, createTestPage, normalizeLevel, normalizeStrictness, resolveEnforcement };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/utils/test/src/RelativeTargetResolver.ts
|
|
2
|
+
var RelativeTargetResolver = class {
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a relative target like "first", "second", "last", "next", "previous"
|
|
5
|
+
* @param page Playwright page instance
|
|
6
|
+
* @param selector Base selector to find elements
|
|
7
|
+
* @param relative Relative position (first, second, last, next, previous)
|
|
8
|
+
* @returns The resolved Locator or null if not found
|
|
9
|
+
*/
|
|
10
|
+
static async resolve(page, selector, relative) {
|
|
11
|
+
const items = await page.locator(selector).all();
|
|
12
|
+
switch (relative) {
|
|
13
|
+
case "first":
|
|
14
|
+
return items[0];
|
|
15
|
+
case "second":
|
|
16
|
+
return items[1];
|
|
17
|
+
case "last":
|
|
18
|
+
return items[items.length - 1];
|
|
19
|
+
case "next": {
|
|
20
|
+
const currentIndex = await page.evaluate(([sel]) => {
|
|
21
|
+
const items2 = Array.from(document.querySelectorAll(sel));
|
|
22
|
+
return items2.indexOf(document.activeElement);
|
|
23
|
+
}, [selector]);
|
|
24
|
+
const nextIndex = (currentIndex + 1) % items.length;
|
|
25
|
+
return items[nextIndex];
|
|
26
|
+
}
|
|
27
|
+
case "previous": {
|
|
28
|
+
const currentIndex = await page.evaluate(([sel]) => {
|
|
29
|
+
const items2 = Array.from(document.querySelectorAll(sel));
|
|
30
|
+
return items2.indexOf(document.activeElement);
|
|
31
|
+
}, [selector]);
|
|
32
|
+
const prevIndex = (currentIndex - 1 + items.length) % items.length;
|
|
33
|
+
return items[prevIndex];
|
|
34
|
+
}
|
|
35
|
+
default:
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { RelativeTargetResolver };
|
|
@@ -69,8 +69,8 @@ function validateConfig(config) {
|
|
|
69
69
|
if (typeof comp.name !== "string") {
|
|
70
70
|
errors.push(`test.components[${idx}].name must be a string`);
|
|
71
71
|
}
|
|
72
|
-
if (comp.
|
|
73
|
-
errors.push(`test.components[${idx}].
|
|
72
|
+
if (comp.contractPath !== void 0 && typeof comp.contractPath !== "string") {
|
|
73
|
+
errors.push(`test.components[${idx}].contractPath must be a string when provided`);
|
|
74
74
|
}
|
|
75
75
|
if (comp.strategyPath !== void 0 && typeof comp.strategyPath !== "string") {
|
|
76
76
|
errors.push(`test.components[${idx}].strategyPath must be a string when provided`);
|