Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
240 changes: 240 additions & 0 deletions packages/site/src/pages/visualTests/VisualTestInputTimeV2Page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import { Box, Grid, Heading, InputTime, Stack, Text } from "@jobber/components";
import { useState } from "react";

const REFERENCE_TIME = new Date(2024, 0, 1, 14, 30, 0);

export const VisualTestInputTimeV2Page = () => {
const [value, setValue] = useState<Date | undefined>(undefined);

return (
<Box padding="large">
<Stack gap="extravagant">
<Heading level={3}>InputTime v2 Examples</Heading>

<Stack gap="large">
<section data-testid="basic-empty">
<Text size="large">Basic (empty)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={value}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="with-value">
<Text size="large">With value</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="with-description">
<Text size="large">With description</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={value}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
description="Please select a start time"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="with-error">
<Text size="large">With error</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={value}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
error="Please enter a valid time"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="invalid">
<Text size="large">Invalid (no message)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={value}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
invalid={true}
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="disabled">
<Text size="large">Disabled (with value)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
disabled={true}
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="disabled-empty">
<Text size="large">Disabled (empty)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={undefined}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
disabled={true}
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="readonly">
<Text size="large">ReadOnly (with value)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
readOnly={true}
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="size-small">
<Text size="large">Small size</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
size="small"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="size-large">
<Text size="large">Large size</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
size="large"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="align-center">
<Text size="large">Center aligned</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
align="center"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="align-right">
<Text size="large">Right aligned</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
align="right"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="inline">
<Text size="large">Inline</Text>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<Text>Start:</Text>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Time"
inline={true}
/>
</div>
</section>

<section data-testid="clearable-always">
<Text size="large">Clearable always (with value)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
clearable="always"
/>
</Grid.Cell>
</Grid>
</section>

<section data-testid="clearable-focus">
<Text size="large">Clearable on focus (with value)</Text>
<Grid>
<Grid.Cell size={{ xs: 12, md: 6 }}>
<InputTime
version={2}
value={REFERENCE_TIME}
onChange={newValue => setValue(newValue)}
placeholder="Select time"
clearable="while-editing"
/>
</Grid.Cell>
</Grid>
</section>
</Stack>
</Stack>
</Box>
);
};
2 changes: 2 additions & 0 deletions packages/site/src/pages/visualTests/VisualTestRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { VisualTestInputPasswordPage } from "./VisualTestInputPasswordPage";
import { VisualTestInputPhoneNumberPage } from "./VisualTestInputPhoneNumberPage";
import { VisualTestInputTextPage } from "./VisualTestInputTextPage";
import { VisualTestInputTimePage } from "./VisualTestInputTimePage";
import { VisualTestInputTimeV2Page } from "./VisualTestInputTimeV2Page";
import { VisualTestInputValidationPage } from "./VisualTestInputValidationPage";
import { VisualTestLayoutPage } from "./VisualTestLayoutPage";
import { VisualTestLightBoxPage } from "./VisualTestLightBoxPage";
Expand Down Expand Up @@ -105,6 +106,7 @@ const visualTestPages: Record<string, () => ReactElement> = {
"input-phone-number": VisualTestInputPhoneNumberPage,
"input-text": VisualTestInputTextPage,
"input-time": VisualTestInputTimePage,
"input-time-v2": VisualTestInputTimeV2Page,
"input-validation": VisualTestInputValidationPage,
lightbox: VisualTestLightBoxPage,
"lightbox-composable": VisualTestLightBoxComposablePage,
Expand Down
88 changes: 88 additions & 0 deletions packages/site/tests/visual/inputtime-v2.visual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { expect, test } from "@playwright/test";

const screenshotOptions = {
animations: "disabled" as const,
caret: "hide" as const,
fullPage: true,
};

test.describe("InputTime v2 Visual Tests", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/visual-tests/input-time-v2");
await page.waitForLoadState("networkidle");
await page.waitForTimeout(500);
});

test("1 - initial page state", async ({ page }) => {
await expect(page).toHaveScreenshot("1-initial.png", screenshotOptions);
});

test.describe("interactions", () => {
test("2 - focus state (empty)", async ({ page }) => {
const input = page
.getByTestId("basic-empty")
.getByTestId("ATL-InputTime-input");
await input.scrollIntoViewIfNeeded();
await input.focus();
await page.waitForTimeout(200);
await expect(page).toHaveScreenshot(
"2-focus-empty.png",
screenshotOptions,
);
});

test("3 - focus state (with value)", async ({ page }) => {
const input = page
.getByTestId("with-value")
.getByTestId("ATL-InputTime-input");
await input.scrollIntoViewIfNeeded();
await input.focus();
await page.waitForTimeout(200);
await expect(page).toHaveScreenshot(
"3-focus-with-value.png",
screenshotOptions,
);
});

test("4 - focus state (error)", async ({ page }) => {
const input = page
.getByTestId("with-error")
.getByTestId("ATL-InputTime-input");
await input.scrollIntoViewIfNeeded();
await input.focus();
await page.waitForTimeout(200);
await expect(page).toHaveScreenshot(
"4-focus-error.png",
screenshotOptions,
);
});

test("5 - clearable focus: clear button visible on focus", async ({
page,
}) => {
const input = page
.getByTestId("clearable-focus")
.getByTestId("ATL-InputTime-input");
await input.scrollIntoViewIfNeeded();
await input.focus();
await page.waitForTimeout(200);
await expect(page).toHaveScreenshot(
"5-clearable-focus-focused.png",
screenshotOptions,
);
});

test("6 - clearable always: clear button hover", async ({ page }) => {
const clearButton = page
.getByTestId("clearable-always")
.getByRole("button", { name: /clear/i });
await clearButton.scrollIntoViewIfNeeded();
await clearButton.hover();
await page.waitForTimeout(200);
await expect(page).toHaveScreenshot(
"6-clearable-always-clear-hover.png",
screenshotOptions,
);
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right Align and Center align has existing issue in Safari on both our V1 and V2 versions of InputTime. We likely didn't know about it

https://atlantis.getjobber.com/storybook/web/?path=/story/components-forms-and-inputs-inputtime--controlled&args=align:right

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading