Skip to content

Commit ac14634

Browse files
authored
Merge branch 'main' into list-item-custom-announcements
2 parents c3b050d + 3afc0e8 commit ac14634

7 files changed

Lines changed: 186 additions & 30 deletions

File tree

packages/main/cypress/specs/CheckBox.cy.tsx

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,14 @@ describe("Accessibility", () => {
406406
const accInfo = checkbox.accessibilityInfo;
407407

408408
// Description should come from accessibleName property
409-
expect(accInfo.description).to.equal("Custom Aria Label");
409+
expect(accInfo.description).to.equal("Accessibility Test Not checked");
410+
expect(accInfo.label).to.equal("Custom Aria Label");
410411

411412
expect(accInfo.readonly).to.be.true;
412413
expect(accInfo.required).to.be.true;
413414
expect(accInfo.disabled).to.be.false;
414-
415+
416+
expect(accInfo.type).to.equal("Checkbox");
415417
expect(accInfo.role).to.equal("checkbox");
416418
});
417419
});
@@ -432,26 +434,8 @@ describe("Accessibility", () => {
432434
const accInfo = checkbox.accessibilityInfo;
433435

434436
// Description should come from associated label
435-
expect(accInfo.description).to.equal("Label For Accessibility Test");
436-
});
437-
});
438-
439-
it("should provide correct accessibilityInfo description from text", () => {
440-
cy.mount(
441-
<>
442-
<CheckBox
443-
id="accessibilityTestCb2"
444-
text="Accessibility Test Text"
445-
></CheckBox>
446-
</>
447-
);
448-
449-
cy.get("#accessibilityTestCb2").then($checkbox => {
450-
const checkbox = $checkbox[0] as CheckBox;
451-
const accInfo = checkbox.accessibilityInfo;
452-
453-
// Description should come from text property
454-
expect(accInfo.description).to.equal("Accessibility Test Text");
437+
expect(accInfo.description).to.equal("Not checked");
438+
expect(accInfo.label).to.equal("Label For Accessibility Test");
455439
});
456440
});
457441

@@ -470,7 +454,8 @@ describe("Accessibility", () => {
470454
const accInfo = checkbox.accessibilityInfo;
471455

472456
// Description should come from associated label
473-
expect(accInfo.description).to.equal("Label For Accessibility Test");
457+
expect(accInfo.description).to.equal("Not checked");
458+
expect(accInfo.label).to.equal("Label For Accessibility Test");
474459
});
475460
});
476461
});

packages/main/cypress/specs/Select.cy.tsx

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,85 @@ describe("Select - Accessibility", () => {
513513
.find(".ui5-select-label-root")
514514
.should("contain.text", "SelectedOption – ExtraInfo");
515515
});
516+
517+
it("tests accessibilityInfo getter returns correct values", () => {
518+
cy.mount(
519+
<>
520+
<span id="labelRef">Reference Label</span>
521+
{/* Basic select with selected option */}
522+
<Select id="basicSelect">
523+
<Option value="Option1" selected>Option 1</Option>
524+
<Option value="Option2">Option 2</Option>
525+
</Select>
526+
527+
{/* Select with accessibleName */}
528+
<Select id="namedSelect" accessibleName="Select Name">
529+
<Option value="Option1" selected>Option 1</Option>
530+
</Select>
531+
532+
{/* Select with accessibleNameRef */}
533+
<Select id="refSelect" accessibleNameRef="labelRef">
534+
<Option value="Option1" selected>Option 1</Option>
535+
</Select>
536+
537+
{/* Select with readonly and required attributes */}
538+
<Select id="propsSelect" readonly required disabled>
539+
<Option value="Option1" selected>Option 1</Option>
540+
</Select>
541+
</>
542+
);
543+
544+
// Test basic select
545+
cy.get("#basicSelect").then(($select) => {
546+
const select = $select[0] as Select;
547+
const accessInfo = select.accessibilityInfo;
548+
549+
expect(accessInfo.role).to.equal("combobox");
550+
expect(accessInfo.type).to.equal("Listbox");
551+
expect(accessInfo.readonly).to.be.false;
552+
expect(accessInfo.required).to.be.false;
553+
expect(accessInfo.description).to.equal("Option 1"); // Just text
554+
expect(accessInfo.label).to.be.undefined; // No aria-label
555+
});
556+
557+
// Test select with accessibleName
558+
cy.get("#namedSelect").then(($select) => {
559+
const select = $select[0] as Select;
560+
const accessInfo = select.accessibilityInfo;
561+
562+
expect(accessInfo.description).to.equal("Option 1"); // Just text
563+
expect(accessInfo.label).to.equal("Select Name"); // Aria label
564+
});
565+
566+
// Test select with accessibleNameRef
567+
cy.get("#refSelect").then(($select) => {
568+
const select = $select[0] as Select;
569+
const accessInfo = select.accessibilityInfo;
570+
571+
expect(accessInfo.description).to.equal("Option 1"); // Just text
572+
expect(accessInfo.label).to.equal("Reference Label"); // Aria label from ref
573+
});
574+
575+
// Test select with readonly and required properties
576+
cy.get("#propsSelect").then(($select) => {
577+
const select = $select[0] as Select;
578+
const accessInfo = select.accessibilityInfo;
579+
580+
expect(accessInfo.readonly).to.be.true;
581+
expect(accessInfo.required).to.be.true;
582+
expect(accessInfo.disabled).to.be.true;
583+
});
584+
585+
// Update the referenced label and check if the label updates
586+
cy.get("#labelRef").invoke("text", "Updated Reference");
587+
cy.get("#refSelect").then(($select) => {
588+
const select = $select[0] as Select;
589+
const accessInfo = select.accessibilityInfo;
590+
591+
expect(accessInfo.description).to.equal("Option 1"); // Text remains the same
592+
expect(accessInfo.label).to.equal("Updated Reference"); // Updated aria label from ref
593+
});
594+
});
516595
});
517596

518597
describe("Select - Popover", () => {
@@ -1740,4 +1819,4 @@ describe("Select general interaction", () => {
17401819
.should("have.attr", "selected");
17411820
cy.get("[ui5-select]").should("have.prop", "value", "C");
17421821
});
1743-
});
1822+
});

packages/main/cypress/specs/ToolbarSelect.cy.tsx

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Toolbar from "../../src/Toolbar.js";
22
import ToolbarSelect from "../../src/ToolbarSelect.js";
33
import ToolbarSelectOption from "../../src/ToolbarSelectOption.js";
4+
import Button from "../../src/Button.js";
45

56
describe("Toolbar general interaction", () => {
67
it("Should render the select with the correct attributes", () => {
@@ -264,10 +265,10 @@ describe("Toolbar general interaction", () => {
264265
cy.mount(
265266
<Toolbar id="otb_d">
266267
<ToolbarSelect style="width: 201px;" id="toolbar-select">
267-
<ToolbarSelectOption>1</ToolbarSelectOption>
268-
<ToolbarSelectOption selected>2</ToolbarSelectOption>
269-
<ToolbarSelectOption>3</ToolbarSelectOption>
270-
</ToolbarSelect>
268+
<ToolbarSelectOption>1</ToolbarSelectOption>
269+
<ToolbarSelectOption selected>2</ToolbarSelectOption>
270+
<ToolbarSelectOption>3</ToolbarSelectOption>
271+
</ToolbarSelect>
271272
</Toolbar>
272273
);
273274
cy.viewport(220, 1080); // Set a small viewport width to trigger overflow
@@ -282,4 +283,65 @@ describe("Toolbar general interaction", () => {
282283
// Verify the toolbar-select is rendered inside the popover
283284
cy.get("ui5-toolbar-select").should("be.visible");
284285
});
286+
287+
it("Should update selection when option's selected property is changed programmatically", () => {
288+
cy.mount(
289+
<>
290+
<Toolbar>
291+
<ToolbarSelect>
292+
<ToolbarSelectOption>1</ToolbarSelectOption>
293+
<ToolbarSelectOption id="opt2">2</ToolbarSelectOption>
294+
<ToolbarSelectOption>3</ToolbarSelectOption>
295+
<ToolbarSelectOption>4</ToolbarSelectOption>
296+
</ToolbarSelect>
297+
</Toolbar>
298+
<Button id="btn">select option 2</Button>
299+
</>
300+
);
301+
302+
// Set up button click handler
303+
cy.get("#btn").then($btn => {
304+
$btn.get(0).addEventListener("ui5-click", () => {
305+
// First, deselect all options
306+
const select = document.querySelector("ui5-toolbar-select");
307+
const options = select?.querySelectorAll("ui5-toolbar-select-option");
308+
options?.forEach(opt => {
309+
(opt as ToolbarSelectOption).selected = false;
310+
});
311+
// Then select option 2
312+
const opt2 = document.getElementById("opt2") as ToolbarSelectOption;
313+
opt2.selected = true;
314+
});
315+
});
316+
317+
// Verify initial state - first option has selected attribute
318+
cy.get("[ui5-toolbar]")
319+
.find("[ui5-toolbar-select]")
320+
.shadow()
321+
.find("[ui5-select]")
322+
.find("[ui5-option]")
323+
.eq(0)
324+
.should("have.attr", "selected");
325+
326+
// Click button using realClick
327+
cy.get("#btn").realClick();
328+
329+
// Verify option 2 now has the selected attribute
330+
cy.get("[ui5-toolbar]")
331+
.find("[ui5-toolbar-select]")
332+
.shadow()
333+
.find("[ui5-select]")
334+
.find("[ui5-option]")
335+
.eq(1)
336+
.should("have.attr", "selected");
337+
338+
// Verify option 1 no longer has selected attribute
339+
cy.get("[ui5-toolbar]")
340+
.find("[ui5-toolbar-select]")
341+
.shadow()
342+
.find("[ui5-select]")
343+
.find("[ui5-option]")
344+
.eq(0)
345+
.should("not.have.attr", "selected");
346+
});
285347
});

packages/main/src/CheckBox.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import {
2222
VALUE_STATE_WARNING,
2323
VALUE_STATE_SUCCESS,
2424
FORM_CHECKABLE_REQUIRED,
25+
CHECKBOX_CHECKED,
26+
CHECKBOX_NOT_CHECKED,
27+
CHECKBOX_ARIA_TYPE,
2528
} from "./generated/i18n/i18n-defaults.js";
2629

2730
// Styles
@@ -466,9 +469,14 @@ class CheckBox extends UI5Element implements IFormInputElement {
466469
}
467470

468471
get accessibilityInfo() {
472+
const checkboxState = this.checked ? CheckBox.i18nBundle.getText(CHECKBOX_CHECKED) : CheckBox.i18nBundle.getText(CHECKBOX_NOT_CHECKED);
473+
const description = [this.text || "", checkboxState].filter(Boolean).join(" ");
474+
469475
return {
470476
role: this.accInfo.role,
471-
description: this.ariaLabelText || this.text || "",
477+
type: CheckBox.i18nBundle.getText(CHECKBOX_ARIA_TYPE),
478+
description,
479+
label: this.ariaLabelText,
472480
disabled: !!this.accInfo.ariaDisabled,
473481
readonly: !!this.accInfo.ariaReadonly,
474482
required: this.accInfo.ariaRequired,

packages/main/src/Select.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import "@ui5/webcomponents-icons/dist/information.js";
3434
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
3535
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
3636
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
37-
import type { Timeout } from "@ui5/webcomponents-base/dist/types.js";
37+
import type { Timeout, AriaRole } from "@ui5/webcomponents-base/dist/types.js";
3838
import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js";
3939
import { getScopedVarName } from "@ui5/webcomponents-base/dist/CustomElementsScope.js";
4040
import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js";
@@ -1174,6 +1174,18 @@ class Select extends UI5Element implements IFormInputElement {
11741174
return ids.length ? ids.join(" ") : undefined;
11751175
}
11761176

1177+
get accessibilityInfo() {
1178+
return {
1179+
role: "combobox" as AriaRole,
1180+
type: this._ariaRoleDescription,
1181+
description: this.text,
1182+
label: this.ariaLabelText,
1183+
readonly: this.readonly,
1184+
required: this.required,
1185+
disabled: this.disabled,
1186+
};
1187+
}
1188+
11771189
_updateAssociatedLabelsTexts() {
11781190
this._associatedDescriptionRefTexts = getAllAccessibleDescriptionRefTexts(this);
11791191
}

packages/main/src/ToolbarSelect.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class ToolbarSelect extends ToolbarItem {
9191
@slot({
9292
"default": true,
9393
type: HTMLElement,
94+
invalidateOnChildChange: true,
9495
})
9596
options!: Array<ToolbarSelectOption>;
9697

packages/main/src/i18n/messagebundle.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,15 @@ DYNAMIC_DATE_RANGE_LAST_YEARS_TEXT=Last X Years
925925
#XFLD: Text for the "Next Years" option in the DynamicDateRange component.
926926
DYNAMIC_DATE_RANGE_NEXT_YEARS_TEXT=Next X Years
927927

928+
#XACT: Text for checkbox state - checked
929+
CHECKBOX_CHECKED=Checked
930+
931+
#XACT: Text for checkbox state - not checked
932+
CHECKBOX_NOT_CHECKED=Not checked
933+
934+
#XACT: ARIA type for checkbox
935+
CHECKBOX_ARIA_TYPE=Checkbox
936+
928937
#XFLD: Label for the value input field in the DynamicDateRange component.
929938
DYNAMIC_DATE_RANGE_VALUE_LABEL_TEXT=Value for X
930939

0 commit comments

Comments
 (0)