11jest . mock ( '@actions/core' ) ;
22jest . mock ( '@aws-sdk/client-lambda' ) ;
33jest . mock ( '@aws-sdk/client-s3' ) ;
4+ jest . mock ( '@aws-sdk/client-sts' ) ;
45jest . mock ( 'fs/promises' ) ;
56
67const core = require ( '@actions/core' ) ;
78const { S3Client, HeadBucketCommand, CreateBucketCommand, PutObjectCommand } = require ( '@aws-sdk/client-s3' ) ;
9+ const { STSClient, GetCallerIdentityCommand } = require ( '@aws-sdk/client-sts' ) ;
810const fs = require ( 'fs/promises' ) ;
911const mainModule = require ( '../index' ) ;
1012
@@ -29,6 +31,7 @@ describe('S3 Bucket Operations Tests', () => {
2931 } ) ;
3032 core . info = jest . fn ( ) ;
3133 core . error = jest . fn ( ) ;
34+ core . warning = jest . fn ( ) ;
3235 core . setFailed = jest . fn ( ) ;
3336 core . setOutput = jest . fn ( ) ;
3437
@@ -40,6 +43,15 @@ describe('S3 Bucket Operations Tests', () => {
4043
4144 mockS3Send = jest . fn ( ) ;
4245 S3Client . prototype . send = mockS3Send ;
46+
47+ STSClient . prototype . send = jest . fn ( ) . mockImplementation ( ( command ) => {
48+ if ( command instanceof GetCallerIdentityCommand ) {
49+ return Promise . resolve ( {
50+ Account : '123456789012'
51+ } ) ;
52+ }
53+ return Promise . reject ( new Error ( 'Unknown STS command' ) ) ;
54+ } ) ;
4355 } ) ;
4456 describe ( 'checkBucketExists function' , ( ) => {
4557 it ( 'should return true when bucket exists' , async ( ) => {
@@ -121,7 +133,6 @@ describe('S3 Bucket Operations Tests', () => {
121133 } )
122134 ) ;
123135 const createBucketCommand = CreateBucketCommand . mock . calls [ 0 ] [ 0 ] ;
124- // For us-east-1, CreateBucketConfiguration is not set in the implementation
125136 expect ( createBucketCommand . CreateBucketConfiguration ) . toBeUndefined ( ) ;
126137 } ) ;
127138 it ( 'should handle bucket already exists error' , async ( ) => {
@@ -133,6 +144,24 @@ describe('S3 Bucket Operations Tests', () => {
133144 . rejects . toThrow ( ) ;
134145 expect ( core . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'already taken' ) ) ;
135146 } ) ;
147+
148+ it ( 'should handle bucket already owned by you error' , async ( ) => {
149+ const ownedError = new Error ( 'Bucket already owned by you' ) ;
150+ ownedError . name = 'BucketAlreadyOwnedByYou' ;
151+ ownedError . code = 'BucketAlreadyOwnedByYou' ;
152+
153+ mockS3Send . mockRejectedValueOnce ( ownedError ) ;
154+ const s3Client = new S3Client ( { region : 'us-east-1' } ) ;
155+
156+ await expect ( mainModule . createBucket ( s3Client , 'my-existing-bucket' , 'us-east-1' ) )
157+ . rejects . toThrow ( ownedError ) ;
158+
159+ expect ( core . info ) . toHaveBeenCalledWith ( 'Creating S3 bucket: my-existing-bucket' ) ;
160+ expect ( core . info ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sending CreateBucket request' ) ) ;
161+
162+ expect ( mockS3Send ) . toHaveBeenCalledTimes ( 1 ) ;
163+ expect ( mockS3Send ) . toHaveBeenCalledWith ( expect . any ( CreateBucketCommand ) ) ;
164+ } ) ;
136165 it ( 'should handle permission denied error' , async ( ) => {
137166 const accessError = new Error ( 'Access Denied' ) ;
138167 accessError . name = 'AccessDenied' ;
@@ -238,6 +267,35 @@ describe('S3 Bucket Operations Tests', () => {
238267 ) ) . rejects . toThrow ( 'Permission denied' ) ;
239268 expect ( core . error ) . toHaveBeenCalled ( ) ;
240269 } ) ;
270+
271+ it ( 'should handle bucket already owned by you error in uploadToS3' , async ( ) => {
272+ fs . readFile . mockResolvedValue ( Buffer . from ( 'test file content' ) ) ;
273+ fs . access . mockResolvedValue ( undefined ) ;
274+
275+ const notFoundError = new Error ( 'Not Found' ) ;
276+ notFoundError . $metadata = { httpStatusCode : 404 } ;
277+ notFoundError . name = 'NotFound' ;
278+ mockS3Send . mockRejectedValueOnce ( notFoundError ) ;
279+
280+ const ownedError = new Error ( 'Bucket already owned by you' ) ;
281+ ownedError . name = 'BucketAlreadyOwnedByYou' ;
282+ ownedError . code = 'BucketAlreadyOwnedByYou' ;
283+
284+ mockS3Send . mockRejectedValueOnce ( ownedError ) ;
285+
286+ await expect ( mainModule . uploadToS3 (
287+ '/path/to/deployment.zip' ,
288+ 'my-existing-bucket' ,
289+ 'lambda/function.zip' ,
290+ 'us-east-1'
291+ ) ) . rejects . toThrow ( 'Bucket already owned by you' ) ;
292+
293+ expect ( core . error ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Failed to create bucket my-existing-bucket' ) ) ;
294+ expect ( core . info ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Bucket name my-existing-bucket is already taken' ) ) ;
295+
296+ expect ( core . info ) . toHaveBeenCalledWith ( 'Bucket my-existing-bucket does not exist. Attempting to create it...' ) ;
297+ expect ( core . info ) . toHaveBeenCalledWith ( 'Creating S3 bucket: my-existing-bucket' ) ;
298+ } ) ;
241299 it ( 'should handle S3 upload errors' , async ( ) => {
242300
243301 fs . readFile . mockResolvedValue ( Buffer . from ( 'test file content' ) ) ;
@@ -254,7 +312,7 @@ describe('S3 Bucket Operations Tests', () => {
254312 'test-bucket' ,
255313 'key.zip' ,
256314 'us-east-1' ,
257- '123456789012' // Adding expected bucket owner
315+ '123456789012'
258316 ) ) . rejects . toThrow ( 'Upload failed' ) ;
259317
260318 const errorCalls = core . error . mock . calls . flat ( ) . join ( ' ' ) ;
@@ -285,6 +343,22 @@ describe('S3 Bucket Operations Tests', () => {
285343 } ) ;
286344 } ) ;
287345
346+ describe ( 'getAwsAccountId function' , ( ) => {
347+ it ( 'should retrieve AWS account ID successfully' , async ( ) => {
348+ const result = await mainModule . getAwsAccountId ( 'us-east-1' ) ;
349+ expect ( result ) . toBe ( '123456789012' ) ;
350+ expect ( STSClient . prototype . send ) . toHaveBeenCalledWith ( expect . any ( GetCallerIdentityCommand ) ) ;
351+ expect ( core . info ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Successfully retrieved AWS account ID' ) ) ;
352+ } ) ;
353+
354+ it ( 'should handle errors and return null' , async ( ) => {
355+ STSClient . prototype . send = jest . fn ( ) . mockRejectedValueOnce ( new Error ( 'STS error' ) ) ;
356+ const result = await mainModule . getAwsAccountId ( 'us-east-1' ) ;
357+ expect ( result ) . toBeNull ( ) ;
358+ expect ( core . warning ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Failed to retrieve AWS account ID' ) ) ;
359+ } ) ;
360+ } ) ;
361+
288362 describe ( 'S3 Key Generation' , ( ) => {
289363 it ( 'should generate S3 key with timestamp and commit hash' , ( ) => {
290364 const originalEnv = process . env ;
0 commit comments