@@ -2,13 +2,20 @@ jest.mock('child_process');
2
2
3
3
import { Manifest } from '@aws-cdk/cloud-assembly-schema' ;
4
4
import * as mockfs from 'mock-fs' ;
5
- import { AssetManifest , AssetPublishing } from '../lib' ;
5
+ import { AssetPublishing , AssetManifest } from '../lib' ;
6
6
import { FakeListener } from './fake-listener' ;
7
7
import { mockAws , mockedApiFailure , mockedApiResult , mockUpload } from './mock-aws' ;
8
8
import { mockSpawn } from './mock-child_process' ;
9
9
10
10
const ABS_PATH = '/simple/cdk.out/some_external_file' ;
11
11
12
+ const DEFAULT_DESTINATION = {
13
+ region : 'us-north-50' ,
14
+ assumeRoleArn : 'arn:aws:role' ,
15
+ bucketName : 'some_bucket' ,
16
+ objectKey : 'some_key' ,
17
+ } ;
18
+
12
19
let aws : ReturnType < typeof mockAws > ;
13
20
beforeEach ( ( ) => {
14
21
jest . resetAllMocks ( ) ;
@@ -21,34 +28,20 @@ beforeEach(() => {
21
28
source : {
22
29
path : 'some_file' ,
23
30
} ,
24
- destinations : {
25
- theDestination : {
26
- region : 'us-north-50' ,
27
- assumeRoleArn : 'arn:aws:role' ,
28
- bucketName : 'some_bucket' ,
29
- objectKey : 'some_key' ,
30
- } ,
31
- } ,
31
+ destinations : { theDestination : DEFAULT_DESTINATION } ,
32
32
} ,
33
33
} ,
34
34
} ) ,
35
35
'/simple/cdk.out/some_file' : 'FILE_CONTENTS' ,
36
- [ ABS_PATH ] : 'FILE_CONTENTS ' ,
36
+ [ ABS_PATH ] : 'ZIP_FILE_THAT_IS_DEFINITELY_NOT_EMPTY ' ,
37
37
'/abs/cdk.out/assets.json' : JSON . stringify ( {
38
38
version : Manifest . version ( ) ,
39
39
files : {
40
40
theAsset : {
41
41
source : {
42
42
path : '/simple/cdk.out/some_file' ,
43
43
} ,
44
- destinations : {
45
- theDestination : {
46
- region : 'us-north-50' ,
47
- assumeRoleArn : 'arn:aws:role' ,
48
- bucketName : 'some_other_bucket' ,
49
- objectKey : 'some_key' ,
50
- } ,
51
- } ,
44
+ destinations : { theDestination : { ...DEFAULT_DESTINATION , bucketName : 'some_other_bucket' } } ,
52
45
} ,
53
46
} ,
54
47
} ) ,
@@ -59,14 +52,7 @@ beforeEach(() => {
59
52
source : {
60
53
executable : [ 'sometool' ] ,
61
54
} ,
62
- destinations : {
63
- theDestination : {
64
- region : 'us-north-50' ,
65
- assumeRoleArn : 'arn:aws:role' ,
66
- bucketName : 'some_external_bucket' ,
67
- objectKey : 'some_key' ,
68
- } ,
69
- } ,
55
+ destinations : { theDestination : { ...DEFAULT_DESTINATION , bucketName : 'some_external_bucket' } } ,
70
56
} ,
71
57
} ,
72
58
} ) ,
@@ -77,32 +63,31 @@ beforeEach(() => {
77
63
source : {
78
64
path : 'plain_text.txt' ,
79
65
} ,
80
- destinations : {
81
- theDestination : {
82
- region : 'us-north-50' ,
83
- assumeRoleArn : 'arn:aws:role' ,
84
- bucketName : 'some_bucket' ,
85
- objectKey : 'some_key.txt' ,
86
- } ,
87
- } ,
66
+ destinations : { theDestination : { ...DEFAULT_DESTINATION , objectKey : 'some_key.txt' } } ,
88
67
} ,
89
68
theImageAsset : {
90
69
source : {
91
70
path : 'image.png' ,
92
71
} ,
93
- destinations : {
94
- theDestination : {
95
- region : 'us-north-50' ,
96
- assumeRoleArn : 'arn:aws:role' ,
97
- bucketName : 'some_bucket' ,
98
- objectKey : 'some_key.png' ,
99
- } ,
100
- } ,
72
+ destinations : { theDestination : { ...DEFAULT_DESTINATION , objectKey : 'some_key.png' } } ,
101
73
} ,
102
74
} ,
103
75
} ) ,
104
76
'/types/cdk.out/plain_text.txt' : 'FILE_CONTENTS' ,
105
77
'/types/cdk.out/image.png' : 'FILE_CONTENTS' ,
78
+ '/emptyzip/cdk.out/assets.json' : JSON . stringify ( {
79
+ version : Manifest . version ( ) ,
80
+ files : {
81
+ theTextAsset : {
82
+ source : {
83
+ path : 'empty_dir' ,
84
+ packaging : 'zip' ,
85
+ } ,
86
+ destinations : { theDestination : DEFAULT_DESTINATION } ,
87
+ } ,
88
+ } ,
89
+ } ) ,
90
+ '/emptyzip/cdk.out/empty_dir' : { } , // Empty directory
106
91
} ) ;
107
92
108
93
aws = mockAws ( ) ;
@@ -114,6 +99,7 @@ afterEach(() => {
114
99
115
100
test ( 'pass destination properties to AWS client' , async ( ) => {
116
101
const pub = new AssetPublishing ( AssetManifest . fromPath ( '/simple/cdk.out' ) , { aws, throwOnError : false } ) ;
102
+ aws . mockS3 . listObjectsV2 = mockedApiResult ( { } ) ;
117
103
118
104
await pub . publish ( ) ;
119
105
@@ -127,15 +113,29 @@ test('Do nothing if file already exists', async () => {
127
113
const pub = new AssetPublishing ( AssetManifest . fromPath ( '/simple/cdk.out' ) , { aws } ) ;
128
114
129
115
aws . mockS3 . listObjectsV2 = mockedApiResult ( { Contents : [ { Key : 'some_key' } ] } ) ;
116
+ aws . mockS3 . upload = mockUpload ( ) ;
130
117
await pub . publish ( ) ;
131
118
132
119
expect ( aws . mockS3 . listObjectsV2 ) . toHaveBeenCalledWith ( expect . objectContaining ( {
133
120
Bucket : 'some_bucket' ,
134
121
Prefix : 'some_key' ,
135
122
MaxKeys : 1 ,
136
123
} ) ) ;
124
+ expect ( aws . mockS3 . upload ) . not . toHaveBeenCalled ( ) ;
125
+ } ) ;
126
+
127
+ test ( 'tiny file does not count as cache hit' , async ( ) => {
128
+ const pub = new AssetPublishing ( AssetManifest . fromPath ( '/simple/cdk.out' ) , { aws } ) ;
129
+
130
+ aws . mockS3 . listObjectsV2 = mockedApiResult ( { Contents : [ { Key : 'some_key' , Size : 5 } ] } ) ;
131
+ aws . mockS3 . upload = mockUpload ( ) ;
132
+
133
+ await pub . publish ( ) ;
134
+
135
+ expect ( aws . mockS3 . upload ) . toHaveBeenCalled ( ) ;
137
136
} ) ;
138
137
138
+
139
139
test ( 'upload file if new (list returns other key)' , async ( ) => {
140
140
const pub = new AssetPublishing ( AssetManifest . fromPath ( '/simple/cdk.out' ) , { aws } ) ;
141
141
@@ -310,6 +310,18 @@ test('correctly identify asset path if path is absolute', async () => {
310
310
expect ( true ) . toBeTruthy ( ) ; // No exception, satisfy linter
311
311
} ) ;
312
312
313
+ test ( 'empty directory prints failures' , async ( ) => {
314
+ const progressListener = new FakeListener ( ) ;
315
+ const pub = new AssetPublishing ( AssetManifest . fromPath ( '/emptyzip/cdk.out' ) , { aws, progressListener } ) ;
316
+
317
+ aws . mockS3 . listObjectsV2 = mockedApiResult ( { Contents : undefined } ) ;
318
+ aws . mockS3 . upload = mockUpload ( ) ; // Should not be hit
319
+
320
+ await pub . publish ( ) ;
321
+
322
+ expect ( progressListener . messages ) . toContainEqual ( expect . stringContaining ( 'EMPTY ZIP FILE' ) ) ;
323
+ } ) ;
324
+
313
325
describe ( 'external assets' , ( ) => {
314
326
let pub : AssetPublishing ;
315
327
beforeEach ( ( ) => {
@@ -330,7 +342,7 @@ describe('external assets', () => {
330
342
331
343
test ( 'upload external asset correctly' , async ( ) => {
332
344
aws . mockS3 . listObjectsV2 = mockedApiResult ( { Contents : undefined } ) ;
333
- aws . mockS3 . upload = mockUpload ( 'FILE_CONTENTS ' ) ;
345
+ aws . mockS3 . upload = mockUpload ( 'ZIP_FILE_THAT_IS_DEFINITELY_NOT_EMPTY ' ) ;
334
346
const expectAllSpawns = mockSpawn ( { commandLine : [ 'sometool' ] , stdout : ABS_PATH } ) ;
335
347
336
348
await pub . publish ( ) ;
0 commit comments