@liflig/cdk-snapshot 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/package.json +101 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Liflig
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # @liflig/cdk-snapshot
2
+
3
+ [![npm](https://img.shields.io/npm/v/@liflig/cdk-snapshot.svg)](https://www.npmjs.com/package/@liflig/cdk-snapshot)
4
+ [![ci](https://github.com/capralifecycle/cdk-snapshot/actions/workflows/ci.yml/badge.svg)](https://github.com/capralifecycle/cdk-snapshot/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/@liflig/cdk-snapshot.svg)](LICENSE)
6
+
7
+ Normalizes synthesized AWS CDK stacks for snapshot testing by stripping values such as asset hashes, bootstrap parameters, Lambda version suffixes and more, in order to produce more stable and usable snapshot files.
8
+
9
+ The library provides a generic implementation with a thin adapter per test runner: `node:test`, Bun, Vitest and Jest. Everything is built around one pure function, `cdkTemplate`, which turns a stack into a normalized template object; each adapter wraps that function in whatever the runner's own snapshot assertion looks like. All four write the same snapshot bodies — only the file header differs — so the same `.snap` files stay valid if a project switches runner.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ bun add -d @liflig/cdk-snapshot
15
+ ```
16
+
17
+ `aws-cdk-lib` and `constructs` are peer dependencies. The package is ESM; CommonJS test files can `require()` it on Node 22.12 or later.
18
+
19
+ ## Usage
20
+
21
+ Import the entry point for your runner. Jest, Vitest and Bun get a `toMatchCdkSnapshot` matcher; `node:test` has no `expect` at the time of writing, so it calls `cdkTemplate` directly.
22
+
23
+ ### node:test
24
+
25
+ `configureCdkSnapshots()` points `node:test` at `__snapshots__/*.snap` and the shared serializer. Call it once, before any test runs. It replaces the default serializer for _every_ snapshot in the run, not just CDK ones, so snapshots taken elsewhere in the same project will be reformatted.
26
+
27
+ ```js
28
+ import test from "node:test";
29
+ import { cdkTemplate, configureCdkSnapshots } from "@liflig/cdk-snapshot/node";
30
+
31
+ configureCdkSnapshots();
32
+
33
+ test("my stack", (t) => {
34
+ t.assert.snapshot(cdkTemplate(stack, { ignoreAssets: true }));
35
+ });
36
+ ```
37
+
38
+ Write snapshots with `node --test --test-update-snapshots`.
39
+
40
+ ### Bun
41
+
42
+ ```js
43
+ import { expect, test } from "bun:test";
44
+ import "@liflig/cdk-snapshot/bun";
45
+
46
+ test("my stack", () => {
47
+ expect(stack).toMatchCdkSnapshot({ ignoreAssets: true });
48
+ });
49
+ ```
50
+
51
+ ### Vitest
52
+
53
+ ```js
54
+ import { expect, test } from "vitest";
55
+ import "@liflig/cdk-snapshot/vitest";
56
+
57
+ test("my stack", () => {
58
+ expect(stack).toMatchCdkSnapshot({ ignoreAssets: true });
59
+ });
60
+ ```
61
+
62
+ ### Jest
63
+
64
+ ```js
65
+ import "@liflig/cdk-snapshot/jest";
66
+
67
+ test("my stack", () => {
68
+ expect(stack).toMatchCdkSnapshot({ ignoreAssets: true });
69
+ });
70
+ ```
71
+
72
+ The Jest entry point uses the global `expect`, so it throws on import if Jest is configured with `injectGlobals: false`.
73
+
74
+ The matcher also accepts `propertyMatchers`, forwarded to the runner's own snapshot assertion for values the normalizations do not cover:
75
+
76
+ ```js
77
+ expect(stack).toMatchCdkSnapshot({
78
+ propertyMatchers: { Resources: expect.any(Object) },
79
+ });
80
+ ```
81
+
82
+ Every entry point also exports `cdkTemplate(stack, options)`. Reach for it to assert on the template without a snapshot. It leaves the stack untouched, so one stack can be synthesized repeatedly with different options.
83
+
84
+ `toMatchCdkSnapshot` cannot be negated; `.not` throws rather than silently passing.
85
+
86
+ ## Options
87
+
88
+ | Option | Default | Effect |
89
+ | ------------------------ | ------------- | ----------------------------------------------------------------------------------- |
90
+ | `ignoreAssets` | `false` | Replaces Lambda `Code`, container `Image` and the whole `Parameters` block with `Any<Object>` |
91
+ | `ignoreBootstrapVersion` | `true` | Drops the `BootstrapVersion` parameter and its check rule |
92
+ | `ignoreCurrentVersion` | `false` | Masks the content hash on Lambda `CurrentVersion` logical IDs |
93
+ | `ignoreMetadata` | `false` | Drops template and resource `Metadata` |
94
+ | `ignoreTags` | `false` | Drops `Tags` from resource properties |
95
+ | `ignorePipelineAssets` | `false` | Masks asset paths and IDs in CDK Pipelines `cdk-assets` commands |
96
+ | `subsetResourceTypes` | — | Keeps only resources of these CloudFormation types |
97
+ | `subsetResourceKeys` | — | Keeps only resources with these logical IDs |
98
+ | `assetPlaceholder` | `anyObject` | Token substituted for asset-derived values |
99
+ | `propertyMatchers` | — | Matchers forwarded to the runner's snapshot assertion (matcher only) |
100
+
101
+ `subsetResourceTypes` and `subsetResourceKeys` intersect: given both, a resource is kept only if it matches both.
102
+
103
+ `ignoreAssets` replaces the entire `Parameters` block rather than the individual asset parameters, matching what jest-cdk-snapshot does.
104
+
105
+ `anyObject` is exported from the package root. It is an asymmetric matcher that serializes as `Any<Object>` and matches any non-null object. The Bun entry point substitutes `expect.any(Object)` instead, because Bun's serializer only recognizes matchers built by its own `expect`.
106
+
107
+ ## Development
108
+
109
+ ```sh
110
+ make build # install, format, typecheck, refresh snapshots, test
111
+ make ci # what the CI workflow runs: refuses a stale lockfile, fails on an uncommitted snapshot change
112
+ ```
113
+
114
+ `make snapshots` regenerates the unit snapshots plus the shared fixture under all four runners, which `test/compat.test.ts` then compares against each other.
115
+
116
+ ## Migrating from jest-cdk-snapshot
117
+
118
+ Change the import. Call sites and `.snap` files stay as they are, since the options, their defaults and the serialization all match.
119
+
120
+ ```diff
121
+ -import "jest-cdk-snapshot"
122
+ +import "@liflig/cdk-snapshot/jest"
123
+ ```
124
+
125
+ Verified against liflig-cdk (64 snapshots) and cdk-cloudfront-auth: every snapshot passes under `jest --ci`, and a forced `--updateSnapshot` rewrites nothing.
126
+
127
+ Two of its options are gone. `yaml` is not supported, so a project snapshotting YAML has to regenerate as JSON. The no-op synthesis options it inherited from `StageSynthesisOptions` — `skipValidation`, `validateOnSynthesis`, `force` — are rejected by the type checker instead of warned about at runtime; delete them.
128
+
129
+ ## License
130
+
131
+ MIT, see [LICENSE](LICENSE).
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "@liflig/cdk-snapshot",
3
+ "version": "0.0.1",
4
+ "description": "Normalizes synthesized AWS CDK stacks for snapshot testing",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Liflig",
8
+ "engines": {
9
+ "node": ">=22.12.0"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/capralifecycle/cdk-snapshot.git"
14
+ },
15
+ "homepage": "https://github.com/capralifecycle/cdk-snapshot#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/capralifecycle/cdk-snapshot/issues"
18
+ },
19
+ "keywords": [
20
+ "aws",
21
+ "cdk",
22
+ "cloudformation",
23
+ "snapshot",
24
+ "snapshot-testing",
25
+ "testing",
26
+ "jest",
27
+ "vitest",
28
+ "bun",
29
+ "node-test"
30
+ ],
31
+ "main": "./lib/index.js",
32
+ "types": "./lib/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./lib/index.d.ts",
36
+ "import": "./lib/index.js",
37
+ "default": "./lib/index.js"
38
+ },
39
+ "./bun": {
40
+ "types": "./lib/bun.d.ts",
41
+ "import": "./lib/bun.js",
42
+ "default": "./lib/bun.js"
43
+ },
44
+ "./jest": {
45
+ "types": "./lib/jest.d.ts",
46
+ "import": "./lib/jest.js",
47
+ "default": "./lib/jest.js"
48
+ },
49
+ "./node": {
50
+ "types": "./lib/node.d.ts",
51
+ "import": "./lib/node.js",
52
+ "default": "./lib/node.js"
53
+ },
54
+ "./vitest": {
55
+ "types": "./lib/vitest.d.ts",
56
+ "import": "./lib/vitest.js",
57
+ "default": "./lib/vitest.js"
58
+ },
59
+ "./package.json": "./package.json"
60
+ },
61
+ "files": [
62
+ "lib/**/*"
63
+ ],
64
+ "scripts": {
65
+ "build": "tsc",
66
+ "test": "bun test ./test",
67
+ "snapshots": "bun test ./test --update-snapshots",
68
+ "typecheck": "tsc -p tsconfig.check.json",
69
+ "check": "biome ci && bun run typecheck",
70
+ "fix": "biome check --write",
71
+ "semantic-release": "semantic-release"
72
+ },
73
+ "peerDependencies": {
74
+ "aws-cdk-lib": "^2.0.0",
75
+ "constructs": "^10.0.0",
76
+ "vitest": ">=4"
77
+ },
78
+ "peerDependenciesMeta": {
79
+ "vitest": {
80
+ "optional": true
81
+ }
82
+ },
83
+ "dependencies": {
84
+ "pretty-format": "^29.7.0"
85
+ },
86
+ "devDependencies": {
87
+ "@biomejs/biome": "2.5.10",
88
+ "@types/bun": "1.4.0",
89
+ "@types/jest": "30.0.0",
90
+ "@types/node": "24.13.3",
91
+ "aws-cdk-lib": "2.266.0",
92
+ "constructs": "10.8.1",
93
+ "jest": "30.4.2",
94
+ "semantic-release": "25.0.9",
95
+ "typescript": "7.0.2",
96
+ "vitest": "4.1.11"
97
+ },
98
+ "publishConfig": {
99
+ "access": "public"
100
+ }
101
+ }