Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui5-view-settings-dialog): clicking on the radio button/checkbox works #10706

Merged
merged 16 commits into from
Jan 31, 2025
Merged
179 changes: 179 additions & 0 deletions packages/fiori/cypress/specs/ViewSettingsDialog.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { html } from "lit";
import "../../src/ViewSettingsDialog.js";
import "../../src/SortItem.js";
import "../../src/FilterItem.js";
import "../../src/FilterItemOption.js";

describe("View settings dialog - selection", () => {
it("tests clicking on sort items (both on the text and radio button)", () => {
cy.mount(html`
<ui5-view-settings-dialog id="vsd" sort-ascending>
<ui5-sort-item slot="sortItems" text="Name" selected></ui5-sort-item>
<ui5-sort-item slot="sortItems" text="Position"></ui5-sort-item>
</ui5-view-settings-dialog>
`);

// Bind the "confirm" event - it will be called twice (first with Position, then with Name)
cy.get("[ui5-view-settings-dialog]")
.as("vsd")
.then(vsd => {
vsd.get(0).addEventListener("ui5-confirm", cy.stub().as("confirm"));
});

// Open the dialog and wait until it's visible
cy.get("@vsd")
.invoke("prop", "open", true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate invoke from other commands.

	cy.get("@vsd")
		.invoke("prop", "open", true)

	cy.get("@vsd")
		.shadow()
		.find("[ui5-dialog]")
		.should("be.visible");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

.shadow()
.find("[ui5-dialog]")
.should("be.visible");

// There should be 4 list items in the dialog - Ascending, Descending, Name, Position
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.should("have.length", 4);

// Click the TEXT of the 4th item (Position)
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.eq(3)
.shadow()
.find("span[part=title]") // we click the text itself first
.realClick();

// Click the OK button of the dialog
cy.get("@vsd")
.shadow()
.find("ui5-button[design=Emphasized]")
.realClick();

// Check if the confirm event was fired with sortBy = "Position"
cy.get("@confirm")
.should("be.called")
.its("firstCall.args.0.detail.sortBy")
.should("equal", "Position");

// Wait until the dialog is closed
cy.get("@vsd")
.shadow()
.find("[ui5-dialog]")
.should("not.be.visible");

// Open the dialog again and wait until it's visible
cy.get("@vsd")
.invoke("prop", "open", true)
.shadow()
.find("[ui5-dialog]")
.should("be.visible");

// Click the RADIO BUTTON of the 3th item (Name) instead of the text this time
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.eq(2)
.shadow()
.find("[ui5-radio-button]")
.realClick();

// Click the OK button of the dialog again
cy.get("@vsd")
.shadow()
.find("ui5-button[design=Emphasized]")
.realClick();

// Check if the confirm event was fired for a second time, now with sortBy = "Name"
cy.get("@confirm")
.should("be.called")
.its("secondCall.args.0.detail.sortBy")
.should("equal", "Name");
});

it("tests clicking on filter items, and filter item options (both on the text and checkbox)", () => {
cy.mount(html`
<ui5-view-settings-dialog id="vsd">
<ui5-filter-item slot="filterItems" text="Filter 1">
<ui5-filter-item-option slot="values" text="Some filter 1"></ui5-filter-item-option>
<ui5-filter-item-option slot="values" text="Some filter 2"></ui5-filter-item-option>
<ui5-filter-item-option slot="values" text="Some filter 3"></ui5-filter-item-option>
</ui5-filter-item>
<ui5-filter-item slot="filterItems" text="Filter 2">
<ui5-filter-item-option slot="values" text="Some filter 4"></ui5-filter-item-option>
<ui5-filter-item-option slot="values" text="Some filter 5"></ui5-filter-item-option>
<ui5-filter-item-option slot="values" text="Some filter 6"></ui5-filter-item-option>
</ui5-filter-item>
</ui5-view-settings-dialog>
`);

// Bind the "confirm" event - it will be called once with filters = [{"Filter 1":["Some filter 1","Some filter 3"]}]
cy.get("[ui5-view-settings-dialog]")
.as("vsd")
.then(vsd => {
vsd.get(0).addEventListener("ui5-confirm", cy.stub().as("confirm"));
});

// Open the dialog and wait until it's visible
cy.get("@vsd")
.invoke("prop", "open", true)
.shadow()
.find("[ui5-dialog]")
.should("be.visible");

// There should be 2 list items in the dialog - Filter 1 and Filter 2
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.should("have.length", 2);

// Click the "Filter 1" item
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.eq(0)
.shadow()
.find("span[part=title]")
.realClick();

// There should be 3 list items in the dialog - Some filter 1, Some filter 2, Some filter 3
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.should("have.length", 3);

// Click on the text of the first list item (Some filter 1)
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.eq(0)
.shadow()
.find("span[part=title]")
.realClick();

// Click on the checkbox of the third list item (Some filter 3)
cy.get("@vsd")
.shadow()
.find("[ui5-li]")
.eq(2)
.shadow()
.find("[ui5-checkbox]")
.realClick();

// Click the OK button of the dialog
cy.get("@vsd")
.shadow()
.find("ui5-button[design=Emphasized]")
.realClick();

// Check if the confirm event was fired with: filters = [{"Filter 1":["Some filter 1","Some filter 3"]}]
cy.get("@confirm")
.should("be.called")
.its("firstCall.args.0.detail.filters")
.should("deep.equal", [{ "Filter 1": ["Some filter 1", "Some filter 3"] }]);

// Wait until the dialog is closed
cy.get("@vsd")
.shadow()
.find("[ui5-dialog]")
.should("not.be.visible");
});
});
23 changes: 12 additions & 11 deletions packages/fiori/src/ViewSettingsDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import type { ChangeInfo } from "@ui5/webcomponents-base/dist/UI5Element.js";
import type Dialog from "@ui5/webcomponents/dist/Dialog.js";
import type List from "@ui5/webcomponents/dist/List.js";
import type { ListItemClickEventDetail } from "@ui5/webcomponents/dist/List.js";
import type { ListItemClickEventDetail, ListSelectionChangeEventDetail } from "@ui5/webcomponents/dist/List.js";
import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js";

Expand Down Expand Up @@ -515,33 +515,34 @@ class ViewSettingsDialog extends UI5Element {
this._currentMode = ViewSettingsDialogMode[mode];
}

_handleFilterValueItemClick(e: CustomEvent<ListItemClickEventDetail>) {
_handleFilterValueItemClick(e: CustomEvent<ListSelectionChangeEventDetail>) {
const itemText = e.detail.targetItem.innerText;

// Update the component state
this._currentSettings.filters = this._currentSettings.filters.map(filter => {
if (filter.selected) {
filter.filterOptions.forEach(option => {
if (option.text === e.detail.item.innerText) {
if (option.text === itemText) {
option.selected = !option.selected;
}
});
}
return filter;
});

this._setSelectedProp(e);
this._setSelectedProp(itemText);

this._currentSettings = JSON.parse(JSON.stringify(this._currentSettings));
}

/**
* Sets the selected property of the clicked item.
* @param e
* @private
*/
_setSelectedProp(e: CustomEvent<ListItemClickEventDetail>) {
_setSelectedProp(itemText: string) {
this.filterItems.forEach(filterItem => {
filterItem.values.forEach(option => {
if (option.text === e.detail.item.innerText) {
if (option.text === itemText) {
option.selected = !option.selected;
}
});
Expand Down Expand Up @@ -669,10 +670,10 @@ class ViewSettingsDialog extends UI5Element {
/**
* Stores `Sort Order` list as recently used control and its selected item in current state.
*/
_onSortOrderChange(e: CustomEvent<ListItemClickEventDetail>) {
_onSortOrderChange(e: CustomEvent<ListSelectionChangeEventDetail>) {
this._recentlyFocused = this._sortOrder!;
this._currentSettings.sortOrder = this.initSortOrderItems.map(item => {
item.selected = item.text === e.detail.item.innerText;
item.selected = item.text === e.detail.targetItem.innerText;
return item;
});

Expand All @@ -683,8 +684,8 @@ class ViewSettingsDialog extends UI5Element {
/**
* Stores `Sort By` list as recently used control and its selected item in current state.
*/
_onSortByChange(e: CustomEvent<ListItemClickEventDetail>) {
const selectedItemIndex = Number(e.detail.item.getAttribute("data-ui5-external-action-item-index"));
_onSortByChange(e: CustomEvent<ListSelectionChangeEventDetail>) {
const selectedItemIndex = Number(e.detail.targetItem.getAttribute("data-ui5-external-action-item-index"));
this._recentlyFocused = this._sortBy!;
this._currentSettings.sortBy = this.initSortByItems.map((item, index) => {
item.selected = index === selectedItemIndex;
Expand Down
8 changes: 4 additions & 4 deletions packages/fiori/src/ViewSettingsDialogTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function ViewSettingsDialogTemplateContent(this: ViewSettingsDialog) {
<div class="ui5-vsd-sort">
<List
selectionMode="SingleStart"
onItemClick={this._onSortOrderChange}
onSelectionChange={this._onSortOrderChange} // radio button - use selectionChange
sort-order=""
accessibleNameRef={`${this._id}-label`}
>
Expand All @@ -92,7 +92,7 @@ function ViewSettingsDialogTemplateContent(this: ViewSettingsDialog) {
</List>
<List
selectionMode="SingleStart"
onItemClick={this._onSortByChange}
onSelectionChange={this._onSortByChange} // radio button - use selectionChange
sort-by=""
>
<ListItemGroup headerText={this._sortByLabel}>
Expand All @@ -110,7 +110,7 @@ function ViewSettingsDialogTemplateContent(this: ViewSettingsDialog) {
{this._filterStepTwo ? (
<List
selectionMode="Multiple"
onItemClick={this._handleFilterValueItemClick}
onSelectionChange={this._handleFilterValueItemClick} // checkboxes to select/deselect - use selectionChange
accessibleNameRef={`${this._id}-label`}
>
{this._currentSettings.filters.filter(item => item.selected).map(item => (<>
Expand All @@ -123,7 +123,7 @@ function ViewSettingsDialogTemplateContent(this: ViewSettingsDialog) {
</List>
) : ( // else
<List
onItemClick={this._changeCurrentFilter}
onItemClick={this._changeCurrentFilter} // list item to drill down into the second-level menu - use click
accessibleNameRef={`${this._id}-label`}
>
<ListItemGroup headerText={this._filterByLabel}>
Expand Down