aws-cdk.assertions


Nameaws-cdk.assertions JSON
Version 1.203.0 PyPI version JSON
download
home_pagehttps://github.com/aws/aws-cdk
SummaryAn assertion library for use with CDK Apps
upload_time2023-05-31 23:00:17
maintainer
docs_urlNone
authorAmazon Web Services
requires_python~=3.7
licenseApache-2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Assertions

<!--BEGIN STABILITY BANNER-->---


![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge)

---
<!--END STABILITY BANNER-->

If you're migrating from the old `assert` library, the migration guide can be found in
[our GitHub repository](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/assertions/MIGRATING.md).

Functions for writing test asserting against CDK applications, with focus on CloudFormation templates.

The `Template` class includes a set of methods for writing assertions against CloudFormation templates. Use one of the `Template.fromXxx()` static methods to create an instance of this class.

To create `Template` from CDK stack, start off with:

```python
from aws_cdk.core import Stack
from aws_cdk.assertions import Template

stack = Stack()
# ...
template = Template.from_stack(stack)
```

Alternatively, assertions can be run on an existing CloudFormation template -

```python
template_json = "{ \"Resources\": ... }" # The CloudFormation template as JSON serialized string.
template = Template.from_string(template_json)
```

## Full Template Match

The simplest assertion would be to assert that the template matches a given
template.

```python
template.template_matches({
    "Resources": {
        "BarLogicalId": {
            "Type": "Foo::Bar",
            "Properties": {
                "Baz": "Qux"
            }
        }
    }
})
```

By default, the `templateMatches()` API will use the an 'object-like' comparison,
which means that it will allow for the actual template to be a superset of the
given expectation. See [Special Matchers](#special-matchers) for details on how
to change this.

Snapshot testing is a common technique to store a snapshot of the output and
compare it during future changes. Since CloudFormation templates are human readable,
they are a good target for snapshot testing.

The `toJSON()` method on the `Template` can be used to produce a well formatted JSON
of the CloudFormation template that can be used as a snapshot.

See [Snapshot Testing in Jest](https://jestjs.io/docs/snapshot-testing) and [Snapshot
Testing in Java](https://json-snapshot.github.io/).

## Counting Resources

This module allows asserting the number of resources of a specific type found
in a template.

```python
template.resource_count_is("Foo::Bar", 2)
```

## Resource Matching & Retrieval

Beyond resource counting, the module also allows asserting that a resource with
specific properties are present.

The following code asserts that the `Properties` section of a resource of type
`Foo::Bar` contains the specified properties -

```python
template.has_resource_properties("Foo::Bar", {
    "Foo": "Bar",
    "Baz": 5,
    "Qux": ["Waldo", "Fred"]
})
```

Alternatively, if you would like to assert the entire resource definition, you
can use the `hasResource()` API.

```python
template.has_resource("Foo::Bar", {
    "Properties": {"Foo": "Bar"},
    "DependsOn": ["Waldo", "Fred"]
})
```

Beyond assertions, the module provides APIs to retrieve matching resources.
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
partial object matching. This behavior can be configured using matchers.
See subsequent section on [special matchers](#special-matchers).

## Output and Mapping sections

The module allows you to assert that the CloudFormation template contains an Output
that matches specific properties. The following code asserts that a template contains
an Output with a `logicalId` of `Foo` and the specified properties -

```python
expected = {
    "Value": "Bar",
    "Export": {"Name": "ExportBaz"}
}
template.has_output("Foo", expected)
```

If you want to match against all Outputs in the template, use `*` as the `logicalId`.

```python
template.has_output("*", {
    "Value": "Bar",
    "Export": {"Name": "ExportBaz"}
})
```

`findOutputs()` will return a set of outputs that match the `logicalId` and `props`,
and you can use the `'*'` special case as well.

```python
result = template.find_outputs("*", {"Value": "Fred"})
expect(result.Foo).to_equal({"Value": "Fred", "Description": "FooFred"})
expect(result.Bar).to_equal({"Value": "Fred", "Description": "BarFred"})
```

The APIs `hasMapping()`, `findMappings()`, `hasCondition()`, and `hasCondtions()` provide similar functionalities.

## Special Matchers

The expectation provided to the `hasXxx()`, `findXxx()` and `templateMatches()`
APIs, besides carrying literal values, as seen in the above examples, also accept
special matchers.

They are available as part of the `Match` class.

### Object Matchers

The `Match.objectLike()` API can be used to assert that the target is a superset
object of the provided pattern.
This API will perform a deep partial match on the target.
Deep partial matching is where objects are matched partially recursively. At each
level, the list of keys in the target is a subset of the provided pattern.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": {
#           "Wobble": "Flob",
#           "Bob": "Cat"
#         }
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.object_like({
        "Wobble": "Flob"
    })
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.object_like({
        "Brew": "Coffee"
    })
})
```

The `Match.objectEquals()` API can be used to assert a target as a deep exact
match.

### Presence and Absence

The `Match.absent()` matcher can be used to specify that a specific
value should not exist on the target. This can be used within `Match.objectLike()`
or outside of any matchers.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": {
#           "Wobble": "Flob",
#         }
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.object_like({
        "Bob": Match.absent()
    })
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.object_like({
        "Wobble": Match.absent()
    })
})
```

The `Match.anyValue()` matcher can be used to specify that a specific value should be found
at the location. This matcher will fail if when the target location has null-ish values
(i.e., `null` or `undefined`).

This matcher can be combined with any of the other matchers.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": {
#           "Wobble": ["Flob", "Flib"],
#         }
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": {
        "Wobble": [Match.any_value(), Match.any_value()]
    }
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": {
        "Wimble": Match.any_value()
    }
})
```

### Array Matchers

The `Match.arrayWith()` API can be used to assert that the target is equal to or a subset
of the provided pattern array.
This API will perform subset match on the target.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": ["Flob", "Cat"]
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.array_with(["Flob"])
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", Match.object_like({
    "Fred": Match.array_with(["Wobble"])
}))
```

