Internal testing utilities for simulating multi-user and multi-device scenarios
Our testing framework provides worker utilities that allow you to easily create predefined workers (like Alice, Bob, etc.) with different installations. This is particularly useful for testing multi-device scenarios or different client configurations within our test suite.
// Quick example
const workers = await getWorkers(["alice", "bob"], "my-test");
const alice = workers.get("alice");
const bob = workers.get("bob");
// Start a conversation
const conversation = await alice.client.conversations.newDm(bob.client.inboxId);
await conversation.send("Hello from Alice to Bob");
- 🔑 Identity Management: Automatic key creation with persistence between test runs
- 📱 Multi-Device Testing: Simulate multiple installations (desktop, mobile, etc.) for the same worker
- 📊 Separate Storage: Independent database paths for each installation
- 🔄 Stream Handling: Built-in support for message, conversation, and consent streams
- 🤖 GPT Integration: Optional AI-powered responses for automated testing scenarios
// Import the getWorkers function
import { getWorkers } from "./path/to/manager";
// Initialize workers in your test file
const workers = await getWorkers(["alice", "bob"], testName);
// Access workers by name (default installation "a")
const alice = workers.get("alice");
const bob = workers.get("bob");
// Test a simple conversation
const conversation = await alice.client.conversations.newDm(bob.client.inboxId);
await conversation.send("Hello Bob!");
// Wait for Bob to receive the message
await bob.client.conversations.sync();
const bobConversations = await bob.client.conversations.list();
// Create primary and secondary installations
const primaryWorkers = await getWorkers(["alice", "bob"], testName);
const secondaryWorkers = await getWorkers(
["alice-desktop", "bob-mobile"],
testName,
);
// Access specific installations
const alicePhone = primaryWorkers.get("alice");
const aliceDesktop = secondaryWorkers.get("alice", "desktop");
const bobMobile = secondaryWorkers.get("bob", "mobile");
// Test synchronization across devices
const conversation = await aliceDesktop.client.conversations.newDm(
bobMobile.client.inboxId,
);
await conversation.send("Hello from Alice's desktop!");
// Verify message appears on Alice's phone
await alicePhone.client.conversations.sync();
const alicePhoneConversations = await alicePhone.client.conversations.list();
// Set up worker with message streaming
const workers = await getWorkers(["alice", "bob"], testName, "message");
const alice = workers.get("alice");
const bob = workers.get("bob");
// Start conversation and send message
const conversation = await alice.client.conversations.newDm(bob.client.inboxId);
const conversationId = conversation.id;
await conversation.send("Testing stream collection");
// Collect incoming messages for Bob
const incomingMessages = await bob.worker.collectMessages(
conversationId,
"text",
1, // number of messages to collect
5000, // timeout in ms
);
console.log(`Received message: ${incomingMessages[0].message.content}`);
// Create workers with GPT-powered responses
const workers = await getWorkers(["alice", "bob"], testName, "message", true);
const alice = workers.get("alice");
const bob = workers.get("bob");
// Send message that will trigger GPT response from Bob
const conversation = await alice.client.conversations.newDm(bob.client.inboxId);
await conversation.send("Hey bob, what do you think about this feature?");
// Bob will automatically generate and send a response
// Wait for the response to come back to Alice
const responses = await alice.worker.collectMessages(
conversation.id,
"text",
1,
);
// Create 4 workers using default names
const workers = await getWorkers(4, testName);
// This will create workers for the first 4 names in defaultNames
Method | Description |
---|---|
getWorkers(descriptors, testName, streamType?, gptEnabled?) |
Creates and initializes worker instances |
workers.get(name, installationId?) |
Retrieves a specific worker |
workers.getLength() |
Returns the total number of workers |
workers.getRandomWorkers(count) |
Gets a random subset of workers |
worker.worker.collectMessages(groupId, typeId, count, timeout?) |
Collects message stream events |
worker.worker.collectConversations(fromPeer, count?, timeout?) |
Collects conversation stream events |
worker.worker.collectConsentUpdates(count?, timeout?) |
Collects consent stream events |
The framework comes with 61 predefined worker names that you can use:
import { defaultNames } from "@xmtp/node-sdk";
// First few names from the list:
// "bob", "alice", "fabri", "bot", "elon", "joe", "charlie"...
💡 Tip: Access our repository of 600 dummy wallets with inboxIds in the
generated-inboxes.json
file
Always clean up your workers after tests:
afterAll(async () => {
await closeEnv(testName, allWorkers);
});
- Worker instances use Node.js worker threads for parallel processing
- Keys are stored in
.env
files (except for "random" workers which store keys only in memory) - Database paths follow a structured format to avoid conflicts between tests
- Message streams, conversation streams, and consent streams are supported
- GPT responses are generated using OpenAI's API if enabled