Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 9db038c

Browse files
feat(c-skip-nav): create tests
1 parent dea966b commit 9db038c

File tree

3 files changed

+171
-58
lines changed

3 files changed

+171
-58
lines changed

packages/c-skip-nav/src/c-skip-nav.ts

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,81 @@
1111
import { h, defineComponent } from "vue"
1212
import {
1313
chakra,
14+
ComponentWithProps,
15+
DeepPartial,
16+
HTMLChakraProps,
1417
SystemStyleObject,
1518
useStyleConfig,
1619
} from "@chakra-ui/vue-system"
1720
import { CBox } from "@chakra-ui/vue-next"
1821

1922
const FALLBACK_ID = "chakra-skip-nav"
2023

21-
export const CSkipNavLink = defineComponent({
22-
name: "CSkipNavLink",
23-
props: {
24-
id: {
25-
type: String,
26-
default: FALLBACK_ID,
24+
export interface CSkipNavLinkProps extends HTMLChakraProps<"a"> {}
25+
26+
export const CSkipNavLink: ComponentWithProps<DeepPartial<CSkipNavLinkProps>> =
27+
defineComponent({
28+
name: "CSkipNavLink",
29+
props: {
30+
id: {
31+
type: String,
32+
default: FALLBACK_ID,
33+
},
2734
},
28-
},
29-
setup(props, { slots, attrs }) {
30-
function getBaseStyles(styles: any): SystemStyleObject {
31-
return {
32-
userSelect: "none",
33-
border: "0",
34-
borderRadius: "md",
35-
fontWeight: "semibold",
36-
height: "1px",
37-
width: "1px",
38-
margin: "-1px",
39-
padding: "0",
40-
outline: "0",
41-
overflow: "hidden",
42-
position: "absolute",
43-
clip: "rect(0 0 0 0)",
44-
...styles,
45-
_focus: {
46-
clip: "auto",
47-
width: "auto",
48-
height: "auto",
49-
boxShadow: "outline",
50-
padding: "1rem",
51-
position: "fixed",
52-
top: "1.5rem",
53-
insetStart: "1.5rem",
54-
...styles["_focusVisible"],
55-
},
35+
setup(props, { slots, attrs }) {
36+
function getBaseStyles(styles: any): SystemStyleObject {
37+
return {
38+
userSelect: "none",
39+
border: "0",
40+
borderRadius: "md",
41+
fontWeight: "semibold",
42+
height: "1px",
43+
width: "1px",
44+
margin: "-1px",
45+
padding: "0",
46+
outline: "0",
47+
overflow: "hidden",
48+
position: "absolute",
49+
clip: "rect(0 0 0 0)",
50+
...styles,
51+
_focus: {
52+
clip: "auto",
53+
width: "auto",
54+
height: "auto",
55+
boxShadow: "outline",
56+
padding: "1rem",
57+
position: "fixed",
58+
top: "1.5rem",
59+
insetStart: "1.5rem",
60+
...styles["_focusVisible"],
61+
},
62+
}
5663
}
57-
}
5864

59-
const styles = useStyleConfig("SkipLink", props)
65+
const styles = useStyleConfig("SkipLink", props)
6066

61-
return () => {
62-
return h(
63-
chakra("a", {
64-
__css: {
65-
...getBaseStyles(styles.value),
67+
return () => {
68+
return h(
69+
chakra("a", {
70+
__css: {
71+
...getBaseStyles(styles.value),
72+
},
73+
}),
74+
{
75+
...attrs,
76+
href: `#${props.id}`,
6677
},
67-
}),
68-
{
69-
...attrs,
70-
href: `#${props.id}`,
71-
},
72-
slots
73-
)
74-
}
75-
},
76-
})
78+
slots
79+
)
80+
}
81+
},
82+
})
83+
84+
export interface CSkipNavContentProps extends HTMLChakraProps<"div"> {}
7785

78-
export const CSkipNavContent = defineComponent({
86+
export const CSkipNavContent: ComponentWithProps<
87+
DeepPartial<CSkipNavContentProps>
88+
> = defineComponent({
7989
name: "CSkipNavContent",
8090
props: {
8191
id: {
@@ -91,6 +101,7 @@ export const CSkipNavContent = defineComponent({
91101
...attrs,
92102
id: props.id,
93103
tabIndex: "-1",
104+
"data-testid": FALLBACK_ID,
94105
},
95106
slots
96107
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`CSkipNavContent should render properly 1`] = `
4+
<DocumentFragment>
5+
<div
6+
class="chakra-box css-1avyp1d"
7+
data-testid="chakra-skip-nav"
8+
id="chakra-skip-nav"
9+
tabindex="-1"
10+
/>
11+
</DocumentFragment>
12+
`;
13+
14+
exports[`CSkipNavLink should render properly 1`] = `
15+
<DocumentFragment>
16+
<a
17+
class="css-fkbol"
18+
href="#chakra-skip-nav"
19+
/>
20+
</DocumentFragment>
21+
`;
Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,88 @@
1-
import { render } from '../../test-utils/src'
2-
import { CSkipNav } from '../src'
1+
import {
2+
fireEvent,
3+
render,
4+
screen,
5+
userEvent,
6+
} from "@chakra-ui/vue-test-utils/src"
7+
import { wait } from "@testing-library/user-event/dist/utils"
8+
import { Component } from "vue"
9+
import { CSkipNavContent, CSkipNavLink } from "../src"
310

4-
it('should render properly', () => {
5-
const { asFragment } = render(CSkipNav)
6-
expect(asFragment()).toMatchSnapshot()
7-
})
11+
const MOCK_INPUT_PLACEHOLDER_TEXT = "Search"
12+
13+
const renderBaseTemplate = (options: Component = {}) => {
14+
return render({
15+
components: {
16+
CSkipNavLink,
17+
CSkipNavContent,
18+
},
19+
template: `
20+
<div>
21+
<c-skip-nav-link>Skip to Content</c-skip-nav-link>
22+
<c-skip-nav-content>
23+
<main>
24+
<form>
25+
<input type="text" placeholder=${MOCK_INPUT_PLACEHOLDER_TEXT} />
26+
</form>
27+
</main>
28+
</c-skip-nav-content>
29+
</div>
30+
`,
31+
...options,
32+
})
33+
}
34+
35+
const getSkipLink = () => screen.getByText("Skip to Content")
36+
37+
const getContentWrapper = () => screen.getByTestId("chakra-skip-nav")
38+
39+
const triggerSkipLink = async () => {
40+
const link = getSkipLink()
41+
await fireEvent.keyDown(link, {
42+
key: "Enter",
43+
code: "Enter",
44+
})
45+
}
46+
47+
describe("CSkipNavLink", () => {
48+
it("should render properly", () => {
49+
const { asFragment } = render(CSkipNavLink)
50+
expect(asFragment()).toMatchSnapshot()
51+
})
52+
})
53+
54+
describe("CSkipNavContent", () => {
55+
it("should render properly", () => {
56+
const { asFragment } = render(CSkipNavContent)
57+
expect(asFragment()).toMatchSnapshot()
58+
})
59+
})
60+
61+
describe("CSkipNav Pair", () => {
62+
beforeEach(async () => {
63+
renderBaseTemplate()
64+
userEvent.tab()
65+
})
66+
it("should have the user tab to `CSkipNavLink` after initial render", () => {
67+
const link = getSkipLink()
68+
expect(link).toHaveAttribute("href", "#chakra-skip-nav")
69+
})
70+
71+
it("should have the user navigate from `CSkipNavLink` to `CSkipNavContent` upon selection", async () => {
72+
await triggerSkipLink()
73+
const contentWrapper = getContentWrapper()
74+
75+
wait().then(() => {
76+
expect(contentWrapper).toHaveFocus()
77+
})
78+
})
79+
80+
it("should tab to input after wrapper focus", async () => {
81+
await triggerSkipLink()
82+
userEvent.tab()
83+
84+
const input = screen.getByPlaceholderText(MOCK_INPUT_PLACEHOLDER_TEXT)
85+
86+
expect(input).toHaveFocus()
87+
})
88+
})

0 commit comments

Comments
 (0)