#!/usr/bin/env node
/**
* Test script to verify basic Keet messaging functionality.
* This test uses the actual Keet dependencies directly in Node.js.
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// Get the directory name of the current module
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Configure logging
const logLevels = {
INFO: 'INFO',
ERROR: 'ERROR',
WARNING: 'WARNING'
};
function log(level, message) {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [${level}] ${message}`);
}
// Import Keet dependencies
let KeetBackend, KeetCoreApi;
let KEET_AVAILABLE = false;
try {
// Dynamic imports to handle potential import failures gracefully
const backendModule = await import('@holepunchto/keet-backend');
const coreApiModule = await import('@holepunchto/keet-core-api');
// Try to get the exports
KeetBackend = backendModule.default || backendModule;
KeetCoreApi = coreApiModule.default || coreApiModule;
KEET_AVAILABLE = true;
log(logLevels.INFO, 'Successfully imported Keet dependencies');
} catch (error) {
log(logLevels.WARNING, `Failed to import Keet dependencies: ${error.message}`);
log(logLevels.WARNING, 'This test will be skipped');
}
/**
* Test basic Keet messaging functionality.
*/
async function testKeetMessaging() {
if (!KEET_AVAILABLE) {
log(logLevels.ERROR, 'Keet dependencies not available. Skipping test.');
return false;
}
try {
// Create a test storage directory
const storagePath = path.join(__dirname, '..', 'test-keet-storage');
if (!fs.existsSync(storagePath)) {
fs.mkdirSync(storagePath, { recursive: true });
}
// Initialize Keet backend
log(logLevels.INFO, 'Initializing Keet backend...');
const backend = new KeetBackend(storagePath, {
experimental: false,
devMirrors: false
});
// Wait for backend to be ready
await backend.ready();
// Check if we have an identity
log(logLevels.INFO, 'Checking identity...');
const identity = await backend.api.core.getIdentity();
log(logLevels.INFO, `Current identity: ${JSON.stringify(identity)}`);
// If we don't have an identity, create one
if (!identity) {
log(logLevels.INFO, 'No identity found, generating a new one...');
await backend.api.core.generateIdentity();
const newIdentity = await backend.api.core.getIdentity();
log(logLevels.INFO, `New identity created: ${JSON.stringify(newIdentity)}`);
}
// Use the specific room invite key provided
const roomInviteKey = 'pear://keet/yrb5rjakidnqo5qx3mp6qonhtnw5fuh1ebciz5jrdd14mz8x4xt9kxep31z6d3n4qrqb7eerqp6f9zga5hb6ug9demezyftfarhnu3q571axqgde';
log(logLevels.INFO, `Using room invite key: ${roomInviteKey}`);
// Extract the room key from the invite link
const roomKey = roomInviteKey.replace('pear://keet/', '');
log(logLevels.INFO, `Extracted room key: ${roomKey}`);
// Get recent rooms to check if we already joined this room
log(logLevels.INFO, 'Getting recent rooms to check if we already joined this room...');
const recentRooms = await backend.api.core.getRecentRooms();
log(logLevels.INFO, `Found ${recentRooms.length} recent rooms`);
// Log all rooms for debugging
for (const room of recentRooms) {
log(logLevels.INFO, `Room: ${JSON.stringify(room)}`);
}
// Try to join the room using the room key
log(logLevels.INFO, 'Attempting to join the room...');
// Check if there's a pairRoom method available
if (backend.api.core.pairRoom) {
log(logLevels.INFO, 'Using pairRoom method to join the room...');
try {
await backend.api.core.pairRoom(roomKey);
log(logLevels.INFO, 'Successfully paired with the room');
// Wait for the room to be fully joined
log(logLevels.INFO, 'Waiting for the room to be fully joined (5 seconds)...');
await new Promise(resolve => setTimeout(resolve, 5000));
// Get recent rooms again to find the newly joined room
log(logLevels.INFO, 'Getting recent rooms again to find the newly joined room...');
const updatedRooms = await backend.api.core.getRecentRooms();
log(logLevels.INFO, `Found ${updatedRooms.length} recent rooms after joining`);
// Log all rooms for debugging
for (const room of updatedRooms) {
log(logLevels.INFO, `Room after joining: ${JSON.stringify(room)}`);
}
} catch (error) {
log(logLevels.WARNING, `Failed to pair with room: ${error.message}`);
}
} else {
log(logLevels.WARNING, 'pairRoom method not available');
}
// Get recent rooms one more time to find the room to use
const finalRooms = await backend.api.core.getRecentRooms();
// Use the first room if available
let roomId;
if (finalRooms.length > 0) {
roomId = finalRooms[0].roomId;
log(logLevels.INFO, `Using room: ${roomId}`);
} else {
log(logLevels.ERROR, 'No rooms available');
return false;
}
// Try to get room metadata
try {
log(logLevels.INFO, `Getting room metadata for room: ${roomId}`);
const metadata = await backend.api.core.getLocalRoomMetadata(roomId);
log(logLevels.INFO, `Room metadata: ${JSON.stringify(metadata)}`);
} catch (error) {
log(logLevels.WARNING, `Failed to get room metadata: ${error.message}`);
}
// Try to get room members
try {
log(logLevels.INFO, `Getting room members for room: ${roomId}`);
const members = await backend.api.core.getMembers(roomId);
log(logLevels.INFO, `Room members: ${JSON.stringify(members)}`);
} catch (error) {
log(logLevels.WARNING, `Failed to get room members: ${error.message}`);
}
// Get messages from the room
try {
log(logLevels.INFO, `Getting messages from room: ${roomId}`);
const messages = await backend.api.core.getChatMessages(roomId);
log(logLevels.INFO, `Found ${messages.length} messages in the room`);
// Log all messages for debugging
log(logLevels.INFO, 'Listing all messages:');
for (const message of messages) {
log(logLevels.INFO, `Message: ${JSON.stringify(message)}`);
}
} catch (error) {
log(logLevels.WARNING, `Failed to get messages: ${error.message}`);
log(logLevels.WARNING, 'This might be because the room is not fully joined yet');
}
// Send a test message to the room
try {
const testMessage = 'This is a test message from the Keet messaging test';
log(logLevels.INFO, `Sending a test message to room: ${roomId}`);
await backend.api.core.addChatMessage(roomId, testMessage);
log(logLevels.INFO, 'Test message sent successfully!');
// Get messages again to verify the message was sent
log(logLevels.INFO, 'Getting messages again to verify...');
const updatedMessages = await backend.api.core.getChatMessages(roomId);
log(logLevels.INFO, `Found ${updatedMessages.length} messages in the room after sending`);
// Check if our message was added
let foundOurMessage = false;
for (const message of updatedMessages) {
if (message.chat && message.chat.text === testMessage) {
foundOurMessage = true;
log(logLevels.INFO, `Found our test message: ${JSON.stringify(message)}`);
break;
}
}
if (!foundOurMessage) {
log(logLevels.WARNING, 'Could not find our test message. This might indicate the message was not sent properly.');
// Log all messages for debugging
log(logLevels.INFO, 'Listing all messages after sending:');
for (const message of updatedMessages) {
log(logLevels.INFO, `Message: ${JSON.stringify(message)}`);
}
}
} catch (error) {
log(logLevels.WARNING, `Failed to send message: ${error.message}`);
}
// Keep the connection open for a short time to potentially receive messages
log(logLevels.INFO, 'Waiting for potential incoming messages (5 seconds)...');
await new Promise(resolve => setTimeout(resolve, 5000));
// Try to get messages one more time
try {
log(logLevels.INFO, `Getting messages from room one more time: ${roomId}`);
const finalMessages = await backend.api.core.getChatMessages(roomId);
log(logLevels.INFO, `Found ${finalMessages.length} messages in the room at the end`);
// Log all messages for debugging
log(logLevels.INFO, 'Listing all final messages:');
for (const message of finalMessages) {
log(logLevels.INFO, `Message: ${JSON.stringify(message)}`);
}
} catch (error) {
log(logLevels.WARNING, `Failed to get final messages: ${error.message}`);
}
// Clean up
log(logLevels.INFO, 'Cleaning up...');
// Close the backend
log(logLevels.INFO, 'Closing backend...');
await backend.close();
return true;
} catch (error) {
log(logLevels.ERROR, `Error in Keet messaging test: ${error.message}`);
log(logLevels.ERROR, error.stack);
return false;
}
}
// Run the test if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
try {
const success = await testKeetMessaging();
if (success) {
log(logLevels.INFO, 'Keet messaging test successful!');
process.exit(0);
} else {
log(logLevels.ERROR, 'Keet messaging test failed!');
process.exit(1);
}
} catch (error) {
log(logLevels.ERROR, `Unhandled error: ${error.message}`);
log(logLevels.ERROR, error.stack);
process.exit(1);
}
}
export { testKeetMessaging };