Skip to content

Battery Swap Service: Scenario Tests

Purpose

This document contains test scenarios that validate the consistency between the business logic described in bss-business-logic.md and the FSM definitions in bss-fsm-v1.json. These tests ensure the asset-centric FSM design and agent-level business logic coordination work correctly together.

Test Categories

T1: Country-Specific Template and Currency Validation

Purpose: Validate country-specific contract controlling points and currency inheritance.

Test Scenario: Template creation and ServicePlan inheritance with country-specific settings - Prerequisites: Country-specific contract terms and legal frameworks defined - Steps: 1. Create ServicePlanTemplate with US country code and USD currency 2. Create CommonTerms with matching US jurisdiction and USD billing currency 3. Create ServicePlan from template 4. Verify all derived elements inherit USD currency 5. Attempt to create ServicePlan with mismatched currency (should fail) - Expected Outcome: Currency inheritance works correctly, mismatches are rejected - Validation Points: - Template country/jurisdiction settings are immutable after creation - ServicePlan inherits template's country, jurisdiction, and currency - All services use inherited currency for pricing - PaymentAccount uses inherited currency for all transactions - Manual quota operations respect inherited currency - Currency mismatches between template and terms are rejected

Test Scenario: Multi-country template management - Prerequisites: Multiple country-specific templates available - Steps: 1. Create US template (USD, California jurisdiction) 2. Create CA template (CAD, Ontario jurisdiction) 3. Create UK template (GBP, England jurisdiction) 4. Verify each template enforces its own currency and legal framework 5. Attempt cross-country operations (should fail) - Expected Outcome: Clear geographic and legal boundaries enforced - Validation Points: - Each template maintains its own country-specific settings - No cross-country currency mixing allowed - Legal frameworks remain jurisdiction-specific - Service availability limited to template's country

T2: Baseline Linear Customer Journey

Purpose: Validate the complete "happy path" customer journey without exceptions.

Test Scenario: Complete customer lifecycle from signup to service termination - Prerequisites: Customer account created, BSS plan template available - Steps: 1. Customer subscribes to BSS plan 2. Customer pays deposit 3. Customer receives first battery 4. Customer performs battery swaps 5. Customer renews subscription 6. Customer terminates service and returns battery - Expected Outcome: Service completes successfully with deposit refund - Validation Points: - All FSM transitions follow expected paths - Payment and service cycles remain synchronized - Quota tracking works correctly - Final settlement processes deposit refund

T3: Payment Suspension and Recovery

Purpose: Validate agent-level payment validation blocks service access during payment issues.

Test Scenario: Payment overdue blocks service access, payment received restores access - Prerequisites: Active BSS subscription with current payment - Steps: 1. Payment becomes overdue (payment_cycle FSM transitions to RENEWAL_DUE) 2. Agent-level validation blocks service access (validateServiceAccess returns ACCESS_DENIED) 3. Customer makes payment (payment_cycle FSM returns to CURRENT) 4. Agent-level validation allows service access again - Expected Outcome: Agent-level payment validation works correctly - Validation Points: - PaymentAgent blocks service access when payment_cycle in RENEWAL_DUE state - Service_cycle FSM state remains unchanged during payment issues - Customer retains battery possession status during payment suspension - Service access resumes when payment_cycle returns to CURRENT state

T4: Quota Exhaustion and Manual Restoration

Purpose: Validate manual quota management and agent-level quota validation.

Test Scenario: Service quota exhausted, manual operator intervention restores quota - Prerequisites: Active BSS subscription with quota tracking - Steps: 1. Customer uses all service quota 2. Agent-level validation blocks further service access (validateServiceAccess returns QUOTA_EXHAUSTED) 3. Human operator manually adjusts quota 4. Agent-level validation allows service access again - Expected Outcome: Manual quota management works correctly - Validation Points: - QuotaAgent blocks service access when quota exhausted - Service_cycle FSM state remains unchanged during quota exhaustion - Manual quota adjustment by operator restores service access - Bundle integrity maintained - quota exhaustion in one service blocks entire bundle

