1
1
import userEvent from '@testing-library/user-event' ;
2
2
import axios from 'axios' ;
3
+ import type { FC } from 'react' ;
3
4
4
5
import { createAuthenticatedUser } from '@/common/models' ;
5
- import { render , screen } from '@/test' ;
6
+ import { render , screen , waitFor } from '@/test' ;
6
7
import { createGame } from '@/test/factories' ;
7
8
8
9
import { GameListItemDrawerBacklogToggleButton } from './GameListItemDrawerBacklogToggleButton' ;
10
+ import { useGameBacklogState } from './useGameBacklogState' ;
11
+
12
+ interface TestHarnessProps {
13
+ game : App . Platform . Data . Game ;
14
+ isInitiallyInBacklog : boolean ;
15
+
16
+ onToggle ?: ( ) => void ;
17
+ }
18
+
19
+ const TestHarness : FC < TestHarnessProps > = ( { game, isInitiallyInBacklog, onToggle } ) => {
20
+ const backlogState = useGameBacklogState ( { game, isInitiallyInBacklog } ) ;
21
+
22
+ return (
23
+ < GameListItemDrawerBacklogToggleButton
24
+ backlogState = { backlogState }
25
+ onToggle = { onToggle ?? vi . fn ( ) }
26
+ />
27
+ ) ;
28
+ } ;
9
29
10
30
describe ( 'Component: GameListItemDrawerBacklogToggleButton' , ( ) => {
11
31
let originalUrl : string ;
@@ -25,17 +45,15 @@ describe('Component: GameListItemDrawerBacklogToggleButton', () => {
25
45
26
46
it ( 'renders without crashing' , ( ) => {
27
47
// ARRANGE
28
- const { container } = render (
29
- < GameListItemDrawerBacklogToggleButton game = { createGame ( ) } isInBacklog = { false } /> ,
30
- ) ;
48
+ const { container } = render ( < TestHarness game = { createGame ( ) } isInitiallyInBacklog = { false } /> ) ;
31
49
32
50
// ASSERT
33
51
expect ( container ) . toBeTruthy ( ) ;
34
52
} ) ;
35
53
36
54
it ( "given the game is not in the user's backlog, renders an accessible button that allows them to add it" , ( ) => {
37
55
// ARRANGE
38
- render ( < GameListItemDrawerBacklogToggleButton game = { createGame ( ) } isInBacklog = { false } /> ) ;
56
+ render ( < TestHarness game = { createGame ( ) } isInitiallyInBacklog = { false } /> ) ;
39
57
40
58
// ASSERT
41
59
expect ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) . toBeVisible ( ) ;
@@ -44,113 +62,64 @@ describe('Component: GameListItemDrawerBacklogToggleButton', () => {
44
62
45
63
it ( "given the game is currently in the user's backlog, renders an accessible button that allows them to remove it" , ( ) => {
46
64
// ARRANGE
47
- render ( < GameListItemDrawerBacklogToggleButton game = { createGame ( ) } isInBacklog = { true } /> ) ;
65
+ render ( < TestHarness game = { createGame ( ) } isInitiallyInBacklog = { true } /> ) ;
48
66
49
67
// ASSERT
50
68
expect ( screen . getByRole ( 'button' , { name : / r e m o v e f r o m w a n t t o p l a y g a m e s / i } ) ) . toBeVisible ( ) ;
51
69
expect ( screen . queryByText ( / a d d t o / i) ) . not . toBeInTheDocument ( ) ;
52
70
} ) ;
53
71
54
- it ( ' given the user is not authenticated and presses the button, redirects them to login' , async ( ) => {
72
+ it ( " given the game is not currently in the user's backlog and the user presses the button, invokes the toggle event" , async ( ) => {
55
73
// ARRANGE
56
- render ( < GameListItemDrawerBacklogToggleButton game = { createGame ( ) } isInBacklog = { false } /> , {
57
- pageProps : { auth : null } ,
58
- } ) ;
59
-
60
- // ACT
61
- await userEvent . click ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) ;
62
-
63
- // ASSERT
64
- expect ( window . location . href ) . toEqual ( [ 'login' ] ) ;
65
- } ) ;
66
-
67
- it ( "given the game is not currently in the user's backlog and the user presses the button, makes the call to add the game to the user's backlog" , async ( ) => {
68
- // ARRANGE
69
- const postSpy = vi . spyOn ( axios , 'post' ) . mockResolvedValueOnce ( { success : true } ) ;
70
-
71
74
const game = createGame ( { id : 1 } ) ;
72
75
73
- render ( < GameListItemDrawerBacklogToggleButton game = { game } isInBacklog = { false } /> , {
76
+ const onToggle = vi . fn ( ) ;
77
+
78
+ render ( < TestHarness game = { game } isInitiallyInBacklog = { false } onToggle = { onToggle } /> , {
74
79
pageProps : { auth : { user : createAuthenticatedUser ( ) } } ,
75
80
} ) ;
76
81
77
82
// ACT
78
83
await userEvent . click ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) ;
79
84
80
85
// ASSERT
81
- expect ( postSpy ) . toHaveBeenCalledTimes ( 1 ) ;
82
- expect ( postSpy ) . toHaveBeenCalledWith ( [ 'api.user-game-list.store' , 1 ] , {
83
- userGameListType : 'play' ,
84
- } ) ;
86
+ expect ( onToggle ) . toHaveBeenCalledOnce ( ) ;
85
87
} ) ;
86
88
87
- it ( 'given the user presses the button, an optional event is emitted that a consumer can use' , async ( ) => {
89
+ // FIXME this test is throwing a exception vitest can't handle
90
+ it . skip ( 'given the back-end API call throws, reverts the optimistic state' , async ( ) => {
88
91
// ARRANGE
89
- vi . spyOn ( axios , 'post' ) . mockResolvedValueOnce ( { success : true } ) ;
92
+ vi . spyOn ( axios , 'post' ) . mockRejectedValueOnce ( { success : false } ) ;
90
93
91
94
const game = createGame ( { id : 1 } ) ;
92
95
93
- const onToggle = vi . fn ( ) ;
94
-
95
- render (
96
- < GameListItemDrawerBacklogToggleButton game = { game } isInBacklog = { false } onToggle = { onToggle } /> ,
97
- {
98
- pageProps : { auth : { user : createAuthenticatedUser ( ) } } ,
99
- } ,
100
- ) ;
96
+ render ( < TestHarness game = { game } isInitiallyInBacklog = { false } /> , {
97
+ pageProps : { auth : { user : createAuthenticatedUser ( ) } } ,
98
+ } ) ;
101
99
102
100
// ACT
103
101
await userEvent . click ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) ;
104
102
105
103
// ASSERT
106
- expect ( onToggle ) . toHaveBeenCalledTimes ( 1 ) ;
107
- expect ( onToggle ) . toHaveBeenCalledWith ( true ) ;
104
+ await waitFor ( ( ) => {
105
+ expect ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) . toBeVisible ( ) ;
106
+ } ) ;
108
107
} ) ;
109
108
110
- // FIXME this test is throwing a exception vitest can't handle
111
- it . skip ( 'given the back-end API call throws, emits another optional event with the current button toggle state' , async ( ) => {
109
+ it ( "given the game is currently in the user's backlog and the user presses the button, invokes the toggle event" , async ( ) => {
112
110
// ARRANGE
113
- vi . spyOn ( axios , 'post' )
114
- . mockRejectedValueOnce ( { success : false } )
115
- . mockResolvedValue ( { success : true } ) ;
116
-
117
111
const game = createGame ( { id : 1 } ) ;
118
112
119
113
const onToggle = vi . fn ( ) ;
120
114
121
- render (
122
- < GameListItemDrawerBacklogToggleButton game = { game } isInBacklog = { false } onToggle = { onToggle } /> ,
123
- {
124
- pageProps : { auth : { user : createAuthenticatedUser ( ) } } ,
125
- } ,
126
- ) ;
127
-
128
- // ACT
129
- await userEvent . click ( screen . getByRole ( 'button' , { name : / a d d t o w a n t t o p l a y g a m e s / i } ) ) ;
130
-
131
- // ASSERT
132
- expect ( onToggle ) . toHaveBeenCalledTimes ( 2 ) ;
133
- expect ( onToggle ) . toHaveBeenNthCalledWith ( 1 , true ) ;
134
- expect ( onToggle ) . toHaveBeenNthCalledWith ( 2 , false ) ;
135
- } ) ;
136
-
137
- it ( "given the game is currently in the user's backlog and the user presses the button, makes the call to remove the game from the user's backlog" , async ( ) => {
138
- // ARRANGE
139
- const deleteSpy = vi . spyOn ( axios , 'delete' ) . mockResolvedValueOnce ( { success : true } ) ;
140
-
141
- const game = createGame ( { id : 1 } ) ;
142
-
143
- render ( < GameListItemDrawerBacklogToggleButton game = { game } isInBacklog = { true } /> , {
115
+ render ( < TestHarness game = { game } isInitiallyInBacklog = { true } onToggle = { onToggle } /> , {
144
116
pageProps : { auth : { user : createAuthenticatedUser ( ) } } ,
145
117
} ) ;
146
118
147
119
// ACT
148
120
await userEvent . click ( screen . getByRole ( 'button' , { name : / r e m o v e f r o m w a n t t o p l a y g a m e s / i } ) ) ;
149
121
150
122
// ASSERT
151
- expect ( deleteSpy ) . toHaveBeenCalledTimes ( 1 ) ;
152
- expect ( deleteSpy ) . toHaveBeenCalledWith ( [ 'api.user-game-list.destroy' , 1 ] , {
153
- data : { userGameListType : 'play' } ,
154
- } ) ;
123
+ expect ( onToggle ) . toHaveBeenCalledOnce ( ) ;
155
124
} ) ;
156
125
} ) ;
0 commit comments