Tone.js/Tone/signal/ToneConstantSource.test.ts
Yotam Mann 2f55cc2ec2 wrap the native ConstantSourceNode into ToneConstantSource
gets more consistent onended callback and other syntactic sugar
2019-09-06 17:10:32 -04:00

202 lines
5.4 KiB
TypeScript

import { expect } from "chai";
import { BasicTests } from "test/helper/Basic";
import { CompareToFile } from "test/helper/CompareToFile";
import { Offline, whenBetween } from "test/helper/Offline";
import { ONLINE_TESTING } from "test/helper/Supports";
import { ToneConstantSource } from "./ToneConstantSource";
describe("ToneConstantSource", () => {
BasicTests(ToneConstantSource);
context("Constructor", () => {
it("can be constructed with an offset", () => {
const source = new ToneConstantSource(330);
expect(source.offset.value).to.equal(330);
source.dispose();
});
it("can be constructed with no arguments", () => {
const source = new ToneConstantSource();
expect(source.offset.value).to.equal(1);
source.dispose();
});
it("can be constructed with an options object", () => {
const source = new ToneConstantSource({
offset: 2,
});
expect(source.offset.value).to.be.closeTo(2, 0.01);
source.dispose();
});
});
context("onended", () => {
if (ONLINE_TESTING) {
it("invokes the onended callback in the online context", (done) => {
const source = new ToneConstantSource();
source.start();
source.stop("+0.3");
const now = source.now();
source.onended = () => {
expect(source.now() - now).to.be.within(0.25, 0.5);
source.dispose();
done();
};
});
it("invokes the onended callback only once in the online context", (done) => {
const source = new ToneConstantSource();
source.start();
source.stop("+0.1");
source.stop("+0.2");
source.stop("+0.3");
const now = source.now();
source.onended = () => {
expect(source.now() - now).to.be.within(0.25, 0.5);
source.dispose();
done();
};
});
}
it("invokes the onended callback in the offline context", () => {
let wasInvoked = false;
return Offline(() => {
const source = new ToneConstantSource();
source.start(0);
source.stop(0.2);
source.onended = () => {
expect(source.now() - 0.2).to.be.closeTo(0, 0.05);
source.dispose();
wasInvoked = true;
};
}, 0.3).then(() => {
expect(wasInvoked).to.equal(true);
});
});
it("invokes the onended callback only once in offline context", () => {
let wasInvoked = false;
return Offline(() => {
const source = new ToneConstantSource();
source.start(0);
source.stop(0.1);
source.stop(0.2);
source.stop(0.3);
source.onended = () => {
expect(source.now() - 0.3).to.be.closeTo(0, 0.05);
source.dispose();
expect(wasInvoked).to.equal(false);
wasInvoked = true;
};
}, 0.4).then(() => {
expect(wasInvoked).to.equal(true);
});
});
});
context("Scheduling", () => {
it("throw an error if start is called multiple time", () => {
const source = new ToneConstantSource();
source.start();
expect(() => {
source.start();
}).to.throw();
source.dispose();
});
it("can play for a specific duration", () => {
return Offline(() => {
const source = new ToneConstantSource().toDestination();
source.start(0).stop(0.1);
}, 0.4).then(buffer => {
expect(buffer.getValueAtTime(0)).to.be.above(0);
expect(buffer.getValueAtTime(0.09)).to.be.above(0);
expect(buffer.getValueAtTime(0.1)).to.equal(0);
});
});
it("can call stop multiple times and takes the last value", () => {
return Offline(() => {
const source = new ToneConstantSource().toDestination();
source.start(0).stop(0.1).stop(0.2);
}, 0.4).then((buffer) => {
expect(buffer.getValueAtTime(0)).to.be.above(0);
expect(buffer.getValueAtTime(0.1)).to.be.above(0);
expect(buffer.getValueAtTime(0.19)).to.be.above(0);
expect(buffer.getValueAtTime(0.2)).to.equal(0);
});
});
if (ONLINE_TESTING) {
it("clamps start time to the currentTime", () => {
const source = new ToneConstantSource();
source.start(0);
const currentTime = source.context.currentTime;
expect(source.getStateAtTime(0)).to.equal("stopped");
expect(source.getStateAtTime(currentTime)).to.equal("started");
source.dispose();
});
it("clamps stop time to the currentTime", (done) => {
const source = new ToneConstantSource();
source.start(0);
let currentTime = source.context.currentTime;
expect(source.getStateAtTime(0)).to.equal("stopped");
expect(source.getStateAtTime(currentTime)).to.equal("started");
setTimeout(() => {
currentTime = source.context.currentTime;
source.stop(0);
expect(source.getStateAtTime(currentTime + 0.01)).to.equal("stopped");
source.dispose();
done();
}, 100);
});
}
});
context("State", () => {
it("reports the right state", () => {
return Offline(() => {
const source = new ToneConstantSource();
source.start(0);
source.stop(0.05);
return (time) => {
whenBetween(time, 0, 0.05, () => {
expect(source.state).to.equal("started");
});
whenBetween(time, 0.05, 0.1, () => {
expect(source.state).to.equal("stopped");
});
};
}, 0.1);
});
it("can call stop multiple times, takes the last value", () => {
return Offline(() => {
const source = new ToneConstantSource();
source.start(0);
source.stop(0.05);
source.stop(0.1);
return (time) => {
whenBetween(time, 0, 0.1, () => {
expect(source.state).to.equal("started");
});
whenBetween(time, 0.1, 0.2, () => {
expect(source.state).to.equal("stopped");
});
};
}, 0.2);
});
});
});