aria-ease 6.9.1 → 6.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +3 -3
  2. package/bin/{buildContracts-GBOY7UXG.js → buildContracts-S22V7AGV.js} +28 -0
  3. package/bin/{chunk-LMSKLN5O.js → chunk-NI3MQCAS.js} +34 -0
  4. package/bin/cli.cjs +235 -20
  5. package/bin/cli.js +4 -4
  6. package/bin/{configLoader-Q6A4JLKW.js → configLoader-UJZHQBYS.js} +1 -1
  7. package/{dist/contractTestRunnerPlaywright-XBWJZMR3.js → bin/contractTestRunnerPlaywright-QDXSK3FE.js} +173 -20
  8. package/bin/{test-OND56UUL.js → test-O3J4ZPQR.js} +2 -2
  9. package/dist/{configLoader-WTGJAP4Z.js → configLoader-DWHOHXHL.js} +34 -0
  10. package/{bin/contractTestRunnerPlaywright-ZZNWDUYP.js → dist/contractTestRunnerPlaywright-WNWQYSXZ.js} +173 -20
  11. package/dist/index.cjs +492 -298
  12. package/dist/index.d.cts +53 -53
  13. package/dist/index.d.ts +53 -53
  14. package/dist/index.js +289 -282
  15. package/dist/src/{Types.d-DYfYR3Vc.d.cts → Types.d-yGC2bBaB.d.cts} +1 -1
  16. package/dist/src/{Types.d-DYfYR3Vc.d.ts → Types.d-yGC2bBaB.d.ts} +1 -1
  17. package/dist/src/accordion/index.d.cts +1 -1
  18. package/dist/src/accordion/index.d.ts +1 -1
  19. package/dist/src/block/index.d.cts +1 -1
  20. package/dist/src/block/index.d.ts +1 -1
  21. package/dist/src/checkbox/index.d.cts +1 -1
  22. package/dist/src/checkbox/index.d.ts +1 -1
  23. package/dist/src/combobox/index.cjs +21 -7
  24. package/dist/src/combobox/index.d.cts +1 -1
  25. package/dist/src/combobox/index.d.ts +1 -1
  26. package/dist/src/combobox/index.js +21 -7
  27. package/dist/src/menu/index.d.cts +1 -1
  28. package/dist/src/menu/index.d.ts +1 -1
  29. package/dist/src/radio/index.d.cts +1 -1
  30. package/dist/src/radio/index.d.ts +1 -1
  31. package/dist/src/tabs/index.d.cts +1 -1
  32. package/dist/src/tabs/index.d.ts +1 -1
  33. package/dist/src/toggle/index.d.cts +1 -1
  34. package/dist/src/toggle/index.d.ts +1 -1
  35. package/dist/src/utils/test/{configLoader-YE2CYGDG.js → configLoader-SHJSRG2A.js} +34 -0
  36. package/dist/src/utils/test/{contractTestRunnerPlaywright-LC5OAVXB.js → contractTestRunnerPlaywright-Z2AHXSNM.js} +173 -20
  37. package/dist/src/utils/test/dsl/index.cjs +263 -270
  38. package/dist/src/utils/test/dsl/index.d.cts +53 -53
  39. package/dist/src/utils/test/dsl/index.d.ts +53 -53
  40. package/dist/src/utils/test/dsl/index.js +263 -270
  41. package/dist/src/utils/test/index.cjs +207 -20
  42. package/dist/src/utils/test/index.js +2 -2
  43. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1022,16 +1022,12 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1022
1022
  }
