import * as path from "path"; import * as fs from "fs-extra"; import { expect as expectCdk, haveResource, objectLike, stringLike, anything, } from "@aws-cdk/assert"; import { App, Stack, ReactStaticSite } from "../src"; ///////////////////////////// // Test Constructor ///////////////////////////// test("constructor: environment invalid name", async () => { const stack = new Stack(new App(), "stack"); expect(() => { new ReactStaticSite(stack, "Site", { path: "test/site", environment: { API_URL: "my-url", }, }); }).toThrow(/Environment variables in the "Site" ReactStaticSite must start with "REACT_APP_"./); }); test("constructor: default indexPage", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", }); expectCdk(stack).to( haveResource("AWS::CloudFront::Distribution", { DistributionConfig: objectLike({ DefaultRootObject: "index.html", }), }) ); }); test("constructor: default errorPage redirect to indexPage", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", }); expectCdk(stack).to( haveResource("AWS::CloudFront::Distribution", { DistributionConfig: objectLike({ CustomErrorResponses: [ { ErrorCode: 403, ResponseCode: 200, ResponsePagePath: "/index.html", }, { ErrorCode: 404, ResponseCode: 200, ResponsePagePath: "/index.html", }, ], }), }) ); }); test("constructor: default buildCommand", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", environment: { REACT_APP_API_URL: "my-url", }, }); const indexHtml = fs.readFileSync( path.join(__dirname, "site", "build", "index.html") ); expect(indexHtml.toString().trim()).toBe("{{ REACT_APP_API_URL }}"); }); test("constructor: default buildCommand override", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", buildCommand: 'rm -rf build && mkdir build && node -e "console.log(process.env.REACT_APP_API_URL, process.env.REACT_APP_API_URL)" > build/index.html', environment: { REACT_APP_API_URL: "my-url", }, }); const indexHtml = fs.readFileSync( path.join(__dirname, "site", "build", "index.html") ); expect(indexHtml.toString().trim()).toBe( "{{ REACT_APP_API_URL }} {{ REACT_APP_API_URL }}" ); }); test("constructor: default fileOptions for cache control", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", }); expectCdk(stack).to( haveResource("Custom::SSTBucketDeployment", { Sources: [{ BucketName: anything(), ObjectKey: anything(), }], DistributionPaths: ["/*"], DestinationBucketName: { Ref: "SiteBucket978D4AEB", }, DestinationBucketKeyPrefix: stringLike("deploy-*"), FileOptions: [ [ "--exclude", "*", "--include", "*.html", "--cache-control", "max-age=0,no-cache,no-store,must-revalidate", ], [ "--exclude", "*", "--include", "*.js", "--include", "*.css", "--cache-control", "max-age=31536000,public,immutable", ], ], ReplaceValues: [], }) ); }); test("constructor: default replaceValues", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", environment: { REACT_APP_API_URL: "my-url", }, }); expectCdk(stack).to( haveResource("Custom::SSTBucketDeployment", { ReplaceValues: [ { files: "**/*.js", search: "{{ REACT_APP_API_URL }}", replace: "my-url", }, { files: "index.html", search: "{{ REACT_APP_API_URL }}", replace: "my-url", }, ], }) ); }); test("constructor: default replaceValues override", async () => { const stack = new Stack(new App(), "stack"); new ReactStaticSite(stack, "Site", { path: "test/site", environment: { REACT_APP_API_URL: "my-url", }, replaceValues: [ { files: "*.txt", search: "{{ KEY }}", replace: "value", }, ], }); expectCdk(stack).to( haveResource("Custom::SSTBucketDeployment", { ReplaceValues: [ { files: "*.txt", search: "{{ KEY }}", replace: "value", }, { files: "**/*.js", search: "{{ REACT_APP_API_URL }}", replace: "my-url", }, { files: "index.html", search: "{{ REACT_APP_API_URL }}", replace: "my-url", }, ], }) ); });