@@ -4,11 +4,11 @@ import request from 'supertest';
44
55import { mockTokenPayload } from '../../assets/jwt.ts' ;
66import { initWsApp } from '../core/express.ts' ;
7- import { s3Extension } from '../core/hocuspocus.ts' ;
87import * as jwt from '../../app/utils/jwt.ts' ;
98import { s3Extension , registerHocuspocus } from '../core/hocuspocus.ts' ;
109import { slateReportToDoc } from '../../app/utils/report.ts' ;
1110import { report } from '../../assets/report.ts' ;
11+ import { getS3Implementation } from '../../assets/s3.ts' ;
1212
1313describe ( 'REST doc' , ( ) => {
1414 const wsApp = initWsApp (
@@ -22,18 +22,22 @@ describe('REST doc', () => {
2222 ) ;
2323
2424 const verifyJwtSpy = vi . spyOn ( jwt , 'verifyJwt' ) ;
25+ const verifyServiceTokenSpy = vi . spyOn ( jwt , 'verifyServiceToken' ) ;
2526 const s3FetchSpy = vi . spyOn ( s3Extension . configuration , 'fetch' ) ;
27+ const s3StoreSpy = vi . spyOn ( s3Extension . configuration , 'store' ) ;
2628
2729 afterEach ( ( ) => {
2830 verifyJwtSpy . mockClear ( ) ;
29- s3FetchSpy . mockClear ( ) ;
31+ verifyServiceTokenSpy . mockClear ( ) ;
32+ s3FetchSpy . mockReset ( ) ;
33+ s3StoreSpy . mockReset ( ) ;
3034 } ) ;
3135
32- test ( 'GET /documents/ with incorrect document format' , async ( ) => {
36+ test ( 'GET /documents/{name} with incorrect document format' , async ( ) => {
3337 verifyJwtSpy . mockResolvedValueOnce ( mockTokenPayload ) ;
3438
3539 const res = await request ( wsApp )
36- . get ( '/documents/doc_v1_9999 ' )
40+ . get ( '/documents/doc_v1_7777 ' )
3741 . set ( 'Authorization' , 'Bearer my-valid-token' ) ;
3842
3943 expect ( verifyJwtSpy ) . toHaveBeenCalledOnce ( ) ;
@@ -44,22 +48,25 @@ describe('REST doc', () => {
4448 details : {
4549 name : {
4650 message : 'Document name should start with "document"' ,
47- value : 'doc_v1_9999 ' ,
51+ value : 'doc_v1_7777 ' ,
4852 } ,
4953 } ,
5054 } ) ;
5155 } ) ;
5256
53- test ( 'GET /documents/ with non existing document' , async ( ) => {
57+ test ( 'GET /documents/{name} with non existing document' , async ( ) => {
5458 verifyJwtSpy . mockResolvedValueOnce ( mockTokenPayload ) ;
55- s3FetchSpy . mockResolvedValueOnce ( null ) ;
59+ const { fetch, store } = getS3Implementation ( ) ;
60+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
61+ s3StoreSpy . mockImplementationOnce ( store ) ;
5662
5763 const res = await request ( wsApp )
58- . get ( '/documents/document_v1_8888 ' )
64+ . get ( '/documents/document_v1_11 ' )
5965 . set ( 'Authorization' , 'Bearer my-valid-token' ) ;
6066
6167 expect ( verifyJwtSpy ) . toHaveBeenCalledOnce ( ) ;
6268 expect ( s3FetchSpy ) . toHaveBeenCalledOnce ( ) ;
69+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 0 ) ;
6370
6471 expect ( res . status ) . toBe ( 404 ) ;
6572 expect ( res . body ) . toStrictEqual ( {
@@ -68,20 +75,26 @@ describe('REST doc', () => {
6875 } ) ;
6976 } ) ;
7077
71- test ( 'GET /doc/ with existing document' , async ( ) => {
78+ test ( 'GET /documents/{name} with existing document' , async ( ) => {
7279 verifyJwtSpy . mockResolvedValueOnce ( mockTokenPayload ) ;
7380
7481 const doc = new Y . Doc ( ) ;
7582 slateReportToDoc ( report , doc ) ;
7683 const binaryData = Y . encodeStateAsUpdate ( doc ) ;
77- s3FetchSpy . mockResolvedValueOnce ( binaryData ) ;
84+
85+ const { fetch, store } = getS3Implementation ( {
86+ document_v1_22 : binaryData ,
87+ } ) ;
88+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
89+ s3StoreSpy . mockImplementationOnce ( store ) ;
7890
7991 const res = await request ( wsApp )
80- . get ( '/documents/document_v1_9999 ' )
92+ . get ( '/documents/document_v1_22 ' )
8193 . set ( 'Authorization' , 'Bearer my-valid-token' ) ;
8294
8395 expect ( verifyJwtSpy ) . toHaveBeenCalledOnce ( ) ;
8496 expect ( s3FetchSpy ) . toHaveBeenCalledOnce ( ) ;
97+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 0 ) ;
8598
8699 expect ( res . status ) . toBe ( 200 ) ;
87100 expect ( res . body ) . toStrictEqual ( {
@@ -107,4 +120,108 @@ describe('REST doc', () => {
107120 } ,
108121 } ) ;
109122 } ) ;
123+
124+ test ( 'GET /documents/{name}/reset/ with invalid data' , async ( ) => {
125+ verifyServiceTokenSpy . mockResolvedValueOnce ( true ) ;
126+ const { fetch, store } = getS3Implementation ( ) ;
127+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
128+ s3StoreSpy . mockImplementationOnce ( store ) ;
129+
130+ const res = await request ( wsApp )
131+ . put ( '/documents/document_v1_33/reset' )
132+ . send ( { } )
133+ . set ( 'Authorization' , 'Bearer my-valid-service-token' ) ;
134+
135+ expect ( verifyServiceTokenSpy ) . toHaveBeenCalledOnce ( ) ;
136+ expect ( s3FetchSpy ) . toHaveBeenCalledTimes ( 0 ) ;
137+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 0 ) ;
138+
139+ expect ( res . status ) . toBe ( 422 ) ;
140+ expect ( res . body ) . toStrictEqual ( {
141+ details : {
142+ 'body.document' : {
143+ message : '\'document\' is required' ,
144+ } ,
145+ 'body.last_updated_at' : {
146+ message : '\'last_updated_at\' is required' ,
147+ } ,
148+ 'body.sections_completed' : {
149+ message : '\'sections_completed\' is required' ,
150+ } ,
151+ } ,
152+ message : 'Validation failed' ,
153+ } ) ;
154+ } ) ;
155+
156+ test ( 'GET /documents/{name}/reset/ with no data in s3' , async ( ) => {
157+ verifyServiceTokenSpy . mockResolvedValueOnce ( true ) ;
158+ const { fetch, store } = getS3Implementation ( ) ;
159+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
160+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
161+ s3StoreSpy . mockImplementation ( store ) ;
162+
163+ const res = await request ( wsApp )
164+ . put ( '/documents/document_v1_44/reset' )
165+ . send ( report )
166+ . set ( 'Authorization' , 'Bearer my-valid-service-token' ) ;
167+
168+ expect ( verifyServiceTokenSpy ) . toHaveBeenCalledOnce ( ) ;
169+ expect ( s3FetchSpy ) . toHaveBeenCalledTimes ( 2 ) ;
170+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 0 ) ;
171+
172+ expect ( res . status ) . toBe ( 200 ) ;
173+ expect ( res . body ) . toStrictEqual ( {
174+ docName : 'document_v1_44' ,
175+ } ) ;
176+ } ) ;
177+
178+ test ( 'GET /documents/{name}/reset/ with data in s3' , async ( ) => {
179+ verifyServiceTokenSpy . mockResolvedValueOnce ( true ) ;
180+
181+ const doc = new Y . Doc ( ) ;
182+ slateReportToDoc ( report , doc ) ;
183+ const binaryData = Y . encodeStateAsUpdate ( doc ) ;
184+ const { fetch, store } = getS3Implementation ( {
185+ document_v1_55 : binaryData ,
186+ } ) ;
187+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
188+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
189+ s3StoreSpy . mockImplementationOnce ( store ) ;
190+
191+ const updatedReport = {
192+ ...report ,
193+ sections_completed : {
194+ ...report . sections_completed ,
195+ department : 'complete' ,
196+ } ,
197+ } ;
198+
199+ const res = await request ( wsApp )
200+ . put ( '/documents/document_v1_55/reset' )
201+ . send ( updatedReport )
202+ . set ( 'Authorization' , 'Bearer my-valid-service-token' ) ;
203+
204+ expect ( verifyServiceTokenSpy ) . toHaveBeenCalledOnce ( ) ;
205+ expect ( s3FetchSpy ) . toHaveBeenCalledTimes ( 2 ) ;
206+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 1 ) ;
207+
208+ expect ( res . status ) . toBe ( 200 ) ;
209+ expect ( res . body ) . toStrictEqual ( {
210+ docName : 'document_v1_55' ,
211+ } ) ;
212+
213+ verifyJwtSpy . mockResolvedValueOnce ( mockTokenPayload ) ;
214+ s3FetchSpy . mockImplementationOnce ( fetch ) ;
215+ s3StoreSpy . mockImplementationOnce ( store ) ;
216+
217+ const res2 = await request ( wsApp )
218+ . get ( '/documents/document_v1_55' )
219+ . set ( 'Authorization' , 'Bearer my-valid-token' ) ;
220+
221+ // FIXME: confirm if direct connection does not load document into memory
222+ expect ( verifyJwtSpy ) . toHaveBeenCalledOnce ( ) ;
223+ expect ( s3FetchSpy ) . toHaveBeenCalledTimes ( 3 ) ;
224+ expect ( s3StoreSpy ) . toHaveBeenCalledTimes ( 1 ) ;
225+ expect ( res2 . status ) . toBe ( 200 ) ;
226+ } ) ;
110227} ) ;
0 commit comments