@telus-uds/components-base 0.0.2-prerelease.3 → 0.0.2-prerelease.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ultra.cache.json +1 -0
- package/CHANGELOG.md +55 -0
- package/__fixtures__/testTheme.js +528 -42
- package/__tests__/Button/ButtonBase.test.jsx +3 -32
- package/__tests__/Checkbox/Checkbox.test.jsx +94 -0
- package/__tests__/Divider/Divider.test.jsx +26 -5
- package/__tests__/Feedback/Feedback.test.jsx +42 -0
- package/__tests__/FlexGrid/Col.test.jsx +5 -0
- package/__tests__/InputSupports/InputSupports.test.jsx +50 -0
- package/__tests__/List/List.test.jsx +60 -0
- package/__tests__/Radio/Radio.test.jsx +87 -0
- package/__tests__/Select/Select.test.jsx +93 -0
- package/__tests__/Skeleton/Skeleton.test.jsx +61 -0
- package/__tests__/Spacer/Spacer.test.jsx +63 -0
- package/__tests__/StackView/StackView.test.jsx +216 -0
- package/__tests__/StackView/StackWrap.test.jsx +47 -0
- package/__tests__/StackView/getStackedContent.test.jsx +295 -0
- package/__tests__/Tags/Tags.test.jsx +328 -0
- package/__tests__/TextInput/TextArea.test.jsx +34 -0
- package/__tests__/TextInput/TextInputBase.test.jsx +120 -0
- package/__tests__/Tooltip/Tooltip.test.jsx +65 -0
- package/__tests__/Tooltip/getTooltipPosition.test.js +79 -0
- package/__tests__/utils/useCopy.test.js +31 -0
- package/__tests__/utils/useResponsiveProp.test.jsx +202 -0
- package/__tests__/utils/{spacing.test.jsx → useSpacingScale.test.jsx} +1 -1
- package/__tests__/utils/useUniqueId.test.js +31 -0
- package/jest.config.js +8 -2
- package/lib/Box/Box.js +7 -2
- package/lib/Button/Button.js +10 -3
- package/lib/Button/ButtonBase.js +79 -75
- package/lib/Button/ButtonGroup.js +24 -49
- package/lib/Button/ButtonLink.js +5 -0
- package/lib/Checkbox/Checkbox.js +308 -0
- package/lib/Checkbox/CheckboxInput.native.js +6 -0
- package/lib/Checkbox/CheckboxInput.web.js +57 -0
- package/lib/Checkbox/index.js +2 -0
- package/lib/Divider/Divider.js +40 -2
- package/lib/Feedback/Feedback.js +132 -0
- package/lib/Feedback/index.js +2 -0
- package/lib/Icon/Icon.js +9 -6
- package/lib/Icon/IconText.js +72 -0
- package/lib/Icon/index.js +2 -1
- package/lib/InputLabel/InputLabel.js +88 -0
- package/lib/InputLabel/LabelContent.native.js +8 -0
- package/lib/InputLabel/LabelContent.web.js +17 -0
- package/lib/InputLabel/index.js +2 -0
- package/lib/InputSupports/InputSupports.js +90 -0
- package/lib/InputSupports/index.js +2 -0
- package/lib/InputSupports/propTypes.js +55 -0
- package/lib/Link/ChevronLink.js +35 -10
- package/lib/Link/InlinePressable.native.js +78 -0
- package/lib/Link/InlinePressable.web.js +32 -0
- package/lib/Link/Link.js +11 -10
- package/lib/Link/LinkBase.js +69 -124
- package/lib/Link/TextButton.js +20 -9
- package/lib/Link/index.js +2 -1
- package/lib/List/List.js +52 -0
- package/lib/List/ListItem.js +207 -0
- package/lib/List/index.js +2 -0
- package/lib/Pagination/PageButton.js +3 -26
- package/lib/Pagination/SideButton.js +32 -42
- package/lib/Radio/Radio.js +291 -0
- package/lib/Radio/RadioInput.native.js +6 -0
- package/lib/Radio/RadioInput.web.js +59 -0
- package/lib/Radio/index.js +2 -0
- package/lib/Select/Group.native.js +14 -0
- package/lib/Select/Group.web.js +18 -0
- package/lib/Select/Item.native.js +9 -0
- package/lib/Select/Item.web.js +15 -0
- package/lib/Select/Picker.native.js +87 -0
- package/lib/Select/Picker.web.js +63 -0
- package/lib/Select/Select.js +272 -0
- package/lib/Select/index.js +6 -0
- package/lib/Skeleton/Skeleton.js +119 -0
- package/lib/Skeleton/index.js +2 -0
- package/lib/Spacer/Spacer.js +98 -0
- package/lib/Spacer/index.js +2 -0
- package/lib/StackView/StackView.js +107 -0
- package/lib/StackView/StackWrap.js +32 -0
- package/lib/StackView/StackWrap.native.js +3 -0
- package/lib/StackView/StackWrapBox.js +90 -0
- package/lib/StackView/StackWrapGap.js +50 -0
- package/lib/StackView/common.js +30 -0
- package/lib/StackView/getStackedContent.js +111 -0
- package/lib/StackView/index.js +5 -0
- package/lib/Tags/Tags.js +217 -0
- package/lib/Tags/index.js +2 -0
- package/lib/TextInput/TextArea.js +82 -0
- package/lib/TextInput/TextInput.js +54 -0
- package/lib/TextInput/TextInputBase.js +229 -0
- package/lib/TextInput/index.js +3 -0
- package/lib/TextInput/propTypes.js +31 -0
- package/lib/ThemeProvider/useThemeTokens.js +54 -3
- package/lib/ToggleSwitch/ToggleSwitch.js +1 -1
- package/lib/Tooltip/Backdrop.native.js +35 -0
- package/lib/Tooltip/Backdrop.web.js +52 -0
- package/lib/Tooltip/Tooltip.js +315 -0
- package/lib/Tooltip/dictionary.js +8 -0
- package/lib/Tooltip/getTooltipPosition.js +164 -0
- package/lib/Tooltip/index.js +2 -0
- package/lib/TooltipButton/TooltipButton.js +64 -0
- package/lib/TooltipButton/index.js +2 -0
- package/lib/Typography/Typography.js +4 -23
- package/lib/ViewportProvider/ViewportProvider.js +25 -0
- package/lib/ViewportProvider/index.js +2 -43
- package/lib/ViewportProvider/useViewport.js +3 -0
- package/lib/ViewportProvider/useViewportListener.js +43 -0
- package/lib/index.js +15 -1
- package/lib/utils/a11y/index.js +1 -0
- package/lib/utils/a11y/textSize.js +33 -0
- package/lib/utils/index.js +7 -1
- package/lib/utils/info/index.js +7 -0
- package/lib/utils/info/platform/index.js +11 -0
- package/lib/utils/info/platform/platform.android.js +1 -0
- package/lib/utils/info/platform/platform.ios.js +1 -0
- package/lib/utils/info/platform/platform.native.js +4 -0
- package/lib/utils/info/platform/platform.web.js +1 -0
- package/lib/utils/info/versions.js +5 -0
- package/lib/utils/input.js +3 -1
- package/lib/utils/pressability.js +92 -0
- package/lib/utils/propTypes.js +77 -8
- package/lib/utils/useCopy.js +16 -0
- package/lib/utils/useResponsiveProp.js +47 -0
- package/lib/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +30 -9
- package/lib/utils/useUniqueId.js +12 -0
- package/package.json +7 -5
- package/release-context.json +4 -4
- package/src/Box/Box.jsx +4 -2
- package/src/Button/Button.jsx +6 -3
- package/src/Button/ButtonBase.jsx +72 -75
- package/src/Button/ButtonGroup.jsx +22 -39
- package/src/Button/ButtonLink.jsx +11 -2
- package/src/Checkbox/Checkbox.jsx +275 -0
- package/src/Checkbox/CheckboxInput.native.jsx +6 -0
- package/src/Checkbox/CheckboxInput.web.jsx +55 -0
- package/src/Checkbox/index.js +3 -0
- package/src/Divider/Divider.jsx +38 -3
- package/src/Feedback/Feedback.jsx +108 -0
- package/src/Feedback/index.js +3 -0
- package/src/Icon/Icon.jsx +11 -6
- package/src/Icon/IconText.jsx +63 -0
- package/src/Icon/index.js +2 -1
- package/src/InputLabel/InputLabel.jsx +99 -0
- package/src/InputLabel/LabelContent.native.jsx +6 -0
- package/src/InputLabel/LabelContent.web.jsx +13 -0
- package/src/InputLabel/index.js +3 -0
- package/src/InputSupports/InputSupports.jsx +86 -0
- package/src/InputSupports/index.js +3 -0
- package/src/InputSupports/propTypes.js +44 -0
- package/src/Link/ChevronLink.jsx +28 -7
- package/src/Link/InlinePressable.native.jsx +73 -0
- package/src/Link/InlinePressable.web.jsx +37 -0
- package/src/Link/Link.jsx +17 -13
- package/src/Link/LinkBase.jsx +62 -139
- package/src/Link/TextButton.jsx +25 -11
- package/src/Link/index.js +2 -1
- package/src/List/List.jsx +47 -0
- package/src/List/ListItem.jsx +187 -0
- package/src/List/index.js +3 -0
- package/src/Pagination/PageButton.jsx +3 -17
- package/src/Pagination/SideButton.jsx +27 -38
- package/src/Radio/Radio.jsx +270 -0
- package/src/Radio/RadioInput.native.jsx +6 -0
- package/src/Radio/RadioInput.web.jsx +57 -0
- package/src/Radio/index.js +3 -0
- package/src/Select/Group.native.jsx +14 -0
- package/src/Select/Group.web.jsx +15 -0
- package/src/Select/Item.native.jsx +10 -0
- package/src/Select/Item.web.jsx +11 -0
- package/src/Select/Picker.native.jsx +95 -0
- package/src/Select/Picker.web.jsx +67 -0
- package/src/Select/Select.jsx +265 -0
- package/src/Select/index.js +8 -0
- package/src/Skeleton/Skeleton.jsx +101 -0
- package/src/Skeleton/index.js +3 -0
- package/src/Spacer/Spacer.jsx +91 -0
- package/src/Spacer/index.js +3 -0
- package/src/StackView/StackView.jsx +104 -0
- package/src/StackView/StackWrap.jsx +33 -0
- package/src/StackView/StackWrap.native.jsx +4 -0
- package/src/StackView/StackWrapBox.jsx +93 -0
- package/src/StackView/StackWrapGap.jsx +49 -0
- package/src/StackView/common.jsx +28 -0
- package/src/StackView/getStackedContent.jsx +106 -0
- package/src/StackView/index.js +6 -0
- package/src/Tags/Tags.jsx +206 -0
- package/src/Tags/index.js +3 -0
- package/src/TextInput/TextArea.jsx +78 -0
- package/src/TextInput/TextInput.jsx +52 -0
- package/src/TextInput/TextInputBase.jsx +220 -0
- package/src/TextInput/index.js +4 -0
- package/src/TextInput/propTypes.js +29 -0
- package/src/ThemeProvider/useThemeTokens.js +54 -3
- package/src/ToggleSwitch/ToggleSwitch.jsx +1 -1
- package/src/Tooltip/Backdrop.native.jsx +33 -0
- package/src/Tooltip/Backdrop.web.jsx +60 -0
- package/src/Tooltip/Tooltip.jsx +294 -0
- package/src/Tooltip/dictionary.js +8 -0
- package/src/Tooltip/getTooltipPosition.js +161 -0
- package/src/Tooltip/index.js +3 -0
- package/src/TooltipButton/TooltipButton.jsx +53 -0
- package/src/TooltipButton/index.js +3 -0
- package/src/Typography/Typography.jsx +4 -19
- package/src/ViewportProvider/ViewportProvider.jsx +21 -0
- package/src/ViewportProvider/index.jsx +2 -41
- package/src/ViewportProvider/useViewport.js +5 -0
- package/src/ViewportProvider/useViewportListener.js +43 -0
- package/src/index.js +15 -1
- package/src/utils/a11y/index.js +1 -0
- package/src/utils/a11y/textSize.js +30 -0
- package/src/utils/index.js +8 -1
- package/src/utils/info/index.js +8 -0
- package/src/utils/info/platform/index.js +11 -0
- package/src/utils/info/platform/platform.android.js +1 -0
- package/src/utils/info/platform/platform.ios.js +1 -0
- package/src/utils/info/platform/platform.native.js +4 -0
- package/src/utils/info/platform/platform.web.js +1 -0
- package/src/utils/info/versions.js +6 -0
- package/src/utils/input.js +2 -1
- package/src/utils/pressability.js +92 -0
- package/src/utils/propTypes.js +97 -13
- package/src/utils/useCopy.js +13 -0
- package/src/utils/useResponsiveProp.js +50 -0
- package/src/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +25 -10
- package/src/utils/useUniqueId.js +14 -0
- package/stories/A11yText/A11yText.stories.jsx +11 -5
- package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
- package/stories/Box/Box.stories.jsx +29 -2
- package/stories/Button/Button.stories.jsx +21 -20
- package/stories/Button/ButtonGroup.stories.jsx +2 -1
- package/stories/Button/ButtonLink.stories.jsx +6 -4
- package/stories/Card/Card.stories.jsx +13 -1
- package/stories/Checkbox/Checkbox.stories.jsx +71 -0
- package/stories/Divider/Divider.stories.jsx +26 -2
- package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
- package/stories/Feedback/Feedback.stories.jsx +96 -0
- package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
- package/stories/Icon/Icon.stories.jsx +11 -3
- package/stories/InputLabel/InputLabel.stories.jsx +42 -0
- package/stories/Link/ChevronLink.stories.jsx +20 -4
- package/stories/Link/Link.stories.jsx +39 -3
- package/stories/Link/TextButton.stories.jsx +24 -2
- package/stories/List/List.stories.jsx +117 -0
- package/stories/Pagination/Pagination.stories.jsx +28 -14
- package/stories/Radio/Radio.stories.jsx +113 -0
- package/stories/Select/Select.stories.jsx +55 -0
- package/stories/SideNav/SideNav.stories.jsx +17 -2
- package/stories/Skeleton/Skeleton.stories.jsx +36 -0
- package/stories/Spacer/Spacer.stories.jsx +38 -0
- package/stories/StackView/StackView.stories.jsx +75 -0
- package/stories/StackView/StackWrap.stories.jsx +64 -0
- package/stories/Tags/Tags.stories.jsx +69 -0
- package/stories/TextInput/TextArea.stories.jsx +100 -0
- package/stories/TextInput/TextInput.stories.jsx +103 -0
- package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
- package/stories/Tooltip/Tooltip.stories.jsx +81 -0
- package/stories/TooltipButton/TooltipButton.stories.jsx +11 -0
- package/stories/Typography/Typography.stories.jsx +12 -3
- package/stories/platform-supports.web.jsx +1 -1
- package/stories/supports.jsx +110 -14
- package/lib/Pagination/useCopy.js +0 -10
- package/lib/utils/spacing/index.js +0 -2
- package/lib/utils/spacing/utils.js +0 -32
- package/src/Pagination/useCopy.js +0 -7
- package/src/utils/spacing/index.js +0 -3
- package/src/utils/spacing/utils.js +0 -28
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react-native'
|
|
3
|
+
import { toHaveTextContent } from '@testing-library/jest-native'
|
|
4
|
+
|
|
5
|
+
import Theme from '../../__fixtures__/Theme'
|
|
6
|
+
import Tags from '../../src/Tags'
|
|
7
|
+
|
|
8
|
+
const items = [
|
|
9
|
+
{ label: 'One', id: 'one', accessibilityLabel: 'Option one' },
|
|
10
|
+
{ label: 'Two', id: 'two', accessibilityLabel: 'Option two' },
|
|
11
|
+
{ label: 'Three', id: 'three', accessibilityLabel: 'Option three' },
|
|
12
|
+
{ label: 'Four', id: 'four', accessibilityLabel: 'Option four' }
|
|
13
|
+
]
|
|
14
|
+
const checked = { checked: true }
|
|
15
|
+
|
|
16
|
+
// expect().toHaveTextContent doesn't work on arrays, expect().toContain etc doesn't match elements
|
|
17
|
+
const containsText = (queryResult, text) =>
|
|
18
|
+
queryResult.some((testInstance) => toHaveTextContent(testInstance, text).pass)
|
|
19
|
+
|
|
20
|
+
describe('Tags', () => {
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
const consoleError = console.error
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
// eslint-disable-next-line no-console
|
|
25
|
+
console.error = () => {}
|
|
26
|
+
})
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
// eslint-disable-next-line no-console
|
|
29
|
+
console.error = consoleError
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('Throws if has `values` without `onChange`', () => {
|
|
33
|
+
expect(() =>
|
|
34
|
+
render(
|
|
35
|
+
<Theme>
|
|
36
|
+
<Tags items={items} values={['one']} />
|
|
37
|
+
</Theme>
|
|
38
|
+
)
|
|
39
|
+
).toThrow(/values.+without.+onChange/)
|
|
40
|
+
})
|
|
41
|
+
it("Doesn't throw if has `values` without `onChange` and is read only", () => {
|
|
42
|
+
expect(() =>
|
|
43
|
+
render(
|
|
44
|
+
<Theme>
|
|
45
|
+
<Tags items={items} values={['one']} readOnly />
|
|
46
|
+
</Theme>
|
|
47
|
+
)
|
|
48
|
+
).not.toThrow()
|
|
49
|
+
})
|
|
50
|
+
it('Throws if has both `values` and `initialValues`', () => {
|
|
51
|
+
expect(() =>
|
|
52
|
+
render(
|
|
53
|
+
<Theme>
|
|
54
|
+
<Tags items={items} values={['one']} initialValues={['one']} onChange={() => {}} />
|
|
55
|
+
</Theme>
|
|
56
|
+
)
|
|
57
|
+
).toThrow(/both(?=.*initialValues)(?=.*values){2}/)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe('Tags (uncontrolled)', () => {
|
|
62
|
+
// These tests are almost the same as ButtonGroup while Tags-specific behaviours are still TBC
|
|
63
|
+
it('Selects one and only one item if maxValues is passed', async () => {
|
|
64
|
+
const { getByText, queryAllByA11yState } = render(
|
|
65
|
+
<Theme>
|
|
66
|
+
<Tags items={items} maxValues={1} />
|
|
67
|
+
</Theme>
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
71
|
+
|
|
72
|
+
const one = getByText('One')
|
|
73
|
+
await fireEvent.press(one)
|
|
74
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
75
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
76
|
+
|
|
77
|
+
const two = getByText('Two')
|
|
78
|
+
await fireEvent.press(two)
|
|
79
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
80
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
81
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('Deselects if the selected item is pressed', async () => {
|
|
85
|
+
const { getByText, queryAllByA11yState } = render(
|
|
86
|
+
<Theme>
|
|
87
|
+
<Tags items={items} />
|
|
88
|
+
</Theme>
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
92
|
+
|
|
93
|
+
const three = getByText('Three')
|
|
94
|
+
await fireEvent.press(three)
|
|
95
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
96
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
97
|
+
|
|
98
|
+
await fireEvent.press(three)
|
|
99
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
100
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).not.toBeTruthy()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('Selects <= two items when maxValues === 2', async () => {
|
|
104
|
+
const { getByText, queryAllByA11yState } = render(
|
|
105
|
+
<Theme>
|
|
106
|
+
<Tags items={items} maxValues={2} />
|
|
107
|
+
</Theme>
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
111
|
+
|
|
112
|
+
const one = getByText('One')
|
|
113
|
+
await fireEvent.press(one)
|
|
114
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
115
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
116
|
+
|
|
117
|
+
const two = getByText('Two')
|
|
118
|
+
await fireEvent.press(two)
|
|
119
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
120
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
121
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
122
|
+
|
|
123
|
+
const three = getByText('Three')
|
|
124
|
+
await fireEvent.press(three)
|
|
125
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
126
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
127
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
128
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
129
|
+
|
|
130
|
+
const four = getByText('Four')
|
|
131
|
+
await fireEvent.press(four)
|
|
132
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
133
|
+
expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
|
|
134
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
135
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
|
|
136
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('Is accessible as checkboxes by default', async () => {
|
|
140
|
+
const { queryAllByA11yRole, queryAllByA11yState } = render(
|
|
141
|
+
<Theme>
|
|
142
|
+
<Tags items={items} />
|
|
143
|
+
</Theme>
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
expect(queryAllByA11yRole('radioGroup')).toHaveLength(0)
|
|
147
|
+
expect(queryAllByA11yRole('radio')).toHaveLength(0)
|
|
148
|
+
|
|
149
|
+
const checks = queryAllByA11yRole('checkbox')
|
|
150
|
+
expect(checks).toHaveLength(4)
|
|
151
|
+
|
|
152
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
153
|
+
await fireEvent.press(checks[0])
|
|
154
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('Selects unlimited items by default', async () => {
|
|
158
|
+
const { getByText, queryAllByA11yState } = render(
|
|
159
|
+
<Theme>
|
|
160
|
+
<Tags items={items} />
|
|
161
|
+
</Theme>
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
expect(queryAllByA11yState(checked)).toHaveLength(0)
|
|
165
|
+
|
|
166
|
+
const one = getByText('One')
|
|
167
|
+
await fireEvent.press(one)
|
|
168
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
169
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
170
|
+
|
|
171
|
+
const two = getByText('Two')
|
|
172
|
+
await fireEvent.press(two)
|
|
173
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
174
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
175
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
176
|
+
|
|
177
|
+
const three = getByText('Three')
|
|
178
|
+
await fireEvent.press(three)
|
|
179
|
+
expect(queryAllByA11yState(checked)).toHaveLength(3)
|
|
180
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
181
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
182
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
183
|
+
|
|
184
|
+
const four = getByText('Four')
|
|
185
|
+
await fireEvent.press(four)
|
|
186
|
+
expect(queryAllByA11yState(checked)).toHaveLength(4)
|
|
187
|
+
expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
|
|
188
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
189
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
190
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('Auto-selects any provided initialValues', async () => {
|
|
194
|
+
const { getByText, queryAllByA11yState } = render(
|
|
195
|
+
<Theme>
|
|
196
|
+
<Tags items={items} initialValues={['one', 'two']} maxValues={3} />
|
|
197
|
+
</Theme>
|
|
198
|
+
)
|
|
199
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
200
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
201
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
202
|
+
|
|
203
|
+
const three = getByText('Three')
|
|
204
|
+
await fireEvent.press(three)
|
|
205
|
+
|
|
206
|
+
expect(queryAllByA11yState(checked)).toHaveLength(3)
|
|
207
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
208
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
209
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
210
|
+
|
|
211
|
+
const four = getByText('Four')
|
|
212
|
+
await fireEvent.press(four)
|
|
213
|
+
expect(queryAllByA11yState(checked)).toHaveLength(3)
|
|
214
|
+
expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
|
|
215
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
216
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
217
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
218
|
+
|
|
219
|
+
const two = getByText('Two')
|
|
220
|
+
await fireEvent.press(two)
|
|
221
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
222
|
+
expect(containsText(queryAllByA11yState(checked), 'Four')).toBeTruthy()
|
|
223
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
224
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
|
|
225
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
describe('Tags (controlled)', () => {
|
|
230
|
+
it('Calls onChange handler on press in controlled mode, providing pressed id', async () => {
|
|
231
|
+
const handleChange = jest.fn((arg) => arg)
|
|
232
|
+
const { getByText } = render(
|
|
233
|
+
<Theme>
|
|
234
|
+
<Tags items={items} values={[]} onChange={handleChange} />
|
|
235
|
+
</Theme>
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
expect(handleChange).toHaveBeenCalledTimes(0)
|
|
239
|
+
|
|
240
|
+
const one = getByText('One')
|
|
241
|
+
await fireEvent.press(one)
|
|
242
|
+
expect(handleChange).toHaveBeenCalledTimes(1)
|
|
243
|
+
|
|
244
|
+
expect(handleChange.mock.calls[0][0]).toEqual(['one'])
|
|
245
|
+
|
|
246
|
+
const two = getByText('Two')
|
|
247
|
+
await fireEvent.press(two)
|
|
248
|
+
expect(handleChange).toHaveBeenCalledTimes(2)
|
|
249
|
+
expect(handleChange.mock.calls[1][0]).toEqual(['two'])
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it("Doesn't change its own selection if `values` is passed", async () => {
|
|
253
|
+
const { getByText, queryAllByA11yState } = render(
|
|
254
|
+
<Theme>
|
|
255
|
+
<Tags items={items} values={['one']} onChange={() => {}} />
|
|
256
|
+
</Theme>
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
260
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
261
|
+
|
|
262
|
+
const one = getByText('One')
|
|
263
|
+
await fireEvent.press(one)
|
|
264
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
265
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
266
|
+
|
|
267
|
+
const two = getByText('Two')
|
|
268
|
+
await fireEvent.press(two)
|
|
269
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
270
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
|
|
271
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('Does not render an invalid `values` invalidly', async () => {
|
|
275
|
+
const { queryAllByA11yState } = render(
|
|
276
|
+
<Theme>
|
|
277
|
+
<Tags items={items} values={['one', 'two', 'three']} maxValues={2} onChange={() => {}} />
|
|
278
|
+
</Theme>
|
|
279
|
+
)
|
|
280
|
+
expect(queryAllByA11yState(checked)).toHaveLength(2)
|
|
281
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).not.toBeTruthy()
|
|
282
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).toBeTruthy()
|
|
283
|
+
expect(containsText(queryAllByA11yState(checked), 'Three')).toBeTruthy()
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
describe('Tags (read-only)', () => {
|
|
288
|
+
it("Doesn't call onChange handler when read-only", async () => {
|
|
289
|
+
const handleChange = jest.fn((arg) => arg)
|
|
290
|
+
const { getByText } = render(
|
|
291
|
+
<Theme>
|
|
292
|
+
<Tags items={items} values={[]} onChange={handleChange} readOnly />
|
|
293
|
+
</Theme>
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
expect(handleChange).toHaveBeenCalledTimes(0)
|
|
297
|
+
|
|
298
|
+
const one = getByText('One')
|
|
299
|
+
await fireEvent.press(one)
|
|
300
|
+
expect(handleChange).toHaveBeenCalledTimes(0)
|
|
301
|
+
|
|
302
|
+
const two = getByText('Two')
|
|
303
|
+
await fireEvent.press(two)
|
|
304
|
+
expect(handleChange).toHaveBeenCalledTimes(0)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it("Doesn't change its selection on press", async () => {
|
|
308
|
+
const { getByText, queryAllByA11yState } = render(
|
|
309
|
+
<Theme>
|
|
310
|
+
<Tags items={items} values={['one']} readOnly />
|
|
311
|
+
</Theme>
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
315
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
316
|
+
|
|
317
|
+
const one = getByText('One')
|
|
318
|
+
await fireEvent.press(one)
|
|
319
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
320
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
321
|
+
|
|
322
|
+
const two = getByText('Two')
|
|
323
|
+
await fireEvent.press(two)
|
|
324
|
+
expect(queryAllByA11yState(checked)).toHaveLength(1)
|
|
325
|
+
expect(containsText(queryAllByA11yState(checked), 'Two')).not.toBeTruthy()
|
|
326
|
+
expect(containsText(queryAllByA11yState(checked), 'One')).toBeTruthy()
|
|
327
|
+
})
|
|
328
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fireEvent, render } from '@testing-library/react-native'
|
|
3
|
+
|
|
4
|
+
import { Platform } from 'react-native'
|
|
5
|
+
import { TextArea } from '../../src'
|
|
6
|
+
import Theme from '../../__fixtures__/Theme'
|
|
7
|
+
|
|
8
|
+
describe('TextArea', () => {
|
|
9
|
+
it('renders', () => {
|
|
10
|
+
// at least one called test is required in a suite
|
|
11
|
+
render(<TextArea />, { wrapper: Theme })
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
// TODO: this won't be called until cross-platform Jest tests are configured
|
|
15
|
+
// see https://github.com/telus/universal-design-system/issues/319
|
|
16
|
+
if (Platform.OS === 'web') {
|
|
17
|
+
it('grows in size on input', () => {
|
|
18
|
+
const { getByTestId } = render(
|
|
19
|
+
<TextArea tokens={{ minLines: 1, maxLines: 5, lineHeight: 20 }} testID="textarea" />,
|
|
20
|
+
{
|
|
21
|
+
wrapper: Theme
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const textarea = getByTestId('textarea')
|
|
26
|
+
|
|
27
|
+
expect(textarea).toHaveStyle({ height: 20 })
|
|
28
|
+
|
|
29
|
+
fireEvent.changeText(textarea, '\n\n\n')
|
|
30
|
+
|
|
31
|
+
expect(textarea).toHaveStyle({ height: 60 })
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
})
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { fireEvent, render } from '@testing-library/react-native'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import TextInputBase from '../../src/TextInput/TextInputBase'
|
|
4
|
+
import Viewport from '../../__fixtures__/Viewport'
|
|
5
|
+
import Theme from '../../__fixtures__/Theme'
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line react/prop-types
|
|
8
|
+
const Wrapper = ({ children }) => (
|
|
9
|
+
<Viewport viewport="xs">
|
|
10
|
+
<Theme>{children}</Theme>
|
|
11
|
+
</Viewport>
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
describe('TextInputBaseBase', () => {
|
|
15
|
+
it('triggers the interactive callbacks', () => {
|
|
16
|
+
const onFocus = jest.fn()
|
|
17
|
+
const onBlur = jest.fn()
|
|
18
|
+
const onMouseOver = jest.fn()
|
|
19
|
+
const onMouseOut = jest.fn()
|
|
20
|
+
|
|
21
|
+
const { getByA11yLabel } = render(
|
|
22
|
+
<TextInputBase
|
|
23
|
+
accessibilityLabel="Input label"
|
|
24
|
+
onFocus={onFocus}
|
|
25
|
+
onBlur={onBlur}
|
|
26
|
+
onMouseOver={onMouseOver}
|
|
27
|
+
onMouseOut={onMouseOut}
|
|
28
|
+
/>,
|
|
29
|
+
{
|
|
30
|
+
wrapper: Wrapper
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const input = getByA11yLabel('Input label')
|
|
35
|
+
|
|
36
|
+
expect(onFocus).not.toHaveBeenCalled()
|
|
37
|
+
fireEvent(input, 'focus')
|
|
38
|
+
expect(onFocus).toHaveBeenCalledTimes(1)
|
|
39
|
+
|
|
40
|
+
expect(onBlur).not.toHaveBeenCalled()
|
|
41
|
+
fireEvent(input, 'blur')
|
|
42
|
+
expect(onBlur).toHaveBeenCalledTimes(1)
|
|
43
|
+
|
|
44
|
+
expect(onMouseOver).not.toHaveBeenCalled()
|
|
45
|
+
fireEvent(input, 'mouseOver')
|
|
46
|
+
expect(onMouseOver).toHaveBeenCalledTimes(1)
|
|
47
|
+
|
|
48
|
+
expect(onMouseOut).not.toHaveBeenCalled()
|
|
49
|
+
fireEvent(input, 'mouseOut')
|
|
50
|
+
expect(onMouseOut).toHaveBeenCalledTimes(1)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it("can't be edited when inactive", () => {
|
|
54
|
+
const { getByA11yLabel } = render(<TextInputBase accessibilityLabel="Input label" inactive />, {
|
|
55
|
+
wrapper: Wrapper
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const input = getByA11yLabel('Input label')
|
|
59
|
+
|
|
60
|
+
expect(input).toHaveProp('editable', false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('changes value when uncontrolled', () => {
|
|
64
|
+
const onChange = jest.fn()
|
|
65
|
+
|
|
66
|
+
const { getByA11yLabel } = render(
|
|
67
|
+
<TextInputBase accessibilityLabel="Input label" onChange={onChange} />,
|
|
68
|
+
{
|
|
69
|
+
wrapper: Wrapper
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const input = getByA11yLabel('Input label')
|
|
74
|
+
|
|
75
|
+
expect(onChange).not.toHaveBeenCalled()
|
|
76
|
+
fireEvent.changeText(input, 'new value')
|
|
77
|
+
expect(onChange).toHaveBeenCalledTimes(1)
|
|
78
|
+
expect(onChange).toHaveBeenLastCalledWith('new value')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('changes value when controlled', () => {
|
|
82
|
+
const onChange = jest.fn()
|
|
83
|
+
|
|
84
|
+
const { getByA11yLabel } = render(
|
|
85
|
+
<TextInputBase accessibilityLabel="Input label" onChange={onChange} value="initial value" />,
|
|
86
|
+
{
|
|
87
|
+
wrapper: Wrapper
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const input = getByA11yLabel('Input label')
|
|
92
|
+
|
|
93
|
+
expect(onChange).not.toHaveBeenCalled()
|
|
94
|
+
fireEvent.changeText(input, 'new value')
|
|
95
|
+
expect(onChange).toHaveBeenCalledTimes(1)
|
|
96
|
+
expect(onChange).toHaveBeenLastCalledWith('new value')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it("doesn't change value when readOnly", () => {
|
|
100
|
+
const onChange = jest.fn()
|
|
101
|
+
|
|
102
|
+
const { getByA11yLabel } = render(
|
|
103
|
+
<TextInputBase
|
|
104
|
+
accessibilityLabel="Input label"
|
|
105
|
+
onChange={onChange}
|
|
106
|
+
value="initial value"
|
|
107
|
+
readOnly
|
|
108
|
+
/>,
|
|
109
|
+
{
|
|
110
|
+
wrapper: Wrapper
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
const input = getByA11yLabel('Input label')
|
|
115
|
+
|
|
116
|
+
expect(onChange).not.toHaveBeenCalled()
|
|
117
|
+
fireEvent.changeText(input, 'new value')
|
|
118
|
+
expect(onChange).not.toHaveBeenCalled()
|
|
119
|
+
})
|
|
120
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fireEvent, render } from '@testing-library/react-native'
|
|
3
|
+
|
|
4
|
+
import { Text } from 'react-native'
|
|
5
|
+
import { Tooltip } from '../../src'
|
|
6
|
+
|
|
7
|
+
import Theme from '../../__fixtures__/Theme'
|
|
8
|
+
import Viewport from '../../__fixtures__/Viewport'
|
|
9
|
+
|
|
10
|
+
const wrapper = ({ children }) => (
|
|
11
|
+
<Theme>
|
|
12
|
+
<Viewport>{children}</Viewport>
|
|
13
|
+
</Theme>
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
const content = 'tooltip content'
|
|
17
|
+
|
|
18
|
+
describe('Tooltip', () => {
|
|
19
|
+
it('renders content after control is pressed', () => {
|
|
20
|
+
const { queryByText, getByA11yRole } = render(<Tooltip content={content} />, { wrapper })
|
|
21
|
+
|
|
22
|
+
expect(queryByText(content)).toBeFalsy()
|
|
23
|
+
|
|
24
|
+
fireEvent.press(getByA11yRole('button'))
|
|
25
|
+
|
|
26
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it("renders custom control, and renders content after it's pressed", () => {
|
|
30
|
+
const { queryByTestId, getByA11yRole, queryByText } = render(
|
|
31
|
+
<Tooltip content={content}>
|
|
32
|
+
<Text testID="control" />
|
|
33
|
+
</Tooltip>,
|
|
34
|
+
{ wrapper }
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
expect(queryByTestId('control')).not.toBeFalsy()
|
|
38
|
+
|
|
39
|
+
expect(queryByText(content)).toBeFalsy()
|
|
40
|
+
|
|
41
|
+
fireEvent.press(getByA11yRole('button'))
|
|
42
|
+
|
|
43
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it("renders custom control render function, and renders content after it's pressed", () => {
|
|
47
|
+
const { queryByTestId, getByA11yRole, queryByText } = render(
|
|
48
|
+
<Tooltip content={content} variant={{ inverse: true }}>
|
|
49
|
+
{(pressableState, variant) => (
|
|
50
|
+
<Text testID="control">{variant.inverse ? 'Inverse' : 'Default'}</Text>
|
|
51
|
+
)}
|
|
52
|
+
</Tooltip>,
|
|
53
|
+
{ wrapper }
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
expect(queryByTestId('control')).not.toBeFalsy()
|
|
57
|
+
expect(queryByText('Inverse')).not.toBeFalsy()
|
|
58
|
+
|
|
59
|
+
expect(queryByText(content)).toBeFalsy()
|
|
60
|
+
|
|
61
|
+
fireEvent.press(getByA11yRole('button'))
|
|
62
|
+
|
|
63
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import getTooltipPosition from '../../lib/Tooltip/getTooltipPosition'
|
|
2
|
+
|
|
3
|
+
const windowDimensions = {
|
|
4
|
+
width: 320,
|
|
5
|
+
height: 400
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const tooltipDimensions = {
|
|
9
|
+
width: 200,
|
|
10
|
+
height: 40
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('getTooltipPosition()', () => {
|
|
14
|
+
it('automatically places the tooltip within viewport', () => {
|
|
15
|
+
const controlLayout = {
|
|
16
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
17
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
18
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
19
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
23
|
+
const result = getTooltipPosition('auto', {
|
|
24
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
25
|
+
tooltipDimensions,
|
|
26
|
+
windowDimensions
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(result.position).toBe(position)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('places the tooltip in the position from prop if that fits within viewport', () => {
|
|
34
|
+
const controlLayout = {
|
|
35
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
36
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
37
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
38
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
42
|
+
const positionProp = position // this would normally come from the component's prop
|
|
43
|
+
|
|
44
|
+
const result = getTooltipPosition(positionProp, {
|
|
45
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
46
|
+
tooltipDimensions,
|
|
47
|
+
windowDimensions
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
expect(result.position).toBe(position)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it("places the tooltip in a different position if prop wouldn't fit in the viewport", () => {
|
|
55
|
+
const controlLayout = {
|
|
56
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
57
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
58
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
59
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const positionProp = {
|
|
63
|
+
right: 'left',
|
|
64
|
+
left: 'right',
|
|
65
|
+
above: 'below',
|
|
66
|
+
below: 'above'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
70
|
+
const result = getTooltipPosition(positionProp[position], {
|
|
71
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
72
|
+
tooltipDimensions,
|
|
73
|
+
windowDimensions
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
expect(result.position).toBe(position)
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
2
|
+
import useCopy from '../../lib/utils/useCopy'
|
|
3
|
+
|
|
4
|
+
const dictionary = {
|
|
5
|
+
en: {
|
|
6
|
+
'translation key': 'english version'
|
|
7
|
+
},
|
|
8
|
+
fr: {
|
|
9
|
+
'translation key': 'french version'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('useCopy hook', () => {
|
|
14
|
+
it('returns a correct english translation', () => {
|
|
15
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
|
|
16
|
+
|
|
17
|
+
expect(result.current('translation key')).toBe('english version')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('returns a correct french translation', () => {
|
|
21
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'fr' }))
|
|
22
|
+
|
|
23
|
+
expect(result.current('translation key')).toBe('french version')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('returns undefined when no translation is found', () => {
|
|
27
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
|
|
28
|
+
|
|
29
|
+
expect(result.current('non-existing key')).toBe(undefined)
|
|
30
|
+
})
|
|
31
|
+
})
|