aissia/tests/modules/WebModuleTests.cpp
StillHammer d17ee5fbdc feat: AISSIA rename and codebase updates
- Renamed project from Celuna to AISSIA
- Updated all documentation and configuration files
- Codebase improvements and fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:37:13 +07:00

307 lines
9.8 KiB
C++

/**
* @file WebModuleTests.cpp
* @brief Integration tests for WebModule (10 TI)
*/
#include <catch2/catch_test_macros.hpp>
#include "mocks/MockIO.hpp"
#include "utils/TimeSimulator.hpp"
#include "utils/TestHelpers.hpp"
#include "modules/WebModule.h"
#include <grove/JsonDataNode.h>
using namespace celuna;
using namespace celuna::tests;
// ============================================================================
// Test Fixture
// ============================================================================
class WebTestFixture {
public:
MockIO io;
TimeSimulator time;
WebModule module;
void configure(const json& config = json::object()) {
json fullConfig = {
{"enabled", true},
{"requestTimeoutMs", 5000},
{"maxConcurrentRequests", 10}
};
fullConfig.merge_patch(config);
grove::JsonDataNode configNode("config", fullConfig);
module.setConfiguration(configNode, &io, nullptr);
}
void process() {
grove::JsonDataNode input("input", time.createInput());
module.process(input);
}
};
// ============================================================================
// TI_WEB_001: Simple GET Request
// ============================================================================
TEST_CASE("TI_WEB_001_SimpleGetRequest", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send GET request (we use a public API that should work)
f.io.injectMessage("web:request", {
{"requestId", "test-001"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Verify response published
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == "test-001");
REQUIRE(response.contains("success"));
REQUIRE(response.contains("durationMs"));
}
// ============================================================================
// TI_WEB_002: POST Request with Body
// ============================================================================
TEST_CASE("TI_WEB_002_PostRequestWithBody", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send POST request
f.io.injectMessage("web:request", {
{"requestId", "test-002"},
{"url", "https://httpbin.org/post"},
{"method", "POST"},
{"body", R"({"key": "value"})"}
});
f.process();
// Verify response
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == "test-002");
REQUIRE(response.contains("success"));
}
// ============================================================================
// TI_WEB_003: Invalid URL Handling
// ============================================================================
TEST_CASE("TI_WEB_003_InvalidUrlHandling", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send request with invalid URL
f.io.injectMessage("web:request", {
{"requestId", "test-003"},
{"url", ""},
{"method", "GET"}
});
f.process();
// Verify error response
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == "test-003");
REQUIRE(response["success"] == false);
REQUIRE(response["errorCode"] == "INVALID_URL");
}
// ============================================================================
// TI_WEB_004: Timeout Handling
// ============================================================================
TEST_CASE("TI_WEB_004_TimeoutHandling", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send request with very short timeout to a slow endpoint
f.io.injectMessage("web:request", {
{"requestId", "test-004"},
{"url", "https://httpbin.org/delay/10"},
{"method", "GET"},
{"timeoutMs", 100}
});
f.process();
// Verify response (should timeout or fail)
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == "test-004");
// Either timeout or connection error
REQUIRE(response.contains("success"));
}
// ============================================================================
// TI_WEB_005: Multiple Concurrent Requests
// ============================================================================
TEST_CASE("TI_WEB_005_MultipleConcurrentRequests", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send multiple requests
f.io.injectMessage("web:request", {
{"requestId", "test-005-a"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.io.injectMessage("web:request", {
{"requestId", "test-005-b"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.io.injectMessage("web:request", {
{"requestId", "test-005-c"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Verify all responses
REQUIRE(f.io.countPublished("web:response") >= 3);
auto messages = f.io.getAllPublished("web:response");
REQUIRE(messages.size() >= 3);
}
// ============================================================================
// TI_WEB_006: Request ID Tracking
// ============================================================================
TEST_CASE("TI_WEB_006_RequestIdTracking", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send request with specific ID
std::string testId = "unique-request-id-12345";
f.io.injectMessage("web:request", {
{"requestId", testId},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Verify response has same ID
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == testId);
}
// ============================================================================
// TI_WEB_007: Statistics Tracking
// ============================================================================
TEST_CASE("TI_WEB_007_StatisticsTracking", "[web][integration]") {
WebTestFixture f;
f.configure();
// Initial health check
auto health1 = f.module.getHealthStatus();
int initialTotal = health1->getInt("totalRequests", 0);
// Send successful request
f.io.injectMessage("web:request", {
{"requestId", "test-007"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Check health status
auto health2 = f.module.getHealthStatus();
REQUIRE(health2->getInt("totalRequests", 0) == initialTotal + 1);
REQUIRE(health2->getInt("successfulRequests", 0) >= 0);
}
// ============================================================================
// TI_WEB_008: State Serialization
// ============================================================================
TEST_CASE("TI_WEB_008_StateSerialization", "[web][integration]") {
WebTestFixture f;
f.configure();
// Make some requests
f.io.injectMessage("web:request", {
{"requestId", "test-008"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Get state
auto state = f.module.getState();
REQUIRE(state != nullptr);
int totalRequests = state->getInt("totalRequests", 0);
REQUIRE(totalRequests > 0);
// Create new module and restore state
WebModule newModule;
grove::JsonDataNode emptyConfig("config");
newModule.setConfiguration(emptyConfig, &f.io, nullptr);
newModule.setState(*state);
// Verify state restored
auto restoredHealth = newModule.getHealthStatus();
REQUIRE(restoredHealth->getInt("totalRequests", 0) == totalRequests);
}
// ============================================================================
// TI_WEB_009: Configuration Loading
// ============================================================================
TEST_CASE("TI_WEB_009_ConfigurationLoading", "[web][integration]") {
WebTestFixture f;
// Configure with custom values
f.configure({
{"enabled", false},
{"requestTimeoutMs", 15000},
{"maxConcurrentRequests", 5}
});
// Verify module respects enabled flag
f.io.injectMessage("web:request", {
{"requestId", "test-009"},
{"url", "https://api.github.com"},
{"method", "GET"}
});
f.process();
// Should not process when disabled
REQUIRE(f.io.countPublished("web:response") == 0);
}
// ============================================================================
// TI_WEB_010: Error Response Format
// ============================================================================
TEST_CASE("TI_WEB_010_ErrorResponseFormat", "[web][integration]") {
WebTestFixture f;
f.configure();
// Send request with blocked URL (localhost)
f.io.injectMessage("web:request", {
{"requestId", "test-010"},
{"url", "http://localhost:8080/test"},
{"method", "GET"}
});
f.process();
// Verify error response format
REQUIRE(f.io.wasPublished("web:response"));
auto response = f.io.getLastPublished("web:response");
REQUIRE(response["requestId"] == "test-010");
REQUIRE(response["success"] == false);
REQUIRE(response.contains("error"));
REQUIRE(response.contains("errorCode"));
REQUIRE(response["errorCode"] == "BLOCKED_URL");
}