1
+ const chai = require ( "chai" )
2
+ const chaiAsPromised = require ( "chai-as-promised" )
3
+ const sinonChai = require ( "sinon-chai" )
4
+ const sinon = require ( "sinon" )
5
+
6
+ chai . use ( sinonChai )
7
+ chai . use ( chaiAsPromised )
8
+ chai . should ( )
9
+
10
+ const rewire = require ( 'rewire' )
11
+
12
+ const { Storage, Bucket, File} = require ( '@google-cloud/storage' )
13
+ const { Readable} = require ( 'stream' )
14
+ const sourceNodes = rewire ( '../src/gatsby-node' )
15
+
16
+ // Mock the Gatsby API
17
+ const apiMock = {
18
+ actions : {
19
+ createNode : sinon . spy ( )
20
+ } ,
21
+ reporter : {
22
+ panic : sinon . stub ( ) ,
23
+ warn : sinon . stub ( ) ,
24
+ info : sinon . stub ( )
25
+ } ,
26
+ createNodeId : sinon . stub ( ) ,
27
+ store : sinon . stub ( ) ,
28
+ cache : sinon . stub ( )
29
+ }
30
+
31
+ // Mock gatsby-source-filesystem helper function
32
+ const createFileNodeFromBufferStub = sinon . stub ( ) . resolves ( { id : '9876' } )
33
+
34
+ // Mock the @Google Storage API
35
+ class FileStub {
36
+ constructor ( ) { }
37
+
38
+ getMetadata ( ) { return Promise . resolve ( [
39
+ {
40
+ mediaLink : 'https://foo.com/files/bar.md' ,
41
+ name : 'files/bar.md' ,
42
+ bucket : 'fooBucket' ,
43
+ md5hash : 'ABC123'
44
+ }
45
+ ] ) }
46
+ createReadStream ( ) { return Promise . resolve ( new Readable ( ) ) }
47
+ }
48
+
49
+ class BucketStub {
50
+ constructor ( ) { }
51
+
52
+ getFiles ( options ) {
53
+ if ( options . directory !== '/' )
54
+ return Promise . resolve ( [ [ new FileStub ( ) ] , [ ] ] )
55
+ else
56
+ return Promise . resolve ( [ [ ] , [ ] ] )
57
+ }
58
+ }
59
+
60
+ class StorageStub {
61
+ constructor ( ) { }
62
+
63
+ bucket ( ) { return new BucketStub ( ) }
64
+ }
65
+
66
+ // Arrange stubs
67
+ sourceNodes . __set__ ( "createFileNodeFromBuffer" , createFileNodeFromBufferStub )
68
+ sourceNodes . __set__ ( "Storage" , StorageStub )
69
+
70
+ describe ( 'gatsby-source-gcp-storage' , ( ) => {
71
+
72
+ beforeEach ( ( ) => {
73
+ apiMock . reporter . panic . resetHistory ( )
74
+ apiMock . reporter . warn . resetHistory ( )
75
+ apiMock . actions . createNode . resetHistory ( )
76
+ createFileNodeFromBufferStub . resetHistory ( )
77
+ } )
78
+
79
+ it ( 'validates required options' , async ( ) => {
80
+
81
+ const params = [
82
+ { gcpTokenFile : null , gcpBucketName : "bucket" } ,
83
+ { gcpTokenFile : "token" , gcpBucketName : null }
84
+ ]
85
+
86
+ for ( let i = 0 ; i < params . length ; i ++ ) {
87
+ apiMock . reporter . panic . resetHistory ( )
88
+ await sourceNodes . sourceNodes ( apiMock , params [ i ] )
89
+ apiMock . reporter . panic . should . be . calledOnce
90
+ }
91
+ } )
92
+
93
+ it ( 'works' , async ( ) => {
94
+ await sourceNodes . sourceNodes ( apiMock , { gcpTokenFile : "token" , gcpBucketName : "bucket" , storageDirectory : "/foo" } )
95
+ apiMock . reporter . panic . should . not . be . called
96
+ apiMock . actions . createNode . should . be . calledOnce
97
+ apiMock . actions . createNode . args [ 0 ] [ 0 ] . internal . type . should . deep . equals ( 'GcpStorage' )
98
+ apiMock . actions . createNode . args [ 0 ] [ 0 ] . internal . mediaType . should . deep . equals ( 'application/gcpfile' )
99
+ apiMock . actions . createNode . args [ 0 ] [ 0 ] . localFile___NODE . should . deep . equals ( '9876' )
100
+ } )
101
+
102
+ it ( "defaults to the root directory" , async ( ) => {
103
+ await sourceNodes . sourceNodes ( apiMock , { gcpTokenFile : "token" , gcpBucketName : "bucket" } )
104
+ apiMock . reporter . warn . should . be . calledOnce
105
+ } )
106
+
107
+ it ( 'type can be renamed' , async ( ) => {
108
+ await sourceNodes . sourceNodes ( apiMock , { gcpTokenFile : "token" , gcpBucketName : "bucket" , storageDirectory : "/foo" , name : "FooDocs" } )
109
+ apiMock . actions . createNode . args [ 0 ] [ 0 ] . internal . type . should . deep . equals ( 'FooDocs' )
110
+ } )
111
+
112
+ } )
0 commit comments