@cdktn/vitest 0.0.0 → 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cdktn-io
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/NOTICE ADDED
@@ -0,0 +1,21 @@
1
+ @cdktn/vitest
2
+ Copyright (c) 2026 cdktn-io
3
+
4
+ This product includes software designed by, and adapts the public API of, the
5
+ following MIT-licensed projects:
6
+
7
+ - cdktn-vitest (https://www.npmjs.com/package/cdktn-vitest)
8
+ Copyright (c) Aníbal Jorquera <ajorquera.cornejo@gmail.com>
9
+ The single-export `setupVitest()` API and the Vitest `passEvaluation`
10
+ predicate mirror this package's design. This is a clean reimplementation in
11
+ TypeScript; no compiled artifacts from the original are distributed here.
12
+
13
+ - cdktf-vitest (https://www.npmjs.com/package/cdktf-vitest)
14
+ Copyright (c) Daniel Grefberg <hello@danielgrefberg.com>
15
+ The original (now deprecated) Vitest matchers adapter for HashiCorp's CDKTF,
16
+ from which the cdktn variant was derived.
17
+
18
+ The matcher *logic* (resource/data-source/provider assertions, Terraform
19
+ validation) is provided by CDK Terrain (cdktn) core via its exported
20
+ `testingMatchers`. This package is a thin Vitest adapter over that logic,
21
+ mirroring cdktn core's built-in Jest adapter (`setupJest()`).
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # @cdktn/vitest
2
+
3
+ Vitest matchers for [CDK Terrain (cdktn)](https://cdktn.io).
4
+
5
+ `cdktn` ships [Jest matchers](https://cdktn.io/docs/test/unit-tests#write-assertions)
6
+ out of the box but no Vitest adapter. This package fills that gap: it registers
7
+ the same assertion logic cdktn core exposes (`testingMatchers`) onto Vitest's
8
+ `expect`, mirroring cdktn's built-in Jest adapter (`setupJest()`).
9
+
10
+ It is the org-owned, provenance-signed successor to the third-party
11
+ `cdktn-vitest` package — same public API (`setupVitest()`), published under the
12
+ `@cdktn` scope.
13
+
14
+ > **Long-term direction:** the goal is to fold a Vitest adapter directly into
15
+ > cdktn core as `cdktn/lib/testing/adapters/vitest` (mirroring the Jest adapter)
16
+ > and deprecate this standalone package. Tracking issue:
17
+ > [open-constructs/cdk-terrain#289](https://github.com/open-constructs/cdk-terrain/issues/289).
18
+ > Until core ships that, `@cdktn/vitest` is the supported path.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pnpm add -D @cdktn/vitest
24
+ # or: npm install -D @cdktn/vitest
25
+ ```
26
+
27
+ `cdktn` and `vitest` are peer dependencies:
28
+
29
+ - `cdktn >= 0.23.0`
30
+ - `vitest >= 2.1.0`
31
+
32
+ ## Setup
33
+
34
+ ### 1. Register the matchers
35
+
36
+ Create a Vitest setup file that calls `setupVitest()`:
37
+
38
+ ```ts
39
+ // vitest.setup.ts
40
+ import { setupVitest } from "@cdktn/vitest";
41
+
42
+ setupVitest();
43
+ ```
44
+
45
+ ### 2. Wire it into your Vitest config
46
+
47
+ ```ts
48
+ // vitest.config.ts
49
+ import { defineConfig } from "vitest/config";
50
+
51
+ export default defineConfig({
52
+ test: {
53
+ setupFiles: ["./vitest.setup.ts"],
54
+ },
55
+ });
56
+ ```
57
+
58
+ ### 3. Enable the matcher types
59
+
60
+ Add the package to your `tsconfig.json` so the matchers are typed on `expect`:
61
+
62
+ ```json
63
+ {
64
+ "compilerOptions": {
65
+ "types": ["@cdktn/vitest"]
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Available matchers
71
+
72
+ | Matcher | Asserts that the synthesized stack… |
73
+ | --- | --- |
74
+ | `toHaveResource(resource)` | contains a resource of the given type |
75
+ | `toHaveResourceWithProperties(resource, props)` | contains a matching resource with the given properties |
76
+ | `toHaveDataSource(dataSource)` | contains a data source of the given type |
77
+ | `toHaveDataSourceWithProperties(dataSource, props)` | contains a matching data source with the given properties |
78
+ | `toHaveProvider(provider)` | configures the given provider |
79
+ | `toHaveProviderWithProperties(provider, props)` | configures the given provider with the given properties |
80
+ | `toBeValidTerraform()` | passes `terraform validate` (requires the `terraform` CLI) |
81
+ | `toPlanSuccessfully()` | passes `terraform plan` (requires the `terraform` CLI) |
82
+
83
+ Property matchers use subset (`objectContaining`) semantics — the resource may
84
+ have additional properties beyond those asserted.
85
+
86
+ ## Example
87
+
88
+ ```ts
89
+ import { describe, expect, it } from "vitest";
90
+ import { Testing } from "cdktn";
91
+ import { MyStack } from "./my-stack";
92
+
93
+ describe("MyStack", () => {
94
+ it("creates the bucket with the right name", () => {
95
+ const synthesized = Testing.synth(new MyStack(Testing.app(), "test"));
96
+
97
+ expect(synthesized).toHaveResourceWithProperties(S3Bucket, {
98
+ bucket: "my-bucket",
99
+ });
100
+ });
101
+ });
102
+ ```
103
+
104
+ > `toBeValidTerraform()` / `toPlanSuccessfully()` operate on a synthesized
105
+ > output **directory** (containing `manifest.json`) and shell out to the
106
+ > `terraform` CLI, so they require Terraform to be installed.
107
+
108
+ ## Credits
109
+
110
+ This is a clean-room TypeScript reimplementation that mirrors the public API of
111
+ the MIT-licensed [`cdktn-vitest`](https://www.npmjs.com/package/cdktn-vitest) by
112
+ Aníbal Jorquera, itself derived from
113
+ [`cdktf-vitest`](https://www.npmjs.com/package/cdktf-vitest) by Daniel Grefberg.
114
+ See [`NOTICE`](./NOTICE).
115
+
116
+ ## License
117
+
118
+ [MIT](./LICENSE)
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./matcher/index.js";
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./matcher/index.js";
@@ -0,0 +1,2 @@
1
+ export * from "./matcher.js";
2
+ export * from "./matcher.types.js";
@@ -0,0 +1,2 @@
1
+ export * from "./matcher.js";
2
+ export * from "./matcher.types.js";
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Register the cdktn Vitest matchers on the global `expect`.
3
+ *
4
+ * Call this once from a Vitest setup file:
5
+ *
6
+ * ```ts
7
+ * // vitest.setup.ts
8
+ * import { setupVitest } from "@cdktn/vitest";
9
+ * setupVitest();
10
+ * ```
11
+ *
12
+ * The matchers delegate to cdktn core's `testingMatchers`, the same logic the
13
+ * built-in Jest adapter uses, wired to a Vitest `passEvaluation`.
14
+ */
15
+ export declare const setupVitest: () => void;
@@ -0,0 +1,50 @@
1
+ import { testingMatchers } from "cdktn";
2
+ import { expect } from "vitest";
3
+ import { parseResult, passEvaluation } from "./matcher.utils.js";
4
+ /**
5
+ * Register the cdktn Vitest matchers on the global `expect`.
6
+ *
7
+ * Call this once from a Vitest setup file:
8
+ *
9
+ * ```ts
10
+ * // vitest.setup.ts
11
+ * import { setupVitest } from "@cdktn/vitest";
12
+ * setupVitest();
13
+ * ```
14
+ *
15
+ * The matchers delegate to cdktn core's `testingMatchers`, the same logic the
16
+ * built-in Jest adapter uses, wired to a Vitest `passEvaluation`.
17
+ */
18
+ export const setupVitest = () => {
19
+ // Build the property-aware matchers once with our Vitest predicate, then
20
+ // reuse them across every matcher invocation.
21
+ const toHaveResourceWithProperties = testingMatchers.getToHaveResourceWithProperties(passEvaluation);
22
+ const toHaveDataSourceWithProperties = testingMatchers.getToHaveDataSourceWithProperties(passEvaluation);
23
+ const toHaveProviderWithProperties = testingMatchers.getToHaveProviderWithProperties(passEvaluation);
24
+ expect.extend({
25
+ toHaveResource(received, resource) {
26
+ return parseResult(toHaveResourceWithProperties(received, resource, {}));
27
+ },
28
+ toHaveResourceWithProperties(received, resource, properties) {
29
+ return parseResult(toHaveResourceWithProperties(received, resource, properties));
30
+ },
31
+ toHaveDataSource(received, dataSourceConstructor) {
32
+ return parseResult(toHaveDataSourceWithProperties(received, dataSourceConstructor, {}));
33
+ },
34
+ toHaveDataSourceWithProperties(received, dataSourceConstructor, properties) {
35
+ return parseResult(toHaveDataSourceWithProperties(received, dataSourceConstructor, properties));
36
+ },
37
+ toHaveProvider(received, providerConstructor) {
38
+ return parseResult(toHaveProviderWithProperties(received, providerConstructor, {}));
39
+ },
40
+ toHaveProviderWithProperties(received, providerConstructor, properties) {
41
+ return parseResult(toHaveProviderWithProperties(received, providerConstructor, properties));
42
+ },
43
+ toBeValidTerraform(received) {
44
+ return parseResult(testingMatchers.toBeValidTerraform(received));
45
+ },
46
+ toPlanSuccessfully(received) {
47
+ return parseResult(testingMatchers.toPlanSuccessfully(received));
48
+ },
49
+ });
50
+ };
@@ -0,0 +1,29 @@
1
+ import "vitest";
2
+ import type { testingMatchers } from "cdktn";
3
+ type TerraformConstructor = testingMatchers.TerraformConstructor;
4
+ /**
5
+ * Ambient typing for the cdktn matchers registered by {@link setupVitest}.
6
+ *
7
+ * Consumers opt in by adding this package to their tsconfig:
8
+ *
9
+ * ```json
10
+ * { "compilerOptions": { "types": ["@cdktn/vitest"] } }
11
+ * ```
12
+ */
13
+ export interface CdktnVitestMatchers<R = unknown> {
14
+ toHaveResource(resource: TerraformConstructor): R;
15
+ toHaveResourceWithProperties(resource: TerraformConstructor, properties: Record<string, any>): R;
16
+ toHaveDataSource(dataSourceConstructor: TerraformConstructor): R;
17
+ toHaveDataSourceWithProperties(dataSourceConstructor: TerraformConstructor, properties: Record<string, any>): R;
18
+ toHaveProvider(providerConstructor: TerraformConstructor): R;
19
+ toHaveProviderWithProperties(providerConstructor: TerraformConstructor, properties: Record<string, any>): R;
20
+ toBeValidTerraform(): R;
21
+ toPlanSuccessfully(): R;
22
+ }
23
+ declare module "vitest" {
24
+ interface Assertion<T = any> extends CdktnVitestMatchers<T> {
25
+ }
26
+ interface AsymmetricMatchersContaining extends CdktnVitestMatchers {
27
+ }
28
+ }
29
+ export {};
@@ -0,0 +1 @@
1
+ import "vitest";
@@ -0,0 +1,18 @@
1
+ import type { testingMatchers } from "cdktn";
2
+ /**
3
+ * Predicate handed to cdktn's core matchers to decide whether a collection of
4
+ * synthesized items contains one matching the asserted properties.
5
+ *
6
+ * This mirrors the role of the Jest adapter's predicate in cdktn core, but is
7
+ * built on Vitest's asymmetric matchers. An empty property set degrades to a
8
+ * pure existence check.
9
+ */
10
+ export declare const passEvaluation: (items: any, assertedProperties: Record<string, any>) => boolean;
11
+ /**
12
+ * Translate cdktn's `AssertionReturn` ({ message, pass }) into the shape Vitest
13
+ * expects a matcher to return (message as a thunk).
14
+ */
15
+ export declare const parseResult: (result: testingMatchers.AssertionReturn) => {
16
+ message: () => string;
17
+ pass: boolean;
18
+ };
@@ -0,0 +1,32 @@
1
+ import { expect } from "vitest";
2
+ /**
3
+ * Predicate handed to cdktn's core matchers to decide whether a collection of
4
+ * synthesized items contains one matching the asserted properties.
5
+ *
6
+ * This mirrors the role of the Jest adapter's predicate in cdktn core, but is
7
+ * built on Vitest's asymmetric matchers. An empty property set degrades to a
8
+ * pure existence check.
9
+ */
10
+ export const passEvaluation = (items, assertedProperties) => {
11
+ if (Object.entries(assertedProperties).length === 0) {
12
+ return items.length > 0;
13
+ }
14
+ // `expect().toEqual()` throws on mismatch; we translate that into a boolean.
15
+ // This is more robust across Vitest versions than poking at the asymmetric
16
+ // matcher's semi-internal `asymmetricMatch()` method.
17
+ try {
18
+ expect(items).toEqual(expect.arrayContaining([expect.objectContaining(assertedProperties)]));
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ };
25
+ /**
26
+ * Translate cdktn's `AssertionReturn` ({ message, pass }) into the shape Vitest
27
+ * expects a matcher to return (message as a thunk).
28
+ */
29
+ export const parseResult = (result) => ({
30
+ message: () => result.message,
31
+ pass: result.pass,
32
+ });
package/package.json CHANGED
@@ -1,9 +1,59 @@
1
1
  {
2
2
  "name": "@cdktn/vitest",
3
- "version": "0.0.0",
4
- "description": "Placeholder reserving @cdktn/vitest real release published via GitHub Actions OIDC trusted publishing.",
3
+ "version": "0.1.0",
4
+ "description": "Vitest matchers for CDK Terrain (cdktn)",
5
5
  "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./lib/index.d.ts",
10
+ "default": "./lib/index.js"
11
+ }
12
+ },
13
+ "main": "./lib/index.js",
14
+ "types": "./lib/index.d.ts",
15
+ "files": [
16
+ "lib",
17
+ "NOTICE"
18
+ ],
19
+ "keywords": [
20
+ "cdktn",
21
+ "cdk-terrain",
22
+ "vitest",
23
+ "terraform",
24
+ "opentofu",
25
+ "testing",
26
+ "matchers"
27
+ ],
28
+ "homepage": "https://github.com/cdktn-io/cdktn-vitest#readme",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/cdktn-io/cdktn-vitest.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/cdktn-io/cdktn-vitest/issues"
35
+ },
36
+ "packageManager": "pnpm@11.9.0",
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "test": "vitest run",
40
+ "lint": "biome check .",
41
+ "format": "biome format --write .",
42
+ "prepublishOnly": "pnpm build"
43
+ },
44
+ "peerDependencies": {
45
+ "cdktn": ">= 0.23.0",
46
+ "vitest": ">= 2.1.0"
47
+ },
48
+ "devDependencies": {
49
+ "@biomejs/biome": "2.4.2",
50
+ "cdktn": "^0.23.3",
51
+ "constructs": "^10.4.2",
52
+ "typescript": "^5.9.2",
53
+ "vitest": "^4.0.0"
54
+ },
6
55
  "publishConfig": {
7
- "access": "public"
56
+ "access": "public",
57
+ "provenance": true
8
58
  }
9
59
  }