Skip to content
This repository has been archived by the owner on Jan 5, 2022. It is now read-only.

Commit

Permalink
write a snapshot test on new and migrate
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamie Lynch committed Jan 22, 2021
1 parent 5c89afa commit 4ad7c58
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/commands/migrate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("The MigrateCommand class", () => {
cfnFile: "template.ts",
appPath: `/path/to/output/bin/app.ts`,
stackPath: `/path/to/output/lib/stack-name.ts`,
testPath: `/path/to/output/lib/stack-name.test.ts`,
});
});

Expand All @@ -47,6 +48,7 @@ describe("The MigrateCommand class", () => {
cfnFile: "template.ts",
appPath: `/path/to/output/bin/app.ts`,
stackPath: `/path/to/output/lib/app/stack-name.ts`,
testPath: `/path/to/output/lib/app/stack-name.test.ts`,
});
});

Expand Down
18 changes: 17 additions & 1 deletion src/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
getStackNameFromFileName,
} from "../utils/args";
import { parse } from "../utils/cfn";
import { newAppImports } from "../utils/imports";
import { newAppImports, newTestImports } from "../utils/imports";
import { constructStack } from "../utils/stack";
import { constructTest } from "../utils/snapshot";

interface MigrateCommandConfig {
cfnPath: string;
Expand All @@ -20,6 +21,7 @@ interface MigrateCommandConfig {
appName: string;
stackPath: string;
stackName: string;
testPath: string;
}

interface MigrateCommandArgs {
Expand Down Expand Up @@ -91,6 +93,9 @@ export class MigrateCommand extends Command {
stackPath: `${cdkDir}/lib/${
flags["multi-app"] ? `${kebabAppName}/` : ""
}${kebabStackName}.ts`,
testPath: `${cdkDir}/lib/${
flags["multi-app"] ? `${kebabAppName}/` : ""
}${kebabStackName}.test.ts`,
};

MigrateCommand.validateConfig(config);
Expand Down Expand Up @@ -140,5 +145,16 @@ export class MigrateCommand extends Command {
config.stackPath
)} using @guardian/cdk-cli\n// It is a starting point for migration to CDK *only*. Please check the output carefully before deploying`,
});

await constructTest({
stackName: config.stackName,
appName: config.appName,
outputFile: basename(config.testPath),
outputDir: dirname(config.stackPath),
imports: newTestImports(config.stackName),
comment: `// This file was autogenerated from ${basename(
config.stackPath
)} using @guardian/cdk-cli\n// It is a starting point for migration to CDK *only*. Please check the output carefully before deploying`,
});
}
}
2 changes: 2 additions & 0 deletions src/commands/new.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe("The NewCommand class", () => {
expect(NewCommand.getConfig(args)).toMatchObject({
appPath: `/path/to/output/bin/app.ts`,
stackPath: `/path/to/output/lib/stack-name.ts`,
testPath: `/path/to/output/lib/stack-name.test.ts`,
});
});

Expand All @@ -43,6 +44,7 @@ describe("The NewCommand class", () => {
).toMatchObject({
appPath: `/path/to/output/bin/app.ts`,
stackPath: `/path/to/output/lib/app/stack-name.ts`,
testPath: `/path/to/output/lib/app/stack-name.test.ts`,
});
});
});
Expand Down
28 changes: 23 additions & 5 deletions src/commands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import { Command, flags } from "@oclif/command";
import kebabCase from "lodash.kebabcase";
import { constructApp } from "../utils/app";
import { checkPathDoesNotExist, checkPathExists } from "../utils/args";
import { newAppImports, newStackImports } from "../utils/imports";
import {
newAppImports,
newStackImports,
newTestImports,
} from "../utils/imports";
import { cancellablePrompts } from "../utils/prompts";
import type { StackTemplate } from "../utils/stack";
import { constructStack } from "../utils/stack";
import { constructTest } from "../utils/snapshot";

interface NewCommandConfig {
cdkDir: string;
Expand All @@ -19,6 +24,7 @@ interface NewCommandConfig {
appName: string;
stackPath: string;
stackName: string;
testPath: string;
}

interface NewCommandArgs {
Expand Down Expand Up @@ -58,7 +64,7 @@ export class NewCommand extends Command {
},
];

imports = newStackImports();
stackImports = newStackImports();

template: StackTemplate = {
Parameters: {},
Expand All @@ -85,6 +91,9 @@ export class NewCommand extends Command {
stackPath: `${cdkDir}/lib/${
flags["multi-app"] ? `${kebabAppName}/` : ""
}${kebabStackName}.ts`,
testPath: `${cdkDir}/lib/${
flags["multi-app"] ? `${kebabAppName}/` : ""
}${kebabStackName}.test.ts`,
};

NewCommand.validateConfig(config);
Expand Down Expand Up @@ -122,13 +131,22 @@ export class NewCommand extends Command {
});

await constructStack({
imports: this.imports,
imports: this.stackImports,
template: this.template,
stackName: config.stackName,
outputFile: basename(config.stackPath),
outputDir: dirname(config.stackPath),
comment: "// This file was autogenerated using @guardian/cdk-cli",
});

await constructTest({
imports: newTestImports(config.stackName),
stackName: config.stackName,
appName: config.appName,
outputFile: basename(config.testPath),
outputDir: dirname(config.stackPath),
comment: "// This file was autogenerated using @guardian/cdk-cli",
});
}

