FeaturesTemplatesShowcaseTownie
AI
BlogDocsPricing
Log inSign up
c15r
c15rChat
Public
Like
Chat
Home
Code
12
backend
1
frontend
6
shared
1
test
4
IMPLEMENTATION-SUMMARY.md
NextSteps-Examples.md
NextSteps-README.md
README.md
ResourceViewer-README.md
TESTING.md
package.json
H
test-runner.ts
Branches
2
Pull requests
Remixes
1
History
Environment variables
Settings
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in miliseconds.
Sign up now
Code
/
TESTING.md
Code
/
TESTING.md
Search
…
TESTING.md

Testing Guide

This document provides comprehensive guidance for testing the Anthropic Streaming Chat MCP application.

Overview

The application uses Deno as the test runner with React Testing Library for component testing. Tests are written in TypeScript and follow modern testing practices with proper mocking and isolation.

Quick Start

# Install dependencies (if using npm scripts) npm install # Run all tests npm test # Run tests in watch mode npm run test:watch # Run with coverage npm run test:coverage

Test Architecture

Testing Stack

  • Test Runner: Deno Test
  • Component Testing: React Testing Library
  • Assertions: Deno Standard Library Assert
  • Mocking: Custom utilities + built-in Deno mocks
  • Coverage: Deno built-in coverage tools

Project Structure

test/
├── components/           # Component-specific tests
│   └── Message.test.tsx  # Message component tests
├── utils/               # Testing utilities
│   └── test-helpers.ts  # Mock factories and helpers
├── setup.ts            # Global test configuration
└── README.md           # Test-specific documentation

Writing Tests

Component Testing Pattern