*Note:* The list of items in the pattern array should be in order as they appear in the
target array. Out of order will be recorded as a match failure.

Alternatively, the `Match.arrayEquals()` API can be used to assert that the target is
exactly equal to the pattern array.

### String Matchers

The `Match.stringLikeRegexp()` API can be used to assert that the target matches the
provided regular expression.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Template": "const includeHeaders = true;"
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Template": Match.string_like_regexp("includeHeaders = (true|false)")
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Template": Match.string_like_regexp("includeHeaders = null")
})
```

### Not Matcher

The not matcher inverts the search pattern and matches all patterns in the path that does
not match the pattern specified.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": ["Flob", "Cat"]
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Fred": Match.not(["Flob"])
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", Match.object_like({
    "Fred": Match.not(["Flob", "Cat"])
}))
```

### Serialized JSON

Often, we find that some CloudFormation Resource types declare properties as a string,
but actually expect JSON serialized as a string.
For example, the [`BuildSpec` property of `AWS::CodeBuild::Project`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-source.html#cfn-codebuild-project-source-buildspec),
the [`Definition` property of `AWS::StepFunctions::StateMachine`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definition),
to name a couple.

The `Match.serializedJson()` matcher allows deep matching within a stringified JSON.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Baz": "{ \"Fred\": [\"Waldo\", \"Willow\"] }"
#       }
#     }
#   }
# }

# The following will NOT throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Baz": Match.serialized_json({
        "Fred": Match.array_with(["Waldo"])
    })
})

# The following will throw an assertion error
template.has_resource_properties("Foo::Bar", {
    "Baz": Match.serialized_json({
        "Fred": ["Waldo", "Johnny"]
    })
})
```

## Capturing Values

The matcher APIs documented above allow capturing values in the matching entry
(Resource, Output, Mapping, etc.). The following code captures a string from a
matching resource.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": ["Flob", "Cat"],
#         "Waldo": ["Qix", "Qux"],
#       }
#     }
#   }
# }

fred_capture = Capture()
waldo_capture = Capture()
template.has_resource_properties("Foo::Bar", {
    "Fred": fred_capture,
    "Waldo": ["Qix", waldo_capture]
})

fred_capture.as_array() # returns ["Flob", "Cat"]
waldo_capture.as_string()
```

With captures, a nested pattern can also be specified, so that only targets
that match the nested pattern will be captured. This pattern can be literals or
further Matchers.

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar1": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": ["Flob", "Cat"],
#       }
#     }
#     "MyBar2": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": ["Qix", "Qux"],
#       }
#     }
#   }
# }

capture = Capture(Match.array_with(["Cat"]))
template.has_resource_properties("Foo::Bar", {
    "Fred": capture
})

capture.as_array()
```

When multiple resources match the given condition, each `Capture` defined in
the condition will capture all matching values. They can be paged through using
the `next()` API. The following example illustrates this -

```python
# Given a template -
# {
#   "Resources": {
#     "MyBar": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": "Flob",
#       }
#     },
#     "MyBaz": {
#       "Type": "Foo::Bar",
#       "Properties": {
#         "Fred": "Quib",
#       }
#     }
#   }
# }