T5: Subscription Expiration and Renewal

Purpose: Validate service suspension due to subscription expiration and renewal.

Test Scenario: Subscription expires, renewal reactivates service - Prerequisites: Active BSS subscription approaching expiration - Steps: 1. Subscription period expires 2. Service suspends automatically 3. Customer renews subscription 4. Service resumes automatically - Expected Outcome: Subscription lifecycle management works correctly - Validation Points: - SUBSCRIPTION_EXPIRED signal triggers suspension - SUBSCRIPTION_RENEWED signal resumes service - Subscription dates update correctly - Service state returns to active after renewal

T6: Service Termination with Asset Return

Purpose: Validate proper service termination and asset return process.

Test Scenario: Customer terminates service and returns final battery - Prerequisites: Active BSS subscription with battery allocated - Steps: 1. Customer initiates service termination 2. Customer returns battery to swap station 3. IoT confirms battery return 4. Final settlement processes deposit refund - Expected Outcome: Service termination and asset return work correctly - Validation Points: - BATTERY_RETURNED signal completes service cycle - Final settlement calculates correct refund amount - Customer receives deposit refund notification - Service plan moves to COMPLETE state

T7: Inventory Shortage Handling

Purpose: Validate system behavior when no batteries are available.

Test Scenario: Customer requests battery swap but no inventory available - Prerequisites: Active BSS subscription, station with no available batteries - Steps: 1. Customer requests battery swap at specific station 2. System validates access and quota 3. System checks inventory availability 4. System denies allocation due to no inventory - Expected Outcome: System handles inventory shortages gracefully - Validation Points: - validateServiceAccess returns ACCESS_OK - allocateServiceAsset returns NO_INVENTORY - Customer receives appropriate error message - Service remains in active state (not suspended)

T8: Multiple Agent Validation Failures

Purpose: Validate system behavior when multiple agent validation conditions fail simultaneously.

Test Scenario: Payment overdue and quota exhausted at same time - Prerequisites: Active BSS subscription with payment issues and quota usage - Steps: 1. Payment becomes overdue (payment_cycle → RENEWAL_DUE) 2. Service quota becomes exhausted 3. Both PaymentAgent and QuotaAgent block service access 4. System handles multiple validation failures - Expected Outcome: System handles multiple validation failures correctly - Validation Points: - Both PaymentAgent and QuotaAgent return ACCESS_DENIED - Service_cycle FSM state remains unchanged - Recovery requires both payment resolution and manual quota adjustment - Agent-level coordination prevents access until all conditions resolved

T9: Grace Period Management

Purpose: Validate template-level grace period configuration and agent-level enforcement.

Test Scenario: Agent validation failure triggers grace period, expiration initiates asset recall - Prerequisites: Service plan with configured grace period, payment/quota issues - Steps: 1. Agent validation blocks service access (payment overdue or quota exhausted) 2. Template-configured grace period timer starts 3. Grace period expires without issue resolution 4. Agent initiates asset recall notification via MQTT - Expected Outcome: Grace period management works correctly - Validation Points: - Grace period duration follows ServicePlanTemplate configuration - Agent-level timer management independent of FSM states - Asset recall notification sent via MQTT when grace period expires - Service_cycle FSM state unchanged during grace period management

MQTT-Based Unit Test Implementation

Unit Test Pattern: MQTT Emit/Echo

All unit tests follow the standardized MQTT signal emit/echo pattern:

Test Structure: 1. EMIT: Publish MQTT signal to trigger system behavior 2. PROCESS: System processes the signal and updates internal state 3. ECHO: Validate expected response signal is published 4. VERIFY: Confirm system state changes are correct

MQTT Topic Convention: - EMIT topics: emit/abs/service/battery_swap/{plan_id}/{signal_name} - ECHO topics: echo/abs/service/battery_swap/{plan_id}/{response_name} - Status topics: status/abs/service/battery_swap/{plan_id}/{state_name}

T1.1: Country Template Creation

Test: Validate country-specific template creation and currency inheritance

MQTT Unit Test:

// EMIT: Request template creation
publish('emit/abs/template/create', {
  country_code: 'US',
  jurisdiction: 'California',
  currency: 'USD',
  template_id: 'BSS-US-001'
});

// ECHO: Confirm template created
expectSignal('echo/abs/template/BSS-US-001/created', {
  status: 'success',
  currency: 'USD',
  immutable_settings: ['country_code', 'jurisdiction']
});

// VERIFY: Template configuration accessible
expectSignal('status/abs/template/BSS-US-001/ready', {
  country_code: 'US',
  currency: 'USD'
});

T1.2: Currency Inheritance Validation

Test: Validate ServicePlan inherits template currency correctly

MQTT Unit Test:

// EMIT: Create ServicePlan from template
publish('emit/abs/plan/create', {
  template_id: 'BSS-US-001',
  plan_id: 'PLAN-123',
  customer_id: 'CUST-456'
});

// ECHO: Confirm plan created with inherited currency
expectSignal('echo/abs/plan/PLAN-123/created', {
  status: 'success',
  inherited_currency: 'USD',
  payment_cycle: 'INITIAL',
  service_cycle: 'INITIAL'
});

// VERIFY: All plan operations use inherited currency
expectSignal('status/abs/plan/PLAN-123/currency_validated', {
  currency: 'USD',
  validation: 'passed'
});

T2.1: Customer Signup Flow

Test: Complete customer journey from signup to service activation

MQTT Unit Test:

// EMIT: Contract signed
publish('emit/abs/plan/PLAN-123/contract_signed', {
  customer_id: 'CUST-456',
  template_id: 'BSS-US-001',
  agreement_date: '2024-01-15T10:00:00Z'
});

// ECHO: Deposit required
expectSignal('echo/abs/plan/PLAN-123/deposit_required', {
  amount: 500.00,
  currency: 'USD',
  payment_cycle: 'DEPOSIT_DUE'
});

// EMIT: Deposit paid (from Odoo via MQTT)
publish('emit/abs/plan/PLAN-123/deposit_paid', {
  amount: 500.00,
  currency: 'USD',
  payment_id: 'PAY-789',
  odoo_sync: true
});

// ECHO: Service activated
expectSignal('echo/abs/plan/PLAN-123/service_activated', {
  payment_cycle: 'CURRENT',
  service_cycle: 'WAIT_BATTERY_ISSUE',
  status: 'ready_for_service'
});

T3.1: Payment Synchronization

Test: Validate MQTT-based payment synchronization with Odoo

MQTT Unit Test:

// EMIT: Payment overdue signal from Odoo
publish('emit/abs/plan/PLAN-123/payment_overdue', {
  due_date: '2024-01-10T00:00:00Z',
  amount: 99.99,
  currency: 'USD',
  odoo_subscription_id: 'SUB-001'
});

// ECHO: Payment status updated
expectSignal('echo/abs/plan/PLAN-123/payment_status_updated', {
  payment_cycle: 'RENEWAL_DUE',
  access_blocked: true,
  grace_period_started: true
});

// EMIT: Payment received signal from Odoo
publish('emit/abs/plan/PLAN-123/payment_received', {
  amount: 99.99,
  currency: 'USD',
  payment_id: 'PAY-790',
  odoo_sync: true
});

// ECHO: Service access restored
expectSignal('echo/abs/plan/PLAN-123/access_restored', {
  payment_cycle: 'CURRENT',
  access_blocked: false,
  grace_period_ended: true
});

T4.1: Quota Exhaustion Management

Test: Manual quota management and bundle integrity

MQTT Unit Test:

// EMIT: Service usage that exhausts quota
publish('emit/abs/plan/PLAN-123/service_usage', {
  service_type: 'battery_swap',
  usage_count: 20, // exhausts monthly quota
  bundle_id: 'BUNDLE-001'
});

// ECHO: Quota exhausted notification
expectSignal('echo/abs/plan/PLAN-123/quota_exhausted', {
  service_type: 'battery_swap',
  quota_remaining: 0,
  bundle_access_blocked: true
});

