CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-cdktf

Cloud Development Kit for Terraform - programmatic infrastructure as code using familiar programming languages

Overview
Eval results
Files

testing.mddocs/

Testing Framework

Built-in testing utilities for validating CDKTF applications and infrastructure configurations, providing synthesis testing, construct tree validation, and Jest matcher integration.

Capabilities

Testing Class

Core testing utilities for CDKTF applications, providing synthesis and validation capabilities.

/**
 * Testing utilities for CDKTF applications
 */
class Testing {
  /**
   * Create a test app with sensible defaults
   * @param options - Optional app configuration
   * @returns App instance configured for testing
   */
  static app(options?: TestingAppConfig): App;

  /**
   * Synthesize a stack for testing purposes
   * @param stack - Stack to synthesize
   * @param runValidations - Whether to run validations
   * @returns JSON string of synthesized configuration
   */
  static synth(stack: TerraformStack, runValidations?: boolean): string;

  /**
   * Synthesize a stack to HCL format for testing
   * @param stack - Stack to synthesize
   * @param runValidations - Whether to run validations
   * @param returnMetadata - Whether to include metadata
   * @returns HCL string of synthesized configuration
   */
  static synthHcl(stack: TerraformStack, runValidations?: boolean, returnMetadata?: boolean): string;

  /**
   * Synthesize within a callback scope
   * @param fn - Callback function that creates constructs
   * @returns JSON string of synthesized configuration
   */
  static synthScope(fn: IScopeCallback): string;

  /**
   * Perform full synthesis including all metadata
   * @param stack - Stack to synthesize
   * @returns Complete synthesized output
   */
  static fullSynth(stack: TerraformStack): string;

  /**
   * Render the construct tree structure
   * @param construct - Root construct to render
   * @returns String representation of the tree
   */
  static renderConstructTree(construct: IConstruct): string;

  /**
   * Stub the CDKTF version for consistent testing
   * @param app - App to stub version for
   * @returns Modified app with stubbed version
   */
  static stubVersion(app: App): App;

  /**
   * Enable future flags for testing new features
   * @param app - App to enable flags for
   * @returns Modified app with future flags
   */
  static enableFutureFlags(app: App): App;

  /**
   * Set up fake cdktf.json path for testing
   * @param app - App to configure
   * @returns Modified app with fake path
   */
  static fakeCdktfJsonPath(app: App): App;

  /**
   * Setup Jest matchers for CDKTF testing
   */
  static setupJest(): void;

  // Testing Matcher Methods
  static toHaveDataSourceWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
  static toHaveDataSource(received: string, resourceType: string): boolean;
  static toHaveResourceWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
  static toHaveResource(received: string, resourceType: string): boolean;
  static toHaveProviderWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
  static toHaveProvider(received: string, resourceType: string): boolean;
  static toBeValidTerraform(received: string): boolean;
}

Usage Examples:

import { Testing, TerraformStack } from "cdktf";
import { Construct } from "constructs";
import { AwsInstance } from "../.gen/providers/aws/instance";

describe("Infrastructure Tests", () => {
  let app: App;
  let stack: TerraformStack;

  beforeEach(() => {
    app = Testing.app();
    stack = new TerraformStack(app, "test-stack");
  });

  test("synthesizes valid terraform", () => {
    // Create resources in the stack
    new AwsInstance(stack, "instance", {
      ami: "ami-12345678",
      instanceType: "t2.micro"
    });

    // Synthesize and validate
    const synthesized = Testing.synth(stack);
    expect(synthesized).toMatchSnapshot();
  });

  test("generates correct HCL", () => {
    new AwsInstance(stack, "instance", {
      ami: "ami-12345678",
      instanceType: "t2.micro"
    });

    const hcl = Testing.synthHcl(stack);
    expect(hcl).toContain('resource "aws_instance" "instance"');
  });
});

Jest Matchers

CDKTF-specific Jest matchers for testing synthesized infrastructure configurations.

/**
 * Jest matcher to check if synthesized config contains a resource
 * @param received - Synthesized JSON string
 * @param resourceType - Terraform resource type
 * @returns Matcher result
 */
function toHaveResource(received: string, resourceType: string): boolean;

/**
 * Jest matcher to check if synthesized config contains a resource with specific properties
 * @param received - Synthesized JSON string
 * @param resourceType - Terraform resource type
 * @param properties - Expected properties object
 * @returns Matcher result
 */
function toHaveResourceWithProperties(
  received: string,
  resourceType: string,
  properties: Record<string, any>
): boolean;

/**
 * Jest matcher to check if synthesized config contains a data source
 * @param received - Synthesized JSON string
 * @param dataSourceType - Terraform data source type
 * @returns Matcher result
 */
function toHaveDataSource(received: string, dataSourceType: string): boolean;

/**
 * Jest matcher to check if synthesized config contains a data source with specific properties
 * @param received - Synthesized JSON string
 * @param dataSourceType - Terraform data source type
 * @param properties - Expected properties object
 * @returns Matcher result
 */
function toHaveDataSourceWithProperties(
  received: string,
  dataSourceType: string,
  properties: Record<string, any>
): boolean;

/**
 * Jest matcher to check if synthesized config contains a provider
 * @param received - Synthesized JSON string
 * @param providerType - Terraform provider type
 * @returns Matcher result
 */
function toHaveProvider(received: string, providerType: string): boolean;

/**
 * Jest matcher to check if synthesized config contains a provider with specific properties
 * @param received - Synthesized JSON string
 * @param providerType - Terraform provider type
 * @param properties - Expected properties object
 * @returns Matcher result
 */
function toHaveProviderWithProperties(
  received: string,
  providerType: string,
  properties: Record<string, any>
): boolean;

/**
 * Jest matcher to validate that the synthesized config is valid Terraform
 * @param received - Synthesized JSON string
 * @returns Matcher result
 */
function toBeValidTerraform(received: string): boolean;

Usage Examples:

import { Testing, TerraformStack } from "cdktf";
import { AwsProvider } from "../.gen/providers/aws/provider";
import { AwsInstance } from "../.gen/providers/aws/instance";
import { DataAwsAmi } from "../.gen/providers/aws/data-aws-ami";

// Setup Jest matchers
Testing.setupJest();

describe("Resource Testing", () => {
  test("creates correct resources", () => {
    const app = Testing.app();
    const stack = new TerraformStack(app, "test");

    new AwsProvider(stack, "aws", {
      region: "us-west-2"
    });

    new AwsInstance(stack, "web", {
      ami: "ami-12345678",
      instanceType: "t2.micro",
      tags: {
        Name: "web-server"
      }
    });

    const synthesized = Testing.synth(stack);

    // Test using CDKTF matchers
    expect(synthesized).toHaveProvider("aws");
    expect(synthesized).toHaveProviderWithProperties("aws", {
      region: "us-west-2"
    });

    expect(synthesized).toHaveResource("aws_instance");
    expect(synthesized).toHaveResourceWithProperties("aws_instance", {
      instance_type: "t2.micro",
      tags: {
        Name: "web-server"
      }
    });

    expect(synthesized).toBeValidTerraform();
  });

  test("includes data sources", () => {
    const app = Testing.app();
    const stack = new TerraformStack(app, "test");

    new DataAwsAmi(stack, "ubuntu", {
      mostRecent: true,
      owners: ["099720109477"]
    });

    const synthesized = Testing.synth(stack);
    expect(synthesized).toHaveDataSource("aws_ami");
  });
});

Test Utilities

Additional utilities for testing complex CDKTF applications.

/**
 * Callback function for scope-based synthesis
 */
interface IScopeCallback {
  (scope: Construct): void;
}

/**
 * Configuration for test apps
 */
interface TestingAppConfig extends AppConfig {
  /**
   * Whether to enable stack traces in test mode
   * @default false
   */
  readonly enableStackTrace?: boolean;

  /**
   * Fake values to use for context
   */
  readonly fakeContext?: {[key: string]: any};
}

/**
 * Assertion helpers for construct tree testing
 */
class ConstructTreeAssertion {
  /**
   * Assert that a construct exists in the tree
   * @param tree - Construct tree string
   * @param path - Path to the construct
   */
  static hasConstruct(tree: string, path: string): boolean;

  /**
   * Assert construct count at a specific level
   * @param tree - Construct tree string
   * @param level - Tree level to check
   * @param count - Expected count
   */
  static hasConstructCount(tree: string, level: number, count: number): boolean;
}

Usage Examples:

import { Testing, ConstructTreeAssertion } from "cdktf";

test("construct tree structure", () => {
  const app = Testing.app();
  const stack = new TerraformStack(app, "test");

  // Add some constructs
  new AwsInstance(stack, "web1", { /* config */ });
  new AwsInstance(stack, "web2", { /* config */ });

  const tree = Testing.renderConstructTree(app);

  expect(ConstructTreeAssertion.hasConstruct(tree, "test/web1")).toBe(true);
  expect(ConstructTreeAssertion.hasConstruct(tree, "test/web2")).toBe(true);
  expect(ConstructTreeAssertion.hasConstructCount(tree, 2, 2)).toBe(true);
});

test("synthesis with callback", () => {
  const synthesized = Testing.synthScope((scope) => {
    new TerraformOutput(scope, "test-output", {
      value: "test-value"
    });
  });

  expect(synthesized).toContain('"test-output"');
  expect(synthesized).toContain('"test-value"');
});

Install with Tessl CLI

npx tessl i tessl/npm-cdktf

docs

annotations-aspects.md

backend-configuration.md

core-infrastructure.md

index.md

iterators-dynamic.md

providers-modules.md

provisioners.md

resources-data-sources.md

terraform-functions.md

testing.md

tokens-expressions.md

variables-outputs.md

tile.json