import { iso8601ToDate } from "@hesxenon/prelude/Codec.js"; import * as Either from "@hesxenon/prelude/Either.js"; import { failWith, pipe } from "@hesxenon/prelude/Function.js"; import { describe, expect, it, render, select, user } from "../utils/Test.js"; const setup = (props: Partial> = {}) => { const page = render(); const datepicker = select(page, "uwc-datepicker"); const form = page.querySelector("form"); return { datepicker, form }; }; const encodeContentIso8601 = (content: string) => pipe( iso8601ToDate.decode(content), Either.flatMap(iso8601ToDate.encode), Either.getOrElse(failWith), ); describe("uwc-datepicker", () => { it("should align its [anchor-date] to the [selected-date] initially", () => { const { datepicker } = setup({ "selected-date": "2024-01-01" }); expect(datepicker.anchorDate.toISOString()).to.eq( encodeContentIso8601("2024-01-01"), ); datepicker["selected-date"] = "2023-01-01"; expect(datepicker.anchorDate.toISOString()).to.eq( encodeContentIso8601("2024-01-01"), ); }); it("should set [aria-selected=true] on the selected value only", () => { const { datepicker } = setup({ "selected-date": "2024-01-01" }); const [onlySelected, ...others] = Array.from( datepicker.querySelectorAll("[aria-selected=true]"), ); expect(others).to.have.length(0); expect(onlySelected).to.include({ "data-value": encodeContentIso8601("2024-01-01"), }); }); // WARNING: hovering also doesn't work in combination with css with user-event it.skip("should set [aria-current=true] if a valid option is focused", async () => { const { datepicker } = setup({ "selected-date": "2024-01-01" }); await user.hover(select(datepicker, "[data-value]")); expect(datepicker.querySelector("[aria-current=true]")).to.exist; }); it.todo("should be possible to use custom views"); it.todo("should not be possible to go to a page without selectable options"); it.todo( "should not be possible to select a range with no selectable lower options", ); it.todo("should disable options according to min and max"); }); //////////////////////////////// // REWRITE // ///////////////////////////// // describe("uwc-datepicker", () => { // const render = async (...[component]: Parameters) => { // const page = renderSync(component); // await new Promise((resolve) => schedule(resolve)); // return page; // }; // // it("should be possible to move to the months view initially", async () => { // const page = await render(); // const current = select(page, "button.current"); // expect(current.disabled).to.eq(false); // }); // // it("should not be possible to go below min", async () => { // const page = await render( // , // ); // expect(select(page, "button.leap-backward").disabled).to.eq(true); // expect(select(page, "button.previous").disabled).to.eq(true); // }); // // it("should not be possible to go above max", async () => { // const page = await render( // , // ); // expect(select(page, "button.next").disabled).to.eq(true); // expect(select(page, "button.leap-forward").disabled).to.eq(true); // }); // // it.todo( // "if the max value coincides with the start of a time unit, the time unit should be enabled", // ); // // describe("uwc-datepicker-days", () => { // it("should render as many days as a month has", async () => { // const page = await render( // , // ); // const days = page.querySelectorAll( // "ul.days li[data-value]:not(:where(.previous-month, .next-month))", // ); // expect(days.length).to.eq(30); // expect(page.querySelectorAll("li.previous-month").length).to.eq(0); // expect(page.querySelectorAll("li.next-month").length).to.eq(5); // }); // // it("should render the weekdays in the given locale", async () => { // const page = await render( // , // ); // expect(page.querySelector("ul li.weekday")?.textContent).to.eq("So"); // }); // // it("should render the week numbers", async () => { // const page = await render(); // // expect( // Array.from(page.querySelectorAll("ul.days li.weeknumber")).map( // (element) => element.textContent, // ), // ).to.deep.eq(["14", "15", "16", "17", "18"]); // }); // // it("should render with initial value as selected", async () => { // const page = await render(); // // expect( // Array.from(page.querySelectorAll("ul.days li.selected")).map( // (element) => element.textContent, // ), // ).to.deep.eq(["1"]); // }); // // it("should be possible to select the last day of month", async () => { // const page = await render(); // // await user.click( // select( // page, // `ul.days li[data-value="${new Date(2024, 7, 31).toISOString()}"]`, // ), // ); // // expect( // Array.from(page.querySelectorAll("ul.days li.selected")).map( // (element) => element.textContent, // ), // ).to.deep.eq(["31"]); // }); // // it("should render previous month december with 31 days when current month is january", async () => { // const page = await render(); // // expect( // page.querySelector( // `ul.days li[data-value="${new Date(2021, 11, 31).toISOString()}"]`, // ), // ).to.exist; // }); // // it("should render sunday as first column when start-of-week is sunday", async () => { // const page = await render( // , // ); // // expect(page.querySelector("ul li.weekday")?.textContent).to.eq("Sun"); // }); // // it("should render monday as first column when start-of-week is monday", async () => { // const page = await render( // , // ); // // expect(page.querySelector("ul li.weekday")?.textContent).to.eq("Mon"); // }); // // it("should render 2024-07-03 in correct position as wednesday when start-of-week is sunday", async () => { // const page = await render( // , // ); // // expect( // page.querySelector("ul.days li:nth-child(4 of li[data-value])") // ?.textContent, // ).to.eq("3"); // }); // // it("should render 2024-07-03 in correct position as wednesday when start-of-week is monday", async () => { // const page = await render( // , // ); // // expect( // page.querySelector("ul.days li:nth-child(3 of li[data-value])") // ?.textContent, // ).to.eq("3"); // }); // // it("should be possible to select min date", async () => { // const page = await render( // , // ); // // await user.click( // select( // page, // `ul.days li[data-value="${new Date(2024, 0, 10).toISOString()}"]`, // ), // ); // // expect( // page.querySelector("uwc-datepicker")?.getAttribute("value"), // ).to.equal("2024-01-09T23:00:00.000Z"); // }); // // // WARNING: this is in direct conflict to the "units must be fully contained in the min-max range" // // max is specified as a point in time, up to an arbitrary precision. // // We can either treat a date as _only_ its beginning, in which case units become selectable // // even if they aren't fully contained in the min-max range, or we don't. // it.skip("should be possible to select max date", async () => { // const page = await render( // , // ); // // await user.click( // select( // page, // `ul.days li[data-value="${new Date(2024, 0, 20).toISOString()}"]`, // ), // ); // // expect( // page.querySelector("uwc-datepicker")?.getAttribute("value"), // ).to.equal("2024-01-19T23:00:00.000Z"); // }); // // it("current day has class current", async () => { // const page = await render( // , // ); // // expect( // Array.from(page.querySelectorAll("ul.days li.current")).map( // (element) => element.textContent, // ), // ).to.deep.eq([`${new Date().getDate()}`]); // }); // // it("should be possible to select date from previous month, current month should change accordingly", async () => { // const page = await render( // , // ); // // await user.click( // select( // page, // `ul.days li[data-value="${new Date(2024, 6, 31).toISOString()}"]`, // ), // ); // // expect( // Array.from(page.querySelectorAll("ul.days li.selected")).map( // (element) => element.textContent, // ), // ).to.deep.eq(["31"]); // // expect(page.querySelector("button.current")?.textContent).to.equal( // "July 2024", // ); // }); // // it("should be possible to select date from next month, current month should change accordingly", async () => { // const page = await render( // , // ); // // await user.click( // select( // page, // `ul.days li[data-value="${new Date(2024, 9, 1).toISOString()}"]`, // ), // ); // // expect( // Array.from(page.querySelectorAll("ul.days li.selected")).map( // (element) => element.textContent, // ), // ).to.deep.eq(["1"]); // // expect(page.querySelector("button.current")?.textContent).to.equal( // "October 2024", // ); // }); // }); // // describe("months view", () => { // it("should be possible to go from months view to days view, when type is days, even when min max does not include entire month", async () => { // const page = await render( // // // // , // ); // // expect( // Array.from( // page.querySelectorAll(`ul.months li[aria-disabled=false]`), // ).map((element) => element.textContent), // ).to.deep.eq(["January"]); // }); // // // wrong assumption // it.skip("should be possible to select only month which is fully contained within min and max date when type is months", async () => { // const page = await render( // // // , // ); // // expect( // Array.from( // page.querySelectorAll(`ul.months li[aria-disabled=false]`), // ).map((element) => element.textContent), // ).to.deep.eq(["February"]); // }); // // it("current month has class current", async () => { // const page = await render( // // // , // ); // // expect( // Array.from(page.querySelectorAll("ul.months li.current")).map( // (element) => element.textContent, // ), // ).to.deep.eq([`${format(new Date(), "MMMM")}`]); // }); // }); // // describe("years view", () => { // it("should be possible to go from years view to months view, when type is days, even when min max does not include entire year", async () => { // const page = await render( // // // // // , // ); // // expect( // Array.from( // page.querySelectorAll(`ul.years li[aria-disabled=false]`), // ).map((element) => element.textContent), // ).to.deep.eq(["2024"]); // }); // // it("years should be enabled as long as their lower view has selectable dates", async () => { // const page = await render( // // // // , // ); // // expect( // Array.from( // page.querySelectorAll(`ul.years li[aria-disabled=false]`), // ).map((element) => element.textContent), // ).to.deep.eq([ // "2023", // december is partially contained -> selectable // "2024", // all months fully contained -> selectable // "2025", // january is partially contained -> selectable // ]); // }); // // // wrong assumption // it.skip("only fully contained years should be selectable if no lower view exists", async () => { // const page = await render( // // // , // ); // // expect( // Array.from( // page.querySelectorAll(`ul.years li[aria-disabled=false]`), // ).map((element) => element.textContent), // ).to.deep.eq(["2024"]); // }); // // it("current year has class current", async () => { // const page = await render( // // // , // ); // // expect( // Array.from(page.querySelectorAll("ul.years li.current")).map( // (element) => element.textContent, // ), // ).to.deep.eq([`${new Date().getFullYear()}`]); // }); // }); // // describe("syncing attributes", () => { // each( // [ // { // message: "should sync the anchor-date across all contained views", // }, // ], // "it should sync [$attribute] on change across all contained views", // async () => {}, // ); // }); // // describe("days view", () => { // it.todo( // "should be possible to select days that aren't fully contained in the min/max limits", // ); // // it.todo("2024-10-01 should be a tuesday, regardless of start-of-week"); // // it.todo( // "october '24 view should have 35 days (2 before and 2 after if start-of-week is sunday, 1/3 otherwise)", // ); // // it.todo("should disable days when min or max change"); // // describe("a11y", () => { // it("should set role 'grid' on the date grid", async () => { // const page = await render(); // // expect(queryByRole(page, "grid")).to.exist; // }); // // it.todo("should include the full weekday name in the [abbr] attribute"); // // it.todo( // "should be possible to use the arrow keys to navigate between days", // ); // // it.todo( // "should be possible to change to week borders with {Home} and {End} keys", // ); // // it.todo( // "should be possible to change selected months with the {PageUp} and {PageDown} keys", // ); // // it.todo( // "should be possible to change selected years with the {Shift+PageUp} and {Shift+PageDown} keys", // ); // }); // }); // // describe("a11y", () => { // it.todo("should mark the selection region as a live region"); // }); // });