// EMIT: Manual quota adjustment by operator
publish('emit/abs/plan/PLAN-123/quota_adjusted', {
  service_type: 'battery_swap',
  new_quota: 30,
  operator_id: 'OPR-123',
  reason: 'customer_request'
});

// ECHO: Bundle access restored
expectSignal('echo/abs/plan/PLAN-123/bundle_access_restored', {
  bundle_id: 'BUNDLE-001',
  all_services_valid: true,
  access_granted: true
});

T5.1: Asset-Centric FSM Validation

Test: Battery possession tracking during payment issues

MQTT Unit Test:

// EMIT: Battery issued to customer
publish('emit/abs/plan/PLAN-123/battery_issued', {
  battery_id: 'BAT-001',
  station_id: 'STA-456',
  issue_time: '2024-01-15T14:30:00Z'
});

// ECHO: Battery possession confirmed
expectSignal('echo/abs/plan/PLAN-123/battery_possession_confirmed', {
  service_cycle: 'BATTERY_ISSUED',
  battery_id: 'BAT-001',
  customer_has_battery: true
});

// EMIT: Payment becomes overdue while customer has battery
publish('emit/abs/plan/PLAN-123/payment_overdue', {
  amount: 99.99,
  due_date: '2024-01-10T00:00:00Z'
});

// ECHO: Access blocked but battery possession unchanged
expectSignal('echo/abs/plan/PLAN-123/access_blocked_battery_retained', {
  service_cycle: 'BATTERY_ISSUED', // unchanged
  payment_cycle: 'RENEWAL_DUE',
  customer_has_battery: true, // still has battery
  new_operations_blocked: true
});

T6.1: Bundle Integrity Testing

Test: Multi-service bundle validation with AND logic

MQTT Unit Test:

// EMIT: Service request for bundle with multiple services
publish('emit/abs/plan/PLAN-123/service_request', {
  requested_service: 'battery_swap',
  bundle_id: 'BUNDLE-002',
  services: ['battery_swap', 'energy_tracking'],
  location: 'STA-789'
});

// EMIT: One service in bundle becomes invalid
publish('emit/abs/plan/PLAN-123/service_quota_exhausted', {
  service_type: 'energy_tracking',
  bundle_id: 'BUNDLE-002'
});

// ECHO: Entire bundle access denied
expectSignal('echo/abs/plan/PLAN-123/bundle_access_denied', {
  bundle_id: 'BUNDLE-002',
  failed_service: 'energy_tracking',
  reason: 'bundle_integrity_violation',
  all_services_required: true
});

T7.1: Multi-Fleet Access Control

Test: Bundle access to multiple battery fleets

MQTT Unit Test:

// EMIT: Swap request for specific fleet
publish('emit/abs/plan/PLAN-123/swap_request', {
  station_id: 'STA-789',
  requested_fleet: 'FLEET-PREMIUM',
  bundle_permissions: ['FLEET-STANDARD', 'FLEET-PREMIUM']
});

// ECHO: Fleet access validated and battery allocated
expectSignal('echo/abs/plan/PLAN-123/battery_allocated', {
  battery_id: 'BAT-PREM-001',
  fleet_type: 'FLEET-PREMIUM',
  access_granted: true,
  station_id: 'STA-789'
});

// EMIT: Request for unauthorized fleet
publish('emit/abs/plan/PLAN-123/swap_request', {
  station_id: 'STA-456',
  requested_fleet: 'FLEET-LUXURY',
  bundle_permissions: ['FLEET-STANDARD', 'FLEET-PREMIUM']
});

// ECHO: Fleet access denied
expectSignal('echo/abs/plan/PLAN-123/fleet_access_denied', {
  requested_fleet: 'FLEET-LUXURY',
  reason: 'insufficient_bundle_permissions',
  available_fleets: ['FLEET-STANDARD', 'FLEET-PREMIUM']
});

T8.1: Grace Period Management

Test: Template-configured grace period with MQTT notifications

MQTT Unit Test:

// EMIT: Agent validation failure triggers grace period
publish('emit/abs/plan/PLAN-123/validation_failure', {
  failure_type: 'payment_overdue',
  grace_period_config: {
    duration_hours: 72,
    template_id: 'BSS-US-001'
  }
});

// ECHO: Grace period started
expectSignal('echo/abs/plan/PLAN-123/grace_period_started', {
  duration_hours: 72,
  expiry_time: '2024-01-18T14:30:00Z',
  asset_recall_pending: false
});

// EMIT: Grace period expiration (simulated timer)
publish('emit/abs/plan/PLAN-123/grace_period_expired', {
  expiry_time: '2024-01-18T14:30:00Z',
  issue_resolved: false
});

// ECHO: Asset recall notification sent
expectSignal('echo/abs/plan/PLAN-123/asset_recall_initiated', {
  customer_notification_sent: true,
  escalation_level: 'asset_recovery',
  service_cycle: 'BATTERY_ISSUED' // unchanged
});

T9.1: Service Termination Flow

Test: Complete service termination with asset return

MQTT Unit Test:

// EMIT: Customer initiates service termination
publish('emit/abs/plan/PLAN-123/termination_requested', {
  customer_id: 'CUST-456',
  reason: 'subscription_end',
  has_unreturned_assets: true
});

// ECHO: Asset return required
expectSignal('echo/abs/plan/PLAN-123/asset_return_required', {
  required_assets: ['BAT-001'],
  termination_blocked: true,
  return_instructions_sent: true
});

// EMIT: Battery returned by customer
publish('emit/abs/plan/PLAN-123/battery_returned', {
  battery_id: 'BAT-001',
  station_id: 'STA-456',
  return_time: '2024-01-20T16:00:00Z'
});

// ECHO: Service termination completed
expectSignal('echo/abs/plan/PLAN-123/termination_completed', {
  service_cycle: 'COMPLETE',
  final_settlement_initiated: true,
  deposit_refund_processed: true
});

T10.1: Error Handling and Recovery

Test: MQTT signal processing error handling

MQTT Unit Test:

// EMIT: Invalid signal format
publish('emit/abs/plan/PLAN-123/invalid_signal', {
  malformed_data: 'invalid_json_structure',
  missing_required_fields: true
});

// ECHO: Error handled gracefully
expectSignal('echo/abs/plan/PLAN-123/signal_processing_error', {
  error_type: 'invalid_format',
  signal_rejected: true,
  system_state_unchanged: true
});

// EMIT: Network communication failure simulation
publish('emit/abs/plan/PLAN-123/network_failure', {
  failure_type: 'odoo_connection_lost',
  last_sync_time: '2024-01-15T10:00:00Z'
});

// ECHO: Fallback behavior activated
expectSignal('echo/abs/plan/PLAN-123/fallback_mode_activated', {
  local_operation_mode: true,
  sync_pending: true,
  service_continuity_maintained: true
});

MQTT Test Framework Implementation

Test Setup Requirements

// MQTT Test Client Setup
const mqtt = require('mqtt');
const testClient = mqtt.connect('mqtt://localhost:1883');

// Test Helper Functions
function publish(topic, payload) {
  testClient.publish(topic, JSON.stringify(payload));
}

function expectSignal(topic, expectedPayload, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error(`Signal not received on ${topic} within ${timeout}ms`));
    }, timeout);

    testClient.subscribe(topic);
    testClient.on('message', (receivedTopic, message) => {
      if (receivedTopic === topic) {
        clearTimeout(timer);
        const payload = JSON.parse(message.toString());
        expect(payload).toMatchObject(expectedPayload);
        resolve(payload);
      }
    });
  });
}

Integration with Jest Testing Framework

// Example Jest Test Implementation
describe('BSS MQTT Signal Processing', () => {
  beforeEach(async () => {
    // Setup test environment
    await setupTestPlan('PLAN-123');
  });

  afterEach(async () => {
    // Cleanup test data
    await cleanupTestPlan('PLAN-123');
  });

  test('T3.1: Payment Synchronization Flow', async () => {
    // Test implementation using MQTT emit/echo pattern
    // ... (test code from T3.1 above)
  });
});