async getParameters(): Promise<void> {
Expand Down Expand Up @@ -159,7 +177,7 @@ export class NewCommand extends Command {
parameterType: "GuStringParameter",
};

this.imports.addImport("@guardian/cdk/lib/constructs/core", [
this.stackImports.addImport("@guardian/cdk/lib/constructs/core", [
"GuStringParameter",
]);
} else {
Expand All @@ -168,7 +186,7 @@ export class NewCommand extends Command {
type,
};

this.imports.addImport("@guardian/cdk/lib/constructs/core", [
this.stackImports.addImport("@guardian/cdk/lib/constructs/core", [
"GuParameter",
]);
}
Expand Down
36 changes: 35 additions & 1 deletion src/utils/imports.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { MockCodeMaker } from "../../test/utils/codemaker";
import { Imports, newAppImports, newStackImports } from "./imports";
import {
Imports,
newAppImports,
newStackImports,
newTestImports,
} from "./imports";

describe("The Imports class", () => {
describe("addImport function", () => {
Expand Down Expand Up @@ -288,3 +293,32 @@ describe("The newAppImports function", () => {
});
});
});

describe("The newTestImports function", () => {
test("adds the correct initial imports", () => {
const imports = newTestImports("stack");
expect(imports.imports["@aws-cdk/assert"]).toEqual({
types: [],
components: ["SynthUtils"],
});

expect(imports.imports["@aws-cdk/core"]).toEqual({
types: [],
components: ["App"],
});

expect(imports.imports["@aws-cdk/assert/jest"]).toEqual({
basic: true,
types: [],
components: [],
});
});

test("adds the correct stack import", () => {
const imports = newTestImports("StackName");
expect(imports.imports["./stack-name"]).toEqual({
types: [],
components: ["StackName"],
});
});
});
22 changes: 22 additions & 0 deletions src/utils/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,25 @@ export const newAppImports = (

return imports;
};

export const newTestImports = (name: string): Imports => {
const imports = new Imports({
"@aws-cdk/assert/jest": {
types: [],
components: [],
basic: true,
},
"@aws-cdk/assert": {
types: [],
components: ["SynthUtils"],
},
"@aws-cdk/core": {
types: [],
components: ["App"],
},
});

imports.addImport(`./${kebabCase(name)}`, [name]);

return imports;
};
47 changes: 47 additions & 0 deletions src/utils/snapshot.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { MockCodeMaker } from "../../test/utils/codemaker";
import { Imports } from "./imports";
import { TestBuilder } from "./snapshot";

describe("The TestBuilder class", () => {
describe("addTest function", () => {
const builder = new TestBuilder({
outputDir: "",
outputFile: "",
stackName: "StackName",
appName: "AppName",
imports: new Imports(),
});
const codemaker = new MockCodeMaker();
builder.code = codemaker.codemaker;

beforeEach(() => {
codemaker.clear();
});

test("adds a snapshot test", () => {
builder.addTest();
expect(codemaker._codemaker.openBlock).toHaveBeenNthCalledWith(
1,
`describe("The StackName stack", () =>`
);
expect(codemaker._codemaker.openBlock).toHaveBeenNthCalledWith(
2,
`it("matches the snapshot", () =>`
);
expect(codemaker._codemaker.line).toHaveBeenNthCalledWith(
1,
`const app = new App();`
);
expect(codemaker._codemaker.line).toHaveBeenNthCalledWith(
2,
`const stack = new StackName(app, "stack-name", { app: "app-name" });`
);
expect(codemaker._codemaker.line).toHaveBeenNthCalledWith(
3,
`expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot();`
);
expect(codemaker._codemaker.closeBlock).toHaveBeenNthCalledWith(1, `});`);
expect(codemaker._codemaker.closeBlock).toHaveBeenNthCalledWith(2, `});`);
});
});
});
65 changes: 65 additions & 0 deletions src/utils/snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { CodeMaker } from "codemaker";
import kebabCase from "lodash.kebabcase";
import type { Imports } from "./imports";

export interface TestBuilderProps {
imports: Imports;
appName: string;
stackName: string;
outputFile: string;
outputDir: string;
comment?: string;
}

export class TestBuilder {
config: TestBuilderProps;
imports: Imports;

code: CodeMaker;

constructor(props: TestBuilderProps) {
this.config = props;
this.imports = props.imports;

this.code = new CodeMaker({ indentationLevel: 2 });
this.code.closeBlockFormatter = (s?: string): string => s ?? "}";
}

async constructCdkFile(): Promise<void> {
this.code.openFile(this.config.outputFile);
if (this.config.comment) {
this.code.line(this.config.comment);
this.code.line();
}

this.config.imports.render(this.code);

this.addTest();

this.code.closeFile(this.config.outputFile);
await this.code.save(this.config.outputDir);
}

addTest(): void {
this.code.openBlock(`describe("The ${this.config.stackName} stack", () =>`);
this.code.openBlock(`it("matches the snapshot", () =>`);

this.code.line("const app = new App();");
this.code.line(
`const stack = new ${this.config.stackName}(app, "${kebabCase(
this.config.stackName
)}", { app: "${kebabCase(this.config.appName)}" });`
);
this.code.line(
"expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot();"
);

this.code.closeBlock("});");
this.code.closeBlock("});");
}
}

export const constructTest = async (props: TestBuilderProps): Promise<void> => {
const builder = new TestBuilder(props);
await builder.constructCdkFile();
};

0 comments on commit 4ad7c58

Please sign in to comment.