@loadsmart/loadsmart-ui 5.11.2-beta.1 → 5.12.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loadsmart/loadsmart-ui",
3
- "version": "5.11.2-beta.1",
3
+ "version": "5.12.1",
4
4
  "description": "Miranda UI, a React UI library",
5
5
  "main": "dist",
6
6
  "files": [
@@ -97,9 +97,9 @@
97
97
  "@svgr/webpack": "5.5.0",
98
98
  "@tailwindcss/postcss7-compat": "2.1.2",
99
99
  "@testing-library/jest-dom": "5.16.5",
100
- "@testing-library/react": "11.2.6",
101
- "@testing-library/react-hooks": "5.1.2",
102
- "@testing-library/user-event": "13.1.9",
100
+ "@testing-library/react": "^11.2.7",
101
+ "@testing-library/react-hooks": "^5.1.3",
102
+ "@testing-library/user-event": "^13.5.0",
103
103
  "@types/chance": "1.1.1",
104
104
  "@types/jest": "26.0.23",
105
105
  "@types/lodash.debounce": "4.0.6",
@@ -135,7 +135,7 @@
135
135
  "eslint-plugin-react": "7.23.2",
136
136
  "eslint-plugin-react-hooks": "4.2.0",
137
137
  "eslint-plugin-storybook": "^0.5.11",
138
- "eslint-plugin-testing-library": "4.2.1",
138
+ "eslint-plugin-testing-library": "^5.9.1",
139
139
  "fork-ts-checker-webpack-plugin": "6.2.6",
140
140
  "husky": "7.0.4",
141
141
  "identity-obj-proxy": "3.0.0",
@@ -83,10 +83,11 @@ describe('<Banner />', () => {
83
83
  onSecondaryActionButtonClick: onSecondaryActionButtonClick,
84
84
  }
85
85
 
86
- const { getByText } = setupBannerAction(props)
87
- getByText(props.title)
88
- getByText('click me')
89
- getByText('or click me')
86
+ setupBannerAction(props)
87
+
88
+ screen.getByText(props.title)
89
+ screen.getByText('click me')
90
+ screen.getByText('or click me')
90
91
  })
91
92
 
