mirror of
https://github.com/scratchfoundation/scratch-audio.git
synced 2024-12-22 05:53:43 -05:00
add Effect tests and mocks
This commit is contained in:
parent
6c8edf52b9
commit
e40e6e0b1b
7 changed files with 214 additions and 3 deletions
|
@ -24,8 +24,7 @@
|
|||
"dependencies": {
|
||||
"audio-context": "1.0.1",
|
||||
"minilog": "^3.0.1",
|
||||
"startaudiocontext": "1.2.1",
|
||||
"tap": "^12.0.1"
|
||||
"startaudiocontext": "1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.24.1",
|
||||
|
@ -37,6 +36,7 @@
|
|||
"json": "^9.0.6",
|
||||
"travis-after-all": "^1.4.4",
|
||||
"webpack": "^4.8.0",
|
||||
"webpack-cli": "^2.0.15"
|
||||
"webpack-cli": "^2.0.15",
|
||||
"tap": "^12.0.1"
|
||||
}
|
||||
}
|
||||
|
|
20
test/__mocks__/AudioContext.js
Normal file
20
test/__mocks__/AudioContext.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
const AudioNodeMock = require('./AudioNode');
|
||||
const AudioParamMock = require('./AudioParam');
|
||||
|
||||
class AudioContextMock {
|
||||
createGain () {
|
||||
return new AudioNodeMock({
|
||||
gain: new AudioParamMock({
|
||||
default: 1,
|
||||
min: -3,
|
||||
max: 3
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
createChannelMerger () {
|
||||
return new AudioNodeMock();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AudioContextMock;
|
12
test/__mocks__/AudioEngine.js
Normal file
12
test/__mocks__/AudioEngine.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
const AudioContextMock = require('./AudioContext');
|
||||
const AudioTargetMock = require('./AudioTarget');
|
||||
|
||||
class AudioEngineMock extends AudioTargetMock {
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
this.audioContext = new AudioContextMock();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AudioEngineMock;
|
36
test/__mocks__/AudioNode.js
Normal file
36
test/__mocks__/AudioNode.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
class AudioNodeMock {
|
||||
constructor (params) {
|
||||
Object.assign(this, params);
|
||||
|
||||
this.connected = null;
|
||||
this.connectedFrom = [];
|
||||
this._testResult = [];
|
||||
}
|
||||
|
||||
connect (node) {
|
||||
this.connected = node;
|
||||
node.connectedFrom.push(this);
|
||||
}
|
||||
|
||||
disconnect () {
|
||||
if (this.connected !== null) {
|
||||
this.connectedFrom = this.connectedFrom.filter(connection => connection !== this);
|
||||
}
|
||||
this.connected = null;
|
||||
}
|
||||
|
||||
_test (test, message, depth = 0) {
|
||||
if (this.connected === null) {
|
||||
this._testResult.push({test, message, depth});
|
||||
} else {
|
||||
this.connected._test(test, message, depth + 1);
|
||||
this._testResult.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
_result () {
|
||||
return this._testResult.pop();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AudioNodeMock;
|
7
test/__mocks__/AudioParam.js
Normal file
7
test/__mocks__/AudioParam.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
class AudioParamMock {
|
||||
setTargetAtTime (value /* , start, stop */) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AudioParamMock;
|
21
test/__mocks__/AudioTarget.js
Normal file
21
test/__mocks__/AudioTarget.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
const AudioNodeMock = require('./AudioNode');
|
||||
|
||||
class AudioTargetMock {
|
||||
constructor () {
|
||||
this.inputNode = new AudioNodeMock();
|
||||
}
|
||||
|
||||
connect (target) {
|
||||
this.inputNode.connect(target.getInputNode());
|
||||
}
|
||||
|
||||
getInputNode () {
|
||||
return this.inputNode;
|
||||
}
|
||||
|
||||
getSoundPlayers () {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AudioTargetMock;
|
115
test/effects/EffectShape.js
Normal file
115
test/effects/EffectShape.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
const tap = require('tap');
|
||||
|
||||
const PanEffect = require('../../src/effects/PanEffect');
|
||||
const PitchEffect = require('../../src/effects/PitchEffect');
|
||||
const VolumeEffect = require('../../src/effects/VolumeEffect');
|
||||
|
||||
const AudioEngine = require('../__mocks__/AudioEngine');
|
||||
const AudioTarget = require('../__mocks__/AudioTarget');
|
||||
|
||||
const testEffect = (EffectClass, effectDepth) => {
|
||||
tap.test(EffectClass.name, t1 => {
|
||||
t1.plan(3);
|
||||
|
||||
t1.test('methods', t2 => {
|
||||
t2.plan(7);
|
||||
|
||||
t2.ok(
|
||||
'DEFAULT_VALUE' in EffectClass.prototype,
|
||||
'has DEFAULT_VALUE'
|
||||
);
|
||||
t2.type(EffectClass.prototype.initialize, 'function', 'has initialize');
|
||||
t2.type(EffectClass.prototype.set, 'function', 'has set');
|
||||
t2.type(EffectClass.prototype.update, 'function', 'has update');
|
||||
t2.type(EffectClass.prototype.clear, 'function', 'has clear');
|
||||
t2.type(EffectClass.prototype.connect, 'function', 'has connect');
|
||||
t2.type(EffectClass.prototype.dispose, 'function', 'has dispose');
|
||||
|
||||
t2.end();
|
||||
});
|
||||
|
||||
t1.test('connect', t2 => {
|
||||
t2.plan(6);
|
||||
|
||||
const engine = new AudioEngine();
|
||||
const target = new AudioTarget();
|
||||
let effect = new EffectClass(engine, target, null);
|
||||
|
||||
target.inputNode._test('stall', 'message does not move');
|
||||
t2.equal(target.inputNode._result().depth, 0, 'message not sent');
|
||||
t2.ok(!engine.inputNode._result(), 'message not received');
|
||||
t2.ok(!engine.inputNode.connected, 'engine not connected');
|
||||
|
||||
effect.dispose();
|
||||
effect = new EffectClass(engine, target, null);
|
||||
const effect2 = new EffectClass(engine, target, effect);
|
||||
effect2.connect(engine);
|
||||
effect.connect(effect2);
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1, 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
t2.end();
|
||||
});
|
||||
|
||||
t1.test('lifecycle', t2 => {
|
||||
t2.plan(18);
|
||||
|
||||
const engine = new AudioEngine();
|
||||
const target = new AudioTarget();
|
||||
let effect = new EffectClass(engine, target, null);
|
||||
let effect2 = new EffectClass(engine, target, effect);
|
||||
|
||||
target.inputNode._test('stall', 'message does not move');
|
||||
t2.equal(target.inputNode._result().depth, 0, 'message not sent');
|
||||
t2.ok(!engine.inputNode._result(), 'message not received');
|
||||
t2.ok(!engine.inputNode.connected, 'engine not connected');
|
||||
|
||||
effect2.connect(engine);
|
||||
effect.connect(effect2);
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1, 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
effect.set(effect.DEFAULT_VALUE - 1);
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1 + effectDepth, 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
effect2.set(effect2.DEFAULT_VALUE - 1);
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1 + (2 * effectDepth), 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
effect.clear();
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1 + effectDepth, 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
effect2.clear();
|
||||
|
||||
target.inputNode._test('move', 'message does move');
|
||||
t2.ok(!target.inputNode._result(), 'message sent');
|
||||
t2.equal(engine.inputNode._result().depth, 1, 'message received');
|
||||
t2.ok(engine.inputNode.connectedFrom.length, 'engine connected');
|
||||
|
||||
t2.end();
|
||||
});
|
||||
|
||||
t1.end();
|
||||
});
|
||||
};
|
||||
|
||||
testEffect(PanEffect, 3);
|
||||
testEffect(PitchEffect, 0);
|
||||
testEffect(VolumeEffect, 1);
|
Loading…
Reference in a new issue