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

chore(ui5-datetime-picker): migrate tests to cypress #10845

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
303 changes: 303 additions & 0 deletions packages/main/cypress/specs/DateTimePicker.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
import DateTimePicker from "../../src/DateTimePicker.js";

function DefaultDateTimePicker() {
return (
<DateTimePicker id="dt" />
);
}

function DateTimePickerWithMinutes() {
return <DateTimePicker
id="dtMinutes"
formatPattern="dd/MM/yyyy, hh:mm a"
value="13/04/2020, 09:16 AM"/>;
}

function DateTimePickerWithSeconds({ initialValue }: { initialValue: string }) {
return (
<>
<DateTimePicker
id="dtSeconds"
formatPattern="dd/MM/yyyy, hh:mm:ss a"
value={initialValue || "13/04/2020, 03:16:16 AM"}
/>
</>
);
}
describe("DateTimePicker general interaction", () => {
it("tests picker opens/closes programmatically", () => {
cy.mount(<DefaultDateTimePicker />);

cy.ui5DateTimePickerOpen("#dt");
cy.ui5DateTimePickerIsOpen("#dt").should("equal", true);
cy.ui5DateTimePickerClose("#dt");
cy.ui5DateTimePickerIsOpen("#dt").should("equal", false);
});

it("tests selection of new date/time", () => {
Copy link
Contributor

@unazko unazko Feb 17, 2025

Choose a reason for hiding this comment

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

This test runs successfully standalone, but it is unstable when executed with the other tests.
Not exactly sure where is the root cause of this instability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could not identify it either, I will comment it out for now.

const PREVIOUS_VALUE = "13/04/2020, 03:16:16 AM";

cy.mount(<DateTimePickerWithSeconds initialValue={PREVIOUS_VALUE} />);

cy.ui5DateTimePickerOpen("#dtSeconds");

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.should("have.value", PREVIOUS_VALUE);

cy.ui5DateTimePickerGetPicker("#dtSeconds").within(() => {
// Select the next day (click on the currently selected day, then ArrowRight and Space).
cy.get("ui5-calendar")
.shadow()
.find("ui5-daypicker")
.shadow()
.find(".ui5-dp-item--selected")
.realClick();
cy.realPress("ArrowRight");
cy.realPress("Space");

cy.get("ui5-time-selection-clocks")
.shadow()
.find(`ui5-toggle-spin-button[data-ui5-clock="hours"]`)
.realClick();
cy.realPress("ArrowDown");
cy.realPress("Space");

// Adjust minutes.
cy.realPress("ArrowDown");
cy.realPress("ArrowDown");
cy.realPress("Space");

// Adjust seconds.
cy.realPress("ArrowUp");
cy.realPress("ArrowUp");
cy.realPress("ArrowUp");
cy.realType("p");

// Confirm.
cy.get("#ok").realClick();
});

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.invoke("prop", "value")
.should("equal", "14/04/2020, 02:14:19 PM");
});

it("tests selection of new date without changing the time section", () => {
const PREVIOUS_VALUE = "14/04/2020, 02:14:19 PM";
cy.mount(<DateTimePickerWithSeconds initialValue={PREVIOUS_VALUE} />);

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.should("have.value", PREVIOUS_VALUE);

// Simulate keyboard interactions
cy.realPress("Tab");
cy.realPress(["Shift", "Tab"]);
cy.realPress("Backspace");
cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.realClick();
cy.realType("wrongtext");
cy.realPress("Tab");

cy.ui5DateTimePickerOpen("#dtSeconds");

// Act
let selectedDate: string;
cy.ui5DateTimePickerGetPicker("#dtSeconds").within(() => {
cy.get("ui5-calendar")
.shadow()
.find("ui5-daypicker")
.shadow()
.find(".ui5-dp-item--now")
.then($el => {
const timestamp = $el.attr("data-sap-timestamp") || "";
const date = new Date(parseInt(timestamp) * 1000);
selectedDate = `${String(date.getDate()).padStart(2, "0")}/${String(date.getMonth() + 1).padStart(2, "0")}/${date.getFullYear()}`;
})
.realClick();

cy.get("#ok").realClick();
});

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.invoke("prop", "value")
.should(val => {
expect(val).to.include(selectedDate);
});
});

it("tests time controls for dtSeconds picker", () => {
const expectedClocksCount = 3;
const expectedPeriodCount = 1;

cy.mount(<DateTimePickerWithSeconds initialValue="13/04/2020, 03:16:16 AM" />);

cy.ui5DateTimePickerOpen("#dtSeconds");

cy.ui5DateTimePickerTimeSelectionClocksCount("#dtSeconds").then(clocksCount => {
expect(clocksCount).to.equal(expectedClocksCount,
"The picker should display 3 clocks for hours, minutes and seconds.");
});

cy.ui5DateTimePickerPeriodSegmentedButtonCount("#dtSeconds").then(periodCount => {
expect(periodCount).to.equal(expectedPeriodCount,
"The picker should display 1 period selector.");
});

cy.ui5DateTimePickerClose("#dtSeconds");
});

it("tests time controls for dtMinutes picker", () => {
const expectedClocksCount = 2;
const expectedPeriodCount = 1;

cy.mount(<DateTimePickerWithMinutes />);

cy.ui5DateTimePickerOpen("#dtMinutes");

cy.ui5DateTimePickerTimeSelectionClocksCount("#dtMinutes").then(clocksCount => {
expect(clocksCount).to.equal(expectedClocksCount,
"The picker should display 2 clocks for hours and minutes.");
});

cy.ui5DateTimePickerPeriodSegmentedButtonCount("#dtMinutes").then(periodCount => {
expect(periodCount).to.equal(expectedPeriodCount,
"The picker should display 1 period selector.");
});

cy.ui5DateTimePickerClose("#dtMinutes");
});

it("tests hours clock is active on picker open", () => {
cy.mount(<DefaultDateTimePicker />);
cy.ui5DateTimePickerOpen("#dt");

cy.ui5DateTimePickerGetPicker("#dt").within(() => {
cy.get("ui5-time-selection-clocks")
.shadow()
.find(`ui5-time-picker-clock[data-ui5-clock="hours"]`)
.invoke("prop", "active")
.should("equal", true);
});

cy.ui5DateTimePickerClose("#dt");
});

it("tests selection of 12:34:56 AM", () => {
cy.mount(<DateTimePickerWithSeconds initialValue="13/04/2020, 03:16:16 AM" />);

cy.ui5DateTimePickerOpen("#dtSeconds");

cy.ui5DateTimePickerGetPicker("#dtSeconds").within(() => {
cy.get("ui5-time-selection-clocks")
.shadow()
.find(`ui5-toggle-spin-button[data-ui5-clock="hours"]`)
.click();
cy.realType("123456a"); // select 12:34:56 AM
cy.get("#ok").click();
});

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.invoke("prop", "value")
.should("equal", "13/04/2020, 12:34:56 AM");
});

it("tests selection of 12:34:56 PM", () => {
cy.mount(<DateTimePickerWithSeconds initialValue="13/04/2020, 03:16:16 AM" />);

cy.ui5DateTimePickerOpen("#dtSeconds");

cy.ui5DateTimePickerGetPicker("#dtSeconds").within(() => {
cy.get("ui5-time-selection-clocks")
.shadow()
.find(`ui5-toggle-spin-button[data-ui5-clock="hours"]`)
.click();
cy.realType("123456p"); // select 12:34:56 PM
cy.get("#ok").click();
});

cy.get("#dtSeconds")
.shadow()
.find("ui5-input")
.invoke("prop", "value")
.should("equal", "13/04/2020, 12:34:56 PM");
});

it("tests change event is prevented on submit when prevent default is called", () => {
cy.mount(<DefaultDateTimePicker />);

// Prevent default behavior of ui5-change event.
cy.get("#dt").then($el => {
$el[0].addEventListener("ui5-change", (ev: Event) => {
ev.preventDefault();
});
});

cy.ui5DateTimePickerOpen("#dt");

cy.ui5DateTimePickerGetPicker("#dt").within(() => {
// Click the focused day and confirm the selection.
cy.get("ui5-calendar")
.shadow()
.find("ui5-daypicker")
.shadow()
.find("[data-sap-focus-ref]")
.click();
cy.get("#ok").click();
});

cy.get("#dt")
.shadow()
.find("ui5-input")
.invoke("prop", "value")
.should("equal", "");
});

it("Min and max dates are set, with no format pattern provided, using valid ISO format", () => {
cy.mount(
<DateTimePicker
id="dtMinMaxDatesISO"
minDate="2023-05-01"
maxDate="2023-05-31"
></DateTimePicker>
);

cy.ui5DateTimePickerOpen("#dtMinMaxDatesISO");

cy.ui5DateTimePickerGetPicker("#dtMinMaxDatesISO").within(() => {
cy.get("ui5-calendar")
.shadow()
.find(".ui5-calheader")
.find("div[data-ui5-cal-header-btn-prev]")
.should("have.class", "ui5-calheader-arrowbtn-disabled");

cy.get("ui5-calendar")
.shadow()
.find(".ui5-calheader")
.find("div[data-ui5-cal-header-btn-next]")
.should("have.class", "ui5-calheader-arrowbtn-disabled");
});
});

it("picker popover should have accessible name", () => {
cy.mount(<DefaultDateTimePicker />);
cy.ui5DateTimePickerOpen("#dt");

cy.ui5DateTimePickerGetPicker("#dt")
.invoke("attr", "accessible-name")
.should("equal", "Choose Date and Time");

cy.ui5DateTimePickerClose("#dt");
});
});
9 changes: 9 additions & 0 deletions packages/main/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { internals, isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import "./commands/Calendar.commands.js";
import "./commands/ColorPalette.commands.js";
import "./commands/ColorPicker.commands.js";
import "./commands/DateTimePicker.commands.js";
import "./commands/Menu.commands.js";

type SimulationDevices = "phone"
Expand All @@ -61,6 +62,14 @@ declare global {
ui5ColorPickerUpdateInput(name: string, value: string): Chainable<void>
ui5ColorPaletteCheckSelectedColor(colorPaletteItem: string, values: {r: string, g: string, b: string, a: string}): Chainable<void>
ui5ColorPaletteNavigateAndCheckSelectedColor(colorPalette: string, startIndex: number, key: string, expectedValue: string): Chainable<void>
ui5DateTimePickerOpen(selector: string): Chainable<void>;
ui5DateTimePickerClose(selector: string): Chainable<void>;
ui5DateTimePickerIsOpen(selector: string): Chainable<boolean>;
ui5DateTimePickerGetSubmitButton(selector: string): Chainable<JQuery<HTMLElement>>;
ui5DateTimePickerGetCancelButton(selector: string): Chainable<JQuery<HTMLElement>>;
ui5DateTimePickerTimeSelectionClocksCount(selector: string): Chainable<number>;
ui5DateTimePickerPeriodSegmentedButtonCount(selector: string): Chainable<number>;
ui5DateTimePickerGetPicker(selector: string): Chainable<JQuery<HTMLElement>>;
}
}
}
Expand Down
60 changes: 60 additions & 0 deletions packages/main/cypress/support/commands/DateTimePicker.commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Cypress.Commands.add("ui5DateTimePickerOpen", selector => {
cy.get(selector)
.then($dateTimePicker => {
cy.wrap($dateTimePicker).invoke("attr", "open", true);
});
});

