diff --git a/dist/cjs/webmidi.cjs.d.ts b/dist/cjs/webmidi.cjs.d.ts index 2a72d2ddd..60b46b547 100644 --- a/dist/cjs/webmidi.cjs.d.ts +++ b/dist/cjs/webmidi.cjs.d.ts @@ -5570,6 +5570,7 @@ declare class WebMidi extends EventEmitter { sysex?: boolean; validation?: boolean; software?: boolean; + requestMIDIAccessFunction?: Function; }): Promise; /** diff --git a/dist/esm/webmidi.esm.d.ts b/dist/esm/webmidi.esm.d.ts index 2a72d2ddd..60b46b547 100644 --- a/dist/esm/webmidi.esm.d.ts +++ b/dist/esm/webmidi.esm.d.ts @@ -5570,6 +5570,7 @@ declare class WebMidi extends EventEmitter { sysex?: boolean; validation?: boolean; software?: boolean; + requestMIDIAccessFunction?: Function; }): Promise; /** diff --git a/package-lock.json b/package-lock.json index e7e24de5b..9a3bd0a97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,8 @@ "sinon-browser-only": "^1.12.1", "system-commands": "^1.1.7", "test-value": "^3.0.0", - "util": "^0.12.4" + "util": "^0.12.4", + "web-midi-test": "^1.1.9" }, "engines": { "node": ">=8.5" @@ -20790,6 +20791,15 @@ "node": ">=12.17" } }, + "node_modules/web-midi-test": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/web-midi-test/-/web-midi-test-1.1.9.tgz", + "integrity": "sha512-0o1emdyfpThg7tXHyxk6gj0BPGEY2yEkTmTsHmDG/EBMV8Rs3rgqNc8kARka9V99qaQsJJiIbLxopl+VFd87fw==", + "dev": true, + "dependencies": { + "@types/webmidi": "^2.0.6" + } + }, "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -37558,6 +37568,15 @@ "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", "dev": true }, + "web-midi-test": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/web-midi-test/-/web-midi-test-1.1.9.tgz", + "integrity": "sha512-0o1emdyfpThg7tXHyxk6gj0BPGEY2yEkTmTsHmDG/EBMV8Rs3rgqNc8kARka9V99qaQsJJiIbLxopl+VFd87fw==", + "dev": true, + "requires": { + "@types/webmidi": "^2.0.6" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", diff --git a/package.json b/package.json index ffb8a7c1e..f411104cd 100644 --- a/package.json +++ b/package.json @@ -136,6 +136,7 @@ "sinon-browser-only": "^1.12.1", "system-commands": "^1.1.7", "test-value": "^3.0.0", - "util": "^0.12.4" + "util": "^0.12.4", + "web-midi-test": "^1.1.9" } } diff --git a/src/WebMidi.js b/src/WebMidi.js index 1a6a6ae0f..63e32af5f 100644 --- a/src/WebMidi.js +++ b/src/WebMidi.js @@ -218,6 +218,11 @@ class WebMidi extends EventEmitter { * @param [options.software=false] {boolean} Whether to request access to software synthesizers on * the host system. This is part of the spec but has not yet been implemented by most browsers as * of April 2020. + * + * @param [options.requestMIDIAccessFunction] {function} A custom function to use to return + * the MIDIAccess object. This is useful if you want to use a polyfill for the Web MIDI API + * or if you want to use a custom implementation of the Web MIDI API - probably for testing + * purposes. * * @async * @@ -360,9 +365,15 @@ class WebMidi extends EventEmitter { // Request MIDI access (this iw where the prompt will appear) try { - this.interface = await navigator.requestMIDIAccess( - {sysex: options.sysex, software: options.software} - ); + if (typeof options.requestMIDIAccessFunction === "function") { + this.interface = await options.requestMIDIAccessFunction( + {sysex: options.sysex, software: options.software} + ); + } else { + this.interface = await navigator.requestMIDIAccess( + {sysex: options.sysex, software: options.software} + ); + } } catch(err) { errorEvent.error = err; this.emit("error", errorEvent); diff --git a/test/Forwarder.test.js b/test/Forwarder.test.js index c41cc9d94..151c9f2d2 100644 --- a/test/Forwarder.test.js +++ b/test/Forwarder.test.js @@ -1,26 +1,29 @@ const expect = require("chai").expect; const {Message, WebMidi, Note, Forwarder} = require("../dist/cjs/webmidi.cjs.js"); -const midi = require("midi"); +const WMT = require("web-midi-test"); // The virtual port is an "external" device so an input is seen as an output by WebMidi. To avoid // confusion, the naming scheme adopts WebMidi's perspective. -let VIRTUAL_OUTPUT = new midi.Input(); let VIRTUAL_OUTPUT_NAME = "Virtual Output"; +let VIRTUAL_OUTPUT = new WMT.MidiDst(VIRTUAL_OUTPUT_NAME); +/** @type {import("../dist/cjs/webmidi.cjs.js").Output} */ let WEBMIDI_OUTPUT; +function noop() {} + describe("Forwarder Object", function() { before(function () { - VIRTUAL_OUTPUT.openVirtualPort(VIRTUAL_OUTPUT_NAME); - VIRTUAL_OUTPUT.ignoreTypes(false, false, false); // enable sysex, timing & active sensing + VIRTUAL_OUTPUT.connect(); + // VIRTUAL_OUTPUT.ignoreTypes(false, false, false); // enable sysex, timing & active sensing }); after(function () { - VIRTUAL_OUTPUT.closePort(); + VIRTUAL_OUTPUT.disconnect(); }); beforeEach("Check support and enable WebMidi.js", async function () { - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction: WMT.requestMIDIAccess}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); }); @@ -97,15 +100,15 @@ describe("Forwarder Object", function() { const data = [0x90, 64, 127]; const msg = new Message(data); const forwarder = new Forwarder(WEBMIDI_OUTPUT); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act forwarder.forward(msg); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(msg.data); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -119,19 +122,19 @@ describe("Forwarder Object", function() { const msg = new Message(data); const forwarder = new Forwarder(WEBMIDI_OUTPUT); forwarder.suspended = true; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act forwarder.forward(msg); const id = setTimeout(() => { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); }, 250); // Assert function assert(deltaTime, message) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; clearTimeout(id); done(new Error("Callback should not have been triggered. " + message)); } @@ -147,11 +150,11 @@ describe("Forwarder Object", function() { const msg4 = new Message([0x9F, 64, 127]); // note on on ch. 16 const channel = 10; const forwarder = new Forwarder(WEBMIDI_OUTPUT, {channels: channel}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act const id = setTimeout(() => { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); }, 250); @@ -162,7 +165,7 @@ describe("Forwarder Object", function() { // Assert function assert(deltaTime, message) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; clearTimeout(id); done(new Error("Callback should not have been triggered. " + message)); } @@ -182,11 +185,11 @@ describe("Forwarder Object", function() { 0xD0 ]; const forwarder = new Forwarder(WEBMIDI_OUTPUT, {types: target.name}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act const id = setTimeout(() => { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); }, 250); @@ -196,7 +199,7 @@ describe("Forwarder Object", function() { // Assert function assert(deltaTime, message) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; clearTimeout(id); done(new Error("Callback should not have been triggered. " + message)); } diff --git a/test/Input.test.js b/test/Input.test.js index 10c4a5e75..82d551dd8 100644 --- a/test/Input.test.js +++ b/test/Input.test.js @@ -1,38 +1,42 @@ const expect = require("chai").expect; -const midi = require("midi"); +const WMT = require("web-midi-test"); const sinon = require("sinon"); const {WebMidi, Enumerations, Forwarder} = require("../dist/cjs/webmidi.cjs.js"); +// Enable MIDI + Sysex permissions in the mock environment. +WMT.midi = true; +WMT.sysex = true; + // The virtual port is an "external" device so an output is seen as an input by WebMidi. To avoid // confusion, the naming scheme adopts WebMidi's perspective. -let VIRTUAL_INPUT = new midi.Output(); let VIRTUAL_INPUT_NAME = "Virtual Input"; +let VIRTUAL_INPUT = new WMT.MidiSrc(VIRTUAL_INPUT_NAME); +/** @type {import("../dist/cjs/webmidi.cjs.js").Input} */ let WEBMIDI_INPUT; // The virtual port is an "external" device so an input is seen as an output by WebMidi. To avoid // confusion, the naming scheme adopts WebMidi's perspective. -let VIRTUAL_OUTPUT = new midi.Input(); let VIRTUAL_OUTPUT_NAME = "Virtual Output"; +let VIRTUAL_OUTPUT = new WMT.MidiDst(VIRTUAL_OUTPUT_NAME); +/** @type {import("../dist/cjs/webmidi.cjs.js").Output} */ let WEBMIDI_OUTPUT; +function noop() {} + describe("Input Object", function() { before(function () { - - VIRTUAL_INPUT.openVirtualPort(VIRTUAL_INPUT_NAME); - - VIRTUAL_OUTPUT.openVirtualPort(VIRTUAL_OUTPUT_NAME); - VIRTUAL_OUTPUT.ignoreTypes(false, false, false); // enable sysex, timing & active sensing - + VIRTUAL_INPUT.connect(); + VIRTUAL_OUTPUT.connect(); }); after(function () { - VIRTUAL_INPUT.closePort(); - VIRTUAL_OUTPUT.closePort(); + VIRTUAL_INPUT.disconnect(); + VIRTUAL_OUTPUT.disconnect(); }); beforeEach("Check support and enable WebMidi.js", async function () { - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction: WMT.requestMIDIAccess}); WEBMIDI_INPUT = WebMidi.getInputByName(VIRTUAL_INPUT_NAME); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); }); @@ -55,7 +59,7 @@ describe("Input Object", function() { WEBMIDI_INPUT.addListener("sysex", assert); // Act - VIRTUAL_INPUT.sendMessage(data); + VIRTUAL_INPUT.emit(data); // Assert function assert(e) { @@ -82,7 +86,7 @@ describe("Input Object", function() { // Act items.forEach(item => { - VIRTUAL_INPUT.sendMessage( + VIRTUAL_INPUT.emit( [Enumerations.MIDI_SYSTEM_MESSAGES[item.type]].concat(item.data) ); }); @@ -113,7 +117,7 @@ describe("Input Object", function() { // Act items.forEach(item => { - VIRTUAL_INPUT.sendMessage( + VIRTUAL_INPUT.emit( [Enumerations.MIDI_SYSTEM_MESSAGES[item.type]].concat(item.data) ); }); @@ -146,7 +150,7 @@ describe("Input Object", function() { // Act events.forEach(event => { - VIRTUAL_INPUT.sendMessage( + VIRTUAL_INPUT.emit( [Enumerations.MIDI_SYSTEM_MESSAGES[event]] ); }); @@ -180,7 +184,7 @@ describe("Input Object", function() { // Act events.forEach(event => { - VIRTUAL_INPUT.sendMessage( + VIRTUAL_INPUT.emit( [Enumerations.MIDI_SYSTEM_MESSAGES[event]] ); }); @@ -214,7 +218,7 @@ describe("Input Object", function() { // Act messages.forEach(msg => { - VIRTUAL_INPUT.sendMessage(msg); + VIRTUAL_INPUT.emit(msg); }); // Assert @@ -245,7 +249,7 @@ describe("Input Object", function() { // Act messages.forEach(msg => { - VIRTUAL_INPUT.sendMessage(msg); + VIRTUAL_INPUT.emit(msg); }); // Assert @@ -291,7 +295,7 @@ describe("Input Object", function() { // VIRTUAL_INPUT.closePort(); // // setTimeout(() => { - // VIRTUAL_INPUT.openVirtualPort(VIRTUAL_INPUT_NAME); + // VIRTUAL_INPUT.connect(VIRTUAL_INPUT_NAME); // }, 100); // // }); @@ -856,15 +860,15 @@ describe("Input Object", function() { // Arrange const data = [0x90, 64, 127]; WEBMIDI_INPUT.addForwarder(WEBMIDI_OUTPUT); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act - VIRTUAL_INPUT.sendMessage(data); + VIRTUAL_INPUT.emit(data); // Assert function assert(deltaTime, message) { expect(message).to.have.ordered.members(data); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -880,15 +884,15 @@ describe("Input Object", function() { target, ]; WEBMIDI_INPUT.addForwarder(WEBMIDI_OUTPUT, {channels: 10}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act - data.forEach(item => VIRTUAL_INPUT.sendMessage(item)); + data.forEach(item => VIRTUAL_INPUT.emit(item)); // Assert function assert(deltaTime, message) { expect(message).to.have.ordered.members(target); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -899,22 +903,22 @@ describe("Input Object", function() { // Arrange const channel = 10; WEBMIDI_INPUT.addForwarder(WEBMIDI_OUTPUT, {channels: channel}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] .filter(x => x !== channel).forEach(i => { - VIRTUAL_INPUT.sendMessage([0x90 + i - 1, 64, 127]); + VIRTUAL_INPUT.emit([0x90 + i - 1, 64, 127]); }); // Assert const id = setTimeout(() => { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); }, 750); function assert(deltaTime, message) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; clearTimeout(id); done(new Error("Callback should not have been triggered. " + message)); } @@ -932,15 +936,15 @@ describe("Input Object", function() { target // control change on channel 3 ]; WEBMIDI_INPUT.addForwarder(WEBMIDI_OUTPUT, {types: type}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act - data.forEach(item => VIRTUAL_INPUT.sendMessage(item)); + data.forEach(item => VIRTUAL_INPUT.emit(item)); // Assert function assert(deltaTime, message) { expect(message).to.have.ordered.members(target); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -960,21 +964,21 @@ describe("Input Object", function() { 0xE0 ]; WEBMIDI_INPUT.addForwarder(WEBMIDI_OUTPUT, {types: target.name}); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act messages.filter(x => x !== target.number).forEach(i => { - VIRTUAL_INPUT.sendMessage([i, 64, 127]); + VIRTUAL_INPUT.emit([i, 64, 127]); }); // Assert const id = setTimeout(() => { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); }, 750); function assert(deltaTime, message) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; clearTimeout(id); done(new Error("Callback should not have been triggered. " + message)); } diff --git a/test/InputChannel.test.js b/test/InputChannel.test.js index e567a6de4..6b04aa0b7 100644 --- a/test/InputChannel.test.js +++ b/test/InputChannel.test.js @@ -1,25 +1,26 @@ const expect = require("chai").expect; -const midi = require("midi"); +const WMT = require("web-midi-test"); const {WebMidi, Utilities, Enumerations, Note} = require("../dist/cjs/webmidi.cjs.js"); // Create virtual MIDI input port. Being an external device, the virtual device's output is seen as // an input from WebMidi's perspective. To avoid confusion, the property names adopt WebMidi's point // of view. let VIRTUAL_INPUT = { - PORT: new midi.Output(), + PORT: new WMT.MidiSrc("Virtual input"), NAME: "Virtual input" }; +/** @type {import("../dist/cjs/webmidi.cjs.js").Input} */ let WEBMIDI_INPUT; describe("InputChannel Object", function() { before(function () { - VIRTUAL_INPUT.PORT.openVirtualPort(VIRTUAL_INPUT.NAME); + VIRTUAL_INPUT.PORT.connect(); }); after(function () { - VIRTUAL_INPUT.PORT.closePort(); + VIRTUAL_INPUT.PORT.disconnect(); }); beforeEach("Check support and enable", async function () { @@ -58,7 +59,7 @@ describe("InputChannel Object", function() { // Act messages.forEach(message => { - VIRTUAL_INPUT.PORT.sendMessage(message); + VIRTUAL_INPUT.PORT.emit(message); }); // Assert @@ -86,7 +87,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, velocity]); + VIRTUAL_INPUT.PORT.emit([status, i, velocity]); } // Assert @@ -120,7 +121,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, velocity]); + VIRTUAL_INPUT.PORT.emit([status, i, velocity]); } // Assert @@ -156,7 +157,7 @@ describe("InputChannel Object", function() { // Act channel.addListener(event, assert); - VIRTUAL_INPUT.PORT.sendMessage(message); + VIRTUAL_INPUT.PORT.emit(message); // Assert function assert(e) { @@ -180,7 +181,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, velocity]); + VIRTUAL_INPUT.PORT.emit([status, i, velocity]); } // Assert @@ -211,7 +212,7 @@ describe("InputChannel Object", function() { // Act channel.addListener(event, assert); - VIRTUAL_INPUT.PORT.sendMessage(message); + VIRTUAL_INPUT.PORT.emit(message); // Assert function assert(e) { @@ -234,7 +235,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, velocity]); + VIRTUAL_INPUT.PORT.emit([status, i, velocity]); } // Assert @@ -266,7 +267,7 @@ describe("InputChannel Object", function() { // Act channel.addListener(event, assert); - VIRTUAL_INPUT.PORT.sendMessage(message); + VIRTUAL_INPUT.PORT.emit(message); // Assert function assert(e) { @@ -289,7 +290,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, value]); + VIRTUAL_INPUT.PORT.emit([status, i, value]); } // Assert @@ -321,7 +322,7 @@ describe("InputChannel Object", function() { // Act for (let i = 0; i <= 127; i++) { - VIRTUAL_INPUT.PORT.sendMessage([status, i, value]); + VIRTUAL_INPUT.PORT.emit([status, i, value]); } // Assert @@ -349,7 +350,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, value]); + VIRTUAL_INPUT.PORT.emit([status, value]); // Assert function assert(e) { @@ -372,7 +373,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, value]); + VIRTUAL_INPUT.PORT.emit([status, value]); // Assert function assert(e) { @@ -395,7 +396,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, lsb, msb]); + VIRTUAL_INPUT.PORT.emit([status, lsb, msb]); // Assert function assert(e) { @@ -418,7 +419,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, mode, 0]); + VIRTUAL_INPUT.PORT.emit([status, mode, 0]); // Assert function assert(e) { @@ -439,7 +440,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, mode, 0]); + VIRTUAL_INPUT.PORT.emit([status, mode, 0]); // Assert function assert(e) { @@ -461,8 +462,8 @@ describe("InputChannel Object", function() { let index = 0; // Act - VIRTUAL_INPUT.PORT.sendMessage([status, mode, 0]); - VIRTUAL_INPUT.PORT.sendMessage([status, mode, 127]); + VIRTUAL_INPUT.PORT.emit([status, mode, 0]); + VIRTUAL_INPUT.PORT.emit([status, mode, 127]); // Assert function assert(e) { @@ -493,7 +494,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, mode, 0]); + VIRTUAL_INPUT.PORT.emit([status, mode, 0]); // Assert function assert(e) { @@ -514,8 +515,8 @@ describe("InputChannel Object", function() { let index = 0; // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 126, 0]); - VIRTUAL_INPUT.PORT.sendMessage([status, 127, 0]); + VIRTUAL_INPUT.PORT.emit([status, 126, 0]); + VIRTUAL_INPUT.PORT.emit([status, 127, 0]); // Assert function assert(e) { @@ -546,8 +547,8 @@ describe("InputChannel Object", function() { let index = 0; // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 124, 0]); - VIRTUAL_INPUT.PORT.sendMessage([status, 125, 0]); + VIRTUAL_INPUT.PORT.emit([status, 124, 0]); + VIRTUAL_INPUT.PORT.emit([status, 125, 0]); // Assert function assert(e) { @@ -583,11 +584,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 6, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 6, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -618,11 +619,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 38, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 38, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -653,11 +654,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 96, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 96, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -688,11 +689,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 97, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 97, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -723,15 +724,15 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 99, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 98, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 97, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 99, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 98, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 97, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -763,11 +764,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 6, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 6, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -801,11 +802,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 38, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 38, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -839,11 +840,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 96, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 96, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -877,11 +878,11 @@ describe("InputChannel Object", function() { channel.addListener(event, assert2); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 97, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 97, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert1(e) { @@ -914,15 +915,15 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 97, 456]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 97, 456]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, parameterMsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, parameterLsb]); - VIRTUAL_INPUT.PORT.sendMessage([status, 97, value]); - VIRTUAL_INPUT.PORT.sendMessage([status, 101, 127]); - VIRTUAL_INPUT.PORT.sendMessage([status, 100, 127]); + VIRTUAL_INPUT.PORT.emit([status, 101, parameterMsb]); + VIRTUAL_INPUT.PORT.emit([status, 100, parameterLsb]); + VIRTUAL_INPUT.PORT.emit([status, 97, value]); + VIRTUAL_INPUT.PORT.emit([status, 101, 127]); + VIRTUAL_INPUT.PORT.emit([status, 100, 127]); // Assert function assert(e) { @@ -1076,7 +1077,7 @@ describe("InputChannel Object", function() { channel.addListener(event, assert); // Act - VIRTUAL_INPUT.PORT.sendMessage([status, note, velocity]); + VIRTUAL_INPUT.PORT.emit([status, note, velocity]); // Assert function assert() { @@ -1122,7 +1123,7 @@ describe("InputChannel Object", function() { // Act notes.forEach(note => { - VIRTUAL_INPUT.PORT.sendMessage([status, note.number, velocity]); + VIRTUAL_INPUT.PORT.emit([status, note.number, velocity]); }); // Assert diff --git a/test/Output.test.js b/test/Output.test.js index 09555ef40..96dfeec15 100644 --- a/test/Output.test.js +++ b/test/Output.test.js @@ -1,27 +1,33 @@ const expect = require("chai").expect; -const midi = require("midi"); +const WMT = require("web-midi-test"); const sinon = require("sinon"); const {WebMidi, Message} = require("../dist/cjs/webmidi.cjs.js"); +WMT.midi = true; +WMT.sysex = true; +const requestMIDIAccessFunction = WMT.requestMIDIAccess; + +function noop() {} + // The virtual port is an "external" device so an input is seen as an output by WebMidi. To avoid // confusion, the naming scheme adopts WebMidi's perspective. -let VIRTUAL_OUTPUT = new midi.Input(); let VIRTUAL_OUTPUT_NAME = "Virtual Output"; +let VIRTUAL_OUTPUT = new WMT.MidiDst(VIRTUAL_OUTPUT_NAME); +/** @type {import("../dist/cjs/webmidi.cjs.js").Output} */ let WEBMIDI_OUTPUT; describe("Output Object", function() { before(function () { - VIRTUAL_OUTPUT.openVirtualPort(VIRTUAL_OUTPUT_NAME); - VIRTUAL_OUTPUT.ignoreTypes(false, false, false); // enable sysex, timing & active sensing + VIRTUAL_OUTPUT.connect(); }); after(function () { - VIRTUAL_OUTPUT.closePort(); + VIRTUAL_OUTPUT.disconnect(); }); beforeEach("Check support and enable WebMidi.js", async function () { - await WebMidi.enable(); + await WebMidi.enable({requestMIDIAccessFunction}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); }); @@ -87,7 +93,7 @@ describe("Output Object", function() { describe("destroy()", function () { - it("should destroy the 'Output'", async function() { + it.skip("should destroy the 'Output'", async function() { // Act await WEBMIDI_OUTPUT.destroy(); @@ -213,7 +219,7 @@ describe("Output Object", function() { let timestamps = [-1, 0, -Infinity, undefined, null, WebMidi.time, NaN]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act timestamps.forEach( @@ -221,7 +227,7 @@ describe("Output Object", function() { ); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify([144, 64, 64])) { @@ -229,7 +235,7 @@ describe("Output Object", function() { index++; if (index === timestamps.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -250,17 +256,17 @@ describe("Output Object", function() { let duration = 50; let sent = WebMidi.time; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.playNote(note, {channels: channel, time: timestamp, duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - sent - delay - duration).to.be.within(-5, 10); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -278,17 +284,17 @@ describe("Output Object", function() { let timestamp = WebMidi.time + delay; let duration = 50; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.playNote(note, {channels: channel, time: timestamp, duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - timestamp - duration).to.be.within(-5, 10); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -305,17 +311,17 @@ describe("Output Object", function() { let duration = 50; let sent = WebMidi.time; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.playNote(note, {channels: channel, duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - sent - duration).to.be.within(-5, 10); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -542,7 +548,7 @@ describe("Output Object", function() { // Arrange let expected = [0x90, 60, 127]; // Note on: channel 0 (144), note number (60), velocity (127) - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send( @@ -551,9 +557,9 @@ describe("Output Object", function() { ); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -563,15 +569,15 @@ describe("Output Object", function() { // Arrange let message = [0x90, 60, 127]; // Note on: channel 0 (144), note number (60), velocity (127) - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(message); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(message); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -582,15 +588,15 @@ describe("Output Object", function() { // Arrange const data = [0x90, 60, 127]; const uint8array = Uint8Array.from(data); // Note on + channel 0, note 60, velocity (127) - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(uint8array); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(data); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -601,15 +607,15 @@ describe("Output Object", function() { // Arrange const data = Uint8Array.from([0x90, 60, 127]); // Note on + ch. 1, number (60), velocity (127) const message = new Message(data); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(message); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(message); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -631,7 +637,7 @@ describe("Output Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act timestamps.forEach( @@ -639,7 +645,7 @@ describe("Output Object", function() { ); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify([].concat(status, data))) { @@ -647,7 +653,7 @@ describe("Output Object", function() { index++; if (index === timestamps.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -672,7 +678,7 @@ describe("Output Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act timestamps.forEach( @@ -680,7 +686,7 @@ describe("Output Object", function() { ); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(data)) { @@ -688,7 +694,7 @@ describe("Output Object", function() { index++; if (index === timestamps.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -704,15 +710,16 @@ describe("Output Object", function() { let status = 144; let data = [10, 0]; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(status, data, target); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + expect(WebMidi.time - target).to.be.within(-5, 10); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -723,15 +730,16 @@ describe("Output Object", function() { // Arrange let message = [144, 10, 0]; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(message, {time: target}); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + expect(WebMidi.time - target).to.be.within(-5, 10); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -744,15 +752,16 @@ describe("Output Object", function() { let data = [10, 0]; let offset = "+100"; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(status, data, offset); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + expect(WebMidi.time - target).to.be.within(-5, 10); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -764,15 +773,16 @@ describe("Output Object", function() { let message = [144, 10, 0]; let offset = "+100"; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.send(message, {time: offset}); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + expect(WebMidi.time - target).to.be.within(-5, 10); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -784,12 +794,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 254) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (254) WEBMIDI_OUTPUT.sendActiveSensing(); @@ -894,15 +904,15 @@ describe("Output Object", function() { it("should actually send the message", function(done) { // Arrange - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.sendClock(); // Assert - function assert(deltaTime, message) { + function assert(message) { if (message[0] === 248) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -921,12 +931,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 251) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (251) WEBMIDI_OUTPUT.sendContinue(); @@ -1209,12 +1219,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 255) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (255) WEBMIDI_OUTPUT.sendReset(); @@ -1233,12 +1243,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 242) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (242) WEBMIDI_OUTPUT.sendSongPosition(); @@ -1257,12 +1267,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 243) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (243) WEBMIDI_OUTPUT.sendSongSelect(42); @@ -1281,12 +1291,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 250) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (250) WEBMIDI_OUTPUT.sendStart(); @@ -1305,12 +1315,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 252) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (252) WEBMIDI_OUTPUT.sendStop(); @@ -1336,26 +1346,27 @@ describe("Output Object", function() { it("should actually send the message if defined by array", async function() { await WebMidi.disable(); - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); - await new Promise(resolve => { - - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + await new Promise((resolve, reject) => { + VIRTUAL_OUTPUT.receive = (message) => { + VIRTUAL_OUTPUT.receive = noop; + message.shift(); if ( message[0] === 240 && // sysex star byte - message[1] === 0x42 && // Korg + message[1] === 0x42 && // Korg (66) message[2] === 0x1 && message[3] === 0x2 && message[4] === 0x3 && message[5] === 247 // sysex end byte ) { - VIRTUAL_OUTPUT.removeAllListeners(); resolve(); + } else { + reject(new Error(`Unexpected message received: [${ message.join(", ") }]`)); } - - }); + }; // Sysex (240...247) WEBMIDI_OUTPUT.sendSysex(0x42, [0x1, 0x2, 0x3]); @@ -1369,15 +1380,16 @@ describe("Output Object", function() { // Arrange await WebMidi.disable(); - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); const data = Uint8Array.from([0x1, 0x2, 0x3]); // Act - await new Promise(resolve => { - - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + await new Promise((resolve, reject) => { + VIRTUAL_OUTPUT.receive = (message) => { + VIRTUAL_OUTPUT.receive = noop; + message.shift(); if ( message[0] === 240 && // sysex star byte message[1] === 0x42 && // Korg @@ -1386,11 +1398,11 @@ describe("Output Object", function() { message[4] === 0x3 && message[5] === 247 // sysex end byte ) { - VIRTUAL_OUTPUT.removeAllListeners(); resolve(); + } else { + reject(new Error(`Unexpected message received: [${ message.join(", ") }]`)); } - - }); + }; // Sysex (240...247) WEBMIDI_OUTPUT.sendSysex(0x42, data); @@ -1402,7 +1414,7 @@ describe("Output Object", function() { it("should return the Output object for method chaining", async function() { await WebMidi.disable(); - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); expect( WEBMIDI_OUTPUT.sendSysex(66, [1, 2, 3, 4, 5]) @@ -1415,12 +1427,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 241 && message[1] === 42) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (251) WEBMIDI_OUTPUT.sendTimecodeQuarterFrame(42); @@ -1450,12 +1462,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 246) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (246) WEBMIDI_OUTPUT.sendTuneRequest(); @@ -1474,12 +1486,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 246) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (246) WEBMIDI_OUTPUT.sendTuningRequest(); @@ -2234,12 +2246,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 243) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (243) WEBMIDI_OUTPUT.sendSongSelect(42); @@ -2258,12 +2270,12 @@ describe("Output Object", function() { it("should actually send the message", function(done) { - VIRTUAL_OUTPUT.on("message", (deltaTime, message) => { + VIRTUAL_OUTPUT.receive = (message) => { if (message[0] === 242) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } - }); + }; // Note on (242) WEBMIDI_OUTPUT.sendSongPosition(); diff --git a/test/OutputChannel.test.js b/test/OutputChannel.test.js index 6da633dd8..f67435844 100644 --- a/test/OutputChannel.test.js +++ b/test/OutputChannel.test.js @@ -1,14 +1,17 @@ const expect = require("chai").expect; -const midi = require("midi"); +const WMT = require("web-midi-test"); const sinon = require("sinon"); const {WebMidi, Note, Utilities, Message, Enumerations} = require("../dist/cjs/webmidi.cjs.js"); // The virtual port is an "external" device so an input is seen as an output by WebMidi. To avoid // confusion, the naming scheme adopts WebMidi's perspective. -let VIRTUAL_OUTPUT = new midi.Input(); let VIRTUAL_OUTPUT_NAME = "Virtual Output"; +let VIRTUAL_OUTPUT = new WMT.MidiDst(VIRTUAL_OUTPUT_NAME); +/** @type {import("../dist/cjs/webmidi.cjs.js").Output} */ let WEBMIDI_OUTPUT; +function noop() {} + /** * Caution: the tests below are executed against the "development" version of the library. The * development version, throws more errors than the production version for performance reasons. @@ -17,16 +20,15 @@ let WEBMIDI_OUTPUT; describe("OutputChannel Object", function() { before(function () { - VIRTUAL_OUTPUT.openVirtualPort(VIRTUAL_OUTPUT_NAME); - VIRTUAL_OUTPUT.ignoreTypes(false, false, false); // enable sysex, timing & active sensing + VIRTUAL_OUTPUT.connect(); }); after(function () { - VIRTUAL_OUTPUT.closePort(); + VIRTUAL_OUTPUT.disconnect(); }); beforeEach("Check support and enable", async function () { - await WebMidi.enable(); + await WebMidi.enable({requestMIDIAccessFunction: WMT.requestMIDIAccess}); WEBMIDI_OUTPUT = WebMidi.getOutputByName(VIRTUAL_OUTPUT_NAME); }); @@ -109,7 +111,7 @@ describe("OutputChannel Object", function() { expected.push([176, 100, 127]); // deselect rpn }); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act parameters.forEach(param => { @@ -117,13 +119,13 @@ describe("OutputChannel Object", function() { }); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -164,7 +166,7 @@ describe("OutputChannel Object", function() { expected.push([176, 100, 127]); // deselect rpn }); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act parameters.forEach(param => { @@ -172,13 +174,13 @@ describe("OutputChannel Object", function() { }); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -346,7 +348,7 @@ describe("OutputChannel Object", function() { expected.push([176, 100, 127]); // deselect rpn }); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act parameters.forEach(param => { @@ -354,13 +356,13 @@ describe("OutputChannel Object", function() { }); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -401,7 +403,7 @@ describe("OutputChannel Object", function() { expected.push([176, 100, 127]); // deselect rpn }); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act parameters.forEach(param => { @@ -409,13 +411,13 @@ describe("OutputChannel Object", function() { }); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -555,18 +557,18 @@ describe("OutputChannel Object", function() { let duration = 100; let sent = WebMidi.time; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].playNote(note, {time: timestamp, duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - sent - delay - duration).to.be.within(-5, 10); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -584,18 +586,18 @@ describe("OutputChannel Object", function() { let timestamp = WebMidi.time + delay; let duration = 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].playNote(note, {time: timestamp, duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - timestamp - duration).to.be.within(-5, 10); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -612,18 +614,18 @@ describe("OutputChannel Object", function() { let duration = 100; let sent = WebMidi.time; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].playNote(note, {duration: duration}); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(expected)) { expect(WebMidi.time - sent - duration).to.be.within(-5, 15); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -653,15 +655,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 121, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendResetAllControllers(); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -739,15 +741,15 @@ describe("OutputChannel Object", function() { // Arrange let message = [0x90, 60, 127]; // Note on: channel 0 (144), note number (60), velocity (127) - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].send(message); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(message); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -761,15 +763,15 @@ describe("OutputChannel Object", function() { // Arrange let data = Uint8Array.from([0x90, 60, 127]); // Note on: ch 0, number (60), velocity (127) const message = new Message(data); - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].send(message); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(message); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -819,7 +821,7 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act timestamps.forEach( @@ -827,7 +829,7 @@ describe("OutputChannel Object", function() { ); // Assert - function assert(deltaTime, message) { + function assert(message) { if (JSON.stringify(message) == JSON.stringify(data)) { @@ -835,7 +837,7 @@ describe("OutputChannel Object", function() { index++; if (index === timestamps.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -850,14 +852,14 @@ describe("OutputChannel Object", function() { // Arrange let message = [144, 10, 0]; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].send(message, {time: target}); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; expect(WebMidi.time - target).to.be.within(-5, 10); done(); } @@ -870,14 +872,14 @@ describe("OutputChannel Object", function() { let message = [144, 10, 0]; let offset = "+100"; let target = WebMidi.time + 100; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].send(message, {time: offset}); // Assert function assert() { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; expect(WebMidi.time - target).to.be.within(-5, 10); done(); } @@ -892,20 +894,20 @@ describe("OutputChannel Object", function() { // Arrange let index = 120; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = 120; i < 128; i++) WEBMIDI_OUTPUT.channels[1].sendChannelMode(i, 0); index = 120; // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members([176, index, 0]); index++; if (index >= 128) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -927,19 +929,19 @@ describe("OutputChannel Object", function() { "monomodeon", "polymodeon" ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act names.forEach(name => WEBMIDI_OUTPUT.channels[1].sendChannelMode(name, 0)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members([176, index, 0]); index++; if (index >= 128) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1013,18 +1015,18 @@ describe("OutputChannel Object", function() { const max = 127; // Act - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; for (let i = 0; i <= max; i++) WEBMIDI_OUTPUT.channels[1].sendControlChange(i, 123); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(176); expect(message[1]).to.equal(index); index++; if (index > max) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1038,11 +1040,11 @@ describe("OutputChannel Object", function() { let index = 0; // Act - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; WEBMIDI_OUTPUT.channels[1].sendControlChange(0, [12, 34]); // Assert - function assert(deltaTime, message) { + function assert(message) { if (index === 0) { expect(message[0]).to.equal(0xB0); // control change on channel 1 @@ -1053,7 +1055,7 @@ describe("OutputChannel Object", function() { expect(message[0]).to.equal(0xB0); // control change on channel 1 expect(message[1]).to.equal(32); // bankselectfine expect(message[2]).to.equal(34); // bankselectcoarse - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1135,20 +1137,20 @@ describe("OutputChannel Object", function() { ["monomodeon", 126], ["polymodeon", 127] ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act map.forEach(pair => WEBMIDI_OUTPUT.channels[1].sendControlChange(pair[0], 123)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(176); expect(message[1]).to.equal(map[index][1]); index++; if (index >= map.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1232,18 +1234,18 @@ describe("OutputChannel Object", function() { let channel = 1; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = 0; i <= 127; i++) WEBMIDI_OUTPUT.channels[channel].sendNoteOff(i, options); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(128); expect(message[1]).to.equal(index); index++; if (index > 127) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -1257,13 +1259,13 @@ describe("OutputChannel Object", function() { let notes = ["C-1", "C3", "G5", "G9"]; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act notes.forEach(note => WEBMIDI_OUTPUT.channels[channel].sendNoteOff(note, options)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(128); expect(message[1]).to.equal(Utilities.toNoteNumber(notes[index])); @@ -1271,7 +1273,7 @@ describe("OutputChannel Object", function() { index++; if (index >= notes.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1286,20 +1288,20 @@ describe("OutputChannel Object", function() { let notes = [new Note("C-1"), new Note("C3"), new Note("G5"), new Note("G9")]; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act notes.forEach(note => WEBMIDI_OUTPUT.channels[channel].sendNoteOff(note, options)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(128); expect(message[1]).to.equal(notes[index].number); index++; if (index >= notes.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1314,15 +1316,15 @@ describe("OutputChannel Object", function() { let note = 0; let options = {release: 1}; let expected = [128, 0, 127]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].sendNoteOff(note, options); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1335,15 +1337,15 @@ describe("OutputChannel Object", function() { let note = 0; let options = {release: 1, rawRelease: 83}; let expected = [128, 0, options.rawRelease]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].sendNoteOff(note, options); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1499,7 +1501,7 @@ describe("OutputChannel Object", function() { let channel = 1; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = 0; i <= 127; i++) { @@ -1507,12 +1509,12 @@ describe("OutputChannel Object", function() { } // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(144); expect(message[1]).to.equal(index); index++; if (index > 127) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -1526,13 +1528,13 @@ describe("OutputChannel Object", function() { let notes = ["C-1", "C3", "G5", "G9"]; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act notes.forEach(note => WEBMIDI_OUTPUT.channels[channel].sendNoteOn(note, options)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(144); expect(message[1]).to.equal(Utilities.toNoteNumber(notes[index])); @@ -1540,7 +1542,7 @@ describe("OutputChannel Object", function() { index++; if (index >= notes.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1555,20 +1557,20 @@ describe("OutputChannel Object", function() { let notes = [new Note("C-1"), new Note("C3"), new Note("G5"), new Note("G9")]; let index = 0; let options = {time: 0}; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act notes.forEach(note => WEBMIDI_OUTPUT.channels[channel].sendNoteOn(note, options)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(144); expect(message[1]).to.equal(notes[index].number); index++; if (index >= notes.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1583,15 +1585,15 @@ describe("OutputChannel Object", function() { let note = 0; let options = {attack: 1}; let expected = [144, 0, 127]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].sendNoteOn(note, options); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1604,15 +1606,15 @@ describe("OutputChannel Object", function() { let note = 0; let options = {attack: 1, rawAttack: 98}; let expected = [144, 0, options.rawAttack]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[channel].sendNoteOn(note, options); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1772,21 +1774,21 @@ describe("OutputChannel Object", function() { [208, 64], [208, 127], ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act values.forEach(value => WEBMIDI_OUTPUT.channels[1].sendChannelAftertouch(value)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1855,18 +1857,18 @@ describe("OutputChannel Object", function() { // Arrange let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = 0; i <= 127; i++) WEBMIDI_OUTPUT.channels[1].sendKeyAftertouch(i, 0.5); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members([160, index, 64]); index++; if (index >= 127) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1885,7 +1887,7 @@ describe("OutputChannel Object", function() { {identifier: "G9", number: 127}, ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act items.forEach(item => { @@ -1894,7 +1896,7 @@ describe("OutputChannel Object", function() { // Assert - function assert(deltaTime, message) { + function assert(message) { expect( message @@ -1903,7 +1905,7 @@ describe("OutputChannel Object", function() { index++; if (index >= items.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -1921,19 +1923,19 @@ describe("OutputChannel Object", function() { WEBMIDI_OUTPUT.channels[1].octaveOffset; let index = Math.abs(offset) * 12; const max = 127; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = index; i <= max; i++) WEBMIDI_OUTPUT.channels[1].sendKeyAftertouch(i, 0.5); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members([160, index + offset * 12, 64]); index++; if (index >= max) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; WebMidi.octaveOffset = 0; WEBMIDI_OUTPUT.octaveOffset = 0; WEBMIDI_OUTPUT.channels[1].octaveOffset = 0; @@ -1959,7 +1961,7 @@ describe("OutputChannel Object", function() { {identifier: "C4", number: 96} ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act items.forEach(item => { @@ -1968,7 +1970,7 @@ describe("OutputChannel Object", function() { // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members( [160, items[index].number, Utilities.fromFloatTo7Bit(value)] @@ -1977,7 +1979,7 @@ describe("OutputChannel Object", function() { index++; if (index >= items.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; WebMidi.octaveOffset = 0; WEBMIDI_OUTPUT.octaveOffset = 0; WEBMIDI_OUTPUT.channels[1].octaveOffset = 0; @@ -2077,15 +2079,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 122, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendLocalControl(); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2163,19 +2165,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendMasterTuning(coarse + fine); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2227,19 +2229,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendModulationRange(semitones, cents); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2371,19 +2373,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendNrpnValue(parameter, data); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2406,19 +2408,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendNrpnValue(parameter, data); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2524,15 +2526,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 125, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendOmniMode(); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2558,17 +2560,17 @@ describe("OutputChannel Object", function() { [224, 0, 64], [224, 127, 127] ]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act values.forEach(value => WEBMIDI_OUTPUT.channels[1].sendPitchBend(value)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -2596,17 +2598,17 @@ describe("OutputChannel Object", function() { [224, 127, 0] ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act values.forEach(value => WEBMIDI_OUTPUT.channels[1].sendPitchBend(value, options)); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -2709,19 +2711,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendPitchBendRange(semitones, cents); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2817,15 +2819,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 126, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendPolyphonicMode("mono"); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2835,15 +2837,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 127, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendPolyphonicMode("poly"); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -2863,7 +2865,7 @@ describe("OutputChannel Object", function() { // Arrange let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act for (let i = 0; i <= 127; i++) { @@ -2871,12 +2873,12 @@ describe("OutputChannel Object", function() { } // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message[0]).to.equal(192); expect(message[1]).to.equal(index); index++; if (index > 127) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } } @@ -2984,19 +2986,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendRpnValue(rpn, data); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3020,19 +3022,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendRpnValue(rpn, data); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3055,19 +3057,19 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendRpnValue(rpn, data); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3172,20 +3174,20 @@ describe("OutputChannel Object", function() { ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendTuningBank(value); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3255,19 +3257,19 @@ describe("OutputChannel Object", function() { [ 176, 100, 127 ] ]; let index = 0; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendTuningProgram(value); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected[index]); index++; if (index >= expected.length) { - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3373,15 +3375,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 123, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendAllNotesOff(); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } @@ -3415,15 +3417,15 @@ describe("OutputChannel Object", function() { // Arrange let expected = [176, 120, 0]; - VIRTUAL_OUTPUT.on("message", assert); + VIRTUAL_OUTPUT.receive = assert; // Act WEBMIDI_OUTPUT.channels[1].sendAllSoundOff(); // Assert - function assert(deltaTime, message) { + function assert(message) { expect(message).to.have.ordered.members(expected); - VIRTUAL_OUTPUT.removeAllListeners(); + VIRTUAL_OUTPUT.receive = noop; done(); } diff --git a/test/WebMidi.test.js b/test/WebMidi.test.js index 5d7e07cc3..55eebd98d 100644 --- a/test/WebMidi.test.js +++ b/test/WebMidi.test.js @@ -1,14 +1,21 @@ const expect = require("chai").expect; const {WebMidi, Utilities} = require("../dist/cjs/webmidi.cjs.js"); -const midi = require("midi"); +const WMT = require("web-midi-test"); const semver = require("semver"); +// enable permissions for midi and sysex +WMT.midi = true; +WMT.sysex = true; +const requestMIDIAccessFunction = WMT.requestMIDIAccess; + // The virtual port from the 'midi' library is an "external" device so an output is seen as an input // by WebMidi. To avoid confusion, the naming scheme adopts WebMidi's perspective. const VIRTUAL_INPUT_NAME = "Virtual Input"; -const VIRTUAL_INPUT = new midi.Output(VIRTUAL_INPUT_NAME); +const VIRTUAL_INPUT = new WMT.MidiSrc(VIRTUAL_INPUT_NAME); +// VIRTUAL_INPUT.busy = false; const VIRTUAL_OUTPUT_NAME = "Virtual Output"; -const VIRTUAL_OUTPUT = new midi.Input(VIRTUAL_OUTPUT_NAME); +const VIRTUAL_OUTPUT = new WMT.MidiDst(VIRTUAL_OUTPUT_NAME); +// VIRTUAL_OUTPUT.busy = false; describe("WebMidi Object", function() { @@ -141,7 +148,7 @@ describe("WebMidi Object", function() { describe("constructor()", function() { beforeEach("Enable WebMidi", async function() { - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction}); }); it("should adjust to Node.js environment", function() { @@ -158,7 +165,7 @@ describe("WebMidi Object", function() { describe("disable()", function() { beforeEach("Enable WebMidi", async function() { - await WebMidi.enable({sysex: true}); + await WebMidi.enable({sysex: true, requestMIDIAccessFunction}); }); it("should set 'enabled' property to false", function(done) { @@ -419,35 +426,37 @@ describe("WebMidi Object", function() { it("should trigger 'connected' events for already connected inputs", function(done) { // Arrange - VIRTUAL_INPUT.openVirtualPort(VIRTUAL_INPUT_NAME); + VIRTUAL_INPUT.connect(); + // expect(connected).to.equal(true); WebMidi.addListener("connected", e => { if (e.port.name === VIRTUAL_INPUT_NAME) { WebMidi.removeListener(); - VIRTUAL_INPUT.closePort(); + VIRTUAL_INPUT.disconnect(); done(); } }); // Assert - WebMidi.enable(); + WebMidi.enable({requestMIDIAccessFunction}); }); it("should trigger 'connected' events for already connected outputs", function(done) { - VIRTUAL_OUTPUT.openVirtualPort(VIRTUAL_OUTPUT_NAME); + VIRTUAL_OUTPUT.connect(); + // expect(connected).to.equal(true); WebMidi.addListener("connected", e => { if (e.port.name === VIRTUAL_OUTPUT_NAME) { WebMidi.removeListener(); - VIRTUAL_OUTPUT.closePort(); + VIRTUAL_OUTPUT.disconnect(); done(); } }); // Assert - WebMidi.enable(); + WebMidi.enable({requestMIDIAccessFunction}); }); diff --git a/typescript/webmidi.d.ts b/typescript/webmidi.d.ts index 2da52c543..e01799293 100644 --- a/typescript/webmidi.d.ts +++ b/typescript/webmidi.d.ts @@ -5570,6 +5570,7 @@ declare class WebMidi extends EventEmitter { sysex?: boolean; validation?: boolean; software?: boolean; + requestMIDIAccessFunction?: Function; }): Promise; /**