MQTT Unit Tests: Odoo-ABS Integration¶
Test Design Pattern: Emit/Echo Validation¶
Following user memory "MQTT Listener Integration, Topic Structure, and Unit Test Pattern": - Each test publishes an MQTT signal (emit) - Validates the corresponding response signal (echo) - Ensures proper alignment with event-driven architecture
Test Suite 1: Odoo Subscription Synchronization¶
Test 1.1: Successful Subscription Payment Update¶
EMIT:
{
"topic": "emit/Odoo/subscription/12345/payment_updated",
"payload": {
"subscription_id": 12345,
"payment_state": "paid",
"amount_total": 2500.0,
"currency_id": "KES",
"invoice_id": "INV-001",
"payment_date": "2025-01-15T14:30:00Z"
}
}
EXPECTED ECHO:
{
"topic": "echo/ABS/serviceplan/plan-123/sync_completed",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["ODOO_SYNC_SUCCESS"],
"metadata": {
"called": "syncOdooSubscription",
"sync_status": "success",
"odoo_subscription_id": 12345,
"agent_state_updates": {
"odoo_subscription_id": 12345,
"odoo_payment_state": "paid",
"odoo_last_sync_at": "2025-01-15T14:30:00Z"
},
"fsm_inputs_generated": 1
},
"fsmInputs": [
{
"cycle": "payment_cycle",
"input": "PAYMENT_CONFIRMED"
}
]
}
}
Test 1.2: Subscription State Change (In Progress)¶
EMIT:
{
"topic": "emit/Odoo/subscription/12345/state_changed",
"payload": {
"subscription_id": 12345,
"state": "in_progress",
"previous_state": "draft",
"change_reason": "customer_activated",
"timestamp": "2025-01-15T14:35:00Z"
}
}
EXPECTED ECHO:
{
"topic": "echo/ABS/serviceplan/plan-123/sync_completed",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["ODOO_SYNC_SUCCESS"],
"metadata": {
"called": "syncOdooSubscription",
"sync_status": "success",
"odoo_subscription_id": 12345,
"agent_state_updates": {
"odoo_subscription_id": 12345,
"odoo_subscription_state": "in_progress",
"odoo_last_sync_at": "2025-01-15T14:35:00Z"
},
"state_mappings": {
"subscription_state": "SERVICE_ACTIVE"
},
"fsm_inputs_generated": 1
},
"fsmInputs": [
{
"cycle": "service_cycle",
"input": "CONTINUE_SERVICE_REQUESTED"
}
]
}
}
Test 1.3: Payment Overdue Notification¶
EMIT:
{
"topic": "emit/Odoo/subscription/12345/payment_overdue",
"payload": {
"subscription_id": 12345,
"payment_state": "not_paid",
"amount_due": 2500.0,
"currency_id": "KES",
"days_overdue": 5,
"grace_period_remaining": 2,
"invoice_id": "INV-002"
}
}
EXPECTED ECHO:
{
"topic": "echo/ABS/serviceplan/plan-123/sync_completed",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["ODOO_SYNC_SUCCESS"],
"metadata": {
"called": "syncOdooSubscription",
"sync_status": "success",
"odoo_subscription_id": 12345,
"agent_state_updates": {
"odoo_subscription_id": 12345,
"odoo_payment_state": "not_paid",
"odoo_last_sync_at": "2025-01-15T14:40:00Z"
},
"state_mappings": {
"payment_state": "PAYMENT_PENDING"
},
"fsm_inputs_generated": 1
},
"fsmInputs": [
{
"cycle": "payment_cycle",
"input": "PAYMENT_OVERDUE"
}
]
}
}
Test Suite 2: Error Handling¶
Test 2.1: Missing Subscription ID¶
EMIT:
{
"topic": "emit/Odoo/subscription/unknown/payment_updated",
"payload": {
"payment_state": "paid",
"amount_total": 2500.0,
"currency_id": "KES"
}
}
EXPECTED ECHO:
{
"topic": "echo/ABS/serviceplan/unknown/sync_error",
"payload": {
"plan_id": "unknown",
"success": false,
"signals": ["ODOO_SYNC_ERROR"],
"metadata": {
"called": "syncOdooSubscription",
"validator_matched": "missing_subscription_id",
"reason": "Odoo subscription ID missing from sync payload",
"sync_status": "failed",
"sync_timestamp": "2025-01-15T14:45:00Z"
}
}
}
Test 2.2: Invalid Payment State¶
EMIT:
{
"topic": "emit/Odoo/subscription/12345/payment_updated",
"payload": {
"subscription_id": 12345,
"payment_state": "invalid_state",
"amount_total": 2500.0,
"currency_id": "KES"
}
}
EXPECTED ECHO:
{
"topic": "echo/ABS/serviceplan/plan-123/sync_warning",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["ODOO_SYNC_WARNING"],
"metadata": {
"called": "syncOdooSubscription",
"sync_status": "success",
"odoo_subscription_id": 12345,
"warnings": [
{
"name": "invalid_payment_state",
"reason": "Unknown Odoo payment state received"
}
],
"agent_state_updates": {
"odoo_subscription_id": 12345,
"odoo_last_sync_at": "2025-01-15T14:50:00Z"
}
}
}
}
Test Suite 3: Service Availability with Odoo Integration¶
Test 3.1: Service Check with Odoo Payment Current¶
EMIT:
{
"topic": "emit/BSS/serviceplan/plan-123/check_service",
"payload": {
"action": "CHECK_SERVICE",
"station_id": "STATION_001",
"battery_type": "TYPE_A",
"agent_state": {
"odoo_subscription_id": 12345,
"odoo_payment_state": "paid",
"odoo_subscription_state": "in_progress"
}
}
}
EXPECTED ECHO:
{
"topic": "echo/BSS/serviceplan/plan-123/service_available",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["SERVICE_AVAILABLE"],
"metadata": {
"called": "checkServiceAvailability",
"validator_matched": "service_available",
"availability_status": "available",
"station_id": "STATION_001",
"quota_status": {
"used": 0,
"limit": 10,
"percentage": 0,
"remaining": 10
},
"payment_status": "current",
"odoo_integration": {
"subscription_id": 12345,
"payment_state": "paid",
"subscription_state": "in_progress"
}
}
}
}
Test Suite 4: Complete Integration Flow¶
Test 4.1: End-to-End Subscription Creation to Service Usage¶
Step 1 - EMIT: Odoo Subscription Created
{
"topic": "emit/Odoo/subscription/12345/created",
"payload": {
"subscription_id": 12345,
"partner_id": "customer-001",
"template_id": "template-nairobi-monthly-flatfee-v2",
"state": "in_progress",
"currency_id": "KES",
"amount_total": 2500.0,
"start_date": "2025-01-15"
}
}
Step 1 - EXPECTED ECHO: ServicePlan Created
{
"topic": "echo/ABS/serviceplan/plan-123/created",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["SERVICE_PLAN_CREATED"],
"metadata": {
"called": "createServicePlanFromOdoo",
"template_id": "template-nairobi-monthly-flatfee-v2",
"customer_id": "customer-001",
"odoo_subscription_id": 12345,
"initial_agent_state": {
"odoo_subscription_id": 12345,
"odoo_subscription_state": "in_progress",
"odoo_last_sync_at": "2025-01-15T15:00:00Z"
}
}
}
}
Step 2 - EMIT: Service Availability Check
{
"topic": "emit/BSS/serviceplan/plan-123/check_service",
"payload": {
"action": "CHECK_SERVICE",
"station_id": "STATION_001",
"battery_type": "TYPE_A"
}
}
Step 2 - EXPECTED ECHO: Service Available
{
"topic": "echo/BSS/serviceplan/plan-123/service_available",
"payload": {
"plan_id": "plan-123",
"success": true,
"signals": ["SERVICE_AVAILABLE"],
"metadata": {
"called": "checkServiceAvailability",
"availability_status": "available",
"odoo_integration_verified": true
}
}
}
Test Implementation Structure¶
Test Framework Requirements¶
interface MQTTTestCase {
name: string;
emit: {
topic: string;
payload: any;
};
expectedEcho: {
topic: string;
payload: any;
timeout_ms: number;
};
setup?: {
plan_state?: any;
agent_state?: any;
};
validation: {
signals: string[];
metadata_fields: string[];
fsm_inputs?: Array<{cycle: string; input: string}>;
};
}
Test Execution Pattern¶
async function runMQTTTest(testCase: MQTTTestCase): Promise<TestResult> {
// 1. Setup test environment
if (testCase.setup) {
await setupTestEnvironment(testCase.setup);
}
// 2. Subscribe to expected echo topic
const echoPromise = mqttClient.waitForMessage(
testCase.expectedEcho.topic,
testCase.expectedEcho.timeout_ms
);
// 3. Emit test message
await mqttClient.publish(testCase.emit.topic, testCase.emit.payload);
// 4. Wait for and validate echo
const echo = await echoPromise;
// 5. Validate response structure and content
return validateEcho(echo, testCase.expectedEcho, testCase.validation);
}
Test Topic Patterns¶
Emit Topic Patterns (Input)¶
emit/Odoo/subscription/{subscription_id}/{event}emit/BSS/serviceplan/{plan_id}/{action}emit/ABS/product_template/{template_id}/{event}
Echo Topic Patterns (Expected Output)¶
echo/ABS/serviceplan/{plan_id}/{result_type}echo/BSS/serviceplan/{plan_id}/{service_status}echo/Odoo/product/{product_id}/{sync_status}
Validation Criteria¶
Signal Validation¶
- Success cases: Specific success signals (e.g.,
ODOO_SYNC_SUCCESS,SERVICE_AVAILABLE) - Error cases: Appropriate error signals (e.g.,
ODOO_SYNC_ERROR,VALIDATION_ERROR) - Warning cases: Warning signals with continued operation (e.g.,
ODOO_SYNC_WARNING)
Metadata Validation¶
- Agent state updates: Verify Odoo fields properly updated in agent_state
- State mappings: Confirm Odoo states correctly mapped to ABS states
- FSM inputs: Validate appropriate FSM inputs generated for state changes
- Timestamp accuracy: Ensure sync timestamps are current and accurate
Integration Validation¶
- Domain isolation: Confirm Odoo data stays within BSS agent_state
- Existing functionality: Verify non-Odoo operations remain unaffected
- Error resilience: Test graceful handling of malformed Odoo payloads
- Performance: Validate O(1) FSM performance maintained with Odoo integration