@sapudex/web-components 2.51.0 → 2.53.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.
- package/cypress/specs/Avatar.cy.tsx +103 -0
- package/cypress/specs/CountrySelector.cy.tsx +21 -0
- package/cypress/specs/List.cy.tsx +119 -10
- package/cypress/specs/SelectBox.cy.tsx +426 -70
- package/dist/Avatar.d.ts +10 -1
- package/dist/Avatar.js +43 -3
- package/dist/Avatar.js.map +1 -1
- package/dist/AvatarTemplate.js +1 -1
- package/dist/AvatarTemplate.js.map +1 -1
- package/dist/CountrySelector.js +1 -0
- package/dist/CountrySelector.js.map +1 -1
- package/dist/List.d.ts +10 -0
- package/dist/List.js +35 -0
- package/dist/List.js.map +1 -1
- package/dist/ListGroupHeaderBase.js +3 -0
- package/dist/ListGroupHeaderBase.js.map +1 -1
- package/dist/ListItem.d.ts +1 -0
- package/dist/ListItem.js +11 -3
- package/dist/ListItem.js.map +1 -1
- package/dist/ListItemBase.d.ts +9 -0
- package/dist/ListItemBase.js +12 -0
- package/dist/ListItemBase.js.map +1 -1
- package/dist/ListSelectAll.js +1 -1
- package/dist/ListSelectAll.js.map +1 -1
- package/dist/MediaPlayer.js +8 -0
- package/dist/MediaPlayer.js.map +1 -1
- package/dist/SearchableListBase.d.ts +10 -0
- package/dist/SearchableListBase.js +29 -6
- package/dist/SearchableListBase.js.map +1 -1
- package/dist/SearchableListBaseTemplate.js +32 -5
- package/dist/SearchableListBaseTemplate.js.map +1 -1
- package/dist/SelectBase.d.ts +65 -1
- package/dist/SelectBase.js +446 -59
- package/dist/SelectBase.js.map +1 -1
- package/dist/SelectBox.d.ts +5 -0
- package/dist/SelectBox.js +33 -2
- package/dist/SelectBox.js.map +1 -1
- package/dist/SelectBoxTemplate.js +2 -2
- package/dist/SelectBoxTemplate.js.map +1 -1
- package/dist/assets/{InputSuggestions-7eP5S95I.js → InputSuggestions-0yCPXAmq.js} +1 -1
- package/dist/assets/{ListItemStandardExpandableTextTemplate-CLcWBFcg.js → ListItemStandardExpandableTextTemplate-DjZEnCXN.js} +1 -1
- package/dist/assets/{bundle-CkxyEA8c.css → bundle-C7Yft7IG.css} +1 -1
- package/dist/assets/{bundle.esm-D4--IDh7.js → bundle.esm-DJuMR5ko.js} +241 -241
- package/dist/assets/messagebundle_lv-D06tlATH.js +1 -0
- package/dist/assets/messagebundle_nl-BKUpVV-D.js +1 -0
- package/dist/css/themes/AccordionItem.css +1 -1
- package/dist/css/themes/BreadcrumbsPopover.css +1 -1
- package/dist/css/themes/Contact.css +1 -1
- package/dist/css/themes/Divider.css +1 -1
- package/dist/css/themes/FilterMenu.css +1 -1
- package/dist/css/themes/Link.css +1 -1
- package/dist/css/themes/ListGroupHeader.css +1 -1
- package/dist/css/themes/ListItem.css +1 -1
- package/dist/css/themes/MessageStrip.css +1 -1
- package/dist/css/themes/Search.css +1 -1
- package/dist/css/themes/SelectBase.css +1 -1
- package/dist/css/themes/SelectBox.css +1 -1
- package/dist/css/themes/Slider.css +1 -1
- package/dist/css/themes/Tile.css +1 -1
- package/dist/css/themes/Toast.css +1 -1
- package/dist/css/themes/Tooltip.css +1 -1
- package/dist/custom-elements-internal.json +167 -156
- package/dist/custom-elements.json +152 -141
- package/dist/generated/assets/i18n/messagebundle_lv.json +1 -1
- package/dist/generated/assets/i18n/messagebundle_nl.json +1 -1
- package/dist/generated/templates/ListTemplate.lit.js +1 -1
- package/dist/generated/templates/ListTemplate.lit.js.map +1 -1
- package/dist/generated/themes/AccordionItem.css.d.ts +1 -1
- package/dist/generated/themes/AccordionItem.css.js +1 -1
- package/dist/generated/themes/AccordionItem.css.js.map +1 -1
- package/dist/generated/themes/BreadcrumbsPopover.css.d.ts +1 -1
- package/dist/generated/themes/BreadcrumbsPopover.css.js +1 -1
- package/dist/generated/themes/BreadcrumbsPopover.css.js.map +1 -1
- package/dist/generated/themes/Contact.css.d.ts +1 -1
- package/dist/generated/themes/Contact.css.js +1 -1
- package/dist/generated/themes/Contact.css.js.map +1 -1
- package/dist/generated/themes/Divider.css.d.ts +1 -1
- package/dist/generated/themes/Divider.css.js +1 -1
- package/dist/generated/themes/Divider.css.js.map +1 -1
- package/dist/generated/themes/FilterMenu.css.d.ts +1 -1
- package/dist/generated/themes/FilterMenu.css.js +1 -1
- package/dist/generated/themes/FilterMenu.css.js.map +1 -1
- package/dist/generated/themes/Link.css.d.ts +1 -1
- package/dist/generated/themes/Link.css.js +1 -1
- package/dist/generated/themes/Link.css.js.map +1 -1
- package/dist/generated/themes/ListGroupHeader.css.d.ts +1 -1
- package/dist/generated/themes/ListGroupHeader.css.js +1 -1
- package/dist/generated/themes/ListGroupHeader.css.js.map +1 -1
- package/dist/generated/themes/ListItem.css.d.ts +1 -1
- package/dist/generated/themes/ListItem.css.js +1 -1
- package/dist/generated/themes/ListItem.css.js.map +1 -1
- package/dist/generated/themes/MessageStrip.css.d.ts +1 -1
- package/dist/generated/themes/MessageStrip.css.js +1 -1
- package/dist/generated/themes/MessageStrip.css.js.map +1 -1
- package/dist/generated/themes/Search.css.d.ts +1 -1
- package/dist/generated/themes/Search.css.js +1 -1
- package/dist/generated/themes/Search.css.js.map +1 -1
- package/dist/generated/themes/SelectBase.css.d.ts +1 -1
- package/dist/generated/themes/SelectBase.css.js +1 -1
- package/dist/generated/themes/SelectBase.css.js.map +1 -1
- package/dist/generated/themes/SelectBox.css.d.ts +1 -1
- package/dist/generated/themes/SelectBox.css.js +1 -1
- package/dist/generated/themes/SelectBox.css.js.map +1 -1
- package/dist/generated/themes/Slider.css.d.ts +1 -1
- package/dist/generated/themes/Slider.css.js +1 -1
- package/dist/generated/themes/Slider.css.js.map +1 -1
- package/dist/generated/themes/Tile.css.d.ts +1 -1
- package/dist/generated/themes/Tile.css.js +1 -1
- package/dist/generated/themes/Tile.css.js.map +1 -1
- package/dist/generated/themes/Toast.css.d.ts +1 -1
- package/dist/generated/themes/Toast.css.js +1 -1
- package/dist/generated/themes/Toast.css.js.map +1 -1
- package/dist/generated/themes/Tooltip.css.d.ts +1 -1
- package/dist/generated/themes/Tooltip.css.js +1 -1
- package/dist/generated/themes/Tooltip.css.js.map +1 -1
- package/dist/messagebundle_lv.properties +126 -0
- package/dist/messagebundle_nl.properties +126 -0
- package/dist/vscode.html-custom-data.json +1 -1
- package/dist/web-types.json +3 -3
- package/package.json +1 -1
- package/src/Avatar.ts +52 -3
- package/src/AvatarTemplate.tsx +2 -2
- package/src/CountrySelector.ts +1 -0
- package/src/List.hbs +2 -1
- package/src/List.ts +36 -0
- package/src/ListGroupHeaderBase.ts +3 -0
- package/src/ListItem.ts +12 -3
- package/src/ListItemBase.ts +11 -0
- package/src/ListSelectAll.ts +1 -1
- package/src/MediaPlayer.ts +8 -0
- package/src/SearchableListBase.ts +31 -8
- package/src/SearchableListBaseTemplate.tsx +38 -6
- package/src/SelectBase.ts +466 -69
- package/src/SelectBox.ts +37 -2
- package/src/SelectBoxTemplate.tsx +4 -3
- package/src/generated/templates/ListTemplate.lit.ts +1 -1
- package/src/generated/themes/AccordionItem.css.ts +1 -1
- package/src/generated/themes/BreadcrumbsPopover.css.ts +1 -1
- package/src/generated/themes/Contact.css.ts +1 -1
- package/src/generated/themes/Divider.css.ts +1 -1
- package/src/generated/themes/FilterMenu.css.ts +1 -1
- package/src/generated/themes/Link.css.ts +1 -1
- package/src/generated/themes/ListGroupHeader.css.ts +1 -1
- package/src/generated/themes/ListItem.css.ts +1 -1
- package/src/generated/themes/MessageStrip.css.ts +1 -1
- package/src/generated/themes/Search.css.ts +1 -1
- package/src/generated/themes/SelectBase.css.ts +1 -1
- package/src/generated/themes/SelectBox.css.ts +1 -1
- package/src/generated/themes/Slider.css.ts +1 -1
- package/src/generated/themes/Tile.css.ts +1 -1
- package/src/generated/themes/Toast.css.ts +1 -1
- package/src/generated/themes/Tooltip.css.ts +1 -1
- package/src/i18n/messagebundle_lv.properties +126 -0
- package/src/i18n/messagebundle_nl.properties +126 -0
- package/src/themes/AccordionItem.css +8 -3
- package/src/themes/BreadcrumbsPopover.css +1 -1
- package/src/themes/Contact.css +3 -3
- package/src/themes/Divider.css +2 -0
- package/src/themes/FilterMenu.css +1 -1
- package/src/themes/Link.css +20 -2
- package/src/themes/ListGroupHeader.css +18 -1
- package/src/themes/ListItem.css +2 -1
- package/src/themes/MessageStrip.css +8 -5
- package/src/themes/Search.css +3 -3
- package/src/themes/SelectBase.css +2 -1
- package/src/themes/SelectBox.css +10 -0
- package/src/themes/Slider.css +1 -1
- package/src/themes/Tile.css +2 -2
- package/src/themes/Toast.css +1 -1
- package/src/themes/Tooltip.css +1 -1
- package/dist/assets/messagebundle_lv-BHId5zho.js +0 -1
- package/dist/assets/messagebundle_nl-etaldyfo.js +0 -1
|
@@ -702,24 +702,22 @@ describe("SelectBox", () => {
|
|
|
702
702
|
cy.get("#select-box").shadow().find(".udex-text-field__search").click();
|
|
703
703
|
cy.realPress("ArrowDown");
|
|
704
704
|
|
|
705
|
+
// Updated: DOM focus stays on the input; the active item is marked via _active-descendant.
|
|
705
706
|
cy.get("#select-box").shadow()
|
|
706
707
|
.find("udex-list-item").eq(0)
|
|
707
|
-
.
|
|
708
|
-
.should("be.focused");
|
|
708
|
+
.should("have.attr", "_active-descendant");
|
|
709
709
|
|
|
710
710
|
cy.realPress("ArrowDown");
|
|
711
711
|
|
|
712
712
|
cy.get("#select-box").shadow()
|
|
713
713
|
.find("udex-list-item").eq(1)
|
|
714
|
-
.
|
|
715
|
-
.should("be.focused");
|
|
714
|
+
.should("have.attr", "_active-descendant");
|
|
716
715
|
|
|
717
716
|
cy.realPress("ArrowUp");
|
|
718
717
|
|
|
719
718
|
cy.get("#select-box").shadow()
|
|
720
719
|
.find("udex-list-item").eq(0)
|
|
721
|
-
.
|
|
722
|
-
.should("be.focused");
|
|
720
|
+
.should("have.attr", "_active-descendant");
|
|
723
721
|
});
|
|
724
722
|
|
|
725
723
|
it("MultiSelect mode - arrow keys navigate through collapsible group header and its items", () => {
|
|
@@ -728,40 +726,35 @@ describe("SelectBox", () => {
|
|
|
728
726
|
cy.get("#select-box").shadow().find(".udex-text-field__search").click();
|
|
729
727
|
cy.realPress("ArrowDown");
|
|
730
728
|
|
|
729
|
+
// Updated: DOM focus stays on the input; the active group header is marked
|
|
730
|
+
// via the _active-descendant attribute rather than receiving DOM focus.
|
|
731
731
|
cy.get("#select-box").shadow()
|
|
732
|
-
.find("udex-list-group-header")
|
|
733
|
-
.
|
|
734
|
-
.find("[part=item]")
|
|
735
|
-
.should("be.focused");
|
|
732
|
+
.find("udex-list-group-header")
|
|
733
|
+
.should("have.attr", "_active-descendant");
|
|
736
734
|
|
|
737
735
|
cy.realPress("ArrowDown");
|
|
738
736
|
|
|
739
737
|
cy.get("#select-box").shadow()
|
|
740
738
|
.find("udex-list-item").eq(0)
|
|
741
|
-
.
|
|
742
|
-
.should("be.focused");
|
|
739
|
+
.should("have.attr", "_active-descendant");
|
|
743
740
|
|
|
744
741
|
cy.realPress("ArrowDown");
|
|
745
742
|
|
|
746
743
|
cy.get("#select-box").shadow()
|
|
747
744
|
.find("udex-list-item").eq(1)
|
|
748
|
-
.
|
|
749
|
-
.should("be.focused");
|
|
745
|
+
.should("have.attr", "_active-descendant");
|
|
750
746
|
|
|
751
747
|
cy.realPress("ArrowUp");
|
|
752
748
|
|
|
753
749
|
cy.get("#select-box").shadow()
|
|
754
750
|
.find("udex-list-item").eq(0)
|
|
755
|
-
.
|
|
756
|
-
.should("be.focused");
|
|
751
|
+
.should("have.attr", "_active-descendant");
|
|
757
752
|
|
|
758
753
|
cy.realPress("ArrowUp");
|
|
759
754
|
|
|
760
755
|
cy.get("#select-box").shadow()
|
|
761
|
-
.find("udex-list-group-header")
|
|
762
|
-
.
|
|
763
|
-
.find("[part=item]")
|
|
764
|
-
.should("be.focused");
|
|
756
|
+
.find("udex-list-group-header")
|
|
757
|
+
.should("have.attr", "_active-descendant");
|
|
765
758
|
});
|
|
766
759
|
|
|
767
760
|
it("MultiSelect mode - Left arrow collapses a collapsible group header, Right arrow expands it", () => {
|
|
@@ -770,12 +763,11 @@ describe("SelectBox", () => {
|
|
|
770
763
|
cy.get("#select-box").shadow().find(".udex-text-field__search").click();
|
|
771
764
|
cy.realPress("ArrowDown");
|
|
772
765
|
|
|
773
|
-
//
|
|
766
|
+
// Updated: the collapsible group header is the active descendant (DOM focus
|
|
767
|
+
// stays on the input), marked via the _active-descendant attribute.
|
|
774
768
|
cy.get("#select-box").shadow()
|
|
775
|
-
.find("udex-list-group-header")
|
|
776
|
-
.
|
|
777
|
-
.find("[part=item]")
|
|
778
|
-
.should("be.focused");
|
|
769
|
+
.find("udex-list-group-header")
|
|
770
|
+
.should("have.attr", "_active-descendant");
|
|
779
771
|
|
|
780
772
|
// Fixture starts expanded: neither the header host nor its children are collapsed.
|
|
781
773
|
cy.get("#select-box").shadow()
|
|
@@ -936,13 +928,14 @@ describe("SelectBox", () => {
|
|
|
936
928
|
|
|
937
929
|
cy.get("@trigger").click();
|
|
938
930
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
.
|
|
931
|
+
// Navigate into the list with ArrowDown (aria-activedescendant model keeps
|
|
932
|
+
// DOM focus on the input throughout). Shift+Tab then closes the dropdown
|
|
933
|
+
// and moves focus to the previous focusable element on the page.
|
|
934
|
+
cy.get("@select").find(".udex-text-field__search").realPress("ArrowDown");
|
|
942
935
|
|
|
943
936
|
cy.realPress(["Shift", "Tab"]);
|
|
944
937
|
|
|
945
|
-
cy.get("
|
|
938
|
+
cy.get("#previous-focus").should("be.focused");
|
|
946
939
|
});
|
|
947
940
|
|
|
948
941
|
it("focus moves to input and dropdown closes when press Esc on the list items", () => {
|
|
@@ -964,6 +957,18 @@ describe("SelectBox", () => {
|
|
|
964
957
|
.find(".udex-select-box__dropdown")
|
|
965
958
|
.should("not.have.attr","open");
|
|
966
959
|
});
|
|
960
|
+
|
|
961
|
+
it("focus() method moves focus to the inner search input", () => {
|
|
962
|
+
cy.mount(<UDExSelectBox id="select-box" label="Languages">
|
|
963
|
+
<UDExSelectBoxItem label="JavaScript"></UDExSelectBoxItem>
|
|
964
|
+
</UDExSelectBox>);
|
|
965
|
+
|
|
966
|
+
cy.get("#select-box").then($el => {
|
|
967
|
+
($el[0] as any).focus();
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
cy.get("#select-box").shadow().find(".udex-text-field__search").should("be.focused");
|
|
971
|
+
});
|
|
967
972
|
});
|
|
968
973
|
|
|
969
974
|
describe("Select Box Select All header tests",async () => {
|
|
@@ -1002,6 +1007,22 @@ describe("SelectBox", () => {
|
|
|
1002
1007
|
cy.get("@selectall")
|
|
1003
1008
|
.should("have.been.called");
|
|
1004
1009
|
});
|
|
1010
|
+
|
|
1011
|
+
// Bug fix: groupListClassName no longer appends _additionalClassName, so the
|
|
1012
|
+
// sticky marker forwarded from SelectBase must not land on the inner list container
|
|
1013
|
+
// (previously caused an unwanted padding-top gap at the top of the dropdown).
|
|
1014
|
+
it("does not apply the udex-list__sticky class to the inner list container", () => {
|
|
1015
|
+
cy.mount(selectAll);
|
|
1016
|
+
cy.get("#select-box").shadow().as("select");
|
|
1017
|
+
|
|
1018
|
+
cy.get("@select").find(".udex-text-field__trigger").click();
|
|
1019
|
+
|
|
1020
|
+
cy.get("@select")
|
|
1021
|
+
.find("udex-list")
|
|
1022
|
+
.find("udex-list-select-all").shadow()
|
|
1023
|
+
.find(".udex-list__group-list")
|
|
1024
|
+
.should("not.have.class", "udex-list__sticky");
|
|
1025
|
+
});
|
|
1005
1026
|
});
|
|
1006
1027
|
|
|
1007
1028
|
describe("Select Box events tests",async () => {
|
|
@@ -1542,11 +1563,12 @@ describe("SelectBox", () => {
|
|
|
1542
1563
|
.find(".udex-select-box__dropdown")
|
|
1543
1564
|
.should("have.attr", "open");
|
|
1544
1565
|
|
|
1566
|
+
// Updated: focus stays on the input; the last list item becomes the active
|
|
1567
|
+
// descendant (marked via _active-descendant) rather than receiving DOM focus.
|
|
1545
1568
|
cy.get("#select-box").shadow()
|
|
1546
1569
|
.find("udex-list-item")
|
|
1547
1570
|
.last()
|
|
1548
|
-
.
|
|
1549
|
-
.should("be.focused");
|
|
1571
|
+
.should("have.attr", "_active-descendant");
|
|
1550
1572
|
});
|
|
1551
1573
|
|
|
1552
1574
|
// when hasFooter is true, pressing Tab on a focused list item moves focus to the
|
|
@@ -1564,11 +1586,10 @@ describe("SelectBox", () => {
|
|
|
1564
1586
|
.find(".udex-select-box__dropdown")
|
|
1565
1587
|
.should("have.attr", "open");
|
|
1566
1588
|
|
|
1567
|
-
// A list item should now be
|
|
1589
|
+
// A list item should now be the active descendant (DOM focus stays on the input).
|
|
1568
1590
|
cy.get("#select-box").shadow()
|
|
1569
|
-
.find("udex-list-item").eq(0)
|
|
1570
|
-
.
|
|
1571
|
-
.should("be.focused");
|
|
1591
|
+
.find("udex-list-item").eq(0)
|
|
1592
|
+
.should("have.attr", "_active-descendant");
|
|
1572
1593
|
|
|
1573
1594
|
// Tab should be intercepted and focus redirected into the footer.
|
|
1574
1595
|
cy.realPress("Tab");
|
|
@@ -1866,15 +1887,17 @@ describe("SelectBox", () => {
|
|
|
1866
1887
|
cy.get("#next-focus").should("be.focused");
|
|
1867
1888
|
});
|
|
1868
1889
|
|
|
1869
|
-
it("Shift+Tab from list item closes dropdown and moves focus to
|
|
1890
|
+
it("Shift+Tab from list item closes dropdown and moves focus to previous focusable element", () => {
|
|
1870
1891
|
cy.mount(shortComponentWithFocusTargets);
|
|
1871
1892
|
openDropdownOnFirstItem();
|
|
1872
1893
|
|
|
1873
1894
|
cy.realPress(["Shift", "Tab"]);
|
|
1874
1895
|
|
|
1875
1896
|
cy.get("#select-box").shadow()
|
|
1876
|
-
.find(".udex-
|
|
1877
|
-
.should("
|
|
1897
|
+
.find(".udex-select-box__dropdown")
|
|
1898
|
+
.should("not.have.attr", "open");
|
|
1899
|
+
|
|
1900
|
+
cy.get("#previous-focus").should("be.focused");
|
|
1878
1901
|
});
|
|
1879
1902
|
|
|
1880
1903
|
it("Escape from list item closes dropdown and returns focus to trigger", () => {
|
|
@@ -1901,6 +1924,59 @@ describe("SelectBox", () => {
|
|
|
1901
1924
|
cy.get("#select-box").shadow().find("#firstIcon").should("be.focused");
|
|
1902
1925
|
});
|
|
1903
1926
|
|
|
1927
|
+
// Added: covers the _handleArrowRightInRow fix — before moving DOM focus into
|
|
1928
|
+
// the first icon button we call _setActiveDescendant(null), which strips the
|
|
1929
|
+
// _udex-active-descendant JS state marker from the list item so only the icon's
|
|
1930
|
+
// :focus ring is visible (not both rings simultaneously).
|
|
1931
|
+
it("ArrowRight into the first icon removes _udex-active-descendant from the list item", () => {
|
|
1932
|
+
cy.mount(shortComponentWithFocusTargets);
|
|
1933
|
+
openDropdownOnFirstItem();
|
|
1934
|
+
|
|
1935
|
+
// Precondition: the first list item is the active descendant before ArrowRight.
|
|
1936
|
+
cy.get("#select-box").shadow()
|
|
1937
|
+
.find("udex-list-item").eq(0)
|
|
1938
|
+
.should("have.class", "_udex-active-descendant");
|
|
1939
|
+
|
|
1940
|
+
cy.realPress("ArrowRight");
|
|
1941
|
+
|
|
1942
|
+
// The list item's active-descendant marker is cleared so it no longer shows a ring.
|
|
1943
|
+
cy.get("#select-box").shadow()
|
|
1944
|
+
.find("udex-list-item").eq(0)
|
|
1945
|
+
.should("not.have.class", "_udex-active-descendant");
|
|
1946
|
+
|
|
1947
|
+
// DOM focus moves onto the icon button (its :focus ring is now the only one).
|
|
1948
|
+
cy.get("#select-box").shadow().find("#firstIcon").should("be.focused");
|
|
1949
|
+
});
|
|
1950
|
+
|
|
1951
|
+
// Added: covers the _handleArrowLeftInRow fix — when ArrowLeft returns from the
|
|
1952
|
+
// first icon button back to the list item we call _setActiveDescendant(renderedItem)
|
|
1953
|
+
// then move DOM focus back to the search input. This restores the list item's
|
|
1954
|
+
// _udex-active-descendant ring while clearing the icon's :focus ring, so only the
|
|
1955
|
+
// list item's ring is visible (not both rings simultaneously).
|
|
1956
|
+
it("ArrowLeft from the first icon restores the list item ring and removes icon focus", () => {
|
|
1957
|
+
cy.mount(shortComponentWithFocusTargets);
|
|
1958
|
+
openDropdownOnFirstItem();
|
|
1959
|
+
|
|
1960
|
+
// Enter the first icon button.
|
|
1961
|
+
cy.realPress("ArrowRight");
|
|
1962
|
+
|
|
1963
|
+
// Precondition: DOM focus is on the icon button.
|
|
1964
|
+
cy.get("#select-box").shadow().find("#firstIcon").should("be.focused");
|
|
1965
|
+
|
|
1966
|
+
// Navigate back to the list item.
|
|
1967
|
+
cy.realPress("ArrowLeft");
|
|
1968
|
+
|
|
1969
|
+
// The list item's active-descendant marker is restored so its ring shows again.
|
|
1970
|
+
cy.get("#select-box").shadow()
|
|
1971
|
+
.find("udex-list-item").eq(0)
|
|
1972
|
+
.should("have.class", "_udex-active-descendant");
|
|
1973
|
+
|
|
1974
|
+
// DOM focus returns to the search input, clearing the icon's :focus ring.
|
|
1975
|
+
cy.get("#select-box").shadow()
|
|
1976
|
+
.find(".udex-text-field__search")
|
|
1977
|
+
.should("be.focused");
|
|
1978
|
+
});
|
|
1979
|
+
|
|
1904
1980
|
it("ArrowRight from firstIcon button focuses secondIcon button", () => {
|
|
1905
1981
|
cy.mount(shortComponentWithFocusTargets);
|
|
1906
1982
|
openDropdownOnFirstItem();
|
|
@@ -1940,10 +2016,11 @@ describe("SelectBox", () => {
|
|
|
1940
2016
|
cy.realPress("ArrowRight");
|
|
1941
2017
|
cy.realPress("ArrowLeft");
|
|
1942
2018
|
|
|
2019
|
+
// Updated: navigating back from the icon button makes the list item the
|
|
2020
|
+
// active descendant (DOM focus returns to the input, not the item).
|
|
1943
2021
|
cy.get("#select-box").shadow()
|
|
1944
2022
|
.find("udex-list-item").eq(0)
|
|
1945
|
-
.
|
|
1946
|
-
.should("be.focused");
|
|
2023
|
+
.should("have.attr", "_active-descendant");
|
|
1947
2024
|
});
|
|
1948
2025
|
|
|
1949
2026
|
it("ArrowDown from firstIcon button navigates to next list item", () => {
|
|
@@ -1955,8 +2032,7 @@ describe("SelectBox", () => {
|
|
|
1955
2032
|
|
|
1956
2033
|
cy.get("#select-box").shadow()
|
|
1957
2034
|
.find("udex-list-item").eq(1)
|
|
1958
|
-
.
|
|
1959
|
-
.should("be.focused");
|
|
2035
|
+
.should("have.attr", "_active-descendant");
|
|
1960
2036
|
});
|
|
1961
2037
|
|
|
1962
2038
|
it("ArrowUp from firstIcon button navigates to previous list item (wraps to last)", () => {
|
|
@@ -1968,8 +2044,7 @@ describe("SelectBox", () => {
|
|
|
1968
2044
|
|
|
1969
2045
|
cy.get("#select-box").shadow()
|
|
1970
2046
|
.find("udex-list-item").last()
|
|
1971
|
-
.
|
|
1972
|
-
.should("be.focused");
|
|
2047
|
+
.should("have.attr", "_active-descendant");
|
|
1973
2048
|
});
|
|
1974
2049
|
|
|
1975
2050
|
it("ArrowDown from secondIcon button navigates to next list item", () => {
|
|
@@ -1982,8 +2057,7 @@ describe("SelectBox", () => {
|
|
|
1982
2057
|
|
|
1983
2058
|
cy.get("#select-box").shadow()
|
|
1984
2059
|
.find("udex-list-item").eq(1)
|
|
1985
|
-
.
|
|
1986
|
-
.should("be.focused");
|
|
2060
|
+
.should("have.attr", "_active-descendant");
|
|
1987
2061
|
});
|
|
1988
2062
|
|
|
1989
2063
|
it("Escape from icon button closes dropdown and returns focus to input", () => {
|
|
@@ -2368,10 +2442,8 @@ describe("SelectBox", () => {
|
|
|
2368
2442
|
});
|
|
2369
2443
|
});
|
|
2370
2444
|
|
|
2371
|
-
//
|
|
2372
|
-
|
|
2373
|
-
// so it must NOT switch to the tree pattern even in MultiSelect + groups.
|
|
2374
|
-
describe("Tree accessibility pattern regression", () => {
|
|
2445
|
+
// Tree accessibility pattern: SelectBox uses tree pattern when group headers are present.
|
|
2446
|
+
describe("Tree accessibility pattern with group headers", () => {
|
|
2375
2447
|
const selectBoxMultiSelectGroup = <div style="width: 350px; position:relative;">
|
|
2376
2448
|
<UDExSelectBox
|
|
2377
2449
|
id="select-box-tree-regression"
|
|
@@ -2390,49 +2462,333 @@ describe("SelectBox", () => {
|
|
|
2390
2462
|
.find(".udex-text-field__trigger").click();
|
|
2391
2463
|
});
|
|
2392
2464
|
|
|
2393
|
-
it("host [udex-list] has
|
|
2465
|
+
it("host [udex-list] has aria-multiselectable=\"true\" (tree + MultiSelect)", () => {
|
|
2394
2466
|
cy.get("#select-box-tree-regression").shadow()
|
|
2395
|
-
.find("[udex-list]").should("
|
|
2467
|
+
.find("[udex-list]").should("have.attr", "aria-multiselectable", "true");
|
|
2396
2468
|
});
|
|
2397
2469
|
|
|
2398
|
-
|
|
2399
|
-
// non-tree mode — it now returns `defaultAccessibleRole` (`"listbox"` for SelectBox)
|
|
2400
|
-
// in every non-tree case. This aligns with the test's original intent (title says
|
|
2401
|
-
// "keeps role=\"listbox\""); the prior `role="group"` assertion was already stale.
|
|
2402
|
-
it("inner list div keeps role=\"listbox\" (not \"tree\")", () => {
|
|
2470
|
+
it("inner list div has role=\"tree\"", () => {
|
|
2403
2471
|
cy.get("#select-box-tree-regression").shadow()
|
|
2404
2472
|
.find("[udex-list]").shadow()
|
|
2405
|
-
.find("#udex-list").should("have.attr", "role", "
|
|
2473
|
+
.find("#udex-list").should("have.attr", "role", "tree");
|
|
2406
2474
|
});
|
|
2407
2475
|
|
|
2408
|
-
|
|
2409
|
-
// by a `_treeMode` boolean (reflected as the `_tree-mode` attribute). SelectBox is
|
|
2410
|
-
// not tree-capable so the boolean must stay false and the attribute must be absent.
|
|
2411
|
-
it("group header host has NO _tree-mode attribute", () => {
|
|
2476
|
+
it("group header host has _tree-mode attribute", () => {
|
|
2412
2477
|
cy.get("#select-box-tree-regression").shadow()
|
|
2413
2478
|
.find("udex-list-group-header")
|
|
2414
|
-
.should("
|
|
2479
|
+
.should("have.attr", "_tree-mode");
|
|
2415
2480
|
});
|
|
2416
2481
|
|
|
2417
|
-
it("child items have role=\"
|
|
2482
|
+
it("child items have role=\"treeitem\" on the host (aria-activedescendant pattern)", () => {
|
|
2418
2483
|
cy.get("#select-box-tree-regression").shadow()
|
|
2419
2484
|
.find("udex-list-group-header")
|
|
2420
|
-
.find("udex-list-item").eq(0)
|
|
2421
|
-
.
|
|
2485
|
+
.find("udex-list-item").eq(0)
|
|
2486
|
+
.should("have.attr", "role", "treeitem");
|
|
2487
|
+
});
|
|
2488
|
+
|
|
2489
|
+
it("child items have aria-checked on the host (MultiSelect tree)", () => {
|
|
2490
|
+
cy.get("#select-box-tree-regression").shadow()
|
|
2491
|
+
.find("udex-list-group-header")
|
|
2492
|
+
.find("udex-list-item").eq(0)
|
|
2493
|
+
.should("have.attr", "aria-checked", "false");
|
|
2422
2494
|
});
|
|
2423
2495
|
|
|
2424
|
-
it("child items
|
|
2496
|
+
it("child items' inner [part=item] div is role=\"presentation\" (host carries the role)", () => {
|
|
2425
2497
|
cy.get("#select-box-tree-regression").shadow()
|
|
2426
2498
|
.find("udex-list-group-header")
|
|
2427
2499
|
.find("udex-list-item").eq(0).shadow()
|
|
2428
|
-
.find("[part=item]").should("
|
|
2500
|
+
.find("[part=item]").should("have.attr", "role", "presentation");
|
|
2429
2501
|
});
|
|
2430
2502
|
|
|
2431
|
-
it("child items' checkbox is
|
|
2503
|
+
it("child items' checkbox is aria-hidden (tree mode, JAWS uses host aria-checked)", () => {
|
|
2432
2504
|
cy.get("#select-box-tree-regression").shadow()
|
|
2433
2505
|
.find("udex-list-group-header")
|
|
2434
2506
|
.find("udex-list-item").eq(0).shadow()
|
|
2435
|
-
.find("udex-checkbox").should("
|
|
2507
|
+
.find("udex-checkbox").should("have.attr", "aria-hidden");
|
|
2508
|
+
});
|
|
2509
|
+
});
|
|
2510
|
+
|
|
2511
|
+
// Covers the aria-live="polite" region that announces the active item
|
|
2512
|
+
// during keyboard navigation. _setActiveDescendant(item) sets _liveRegionText to
|
|
2513
|
+
// "Label, X of Y"; _setActiveDescendant(null) (on close/Escape) resets it to "".
|
|
2514
|
+
describe("Select Box live region announcements", () => {
|
|
2515
|
+
it("populates the live region with 'Label, X of Y' when ArrowDown activates an item", () => {
|
|
2516
|
+
cy.mount(shortComponent);
|
|
2517
|
+
cy.get("#select-box").shadow()
|
|
2518
|
+
.find(".udex-text-field__search")
|
|
2519
|
+
.click()
|
|
2520
|
+
.realPress("ArrowDown");
|
|
2521
|
+
|
|
2522
|
+
// shortComponent has 6 items; the first item "JavaScript" becomes active.
|
|
2523
|
+
cy.get("#select-box").shadow()
|
|
2524
|
+
.find('[aria-live="polite"]')
|
|
2525
|
+
.invoke("text")
|
|
2526
|
+
.should("match", /^JavaScript, 1 of 6$/);
|
|
2527
|
+
});
|
|
2528
|
+
|
|
2529
|
+
// Added: covers _treePositionText — for a grouped SelectBox the announcement
|
|
2530
|
+
// carries the tree position. ArrowDown activates the group header ("level 0");
|
|
2531
|
+
// a further ArrowDown reaches its first child ("level 1").
|
|
2532
|
+
it("uses tree positional text ('level 0' for the group header, 'level 1' for its child)", () => {
|
|
2533
|
+
cy.mount(groupHeaderCollapsible);
|
|
2534
|
+
cy.get("#select-box").shadow()
|
|
2535
|
+
.find(".udex-text-field__search")
|
|
2536
|
+
.click()
|
|
2537
|
+
.realPress("ArrowDown");
|
|
2538
|
+
|
|
2539
|
+
// ArrowDown activates the group header -> tree text reports "level 0".
|
|
2540
|
+
cy.get("#select-box").shadow()
|
|
2541
|
+
.find('[aria-live="polite"]')
|
|
2542
|
+
.invoke("text")
|
|
2543
|
+
.should("contain", "level 0");
|
|
2544
|
+
|
|
2545
|
+
// A further ArrowDown reaches the first child -> tree text reports "level 1".
|
|
2546
|
+
cy.get("#select-box").shadow()
|
|
2547
|
+
.find(".udex-text-field__search")
|
|
2548
|
+
.realPress("ArrowDown");
|
|
2549
|
+
|
|
2550
|
+
cy.get("#select-box").shadow()
|
|
2551
|
+
.find('[aria-live="polite"]')
|
|
2552
|
+
.invoke("text")
|
|
2553
|
+
.should("contain", "level 1");
|
|
2554
|
+
});
|
|
2555
|
+
|
|
2556
|
+
it("clears the live region text when the dropdown closes on Escape", () => {
|
|
2557
|
+
cy.mount(shortComponent);
|
|
2558
|
+
cy.get("#select-box").shadow()
|
|
2559
|
+
.find(".udex-text-field__search")
|
|
2560
|
+
.click()
|
|
2561
|
+
.realPress("ArrowDown");
|
|
2562
|
+
|
|
2563
|
+
// Precondition: the live region is populated by the navigation above.
|
|
2564
|
+
cy.get("#select-box").shadow()
|
|
2565
|
+
.find('[aria-live="polite"]')
|
|
2566
|
+
.invoke("text")
|
|
2567
|
+
.should("not.be.empty");
|
|
2568
|
+
|
|
2569
|
+
cy.get("#select-box").shadow()
|
|
2570
|
+
.find(".udex-text-field__search")
|
|
2571
|
+
.realPress("Escape");
|
|
2572
|
+
|
|
2573
|
+
cy.get("#select-box").shadow()
|
|
2574
|
+
.find(".udex-select-box__dropdown")
|
|
2575
|
+
.should("not.have.attr", "open");
|
|
2576
|
+
|
|
2577
|
+
// _setActiveDescendant(null) resets _liveRegionText to "".
|
|
2578
|
+
cy.get("#select-box").shadow()
|
|
2579
|
+
.find('[aria-live="polite"]')
|
|
2580
|
+
.invoke("text")
|
|
2581
|
+
.should("equal", "");
|
|
2582
|
+
});
|
|
2583
|
+
|
|
2584
|
+
it("appends 'Unselected' to the live region for an unchecked MultiSelect item", () => {
|
|
2585
|
+
cy.mount(multiSelect);
|
|
2586
|
+
cy.get("#select-box").shadow()
|
|
2587
|
+
.find(".udex-text-field__search")
|
|
2588
|
+
.click()
|
|
2589
|
+
.realPress("ArrowDown");
|
|
2590
|
+
|
|
2591
|
+
// First MultiSelect item is not selected -> state suffix is "Unselected".
|
|
2592
|
+
cy.get("#select-box").shadow()
|
|
2593
|
+
.find('[aria-live="polite"]')
|
|
2594
|
+
.should("contain.text", "Unselected");
|
|
2595
|
+
});
|
|
2596
|
+
|
|
2597
|
+
it("appends 'Selected' to the live region for a checked MultiSelect item", () => {
|
|
2598
|
+
const checkedMultiSelect = <div style="width: 350px; position:relative;">
|
|
2599
|
+
<UDExSelectBox
|
|
2600
|
+
id="select-box"
|
|
2601
|
+
height="400px"
|
|
2602
|
+
label="Programming languages"
|
|
2603
|
+
mode={UDExListMode.MultiSelect}>
|
|
2604
|
+
<UDExSelectBoxItem selected label="JavaScript" supportingText="Frontend web development"></UDExSelectBoxItem>
|
|
2605
|
+
<UDExSelectBoxItem label="Python" supportingText="Used in data analysis"></UDExSelectBoxItem>
|
|
2606
|
+
<UDExSelectBoxItem label="Java" supportingText="Building large-scale applications"></UDExSelectBoxItem>
|
|
2607
|
+
</UDExSelectBox>
|
|
2608
|
+
</div>;
|
|
2609
|
+
|
|
2610
|
+
cy.mount(checkedMultiSelect);
|
|
2611
|
+
cy.get("#select-box").shadow()
|
|
2612
|
+
.find(".udex-text-field__search")
|
|
2613
|
+
.click()
|
|
2614
|
+
.realPress("ArrowDown");
|
|
2615
|
+
|
|
2616
|
+
// First MultiSelect item is pre-selected -> state suffix is "Selected".
|
|
2617
|
+
cy.get("#select-box").shadow()
|
|
2618
|
+
.find('[aria-live="polite"]')
|
|
2619
|
+
.should("contain.text", "Selected");
|
|
2620
|
+
});
|
|
2621
|
+
|
|
2622
|
+
it("appends 'collapsed' to the live region for a collapsed collapsible group header", () => {
|
|
2623
|
+
const collapsedGroupHeader = <div style="width: 350px; position:relative;">
|
|
2624
|
+
<UDExSelectBox
|
|
2625
|
+
id="select-box"
|
|
2626
|
+
mode={UDExListMode.MultiSelect}
|
|
2627
|
+
label="Programming languages">
|
|
2628
|
+
<UDExSelectBoxGroupHeader label="Programming Languages" collapsible collapsed>
|
|
2629
|
+
<UDExSelectBoxItem label="JavaScript" supportingText="Frontend web development"></UDExSelectBoxItem>
|
|
2630
|
+
<UDExSelectBoxItem label="Python" supportingText="Used in data analysis"></UDExSelectBoxItem>
|
|
2631
|
+
</UDExSelectBoxGroupHeader>
|
|
2632
|
+
</UDExSelectBox>
|
|
2633
|
+
</div>;
|
|
2634
|
+
|
|
2635
|
+
cy.mount(collapsedGroupHeader);
|
|
2636
|
+
cy.get("#select-box").shadow()
|
|
2637
|
+
.find(".udex-text-field__search")
|
|
2638
|
+
.click()
|
|
2639
|
+
.realPress("ArrowDown");
|
|
2640
|
+
|
|
2641
|
+
// ArrowDown activates the collapsed group header -> tree text reports
|
|
2642
|
+
// "level 0" and the state suffix is "collapsed".
|
|
2643
|
+
cy.get("#select-box").shadow()
|
|
2644
|
+
.find('[aria-live="polite"]')
|
|
2645
|
+
.invoke("text")
|
|
2646
|
+
.should("contain", "level 0")
|
|
2647
|
+
.and("contain", "collapsed");
|
|
2648
|
+
});
|
|
2649
|
+
|
|
2650
|
+
it("appends 'expanded' to the live region for an expanded collapsible group header", () => {
|
|
2651
|
+
// groupHeaderCollapsible starts expanded (no `collapsed` attribute).
|
|
2652
|
+
cy.mount(groupHeaderCollapsible);
|
|
2653
|
+
cy.get("#select-box").shadow()
|
|
2654
|
+
.find(".udex-text-field__search")
|
|
2655
|
+
.click()
|
|
2656
|
+
.realPress("ArrowDown");
|
|
2657
|
+
|
|
2658
|
+
// ArrowDown activates the expanded group header -> tree text reports
|
|
2659
|
+
// "level 0" and the state suffix is "expanded".
|
|
2660
|
+
cy.get("#select-box").shadow()
|
|
2661
|
+
.find('[aria-live="polite"]')
|
|
2662
|
+
.invoke("text")
|
|
2663
|
+
.should("contain", "level 0")
|
|
2664
|
+
.and("contain", "expanded");
|
|
2665
|
+
});
|
|
2666
|
+
});
|
|
2667
|
+
|
|
2668
|
+
// Added: covers the double-outline / flicker fix. After a click on a list item
|
|
2669
|
+
// (SelectBase.handleItemSelection, MultiSelect path) or a group header
|
|
2670
|
+
// (SelectBox.handleHeaderPress), DOM focus is returned to the search input via
|
|
2671
|
+
// (this._search as HTMLElement).focus(). This prevents the clicked element from
|
|
2672
|
+
// retaining its CSS :focus ring while _udex-active-descendant later tracks a
|
|
2673
|
+
// different item during arrow navigation (which would show two rings at once).
|
|
2674
|
+
describe("Select Box click focus retention (double-outline fix)", () => {
|
|
2675
|
+
it("MultiSelect mode - clicking a list item returns DOM focus to the search input", () => {
|
|
2676
|
+
cy.mount(multiSelect);
|
|
2677
|
+
cy.get("#select-box").shadow().find(".udex-text-field__trigger").click();
|
|
2678
|
+
|
|
2679
|
+
cy.get("#select-box").shadow()
|
|
2680
|
+
.find(".udex-select-box__dropdown")
|
|
2681
|
+
.should("have.attr", "open");
|
|
2682
|
+
|
|
2683
|
+
// Click the second list item — the dropdown stays open in MultiSelect mode.
|
|
2684
|
+
cy.get("#select-box").shadow()
|
|
2685
|
+
.find("udex-list-item").eq(1)
|
|
2686
|
+
.click();
|
|
2687
|
+
|
|
2688
|
+
// The fix returns DOM focus to the search input rather than leaving it on
|
|
2689
|
+
// the clicked item.
|
|
2690
|
+
cy.get("#select-box").shadow()
|
|
2691
|
+
.find(".udex-text-field__search")
|
|
2692
|
+
.should("be.focused");
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2695
|
+
it("MultiSelect mode - the clicked list item does not retain DOM focus", () => {
|
|
2696
|
+
cy.mount(multiSelect);
|
|
2697
|
+
cy.get("#select-box").shadow().find(".udex-text-field__trigger").click();
|
|
2698
|
+
|
|
2699
|
+
cy.get("#select-box").shadow()
|
|
2700
|
+
.find("udex-list-item").eq(1)
|
|
2701
|
+
.click();
|
|
2702
|
+
|
|
2703
|
+
// The clicked item must NOT be the active element — otherwise its :focus
|
|
2704
|
+
// ring would linger alongside the active-descendant ring.
|
|
2705
|
+
cy.get("#select-box").shadow()
|
|
2706
|
+
.find("udex-list-item").eq(1)
|
|
2707
|
+
.should("not.be.focused");
|
|
2708
|
+
});
|
|
2709
|
+
|
|
2710
|
+
it("MultiSelect mode - clicking a group header returns DOM focus to the search input", () => {
|
|
2711
|
+
cy.mount(groupHeader);
|
|
2712
|
+
cy.get("#select-box").shadow().find(".udex-text-field__trigger").click();
|
|
2713
|
+
|
|
2714
|
+
cy.get("#select-box").shadow()
|
|
2715
|
+
.find(".udex-select-box__dropdown")
|
|
2716
|
+
.should("have.attr", "open");
|
|
2717
|
+
|
|
2718
|
+
// Click the group header's own focusable row (the inner udex-list-item in
|
|
2719
|
+
// the group header shadow) — this fires the header-press event which routes
|
|
2720
|
+
// to SelectBox.handleHeaderPress.
|
|
2721
|
+
cy.get("#select-box").shadow()
|
|
2722
|
+
.find("udex-list-group-header")
|
|
2723
|
+
.eq(0)
|
|
2724
|
+
.shadow()
|
|
2725
|
+
.find("udex-list-item")
|
|
2726
|
+
.click();
|
|
2727
|
+
|
|
2728
|
+
// SelectBox.handleHeaderPress calls (this._search).focus() after onHeaderPress,
|
|
2729
|
+
// so DOM focus must land on the search input.
|
|
2730
|
+
cy.get("#select-box").shadow()
|
|
2731
|
+
.find(".udex-text-field__search")
|
|
2732
|
+
.should("be.focused");
|
|
2733
|
+
});
|
|
2734
|
+
|
|
2735
|
+
it("MultiSelect mode - after clicking an item then ArrowDown, only the newly navigated item carries the active-descendant ring", () => {
|
|
2736
|
+
cy.mount(multiSelect);
|
|
2737
|
+
cy.get("#select-box").shadow().find(".udex-text-field__trigger").click();
|
|
2738
|
+
|
|
2739
|
+
cy.get("#select-box").shadow()
|
|
2740
|
+
.find(".udex-select-box__dropdown")
|
|
2741
|
+
.should("have.attr", "open");
|
|
2742
|
+
|
|
2743
|
+
// Click the second item (index 1). handleItemSelection sets it as the active
|
|
2744
|
+
// descendant and returns focus to the search input.
|
|
2745
|
+
cy.get("#select-box").shadow()
|
|
2746
|
+
.find("udex-list-item").eq(1)
|
|
2747
|
+
.click();
|
|
2748
|
+
|
|
2749
|
+
cy.get("#select-box").shadow()
|
|
2750
|
+
.find("udex-list-item").eq(1)
|
|
2751
|
+
.should("have.class", "_udex-active-descendant");
|
|
2752
|
+
|
|
2753
|
+
// ArrowDown (dispatched on the focused search input via onKeyDownSearch)
|
|
2754
|
+
// advances the active descendant to the third item (index 2).
|
|
2755
|
+
cy.realPress("ArrowDown");
|
|
2756
|
+
|
|
2757
|
+
// Only the newly navigated item (index 2) carries the ring class.
|
|
2758
|
+
cy.get("#select-box").shadow()
|
|
2759
|
+
.find("udex-list-item").eq(2)
|
|
2760
|
+
.should("have.class", "_udex-active-descendant");
|
|
2761
|
+
|
|
2762
|
+
// The previously clicked item (index 1) must have lost the ring class — no
|
|
2763
|
+
// double outline.
|
|
2764
|
+
cy.get("#select-box").shadow()
|
|
2765
|
+
.find("udex-list-item").eq(1)
|
|
2766
|
+
.should("not.have.class", "_udex-active-descendant");
|
|
2767
|
+
|
|
2768
|
+
// Exactly one element bears the active-descendant class at any time.
|
|
2769
|
+
cy.get("#select-box").shadow()
|
|
2770
|
+
.find("._udex-active-descendant")
|
|
2771
|
+
.should("have.length", 1);
|
|
2772
|
+
});
|
|
2773
|
+
});
|
|
2774
|
+
|
|
2775
|
+
// Added: covers aria-required wiring on the combobox input in SelectBoxTemplate.
|
|
2776
|
+
// The `required` boolean (inherited from SelectBase) drives aria-required={this.required}.
|
|
2777
|
+
describe("aria-required accessibility", () => {
|
|
2778
|
+
it("does not set aria-required=\"true\" on the combobox input by default (required not set)", () => {
|
|
2779
|
+
cy.mount(<UDExSelectBox id="select-box" label="Programming languages"></UDExSelectBox>);
|
|
2780
|
+
|
|
2781
|
+
cy.get("#select-box").shadow()
|
|
2782
|
+
.find('input[role="combobox"]')
|
|
2783
|
+
.should("not.have.attr", "aria-required", "true");
|
|
2784
|
+
});
|
|
2785
|
+
|
|
2786
|
+
it("sets aria-required=\"true\" on the combobox input when required is set", () => {
|
|
2787
|
+
cy.mount(<UDExSelectBox id="select-box" label="Programming languages" required></UDExSelectBox>);
|
|
2788
|
+
|
|
2789
|
+
cy.get("#select-box").shadow()
|
|
2790
|
+
.find('input[role="combobox"]')
|
|
2791
|
+
.should("have.attr", "aria-required", "true");
|
|
2436
2792
|
});
|
|
2437
2793
|
});
|
|
2438
2794
|
});
|