Skip to content

Add integration tests for EventManager (Eve) systemย #12

@Monpolymet

Description

@Monpolymet

The event system (EventManager / Eve) is central to component communication in SoonFx, with 100+ event type constants. Despite its critical role, there are no tests validating event dispatch, listener management, or event propagation.

Event System Components

Component File Purpose
EventManager (Eve) src/core/events/EventManager.ts Global event bus singleton
CallCenter src/communication/messaging/CallCenter.ts Instance-level event handling
EventTypes src/core/types/EventTypes.ts Type definitions

Key Event Constants (Examples)

// From EventManager
Eve.PLAYER_INSTANCE_LEVEL_UP
Eve.ADD_DATABASE_DATA
Eve.ADD_OPERAND_DATA
Eve.FORMULA_CHANGED
Eve.VARIABLE_UPDATED
// ... 95+ more events

Test Scenarios

EventManager Core Tests

describe('EventManager', () => {
  describe('Listener Registration', () => {
    it('should register a listener for an event type')
    it('should allow multiple listeners for same event')
    it('should return unsubscribe function')
    it('should not duplicate identical listeners')
  })

  describe('Event Dispatch', () => {
    it('should call all registered listeners')
    it('should pass event data to listeners')
    it('should handle listeners that throw errors')
    it('should dispatch events synchronously by default')
    it('should support async dispatch mode')
  })

  describe('Listener Removal', () => {
    it('should remove listener via unsubscribe function')
    it('should remove listener by reference')
    it('should clear all listeners for an event type')
    it('should handle removing non-existent listener')
  })

  describe('Event Filtering', () => {
    it('should only trigger matching event types')
    it('should support wildcard listeners')
    it('should respect event namespacing')
  })
})

CallCenter Tests

describe('CallCenter', () => {
  describe('Instance Binding', () => {
    it('should bind events to specific instance')
    it('should isolate events between instances')
    it('should clean up on instance disposal')
  })

  describe('Listen/Dispatch Pattern', () => {
    it('should dispatch to instance-specific listeners')
    it('should bubble to global EventManager')
    it('should support priority ordering')
  })
})

Integration Tests

describe('Event System Integration', () => {
  describe('Player Events', () => {
    it('should emit PLAYER_INSTANCE_LEVEL_UP on level change')
    it('should include player data in event payload')
    it('should trigger in correct order with combat events')
  })

  describe('Formula Events', () => {
    it('should emit FORMULA_CHANGED when formula updates')
    it('should trigger recalculation in dependent components')
    it('should batch rapid changes')
  })

  describe('Data Events', () => {
    it('should emit ADD_DATABASE_DATA on data insertion')
    it('should emit ADD_OPERAND_DATA for operands')
    it('should propagate to visual editor')
  })
})

Edge Case Tests

describe('Event System Edge Cases', () => {
  it('should handle circular event triggers')
  it('should maintain order with nested dispatches')
  it('should recover from listener exceptions')
  it('should handle high-frequency event bursts')
  it('should prevent memory leaks from abandoned listeners')
  it('should work after system reset')
})

Performance Tests

describe('Event System Performance', () => {
  it('should handle 1000 listeners efficiently')
  it('should dispatch 10000 events under 100ms')
  it('should not degrade with listener churn')
})

Test Utilities

// tests/helpers/EventTestUtils.ts
export function createEventSpy(eventType: string) {
  const spy = vi.fn()
  const unsubscribe = Eve.listen(eventType, spy)
  return { spy, unsubscribe }
}

export function waitForEvent(eventType: string, timeout = 1000) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => reject(new Error('Timeout')), timeout)
    Eve.listen(eventType, (data) => {
      clearTimeout(timer)
      resolve(data)
    })
  })
}

export function collectEvents(eventType: string, count: number) {
  const events: unknown[] = []
  return new Promise((resolve) => {
    const unsub = Eve.listen(eventType, (data) => {
      events.push(data)
      if (events.length >= count) {
        unsub()
        resolve(events)
      }
    })
  })
}

File Structure

tests/
โ”œโ”€โ”€ core/
โ”‚   โ””โ”€โ”€ events/
โ”‚       โ””โ”€โ”€ EventManager.test.ts
โ”œโ”€โ”€ communication/
โ”‚   โ””โ”€โ”€ messaging/
โ”‚       โ””โ”€โ”€ CallCenter.test.ts
โ”œโ”€โ”€ integration/
โ”‚   โ””โ”€โ”€ EventSystem.integration.test.ts
โ””โ”€โ”€ helpers/
    โ””โ”€โ”€ EventTestUtils.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions