-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(input-time-picker, time-picker): add time-picker and input-time-…
…picker components (#1736)
- Loading branch information
1 parent
7d71362
commit 6e4c81d
Showing
20 changed files
with
3,248 additions
and
28 deletions.
There are no files selected for viewing
318 changes: 318 additions & 0 deletions
318
src/components/calcite-input-time-picker/calcite-input-time-picker.e2e.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,318 @@ | ||
import { newE2EPage } from "@stencil/core/testing"; | ||
import { accessible, defaults, focusable, reflects, renders } from "../../tests/commonTests"; | ||
import { formatTimePart } from "../../utils/time"; | ||
|
||
describe("calcite-input-time-picker", () => { | ||
it("renders", async () => renders("calcite-input-time-picker")); | ||
|
||
it("is accessible", async () => | ||
accessible(` | ||
<label> | ||
Input Time Picker | ||
<calcite-input-time-picker name="test"></calcite-input-time-picker> | ||
</label> | ||
`)); | ||
|
||
it("has defaults", async () => | ||
defaults("calcite-input-time-picker", [ | ||
{ propertyName: "scale", defaultValue: "m" }, | ||
{ propertyName: "step", defaultValue: 60 } | ||
])); | ||
|
||
it("reflects", async () => | ||
reflects(`calcite-input-time-picker`, [ | ||
{ propertyName: "active", value: true }, | ||
{ propertyName: "disabled", value: true }, | ||
{ propertyName: "scale", value: "m" } | ||
])); | ||
|
||
it("should focus the input when setFocus is called", async () => | ||
focusable(`calcite-input-time-picker`, { | ||
shadowFocusTargetSelector: "input" | ||
})); | ||
|
||
it("opens the time picker on input keyboard focus", async () => { | ||
const page = await newE2EPage({ | ||
html: `<calcite-input-time-picker></calcite-input-time-picker>` | ||
}); | ||
const popover = await page.find("calcite-input-time-picker >>> calcite-popover"); | ||
|
||
await page.keyboard.press("Tab"); | ||
await page.waitForChanges(); | ||
|
||
expect(await popover.getProperty("open")).toBe(true); | ||
}); | ||
|
||
it("opens the time picker on input click", async () => { | ||
const page = await newE2EPage({ | ||
html: `<calcite-input-time-picker></calcite-input-time-picker>` | ||
}); | ||
const input = await page.find("calcite-input-time-picker >>> calcite-input"); | ||
const popover = await page.find("calcite-input-time-picker >>> calcite-popover"); | ||
|
||
await input.click(); | ||
await page.waitForChanges(); | ||
|
||
expect(await popover.getProperty("open")).toBe(true); | ||
}); | ||
|
||
it("changing hour, minute and second values reflects in the input, input-time-picker and time-picker for 24-hour display format", async () => { | ||
const page = await newE2EPage({ | ||
html: `<calcite-input-time-picker hour-display-format="24" step="1"></calcite-input-time-picker>` | ||
}); | ||
|
||
const inputTimePicker = await page.find("calcite-input-time-picker"); | ||
const input = await page.find("calcite-input-time-picker >>> calcite-input"); | ||
const timePicker = await page.find("calcite-input-time-picker >>> calcite-time-picker"); | ||
|
||
for (let second = 0; second < 10; second++) { | ||
const date = new Date(0); | ||
date.setSeconds(second); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
|
||
for (let minute = 0; minute < 10; minute++) { | ||
const date = new Date(0); | ||
date.setMinutes(minute); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
|
||
for (let hour = 0; hour < 10; hour++) { | ||
const date = new Date(0); | ||
date.setHours(hour); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
}); | ||
|
||
it("changing hour, minute and second values reflects in the input, input-time-picker and time-picker for 12-hour display format", async () => { | ||
const page = await newE2EPage({ | ||
html: `<calcite-input-time-picker hour-display-format="12" step="1"></calcite-input-time-picker>` | ||
}); | ||
|
||
const inputTimePicker = await page.find("calcite-input-time-picker"); | ||
const input = await page.find("calcite-input-time-picker >>> calcite-input"); | ||
const timePicker = await page.find("calcite-input-time-picker >>> calcite-time-picker"); | ||
|
||
for (let second = 0; second < 10; second++) { | ||
const date = new Date(0); | ||
date.setSeconds(second); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedHourAsNumber = parseInt(expectedValue.substr(0, 2)); | ||
const expectedDisplayHour = | ||
expectedHourAsNumber > 12 | ||
? formatTimePart(expectedHourAsNumber - 12) | ||
: expectedHourAsNumber === 0 | ||
? "12" | ||
: formatTimePart(expectedHourAsNumber); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
|
||
for (let minute = 0; minute < 10; minute++) { | ||
const date = new Date(0); | ||
date.setMinutes(minute); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedHourAsNumber = parseInt(expectedValue.substr(0, 2)); | ||
const expectedDisplayHour = | ||
expectedHourAsNumber > 12 | ||
? formatTimePart(expectedHourAsNumber - 12) | ||
: expectedHourAsNumber === 0 | ||
? "12" | ||
: formatTimePart(expectedHourAsNumber); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
|
||
for (let hour = 0; hour < 10; hour++) { | ||
const date = new Date(0); | ||
date.setHours(hour); | ||
|
||
const expectedValue = date.toISOString().substr(11, 8); | ||
const expectedHour = expectedValue.substr(0, 2); | ||
const expectedHourAsNumber = parseInt(expectedValue.substr(0, 2)); | ||
const expectedDisplayHour = | ||
expectedHourAsNumber > 12 | ||
? formatTimePart(expectedHourAsNumber - 12) | ||
: expectedHourAsNumber === 0 | ||
? "12" | ||
: formatTimePart(expectedHourAsNumber); | ||
const expectedMinute = expectedValue.substr(3, 2); | ||
const expectedSecond = expectedValue.substr(6, 2); | ||
|
||
inputTimePicker.setProperty("value", expectedValue); | ||
|
||
await page.waitForChanges(); | ||
|
||
const inputValue = await input.getProperty("value"); | ||
const inputTimePickerValue = await inputTimePicker.getProperty("value"); | ||
const timePickerHourValue = await timePicker.getProperty("hour"); | ||
const timePickerMinuteValue = await timePicker.getProperty("minute"); | ||
const timePickerSecondValue = await timePicker.getProperty("second"); | ||
|
||
expect(inputValue).toBe(expectedValue); | ||
expect(inputTimePickerValue).toBe(expectedValue); | ||
expect(timePickerHourValue).toBe(expectedHour); | ||
expect(timePickerMinuteValue).toBe(expectedMinute); | ||
expect(timePickerSecondValue).toBe(expectedSecond); | ||
} | ||
}); | ||
|
||
it("appropriately triggers calciteInputTimePickerChange event when the user types a value", async () => { | ||
const page = await newE2EPage(); | ||
await page.setContent(`<calcite-input-time-picker step="1"></calcite-input-time-picker>`); | ||
|
||
const inputTimePicker = await page.find("calcite-input-time-picker"); | ||
const changeEvent = await inputTimePicker.spyOnEvent("calciteInputTimePickerChange"); | ||
|
||
expect(changeEvent).toHaveReceivedEventTimes(0); | ||
|
||
await page.keyboard.press("Tab"); | ||
await page.keyboard.press("1"); | ||
await page.keyboard.press(":"); | ||
await page.keyboard.press("2"); | ||
|
||
await page.waitForChanges(); | ||
|
||
expect(changeEvent).toHaveReceivedEventTimes(1); | ||
|
||
await page.keyboard.press(":"); | ||
await page.keyboard.press("3"); | ||
|
||
await page.waitForChanges(); | ||
|
||
expect(changeEvent).toHaveReceivedEventTimes(2); | ||
}); | ||
|
||
it("formats valid typed time value appropriately on blur", async () => { | ||
const page = await newE2EPage(); | ||
await page.setContent(`<calcite-input-time-picker step="1"></calcite-input-time-picker><input>`); | ||
|
||
const inputTimePicker = await page.find("calcite-input-time-picker"); | ||
|
||
await page.keyboard.press("Tab"); | ||
await page.keyboard.type("2:3:4"); | ||
await page.keyboard.press("Tab"); | ||
await page.waitForChanges(); | ||
|
||
expect(await inputTimePicker.getProperty("value")).toBe("02:03:04"); | ||
}); | ||
|
||
it("resets to previous value when default event behavior is prevented", async () => { | ||
const page = await newE2EPage({ | ||
html: `<calcite-input-time-picker value="14:59"></calcite-input-time-picker>` | ||
}); | ||
const inputTimePicker = await page.find("calcite-input-time-picker"); | ||
|
||
await page.evaluate(() => { | ||
const inputTimePicker = document.querySelector("calcite-input-time-picker"); | ||
inputTimePicker.addEventListener("calciteInputTimePickerChange", (event) => { | ||
event.preventDefault(); | ||
}); | ||
}); | ||
|
||
expect(await inputTimePicker.getProperty("value")).toBe("14:59"); | ||
|
||
await page.keyboard.press("Tab"); | ||
await page.keyboard.press(":"); | ||
await page.keyboard.press("5"); | ||
await page.waitForChanges(); | ||
|
||
expect(await inputTimePicker.getProperty("value")).toBe("14:59"); | ||
}); | ||
}); |
4 changes: 4 additions & 0 deletions
4
src/components/calcite-input-time-picker/calcite-input-time-picker.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
:host { | ||
@apply inline-block | ||
select-none; | ||
} |
44 changes: 44 additions & 0 deletions
44
src/components/calcite-input-time-picker/calcite-input-time-picker.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { number, select, text } from "@storybook/addon-knobs"; | ||
import { boolean } from "../../../.storybook/helpers"; | ||
import { darkBackground } from "../../../.storybook/utils"; | ||
import readme from "./readme.md"; | ||
import { html } from "../../tests/utils"; | ||
|
||
export default { | ||
title: "Components/Controls/Time/Input Time Picker", | ||
|
||
parameters: { | ||
notes: readme | ||
} | ||
}; | ||
|
||
export const LightTheme = (): string => html` | ||
<calcite-input-time-picker | ||
${boolean("disabled", false)} | ||
${boolean("hidden", false)} | ||
hour-display-format="${select("hour-display-format", ["12", "24"], "12")}" | ||
name="${text("name", "light")}" | ||
scale="${select("scale", ["s", "m", "l"], "m")}" | ||
step="${number("step", 1)}" | ||
value="${text("value", "10:37")}" | ||
> | ||
</calcite-input-time-picker> | ||
`; | ||
|
||
export const DarkTheme = (): string => html` | ||
<calcite-input-time-picker | ||
${boolean("disabled", false)} | ||
${boolean("hidden", false)} | ||
class="calcite-theme-dark" | ||
hour-display-format="${select("hour-display-format", ["12", "24"], "12")}" | ||
name="${text("name", "dark")}" | ||
scale="${select("scale", ["s", "m", "l"], "m")}" | ||
step="${number("step", 1)}" | ||
value="${text("value", "22:37")}" | ||
> | ||
</calcite-input-time-picker> | ||
`; | ||
|
||
DarkTheme.story = { | ||
parameters: { backgrounds: darkBackground } | ||
}; |
Oops, something went wrong.