@@ -4,20 +4,21 @@ import { Provider } from "react-redux";
44import { BrowserRouter as Router } from "react-router-dom" ;
55import MockFactory from "../../../../common/mockFactory" ;
66import createReduxStore from "../../../../redux/store/store" ;
7- import ProjectSettingsPage , { IProjectSettingsPageProps } from "./projectSettingsPage" ;
7+ import ProjectSettingsPage , { IProjectSettingsPageProps , IProjectSettingsPageState } from "./projectSettingsPage" ;
88
99jest . mock ( "../../../../services/projectService" ) ;
1010import ProjectService from "../../../../services/projectService" ;
11- import { IAppSettings } from "../../../../models/applicationState" ;
11+ import { IAppSettings , IProject } from "../../../../models/applicationState" ;
1212import ProjectMetrics from "./projectMetrics" ;
13+ import ProjectForm , { IProjectFormProps } from "./projectForm" ;
1314
1415jest . mock ( "./projectMetrics" , ( ) => ( ) => {
15- return (
16- < div className = "project-settings-page-metrics" >
17- Dummy Project Metrics
18- </ div >
19- ) ;
20- } ,
16+ return (
17+ < div className = "project-settings-page-metrics" >
18+ Dummy Project Metrics
19+ </ div >
20+ ) ;
21+ } ,
2122) ;
2223
2324describe ( "Project settings page" , ( ) => {
@@ -33,12 +34,29 @@ describe("Project settings page", () => {
3334 ) ;
3435 }
3536
37+ const localStorageMock = {
38+ getItem : jest . fn ( ) ,
39+ setItem : jest . fn ( ) ,
40+ removeItem : jest . fn ( ) ,
41+ } ;
42+
43+ beforeAll ( ( ) => {
44+ Object . defineProperty ( global , "_localStorage" , {
45+ value : localStorageMock ,
46+ writable : false ,
47+ } ) ;
48+ } ) ;
49+
3650 beforeEach ( ( ) => {
51+ localStorageMock . getItem . mockClear ( ) ;
52+ localStorageMock . setItem . mockClear ( ) ;
53+ localStorageMock . removeItem . mockClear ( ) ;
54+
3755 projectServiceMock = ProjectService as jest . Mocked < typeof ProjectService > ;
38- projectServiceMock . prototype . load = jest . fn ( ( project ) => ( { ...project } ) ) ;
56+ projectServiceMock . prototype . load = jest . fn ( ( project ) => ( { ...project } ) ) ;
3957 } ) ;
4058
41- it ( "Form submission calls save project action" , ( done ) => {
59+ it ( "Form submission calls save project action" , async ( ) => {
4260 const store = createReduxStore ( MockFactory . initialState ( ) ) ;
4361 const props = MockFactory . projectSettingsProps ( ) ;
4462 const saveProjectSpy = jest . spyOn ( props . projectActions , "saveProject" ) ;
@@ -47,14 +65,12 @@ describe("Project settings page", () => {
4765
4866 const wrapper = createComponent ( store , props ) ;
4967 wrapper . find ( "form" ) . simulate ( "submit" ) ;
68+ await MockFactory . flushUi ( ) ;
5069
51- setImmediate ( ( ) => {
52- expect ( saveProjectSpy ) . toBeCalled ( ) ;
53- done ( ) ;
54- } ) ;
70+ expect ( saveProjectSpy ) . toBeCalled ( ) ;
5571 } ) ;
5672
57- it ( "Throws an error when a user tries to create a duplicate project" , async ( done ) => {
73+ it ( "Throws an error when a user tries to create a duplicate project" , async ( ) => {
5874 const project = MockFactory . createTestProject ( "1" ) ;
5975 project . id = "25" ;
6076 const initialStateOverride = {
@@ -78,18 +94,16 @@ describe("Project settings page", () => {
7894 } ,
7995 } ) ;
8096 wrapper . find ( "form" ) . simulate ( "submit" ) ;
81- setImmediate ( async ( ) => {
82- // expect(saveProjectSpy).toBeCalled();
83- expect ( saveProjectSpy . mockRejectedValue ) . not . toBeNull ( ) ;
84- done ( ) ;
85- } ) ;
97+ await MockFactory . flushUi ( ) ;
98+
99+ expect ( saveProjectSpy . mockRejectedValue ) . not . toBeNull ( ) ;
86100 } ) ;
87101
88- it ( "calls save project when user creates a unique project" , ( done ) => {
102+ it ( "calls save project when user creates a unique project" , async ( ) => {
89103 const initialState = MockFactory . initialState ( ) ;
90104
91105 // New Project should not have id or security token set by default
92- const project = { ...initialState . recentProjects [ 0 ] } ;
106+ const project = { ...initialState . recentProjects [ 0 ] } ;
93107 project . id = null ;
94108 project . name = "Brand New Project" ;
95109 project . securityToken = "" ;
@@ -106,20 +120,20 @@ describe("Project settings page", () => {
106120 const wrapper = createComponent ( store , props ) ;
107121 wrapper . find ( "form" ) . simulate ( "submit" ) ;
108122
109- setImmediate ( ( ) => {
110- // New security token was created for new project
111- expect ( saveAppSettingsSpy ) . toBeCalled ( ) ;
112- const appSettings = saveAppSettingsSpy . mock . calls [ 0 ] [ 0 ] as IAppSettings ;
113- expect ( appSettings . securityTokens . length ) . toEqual ( initialState . appSettings . securityTokens . length + 1 ) ;
123+ await MockFactory . flushUi ( ) ;
114124
115- // New project was saved with new security token
116- expect ( saveProjectSpy ) . toBeCalledWith ( {
117- ...project ,
118- securityToken : `${ project . name } Token` ,
119- } ) ;
125+ // New security token was created for new project
126+ expect ( saveAppSettingsSpy ) . toBeCalled ( ) ;
127+ const appSettings = saveAppSettingsSpy . mock . calls [ 0 ] [ 0 ] as IAppSettings ;
128+ expect ( appSettings . securityTokens . length ) . toEqual ( initialState . appSettings . securityTokens . length + 1 ) ;
120129
121- done ( ) ;
130+ // New project was saved with new security token
131+ expect ( saveProjectSpy ) . toBeCalledWith ( {
132+ ...project ,
133+ securityToken : `${ project . name } Token` ,
122134 } ) ;
135+
136+ expect ( localStorage . removeItem ) . toBeCalledWith ( "projectForm" ) ;
123137 } ) ;
124138
125139 it ( "render ProjectMetrics" , ( ) => {
@@ -146,4 +160,64 @@ describe("Project settings page", () => {
146160 expect ( projectMetrics ) . toHaveLength ( 0 ) ;
147161 } ) ;
148162 } ) ;
163+
164+ describe ( "Persisting project form" , ( ) => {
165+ let wrapper : ReactWrapper = null ;
166+
167+ function initPersistProjectFormTest ( ) {
168+ const store = createReduxStore ( MockFactory . initialState ( ) ) ;
169+ const props = MockFactory . projectSettingsProps ( ) ;
170+ props . match . url = "/projects/create" ;
171+ wrapper = createComponent ( store , props ) ;
172+ }
173+
174+ it ( "Loads partial project from local storage" , ( ) => {
175+ const partialProject : IProject = {
176+ ...{ } as any ,
177+ name : "partial project" ,
178+ description : "partial project description" ,
179+ tags : [
180+ { name : "tag-1" , color : "#ff0000" } ,
181+ { name : "tag-3" , color : "#ffff00" } ,
182+ ] ,
183+ } ;
184+
185+ localStorageMock . getItem . mockImplementationOnce ( ( ) => JSON . stringify ( partialProject ) ) ;
186+
187+ initPersistProjectFormTest ( ) ;
188+ const projectSettingsPage = wrapper
189+ . find ( ProjectSettingsPage )
190+ . childAt ( 0 ) as ReactWrapper < IProjectSettingsPageProps , IProjectSettingsPageState > ;
191+
192+ expect ( localStorage . getItem ) . toBeCalledWith ( "projectForm" ) ;
193+ expect ( projectSettingsPage . state ( ) . project ) . toEqual ( partialProject ) ;
194+ } ) ;
195+
196+ it ( "Stores partial project in local storage" , ( ) => {
197+ initPersistProjectFormTest ( ) ;
198+ const partialProject : IProject = {
199+ ...{ } as any ,
200+ name : "partial project" ,
201+ } ;
202+
203+ const projectForm = wrapper . find ( ProjectForm ) as ReactWrapper < IProjectFormProps > ;
204+ projectForm . props ( ) . onChange ( partialProject ) ;
205+
206+ expect ( localStorage . setItem ) . toBeCalledWith ( "projectForm" , JSON . stringify ( partialProject ) ) ;
207+ } ) ;
208+
209+ it ( "Does NOT store empty project in local storage" , ( ) => {
210+ initPersistProjectFormTest ( ) ;
211+ const emptyProject : IProject = {
212+ ...{ } as any ,
213+ sourceConnection : { } ,
214+ targetConnection : { } ,
215+ exportFormat : { } ,
216+ } ;
217+ const projectForm = wrapper . find ( ProjectForm ) as ReactWrapper < IProjectFormProps > ;
218+ projectForm . props ( ) . onChange ( emptyProject ) ;
219+
220+ expect ( localStorage . setItem ) . not . toBeCalled ( ) ;
221+ } ) ;
222+ } ) ;
149223} ) ;
0 commit comments