fred_capture = Capture()
template.has_resource_properties("Foo::Bar", {
    "Fred": fred_capture
})

fred_capture.as_string() # returns "Flob"
fred_capture.next() # returns true
fred_capture.as_string()
```

## Asserting Annotations

In addition to template matching, we provide an API for annotation matching.
[Annotations](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Annotations.html)
can be added via the [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html)
API. You can learn more about Aspects [here](https://docs.aws.amazon.com/cdk/v2/guide/aspects.html).

Say you have a `MyAspect` and a `MyStack` that uses `MyAspect`:

```python
import aws_cdk.core as cdk
from constructs import Construct, IConstruct

class MyAspect(cdk.IAspect):
    def visit(self, node):
        if node instanceof cdk.CfnResource && node.cfn_resource_type == "Foo::Bar":
            self.error(node, "we do not want a Foo::Bar resource")

    def error(self, node, message):
        cdk.Annotations.of(node).add_error(message)

class MyStack(cdk.Stack):
    def __init__(self, scope, id):
        super().__init__(scope, id)

        stack = cdk.Stack()
        cdk.CfnResource(stack, "Foo",
            type="Foo::Bar",
            properties={
                "Fred": "Thud"
            }
        )
        cdk.Aspects.of(stack).add(MyAspect())
```

We can then assert that the stack contains the expected Error:

```python
# import { Annotations } from '@aws-cdk/assertions';

Annotations.from_stack(stack).has_error("/Default/Foo", "we do not want a Foo::Bar resource")
```

Here are the available APIs for `Annotations`:

* `hasError()`, `hasNoError()`, and `findError()`
* `hasWarning()`, `hasNoWarning()`, and `findWarning()`
* `hasInfo()`, `hasNoInfo()`, and `findInfo()`

The corresponding `findXxx()` API is complementary to the `hasXxx()` API, except instead
of asserting its presence, it returns the set of matching messages.

In addition, this suite of APIs is compatable with `Matchers` for more fine-grained control.
For example, the following assertion works as well:

```python
Annotations.from_stack(stack).has_error("/Default/Foo",
    Match.string_like_regexp(".*Foo::Bar.*"))
