@@ -3,20 +3,57 @@ import { Project, ExecutionCycleStatus } from '../domain';
33import { mount } from 'enzyme' ;
44import { MemoryRouter , Route } from 'react-router-dom' ;
55import { ProjectList } from './ProjectList' ;
6- import { AppStateContext } from '../appStateContext' ;
76import { ProjectService } from "../services/ProjectService" ;
7+ import { AppStateProviderWithProps } from '../AppStateProvider/AppStateProvider' ;
8+ import { AppNotificationProviderWithProps } from '../AppNotificationProvider/AppNotificationProvider' ;
9+ import { AppNotificationContextProps } from '../app-notifications' ;
10+ import { render } from '@testing-library/react' ;
811
912describe ( '<ProjectList />' , ( ) => {
10- it ( 'should show the loader when projects are being fetched' , ( ) => {
11- jest . spyOn ( ProjectService . prototype , "list" ) . mockResolvedValue ( [ ] ) ;
12- const component = mount (
13- < AppStateContext . Provider value = { { appState : { activeProject : undefined , runningProjects : [ ] } , dispatch : jest . fn ( ) } } >
14- < MemoryRouter >
15- < ProjectList />
16- </ MemoryRouter >
17- </ AppStateContext . Provider >
13+
14+ function ComponentWrapper ( {
15+ notifiers,
16+ loadRetryInterval,
17+ maxLoadRetries,
18+ dispatch,
19+ children,
20+ initialEntries
21+ } : React . PropsWithChildren < {
22+ notifiers ?: { [ K in keyof AppNotificationContextProps ] ?: AppNotificationContextProps [ K ] } ;
23+ loadRetryInterval ?: number ;
24+ maxLoadRetries ?: number ;
25+ dispatch ?: React . Dispatch < any > ;
26+ initialEntries ?: Array < any > ;
27+ } > ) {
28+ const { notifyError, notifyInfo, notifySuccess, notifyWarning} = notifiers || { } ;
29+
30+ return (
31+ < AppStateProviderWithProps
32+ appState = { { activeProject : undefined , runningProjects : [ ] } }
33+ dispatch = { dispatch || jest . fn ( ) }
34+ >
35+ < AppNotificationProviderWithProps
36+ notifyError = { notifyError || jest . fn ( ) }
37+ notifyInfo = { notifyInfo || jest . fn ( ) }
38+ notifySuccess = { notifySuccess || jest . fn ( ) }
39+ notifyWarning = { notifyWarning || jest . fn ( ) }
40+ >
41+ < MemoryRouter { ...{ initialEntries} } >
42+ < ProjectList { ...{ loadRetryInterval, maxLoadRetries} } />
43+ { children }
44+ </ MemoryRouter >
45+ </ AppNotificationProviderWithProps >
46+ </ AppStateProviderWithProps >
1847 ) ;
48+ }
1949
50+ beforeEach ( ( ) => {
51+ jest . resetAllMocks ( ) ;
52+ } ) ;
53+
54+ it ( 'should show the loader when projects are being fetched' , ( ) => {
55+ jest . spyOn ( ProjectService . prototype , "list" ) . mockResolvedValue ( [ ] ) ;
56+ const component = mount ( < ComponentWrapper /> ) ;
2057 expect ( component ! ) . toContainExactlyOneMatchingElement ( 'Loader' ) ;
2158 } ) ;
2259
@@ -60,18 +97,11 @@ describe('<ProjectList />', () => {
6097
6198 const apiSpy = jest . spyOn ( ProjectService . prototype , 'list' ) . mockReturnValueOnce ( dataPromise ) ;
6299
63- const component = mount (
64- < AppStateContext . Provider value = { { appState : { activeProject : undefined , runningProjects : [ ] } , dispatch : jest . fn ( ) } } >
65- < MemoryRouter >
66- < ProjectList />
67- </ MemoryRouter >
68- </ AppStateContext . Provider >
69- ) ;
70-
71- expect ( apiSpy ) . toBeCalled ( ) ;
100+ const component = mount ( < ComponentWrapper /> ) ;
72101 await dataPromise ;
73102 component . update ( ) ;
74- console . debug ( component . html ( ) ) ;
103+
104+ expect ( apiSpy ) . toBeCalled ( ) ;
75105 expect ( component . find ( 'div.running' ) ) . toContainMatchingElements ( 1 , '.is-warning' ) ;
76106 expect ( component . find ( 'div.justCompleted' ) ) . toContainMatchingElements ( 1 , '.is-success' ) ;
77107 expect ( component . find ( 'div.justCompleted' ) ) . toContainMatchingElements ( 1 , '.is-warning' ) ;
@@ -86,16 +116,65 @@ describe('<ProjectList />', () => {
86116 ) ;
87117
88118 const component = mount (
89- < AppStateContext . Provider value = { { appState : { activeProject : undefined , runningProjects : [ ] } , dispatch : jest . fn ( ) } } >
90- < MemoryRouter initialEntries = { [ '/projects' ] } >
91- < ProjectList />
92- < Route exact path = "/wizard/projects/new" component = { NewProjectWizard } />
93- </ MemoryRouter >
94- </ AppStateContext . Provider >
119+ < ComponentWrapper
120+ initialEntries = { [ '/projects' ] }
121+ >
122+ < Route exact path = "/wizard/projects/new" component = { NewProjectWizard } />
123+ </ ComponentWrapper >
95124 ) ;
96125
97126 await emptyPromise ;
98127 component . update ( ) ;
99128 expect ( component ) . toContainExactlyOneMatchingElement ( "#NewProjectWizard" ) ;
100129 } ) ;
130+
131+ describe ( 'on project list API call error' , ( ) => {
132+
133+ it ( 'should retry the call' , async ( done ) => {
134+ const listSpy = jest . spyOn ( ProjectService . prototype , 'list' ) . mockRejectedValue ( 'Network error' ) ;
135+ render ( < ComponentWrapper loadRetryInterval = { 10 } /> ) ;
136+ setTimeout ( ( ) => {
137+ done ( ) ;
138+ expect ( listSpy . mock . calls . length ) . toBeGreaterThan ( 1 ) ;
139+ } , 50 ) ;
140+ } ) ;
141+
142+ it ( 'should notify on eventual failure' , ( done ) => {
143+ jest . spyOn ( ProjectService . prototype , 'list' ) . mockRejectedValue ( "Network error" ) ;
144+ const notifyError = jest . fn ( ) ;
145+ render ( < ComponentWrapper notifiers = { { notifyError} } loadRetryInterval = { 10 } /> ) ;
146+ setTimeout ( ( ) => {
147+ done ( ) ;
148+ expect ( notifyError ) . toHaveBeenCalledTimes ( 1 ) ;
149+ } , 50 ) ;
150+ } ) ;
151+
152+ it ( 'should be able to eventually succeed' , ( done ) => {
153+ const listSpy = jest
154+ . spyOn ( ProjectService . prototype , 'list' )
155+ . mockRejectedValueOnce ( "Network Error" )
156+ . mockRejectedValueOnce ( "Network Error" )
157+ . mockResolvedValueOnce ( [ ] ) ;
158+
159+ const notifyError = jest . fn ( ) ;
160+ const notifyWarning = jest . fn ( ) ;
161+ const dispatch = jest . fn ( ) ;
162+ render (
163+ < ComponentWrapper
164+ notifiers = { { notifyWarning, notifyError} }
165+ loadRetryInterval = { 10 }
166+ maxLoadRetries = { 3 }
167+ { ...{ dispatch} }
168+ />
169+ ) ;
170+
171+ setTimeout ( ( ) => {
172+ done ( ) ;
173+ expect ( listSpy ) . toHaveBeenCalledTimes ( 3 ) ;
174+ expect ( notifyWarning ) . toHaveBeenCalledTimes ( 2 ) ;
175+ expect ( dispatch ) . toHaveBeenCalled ( ) ;
176+ expect ( notifyError ) . not . toHaveBeenCalled ( ) ;
177+ } , 50 ) ;
178+ } ) ;
179+ } ) ;
101180} ) ;
0 commit comments