From 0532ffaec4d5dd00bff1907808e8fcbdb4382080 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Mon, 19 Jul 2021 11:05:39 +0100 Subject: [PATCH 1/3] feat(assertions): retrieve matching resources from the template Provide an API `getResources()` that retrieves the matching resources from the template given its type and optional predicate. For complex assertions that cannot be modeled using the primitives provided by this module, this API allows an 'escape hatch' so that assertions can be written directly into the test case. This is being used in the `aws-cloudwatch` module, specifically to assert widgets in a CloudWatch Dashboard that are modeled as serialized JSON within a property in the resource. --- packages/@aws-cdk/assertions/README.md | 6 +- packages/@aws-cdk/assertions/lib/index.ts | 2 +- .../{has-resource.ts => private/resource.ts} | 60 +++++++++++++----- .../lib/{assertions.ts => template.ts} | 13 +++- .../{assertions.test.ts => template.test.ts} | 62 +++++++++++++++++++ packages/@aws-cdk/aws-cloudwatch/package.json | 4 +- .../aws-cloudwatch/test/alarm.test.ts | 23 ++++--- .../test/composite-alarm.test.ts | 4 +- .../test/cross-environment.test.ts | 4 +- .../aws-cloudwatch/test/dashboard.test.ts | 44 ++++++------- .../aws-cloudwatch/test/metric-math.test.ts | 4 +- .../aws-cloudwatch/test/metrics.test.ts | 6 +- 12 files changed, 170 insertions(+), 62 deletions(-) rename packages/@aws-cdk/assertions/lib/{has-resource.ts => private/resource.ts} (53%) rename packages/@aws-cdk/assertions/lib/{assertions.ts => template.ts} (86%) rename packages/@aws-cdk/assertions/test/{assertions.test.ts => template.test.ts} (80%) diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index 5d61312a812cb..f6a6a70982080 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -62,7 +62,7 @@ in a template. assert.resourceCountIs('Foo::Bar', 2); ``` -## Resource Matching +## Resource Matching & Retrieval Beyond resource counting, the module also allows asserting that a resource with specific properties are present. @@ -88,6 +88,10 @@ assert.hasResource('Foo::Bar', { }); ``` +Beyond assertions, the module provides APIs to retrieve matching resources. +The `getResources()` API is complementary to the `hasResource()` API, except, +instead of asserting its presence, it returns the set of matching resources. + By default, the `hasResource()` and `hasResourceProperties()` APIs perform deep partial object matching. This behavior can be configured using matchers. See subsequent section on [special matchers](#special-matchers). diff --git a/packages/@aws-cdk/assertions/lib/index.ts b/packages/@aws-cdk/assertions/lib/index.ts index 937b59823762c..963039f921bc1 100644 --- a/packages/@aws-cdk/assertions/lib/index.ts +++ b/packages/@aws-cdk/assertions/lib/index.ts @@ -1,3 +1,3 @@ -export * from './assertions'; +export * from './template'; export * from './match'; export * from './matcher'; \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/has-resource.ts b/packages/@aws-cdk/assertions/lib/private/resource.ts similarity index 53% rename from packages/@aws-cdk/assertions/lib/has-resource.ts rename to packages/@aws-cdk/assertions/lib/private/resource.ts index e4b6bf3c1eb06..c1c98c75de8c2 100644 --- a/packages/@aws-cdk/assertions/lib/has-resource.ts +++ b/packages/@aws-cdk/assertions/lib/private/resource.ts @@ -1,6 +1,20 @@ -import { Match } from './match'; -import { Matcher, MatchResult } from './matcher'; -import { StackInspector } from './vendored/assert'; +import { Match } from '../match'; +import { Matcher, MatchResult } from '../matcher'; +import { StackInspector } from '../vendored/assert'; + +export function getResources(inspector: StackInspector, type: string, props: any = {}): { [key: string]: any }[] { + const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); + let results: { [key: string]: any }[] = []; + + eachResourceWithType(inspector, type, (resource) => { + const result = matcher.test(resource); + if (!result.hasFailed()) { + results.push(resource); + } + }); + + return results; +} export function hasResource(inspector: StackInspector, type: string, props: any): string | void { const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); @@ -8,19 +22,22 @@ export function hasResource(inspector: StackInspector, type: string, props: any) let closestResource: { [key: string]: any } | undefined = undefined; let count: number = 0; - for (const logicalId of Object.keys(inspector.value.Resources ?? {})) { - const resource: { [key: string]: any } = inspector.value.Resources[logicalId]; - if (resource.Type === type) { - count++; - const result = matcher.test(resource); - if (!result.hasFailed()) { - return; - } - if (closestResult === undefined || closestResult.failCount > result.failCount) { - closestResult = result; - closestResource = resource; - } + let match = false; + eachResourceWithType(inspector, type, (resource) => { + if (match) { return; } + count++; + const result = matcher.test(resource); + if (!result.hasFailed()) { + match = true; + } + if (closestResult === undefined || closestResult.failCount > result.failCount) { + closestResult = result; + closestResource = resource; } + }); + + if (match) { + return; } if (closestResult === undefined) { @@ -37,6 +54,19 @@ export function hasResource(inspector: StackInspector, type: string, props: any) ].join('\n'); } +function eachResourceWithType( + inspector: StackInspector, + type: string, + cb: (resource: {[key: string]: any}) => void): void { + + for (const logicalId of Object.keys(inspector.value.Resources ?? {})) { + const resource: { [key: string]: any } = inspector.value.Resources[logicalId]; + if (resource.Type === type) { + cb(resource); + } + } +} + function formatMessage(closestResult: MatchResult, closestResource: {}): string { return [ 'The closest result is:', diff --git a/packages/@aws-cdk/assertions/lib/assertions.ts b/packages/@aws-cdk/assertions/lib/template.ts similarity index 86% rename from packages/@aws-cdk/assertions/lib/assertions.ts rename to packages/@aws-cdk/assertions/lib/template.ts index aa7eaeb0bfd7d..77fb64a633fab 100644 --- a/packages/@aws-cdk/assertions/lib/assertions.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -1,7 +1,7 @@ import { Stack, Stage } from '@aws-cdk/core'; -import { hasResource } from './has-resource'; import { Match } from './match'; import { Matcher } from './matcher'; +import { getResources, hasResource } from './private/resource'; import * as assert from './vendored/assert'; /** @@ -82,6 +82,17 @@ export class TemplateAssertions { } } + /** + * Get the set of matching resources of a given type and properties in the CloudFormation template. + * @param type the type to match in the CloudFormation template + * @param props by default, matches all resources with the given type. + * When a literal is provided, performs a partial match via `Match.objectLike()`. + * Use the `Match` APIs to configure a different behaviour. + */ + public getResources(type: string, props: any = {}): { [key: string]: any }[] { + return getResources(this.inspector, type, props); + } + /** * Assert that the CloudFormation template matches the given value * @param expected the expected CloudFormation template as key-value pairs. diff --git a/packages/@aws-cdk/assertions/test/assertions.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts similarity index 80% rename from packages/@aws-cdk/assertions/test/assertions.test.ts rename to packages/@aws-cdk/assertions/test/template.test.ts index bd0cdb828f921..9d2420a5c0cc1 100644 --- a/packages/@aws-cdk/assertions/test/assertions.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -221,6 +221,68 @@ describe('TemplateAssertions', () => { })).toThrow(/No resource/); }); }); + + describe('getResources', () => { + test('matching resource type', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { + type: 'Foo::Bar', + properties: { baz: 'qux', fred: 'waldo' }, + }); + + const inspect = TemplateAssertions.fromStack(stack); + expect(inspect.getResources('Foo::Bar')).toEqual([{ + Type: 'Foo::Bar', + Properties: { baz: 'qux', fred: 'waldo' }, + }]); + }); + + test('no matching resource type', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { + type: 'Foo::Bar', + properties: { baz: 'qux', fred: 'waldo' }, + }); + + const inspect = TemplateAssertions.fromStack(stack); + expect(inspect.getResources('Foo::Baz')).toEqual([]); + }); + + test('matching resource props', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { + type: 'Foo::Bar', + properties: { baz: 'qux', fred: 'waldo' }, + }); + + const inspect = TemplateAssertions.fromStack(stack); + expect(inspect.getResources('Foo::Bar', { + Properties: { baz: 'qux' }, + }).length).toEqual(1); + }); + + test('no matching resource props', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { + type: 'Foo::Bar', + properties: { baz: 'qux', fred: 'waldo' }, + }); + + const inspect = TemplateAssertions.fromStack(stack); + expect(inspect.getResources('Foo::Bar', { + Properties: { baz: 'waldo' }, + })).toEqual([]); + }); + + test('multiple matching resources', () => { + const stack = new Stack(); + new CfnResource(stack, 'Foo', { type: 'Foo::Bar' }); + new CfnResource(stack, 'Bar', { type: 'Foo::Bar' }); + + const inspect = TemplateAssertions.fromStack(stack); + expect(inspect.getResources('Foo::Bar').length).toEqual(2); + }); + }); }); function expectToThrow(fn: () => void, msgs: (RegExp | string)[], done: jest.DoneCallback): void { diff --git a/packages/@aws-cdk/aws-cloudwatch/package.json b/packages/@aws-cdk/aws-cloudwatch/package.json index 246ad8a89ef37..683ca79bde154 100644 --- a/packages/@aws-cdk/aws-cloudwatch/package.json +++ b/packages/@aws-cdk/aws-cloudwatch/package.json @@ -73,13 +73,13 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@types/jest": "^26.0.24", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", "jest": "^26.6.3", - "pkglint": "0.0.0", - "@aws-cdk/assert-internal": "0.0.0" + "pkglint": "0.0.0" }, "dependencies": { "@aws-cdk/aws-iam": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts index c143e8baec65b..f6b0b57e71913 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT } from '@aws-cdk/assert-internal'; +import { Match, TemplateAssertions } from '@aws-cdk/assertions'; import { Duration, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Alarm, IAlarm, IAlarmAction, Metric, MathExpression, IMetric } from '../lib'; @@ -68,7 +67,7 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 3, MetricName: 'Metric', @@ -94,7 +93,7 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 3, MetricName: 'Metric', @@ -120,14 +119,14 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 3, MetricName: 'Metric', Namespace: 'CDK/Test', Period: 300, Statistic: 'Maximum', - ExtendedStatistic: ABSENT, + ExtendedStatistic: Match.absentProperty(), Threshold: 1000, }); @@ -147,13 +146,13 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 3, MetricName: 'Metric', Namespace: 'CDK/Test', Period: 300, - Statistic: ABSENT, + Statistic: Match.absentProperty(), ExtendedStatistic: 'p99', Threshold: 1000, }); @@ -174,7 +173,7 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 3, DatapointsToAlarm: 2, @@ -204,7 +203,7 @@ describe('Alarm', () => { alarm.addOkAction(new TestAlarmAction('C')); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { AlarmActions: ['A'], InsufficientDataActions: ['B'], OKActions: ['C'], @@ -226,7 +225,7 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 2, MetricName: 'Metric', @@ -251,7 +250,7 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ExtendedStatistic: 'p99.9', }); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts index 054f1b21724ee..e77d33a546ca5 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/composite-alarm.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { TemplateAssertions } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { Alarm, AlarmRule, AlarmState, CompositeAlarm, Metric } from '../lib'; @@ -59,7 +59,7 @@ describe('CompositeAlarm', () => { alarmRule, }); - expect(stack).toHaveResource('AWS::CloudWatch::CompositeAlarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::CompositeAlarm', { AlarmName: 'CompositeAlarm', AlarmRule: { 'Fn::Join': [ diff --git a/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts index 959ceafab54fc..fc00cda0753d1 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/cross-environment.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { TemplateAssertions } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { Alarm, GraphWidget, IWidget, Metric } from '../lib'; @@ -89,7 +89,7 @@ describe('cross environment', () => { }); // THEN - expect(stack1).toHaveResourceLike('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack1).hasResourceProperties('AWS::CloudWatch::Alarm', { MetricName: 'ACount', Namespace: 'Test', Period: 300, diff --git a/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts index 5501a47ba5c3a..1b63653b9f5d6 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { isSuperObject } from '@aws-cdk/assert-internal'; +import { TemplateAssertions } from '@aws-cdk/assertions'; import { App, Stack } from '@aws-cdk/core'; import { Dashboard, GraphWidget, PeriodOverride, TextWidget } from '../lib'; @@ -27,11 +26,13 @@ describe('Dashboard', () => { })); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', thatHasWidgets([ + const resources = TemplateAssertions.fromStack(stack).getResources('AWS::CloudWatch::Dashboard'); + expect(resources.length).toEqual(1); + hasWidgets(resources[0].Properties, [ { type: 'text', width: 10, height: 2, x: 0, y: 0, properties: { markdown: 'first' } }, { type: 'text', width: 1, height: 4, x: 0, y: 2, properties: { markdown: 'second' } }, { type: 'text', width: 4, height: 1, x: 0, y: 6, properties: { markdown: 'third' } }, - ])); + ]); }); @@ -61,11 +62,13 @@ describe('Dashboard', () => { ); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', thatHasWidgets([ + const resources = TemplateAssertions.fromStack(stack).getResources('AWS::CloudWatch::Dashboard'); + expect(resources.length).toEqual(1); + hasWidgets(resources[0].Properties, [ { type: 'text', width: 10, height: 2, x: 0, y: 0, properties: { markdown: 'first' } }, { type: 'text', width: 1, height: 4, x: 10, y: 0, properties: { markdown: 'second' } }, { type: 'text', width: 4, height: 1, x: 11, y: 0, properties: { markdown: 'third' } }, - ])); + ]); }); @@ -81,7 +84,7 @@ describe('Dashboard', () => { ); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Dashboard', { DashboardBody: { 'Fn::Join': ['', [ '{"widgets":[{"type":"metric","width":1,"height":1,"x":0,"y":0,"properties":{"view":"timeSeries","region":"', @@ -110,7 +113,7 @@ describe('Dashboard', () => { ); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Dashboard', { DashboardBody: { 'Fn::Join': ['', [ '{"start":"-9H","end":"2018-12-17T06:00:00.000Z","periodOverride":"inherit",\ @@ -135,7 +138,7 @@ describe('Dashboard', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Dashboard', { DashboardName: 'MyCustomDashboardName', }); @@ -151,7 +154,7 @@ describe('Dashboard', () => { new Dashboard(stack, 'MyDashboard'); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Dashboard', {}); + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Dashboard', {}); }); @@ -178,15 +181,14 @@ describe('Dashboard', () => { /** * Returns a property predicate that checks that the given Dashboard has the indicated widgets */ -function thatHasWidgets(widgets: any): (props: any) => boolean { - return (props: any) => { - try { - const actualWidgets = JSON.parse(props.DashboardBody).widgets; - return isSuperObject(actualWidgets, widgets); - } catch (e) { - // eslint-disable-next-line no-console - console.error('Error parsing', props); - throw e; - } - }; +function hasWidgets(props: any, widgets: any[]) { + let actualWidgets: any[] = []; + try { + actualWidgets = JSON.parse(props.DashboardBody).widgets; + } catch (e) { + // eslint-disable-next-line no-console + console.error('Error parsing', props); + throw e; + } + expect(actualWidgets).toEqual(expect.arrayContaining(widgets)); } diff --git a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts index b9379bbdc360c..52e7803575d05 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { TemplateAssertions } from '@aws-cdk/assertions'; import { Duration, Stack } from '@aws-cdk/core'; import { Alarm, GraphWidget, IWidget, MathExpression, Metric } from '../lib'; @@ -638,7 +638,7 @@ function graphMetricsAre(w: IWidget, metrics: any[]) { } function alarmMetricsAre(metrics: any[]) { - expect(stack).toHaveResourceLike('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { Metrics: metrics, }); } diff --git a/packages/@aws-cdk/aws-cloudwatch/test/metrics.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/metrics.test.ts index dc958860b6a4c..063bcf00977db 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/metrics.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/metrics.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { TemplateAssertions } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import { Alarm, Metric } from '../lib'; @@ -15,7 +15,7 @@ describe('Metrics', () => { Metric.grantPutMetricData(role); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -188,7 +188,7 @@ describe('Metrics', () => { dimensionA: 'value1', dimensionB: 'value2', }); - expect(stack).toHaveResourceLike('AWS::CloudWatch::Alarm', { + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { Namespace: 'Test', MetricName: 'Metric', Dimensions: [ From 96986f177cf4c9e085e3f934a3f249de12c7a3de Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Wed, 21 Jul 2021 18:10:58 +0100 Subject: [PATCH 2/3] change to findResources() --- packages/@aws-cdk/assertions/README.md | 2 +- packages/@aws-cdk/assertions/lib/private/resource.ts | 2 +- packages/@aws-cdk/assertions/lib/template.ts | 6 +++--- packages/@aws-cdk/assertions/test/template.test.ts | 10 +++++----- .../@aws-cdk/aws-cloudwatch/test/dashboard.test.ts | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/assertions/README.md b/packages/@aws-cdk/assertions/README.md index f6a6a70982080..1a79f8294cf3b 100644 --- a/packages/@aws-cdk/assertions/README.md +++ b/packages/@aws-cdk/assertions/README.md @@ -89,7 +89,7 @@ assert.hasResource('Foo::Bar', { ``` Beyond assertions, the module provides APIs to retrieve matching resources. -The `getResources()` API is complementary to the `hasResource()` API, except, +The `findResources()` API is complementary to the `hasResource()` API, except, instead of asserting its presence, it returns the set of matching resources. By default, the `hasResource()` and `hasResourceProperties()` APIs perform deep diff --git a/packages/@aws-cdk/assertions/lib/private/resource.ts b/packages/@aws-cdk/assertions/lib/private/resource.ts index c1c98c75de8c2..22a2b01734b70 100644 --- a/packages/@aws-cdk/assertions/lib/private/resource.ts +++ b/packages/@aws-cdk/assertions/lib/private/resource.ts @@ -2,7 +2,7 @@ import { Match } from '../match'; import { Matcher, MatchResult } from '../matcher'; import { StackInspector } from '../vendored/assert'; -export function getResources(inspector: StackInspector, type: string, props: any = {}): { [key: string]: any }[] { +export function findResources(inspector: StackInspector, type: string, props: any = {}): { [key: string]: any }[] { const matcher = Matcher.isMatcher(props) ? props : Match.objectLike(props); let results: { [key: string]: any }[] = []; diff --git a/packages/@aws-cdk/assertions/lib/template.ts b/packages/@aws-cdk/assertions/lib/template.ts index 77fb64a633fab..c76f8150292a2 100644 --- a/packages/@aws-cdk/assertions/lib/template.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -1,7 +1,7 @@ import { Stack, Stage } from '@aws-cdk/core'; import { Match } from './match'; import { Matcher } from './matcher'; -import { getResources, hasResource } from './private/resource'; +import { findResources, hasResource } from './private/resource'; import * as assert from './vendored/assert'; /** @@ -89,8 +89,8 @@ export class TemplateAssertions { * When a literal is provided, performs a partial match via `Match.objectLike()`. * Use the `Match` APIs to configure a different behaviour. */ - public getResources(type: string, props: any = {}): { [key: string]: any }[] { - return getResources(this.inspector, type, props); + public findResources(type: string, props: any = {}): { [key: string]: any }[] { + return findResources(this.inspector, type, props); } /** diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index 9d2420a5c0cc1..70b09b618446c 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -231,7 +231,7 @@ describe('TemplateAssertions', () => { }); const inspect = TemplateAssertions.fromStack(stack); - expect(inspect.getResources('Foo::Bar')).toEqual([{ + expect(inspect.findResources('Foo::Bar')).toEqual([{ Type: 'Foo::Bar', Properties: { baz: 'qux', fred: 'waldo' }, }]); @@ -245,7 +245,7 @@ describe('TemplateAssertions', () => { }); const inspect = TemplateAssertions.fromStack(stack); - expect(inspect.getResources('Foo::Baz')).toEqual([]); + expect(inspect.findResources('Foo::Baz')).toEqual([]); }); test('matching resource props', () => { @@ -256,7 +256,7 @@ describe('TemplateAssertions', () => { }); const inspect = TemplateAssertions.fromStack(stack); - expect(inspect.getResources('Foo::Bar', { + expect(inspect.findResources('Foo::Bar', { Properties: { baz: 'qux' }, }).length).toEqual(1); }); @@ -269,7 +269,7 @@ describe('TemplateAssertions', () => { }); const inspect = TemplateAssertions.fromStack(stack); - expect(inspect.getResources('Foo::Bar', { + expect(inspect.findResources('Foo::Bar', { Properties: { baz: 'waldo' }, })).toEqual([]); }); @@ -280,7 +280,7 @@ describe('TemplateAssertions', () => { new CfnResource(stack, 'Bar', { type: 'Foo::Bar' }); const inspect = TemplateAssertions.fromStack(stack); - expect(inspect.getResources('Foo::Bar').length).toEqual(2); + expect(inspect.findResources('Foo::Bar').length).toEqual(2); }); }); }); diff --git a/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts index 1b63653b9f5d6..cf3c4caa96042 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/dashboard.test.ts @@ -26,7 +26,7 @@ describe('Dashboard', () => { })); // THEN - const resources = TemplateAssertions.fromStack(stack).getResources('AWS::CloudWatch::Dashboard'); + const resources = TemplateAssertions.fromStack(stack).findResources('AWS::CloudWatch::Dashboard'); expect(resources.length).toEqual(1); hasWidgets(resources[0].Properties, [ { type: 'text', width: 10, height: 2, x: 0, y: 0, properties: { markdown: 'first' } }, @@ -62,7 +62,7 @@ describe('Dashboard', () => { ); // THEN - const resources = TemplateAssertions.fromStack(stack).getResources('AWS::CloudWatch::Dashboard'); + const resources = TemplateAssertions.fromStack(stack).findResources('AWS::CloudWatch::Dashboard'); expect(resources.length).toEqual(1); hasWidgets(resources[0].Properties, [ { type: 'text', width: 10, height: 2, x: 0, y: 0, properties: { markdown: 'first' } }, From afafa9ab1062fd1e5581f9076eff656afb8d3c47 Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Mon, 26 Jul 2021 10:35:56 +0100 Subject: [PATCH 3/3] fix up incorrect automerge --- packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts index a4aa10cc56c6e..437dbc5df4ab8 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/alarm.test.ts @@ -269,8 +269,8 @@ describe('Alarm', () => { }); // THEN - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { - Statistic: ABSENT, + TemplateAssertions.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { + Statistic: Match.absentProperty(), ExtendedStatistic: 'tm99.9999999999', });