Cypress.Commands.add("ui5DateTimePickerClose", selector => {
cy.get(selector).invoke("attr", "open", false);
});

Cypress.Commands.add("ui5DateTimePickerGetPicker", selector => {
return cy.get(selector)
.shadow()
.find("ui5-responsive-popover");
});

Cypress.Commands.add("ui5DateTimePickerIsOpen", selector => {
return cy
.get(selector)
.invoke("attr", "open")
.then(attr => Boolean(attr));
});

Cypress.Commands.add("ui5DateTimePickerGetSubmitButton", selector => {
return cy.get(selector)
.shadow()
.find("ui5-responsive-popover")
.find("#ok");
});

Cypress.Commands.add("ui5DateTimePickerGetCancelButton", selector => {
return cy
.get(selector)
.shadow()
.find("ui5-responsive-popover")
.find("#cancel");
});

Cypress.Commands.add("ui5DateTimePickerTimeSelectionClocksCount", selector => {
return cy
.get(selector)
.shadow()
.find("ui5-responsive-popover")
.find("ui5-time-selection-clocks")
.shadow()
.find("ui5-time-picker-clock")
.its("length");
});

Cypress.Commands.add("ui5DateTimePickerPeriodSegmentedButtonCount", selector => {
return cy
.get(selector)
.shadow()
.find("ui5-responsive-popover")
.find("ui5-time-selection-clocks")
.shadow()
.find("ui5-segmented-button")
.its("length");
});
Loading