Skip to main content

Quick Start

This guide walks you through your first contract test in under 5 minutes.

Prerequisites

  • CVT server running (see Installation)
  • An OpenAPI schema to test against (we'll use the included Petstore schema)

You can either:

  • Save the Petstore OpenAPI schema as ./openapi.json in your project directory, OR
  • Use the URL directly: https://petstore3.swagger.io/api/v3/openapi.json

All registerSchema methods accept both file paths and URLs. The examples below use a local file path, but you can substitute a URL.

Step 1: Start the Server

# Using the published Docker image (recommended)
docker run -d -p 9550:9550 -p 9551:9551 ghcr.io/sahina/cvt:latest

# Or using Docker Compose (if you've cloned the repository)
make up

# Or build and run locally
make run-server

Verify it's running:

curl http://localhost:9551/metrics
# Should return Prometheus metrics
Producer vs Consumer

In a team environment, the producer (API owner) registers their OpenAPI schema with the shared CVT server, and consumers validate against it. In this Quick Start, we combine both steps for simplicity. See the CI/CD Integration Guide for the recommended production workflow.

Step 2: Create a Simple Test

Create a test file contract.test.ts:

import { ContractValidator } from "@sahina/cvt-sdk";
import * as path from "path";

describe("Petstore API Contract", () => {
let validator: ContractValidator;

beforeAll(async () => {
validator = new ContractValidator("localhost:9550");

// Register the Petstore schema from file
const schemaPath = path.resolve(__dirname, "./openapi.json");
await validator.registerSchema("petstore", schemaPath);
// Or register from URL:
// await validator.registerSchema('petstore', 'https://petstore3.swagger.io/api/v3/openapi.json');
});

afterAll(() => validator.close());

it("validates a correct pet response", async () => {
const result = await validator.validate(
{ method: "GET", path: "/pet/123" },
{
statusCode: 200,
body: {
id: 123,
name: "doggie",
photoUrls: ["https://example.com/photo.jpg"],
status: "available",
},
},
);

expect(result.valid).toBe(true);
});

it("catches invalid responses", async () => {
const result = await validator.validate(
{ method: "GET", path: "/pet/123" },
{
statusCode: 200,
body: { id: 123 }, // missing required 'name' and 'photoUrls' fields
},
);

expect(result.valid).toBe(false);
expect(result.errors.length).toBeGreaterThan(0);
});
});

Run the test:

npm test

Step 3: Use the CLI

For quick validations without code:

# Build the CLI
go build -o cvt ./cmd/cvt

# Create request and response files
cat > request.json << 'EOF'
{
"method": "GET",
"path": "/pet/123"
}
EOF

cat > response.json << 'EOF'
{
"status_code": 200,
"body": "{\"id\": 123, \"name\": \"doggie\", \"photoUrls\": [\"https://example.com/photo.jpg\"], \"status\": \"available\"}"
}
EOF

# Validate the interaction
cvt validate --schema openapi.json --request request.json --response response.json

What's Next?

Now that you've validated your first interaction, explore:

Common Patterns

Loading Schema from URL

// Register schema directly from URL
await validator.registerSchema(
"petstore",
"https://petstore3.swagger.io/api/v3/openapi.json",
);

Using HTTP Adapters

Automatically validate all HTTP traffic:

import axios from "axios";
import { createAxiosAdapter } from "@sahina/cvt-sdk/adapters";

const api = axios.create({ baseURL: "http://api.example.com" });
const adapter = createAxiosAdapter({
axios: api,
validator,
autoValidate: true,
});

// All requests/responses are now validated automatically
const pet = await api.get("/pet/123");

// Check validation results
const interactions = adapter.getInteractions();
console.log(interactions[0].validationResult?.valid);

Registering as a Consumer

Enable deployment safety checks:

await validator.registerConsumer({
consumerId: "my-service",
consumerVersion: "1.0.0",
schemaId: "petstore",
schemaVersion: "1.0.0",
environment: "dev",
usedEndpoints: [
{
method: "GET",
path: "/pet/{petId}",
usedFields: ["id", "name", "status"],
},
],
});