UNPKG

aws-spa

Version:

A no-brainer script to deploy a single page app on AWS

801 lines (786 loc) 29.9 kB
"use strict"; var _clientCloudfront = require("@aws-sdk/client-cloudfront"); var _ = require("."); var _awsServices = require("../aws-services"); var _testHelper = require("../test-helper"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } describe('cloudfront', () => { describe('findDeployedCloudfrontDistribution', () => { const listDistributionMock = jest.spyOn(_awsServices.cloudfront, 'listDistributions'); const listTagsForResourceMock = jest.spyOn(_awsServices.cloudfront, 'listTagsForResource'); const waitForMock = jest.spyOn(_awsServices.waitUntil, 'distributionDeployed'); afterEach(() => { listDistributionMock.mockReset(); listTagsForResourceMock.mockReset(); waitForMock.mockReset(); }); it('should return the distribution even if on page 2', async () => { listDistributionMock.mockReturnValueOnce((0, _testHelper.awsResolve)({ DistributionList: { NextMarker: 'xxx', Items: [{ Id: 'GOODBYE', Aliases: { Items: ['goodbye.example.com'] } }] } })).mockReturnValueOnce((0, _testHelper.awsResolve)({ DistributionList: { Items: [{ Id: 'HELLO', Status: 'Deployed', Aliases: { Items: ['hello.example.com'] } }] } })); listTagsForResourceMock.mockReturnValue((0, _testHelper.awsResolve)({ Tags: { Items: [_.identifyingTag] } })); const distribution = await (0, _.findDeployedCloudfrontDistribution)('hello.example.com'); expect(distribution).toBeDefined(); expect(distribution.Id).toEqual('HELLO'); }); it('should wait for distribution if distribution is not deployed', async () => { listDistributionMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionList: { Items: [{ Id: 'HELLO', Status: 'In Progress', Aliases: { Items: ['hello.example.com'] } }] } })); listTagsForResourceMock.mockReturnValue((0, _testHelper.awsResolve)({ Tags: { Items: [_.identifyingTag] } })); waitForMock.mockReturnValue((0, _testHelper.awsResolve)()); await (0, _.findDeployedCloudfrontDistribution)('hello.example.com'); expect(waitForMock).toHaveBeenCalledTimes(1); }); }); describe('invalidateCloudfrontCache', () => { const createInvalidationMock = jest.spyOn(_awsServices.cloudfront, 'createInvalidation'); const waitForMock = jest.spyOn(_awsServices.waitUntil, 'invalidationCompleted'); afterEach(() => { createInvalidationMock.mockReset(); waitForMock.mockReset(); }); it('should invalidate the specified path', async () => { createInvalidationMock.mockReturnValue((0, _testHelper.awsResolve)({ Invalidation: {} })); await (0, _.invalidateCloudfrontCache)('some-distribution-id', 'index.html'); expect(createInvalidationMock).toHaveBeenCalledTimes(1); const invalidationParams = createInvalidationMock.mock.calls[0][0]; expect(invalidationParams.DistributionId).toEqual('some-distribution-id'); expect(invalidationParams.InvalidationBatch.Paths.Items[0]).toEqual('index.html'); }); it('should invalidate the specified paths', async () => { createInvalidationMock.mockReturnValue((0, _testHelper.awsResolve)({ Invalidation: {} })); await (0, _.invalidateCloudfrontCache)('some-distribution-id', 'index.html, static/*'); expect(createInvalidationMock).toHaveBeenCalledTimes(1); const invalidationParams = createInvalidationMock.mock.calls[0][0]; expect(invalidationParams.DistributionId).toEqual('some-distribution-id'); expect(invalidationParams.InvalidationBatch.Paths.Items).toEqual(['index.html', 'static/*']); }); it('should wait for invalidate if wait flag is true', async () => { createInvalidationMock.mockReturnValue((0, _testHelper.awsResolve)({ Invalidation: { Id: 'some-invalidation-id' } })); waitForMock.mockReturnValue((0, _testHelper.awsResolve)()); await (0, _.invalidateCloudfrontCache)('some-distribution-id', 'index.html', true); expect(waitForMock).toHaveBeenCalledTimes(1); expect(waitForMock).toHaveBeenCalledWith(expect.anything(), { DistributionId: 'some-distribution-id', Id: 'some-invalidation-id' }); }); }); describe('invalidateCloudfrontCacheWithRetry', () => { const createInvalidationMock = jest.spyOn(_awsServices.cloudfront, 'createInvalidation'); const waitForMock = jest.spyOn(_awsServices.waitUntil, 'invalidationCompleted'); afterEach(() => { createInvalidationMock.mockReset(); waitForMock.mockReset(); }); it('should retry once', async () => { createInvalidationMock.mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsResolve)({ Invalidation: {} })); await (0, _.invalidateCloudfrontCacheWithRetry)('some-distribution-id', 'index.html, static/*'); expect(createInvalidationMock).toHaveBeenCalledTimes(2); }); it('should retry 5 times at most', async () => { createInvalidationMock.mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsReject)(1)).mockReturnValueOnce((0, _testHelper.awsResolve)({ Invalidation: {} })); try { await (0, _.invalidateCloudfrontCacheWithRetry)('some-distribution-id', 'index.html, static/*'); } catch (error) { expect(error).toBeDefined(); } expect(createInvalidationMock).toHaveBeenCalledTimes(5); }); }); describe('createCloudFrontDistribution', () => { const createDistributionMock = jest.spyOn(_awsServices.cloudfront, 'createDistribution'); const waitForMock = jest.spyOn(_awsServices.waitUntil, 'distributionDeployed'); const tagResourceMock = jest.spyOn(_awsServices.cloudfront, 'tagResource'); afterEach(() => { createDistributionMock.mockReset(); waitForMock.mockReset(); tagResourceMock.mockReset(); }); it('should create a distribution and wait for it to be available', async () => { const distribution = { Id: 'distribution-id' }; createDistributionMock.mockReturnValue((0, _testHelper.awsResolve)({ Distribution: distribution })); tagResourceMock.mockReturnValue((0, _testHelper.awsResolve)()); waitForMock.mockReturnValue((0, _testHelper.awsResolve)()); const result = await (0, _.createCloudFrontDistribution)('hello.lalilo.com', 'arn:certificate'); expect(result).toEqual(distribution); expect(tagResourceMock).toHaveBeenCalledTimes(1); expect(createDistributionMock).toHaveBeenCalledTimes(1); const distributionParam = createDistributionMock.mock.calls[0][0]; const distributionConfig = distributionParam.DistributionConfig; expect(distributionConfig.Origins.Items[0].DomainName).toEqual('hello.lalilo.com.s3-website.eu-west-3.amazonaws.com'); expect(distributionConfig.DefaultCacheBehavior.ViewerProtocolPolicy).toEqual('redirect-to-https'); expect(distributionConfig.DefaultCacheBehavior.MinTTL).toEqual(0); expect(distributionConfig.DefaultCacheBehavior.Compress).toEqual(true); expect(distributionConfig.ViewerCertificate.ACMCertificateArn).toEqual('arn:certificate'); expect(waitForMock).toHaveBeenCalledTimes(1); expect(waitForMock).toHaveBeenCalledWith(expect.anything(), { Id: 'distribution-id' }); }); }); describe('getCacheInvalidations', () => { it.each([{ input: 'index.html', expectedOutput: '/index.html' }, { input: '/index.html', expectedOutput: '/index.html' }, { input: 'index.html, hello.html', subFolder: undefined, expectedOutput: '/index.html,/hello.html' }, { input: 'index.html', subFolder: 'some-branch', expectedOutput: '/some-branch/index.html' }])('add missing slash', ({ input, subFolder, expectedOutput }) => { expect((0, _.getCacheInvalidations)(input, subFolder)).toEqual(expectedOutput); }); }); describe('updateCloudFrontDistribution', () => { const getDistributionConfigMock = jest.spyOn(_awsServices.cloudfront, 'getDistributionConfig'); const updateDistribution = jest.spyOn(_awsServices.cloudfront, 'updateDistribution'); const listFunctions = jest.spyOn(_awsServices.cloudfront, 'listFunctions'); const createFunction = jest.spyOn(_awsServices.cloudfront, 'createFunction'); const publishFunction = jest.spyOn(_awsServices.cloudfront, 'publishFunction'); beforeEach(() => { getDistributionConfigMock.mockReset(); updateDistribution.mockReset(); listFunctions.mockReturnValue((0, _testHelper.awsResolve)({ FunctionList: { Items: [] } })); publishFunction.mockReturnValue((0, _testHelper.awsResolve)({})); createFunction.mockReturnValue((0, _testHelper.awsResolve)({ ETag: 'lol', FunctionSummary: { FunctionMetadata: { Id: 'oac-id', FunctionARN: 'plop' } } })); }); it.each([{ shouldBlockBucketPublicAccess: true, noDefaultRootObject: false }, { shouldBlockBucketPublicAccess: false, noDefaultRootObject: false }, { shouldBlockBucketPublicAccess: true, noDefaultRootObject: true }, { shouldBlockBucketPublicAccess: false, noDefaultRootObject: true }])(`should not update the distribution if the configuration doesn't change %p`, async ({ shouldBlockBucketPublicAccess, noDefaultRootObject }) => { if (noDefaultRootObject) { listFunctions.mockReturnValueOnce((0, _testHelper.awsResolve)({ FunctionList: { Items: [{ FunctionConfig: { FunctionMetadata: { Id: 'oac-id', FunctionARN: 'plop' } } }] } })); } const domainName = 'hello.lalilo.com'; const originId = shouldBlockBucketPublicAccess ? (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName) : (0, _awsServices.getOriginId)(domainName); const originDomainName = shouldBlockBucketPublicAccess ? (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName) : (0, _awsServices.getS3DomainName)(domainName); const distribution = { Id: 'distribution-id', DefaultRootObject: noDefaultRootObject ? '' : 'index.html', Alias: { Quantity: 1, Items: [originDomainName] }, Origins: { Quantity: 1, Items: [{ Id: originId, DomainName: originDomainName }] }, DefaultCacheBehavior: _objectSpread({ TargetOriginId: originId }, noDefaultRootObject ? { FunctionAssociations: { Quantity: 1, Items: [{ FunctionARN: 'plop', EventType: 'viewer-request' }] } } : { FunctionAssociations: { Quantity: 0, Items: [] } }) }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); if (shouldBlockBucketPublicAccess) { await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess, noDefaultRootObject, oac: { originAccessControl: { Id: 'oac-id' }, ETag: 'etag' }, redirect403ToRoot: false }); } else { await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess, noDefaultRootObject, oac: null, redirect403ToRoot: false }); } expect(updateDistribution).not.toHaveBeenCalled(); }); it('should update the distribution with an OAC when shouldBlockBucketPublicAccess and oac is given', async () => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); const oac = { originAccessControl: { Id: 'oac-id' }, ETag: 'etag' }; const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: (0, _awsServices.getS3DomainName)(domainName) }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultCacheBehavior: { TargetOriginId: (0, _awsServices.getS3DomainName)(domainName) } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess: true, noDefaultRootObject: false, oac, redirect403ToRoot: false }); expect(updateDistribution).toHaveBeenCalled(); expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ DefaultRootObject: 'index.html', Origins: expect.objectContaining({ Items: [expect.objectContaining({ Id: originIdForPrivateBucket, DomainName: originIdForPrivateBucket, OriginAccessControlId: oac.originAccessControl.Id, S3OriginConfig: { OriginAccessIdentity: '' } })] }), DefaultCacheBehavior: expect.objectContaining({ TargetOriginId: originIdForPrivateBucket }) }) })); }); it.each([{ noDefaultRootObject: false }, { noDefaultRootObject: true }])(`should update the distribution if the defaultRootObject if different from the existing config (and not touch to other config) %p`, async ({ noDefaultRootObject }) => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); const oac = { originAccessControl: { Id: 'oac-id' }, ETag: 'etag' }; const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultCacheBehavior: { TargetOriginId: originIdForPrivateBucket }, DefaultRootObject: noDefaultRootObject ? 'index.html' : '' }; const originalConfig = (0, _testHelper.awsResolve)({ DistributionConfig: distribution }); getDistributionConfigMock.mockReturnValue(originalConfig); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess: true, noDefaultRootObject, oac, redirect403ToRoot: false }); expect(updateDistribution).toHaveBeenCalled(); expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ DefaultRootObject: noDefaultRootObject ? '' : 'index.html', Origins: expect.objectContaining({ Items: [expect.objectContaining({ DomainName: originIdForPrivateBucket })] }), DefaultCacheBehavior: expect.objectContaining({ TargetOriginId: originIdForPrivateBucket }) }) })); }); it('only uses the most recent LIVE functions', async () => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); listFunctions.mockReturnValue((0, _testHelper.awsResolve)({ FunctionList: { Items: [{ FunctionMetadata: { LastModifiedTime: new Date('2025-08-08'), Stage: _clientCloudfront.FunctionStage.DEVELOPMENT, FunctionARN: 'ARN_dev' }, Name: 'function1' }, { FunctionMetadata: { LastModifiedTime: new Date('2025-06-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'ARN_live_old' }, Name: 'function1' }, { FunctionMetadata: { LastModifiedTime: new Date('2025-07-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'ARN_live_recent' }, Name: 'function1' }] } })); const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, CustomErrorResponses: { Quantity: 0 } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': ['function1'], 'viewer-response': [] }, shouldBlockBucketPublicAccess: false, noDefaultRootObject: false, oac: null, redirect403ToRoot: true }); expect(updateDistribution).toHaveBeenCalled(); expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ DefaultCacheBehavior: expect.objectContaining({ FunctionAssociations: { Quantity: 1, Items: [{ FunctionARN: 'ARN_live_recent', EventType: _clientCloudfront.EventType.viewer_request }] } }) }) })); }); it.each([{ viewerRequestFunctionNames: ['newFunction1'], withNoDefaultRootObjectFunction: false }, { viewerRequestFunctionNames: ['newFunction1', 'newFunction2'], withNoDefaultRootObjectFunction: false }, { viewerRequestFunctionNames: ['newFunction1'], withNoDefaultRootObjectFunction: true }])('should override existing distribution functions by provided one', async ({ viewerRequestFunctionNames, withNoDefaultRootObjectFunction }) => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); listFunctions.mockReturnValue((0, _testHelper.awsResolve)({ FunctionList: { Items: [{ FunctionMetadata: { LastModifiedTime: new Date('2025-06-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'newFunction1ARN' }, Name: 'newFunction1' }, { FunctionMetadata: { LastModifiedTime: new Date('2025-06-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'newFunction2ARN' }, Name: 'newFunction2' }, { FunctionMetadata: { LastModifiedTime: new Date('2025-06-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'function1ARN' }, Name: 'function1' }, { FunctionMetadata: { LastModifiedTime: new Date('2025-06-08'), Stage: _clientCloudfront.FunctionStage.LIVE, FunctionARN: 'function2ARN' }, Name: 'function2' }] } })); const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultCacheBehavior: { TargetOriginId: originIdForPrivateBucket, FunctionAssociations: { Quantity: 1, Items: [{ FunctionARN: 'function1ARN', EventType: _clientCloudfront.EventType.viewer_request }, { FunctionARN: 'function2ARN', EventType: _clientCloudfront.EventType.viewer_response }] } }, CustomErrorResponses: { Quantity: 0 } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': viewerRequestFunctionNames, 'viewer-response': [] }, shouldBlockBucketPublicAccess: false, noDefaultRootObject: withNoDefaultRootObjectFunction, oac: null, redirect403ToRoot: true }); expect(updateDistribution).toHaveBeenCalled(); const expectedFunctions = viewerRequestFunctionNames.map(functionName => ({ FunctionARN: `${functionName}ARN`, EventType: _clientCloudfront.EventType.viewer_request })); if (withNoDefaultRootObjectFunction) { expectedFunctions.push({ FunctionARN: 'plop', EventType: _clientCloudfront.EventType.viewer_request }); } expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ DefaultCacheBehavior: expect.objectContaining({ FunctionAssociations: { Quantity: viewerRequestFunctionNames.length + (withNoDefaultRootObjectFunction ? 1 : 0), Items: expectedFunctions } }) }) })); }); it('should update the distribution if additionalDomainNames are provided', async () => { const domainName = 'hello.lalilo.com'; const additionalDomainName1 = 'ola.lalilo.com'; const additionalDomainName2 = 'hallo.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultCacheBehavior: { TargetOriginId: originIdForPrivateBucket }, CustomErrorResponses: { Quantity: 0 } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [additionalDomainName1, additionalDomainName2], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess: false, noDefaultRootObject: false, oac: null, redirect403ToRoot: true }); expect(updateDistribution).toHaveBeenCalled(); expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ Aliases: { Quantity: 3, Items: [domainName, additionalDomainName1, additionalDomainName2] } }) })); }); it('should update the distribution if the 403 redirection option was not set in the existing config', async () => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultCacheBehavior: { TargetOriginId: originIdForPrivateBucket }, CustomErrorResponses: { Quantity: 0 } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); updateDistribution.mockReturnValueOnce((0, _testHelper.awsResolve)()); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess: false, noDefaultRootObject: false, oac: null, redirect403ToRoot: true }); expect(updateDistribution).toHaveBeenCalled(); expect(updateDistribution).toHaveBeenCalledWith(expect.objectContaining({ DistributionConfig: expect.objectContaining({ CustomErrorResponses: { Quantity: 1, Items: [{ ErrorCode: 403, ResponsePagePath: '/index.html', ResponseCode: '200', ErrorCachingMinTTL: 10 }] } }) })); }); it('should not update the distribution if the 403 redirection option is already set in the existing config', async () => { const domainName = 'hello.lalilo.com'; const originIdForPrivateBucket = (0, _awsServices.getS3DomainNameForBlockedBucket)(domainName); const distribution = { Id: 'distribution-id', Origins: { Items: [{ DomainName: originIdForPrivateBucket }] }, Aliases: { Quantity: 1, Items: [domainName] }, DefaultRootObject: '', DefaultCacheBehavior: { TargetOriginId: originIdForPrivateBucket, FunctionAssociations: { Quantity: 1, Items: [{ FunctionARN: 'plop', EventType: 'viewer-request' }] } }, CustomErrorResponses: { Quantity: 1, Items: [{ ErrorCode: 403, ResponsePagePath: '/index.html', ResponseCode: '200', ErrorCachingMinTTL: 10 }] } }; getDistributionConfigMock.mockReturnValue((0, _testHelper.awsResolve)({ DistributionConfig: distribution })); await (0, _.updateCloudFrontDistribution)(distribution.Id, domainName, { additionalDomainNames: [], cloudFrontFunctionsAssignments: { 'viewer-request': [], 'viewer-response': [] }, shouldBlockBucketPublicAccess: true, noDefaultRootObject: true, oac: { originAccessControl: { Id: 'oac-id' }, ETag: 'etag' }, redirect403ToRoot: true }); expect(updateDistribution).not.toHaveBeenCalled(); }); }); });