@bsv/message-box-client
Version:
A client for P2P messaging and payments
599 lines • 29.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-env jest */
const MessageBoxClient_js_1 = require("../MessageBoxClient.js");
const sdk_1 = require("@bsv/sdk");
// MOCK: WalletClient methods globally
jest.spyOn(sdk_1.WalletClient.prototype, 'createHmac').mockResolvedValue({
hmac: Array.from(new Uint8Array([1, 2, 3]))
});
jest.spyOn(sdk_1.WalletClient.prototype, 'getPublicKey').mockResolvedValue({
publicKey: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4'
});
jest.spyOn(sdk_1.WalletClient.prototype, 'encrypt').mockResolvedValue({
ciphertext: [9, 9, 9, 9]
});
jest.spyOn(sdk_1.WalletClient.prototype, 'decrypt').mockResolvedValue({
plaintext: [1, 2, 3, 4, 5]
});
jest.spyOn(sdk_1.WalletClient.prototype, 'createSignature').mockResolvedValue({
signature: [1, 2, 3, 4, 5] // <-- any dummy byte array
});
jest.spyOn(sdk_1.WalletClient.prototype, 'connectToSubstrate').mockImplementation(async function () {
this.substrate = {
createSignature: async (message) => {
return Array.from(new Uint8Array([1, 2, 3])); // Return mock signature
}
};
});
const minimalTx = new sdk_1.Transaction();
minimalTx.addOutput({
satoshis: 1,
lockingScript: new sdk_1.LockingScript([]) // ✅ must wrap in LockingScript class
});
const realAtomicBEEF = minimalTx.toAtomicBEEF();
jest.spyOn(sdk_1.WalletClient.prototype, 'createAction').mockResolvedValue({
txid: 'mocked-txid',
tx: realAtomicBEEF
});
// MOCK: AuthFetch responses
const defaultMockResponse = {
json: async () => ({ status: 'success', message: 'Mocked response' }),
headers: new Headers(),
ok: true,
status: 200
};
jest.spyOn(MessageBoxClient_js_1.MessageBoxClient.prototype, 'anointHost').mockImplementation(async () => {
return { txid: 'mocked-anoint-txid' };
});
jest.spyOn(MessageBoxClient_js_1.MessageBoxClient.prototype, 'queryAdvertisements')
.mockResolvedValue([]);
jest.spyOn(sdk_1.AuthFetch.prototype, 'fetch')
.mockResolvedValue(defaultMockResponse);
// MOCK: WebSocket behavior
const socketOnMap = {};
const mockSocket = {
on: jest.fn((event, callback) => {
socketOnMap[event] = callback;
}),
emit: jest.fn(),
disconnect: jest.fn(),
connected: true,
off: jest.fn()
};
jest.mock('@bsv/authsocket-client', () => ({
AuthSocketClient: jest.fn(() => mockSocket)
}));
// Optional: Global WebSocket override (not strictly needed with AuthSocketClient)
class MockWebSocket {
constructor() {
this.readyState = MockWebSocket.OPEN;
this.on = jest.fn();
this.send = jest.fn();
this.close = jest.fn();
}
}
MockWebSocket.CONNECTING = 0;
MockWebSocket.OPEN = 1;
MockWebSocket.CLOSING = 2;
MockWebSocket.CLOSED = 3;
global.WebSocket = MockWebSocket;
describe('MessageBoxClient', () => {
let mockWalletClient;
beforeEach(() => {
mockWalletClient = new sdk_1.WalletClient();
jest.clearAllMocks();
// (Optional, but if you want per-test control, you could move mocks here instead of globally.)
});
const VALID_LIST_AND_READ_RESULT = {
body: JSON.stringify({
status: 200,
messages: [
{ sender: 'mockSender', messageId: 42, body: {} },
{ sender: 'mockSender', messageId: 43, body: {} }
]
})
};
const VALID_ACK_RESULT = {
body: JSON.stringify({
status: 200,
message: 'Messages marked as acknowledged!'
})
};
it('Creates an instance of the MessageBoxClient class', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
expect(messageBoxClient).toHaveProperty('host', 'https://messagebox.babbage.systems');
// Ensure the socket is initialized as undefined before connecting
expect(messageBoxClient.testSocket).toBeUndefined();
});
it('Initializes WebSocket connection', async () => {
await new Promise(resolve => setTimeout(resolve, 100));
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
const connection = messageBoxClient.initializeConnection();
// Simulate server response
setTimeout(() => {
var _a;
(_a = socketOnMap.authenticationSuccess) === null || _a === void 0 ? void 0 : _a.call(socketOnMap, { status: 'ok' });
}, 100);
await expect(connection).resolves.toBeUndefined();
}, 10000);
it('Falls back to HTTP when WebSocket is not initialized', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
// Bypass the real connection logic
jest.spyOn(messageBoxClient, 'initializeConnection').mockImplementation(async () => { });
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
messageBoxClient.socket = null;
// Expect it to fall back to HTTP and succeed
const result = await messageBoxClient.sendLiveMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: 'Test message'
});
expect(result).toEqual({
status: 'success',
message: 'Mocked response',
messageId: '010203'
});
});
it('Listens for live messages', async () => {
var _a;
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
const connection = messageBoxClient.initializeConnection();
setTimeout(() => {
var _a;
(_a = socketOnMap.authenticationSuccess) === null || _a === void 0 ? void 0 : _a.call(socketOnMap, { status: 'ok' });
}, 100);
await connection;
const mockOnMessage = jest.fn();
await messageBoxClient.listenForLiveMessages({
messageBox: 'test_inbox',
onMessage: mockOnMessage
});
expect((_a = messageBoxClient.testSocket) === null || _a === void 0 ? void 0 : _a.emit).toHaveBeenCalledWith('joinRoom', '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4-test_inbox');
}, 10000);
it('Sends a live message', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
const connection = messageBoxClient.initializeConnection();
// Simulate WebSocket auth success
setTimeout(() => {
var _a;
(_a = socketOnMap.authenticationSuccess) === null || _a === void 0 ? void 0 : _a.call(socketOnMap, { status: 'ok' });
}, 100);
await connection;
const emitSpy = jest.spyOn(messageBoxClient.testSocket, 'emit');
// Kick off sending a message (this sets up the ack listener)
const sendPromise = messageBoxClient.sendLiveMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: 'Test message'
});
// Simulate WebSocket acknowledgment
setTimeout(() => {
var _a;
(_a = socketOnMap['sendMessageAck-02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4-test_inbox']) === null || _a === void 0 ? void 0 : _a.call(socketOnMap, {
status: 'success',
messageId: 'mocked123'
});
}, 100);
const result = await sendPromise;
// Check that WebSocket emit happened correctly
expect(emitSpy).toHaveBeenCalledWith('sendMessage', expect.objectContaining({
roomId: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4-test_inbox',
message: expect.objectContaining({
messageId: '010203',
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
body: expect.stringMatching(/encrypted/)
})
}));
// Check the resolved result
expect(result).toEqual({
status: 'success',
messageId: 'mocked123'
});
}, 15000);
it('Sends a message', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
jest.spyOn(messageBoxClient.authFetch, 'fetch').mockResolvedValue({
json: async () => ({
status: 'success',
message: 'Your message has been sent!'
}),
headers: new Headers(),
ok: true,
status: 200
});
const result = await messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: { data: 'test' }
});
expect(result).toHaveProperty('message', 'Your message has been sent!');
});
it('Lists available messages', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
jest.spyOn(messageBoxClient.authFetch, 'fetch').mockResolvedValue({
json: async () => JSON.parse(VALID_LIST_AND_READ_RESULT.body),
headers: new Headers(),
ok: true,
status: 200
});
const result = await messageBoxClient.listMessages({ messageBox: 'test_inbox' });
expect(result).toEqual(JSON.parse(VALID_LIST_AND_READ_RESULT.body).messages);
});
it('Acknowledges a message', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
jest.spyOn(messageBoxClient.authFetch, 'fetch').mockResolvedValue({
json: async () => JSON.parse(VALID_ACK_RESULT.body),
headers: new Headers(),
ok: true,
status: 200
});
const result = await messageBoxClient.acknowledgeMessage({ messageIds: ['42'] });
expect(result).toEqual(200);
});
it('Throws an error when sendMessage() API fails', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
jest.spyOn(messageBoxClient.authFetch, 'fetch')
.mockResolvedValue({
status: 500,
statusText: 'Internal Server Error',
ok: false,
json: async () => ({ status: 'error', description: 'Internal Server Error' }),
headers: new Headers()
});
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: 'Test Message'
})).rejects.toThrow('Message sending failed: HTTP 500 - Internal Server Error');
});
it('throws when every host fails', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({ walletClient: mockWalletClient, host: 'https://primary', enableLogging: false });
await client.init();
// Pretend there are no advertised replicas
jest.spyOn(client, 'queryAdvertisements').mockResolvedValue([]);
// Primary host responds with 500
jest.spyOn(client.authFetch, 'fetch').mockResolvedValue({
ok: false,
status: 500,
statusText: 'Internal Server Error',
json: async () => ({ status: 'error', description: 'DB down' })
});
await expect(client.listMessages({ messageBox: 'inbox' }))
.rejects.toThrow('Failed to retrieve messages from any host');
});
it('returns [] when at least one host succeeds but has no messages', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({ walletClient: mockWalletClient, host: 'https://primary', enableLogging: false });
await client.init();
// One failing replica, one healthy replica
jest.spyOn(client, 'queryAdvertisements').mockResolvedValue([{
host: 'https://replica'
}]);
jest.spyOn(client.authFetch, 'fetch')
.mockImplementation(async (url) =>
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
url.startsWith('https://primary')
? await Promise.resolve({
ok: false,
status: 500,
statusText: 'Internal Server Error',
json: async () => ({ status: 'error', description: 'DB down' })
})
: await Promise.resolve({
ok: true,
status: 200,
json: async () => ({ status: 'success', messages: [] })
}));
await expect(client.listMessages({ messageBox: 'inbox' })).resolves.toEqual([]);
});
it('Throws an error when acknowledgeMessage() API fails', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4';
jest.spyOn(messageBoxClient.authFetch, 'fetch')
.mockResolvedValue({
status: 500,
json: async () => ({ status: 'error', description: 'Failed to acknowledge messages' })
});
await expect(messageBoxClient.acknowledgeMessage({ messageIds: ['42'] }))
.rejects.toThrow('Failed to acknowledge messages');
});
it('Emits joinRoom event and listens for incoming messages', async () => {
var _a;
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
// Mock identity key properly
jest.spyOn(mockWalletClient, 'getPublicKey').mockResolvedValue({ publicKey: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4' });
// Mock socket with `on` method capturing event handlers
const mockSocket = {
emit: jest.fn(),
on: jest.fn()
};
// Mock `initializeConnection` so it assigns `socket` & identity key
jest.spyOn(messageBoxClient, 'initializeConnection').mockImplementation(async () => {
Object.defineProperty(messageBoxClient, 'testIdentityKey', { get: () => '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4' });
Object.defineProperty(messageBoxClient, 'testSocket', { get: () => mockSocket });
messageBoxClient.socket = mockSocket; // Ensures internal socket is set
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4'; // Ensures identity key is set
});
const onMessageMock = jest.fn();
await messageBoxClient.listenForLiveMessages({
onMessage: onMessageMock,
messageBox: 'test_inbox'
});
// Ensure `joinRoom` event was emitted with the correct identity key
expect(mockSocket.emit).toHaveBeenCalledWith('joinRoom', '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4-test_inbox');
// Simulate receiving a message
const receivedMessage = { text: 'Hello, world!' };
// Extract & invoke the callback function stored in `on`
const sendMessageCallback = (_a = mockSocket.on.mock.calls.find(([eventName]) => eventName === 'sendMessage-02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4-test_inbox')) === null || _a === void 0 ? void 0 : _a[1]; // Extract the callback function
if (typeof sendMessageCallback === 'function') {
sendMessageCallback(receivedMessage);
}
// Ensure `onMessage` was called with the received message
expect(onMessageMock).toHaveBeenCalledWith(receivedMessage);
});
it('Handles WebSocket connection and disconnection events', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
// Simulate identity key
jest.spyOn(mockWalletClient, 'getPublicKey').mockResolvedValue({ publicKey: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4' });
// Simulate connection + disconnection + auth success
setTimeout(() => {
var _a, _b, _c;
(_a = socketOnMap.connect) === null || _a === void 0 ? void 0 : _a.call(socketOnMap);
(_b = socketOnMap.disconnect) === null || _b === void 0 ? void 0 : _b.call(socketOnMap);
(_c = socketOnMap.authenticationSuccess) === null || _c === void 0 ? void 0 : _c.call(socketOnMap, { status: 'ok' });
}, 100);
await messageBoxClient.initializeConnection();
// Verify event listeners were registered
expect(mockSocket.on).toHaveBeenCalledWith('connect', expect.any(Function));
expect(mockSocket.on).toHaveBeenCalledWith('disconnect', expect.any(Function));
}, 10000);
it('throws an error when recipient is empty in sendLiveMessage', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
// Mock `initializeConnection` so it assigns `socket` & identity key
jest.spyOn(messageBoxClient, 'initializeConnection').mockImplementation(async () => {
Object.defineProperty(messageBoxClient, 'testIdentityKey', { get: () => '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4' });
Object.defineProperty(messageBoxClient, 'testSocket', { get: () => mockSocket });
messageBoxClient.socket = mockSocket; // Ensures internal socket is set
messageBoxClient.myIdentityKey = '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4'; // Ensures identity key is set
});
// Mock socket to ensure WebSocket validation does not fail
const mockSocket = {
emit: jest.fn()
};
jest.spyOn(messageBoxClient, 'testSocket', 'get').mockReturnValue(mockSocket);
await expect(messageBoxClient.sendLiveMessage({
recipient: ' ',
messageBox: 'test_inbox',
body: 'Test message'
})).rejects.toThrow('[MB CLIENT ERROR] Recipient identity key is required');
});
it('throws an error when recipient is missing in sendMessage', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
await expect(messageBoxClient.sendMessage({
recipient: '', // Empty recipient
messageBox: 'test_inbox',
body: 'Test message'
})).rejects.toThrow('You must provide a message recipient!');
await expect(messageBoxClient.sendMessage({
recipient: ' ', // Whitespace recipient
messageBox: 'test_inbox',
body: 'Test message'
})).rejects.toThrow('You must provide a message recipient!');
await expect(messageBoxClient.sendMessage({
recipient: null, // Null recipient
messageBox: 'test_inbox',
body: 'Test message'
})).rejects.toThrow('You must provide a message recipient!');
});
it('throws an error when messageBox is missing in sendMessage', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: '', // Empty messageBox
body: 'Test message'
})).rejects.toThrow('You must provide a messageBox to send this message into!');
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: ' ', // Whitespace messageBox
body: 'Test message'
})).rejects.toThrow('You must provide a messageBox to send this message into!');
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: null, // Null messageBox
body: 'Test message'
})).rejects.toThrow('You must provide a messageBox to send this message into!');
});
it('throws an error when message body is missing in sendMessage', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: '' // Empty body
})).rejects.toThrow('Every message must have a body!');
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: ' ' // Whitespace body
})).rejects.toThrow('Every message must have a body!');
await expect(messageBoxClient.sendMessage({
recipient: '02b463b8ef7f03c47fba2679c7334d13e4939b8ca30dbb6bbd22e34ea3e9b1b0e4',
messageBox: 'test_inbox',
body: null // Null body
})).rejects.toThrow('Every message must have a body!');
});
it('throws an error when messageBox is empty in listMessages', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
await expect(messageBoxClient.listMessages({
messageBox: '' // Empty messageBox
})).rejects.toThrow('MessageBox cannot be empty');
await expect(messageBoxClient.listMessages({
messageBox: ' ' // Whitespace messageBox
})).rejects.toThrow('MessageBox cannot be empty');
});
it('throws an error when messageIds is empty in acknowledgeMessage', async () => {
const messageBoxClient = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://messagebox.babbage.systems',
enableLogging: true
});
await messageBoxClient.init();
await expect(messageBoxClient.acknowledgeMessage({
messageIds: [] // Empty array
})).rejects.toThrow('Message IDs array cannot be empty');
await expect(messageBoxClient.acknowledgeMessage({
messageIds: undefined // Undefined value
})).rejects.toThrow('Message IDs array cannot be empty');
await expect(messageBoxClient.acknowledgeMessage({
messageIds: null // Null value
})).rejects.toThrow('Message IDs array cannot be empty');
await expect(messageBoxClient.acknowledgeMessage({
messageIds: 'invalid' // Not an array
})).rejects.toThrow('Message IDs array cannot be empty');
});
it('Uses default host if none is provided', () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({ walletClient: mockWalletClient });
expect(client.initialized).toBe(false);
expect(client.host).toBe('https://messagebox.babbage.systems');
});
it('Calls init() to set up a default host when missing', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({ walletClient: mockWalletClient });
expect(client.initialized).toBe(false);
await client.init();
expect(client.initialized).toBe(true);
expect(typeof client.host).toBe('string');
expect(client.host.length).toBeGreaterThan(0);
});
it('init() overrides host if passed with override=true', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://original-host.example'
});
expect(client.initialized).toBe(false);
expect(client.host).toBe('https://original-host.example');
await client.init('https://new-host.example');
expect(client.initialized).toBe(true);
expect(client.host).toBe('https://new-host.example');
});
it('does not anoint when advert already exists', async () => {
jest.spyOn(MessageBoxClient_js_1.MessageBoxClient.prototype, 'queryAdvertisements').mockResolvedValue([{
host: 'https://messagebox.babbage.systems'
}]);
const spy = jest.spyOn(MessageBoxClient_js_1.MessageBoxClient.prototype, 'anointHost');
await new MessageBoxClient_js_1.MessageBoxClient({ walletClient: mockWalletClient }).init();
expect(spy).not.toHaveBeenCalled();
});
it('resolveHostForRecipient returns the first advertised host', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://default.box'
});
await client.init();
MessageBoxClient_js_1.MessageBoxClient.prototype.queryAdvertisements
.mockResolvedValueOnce([
{ host: 'https://peer.box' }, { host: 'https://second.box' }
]);
const result = await client.resolveHostForRecipient('02aa…deadbeef');
expect(result).toBe('https://peer.box');
});
it('resolveHostForRecipient falls back to this.host when no adverts exist', async () => {
const client = new MessageBoxClient_js_1.MessageBoxClient({
walletClient: mockWalletClient,
host: 'https://default.box'
});
await client.init();
MessageBoxClient_js_1.MessageBoxClient.prototype.queryAdvertisements
.mockResolvedValueOnce([]);
const result = await client.resolveHostForRecipient('03bb…cafef00d');
expect(result).toBe('https://default.box');
});
});
//# sourceMappingURL=MessageBoxClient.test.js.map