#!/usr/bin/env node // Test script for mixed-content message testing // Tests receiving a mix of text, json, table, image, audio, video, and binary data // from JavaScript serviceA to JavaScript serviceB using NATSBridge.js smartreceive // // This test demonstrates that any combination and any number of mixed content // can be sent and received correctly. const { smartreceive, log_trace } = require('./src/NATSBridge'); // Configuration const SUBJECT = "/NATSBridge_mix_test"; const NATS_URL = "nats.yiem.cc"; // Helper: Log with correlation ID function log_trace(message) { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${message}`); } // Receiver: Listen for messages and verify mixed content handling async function test_mix_receive() { // Connect to NATS const { connect } = require('nats'); const nc = await connect({ servers: [NATS_URL] }); // Subscribe to the subject const sub = nc.subscribe(SUBJECT); for await (const msg of sub) { log_trace(`Received message on ${msg.subject}`); // Use NATSBridge.smartreceive to handle the data const result = await smartreceive( msg, { maxRetries: 5, baseDelay: 100, maxDelay: 5000 } ); log_trace(`Received ${result.length} payloads`); // Result is a list of {dataname, data, type} objects for (const { dataname, data, type } of result) { log_trace(`\n=== Payload: ${dataname} (type: ${type}) ===`); // Handle different data types if (type === "text") { // Text data - should be a String if (typeof data === 'string') { log_trace(` Type: String`); log_trace(` Length: ${data.length} characters`); // Display first 200 characters if (data.length > 200) { log_trace(` First 200 chars: ${data.substring(0, 200)}...`); } else { log_trace(` Content: ${data}`); } // Save to file const fs = require('fs'); const output_path = `./received_${dataname}.txt`; fs.writeFileSync(output_path, data); log_trace(` Saved to: ${output_path}`); } else { log_trace(` ERROR: Expected String, got ${typeof data}`); } } else if (type === "dictionary") { // Dictionary data - should be an object if (typeof data === 'object' && data !== null && !Array.isArray(data)) { log_trace(` Type: Object`); log_trace(` Keys: ${Object.keys(data).join(', ')}`); // Display nested content for (const [key, value] of Object.entries(data)) { log_trace(` ${key} => ${value}`); } // Save to JSON file const fs = require('fs'); const output_path = `./received_${dataname}.json`; const json_str = JSON.stringify(data, null, 2); fs.writeFileSync(output_path, json_str); log_trace(` Saved to: ${output_path}`); } else { log_trace(` ERROR: Expected Object, got ${typeof data}`); } } else if (type === "table") { // Table data - should be an array of objects (requires apache-arrow) log_trace(` Type: Array (requires apache-arrow for full deserialization)`); if (Array.isArray(data)) { log_trace(` Length: ${data.length} items`); log_trace(` First item: ${JSON.stringify(data[0])}`); } else { log_trace(` ERROR: Expected Array, got ${typeof data}`); } } else if (type === "image" || type === "audio" || type === "video" || type === "binary") { // Binary data - should be Uint8Array if (data instanceof Uint8Array || Array.isArray(data)) { log_trace(` Type: Uint8Array (binary)`); log_trace(` Size: ${data.length} bytes`); // Save to file const fs = require('fs'); const output_path = `./received_${dataname}.bin`; fs.writeFileSync(output_path, Buffer.from(data)); log_trace(` Saved to: ${output_path}`); } else { log_trace(` ERROR: Expected Uint8Array, got ${typeof data}`); } } else { log_trace(` ERROR: Unknown data type '${type}'`); } } // Summary console.log("\n=== Verification Summary ==="); const text_count = result.filter(x => x.type === "text").length; const dict_count = result.filter(x => x.type === "dictionary").length; const table_count = result.filter(x => x.type === "table").length; const image_count = result.filter(x => x.type === "image").length; const audio_count = result.filter(x => x.type === "audio").length; const video_count = result.filter(x => x.type === "video").length; const binary_count = result.filter(x => x.type === "binary").length; log_trace(`Text payloads: ${text_count}`); log_trace(`Dictionary payloads: ${dict_count}`); log_trace(`Table payloads: ${table_count}`); log_trace(`Image payloads: ${image_count}`); log_trace(`Audio payloads: ${audio_count}`); log_trace(`Video payloads: ${video_count}`); log_trace(`Binary payloads: ${binary_count}`); // Print transport type info for each payload if available console.log("\n=== Payload Details ==="); for (const { dataname, data, type } of result) { if (["image", "audio", "video", "binary"].includes(type)) { log_trace(`${dataname}: ${data.length} bytes (binary)`); } else if (type === "table") { log_trace(`${dataname}: ${data.length} items (Array)`); } else if (type === "dictionary") { log_trace(`${dataname}: ${JSON.stringify(data).length} bytes (Object)`); } else if (type === "text") { log_trace(`${dataname}: ${data.length} characters (String)`); } } } // Keep listening for 2 minutes setTimeout(() => { nc.close(); process.exit(0); }, 120000); } // Run the test console.log("Starting mixed-content transport test..."); console.log("Note: This receiver will wait for messages from the sender."); console.log("Run test_js_to_js_mix_sender.js first to send test data."); // Run receiver console.log("\ntesting smartreceive for mixed content"); test_mix_receive(); console.log("\nTest completed.");