1023
1023
  function setActiveDescendant(index) {
1024
1024
  const visibleItems = getVisibleItems();
1025
- visibleItems.forEach((item) => {
1026
- item.setAttribute("aria-selected", "false");
1027
- });
1028
1025
  if (index >= 0 && index < visibleItems.length) {
1029
1026
  const activeItem = visibleItems[index];
1030
1027
  const itemId = activeItem.id || `${listBoxId}-option-${index}`;
1031
1028
  if (!activeItem.id) {
1032
1029
  activeItem.id = itemId;
1033
1030
  }
1034
- activeItem.setAttribute("aria-selected", "true");
1035
1031
  comboboxInput.setAttribute("aria-activedescendant", itemId);
1036
1032
  if (typeof activeItem.scrollIntoView === "function") {
1037
1033
  activeItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
@@ -1064,8 +1060,6 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1064
1060
  comboboxInput.setAttribute("aria-activedescendant", "");
1065
1061
  listBox.style.display = "none";
1066
1062
  activeIndex = -1;
1067
- const visibleItems = getVisibleItems();
1068
- visibleItems.forEach((item) => item.setAttribute("aria-selected", "false"));
1069
1063
  if (callback?.onOpenChange) {
1070
1064
  try {
1071
1065
  callback.onOpenChange(false);
@@ -1077,6 +1071,7 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1077
1071
  function selectOption(item) {
1078
1072
  const value = item.textContent?.trim() || "";
1079
1073
  comboboxInput.value = value;
1074
+ item.setAttribute("aria-selected", "true");
1080
1075
  closeListbox();
1081
1076
  if (callback?.onSelect) {
1082
1077
  try {
@@ -1123,6 +1118,10 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1123
1118
  } else if (comboboxInput.value) {
1124
1119
  event.preventDefault();
1125
1120
  comboboxInput.value = "";
1121
+ const visibleItems2 = getVisibleItems();
1122
+ visibleItems2.forEach((item) => {
1123
+ if (item.getAttribute("aria-selected") === "true") item.setAttribute("aria-selected", "false");
1124
+ });
1126
1125
  if (callback?.onClear) {
1127
1126
  try {
1128
1127
  callback.onClear();
@@ -1201,9 +1200,24 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1201
1200
  function initializeOptions() {
1202
1201
  const items = listBox.querySelectorAll(`.${listBoxItemsClass}`);
1203
1202
  if (items.length === 0) return;
1203
+ let selectedValue = null;
1204
+ for (const item of items) {
1205
+ if (item.getAttribute("aria-selected") === "true") {
1206
+ selectedValue = item.textContent?.trim() || null;
1207
+ break;
1208
+ }
1209
+ }
1210
+ if (!selectedValue && comboboxInput.value) {
1211
+ selectedValue = comboboxInput.value.trim();
1212
+ }
1204
1213
  items.forEach((item, index) => {
1205
1214
  item.setAttribute("role", "option");
1206
- item.setAttribute("aria-selected", "false");
1215
+ const itemValue = item.textContent?.trim() || "";
1216
+ if (selectedValue && itemValue === selectedValue) {
1217
+ item.setAttribute("aria-selected", "true");
1218
+ } else {
1219
+ item.setAttribute("aria-selected", "false");
1220
+ }
1207
1221
  const currentId = item.getAttribute("id");
1208
1222
  if (!currentId || currentId === "") {
1209
1223
  const itemId = `${listBoxId}-option-${index}`;
@@ -1494,7 +1508,151 @@ function makeTabsAccessible({ tabListId, tabsClass, tabPanelsClass, orientation
1494
1508
  return { activateTab, cleanup, refresh };
1495
1509
  }
1496
1510
 
1497
- // src/utils/test/dsl/index.ts
1511
+ // src/utils/test/dsl/src/state-packs/comboboxStatePack.ts
1512
+ var COMBOBOX_STATES = {
1513
+ "listbox.open": {
1514
+ setup: openCombobox(),
1515
+ assertion: isComboboxOpen()
1516
+ },
1517
+ "listbox.closed": {
1518
+ setup: closeCombobox(),
1519
+ assertion: isComboboxClosed()
1520
+ },
1521
+ "input.focused": {
1522
+ setup: focusInput(),
1523
+ assertion: [
1524
+ ...isInputFocused()
1525
+ ]
1526
+ },
1527
+ "input.filled": {
1528
+ setup: fillInput(),
1529
+ assertion: [
1530
+ ...isInputFilled()
1531
+ ]
1532
+ },
1533
+ "activeOption.first": {
1534
+ requires: ["listbox.open"],
1535
+ setup: [
1536
+ { type: "keypress", target: "input", key: "ArrowDown" }
1537
+ ],
1538
+ assertion: [
1539
+ ...isActiveDescendantNotEmpty()
1540
+ ]
1541
+ },
1542
+ "activeOption.last": {
1543
+ requires: ["activeOption.first"],
1544
+ setup: [
1545
+ { type: "keypress", target: "input", key: "ArrowUp" }
1546
+ ],
1547
+ assertion: [
1548
+ ...isActiveDescendantNotEmpty()
1549
+ ]
1550
+ },
1551
+ "selectedOption.first": {
1552
+ requires: ["listbox.open"],
1553
+ setup: [
1554
+ { type: "click", target: "relative", relativeTarget: "first" }
1555
+ ],
1556
+ assertion: [
1557
+ ...isAriaSelected("first")
1558
+ ]
1559
+ },
1560
+ "selectedOption.last": {
1561
+ requires: ["listbox.open"],
1562
+ setup: [
1563
+ { type: "click", target: "relative", relativeTarget: "last" }
1564
+ ],
1565
+ assertion: [
1566
+ ...isAriaSelected("first")
1567
+ ]
1568
+ }
1569
+ };
1570
+ function openCombobox() {
1571
+ return [
1572
+ { type: "keypress", target: "input", key: "ArrowDown" }
1573
+ ];
1574
+ }
1575
+ function closeCombobox() {
1576
+ return [
1577
+ { type: "keypress", target: "input", key: "Escape" }
1578
+ ];
1579
+ }
1580
+ function focusInput() {
1581
+ return [
1582
+ { type: "focus", target: "input" }
1583
+ ];
1584
+ }
1585
+ function fillInput() {
1586
+ return [
1587
+ { type: "type", target: "input", value: "test" }
1588
+ ];
1589
+ }
1590
+ function isComboboxOpen() {
1591
+ return [
1592
+ {
1593
+ target: "listbox",
1594
+ assertion: "toBeVisible",
1595
+ failureMessage: "Expected listbox to be visible"
1596
+ }
1597
+ ];
1598
+ }
1599
+ function isComboboxClosed() {
1600
+ return [
1601
+ {
1602
+ target: "listbox",
1603
+ assertion: "notToBeVisible",
1604
+ failureMessage: "Expected listbox to be closed"
1605
+ }
1606
+ ];
1607
+ }
1608
+ function isActiveDescendantNotEmpty() {
1609
+ return [
1610
+ {
1611
+ target: "input",
1612
+ assertion: "toHaveAttribute",
1613
+ attribute: "aria-activedescendant",
1614
+ expectedValue: "!empty",
1615
+ failureMessage: "Expected aria-activedescendant to not be empty"
1616
+ }
1617
+ ];
1618
+ }
1619
+ function isAriaSelected(index) {
1620
+ return [
1621
+ {
1622
+ target: "relative",
1623
+ relativeTarget: index,
1624
+ assertion: "toHaveAttribute",
1625
+ attribute: "aria-selected",
1626
+ expectedValue: "true",
1627
+ failureMessage: `Expected aria-selected on ${index} option to be true`
1628
+ }
1629
+ ];
1630
+ }
1631
+ function isInputFocused() {
1632
+ return [
1633
+ {
1634
+ target: "input",
1635
+ assertion: "toHaveFocus",
1636
+ failureMessage: "Expected input to be focused"
1637
+ }
1638
+ ];
1639
+ }
1640
+ function isInputFilled() {
1641
+ return [
1642
+ {
1643
+ target: "input",
1644
+ assertion: "toHaveValue",
1645
+ expectedValue: "test",
1646
+ failureMessage: "Expected input to have the value 'test'"
1647
+ }
1648
+ ];
1649
+ }
1650
+
1651
+ // src/utils/test/dsl/src/contractBuilder.ts
1652
+ var STATE_PACKS = {
1653
+ "combobox.listbox": COMBOBOX_STATES
1654
+ // Add more mappings as needed
1655
+ };
1498
1656
  var FluentContract = class {
1499
1657
  constructor(jsonContract) {
1500
1658
  this.jsonContract = jsonContract;
@@ -1503,306 +1661,155 @@ var FluentContract = class {
1503
1661
  return this.jsonContract;
1504
1662
  }
1505
1663
  };
1506
- var StaticTargetBuilder = class {
1507
- constructor(targetName, sink) {
1508
- this.targetName = targetName;
1509
- this.sink = sink;
1510
- }
1511
- has(attribute, expectedValue) {
1512
- const create = (level) => {
1513
- this.sink.push({
1514
- target: this.targetName,
1515
- attribute,
1516
- expectedValue,
1517
- failureMessage: `Expected ${this.targetName} to have ${attribute}${expectedValue !== void 0 ? `=${expectedValue}` : ""}.`,
1518
- level
1519
- });
1520
- };
1521
- return {
1522
- required: () => create("required"),
1523
- recommended: () => create("recommended"),
1524
- optional: () => create("optional")
1525
- };
1526
- }
1527
- };
1528
- var StaticBuilder = class {
1529
- constructor(sink) {
1530
- this.sink = sink;
1531
- }
1532
- target(targetName) {
1533
- return new StaticTargetBuilder(targetName, this.sink);
1534
- }
1535
- };
1536
- var DynamicChain = class {
1537
- constructor(key, testsSink, selectors) {
1538
- this.key = key;
1539
- this.testsSink = testsSink;
1540
- this.selectors = selectors;
1541
- }
1542
- selectorTarget = "";
1543
- actions = [];
1544
- assertions = [];
1545
- explicitDescription = "";
1546
- on(target) {
1547
- this.selectorTarget = target;
1548
- this.actions.push({ type: "keypress", target, key: this.key });
1549
- return this;
1550
- }
1551
- describe(description) {
1552
- this.explicitDescription = description;
1553
- return this;
1664
+ var ContractBuilder = class {
1665
+ constructor(componentName) {
1666
+ this.componentName = componentName;
1667
+ this.statePack = STATE_PACKS[componentName] || {};
1554
1668
  }
1555
- focus(targetExpression) {
1556
- const parsed = this.parseRelativeExpression(targetExpression);
1557
- if (parsed) {
1558
- if (!this.selectors[parsed.selectorKey]) {
1559
- const availableSelectors = Object.keys(this.selectors).sort().join(", ") || "(none)";
1560
- throw new Error(
1561
- `Invalid focus target expression "${targetExpression}": selector "${parsed.selectorKey}" is not defined. Available selectors: ${availableSelectors}`
1562
- );
1563
- }
1564
- if (!this.selectors.relative && this.selectors[parsed.selectorKey]) {
1565
- this.selectors.relative = this.selectors[parsed.selectorKey];
1566
- }
1567
- this.assertions.push({
1568
- target: "relative",
1569
- assertion: "toHaveFocus",
1570
- relativeTarget: parsed.relativeTarget
1571
- });
1572
- } else {
1573
- this.assertions.push({
1574
- target: targetExpression,
1575
- assertion: "toHaveFocus"
1576
- });
1577
- }
1669
+ metaValue = {};
1670
+ selectorsValue = {};
1671
+ relationshipInvariants = [];
1672
+ staticAssertions = [];
1673
+ dynamicTests = [];
1674
+ statePack;
1675
+ meta(meta) {
1676
+ this.metaValue = meta;
1578
1677
  return this;
1579
1678
  }
1580
- visible(target) {
1581
- this.assertions.push({ target, assertion: "toBeVisible" });
1679
+ selectors(selectors) {
1680
+ this.selectorsValue = selectors;
1582
1681
  return this;
1583
1682
  }
1584
- hidden(target) {
1585
- this.assertions.push({ target, assertion: "notToBeVisible" });
1683
+ relationships(fn) {
1684
+ const api = {
1685
+ ariaReference: (from, attribute, to) => ({
1686
+ required: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "required" }),
1687
+ optional: () => this.relationshipInvariants.push({ type: "aria-reference", from, attribute, to, level: "optional" })
1688
+ }),
1689
+ contains: (parent, child) => ({
1690
+ required: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "required" }),
1691
+ optional: () => this.relationshipInvariants.push({ type: "contains", parent, child, level: "optional" })
1692
+ })
1693
+ };
1694
+ fn(api);
1586
1695
  return this;
1587
1696
  }
1588
- has(target, attribute, expectedValue) {
1589
- this.assertions.push({
1590
- target,
1591
- assertion: "toHaveAttribute",
1592
- attribute,
1593
- expectedValue
1594
- });
1697
+ static(fn) {
1698
+ const api = {
1699
+ target: (target) => ({
1700
+ has: (attribute, expectedValue) => ({
1701
+ required: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "required" }),
1702
+ optional: () => this.staticAssertions.push({ target, attribute, expectedValue, failureMessage: "", level: "optional" })
1703
+ })
1704
+ })
1705
+ };
1706
+ fn(api);
1595
1707
  return this;
1596
1708
  }
1597
- required() {
1598
- this.finalize("required");
1599
- }
1600
- recommended() {
1601
- this.finalize("recommended");
1709
+ when(event) {
1710
+ return new DynamicTestBuilder(this, this.statePack, event);
1602
1711
  }
1603
- optional() {
1604
- this.finalize("optional");
1605
- }
1606
- finalize(level) {
1607
- if (!this.selectorTarget) {
1608
- throw new Error("Dynamic contract chain requires .on(<selectorKey>) before level terminator.");
1609
- }
1610
- const description = this.explicitDescription || `Pressing ${this.key} on ${this.selectorTarget} satisfies expected behavior.`;
1611
- this.testsSink.push({
1612
- description,
1613
- level,
1614
- action: this.actions,
1615
- assertions: this.assertions.map((a) => ({ ...a, level }))
1616
- });
1712
+ addDynamicTest(test) {
1713
+ this.dynamicTests.push(test);
1617
1714
  }
1618
- parseRelativeExpression(input) {
1619
- const match = input.match(/^(next|previous|first|last)\(([^)]+)\)$/);
1620
- if (!match) return null;
1621
- const relativeTarget = match[1];
1622
- const selectorKey = match[2].trim();
1623
- return { relativeTarget, selectorKey };
1715
+ build() {
1716
+ return {
1717
+ meta: this.metaValue,
1718
+ selectors: this.selectorsValue,
1719
+ relationships: this.relationshipInvariants.length ? this.relationshipInvariants : void 0,
1720
+ static: this.staticAssertions.length ? [{ assertions: this.staticAssertions }] : [],
1721
+ dynamic: this.dynamicTests
1722
+ };
1624
1723
  }
1625
1724
  };
1626
- var ContractBuilder = class {
1627
- constructor(componentName) {
1628
- this.componentName = componentName;
1629
- }
1630
- metaValue = {};
1631
- selectorsValue = {};
1632
- relationshipInvariants = [];
1633
- staticAssertions = [];
1634
- dynamicTests = [];
1635
- meta(meta) {
1636
- this.metaValue = { ...this.metaValue, ...meta };
1725
+ var DynamicTestBuilder = class {
1726
+ constructor(parent, statePack, event) {
1727
+ this.parent = parent;
1728
+ this.statePack = statePack;
1729
+ this.event = event;
1730
+ }
1731
+ _as;
1732
+ _on;
1733
+ _given = [];
1734
+ _then = [];
1735
+ _desc = "";
1736
+ _level = "required";
1737
+ as(actionType) {
1738
+ this._as = actionType;
1637
1739
  return this;
1638
1740
  }
1639
- selectors(selectors) {
1640
- this.selectorsValue = { ...this.selectorsValue, ...selectors };
1741
+ on(target) {
1742
+ this._on = target;
1641
1743
  return this;
1642
1744
  }
1643
- relationship(invariant) {
1644
- this.relationshipInvariants.push(invariant);
1745
+ given(states) {
1746
+ this._given = Array.isArray(states) ? states : [states];
1645
1747
  return this;
1646
1748
  }
1647
- relationships(builderFn) {
1648
- builderFn({
1649
- ariaReference: (from, attribute, to) => {
1650
- const create = (level) => {
1651
- this.relationshipInvariants.push({
1652
- type: "aria-reference",
1653
- from,
1654
- attribute,
1655
- to,
1656
- level
1657
- });
1658
- };
1659
- return {
1660
- required: () => create("required"),
1661
- recommended: () => create("recommended"),
1662
- optional: () => create("optional")
1663
- };
1664
- },
1665
- contains: (parent, child) => {
1666
- const create = (level) => {
1667
- this.relationshipInvariants.push({
1668
- type: "contains",
1669
- parent,
1670
- child,
1671
- level
1672
- });
1673
- };
1674
- return {
1675
- required: () => create("required"),
1676
- recommended: () => create("recommended"),
1677
- optional: () => create("optional")
1678
- };
1679
- }
1680
- });
1749
+ then(states) {
1750
+ this._then = Array.isArray(states) ? states : [states];
1681
1751
  return this;
1682
1752
  }
1683
- static(builderFn) {
1684
- builderFn(new StaticBuilder(this.staticAssertions));
1753
+ describe(desc) {
1754
+ this._desc = desc;
1685
1755
  return this;
1686
1756
  }
1687
- when(key) {
1688
- return new DynamicChain(key, this.dynamicTests, this.selectorsValue);
1757
+ required() {
1758
+ this._level = "required";
1759
+ this._finalize();
1760
+ return this.parent;
1689
1761
  }
1690
- validateRelationshipInvariants() {
1691
- if (this.relationshipInvariants.length === 0) {
1692
- return;
1693
- }
1694
- const selectorKeys = new Set(Object.keys(this.selectorsValue));
1695
- const available = Object.keys(this.selectorsValue).sort().join(", ");
1696
- const errors = [];
1697
- this.relationshipInvariants.forEach((invariant, index) => {
1698
- const prefix = `relationships[${index}] (${invariant.type})`;
1699
- if (invariant.type === "aria-reference") {
1700
- if (!selectorKeys.has(invariant.from)) {
1701
- errors.push(`${prefix}: "from" references unknown selector "${invariant.from}"`);
1702
- }
1703
- if (!selectorKeys.has(invariant.to)) {
1704
- errors.push(`${prefix}: "to" references unknown selector "${invariant.to}"`);
1705
- }
1706
- }
1707
- if (invariant.type === "contains") {
1708
- if (!selectorKeys.has(invariant.parent)) {
1709
- errors.push(`${prefix}: "parent" references unknown selector "${invariant.parent}"`);
1710
- }
1711
- if (!selectorKeys.has(invariant.child)) {
1712
- errors.push(`${prefix}: "child" references unknown selector "${invariant.child}"`);
1713
- }
1714
- }
1715
- });
1716
- if (errors.length > 0) {
1717
- const availableSelectorsMessage = available.length > 0 ? available : "(none)";
1718
- throw new Error(
1719
- [
1720
- `Contract invariant validation failed for component "${this.componentName}".`,
1721
- ...errors.map((error) => `- ${error}`),
1722
- `Available selectors: ${availableSelectorsMessage}`
1723
- ].join("\n")
1724
- );
1725
- }
1762
+ optional() {
1763
+ this._level = "optional";
1764
+ this._finalize();
1765
+ return this.parent;
1726
1766
  }
1727
- validateStaticTargets() {
1728
- const selectorKeys = new Set(Object.keys(this.selectorsValue));
1729
- const available = Object.keys(this.selectorsValue).sort().join(", ") || "(none)";
1730
- const errors = [];
1731
- this.staticAssertions.forEach((assertion, index) => {
1732
- if (!selectorKeys.has(assertion.target)) {
1733
- errors.push(`static.assertions[${index}]: target "${assertion.target}" is not defined in selectors`);
1767
+ recommended() {
1768
+ this._level = "recommended";
1769
+ this._finalize();
1770
+ return this.parent;
1771
+ }
1772
+ _finalize() {
1773
+ const resolveSetup = (stateName, visited = /* @__PURE__ */ new Set()) => {
1774
+ if (visited.has(stateName)) return [];
1775
+ visited.add(stateName);
1776
+ const s = this.statePack[stateName];
1777
+ if (!s) return [];
1778
+ let actions = [];
1779
+ if (Array.isArray(s.requires)) {
1780
+ for (const req of s.requires) {
1781
+ actions = actions.concat(resolveSetup(req, visited));
1782
+ }
1734
1783
  }
1735
- });
1736
- if (errors.length > 0) {
1737
- throw new Error(
1738
- [
1739
- `Contract static target validation failed for component "${this.componentName}".`,
1740
- ...errors.map((error) => `- ${error}`),
1741
- `Available selectors: ${available}`
1742
- ].join("\n")
1743
- );
1744
- }
1745
- }
1746
- validateDynamicTargets() {
1747
- const selectorKeys = new Set(Object.keys(this.selectorsValue));
1748
- const available = Object.keys(this.selectorsValue).sort().join(", ") || "(none)";
1749
- const errors = [];
1750
- const isValidActionTarget = (target) => {
1751
- return selectorKeys.has(target) || target === "document" || target === "relative";
1752
- };
1753
- const isValidAssertionTarget = (target) => {
1754
- return selectorKeys.has(target) || target === "relative";
1784
+ if (s.setup) actions = actions.concat(s.setup);
1785
+ return actions;
1755
1786
  };
1756
- this.dynamicTests.forEach((test, testIndex) => {
1757
- test.action.forEach((action, actionIndex) => {
1758
- if (!isValidActionTarget(action.target)) {
1759
- errors.push(
1760
- `dynamic[${testIndex}].action[${actionIndex}]: target "${action.target}" is not defined in selectors`
1761
- );
1762
- }
1763
- });
1764
- test.assertions.forEach((assertion, assertionIndex) => {
1765
- if (!isValidAssertionTarget(assertion.target)) {
1766
- errors.push(
1767
- `dynamic[${testIndex}].assertions[${assertionIndex}]: target "${assertion.target}" is not defined in selectors`
1768
- );
1769
- }
1770
- if (assertion.target === "relative" && !this.selectorsValue.relative) {
1771
- errors.push(
1772
- `dynamic[${testIndex}].assertions[${assertionIndex}]: target "relative" requires selectors.relative to be defined`
1773
- );
1774
- }
1775
- });
1787
+ const setup = [];
1788
+ for (const state of this._given) {
1789
+ setup.push(...resolveSetup(state));
1790
+ }
1791
+ const assertions = [];
1792
+ for (const state of this._then) {
1793
+ const s = this.statePack[state];
1794
+ if (s && s.assertion) {
1795
+ if (Array.isArray(s.assertion)) assertions.push(...s.assertion);
1796
+ else assertions.push(s.assertion);
1797
+ }
1798
+ }
1799
+ const action = [
1800
+ {
1801
+ type: this._as,
1802
+ target: this._on,
1803
+ key: this._as === "keypress" ? this.event : void 0
1804
+ }
1805
+ ];
1806
+ this.parent.addDynamicTest({
1807
+ description: this._desc || "",
1808
+ level: this._level,
1809
+ action,
1810
+ assertions,
1811
+ ...setup.length ? { setup } : {}
1776
1812
  });
1777
- if (errors.length > 0) {
1778
- throw new Error(
1779
- [
1780
- `Contract dynamic target validation failed for component "${this.componentName}".`,
1781
- ...errors.map((error) => `- ${error}`),
1782
- `Available selectors: ${available}`,
1783
- `Allowed special targets: document, relative`
1784
- ].join("\n")
1785
- );
1786
- }
1787
- }
1788
- build() {
1789
- this.validateRelationshipInvariants();
1790
- this.validateStaticTargets();
1791
- this.validateDynamicTargets();
1792
- const fallbackId = this.metaValue.id || `aria-ease.contract.${this.componentName}`;
1793
- return {
1794
- meta: {
1795
- id: fallbackId,
1796
- version: this.metaValue.version || "1.0.0",
1797
- description: this.metaValue.description || `Fluent contract for ${this.componentName}`,
1798
- source: this.metaValue.source,
1799
- W3CName: this.metaValue.W3CName
1800
- },
1801
- selectors: this.selectorsValue,
1802
- relationships: this.relationshipInvariants,
1803
- static: [{ assertions: this.staticAssertions }],
1804
- dynamic: this.dynamicTests
1805
- };
1806
1813
  }
1807
1814
  };
1808
1815
  function createContract(componentName, define) {
@@ -2025,7 +2032,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
2025
2032
  let configBaseDir = typeof process !== "undefined" ? process.cwd() : "";
2026
2033
  if (typeof process !== "undefined" && typeof process.cwd === "function") {
2027
2034
  try {
2028
- const { loadConfig } = await import("./configLoader-WTGJAP4Z.js");
2035
+ const { loadConfig } = await import("./configLoader-DWHOHXHL.js");
2029
2036
  const result2 = await loadConfig(process.cwd());
2030
2037
  config = result2.config;
2031
2038
  if (result2.configPath) {
@@ -2047,7 +2054,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
2047
2054
  const devServerUrl = await checkDevServer(url);
2048
2055
  if (devServerUrl) {
2049
2056
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
2050
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-XBWJZMR3.js");
2057
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-WNWQYSXZ.js");
2051
2058
  contract = await runContractTestsPlaywright(componentName, devServerUrl, strictness, config, configBaseDir);
2052
2059
  } else {
2053
2060
  throw new Error(
@@ -88,4 +88,4 @@ interface MenuCallback {
88
88
  onOpenChange?: (isOpen: boolean) => void;
89
89
  }
90
90
 
91
- export type { AccordionConfig as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccessibilityInstance as a };
91
+ export type { AccessibilityInstance as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccordionConfig as a };
@@ -88,4 +88,4 @@ interface MenuCallback {
88
88
  onOpenChange?: (isOpen: boolean) => void;
89
89
  }
90
90
 
91
- export type { AccordionConfig as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccessibilityInstance as a };
91
+ export type { AccessibilityInstance as A, ComboboxConfig as C, MenuConfig as M, TabsConfig as T, AccordionConfig as a };
@@ -1,4 +1,4 @@
1
- import { A as AccordionConfig, a as AccessibilityInstance } from '../Types.d-DYfYR3Vc.cjs';
1
+ import { a as AccordionConfig, A as AccessibilityInstance } from '../Types.d-yGC2bBaB.cjs';
2
2
 
3
3
  /**
4
4
  * Makes an accordion accessible by managing ARIA attributes, keyboard interaction, and state.