/** @jsxImportSource https://esm.sh/react@18.2.0 */ import { assertEquals, assertExists } from "https://deno.land/std@0.208.0/assert/mod.ts"; import { render, cleanup } from "https://esm.sh/@testing-library/react@14.0.0?deps=react@18.2.0,react-dom@18.2.0"; import React from "https://esm.sh/react@18.2.0"; import { createMockMessage } from "../utils/test-helpers.ts"; import ComponentToTest from "../../frontend/components/ComponentToTest.tsx"; Deno.test("ComponentToTest - Feature Category", async (t) => { await t.step("should render correctly with basic props", () => { const mockData = createMockMessage(); const { container } = render( <ComponentToTest data={mockData} /> ); const element = container.querySelector('.expected-class'); assertExists(element, "Component should render expected element"); }); // Always cleanup after component tests cleanup(); });

Test Helpers Usage

The test-helpers.ts file provides utilities for creating consistent mock data:

import { createMockMessage, createMockMCPServer, createMockCallback, createMockAnthropicBlocks } from "../utils/test-helpers.ts"; // Create mock message with defaults const message = createMockMessage(); // Create mock message with overrides const assistantMessage = createMockMessage({ role: "assistant", content: "Custom content" }); // Create mock callback that tracks calls const mockCallback = createMockCallback(); // Later: assertEquals(mockCallback.calls.length, 1); // Create mock Anthropic blocks for streaming tests const blocks = createMockAnthropicBlocks([ { type: "text", text: "Hello" }, { type: "code", text: "console.log('test')", language: "javascript" } ]);

Testing Different Message Types

Text Messages

await t.step("should render text message", () => { const message = createMockMessage({ content: "Simple text message" }); const { container } = render(<MessageComponent message={message} />); assertStringIncludes(container.innerHTML, "Simple text message"); });

Block Content (Streaming)

await t.step("should render streaming blocks", () => { const message = createMockMessage({ content: [ { type: "text", text: "Streaming text", _streaming: true }, { type: "code", text: "const x = 1;", language: "javascript" } ] }); const { container } = render(<MessageComponent message={message} />); // Check for streaming cursor const cursor = container.querySelector('.streaming-cursor'); assertExists(cursor, "Should show streaming cursor"); // Check for code block const codeBlock = container.querySelector('.anthropic-code-block'); assertExists(codeBlock, "Should render code block"); });

MCP Tool Results

await t.step("should render MCP tool results", () => { const message = createMockMessage({ content: [ createMockMCPToolUse({ name: "file_reader" }), createMockMCPToolResult({ content: [{ text: JSON.stringify({ output: "File content" }) }] }) ] }); const { container } = render(<MessageComponent message={message} />); const toolDetails = container.querySelector('.mcp-details'); assertExists(toolDetails, "Should render MCP tool details"); });

Testing Interactive Features

Button Actions

await t.step("should handle button clicks", () => { const mockOnDelete = createMockCallback(); const message = createMockMessage(); const { container } = render( <MessageComponent message={message} onDelete={mockOnDelete} /> ); const deleteButton = container.querySelector('.delete-btn'); assertExists(deleteButton, "Delete button should exist"); // Simulate click (note: actual click simulation requires more setup) // This tests that the button is rendered correctly });

Conditional Rendering

await t.step("should conditionally render retry button", () => { const message = createMockMessage(); const mockOnRetry = createMockCallback(); // Test with canRetry = true const { container: containerWithRetry } = render( <MessageComponent message={message} onRetry={mockOnRetry} canRetry={true} /> ); assertExists( containerWithRetry.querySelector('.retry-btn'), "Should show retry button when canRetry is true" ); // Test with canRetry = false const { container: containerNoRetry } = render( <MessageComponent message={message} onRetry={mockOnRetry} canRetry={false} /> ); assertEquals( containerNoRetry.querySelector('.retry-btn'), null, "Should not show retry button when canRetry is false" ); });

Test Categories

1. Unit Tests

  • Individual component functionality
  • Utility function behavior
  • Type validation

2. Integration Tests

  • Component interaction
  • Data flow between components
  • MCP client integration

3. Rendering Tests

  • Component output verification
  • Conditional rendering
  • Props handling

4. Interaction Tests

  • Button clicks and callbacks
  • Form submissions
  • User input handling

Mocking Strategy

Global Mocks (setup.ts)

// DOM APIs globalThis.localStorage = mockLocalStorage; globalThis.fetch = mockFetch; globalThis.crypto.randomUUID = mockUUID; // Browser APIs navigator.clipboard = mockClipboard; globalThis.alert = mockAlert;

Component-Specific Mocks

// Mock MCP clients const mockMCPClients = []; // Mock callbacks const mockOnSendMessage = createMockCallback(); const mockOnDelete = createMockCallback();

Coverage and Quality

Running Coverage

# Generate coverage data npm run test:coverage # Generate HTML report npm run test:coverage-report # View report open coverage/html/index.html

Coverage Goals

  • Components: >90% line coverage
  • Utilities: >95% line coverage
  • Critical paths: 100% coverage

Quality Metrics

  • All tests should be deterministic
  • No flaky tests
  • Fast execution (<30s total)
  • Clear, descriptive test names

Best Practices

Test Organization

Deno.test("ComponentName - Feature Category", async (t) => { await t.step("should handle normal case", () => { // Test implementation }); await t.step("should handle edge case", () => { // Test implementation }); await t.step("should handle error case", () => { // Test implementation }); cleanup(); // Always cleanup after component tests });

Naming Conventions

  • Test files: ComponentName.test.tsx
  • Test suites: "ComponentName - Feature Category"
  • Test cases: "should [expected behavior]"
  • Mock functions: mock[FunctionName]

Assertion Guidelines

// Good: Specific assertions assertExists(element, "Button should exist"); assertEquals(calls.length, 1, "Callback should be called once"); assertStringIncludes(html, "expected text"); // Avoid: Generic assertions assert(element); // Not descriptive assertEquals(result, true); // Not specific

Mock Data Consistency

// Good: Use test helpers const message = createMockMessage({ role: "assistant" }); // Avoid: Inline mock data const message = { id: "123", role: "assistant", content: "test", timestamp: 1234567890 };

Debugging Tests

Common Issues

  1. Import Errors: Ensure React version pinning in imports
  2. Component Not Rendering: Check required props
  3. Async Issues: Use proper async/await patterns
  4. Mock Problems: Verify setup.ts configuration

Debug Techniques

// Log component output const { container } = render(<Component />); console.log("HTML:", container.innerHTML); // Check mock calls console.log("Mock calls:", mockCallback.calls); // Verify element selection const element = container.querySelector('.target'); console.log("Element found:", !!element);

Test Isolation

  • Each test should be independent
  • Use cleanup() after component tests
  • Reset mocks between tests if needed
  • Avoid shared state between tests

Continuous Integration

Pre-commit Hooks

# Run tests before commit npm test # Run linting deno lint # Run formatting deno fmt --check

CI Pipeline

# Example GitHub Actions workflow - name: Run Tests run: | deno test --allow-all test/ deno coverage coverage --html

Adding New Tests

Checklist

  • Create test file in appropriate directory
  • Follow naming conventions
  • Import required testing utilities
  • Use test helpers for mock data
  • Include cleanup calls
  • Test happy path and edge cases
  • Add descriptive assertions
  • Update documentation if needed

Template

/** @jsxImportSource https://esm.sh/react@18.2.0 */ import { assertEquals, assertExists } from "https://deno.land/std@0.208.0/assert/mod.ts"; import { render, cleanup } from "https://esm.sh/@testing-library/react@14.0.0?deps=react@18.2.0,react-dom@18.2.0"; import React from "https://esm.sh/react@18.2.0"; import { createMockMessage } from "../utils/test-helpers.ts"; import NewComponent from "../../frontend/components/NewComponent.tsx"; Deno.test("NewComponent - Basic Functionality", async (t) => { await t.step("should render with default props", () => { // Test implementation }); await t.step("should handle prop changes", () => { // Test implementation }); cleanup(); });

Resources

  • Deno Testing Documentation
  • React Testing Library Documentation
  • Deno Standard Library Assert
  • ESM.sh for React Dependencies

Contributing

When adding tests:

  1. Follow the established patterns
  2. Use the provided test helpers
  3. Maintain good coverage
  4. Write clear, descriptive tests
  5. Update documentation as needed

For questions or issues with testing, refer to the test README or create an issue in the project repository.

Go to top
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Product
FeaturesPricing
Developers
DocsStatusAPI ExamplesNPM Package Examples
Explore
ShowcaseTemplatesNewest ValsTrending ValsNewsletter
Company
AboutBlogCareersBrandhi@val.town
Terms of usePrivacy policyAbuse contact
© 2025 Val Town, Inc.