1
+ import { useState } from "react" ;
2
+
1
3
import { render , screen , fireEvent } from "@tests-unit-browser" ;
2
4
import "@testing-library/jest-dom" ;
3
5
4
6
import OptionConcepts from "@app-ui/navigation/partials/OptionConcepts" ;
5
7
8
+ function Wrapper ( ) {
9
+ const [ checkedValues , setCheckedValues ] = useState < Record < string , string [ ] > > ( {
10
+ concept : [ ] ,
11
+ } ) ;
12
+ const [ isFetching , setIsFetching ] = useState ( false ) ;
13
+
14
+ return (
15
+ < OptionConcepts
16
+ concepts = { [ "concept1" , "concept2" , "concept3" ] }
17
+ onSearch = { ( ) => {
18
+ setIsFetching ( true ) ;
19
+ setTimeout ( ( ) => {
20
+ setIsFetching ( false ) ;
21
+ } , 3000 ) ;
22
+ } }
23
+ isReqestingConcepts = { isFetching }
24
+ disableButton = { checkedValues . concept . length === 0 || isFetching }
25
+ checkedValuesState = { checkedValues }
26
+ setCheckedValuesState = { setCheckedValues }
27
+ />
28
+ ) ;
29
+ }
30
+
6
31
describe ( "OptionConcepts" , ( ) => {
7
32
it ( "should render with given concepts" , ( ) => {
8
- const onSearch = jest . fn ( ( value : string ) => value ) ;
9
-
10
- render (
11
- < OptionConcepts
12
- concepts = { [ "concept1" , "concept2" , "concept3" ] }
13
- onSearch = { onSearch }
14
- /> ,
15
- ) ;
33
+ render ( < Wrapper /> ) ;
16
34
17
35
const menuList = screen . getByRole ( "menu" ) ;
18
36
expect ( menuList ) . toBeInTheDocument ( ) ;
@@ -26,40 +44,45 @@ describe("OptionConcepts", () => {
26
44
} ) ;
27
45
28
46
it ( "should be able to select different concepts" , ( ) => {
29
- const onSearch = jest . fn ( ( value : string ) => value ) ;
30
-
31
- render (
32
- < OptionConcepts
33
- concepts = { [ "concept1" , "concept2" , "concept3" ] }
34
- onSearch = { onSearch }
35
- /> ,
36
- ) ;
47
+ render ( < Wrapper /> ) ;
37
48
38
49
const concept1 = screen . getByText ( "concept1" ) ;
39
- expect ( concept1 ) . toBeInTheDocument ( ) ;
40
50
const concept2 = screen . getByText ( "concept2" ) ;
41
- expect ( concept2 ) . toBeInTheDocument ( ) ;
42
51
const concept3 = screen . getByText ( "concept3" ) ;
43
- expect ( concept3 ) . toBeInTheDocument ( ) ;
44
52
45
53
const searchButton = screen . getByRole ( "button" , { name : "Search" } ) ;
46
54
expect ( searchButton ) . toBeInTheDocument ( ) ;
47
55
expect ( searchButton ) . toBeDisabled ( ) ;
48
56
49
57
fireEvent . click ( concept1 ) ;
58
+ // has aria-checked attribute, when checked
59
+ expect ( concept1 . parentElement ) . toHaveAttribute ( "aria-checked" , "true" ) ;
50
60
expect ( searchButton ) . toBeEnabled ( ) ;
51
61
52
- fireEvent . click ( searchButton ) ;
53
- expect ( onSearch ) . toHaveBeenCalledWith ( "concept1" ) ;
54
-
55
62
fireEvent . click ( concept2 ) ;
56
- fireEvent . click ( searchButton ) ;
57
- expect ( onSearch ) . toHaveBeenCalledWith ( "concept2" ) ;
63
+ expect ( concept2 . parentElement ) . toHaveAttribute ( "aria-checked" , "true" ) ;
64
+ // concept1 should be unchecked -> exclusitivity
65
+ expect ( concept1 . parentElement ) . toHaveAttribute ( "aria-checked" , "false" ) ;
58
66
59
67
fireEvent . click ( concept3 ) ;
68
+ expect ( concept3 . parentElement ) . toHaveAttribute ( "aria-checked" , "true" ) ;
69
+ expect ( concept2 . parentElement ) . toHaveAttribute ( "aria-checked" , "false" ) ;
70
+ } ) ;
71
+
72
+ it ( "should show loading state and disable search button" , ( ) => {
73
+ render ( < Wrapper /> ) ;
74
+
75
+ const concept1 = screen . getByText ( "concept1" ) ;
76
+ const searchButton = screen . getByRole ( "button" , { name : "Search" } ) ;
77
+
78
+ fireEvent . click ( concept1 ) ;
79
+ expect ( searchButton ) . toBeEnabled ( ) ;
80
+
60
81
fireEvent . click ( searchButton ) ;
61
- expect ( onSearch ) . toHaveBeenCalledWith ( "concept3" ) ;
82
+ expect ( searchButton ) . toBeDisabled ( ) ;
62
83
63
- expect ( onSearch ) . toHaveBeenCalledTimes ( 3 ) ;
84
+ // role progressbar is used for loading state
85
+ const loading = screen . getByRole ( "progressbar" ) ;
86
+ expect ( loading ) . toBeInTheDocument ( ) ;
64
87
} ) ;
65
88
} ) ;
0 commit comments