@@ -82,6 +82,19 @@ jest.mock('@aws-sdk/client-s3', () => {
8282 } ) )
8383 } ;
8484} ) ;
85+ jest . mock ( '@aws-sdk/client-sts' , ( ) => {
86+ const original = jest . requireActual ( '@aws-sdk/client-sts' ) ;
87+ return {
88+ ...original ,
89+ GetCallerIdentityCommand : jest . fn ( ) . mockImplementation ( ( params ) => ( {
90+ ...params ,
91+ type : 'GetCallerIdentityCommand'
92+ } ) ) ,
93+ STSClient : jest . fn ( ) . mockImplementation ( ( ) => ( {
94+ send : jest . fn ( ) . mockResolvedValue ( { Account : '123456789012' } )
95+ } ) )
96+ } ;
97+ } ) ;
8598
8699afterAll ( ( ) => {
87100 jest . clearAllMocks ( ) ;
@@ -598,4 +611,153 @@ describe('Function Existence Check', () => {
598611 } ) ) ;
599612 } ) ;
600613 } ) ;
614+
615+ test ( 'Config changed with dry run logs message' , ( ) => {
616+ const configChanged = true ;
617+ const dryRun = true ;
618+
619+ if ( configChanged ) {
620+ if ( dryRun ) {
621+ core . info ( '[DRY RUN] Configuration updates are not simulated in dry run mode' ) ;
622+ return ;
623+ }
624+ }
625+
626+ expect ( core . info ) . toHaveBeenCalledWith ( '[DRY RUN] Configuration updates are not simulated in dry run mode' ) ;
627+ } ) ;
628+
629+ test ( 'Config changed without dry run calls updateFunctionConfiguration' , async ( ) => {
630+ const mockClient = { send : jest . fn ( ) } ;
631+ const configChanged = true ;
632+ const dryRun = false ;
633+
634+ if ( configChanged ) {
635+ if ( dryRun ) {
636+ core . info ( '[DRY RUN] Configuration updates are not simulated in dry run mode' ) ;
637+ return ;
638+ }
639+
640+ await index . updateFunctionConfiguration ( mockClient , {
641+ functionName : 'test-function' ,
642+ role : 'test-role' ,
643+ handler : 'index.handler' ,
644+ functionDescription : 'test' ,
645+ parsedMemorySize : 256 ,
646+ timeout : 30 ,
647+ runtime : 'nodejs20.x' ,
648+ kmsKeyArn : 'test-kms' ,
649+ ephemeralStorage : 512 ,
650+ vpcConfig : '{}' ,
651+ parsedEnvironment : { } ,
652+ deadLetterConfig : '{}' ,
653+ tracingConfig : '{}' ,
654+ layers : '[]' ,
655+ fileSystemConfigs : '[]' ,
656+ imageConfig : '{}' ,
657+ snapStart : '{}' ,
658+ loggingConfig : '{}' ,
659+ parsedVpcConfig : { } ,
660+ parsedDeadLetterConfig : { } ,
661+ parsedTracingConfig : { } ,
662+ parsedLayers : [ ] ,
663+ parsedFileSystemConfigs : [ ] ,
664+ parsedImageConfig : { } ,
665+ parsedSnapStart : { } ,
666+ parsedLoggingConfig : { }
667+ } ) ;
668+ }
669+
670+ expect ( mockClient . send ) . toHaveBeenCalled ( ) ;
671+ } ) ;
672+
673+ test ( 'No config changes logs no changes message' , ( ) => {
674+ const configChanged = false ;
675+
676+ if ( configChanged ) {
677+ // Should not execute
678+ } else {
679+ core . info ( 'No configuration changes detected' ) ;
680+ }
681+
682+ expect ( core . info ) . toHaveBeenCalledWith ( 'No configuration changes detected' ) ;
683+ } ) ;
684+
685+ test ( 'generateS3Key creates key with timestamp' , ( ) => {
686+ const result = index . generateS3Key ( 'test-function' ) ;
687+ expect ( result ) . toMatch ( / ^ l a m b d a - d e p l o y m e n t s \/ t e s t - f u n c t i o n \/ \d { 4 } - \d { 2 } - \d { 2 } - \d { 2 } - \d { 2 } - \d { 2 } - \d { 3 } \. z i p $ / ) ;
688+ } ) ;
689+
690+ test ( 'generateS3Key includes commit hash when GITHUB_SHA exists' , ( ) => {
691+ process . env . GITHUB_SHA = 'abcdef1234567890' ;
692+ const result = index . generateS3Key ( 'test-function' ) ;
693+ expect ( result ) . toContain ( '-abcdef1' ) ;
694+ delete process . env . GITHUB_SHA ;
695+ } ) ;
696+
697+ test ( 'validateBucketName validates bucket names' , ( ) => {
698+ expect ( index . validateBucketName ( 'valid-bucket-name' ) ) . toBe ( true ) ;
699+ expect ( index . validateBucketName ( 'ab' ) ) . toBe ( false ) ;
700+ expect ( index . validateBucketName ( 'INVALID' ) ) . toBe ( false ) ;
701+ expect ( index . validateBucketName ( '192.168.1.1' ) ) . toBe ( false ) ;
702+ expect ( index . validateBucketName ( 'bucket..name' ) ) . toBe ( false ) ;
703+ } ) ;
704+
705+ test ( 'isEmptyValue checks empty values' , ( ) => {
706+ expect ( index . isEmptyValue ( null ) ) . toBe ( true ) ;
707+ expect ( index . isEmptyValue ( '' ) ) . toBe ( true ) ;
708+ expect ( index . isEmptyValue ( [ ] ) ) . toBe ( true ) ;
709+ expect ( index . isEmptyValue ( { } ) ) . toBe ( true ) ;
710+ expect ( index . isEmptyValue ( 'value' ) ) . toBe ( false ) ;
711+ expect ( index . isEmptyValue ( { SubnetIds : [ ] } ) ) . toBe ( false ) ;
712+ } ) ;
713+
714+ test ( 'cleanNullKeys removes null values' , ( ) => {
715+ expect ( index . cleanNullKeys ( null ) ) . toBeUndefined ( ) ;
716+ expect ( index . cleanNullKeys ( '' ) ) . toBeUndefined ( ) ;
717+ expect ( index . cleanNullKeys ( { key : 'value' , empty : null } ) ) . toEqual ( { key : 'value' } ) ;
718+ expect ( index . cleanNullKeys ( [ ] ) ) . toBeUndefined ( ) ;
719+ expect ( index . cleanNullKeys ( [ 'value' , null ] ) ) . toEqual ( [ 'value' ] ) ;
720+ } ) ;
721+
722+ test ( 'deepEqual compares objects deeply' , ( ) => {
723+ expect ( index . deepEqual ( { a : 1 } , { a : 1 } ) ) . toBe ( true ) ;
724+ expect ( index . deepEqual ( { a : 1 } , { a : 2 } ) ) . toBe ( false ) ;
725+ expect ( index . deepEqual ( [ 1 , 2 ] , [ 1 , 2 ] ) ) . toBe ( true ) ;
726+ expect ( index . deepEqual ( [ 1 , 2 ] , [ 1 , 3 ] ) ) . toBe ( false ) ;
727+ expect ( index . deepEqual ( null , null ) ) . toBe ( true ) ;
728+ expect ( index . deepEqual ( 'test' , 'test' ) ) . toBe ( true ) ;
729+ } ) ;
730+
731+ test ( 'hasConfigurationChanged detects changes' , async ( ) => {
732+ const current = { Role : 'old-role' , Handler : 'old.handler' } ;
733+ const updated = { Role : 'new-role' , Handler : 'old.handler' } ;
734+ const result = await index . hasConfigurationChanged ( current , updated ) ;
735+ expect ( result ) . toBe ( true ) ;
736+ expect ( core . info ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Configuration difference detected' ) ) ;
737+ } ) ;
738+
739+ test ( 'hasConfigurationChanged returns true for empty current config' , async ( ) => {
740+ const result = await index . hasConfigurationChanged ( { } , { Role : 'test' } ) ;
741+ expect ( result ) . toBe ( true ) ;
742+ } ) ;
743+
744+ test ( 'getAwsAccountId retrieves account ID' , async ( ) => {
745+ const mockSend = jest . fn ( ) . mockResolvedValue ( { Account : '123456789012' } ) ;
746+ const { STSClient } = require ( '@aws-sdk/client-sts' ) ;
747+ STSClient . mockImplementation ( ( ) => ( { send : mockSend } ) ) ;
748+
749+ const result = await index . getAwsAccountId ( 'us-east-1' ) ;
750+ expect ( result ) . toBe ( '123456789012' ) ;
751+ expect ( core . info ) . toHaveBeenCalledWith ( 'Successfully retrieved AWS account ID: 123456789012' ) ;
752+ } ) ;
753+
754+ test ( 'getAwsAccountId handles errors' , async ( ) => {
755+ const mockSend = jest . fn ( ) . mockRejectedValue ( new Error ( 'STS error' ) ) ;
756+ const { STSClient } = require ( '@aws-sdk/client-sts' ) ;
757+ STSClient . mockImplementation ( ( ) => ( { send : mockSend } ) ) ;
758+
759+ const result = await index . getAwsAccountId ( 'us-east-1' ) ;
760+ expect ( result ) . toBeNull ( ) ;
761+ expect ( core . warning ) . toHaveBeenCalledWith ( 'Failed to retrieve AWS account ID: STS error' ) ;
762+ } ) ;
601763} ) ;
0 commit comments