Skip to main content

Testing Infrastructure

This directory contains test utilities and integration tests for the runway calculator application.

Contents

  • auth_test_config.rs - Configuration and constants for authentication tests
  • api_integration/ - Integration tests for API functionality
    • auth_integration_tests.rs - Tests for auth service integration
    • http_mock.rs - HTTP mocking utilities for API testing

Running Tests

To run the WebAssembly tests, use one of the provided test scripts in the root directory:

# Run all WASM tests (requires wasm-pack)
./run_tests.sh

# Run just the HTTP mock tests
./run_http_mock_test.sh

HTTP Mocking

The http_mock.rs module provides utilities for mocking HTTP requests in tests. This allows testing API integrations without making actual network requests.

Basic Usage

use crate::tests::api_integration::http_mock::HttpMockInterceptor;
use wasm_bindgen_test::*;
use std::rc::Rc;

#[wasm_bindgen_test]
async fn test_with_http_mock() {
// Create HTTP mock
let mock = HttpMockInterceptor::new();

// Configure mock responses
mock.add_response(
"api/users", // URL pattern to match
200, // HTTP status code
r#"{"users": [{"id": 1, "name": "Test User"}]}"# // Response body
);

// Configure response with more options
mock.add_response_with_config(
"api/auth", // URL pattern
Some("POST"), // HTTP method (optional)
401, // Status code
r#"{"error": "Unauthorized"}"#, // Response body
vec![("Content-Type", "application/json")], // Headers
Some(100) // Response delay in ms (optional)
);

// Install the mock (intercepts fetch calls)
mock.install().expect("Failed to install HTTP mock");

// Make API calls that will be intercepted by the mock...

// Access recorded requests
let requests = mock.get_requests();
assert_eq!(requests.len(), 2);

// Get requests matching a pattern
let auth_requests = mock.get_requests_matching("api/auth");
assert_eq!(auth_requests.len(), 1);

// Clean up requests if needed
mock.clear_requests();

// Uninstall mock when done
mock.uninstall().expect("Failed to uninstall HTTP mock");
}

Advanced Features

Delayed Responses

You can simulate network latency with delayed responses:

// Add a delayed response (500ms delay)
mock.add_delayed_response(
"api/slow-endpoint",
200,
r#"{"data": "response after delay"}"#,
500 // milliseconds
);

// The response will be delayed by approximately 500ms
let response = api_client.fetch("api/slow-endpoint").await;

Request Verification

Verify request contents:

// Make API call with specific payload
api_client.post_json("api/users", json!({
"username": "new_user",
"email": "user@example.com"
})).await;

// Verify the request contained expected data
assert!(mock.verify_request_contains("api/users", "new_user"));

Sequence-Based Responses

Configure different responses for sequential calls to the same endpoint:

// Configure a sequence of responses for an endpoint
mock.add_sequence_responses(
"api/data",
Some("GET"),
vec![
// First call response
MockResponse::new("api/data", 200, r#"{"page": 1, "data": [...]}"#),
// Second call response
MockResponse::new("api/data", 200, r#"{"page": 2, "data": [...]}"#),
// Third call response - error
MockResponse::new("api/data", 500, r#"{"error": "Server error"}"#),
]
);

// First call gets first response
let response1 = api_client.fetch("api/data").await;
// Second call gets second response
let response2 = api_client.fetch("api/data").await;
// Third call gets third response
let response3 = api_client.fetch("api/data").await;

Integration with Auth Tests

For auth integration tests, set up the HTTP mock with authentication-related endpoints:

// Configure login endpoint
mock.add_response_with_config(
"_open/auth",
Some("POST"),
200,
r#"{"error": false, "code": 200, "result": {"jwt": "mock.jwt.token"}}"#,
vec![("Content-Type", "application/json")],
None
);

// Configure user info endpoint
mock.add_response(
"api/users/me",
200,
r#"{
"error": false,
"code": 200,
"result": {
"id": "test_id",
"username": "test_user",
"email": "test@example.com",
"display_name": "Test User",
"roles": ["user"],
"email_verified": true
}
}"#
);

// Test login functionality with mock
let auth_service = AuthService::new(client);
let result = auth_service.login("test_user", "password").await;
assert!(result.is_ok());

Notes

  • The mock intercepts the global fetch() function in the browser environment
  • It restores the original fetch() when uninstalled
  • In wasm-bindgen-test environment, full interception may not work due to limitations
  • For component-level testing, consider using dependency injection to provide a mock client
  • Always call uninstall() when done to restore the original fetch function