```



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/aws/aws-cdk",
    "name": "aws-cdk.assertions",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "~=3.7",
    "maintainer_email": "",
    "keywords": "",
    "author": "Amazon Web Services",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/8d/98/15ed2e1c3c2791ad6d81320aaa70ada5bf11c6d38c10541466a7fc6bd01f/aws-cdk.assertions-1.203.0.tar.gz",
    "platform": null,
    "description": "# Assertions\n\n<!--BEGIN STABILITY BANNER-->---\n\n\n![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge)\n\n---\n<!--END STABILITY BANNER-->\n\nIf you're migrating from the old `assert` library, the migration guide can be found in\n[our GitHub repository](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/assertions/MIGRATING.md).\n\nFunctions for writing test asserting against CDK applications, with focus on CloudFormation templates.\n\nThe `Template` class includes a set of methods for writing assertions against CloudFormation templates. Use one of the `Template.fromXxx()` static methods to create an instance of this class.\n\nTo create `Template` from CDK stack, start off with:\n\n```python\nfrom aws_cdk.core import Stack\nfrom aws_cdk.assertions import Template\n\nstack = Stack()\n# ...\ntemplate = Template.from_stack(stack)\n```\n\nAlternatively, assertions can be run on an existing CloudFormation template -\n\n```python\ntemplate_json = \"{ \\\"Resources\\\": ... }\" # The CloudFormation template as JSON serialized string.\ntemplate = Template.from_string(template_json)\n```\n\n## Full Template Match\n\nThe simplest assertion would be to assert that the template matches a given\ntemplate.\n\n```python\ntemplate.template_matches({\n    \"Resources\": {\n        \"BarLogicalId\": {\n            \"Type\": \"Foo::Bar\",\n            \"Properties\": {\n                \"Baz\": \"Qux\"\n            }\n        }\n    }\n})\n```\n\nBy default, the `templateMatches()` API will use the an 'object-like' comparison,\nwhich means that it will allow for the actual template to be a superset of the\ngiven expectation. See [Special Matchers](#special-matchers) for details on how\nto change this.\n\nSnapshot testing is a common technique to store a snapshot of the output and\ncompare it during future changes. Since CloudFormation templates are human readable,\nthey are a good target for snapshot testing.\n\nThe `toJSON()` method on the `Template` can be used to produce a well formatted JSON\nof the CloudFormation template that can be used as a snapshot.\n\nSee [Snapshot Testing in Jest](https://jestjs.io/docs/snapshot-testing) and [Snapshot\nTesting in Java](https://json-snapshot.github.io/).\n\n## Counting Resources\n\nThis module allows asserting the number of resources of a specific type found\nin a template.\n\n```python\ntemplate.resource_count_is(\"Foo::Bar\", 2)\n```\n\n## Resource Matching & Retrieval\n\nBeyond resource counting, the module also allows asserting that a resource with\nspecific properties are present.\n\nThe following code asserts that the `Properties` section of a resource of type\n`Foo::Bar` contains the specified properties -\n\n```python\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Foo\": \"Bar\",\n    \"Baz\": 5,\n    \"Qux\": [\"Waldo\", \"Fred\"]\n})\n```\n\nAlternatively, if you would like to assert the entire resource definition, you\ncan use the `hasResource()` API.\n\n```python\ntemplate.has_resource(\"Foo::Bar\", {\n    \"Properties\": {\"Foo\": \"Bar\"},\n    \"DependsOn\": [\"Waldo\", \"Fred\"]\n})\n```\n\nBeyond assertions, the module provides APIs to retrieve matching resources.\nThe `findResources()` API is complementary to the `hasResource()` API, except,\ninstead of asserting its presence, it returns the set of matching resources.\n\nBy default, the `hasResource()` and `hasResourceProperties()` APIs perform deep\npartial object matching. This behavior can be configured using matchers.\nSee subsequent section on [special matchers](#special-matchers).\n\n## Output and Mapping sections\n\nThe module allows you to assert that the CloudFormation template contains an Output\nthat matches specific properties. The following code asserts that a template contains\nan Output with a `logicalId` of `Foo` and the specified properties -\n\n```python\nexpected = {\n    \"Value\": \"Bar\",\n    \"Export\": {\"Name\": \"ExportBaz\"}\n}\ntemplate.has_output(\"Foo\", expected)\n```\n\nIf you want to match against all Outputs in the template, use `*` as the `logicalId`.\n\n```python\ntemplate.has_output(\"*\", {\n    \"Value\": \"Bar\",\n    \"Export\": {\"Name\": \"ExportBaz\"}\n})\n```\n\n`findOutputs()` will return a set of outputs that match the `logicalId` and `props`,\nand you can use the `'*'` special case as well.\n\n```python\nresult = template.find_outputs(\"*\", {\"Value\": \"Fred\"})\nexpect(result.Foo).to_equal({\"Value\": \"Fred\", \"Description\": \"FooFred\"})\nexpect(result.Bar).to_equal({\"Value\": \"Fred\", \"Description\": \"BarFred\"})\n```\n\nThe APIs `hasMapping()`, `findMappings()`, `hasCondition()`, and `hasCondtions()` provide similar functionalities.\n\n## Special Matchers\n\nThe expectation provided to the `hasXxx()`, `findXxx()` and `templateMatches()`\nAPIs, besides carrying literal values, as seen in the above examples, also accept\nspecial matchers.\n\nThey are available as part of the `Match` class.\n\n### Object Matchers\n\nThe `Match.objectLike()` API can be used to assert that the target is a superset\nobject of the provided pattern.\nThis API will perform a deep partial match on the target.\nDeep partial matching is where objects are matched partially recursively. At each\nlevel, the list of keys in the target is a subset of the provided pattern.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": {\n#           \"Wobble\": \"Flob\",\n#           \"Bob\": \"Cat\"\n#         }\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.object_like({\n        \"Wobble\": \"Flob\"\n    })\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.object_like({\n        \"Brew\": \"Coffee\"\n    })\n})\n```\n\nThe `Match.objectEquals()` API can be used to assert a target as a deep exact\nmatch.\n\n### Presence and Absence\n\nThe `Match.absent()` matcher can be used to specify that a specific\nvalue should not exist on the target. This can be used within `Match.objectLike()`\nor outside of any matchers.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": {\n#           \"Wobble\": \"Flob\",\n#         }\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.object_like({\n        \"Bob\": Match.absent()\n    })\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.object_like({\n        \"Wobble\": Match.absent()\n    })\n})\n```\n\nThe `Match.anyValue()` matcher can be used to specify that a specific value should be found\nat the location. This matcher will fail if when the target location has null-ish values\n(i.e., `null` or `undefined`).\n\nThis matcher can be combined with any of the other matchers.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": {\n#           \"Wobble\": [\"Flob\", \"Flib\"],\n#         }\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": {\n        \"Wobble\": [Match.any_value(), Match.any_value()]\n    }\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": {\n        \"Wimble\": Match.any_value()\n    }\n})\n```\n\n### Array Matchers\n\nThe `Match.arrayWith()` API can be used to assert that the target is equal to or a subset\nof the provided pattern array.\nThis API will perform subset match on the target.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": [\"Flob\", \"Cat\"]\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.array_with([\"Flob\"])\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", Match.object_like({\n    \"Fred\": Match.array_with([\"Wobble\"])\n}))\n```\n\n*Note:* The list of items in the pattern array should be in order as they appear in the\ntarget array. Out of order will be recorded as a match failure.\n\nAlternatively, the `Match.arrayEquals()` API can be used to assert that the target is\nexactly equal to the pattern array.\n\n### String Matchers\n\nThe `Match.stringLikeRegexp()` API can be used to assert that the target matches the\nprovided regular expression.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Template\": \"const includeHeaders = true;\"\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Template\": Match.string_like_regexp(\"includeHeaders = (true|false)\")\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Template\": Match.string_like_regexp(\"includeHeaders = null\")\n})\n```\n\n### Not Matcher\n\nThe not matcher inverts the search pattern and matches all patterns in the path that does\nnot match the pattern specified.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": [\"Flob\", \"Cat\"]\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": Match.not([\"Flob\"])\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", Match.object_like({\n    \"Fred\": Match.not([\"Flob\", \"Cat\"])\n}))\n```\n\n### Serialized JSON\n\nOften, we find that some CloudFormation Resource types declare properties as a string,\nbut actually expect JSON serialized as a string.\nFor example, the [`BuildSpec` property of `AWS::CodeBuild::Project`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-source.html#cfn-codebuild-project-source-buildspec),\nthe [`Definition` property of `AWS::StepFunctions::StateMachine`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definition),\nto name a couple.\n\nThe `Match.serializedJson()` matcher allows deep matching within a stringified JSON.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Baz\": \"{ \\\"Fred\\\": [\\\"Waldo\\\", \\\"Willow\\\"] }\"\n#       }\n#     }\n#   }\n# }\n\n# The following will NOT throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Baz\": Match.serialized_json({\n        \"Fred\": Match.array_with([\"Waldo\"])\n    })\n})\n\n# The following will throw an assertion error\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Baz\": Match.serialized_json({\n        \"Fred\": [\"Waldo\", \"Johnny\"]\n    })\n})\n```\n\n## Capturing Values\n\nThe matcher APIs documented above allow capturing values in the matching entry\n(Resource, Output, Mapping, etc.). The following code captures a string from a\nmatching resource.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": [\"Flob\", \"Cat\"],\n#         \"Waldo\": [\"Qix\", \"Qux\"],\n#       }\n#     }\n#   }\n# }\n\nfred_capture = Capture()\nwaldo_capture = Capture()\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": fred_capture,\n    \"Waldo\": [\"Qix\", waldo_capture]\n})\n\nfred_capture.as_array() # returns [\"Flob\", \"Cat\"]\nwaldo_capture.as_string()\n```\n\nWith captures, a nested pattern can also be specified, so that only targets\nthat match the nested pattern will be captured. This pattern can be literals or\nfurther Matchers.\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar1\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": [\"Flob\", \"Cat\"],\n#       }\n#     }\n#     \"MyBar2\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": [\"Qix\", \"Qux\"],\n#       }\n#     }\n#   }\n# }\n\ncapture = Capture(Match.array_with([\"Cat\"]))\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": capture\n})\n\ncapture.as_array()\n```\n\nWhen multiple resources match the given condition, each `Capture` defined in\nthe condition will capture all matching values. They can be paged through using\nthe `next()` API. The following example illustrates this -\n\n```python\n# Given a template -\n# {\n#   \"Resources\": {\n#     \"MyBar\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": \"Flob\",\n#       }\n#     },\n#     \"MyBaz\": {\n#       \"Type\": \"Foo::Bar\",\n#       \"Properties\": {\n#         \"Fred\": \"Quib\",\n#       }\n#     }\n#   }\n# }\n\nfred_capture = Capture()\ntemplate.has_resource_properties(\"Foo::Bar\", {\n    \"Fred\": fred_capture\n})\n\nfred_capture.as_string() # returns \"Flob\"\nfred_capture.next() # returns true\nfred_capture.as_string()\n```\n\n## Asserting Annotations\n\nIn addition to template matching, we provide an API for annotation matching.\n[Annotations](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Annotations.html)\ncan be added via the [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html)\nAPI. You can learn more about Aspects [here](https://docs.aws.amazon.com/cdk/v2/guide/aspects.html).\n\nSay you have a `MyAspect` and a `MyStack` that uses `MyAspect`:\n\n```python\nimport aws_cdk.core as cdk\nfrom constructs import Construct, IConstruct\n\nclass MyAspect(cdk.IAspect):\n    def visit(self, node):\n        if node instanceof cdk.CfnResource && node.cfn_resource_type == \"Foo::Bar\":\n            self.error(node, \"we do not want a Foo::Bar resource\")\n\n    def error(self, node, message):\n        cdk.Annotations.of(node).add_error(message)\n\nclass MyStack(cdk.Stack):\n    def __init__(self, scope, id):\n        super().__init__(scope, id)\n\n        stack = cdk.Stack()\n        cdk.CfnResource(stack, \"Foo\",\n            type=\"Foo::Bar\",\n            properties={\n                \"Fred\": \"Thud\"\n            }\n        )\n        cdk.Aspects.of(stack).add(MyAspect())\n```\n\nWe can then assert that the stack contains the expected Error:\n\n```python\n# import { Annotations } from '@aws-cdk/assertions';\n\nAnnotations.from_stack(stack).has_error(\"/Default/Foo\", \"we do not want a Foo::Bar resource\")\n```\n\nHere are the available APIs for `Annotations`:\n\n* `hasError()`, `hasNoError()`, and `findError()`\n* `hasWarning()`, `hasNoWarning()`, and `findWarning()`\n* `hasInfo()`, `hasNoInfo()`, and `findInfo()`\n\nThe corresponding `findXxx()` API is complementary to the `hasXxx()` API, except instead\nof asserting its presence, it returns the set of matching messages.\n\nIn addition, this suite of APIs is compatable with `Matchers` for more fine-grained control.\nFor example, the following assertion works as well:\n\n```python\nAnnotations.from_stack(stack).has_error(\"/Default/Foo\",\n    Match.string_like_regexp(\".*Foo::Bar.*\"))\n```\n\n\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "An assertion library for use with CDK Apps",
    "version": "1.203.0",
    "project_urls": {
        "Homepage": "https://github.com/aws/aws-cdk",
        "Source": "https://github.com/aws/aws-cdk.git"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ac0c5aca86e4866a980fc86faa2617b4bd3e316880bb4992f258273bc2ffb988",
                "md5": "a4c763300ba9a272861f0db31a237c91",
                "sha256": "d4418a0e7fe59237f23f3eecb209d148a36e696768bc57a8cfca6613d58bb283"
            },
            "downloads": -1,
            "filename": "aws_cdk.assertions-1.203.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a4c763300ba9a272861f0db31a237c91",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "~=3.7",
            "size": 161132,
            "upload_time": "2023-05-31T22:52:12",
            "upload_time_iso_8601": "2023-05-31T22:52:12.011463Z",
            "url": "https://files.pythonhosted.org/packages/ac/0c/5aca86e4866a980fc86faa2617b4bd3e316880bb4992f258273bc2ffb988/aws_cdk.assertions-1.203.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8d9815ed2e1c3c2791ad6d81320aaa70ada5bf11c6d38c10541466a7fc6bd01f",
                "md5": "edcd6c5c1b5856c37fea6f8398c2242f",
                "sha256": "f2bc84e0e4b80723d901fc107afbdc02242f6d47d0092e3e8c492e91fa3223cd"
            },
            "downloads": -1,
            "filename": "aws-cdk.assertions-1.203.0.tar.gz",
            "has_sig": false,
            "md5_digest": "edcd6c5c1b5856c37fea6f8398c2242f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "~=3.7",
            "size": 162261,
            "upload_time": "2023-05-31T23:00:17",
            "upload_time_iso_8601": "2023-05-31T23:00:17.672444Z",
            "url": "https://files.pythonhosted.org/packages/8d/98/15ed2e1c3c2791ad6d81320aaa70ada5bf11c6d38c10541466a7fc6bd01f/aws-cdk.assertions-1.203.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-31 23:00:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aws",
    "github_project": "aws-cdk",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "aws-cdk.assertions"
}
        
Elapsed time: 0.65956s