const VmixConnector = require('../lib/VmixConnector') const net = require('net') const EventEmitter = require('events') const waitUntil = (fn) => { return new Promise((resolve, _) => { setInterval(() => { if (fn() === true) { resolve() } }, 100) }) } class MockCommunicator { constructor(configuration, emitter) { this.isConnected = false this.channelCount this.channelNames this.programs this.previews } notifyProgramChanged(programs, previews) { this.programs = programs this.previews = previews } notifyChannels(count, names) { this.channelCount = count this.channelNames = names } notifyMixerIsConnected() { this.isConnected = true } notifyMixerIsDisconnected() { this.isConnected = false } } describe('VmixConnector', () => { describe('onData', () => { beforeEach(() => { global.vMixServerConfig = { version: "0.1.2.3", tallies: "012", xml: '{version}TrialBlankBlank11FalseFalseFalseFalseFalseFalseFalse' } const server = net.Server((sck) => { sck.on('data', data => { data = data.toString() data.toString().replace(/[\r\n]*$/, "").split("\r\n").forEach(command => { console.debug(`< ${command}`) if(command === "XML") { const response = global.vMixServerConfig.xml.replace("{version}", global.vMixServerConfig.version) sck.write(Buffer.from(`'XML ${response.length}\r\n${response}\r\n`)) } else if(command === "SUBSCRIBE TALLY") { sck.write(Buffer.from("SUBSCRIBE OK TALLY Subscribed\r\n", "utf-8")) setTimeout(() => { sck.writable && sck.write(Buffer.from(`TALLY OK ${global.vMixServerConfig.tallies}\r\n`, "utf-8")) }, 100) } else { console.log(`vMix Mock received an unknown command: ${command}`) } }) }) sck.write(Buffer.from(`VERSION OK ${global.vMixServerConfig.version}\r\n`, "utf-8")) }) const promise = new Promise((resolve, reject) => { server.listen({ port: 0, host: 'localhost', }, (error) => { if (error) { console.error(error) reject(error) } else { global.vMixServerConfig.serverIp = server.address().address global.vMixServerConfig.serverPort = server.address().port resolve() } }) }) global.vMixServerConfig.close = server.close.bind(server) return promise }) afterEach(() => { if (global.vMixServerConfig) { return new Promise((resolve, reject) => { global.vMixServerConfig.close((error) => { if (error) { console.error(error) reject(error) } else { resolve() } }) }) } }) test('recognizes VERSION OK', async () => { const communicator = new MockCommunicator() const server = global.vMixServerConfig const vmix = new VmixConnector(server.serverIp, server.serverPort, communicator) try { expect(vmix.wasHelloReceived).toBe(false) vmix.connect() await waitUntil(() => vmix.wasHelloReceived === true).then(() => expect(vmix.wasHelloReceived).toBe(true) ) } finally { await vmix.disconnect() } }) test('recognizes SUBSCRIBE OK TALLY', async () => { const communicator = new MockCommunicator() const server = global.vMixServerConfig const vmix = new VmixConnector(server.serverIp, server.serverPort, communicator) try { expect(vmix.wasSubcribeOkReceived).toBe(false) vmix.connect() await waitUntil(() => vmix.wasSubcribeOkReceived === true).then(() => expect(vmix.wasSubcribeOkReceived).toBe(true) ) } finally { await vmix.disconnect() } }) test('parses TALLY OK command', async () => { const communicator = new MockCommunicator() const server = global.vMixServerConfig server.tallies = "012" const vmix = new VmixConnector(server.serverIp, server.serverPort, communicator) try { vmix.connect() await waitUntil(() => communicator.programs !== undefined).then(() => { expect(communicator.programs).toEqual([2]) expect(communicator.previews).toEqual([3]) }) } finally { await vmix.disconnect() } }) test('parses complex TALLY OK command', async () => { const communicator = new MockCommunicator() const server = global.vMixServerConfig server.tallies = "012210" const vmix = new VmixConnector(server.serverIp, server.serverPort, communicator) try { vmix.connect() await waitUntil(() => communicator.programs !== undefined).then(() => { expect(communicator.programs).toEqual([2, 5]) expect(communicator.previews).toEqual([3, 4]) }) } finally { await vmix.disconnect() } }) test('recognizes XML response', async () => { const communicator = new MockCommunicator() const server = global.vMixServerConfig server.xml = '{version}TrialFoobarTolle rote FarbeColour Bars23FalseFalseFalseFalseFalseFalseFalse' const vmix = new VmixConnector(server.serverIp, server.serverPort, communicator) try { vmix.connect() await waitUntil(() => communicator.channelCount !== undefined).then(() => { expect(communicator.channelCount).toEqual(3) expect(communicator.channelNames).toEqual({1: "Foobar", 2: "Tolle rote Farbe", 3: "Colour Bars"}) }) } finally { await vmix.disconnect() } }) }) })