Postboy Help

Message History

Everything your code sends to the mock bus is recorded.
MessageHistory is the engine behind world.then, and it’s available directly for custom checks or debugging.

Access it through the world:

const history = world.history;

What gets recorded

The mock bus logs four kinds of interactions:

Action

Method on bus

What appears in history

Fire generic message

fire(…)

The message instance

Fire callback

fireCallback(…)

The callback message instance and the result

Execute an executor

exec(…)

The executor instance

Subscribe

sub(Type)/once(Type)

Increment of the subscription counter for that type

Subscriptions are stored as simple counters, not as a list of observer objects.
Messages, callbacks, and executors are stored in collections grouped by their class (the constructor used as key).

API overview

history.messages(type)

Returns a HistoryCollection<T> containing all messages of the given type.
type is the constructor function of a PostboyGenericMessage, PostboyCallbackMessage, or PostboyExecutor.

const events = world.history.messages(OrderPlacedEvent);

The returned collection provides lazy views — you can inspect it multiple times, and it will reflect any new messages that were added after your first call.

history.subs(type)

Returns the total number of subscriptions (sub and once combined) made to the given message type.

const count = world.history.subs(OrderPlacedEvent); should().number(count).equals(2);

history.reset()

Clears all recorded messages and subscription counters.
Normally you don’t need to call this manuallyworld.dispose() triggers it for you.
Only use reset() if you want to start a fresh recording within the same test.

HistoryCollection<T> in detail

HistoryCollection<T> is the container for all messages of a single type.
It exposes a familiar array‑like interface plus a few predicate helpers.

Properties

interface HistoryCollection<T> { first: T | null; last: T | null; all: T[]; length: number; }
  • first — the earliest message sent, or null if empty.

  • last — the most recent message sent, or null if empty.

  • all — a defensive shallow copy of all messages. Modifying the returned array does not affect the real history.

  • length — how many messages are currently stored.

Predicate checks

has(predicate: (item: T) => boolean): boolean

Returns true if at least one message satisfies the predicate.

const hasBigOrder = world.history .messages(OrderPlacedEvent) .has(event => event.amount > 1000);

hasItem(item: T): boolean

Checks for the presence of an exact object reference.

const event = new OrderPlacedEvent(42); world.postboy.fire(event); const found = world.history.messages(OrderPlacedEvent).hasItem(event); // true

Modifying the collection

add(item: T): void

Manually append a message to the collection. Rarely needed; mostly used internally by the mock bus.

clear(): void

Remove all messages of this type only, leaving other types untouched.
Again, usually unnecessary because world.dispose() resets the whole history.

Typical use cases for direct history access

world.then covers most common assertions, but sometimes you need the raw data.

  • Verify exact order of multiple messages

    const all = world.history.messages(MyEvent).all; should().string(all[0].step).equal('start'); should().string(all[1].step).equal('finish');
  • Check properties of a specific message

    const third = world.history.messages(MyEvent).all[2]; should().number(third.payload.id).equals(expectedId);
  • Combine history with custom logic

    const successful = world.history.messages(MyEvent).all.filter(e => e.ok); should().array(successful).length(3);
  • Inspect subscription counts

    should().number(world.history.subs(MyEvent)).greaterOrEqual(1);

Internal structure

MessageHistorymessages(type): HistoryCollection<T>subs(type): numberreset(): voidHistoryCollectionTfirst: T | nulllast: T | nullall: T[]length: numberadd(item: T): voidhas(predicate: (item: T) => boolean): booleanhasItem(item: T): booleanclear(): voidInstances are created lazilywhen messages(type) is first called.per type10..*

Each message type gets its own HistoryCollection, created on first access. Subscription counters are stored separately.

Cleanup: don’t forget dispose()

world.dispose() calls history.reset() internally, clearing everything. Manual calls to reset() or clear() are safe but rarely needed in a well‑structured test suite that follows beforeEach/afterEach.

afterEach(() => { world.dispose(); // also resets the history });

Now you have the full picture of how history works. Combine it with then and waiter for flexible, precise test assertions.

07 мая 2026