This directory contains test cases for the Crossplane TypeScript function. Test cases can be written in either YAML or JSON format and are automatically loaded by the test suite.
Run all tests including test case files:
npm testRun tests in watch mode during development:
npm test -- --watchEach test case file should define one or more test cases with the following structure:
Test cases support two ways to provide the composite resource input:
-
Using
xrPath(recommended for reusing example files):- Reference an external file containing the composite resource
- Keeps test cases clean and allows reuse of example resources
-
Using
input.observed(inline definition):- Define the composite resource directly in the test case
- Useful for small test cases or when you need full control
---
name: Test Case Name
description: Optional description of what this test validates
# Load the composite resource from an external file
xrPath: examples/apps/example.yaml
expected:
# Expected number of resources to be created
resourceCount: 4
# Expected resource types (partial list)
resourceTypes:
- Deployment
- Service
- ServiceAccount
- Ingress
# Specific resource assertions (partial match) - map format
resources:
deployment:
kind: Deployment
apiVersion: apps/v1
spec:
replicas: 2---
name: Test Case Name
description: Optional description of what this test validates
input:
observed:
composite:
resource:
apiVersion: example.crossplane.io/v1alpha1
kind: App
metadata:
name: test-app
namespace: default
spec:
parameters:
name: test-app
# Optional: Include observed resources with status
resources:
deployment:
resource:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
crossplane.io/composition-resource-name: deployment
name: my-deployment
status:
readyReplicas: 3
expected:
# Expected number of resources to be created
resourceCount: 2
# Expected resource types (partial list)
resourceTypes:
- Deployment
- Pod
# Specific resource assertions (partial match) - map format
resources:
deployment:
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: foo
spec:
replicas: 3
selector:
matchLabels:
app: my-app
pod:
kind: Pod
apiVersion: v1
metadata:
namespace: default
spec:
containers: []
# Expected status fields on the composite resource (optional)
status:
ready: true{
"name": "Test Case Name",
"description": "Optional description",
"xrPath": "examples/apps/example.yaml",
"expected": {
"resourceCount": 4,
"resourceTypes": ["Deployment", "Service", "ServiceAccount", "Ingress"]
}
}{
"name": "Test Case Name",
"description": "Optional description",
"input": {
"observed": {
"composite": {
"resource": {
"apiVersion": "example.crossplane.io/v1alpha1",
"kind": "App",
"metadata": {
"name": "test-app"
},
"spec": {
"parameters": {
"name": "test-app"
}
}
}
}
}
},
"expected": {
"resourceCount": 2,
"resourceTypes": ["Deployment", "Pod"]
}
}The test framework supports several types of assertions:
expected:
resourceCount: 2Validates that exactly 2 resources are created.
expected:
resourceTypes:
- Deployment
- PodValidates that these resource kinds are present in the output (doesn't need to be exhaustive).
Resources are specified as a map where keys are resource names:
expected:
resources:
deployment:
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: foo
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
pod:
kind: Pod
apiVersion: v1
metadata:
namespace: default
spec:
containers: []The test format:
- Mirrors the input structure (consistent with
input.observed.resources) - Makes it easy to reference specific resources by name
- Validates with partial match - only the fields you specify are checked
Test the status of the composition:
expected:
status:
ready: true
message: 'Resources created successfully'Validates the status fields set on the composite resource (partial match).
Observed resources simulate what Crossplane passes to your function when resources already exist in the cluster with status information from the provider. This is useful for testing:
- Status Propagation: Verify that resource status information is correctly handled
- Reconciliation: Test how your function behaves when resources already exist
- Update Scenarios: Simulate updating existing infrastructure
input:
observed:
composite:
resource:
# Your composite resource spec
resources:
deployment:
resource:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
crossplane.io/composition-resource-name: deployment
name: my-deployment
namespace: foo
spec:
replicas: 3
status:
readyReplicas: 3
availableReplicas: 3
expected:
# Verify status handling
status:
ready: trueThis simulates the scenario where:
- Crossplane has already created the Deployment resource
- The Kubernetes API has reconciled it and set the status fields
- Your function receives this observed state and can use it to update the composite status
- Create a new
.yamlor.jsonfile in this directory - Define your test case(s) following the format above
- Run
npm test- the test suite will automatically discover and run your test cases
- Use
xrPathto reference existing example files - this keeps tests clean and promotes reuse - Use inline
inputfor small test cases or when you need to test specific edge cases - Use partial matching to focus on the most important assertions
- Group related test cases in the same file (multiple YAML documents or JSON array)
- Use descriptive names and descriptions to document what each test validates
- Start with simple tests validating resource counts and types, then add more specific assertions
- Test both successful scenarios and error conditions
The test framework provides several helper functions in test-helpers.ts:
loadTestCases(filePath)- Load test cases from YAML or JSONassertTestCase(response, testCase)- Run all assertions for a test caseassertResources(response, expectedResources)- Assert specific resourcesassertStatus(response, expectedStatus)- Assert composite statusassertResourceCount(response, count)- Assert resource countassertResourceTypes(response, types)- Assert resource types exist
You can use these directly in custom tests in function.test.ts.