wifi-tally_Oostendam/wifi-tally/hub/spec/VmixConnector.spec.js
Eljakim Herrewijnen 50b5fc1824 Initial commit
2021-09-27 21:52:27 +02:00

182 lines
9.2 KiB
JavaScript

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: '<vmix><version>{version}</version><edition>Trial</edition><inputs><input key="44bcd391-0f5e-433f-8a45-d5960a973a75" number="1" type="Blank" title="Blank" shortTitle="Blank" state="Paused" position="0" duration="0" loop="False">Blank</input><input key="5c6147a9-398b-4013-969f-6b372b0be254" number="2" type="Blank" title="Blank" shortTitle="Blank" state="Paused" position="0" duration="0" loop="False">Blank</input></inputs><overlays><overlay number="1" /><overlay number="2" /><overlay number="3" /><overlay number="4" /><overlay number="5" /><overlay number="6" /></overlays><preview>1</preview><active>1</active><fadeToBlack>False</fadeToBlack><transitions><transition number="1" effect="VerticalSlide" duration="500" /><transition number="2" effect="Merge" duration="1000" /><transition number="3" effect="Wipe" duration="1000" /><transition number="4" effect="CubeZoom" duration="1000" /></transitions><recording>False</recording><external>False</external><streaming>False</streaming><playList>False</playList><multiCorder>False</multiCorder><fullscreen>False</fullscreen><audio><master volume="100" muted="False" meterF1="0" meterF2="0" headphonesVolume="100" /></audio></vmix>'
}
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 = '<vmix><version>{version}</version><edition>Trial</edition><inputs><input key="0182ffa0-9fa9-4514-91af-37ef60240c87" number="1" type="Colour" title="Foobar" shortTitle="Foobar" state="Paused" position="0" duration="0" loop="False">Foobar</input><input key="a108d01e-26f4-466f-a37d-d8f91f3fd6eb" number="2" type="Colour" title="Tolle rote Farbe" shortTitle="Tolle rote Farbe" state="Paused" position="0" duration="0" loop="False">Tolle rote Farbe</input><input key="3f6e4c1b-a13f-46b0-9537-676a4fb17ea3" number="3" type="Colour" title="Colour Bars" shortTitle="Colour Bars" state="Paused" position="0" duration="0" loop="False">Colour Bars</input></inputs><overlays><overlay number="1" /><overlay number="2" /><overlay number="3" /><overlay number="4" /><overlay number="5" /><overlay number="6" /></overlays><preview>2</preview><active>3</active><fadeToBlack>False</fadeToBlack><transitions><transition number="1" effect="VerticalSlide" duration="500" /><transition number="2" effect="Merge" duration="1000" /><transition number="3" effect="Wipe" duration="1000" /><transition number="4" effect="CubeZoom" duration="1000" /></transitions><recording>False</recording><external>False</external><streaming>False</streaming><playList>False</playList><multiCorder>False</multiCorder><fullscreen>False</fullscreen><audio><master volume="100" muted="False" meterF1="0" meterF2="0" headphonesVolume="100" /></audio></vmix>'
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()
}
})
})
})