92
93
  it('allows to use React Element for title', () => {
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import { screen } from '@testing-library/react'
2
3
 
3
4
  import Checkbox from './Checkbox'
4
5
  import generator from '../../tests/generator'
@@ -13,10 +14,10 @@ describe('<Checkbox />', () => {
13
14
  onChange: jest.fn(),
14
15
  }
15
16
 
16
- const { getByTestId } = setup(props)
17
+ setup(props)
17
18
 
18
- const component = getByTestId('checkbox')
19
- const selector = getByTestId('selector')
19
+ const component = screen.getByTestId('checkbox')
20
+ const selector = screen.getByTestId('selector')
20
21
 
21
22
  expect(component).toHaveTextContent(props.children)
22
23
  expect(selector).toHaveAttribute('type', 'checkbox')
@@ -29,12 +30,10 @@ describe('<Checkbox />', () => {
29
30
  onChange: jest.fn(),
30
31
  }
31
32
 
32
- const { getByTestId } = setup(props)
33
+ setup(props)
33
34
 
34
- const component = getByTestId('checkbox')
35
-
36
- expect(component).toHaveTextContent(props.children)
37
- expect(getByTestId('selection-leading')).toBeInTheDocument()
35
+ expect(screen.getByTestId('checkbox')).toHaveTextContent(props.children)
36
+ expect(screen.getByTestId('selection-leading')).toBeInTheDocument()
38
37
  })
39
38
 
40
39
  it('renders trailing correctly', () => {
@@ -44,12 +43,10 @@ describe('<Checkbox />', () => {
44
43
  onChange: jest.fn(),
45
44
  }
46
45
 
47
- const { getByTestId } = setup(props)
48
-
49
- const component = getByTestId('checkbox')
46
+ setup(props)
50
47
 
51
- expect(component).toHaveTextContent(props.children)
52
- expect(getByTestId('selection-trailing')).toBeInTheDocument()
48
+ expect(screen.getByTestId('checkbox')).toHaveTextContent(props.children)
49
+ expect(screen.getByTestId('selection-trailing')).toBeInTheDocument()
53
50
  })
54
51
 
55
52
  it('triggers onChange when clicked', () => {
@@ -58,12 +55,12 @@ describe('<Checkbox />', () => {
58
55
  onChange: jest.fn(),
59
56
  }
60
57
 
61
- const { getByTestId } = setup(props)
58
+ setup(props)
59
+
60
+ expect(screen.getByTestId('selector')).not.toBeChecked()
62
61
 
63
- const selector = getByTestId('selector') as HTMLInputElement
62
+ fire.click(screen.getByTestId('selector'))
64
63
 
65
- expect(selector.checked).toBe(false)
66
- fire.click(selector)
67
- expect(selector.checked).toBe(true)
64
+ expect(screen.getByTestId('selector')).toBeChecked()
68
65
  })
69
66
  })
@@ -29,7 +29,7 @@ describe('Dropdown', () => {
29
29
  user.click(screen.getByText('Actions'))
30
30
 
31
31
  for (let i = 0; i < ACTIONS.length; i++) {
32
- expect(screen.queryByText(ACTIONS[i].label)).toBeInTheDocument()
32
+ expect(screen.getByText(ACTIONS[i].label)).toBeInTheDocument()
33
33
  }
34
34
  })
35
35
 
@@ -38,7 +38,7 @@ describe('Dropdown', () => {
38
38
 
39
39
  user.click(screen.getByText('Actions'))
40
40
 
41
- await waitFor(() => expect(screen.queryByTestId('dropdown-menu')).toBeInTheDocument())
41
+ await screen.findByTestId('dropdown-menu')
42
42
 
43
43
  const items = screen.getAllByTestId('dropdown-menu-item')
44
44
  expect(items.length).toBe(ACTIONS.length)
@@ -80,18 +80,18 @@ describe('Dropdown', () => {
80
80
 
81
81
  user.click(screen.getByText('Sections'))
82
82
 
83
- await waitFor(() => expect(screen.queryByTestId('dropdown-menu')).toBeInTheDocument())
83
+ await screen.findByTestId('dropdown-menu')
84
84
 
85
85
  screen.getByText('My profile')
86
86
 
87
87
  for (let i = 0; i < PROFILE_ACTIONS.length; i++) {
88
- expect(screen.queryByText(PROFILE_ACTIONS[i].label)).toBeInTheDocument()
88
+ expect(screen.getByText(PROFILE_ACTIONS[i].label)).toBeInTheDocument()
89
89
  }
90
90
 
91
91
  screen.getByText('Subscription')
92
92
 
93
93
  for (let i = 0; i < SUBSCRIPTION_ACTIONS.length; i++) {
94
- expect(screen.queryByText(SUBSCRIPTION_ACTIONS[i].label)).toBeInTheDocument()
94
+ expect(screen.getByText(SUBSCRIPTION_ACTIONS[i].label)).toBeInTheDocument()
95
95
  }
96
96
  })
97
97
 
@@ -102,7 +102,7 @@ describe('Dropdown', () => {
102
102
 
103
103
  user.click(screen.getByText('Sections'))
104
104
 
105
- await waitFor(() => expect(screen.queryByTestId('dropdown-menu')).toBeInTheDocument())
105
+ await screen.findByTestId('dropdown-menu')
106
106
 
107
107
  const items = screen.getAllByTestId('dropdown-menu-item')
108
108
  expect(items.length).toBe(SECTION_ACTIONS.length)
@@ -136,12 +136,12 @@ describe('Dropdown', () => {
136
136
 
137
137
  user.click(screen.getByText('With Header & Footer'))
138
138
 
139
- await waitFor(() => expect(screen.queryByTestId('dropdown-menu')).toBeInTheDocument())
139
+ await screen.findByTestId('dropdown-menu')
140
140
 
141
141
  screen.getByText('Header')
142
142
 
143
143
  for (let i = 0; i < ACTIONS.length; i++) {
144
- expect(screen.queryByText(ACTIONS[i].label)).toBeInTheDocument()
144
+ expect(screen.getByText(ACTIONS[i].label)).toBeInTheDocument()
145
145
  }
146
146
 
147
147
  screen.getByText('A cool footer')
@@ -152,7 +152,7 @@ describe('Dropdown', () => {
152
152
 
153
153
  user.click(screen.getByText('With Header & Footer'))
154
154
 
155
- await waitFor(() => expect(screen.queryByTestId('dropdown-menu')).toBeInTheDocument())
155
+ await screen.findByTestId('dropdown-menu')
156
156
 
157
157
  const items = screen.getAllByTestId('dropdown-menu-item')
158
158
  expect(items.length).toBe(ACTIONS.length)
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import { screen } from '@testing-library/react'
2
3
 
3
4
  import Radio from './Radio'
4
5
  import generator from '../../tests/generator'
@@ -13,10 +14,10 @@ describe('<Radio />', () => {
13
14
  onChange: jest.fn(),
14
15
  }
15
16
 
16
- const { getByTestId } = setup(props)
17
+ setup(props)
17
18
 
18
- const component = getByTestId('radio')
19
- const selector = getByTestId('selector')
19
+ const component = screen.getByTestId('radio')
20
+ const selector = screen.getByTestId('selector')
20
21
 
21
22
  expect(component).toHaveTextContent(props.children)
22
23
  expect(selector).toHaveAttribute('type', 'radio')
@@ -29,12 +30,10 @@ describe('<Radio />', () => {
29
30
  onChange: jest.fn(),
30
31
  }
31
32
 
32
- const { getByTestId } = setup(props)
33
+ setup(props)
33
34
 
34
- const component = getByTestId('radio')
35
-
36
- expect(component).toHaveTextContent(props.children)
37
- expect(getByTestId('selection-leading')).toBeInTheDocument()
35
+ expect(screen.getByTestId('radio')).toHaveTextContent(props.children)
36
+ expect(screen.getByTestId('selection-leading')).toBeInTheDocument()
38
37
  })
39
38
 
40
39
  it('renders trailing correctly', () => {
@@ -44,12 +43,10 @@ describe('<Radio />', () => {
44
43
  onChange: jest.fn(),
45
44
  }
46
45
 
47
- const { getByTestId } = setup(props)
48
-
49
- const component = getByTestId('radio')
46
+ setup(props)
50
47
 
51
- expect(component).toHaveTextContent(props.children)
52
- expect(getByTestId('selection-trailing')).toBeInTheDocument()
48
+ expect(screen.getByTestId('radio')).toHaveTextContent(props.children)
49
+ expect(screen.getByTestId('selection-trailing')).toBeInTheDocument()
53
50
  })
54
51
 
55
52
  it('triggers onChange when clicked', () => {
@@ -58,12 +55,12 @@ describe('<Radio />', () => {
58
55
  onChange: jest.fn(),
59
56
  }
60
57
 
61
- const { getByTestId } = setup(props)
58
+ setup(props)
59
+
60
+ expect(screen.getByTestId('selector')).not.toBeChecked()
62
61
 
63
- const selector = getByTestId('selector') as HTMLInputElement
62
+ fire.click(screen.getByTestId('selector'))
64
63
 
65
- expect(selector.checked).toBe(false)
66
- fire.click(selector)
67
- expect(selector.checked).toBe(true)
64
+ expect(screen.getByTestId('selector')).toBeChecked()
68
65
  })
69
66
  })
@@ -298,6 +298,25 @@ describe('Select', () => {
298
298
  expect(await selectEvent.getSelectedOptions(searchInput)).toHaveLength(0)
299
299
  expect(searchInput).toHaveDisplayValue('')
300
300
  })
301
+
302
+ it('removes the clear button', async () => {
303
+ const selectedFruit = generator.pickone([...FRUITS])
304
+
305
+ setup({
306
+ value: selectedFruit as Option,
307
+ hideClear: true,
308
+ })
309
+
310
+ const searchInput = screen.getByLabelText('Select your favorite fruit')
311
+ expect(searchInput).toHaveDisplayValue(selectedFruit.label)
312
+
313
+ const selectedOptions = await selectEvent.getSelectedOptions(searchInput)
314
+ expect(selectedOptions).toHaveLength(1)
315
+
316
+ expect(selectedOptions[0]).toHaveTextContent(selectedFruit.label)
317
+
318
+ expect(screen.queryByTestId('select-trigger-clear')).not.toBeInTheDocument()
319
+ })
301
320
  })
302
321
 
303
322
  describe('Multi selection', () => {
@@ -621,8 +640,8 @@ describe('Select', () => {
621
640
 
622
641
  await waitFor(() => {
623
642
  expect(screen.getByLabelText(availableOption)).toBeInTheDocument()
624
- expect(screen.getByText(`Add "${query}"`)).toBeInTheDocument()
625
643
  })
644
+ expect(screen.getByText(`Add "${query}"`)).toBeInTheDocument()
626
645
  }
627
646
  )
628
647
 
@@ -794,8 +813,8 @@ describe('Select', () => {
794
813
 
795
814
  await waitFor(() => {
796
815
  expect(dsFetch).toBeCalledTimes(2)
797
- expect(dsFetch).lastCalledWith({ query: 'foo', regex: expect.anything() })
798
816
  })
817
+ expect(dsFetch).lastCalledWith({ query: 'foo', regex: expect.anything() })
799
818
  }
800
819
  )
801
820
 
@@ -921,10 +940,10 @@ describe('Select', () => {
921
940
  await waitFor(
922
941
  () => {
923
942
  expect(dsFetch).toBeCalledTimes(2)
924
- expect(dsFetch).lastCalledWith({ query: 'foo', regex: expect.anything() })
925
943
  },
926
944
  { timeout: 5000 }
927
945
  )
946
+ expect(dsFetch).lastCalledWith({ query: 'foo', regex: expect.anything() })
928
947
  })
929
948
 
930
949
  it.each([[{ multiple: false }], [{ multiple: true }]])(
@@ -207,7 +207,7 @@ function renderOptionsMultiple(select: useSelectReturn, components?: Components)
207
207
  }
208
208
 
209
209
  function Select(props: SelectProps): JSX.Element {
210
- const { multiple, placeholder, components, ...others } = props
210
+ const { multiple, placeholder, components, hideClear = false, ...others } = props
211
211
 
212
212
  const select = useSelect(props)
213
213
 
@@ -224,24 +224,26 @@ function Select(props: SelectProps): JSX.Element {
224
224
  return <Loading data-testid="select-trigger-loading">&middot;&middot;&middot;</Loading>
225
225
  }
226
226
 
227
- if (select.value) {
228
- if (multiple) {
229
- return <ClearMultiple select={select} />
230
- }
231
-
232
- if (!select.disabled) {
233
- return (
234
- <CloseButton
235
- size={12}
236
- {...getCommonClearButtonProps()}
237
- {...select.getClearProps()}
238
- type="button"
239
- />
240
- )
241
- }
227
+ if (!select.value) {
228
+ return null
242
229
  }
243
230
 
244
- return null
231
+ if (multiple) {
232
+ return <ClearMultiple select={select} />
233
+ }
234
+
235
+ if (select.disabled || hideClear) {
236
+ return null
237
+ }
238
+
239
+ return (
240
+ <CloseButton
241
+ size={12}
242
+ {...getCommonClearButtonProps()}
243
+ {...select.getClearProps()}
244
+ type="button"
245
+ />
246
+ )
245
247
  }
246
248
 
247
249
  return (
@@ -69,6 +69,12 @@ export type Components = {
69
69
 
70
70
  export type CreateOptionPosition = 'first' | 'last'
71
71
 
72
+ export type OnChange = (event: EventLike<Option | Option[] | null>) => void
73
+
74
+ export type OnCreate = (query: string) => Promise<void | Option> | void | Option
75
+
76
+ export type OnQueryChange = (e: ChangeEvent<HTMLInputElement>) => void
77
+
72
78
  export interface SelectProps extends DropdownProps {
73
79
  name: string
74
80
  placeholder?: string
@@ -78,11 +84,15 @@ export interface SelectProps extends DropdownProps {
78
84
  datasources?: SelectDatasourceFunction<any>[]
79
85
  options?: GenericOption[]
80
86
  components?: Components
81
- onChange?: (event: EventLike<Option | Option[] | null>) => void
82
- onCreate?: (query: string) => Promise<void | Option> | void | Option
83
- onQueryChange?: (e: ChangeEvent<HTMLInputElement>) => void
87
+ onChange?: OnChange
88
+ onCreate?: OnCreate
89
+ onQueryChange?: OnQueryChange
84
90
  isValidNewOption?: ((query: string) => boolean) | boolean
85
91
  createOptionPosition?: CreateOptionPosition
92
+ /**
93
+ * Hide the clear button on the Single Select.
94
+ */
95
+ hideClear?: boolean
86
96
  }
87
97
 
88
98
  export type SelectOptionProps = {
@@ -4,5 +4,9 @@ export type {
4
4
  useSelectExternalReturn as useSelectReturn,
5
5
  SelectComponentsOptionProps as SelectOptionProps,
6
6
  SelectComponentsEmptyProps as SelectEmptyProps,
7
+ Option as SelectOption,
8
+ OnChange as SelectOnChange,
9
+ OnCreate as SelectOnCreate,
10
+ OnQueryChange as SelectOnQueryChange,
7
11
  } from './Select.types'
8
12
  export { useSelectExternal as useSelect } from './useSelectExternal'
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
-
2
+ import { screen } from '@testing-library/react'
3
3
  import Tag from './Tag'
4
4
  import generator from '../../tests/generator'
5
5
  import renderer from '../../tests/renderer'
@@ -12,7 +12,8 @@ describe('<Tag />', () => {
12
12
  children: generator.word(),
13
13
  }
14
14
 
15
- const { getByText } = setup(props)
16
- getByText(props.children)
15
+ setup(props)
16
+
17
+ screen.getByText(props.children)
17
18
  })
18
19
  })
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import { screen } from '@testing-library/react'
2
3
  import TextField from './TextField'
3
4
  import renderer from '../../tests/renderer'
4
5
 
@@ -6,30 +7,30 @@ const setup = ({ ...overrides } = {}) => renderer(<TextField {...overrides} />).
6
7
 
7
8
  describe('<TextField />', () => {
8
9
  it('renders correctly', () => {
9
- const { getByTestId } = setup({})
10
+ setup({})
10
11
 
11
- getByTestId('input')
12
+ screen.getByTestId('input')
12
13
  })
13
14
 
14
15
  it('renders type="text" by default', () => {
15
- const { getByTestId } = setup({})
16
+ setup({})
16
17
 
17
- expect(getByTestId('input')).toHaveAttribute('type', 'text')
18
+ expect(screen.getByTestId('input')).toHaveAttribute('type', 'text')
18
19
  })
19
20
 
20
21
  it('renders type="password" correctly', () => {
21
- const { getByTestId } = setup({
22
+ setup({
22
23
  type: 'password',
23
24
  })
24
25
 
25
- expect(getByTestId('input')).toHaveAttribute('type', 'password')
26
+ expect(screen.getByTestId('input')).toHaveAttribute('type', 'password')
26
27
  })
27
28
 
28
29
  it('renders type="number" correctly', () => {
29
- const { getByTestId } = setup({
30
+ setup({
30
31
  type: 'number',
31
32
  })
32
33
 
33
- expect(getByTestId('input')).toHaveAttribute('type', 'number')
34
+ expect(screen.getByTestId('input')).toHaveAttribute('type', 'number')
34
35
  })
35
36
  })
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import { screen } from '@testing-library/react'
2
3
  import Textarea from './Textarea'
3
4
  import renderer from '../../tests/renderer'
4
5
 
@@ -6,8 +7,8 @@ const setup = ({ ...overrides } = {}) => renderer(<Textarea {...overrides} />).r
6
7
 
7
8
  describe('<Textarea />', () => {
8
9
  it('renders correctly', () => {
9
- const { getByTestId } = setup({})
10
+ setup({})
10
11
 
11
- getByTestId('textarea')
12
+ screen.getByTestId('textarea')
12
13
  })
13
14
  })
@@ -1,7 +1,6 @@
1
- import { act, waitFor } from '@testing-library/react'
2
1
  import React, { useRef, useState } from 'react'
3
2
 
4
- import renderer, { screen, fire, user } from '../../tests/renderer'
3
+ import renderer, { screen, user } from '../../tests/renderer'
5
4
 
6
5
  import useHeightExpansionToggler from './useHeightExpansionToggler'
7
6
 
@@ -47,9 +46,8 @@ describe('useHeightExpansionToggler', () => {
47
46
  expect(screen.getByTestId('container')).toHaveStyle('height: auto;')
48
47
 
49
48
  /* Add +1 Node */
50
- act(() => {
51
- user.click(screen.getByRole('button', { name: 'add item' }))
52
- })
49
+
50
+ user.click(screen.getByRole('button', { name: 'add item' }))
53
51
 
54
52
  /* Nothing should change */
55
53
  expect(screen.getByTestId('expanded')).toHaveTextContent('false')
@@ -58,34 +56,28 @@ describe('useHeightExpansionToggler', () => {
58
56
  expect(screen.getByTestId('container')).toHaveStyle('height: 0px;')
59
57
 
60
58
  /* Expand it */
61
- await act(async () => {
62
- fire.click(screen.getByRole('button', { name: 'toggle' }))
59
+ user.click(screen.getByRole('button', { name: 'toggle' }))
63
60
 
64
- /* It should get expanded */
65
- await waitFor(() => screen.findByText('expanded: true'))
66
- })
61
+ /* It should get expanded */
62
+ await screen.findByText('expanded: true')
67
63
 
68
64
  /* Height should be of 1 Node */
69
65
  expect(screen.getByTestId('container')).toHaveStyle(`height: ${getFakeHeight(1)}px;`)
70
66
 
71
67
  /* We add +1 Node */
72
- await act(async () => {
73
- user.click(screen.getByRole('button', { name: 'add item' }))
68
+ user.click(screen.getByRole('button', { name: 'add item' }))
74
69
 
75
- /* A child must appear in the DOM */
76
- await waitFor(() => screen.findByText('1'))
77
- })
70
+ /* A child must appear in the DOM */
71
+ expect(await screen.findAllByText('1')).toHaveLength(2)
78
72
 
79
73
  /* Height should be of 2 Nodes */
80
74
  expect(screen.getByTestId('container')).toHaveStyle(`height: ${getFakeHeight(2)}px;`)
81
75
 
82
76
  /* Collapse it */
83
- await act(async () => {
84
- fire.click(screen.getByRole('button', { name: 'toggle' }))
77
+ user.click(screen.getByRole('button', { name: 'toggle' }))
85
78
 
86
- /* It should get collapsed */
87
- await waitFor(() => screen.findByText('expanded: false'))
88
- })
79
+ /* It should get collapsed */
80
+ await screen.findByText('expanded: false')
89
81
 
90
82
  /* Height should be zero */
91
83
  expect(screen.getByTestId('container')).toHaveStyle('height: 0px;')