Skip to content

Commit f26eb62

Browse files
authored
chore: extend form-validity test for ui5-switch, ui5-date-picker, ui5-file-uploader, ui5-daterange-picker, ui5-datetime-picker, ui5-time-picker and ui5-step-input
In relation to #10487, extend the tests to check that ui5-switch, ui5-date-picker, ui5-file-uploader, ui5-daterange-picker, ui5-datetime-picker, ui5-time-picker and ui5-step-input correctly expose a "validity" property and related methods required by the Constraint Validation API, as well as are selectable using the :invalid CSS pseudo class.
1 parent 8664743 commit f26eb62

32 files changed

+1571
-159
lines changed

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

Lines changed: 187 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,192 @@ describe("Date Picker Tests", () => {
16441644
});
16451645

16461646

1647+
describe("Validation inside a form ", () => {
1648+
it("has correct validity for valueMissing", () => {
1649+
cy.mount(
1650+
<form>
1651+
<DatePicker id="datePicker1" required={true}></DatePicker>
1652+
<button type="submit" id="submitBtn">Submits forms</button>
1653+
</form>
1654+
);
1655+
1656+
cy.get("form")
1657+
.then($item => {
1658+
$item.get(0).addEventListener("submit", (e) => e.preventDefault());
1659+
$item.get(0).addEventListener("submit", cy.stub().as("submit"));
1660+
});
1661+
1662+
cy.get("#submitBtn")
1663+
.realClick();
1664+
1665+
cy.get("@submit")
1666+
.should("have.not.been.called");
1667+
1668+
cy.get("[ui5-date-picker]")
1669+
.as("datePicker")
1670+
.ui5AssertValidityState({
1671+
formValidity: { valueMissing: true },
1672+
validity: { valueMissing: true, valid: false },
1673+
checkValidity: false,
1674+
reportValidity: false
1675+
});
1676+
1677+
cy.get("#datePicker1:invalid")
1678+
.should("exist", "Required DatePicker without value should have :invalid CSS class");
1679+
1680+
cy.get("@datePicker")
1681+
.ui5DatePickerTypeDate("Apr 12, 2024");
1682+
1683+
cy.get("@datePicker")
1684+
.ui5AssertValidityState({
1685+
formValidity: { valueMissing: false },
1686+
validity: { valueMissing: false, valid: true },
1687+
checkValidity: true,
1688+
reportValidity: true
1689+
});
1690+
1691+
cy.get("#datePicker1:invalid").should("not.exist", "Required DatePicker with value should not have :invalid CSS class");
1692+
});
1693+
1694+
it("has correct validity for patternMismatch", () => {
1695+
cy.mount(
1696+
<form>
1697+
<DatePicker id="datePicker2" required={true} valueFormat="MMM d, y"></DatePicker>
1698+
<button type="submit" id="submitBtn">Submits forms</button>
1699+
</form>
1700+
);
1701+
1702+
cy.get("form")
1703+
.then($item => {
1704+
$item.get(0).addEventListener("submit", (e) => e.preventDefault());
1705+
$item.get(0).addEventListener("submit", cy.stub().as("submit"));
1706+
});
1707+
1708+
cy.get("#datePicker2")
1709+
.as("datePicker")
1710+
.ui5DatePickerTypeDate("Test 33, 2024");
1711+
1712+
cy.get("#submitBtn")
1713+
.realClick();
1714+
1715+
cy.get("@submit")
1716+
.should("have.not.been.called");
1717+
1718+
cy.get("@datePicker")
1719+
.ui5AssertValidityState({
1720+
formValidity: { patternMismatch: true },
1721+
validity: { patternMismatch: true, valid: false },
1722+
checkValidity: false,
1723+
reportValidity: false
1724+
});
1725+
1726+
cy.get("#datePicker2:invalid")
1727+
.should("exist", "DatePicker without correct formatted value should have :invalid CSS class");
1728+
1729+
cy.get("@datePicker")
1730+
.ui5DatePickerTypeDate("Apr 12, 2024");
1731+
1732+
cy.get("@datePicker")
1733+
.ui5AssertValidityState({
1734+
formValidity: { patternMismatch: false },
1735+
validity: { patternMismatch: false, valid: true },
1736+
checkValidity: true,
1737+
reportValidity: true
1738+
});
1739+
1740+
cy.get("#datePicker2:invalid")
1741+
.should("not.exist", "DatePicker with correct formatted value should not have :invalid CSS class");
1742+
});
1743+
1744+
it("has correct validity for rangeUnderflow", () => {
1745+
cy.mount(
1746+
<form method="get">
1747+
<DatePicker id="datePicker3" minDate="Jan 10, 2024" valueFormat="MMM d, y"></DatePicker>
1748+
<button type="submit" id="submitBtn">Submits forms</button>
1749+
</form>
1750+
);
1751+
1752+
cy.get("form")
1753+
.then($item => {
1754+
$item.get(0).addEventListener("submit", (e) => e.preventDefault());
1755+
$item.get(0).addEventListener("submit", cy.stub().as("submit"));
1756+
});
1757+
1758+
cy.get("#datePicker3")
1759+
.as("datePicker")
1760+
.ui5DatePickerTypeDate("Apr 10, 2020");
1761+
1762+
cy.get("@datePicker")
1763+
.ui5AssertValidityState({
1764+
formValidity: { rangeUnderflow: true },
1765+
validity: { rangeUnderflow: true, valid: false },
1766+
checkValidity: false,
1767+
reportValidity: false
1768+
});
1769+
1770+
cy.get("#datePicker3:invalid")
1771+
.should("exist", "DatePicker with value below minDate should have :invalid CSS class");
1772+
1773+
cy.get("@datePicker")
1774+
.ui5DatePickerTypeDate("Jan 20, 2024");
1775+
1776+
cy.get("@datePicker")
1777+
.ui5AssertValidityState({
1778+
formValidity: { rangeUnderflow: false },
1779+
validity: { rangeUnderflow: false, valid: true },
1780+
checkValidity: true,
1781+
reportValidity: true
1782+
});
1783+
1784+
cy.get("#datePicker3:invalid")
1785+
.should("not.exist", "DatePicker with value above minDate should not have :invalid CSS class");
1786+
});
1787+
1788+
1789+
it("has correct validity for rangeOverflow", () => {
1790+
cy.mount(
1791+
<form>
1792+
<DatePicker id="datePicker3" maxDate="Jan 10, 2024" valueFormat="MMM d, y"></DatePicker>
1793+
<button type="submit" id="submitBtn">Submits forms</button>
1794+
</form>
1795+
);
1796+
1797+
cy.get("form")
1798+
.then($item => {
1799+
$item.get(0).addEventListener("submit", (e) => e.preventDefault());
1800+
$item.get(0).addEventListener("submit", cy.stub().as("submit"));
1801+
});
1802+
1803+
cy.get("#datePicker3")
1804+
.ui5DatePickerTypeDate("Jan 14, 2024");
1805+
1806+
cy.get("@datePicker")
1807+
.ui5AssertValidityState({
1808+
formValidity: { rangeOverflow: true },
1809+
validity: { rangeOverflow: true, valid: false },
1810+
checkValidity: false,
1811+
reportValidity: false
1812+
});
1813+
1814+
cy.get("#datePicker3:invalid")
1815+
.should("exist", "DatePicker with value above maxDate should have :invalid CSS class");
1816+
1817+
cy.get("@datePicker")
1818+
.ui5DatePickerTypeDate("Jan 5, 2024");
1819+
1820+
cy.get("@datePicker")
1821+
.ui5AssertValidityState({
1822+
formValidity: { rangeOverflow: false },
1823+
validity: { rangeOverflow: false, valid: true },
1824+
checkValidity: true,
1825+
reportValidity: true
1826+
});
1827+
1828+
cy.get("#datePicker3:invalid")
1829+
.should("not.exist", "DatePicker with value below maxDate should not have :invalid CSS class");
1830+
});
1831+
});
1832+
16471833
describe("Accessibility", () => {
16481834
it("picker popover accessible name with external label", () => {
16491835
const LABEL = "Deadline";
@@ -1723,85 +1909,4 @@ describe("Accessibility", () => {
17231909
.find("span#descr")
17241910
.should("have.text", DESCRIPTION);
17251911
});
1726-
1727-
describe("Accessibility - ariaValueStateHiddenText", () => {
1728-
it("should correctly extract text from nested slot structure in value state messages", () => {
1729-
const ERROR_MESSAGE = "Invalid date format";
1730-
1731-
cy.mount(
1732-
<DatePicker valueState="Negative">
1733-
<div slot="valueStateMessage">{ERROR_MESSAGE}</div>
1734-
</DatePicker>
1735-
);
1736-
1737-
cy.get("[ui5-date-picker]")
1738-
.as("datePicker");
1739-
1740-
// Get the inner datetime input
1741-
cy.get<DatePicker>("@datePicker")
1742-
.shadow()
1743-
.find("[ui5-datetime-input]")
1744-
.as("datetimeInput");
1745-
1746-
// Verify the input has proper value state
1747-
cy.get("@datetimeInput")
1748-
.should("have.attr", "value-state", "Negative");
1749-
1750-
// Test the ariaValueStateHiddenText getter directly
1751-
cy.get("@datetimeInput")
1752-
.then(($input) => {
1753-
const datetimeInput = $input[0] as any;
1754-
const ariaText = datetimeInput.ariaValueStateHiddenText;
1755-
1756-
// Should contain both the value state type and the custom message
1757-
expect(ariaText).to.include("Error");
1758-
expect(ariaText).to.include(ERROR_MESSAGE);
1759-
});
1760-
1761-
// Verify the aria-describedby points to an element with the correct text
1762-
cy.get("@datetimeInput")
1763-
.shadow()
1764-
.find("input")
1765-
.should("have.attr", "aria-describedby")
1766-
.then((describedBy) => {
1767-
cy.get("@datetimeInput")
1768-
.shadow()
1769-
.find(`#${describedBy}`)
1770-
.should("contain.text", "Error")
1771-
.and("contain.text", ERROR_MESSAGE);
1772-
});
1773-
});
1774-
1775-
it("should handle complex nested slot structure from DatePicker forwarding", () => {
1776-
const CUSTOM_ERROR = "Please select a valid date";
1777-
1778-
cy.mount(
1779-
<DatePicker valueState="Critical">
1780-
<div slot="valueStateMessage">
1781-
<span>{CUSTOM_ERROR}</span>
1782-
</div>
1783-
</DatePicker>
1784-
);
1785-
1786-
cy.get("[ui5-date-picker]")
1787-
.as("datePicker");
1788-
1789-
cy.get<DatePicker>("@datePicker")
1790-
.shadow()
1791-
.find("[ui5-datetime-input]")
1792-
.as("datetimeInput");
1793-
1794-
// Test nested slot content extraction
1795-
cy.get("@datetimeInput")
1796-
.then(($input) => {
1797-
const datetimeInput = $input[0] as any;
1798-
const ariaText = datetimeInput.ariaValueStateHiddenText;
1799-
1800-
// Should extract text from nested structure
1801-
expect(ariaText).to.include("Warning");
1802-
expect(ariaText).to.include(CUSTOM_ERROR);
1803-
expect(ariaText.trim()).to.not.be.empty;
1804-
});
1805-
});
1806-
});
1807-
});
1912+
});

0 commit comments

Comments
 (0)