Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(assert): add countResourcesLike method #6168

Merged
merged 5 commits into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions packages/@aws-cdk/assert/lib/assertions/count-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,48 @@ export function countResources(resourceType: string, count = 1): Assertion<Stack
return new CountResourcesAssertion(resourceType, count);
}

/**
* An assertion to check whether a resource of a given type and with the given properties exists, considering properties
*/
export function countResourcesLike(resourceType: string, count = 1, props: any): Assertion<StackInspector> {
return new CountResourcesAssertion(resourceType, count, props);
}

class CountResourcesAssertion extends Assertion<StackInspector> {
private inspected: number = 0;
private readonly props: any;

constructor(private readonly resourceType: string,
private readonly count: number) {
private readonly count: number,
props: any = null) {
super();
this.props = props;
}

public assertUsing(inspector: StackInspector): boolean {
let counted = 0;
for (const logicalId of Object.keys(inspector.value.Resources || {})) {
const resource = inspector.value.Resources[logicalId];
if (resource.Type === this.resourceType) {
counted++;
this.inspected += 1;
if (this.props) {
const propEntries = Object.entries(this.props);
propEntries.forEach(([key, val]) => {
if (resource.Properties && resource.Properties[key] && JSON.stringify(resource.Properties[key]) === JSON.stringify(val)) {
counted++;
this.inspected += 1;
}
});
} else {
counted++;
this.inspected += 1;
}
}
}

return counted === this.count;
}

public get description(): string {
return `stack only has ${this.inspected} resource of type ${this.resourceType} but we expected to find ${this.count}`;
return `stack only has ${this.inspected} resource of type ${this.resourceType}${this.props ? ' with specified properties' : ''} but we expected to find ${this.count}`;
}
}
71 changes: 70 additions & 1 deletion packages/@aws-cdk/assert/test/assertions.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as cdk from '@aws-cdk/core';
import * as cx from '@aws-cdk/cx-api';

import { countResources, exist, expect as cdkExpect, haveType, MatchStyle, matchTemplate } from '../lib/index';
import { countResources, countResourcesLike, exist, expect as cdkExpect, haveType, MatchStyle, matchTemplate } from '../lib/index';

passingExample('expect <synthStack> at <some path> to have <some type>', () => {
const resourceType = 'Test::Resource';
Expand Down Expand Up @@ -237,6 +237,75 @@ failingExample('expect <synthStack> to count resources - less than expected', ()
cdkExpect(synthStack).to(countResources(resourceType, 0));
});

// countResourcesLike

passingExample('expect <synthStack> to count resources like props - as expected', () => {
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: 'Bar', properties: { parentId: 123, name: "A" } });
new TestResource(stack, 'R2', { type: 'Bar', properties: { parentId: 123, name: "B" } });
new TestResource(stack, 'R3', { type: 'Foo', properties: { parentId: 123 } });
});

cdkExpect(synthStack).to(countResourcesLike('Bar', 2, { parentId: 123 }));
cdkExpect(synthStack).to(countResourcesLike('Foo', 1, { parentId: 123 }));
});

passingExample('expect <stack> to count resources like props - expected no resources', () => {
const resourceType = 'Test::Resource';
const stack = new cdk.Stack();
cdkExpect(stack).to(countResourcesLike(resourceType, 0, { parentId: 123 }));
});

passingExample('expect <stack> to count resources like props - expected no resources', () => {
const resourceType = 'Test::Resource';
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: resourceType, properties: { parentId: 123, name: "A" } });
new TestResource(stack, 'R2', { type: resourceType });
new TestResource(stack, 'R3', { type: 'Foo', properties: { parentId: 456} });
});
cdkExpect(synthStack).to(countResourcesLike(resourceType, 0, { parentId: 456 }));
});

failingExample('expect <synthStack> to count resources like props - more than expected', () => {
const resourceType = 'Test::Resource';
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: resourceType, properties: { parentId: 123 } });
new TestResource(stack, 'R2', { type: resourceType, properties: { parentId: 123 } });
});

cdkExpect(synthStack).to(countResourcesLike(resourceType, 1, { parentId: 123 }));
});

failingExample('expect <synthStack> to count resources like props - nested props out of order', () => {
const resourceType = 'Test::Resource';
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: resourceType, properties: { id: 987, parentInfo: { id: 123, name: "A" } } });
new TestResource(stack, 'R2', { type: resourceType, properties: { id: 456, parentInfo: { name: "A", id: 123 } } });
});

cdkExpect(synthStack).to(countResourcesLike(resourceType, 2, { parentInfo: { id: 123, name: "A" } }));
});

failingExample('expect <synthStack> to count resources like props - nested props incomplete', () => {
const resourceType = 'Test::Resource';
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: resourceType, properties: { id: 987, parentInfo: { id: 123, name: "A" } } });
new TestResource(stack, 'R2', { type: resourceType, properties: { id: 456, parentInfo: { name: "A", id: 123 } } });
});

cdkExpect(synthStack).to(countResourcesLike(resourceType, 2, { parentInfo: { id: 123 } }));
});

failingExample('expect <synthStack> to count resources like props - less than expected', () => {
const resourceType = 'Test::Resource';
const synthStack = synthesizedStack(stack => {
new TestResource(stack, 'R1', { type: resourceType, properties: { parentId: 123 } });
new TestResource(stack, 'R2', { type: resourceType, properties: { parentId: 123 } });
});

cdkExpect(synthStack).to(countResourcesLike(resourceType, 0, { parentId: 123 }));
});

function passingExample(title: string, cb: () => void) {
describe('passing', () => {
test(title, cb);
Expand Down