14
14
15
15
import { expect } from 'chai' ;
16
16
import sinon from 'sinon' ;
17
- import { Storage , Bucket } from '@google-cloud/storage' ;
17
+ import { Storage , Bucket , File } from '@google-cloud/storage' ;
18
18
import * as sdkApi from '@google-cloud/synthetics-sdk-api' ;
19
19
import {
20
20
createStorageClientIfStorageSelected ,
21
+ getFolderNameFromStorageLocation ,
21
22
getOrCreateStorageBucket ,
23
+ StorageParameters ,
24
+ uploadScreenshotToGCS ,
22
25
} from '../../src/storage_func' ;
26
+ import { BrokenLinksResultV1_BrokenLinkCheckerOptions } from '@google-cloud/synthetics-sdk-api' ;
23
27
const proxyquire = require ( 'proxyquire' ) ;
24
28
25
29
// global test vars
@@ -33,6 +37,7 @@ describe('GCM Synthetics Broken Links storage_func suite testing', () => {
33
37
'@google-cloud/synthetics-sdk-api' : {
34
38
getExecutionRegion : ( ) => 'test-region' ,
35
39
resolveProjectId : ( ) => 'test-project-id' ,
40
+ getOrCreateStorageBucket : ( ) => getOrCreateStorageBucket ,
36
41
} ,
37
42
} ) ;
38
43
@@ -94,10 +99,14 @@ describe('GCM Synthetics Broken Links storage_func suite testing', () => {
94
99
95
100
const result = await storageFunc . getOrCreateStorageBucket (
96
101
storageClientStub ,
97
- ' ',
102
+ TEST_BUCKET_NAME + '/fake-folder ',
98
103
[ ]
99
104
) ;
100
105
expect ( result ) . to . equal ( bucketStub ) ;
106
+ sinon . assert . calledWithExactly (
107
+ storageClientStub . bucket ,
108
+ TEST_BUCKET_NAME
109
+ ) ;
101
110
sinon . assert . notCalled ( bucketStub . create ) ;
102
111
} ) ;
103
112
@@ -148,4 +157,157 @@ describe('GCM Synthetics Broken Links storage_func suite testing', () => {
148
157
expect ( result ) . to . be . an . instanceOf ( Storage ) ;
149
158
} ) ;
150
159
} ) ;
160
+
161
+ describe ( 'uploadScreenshotToGCS' , ( ) => {
162
+ let storageClientStub : sinon . SinonStubbedInstance < Storage > ;
163
+ let bucketStub : sinon . SinonStubbedInstance < Bucket > ;
164
+
165
+ const screenshotData = 'encoded-image-data' ;
166
+ const filename = 'test-screenshot.png' ;
167
+
168
+ beforeEach ( ( ) => {
169
+ storageClientStub = sinon . createStubInstance ( Storage ) ;
170
+ bucketStub = sinon . createStubInstance ( Bucket ) ;
171
+ storageClientStub . bucket . returns ( bucketStub ) ;
172
+ } ) ;
173
+
174
+ afterEach ( ( ) => {
175
+ sinon . restore ( ) ;
176
+ } ) ;
177
+
178
+ it ( 'should upload the screenshot and return the write_destination' , async ( ) => {
179
+ const storageParams = {
180
+ storageClient : storageClientStub ,
181
+ bucket : bucketStub ,
182
+ uptimeId : 'uptime123' ,
183
+ executionId : 'exec456' ,
184
+ } ;
185
+ const options = {
186
+ screenshot_options : { storage_location : 'bucket/folder1/folder2' } ,
187
+ } as BrokenLinksResultV1_BrokenLinkCheckerOptions ;
188
+ const expectedWriteDestination =
189
+ 'folder1/folder2/uptime123/exec456/test-screenshot.png' ;
190
+
191
+ const successPartialFileMock : Partial < File > = {
192
+ save : sinon . stub ( ) . resolves ( ) ,
193
+ } ;
194
+ bucketStub . file . returns ( successPartialFileMock as File ) ;
195
+
196
+ const result = await uploadScreenshotToGCS (
197
+ screenshotData ,
198
+ filename ,
199
+ storageParams ,
200
+ options
201
+ ) ;
202
+
203
+ expect ( result . screenshot_file ) . to . equal ( expectedWriteDestination ) ;
204
+ expect ( result . screenshot_error ) . to . deep . equal ( { } ) ;
205
+ } ) ;
206
+
207
+ it ( 'should handle GCS upload errors' , async ( ) => {
208
+ const storageParams : StorageParameters = {
209
+ storageClient : storageClientStub ,
210
+ bucket : bucketStub ,
211
+ uptimeId : '' ,
212
+ executionId : '' ,
213
+ } ;
214
+ const options = {
215
+ screenshot_options : { } ,
216
+ } as BrokenLinksResultV1_BrokenLinkCheckerOptions ;
217
+
218
+ const gcsError = new Error ( 'Simulated GCS upload error' ) ;
219
+ const failingPartialFileMock : Partial < File > = {
220
+ save : sinon . stub ( ) . throws ( gcsError ) ,
221
+ } ;
222
+ bucketStub . file . returns ( failingPartialFileMock as File ) ;
223
+
224
+ const result = await uploadScreenshotToGCS (
225
+ screenshotData ,
226
+ filename ,
227
+ storageParams ,
228
+ options
229
+ ) ;
230
+
231
+ expect ( result . screenshot_file ) . to . equal ( '' ) ;
232
+ expect ( result . screenshot_error ) . to . deep . equal ( {
233
+ error_type : 'StorageFileUploadError' ,
234
+ error_message : `Failed to upload screenshot for ${ filename } . Please reference server logs for further information.` ,
235
+ } ) ;
236
+ } ) ;
237
+
238
+ describe ( 'Invalid Storage Configuration' , ( ) => {
239
+ const emptyScreenshotData = '' ;
240
+ const emptyFilename = '' ;
241
+ const emptyOptions = { } as BrokenLinksResultV1_BrokenLinkCheckerOptions ;
242
+ it ( 'should return an empty result if storageClient is null' , async ( ) => {
243
+ // Missing storageClient
244
+ const storageParams = {
245
+ storageClient : null ,
246
+ bucket : bucketStub ,
247
+ uptimeId : '' ,
248
+ executionId : '' ,
249
+ } ;
250
+
251
+ const result = await uploadScreenshotToGCS (
252
+ emptyScreenshotData ,
253
+ emptyFilename ,
254
+ storageParams ,
255
+ emptyOptions
256
+ ) ;
257
+
258
+ expect ( result ) . to . deep . equal ( {
259
+ screenshot_file : '' ,
260
+ screenshot_error : { } ,
261
+ } ) ;
262
+ } ) ;
263
+
264
+ it ( 'should return an empty result if bucket is null' , async ( ) => {
265
+ // Missing bucket
266
+ const storageParams = {
267
+ storageClient : storageClientStub ,
268
+ bucket : null ,
269
+ uptimeId : '' ,
270
+ executionId : '' ,
271
+ } ;
272
+
273
+ const result = await uploadScreenshotToGCS (
274
+ emptyScreenshotData ,
275
+ emptyFilename ,
276
+ storageParams ,
277
+ emptyOptions
278
+ ) ;
279
+
280
+ expect ( result ) . to . deep . equal ( {
281
+ screenshot_file : '' ,
282
+ screenshot_error : { } ,
283
+ } ) ;
284
+ } ) ;
285
+ } ) ;
286
+ } ) ;
287
+
288
+ describe ( 'getFolderNameFromStorageLocation' , ( ) => {
289
+ it ( 'should extract folder name when storage location has a slash' , ( ) => {
290
+ const storageLocation = 'some-bucket/folder1/folder2' ;
291
+ const expectedFolderName = 'folder1/folder2' ;
292
+
293
+ const result = getFolderNameFromStorageLocation ( storageLocation ) ;
294
+ expect ( result ) . to . equal ( expectedFolderName ) ;
295
+ } ) ;
296
+
297
+ it ( 'should return an empty string if storage location has no slash' , ( ) => {
298
+ const storageLocation = 'my-bucket' ;
299
+ const expectedFolderName = '' ;
300
+
301
+ const result = getFolderNameFromStorageLocation ( storageLocation ) ;
302
+ expect ( result ) . to . equal ( expectedFolderName ) ;
303
+ } ) ;
304
+
305
+ it ( 'should return an empty string if given an empty string' , ( ) => {
306
+ const storageLocation = '' ;
307
+ const expectedFolderName = '' ;
308
+
309
+ const result = getFolderNameFromStorageLocation ( storageLocation ) ;
310
+ expect ( result ) . to . equal ( expectedFolderName ) ;
311
+ } ) ;
312
+ } ) ;
151
313
} ) ;
0 commit comments