diff options
Diffstat (limited to 'javascript/videojs/test/unit/tech/middleware.test.js')
| -rw-r--r-- | javascript/videojs/test/unit/tech/middleware.test.js | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/javascript/videojs/test/unit/tech/middleware.test.js b/javascript/videojs/test/unit/tech/middleware.test.js new file mode 100644 index 0000000..6f4d2d3 --- /dev/null +++ b/javascript/videojs/test/unit/tech/middleware.test.js @@ -0,0 +1,538 @@ +/* eslint-env qunit */ +import * as middleware from '../../../src/js/tech/middleware.js'; +import sinon from 'sinon'; +import window from 'global/window'; + +QUnit.module('Middleware', { + beforeEach(assert) { + this.clock = sinon.useFakeTimers(); + }, + afterEach(assert) { + this.clock.restore(); + } +}); + +QUnit.test('middleware can be added with the use method', function(assert) { + const myMw = {}; + const mwFactory = () => myMw; + + middleware.use('foo', mwFactory); + + assert.equal(middleware.getMiddleware('foo').pop(), mwFactory, 'we are able to add middleware'); +}); + +QUnit.test('middleware get iterates through the middleware array in the right order', function(assert) { + const cts = []; + const durs = []; + const foos = []; + const mws = [ + { + currentTime(ct) { + cts.push(ct); + return ct * 2; + }, + duration(dur) { + durs.push(dur); + return dur + 2; + }, + foo(f) { + foos.push(f); + return f / 2; + } + }, + { + currentTime(ct) { + cts.push(ct); + return ct + 2; + }, + duration(dur) { + durs.push(dur); + return dur / 2; + }, + foo(f) { + foos.push(f); + return f + 3; + } + } + ]; + const tech = { + currentTime(ct) { + return 5; + }, + duration(dur) { + return 5; + }, + foo(f) { + return 5; + } + }; + + const ct = middleware.get(mws, tech, 'currentTime'); + const dur = middleware.get(mws, tech, 'duration'); + const foo = middleware.get(mws, tech, 'foo'); + + const assertion = (actual, expected, actualArr, expectedArr, type) => { + assert.equal(actual, expected, `our middleware chain return correctly for ${type}`); + assert.deepEqual(actualArr, expectedArr, `we got called in the correct order for ${type}`); + }; + + assertion(ct, 14, cts, [5, 7], 'currentTime'); + assertion(dur, 4.5, durs, [5, 2.5], 'duration'); + assertion(foo, 4, foos, [5, 8], 'foo'); +}); + +QUnit.test('middleware set iterates through the middleware array in the right order', function(assert) { + const cts = []; + const durs = []; + const foos = []; + const mws = [ + { + currentTime(ct) { + cts.push(ct); + return ct * 2; + }, + duration(dur) { + durs.push(dur); + return dur + 2; + }, + foo(f) { + foos.push(f); + return f / 2; + } + }, + { + currentTime(ct) { + cts.push(ct); + return ct + 2; + }, + duration(dur) { + durs.push(dur); + return dur / 2; + }, + foo(f) { + foos.push(f); + return f + 3; + } + } + ]; + const tech = { + currentTime(ct) { + cts.push(ct); + return ct / 2; + }, + duration(dur) { + durs.push(dur); + return dur; + }, + foo(f) { + foos.push(f); + return f; + } + }; + + const ct = middleware.set(mws, tech, 'currentTime', 10); + const dur = middleware.set(mws, tech, 'duration', 10); + const foo = middleware.set(mws, tech, 'foo', 10); + + const assertion = (actual, expected, actualArr, expectedArr, type) => { + assert.equal(actual, expected, `our middleware chain return correctly for ${type}`); + assert.deepEqual(actualArr, expectedArr, `we got called in the correct order for ${type}`); + }; + + assertion(ct, 11, cts, [10, 20, 22], 'currentTime'); + assertion(dur, 6, durs, [10, 12, 6], 'duration'); + assertion(foo, 8, foos, [10, 5, 8], 'foo'); +}); + +QUnit.test('middleware mediate iterates through the middleware array twice', function(assert) { + let playsToTech = 0; + let playsToPlayer = 0; + let techPlays = 0; + let techPlay; + let pv1; + let pv2; + let pc1; + let pc2; + + const mws = [{ + callPlay() { + playsToTech++; + }, + play(cancelled, value) { + playsToPlayer++; + pv1 = value; + pc1 = cancelled; + } + }, { + callPlay() { + playsToTech++; + }, + play(cancelled, value) { + playsToPlayer++; + pv2 = value; + pc2 = cancelled; + } + }]; + const tech = { + play() { + techPlays++; + techPlay = {then: () => {}}; + + return techPlay; + } + }; + + const pp = middleware.mediate(mws, tech, 'play'); + + assert.equal(playsToTech, playsToPlayer, 'middleware got called the same number of times'); + assert.equal(playsToTech, 2, 'both middleware got called before the tech'); + assert.equal(techPlays, 1, 'the tech method only gets called once'); + assert.equal(playsToPlayer, 2, 'both middleware got called after the tech'); + + assert.deepEqual(pv1.then, techPlay.then, 'the value returned by the tech is passed through the middleware'); + assert.deepEqual(pv2, techPlay, 'the value returned by the tech is passed through the middleware'); + assert.deepEqual(pp, techPlay, 'the value returned to the player is the value returned from the tech'); + assert.equal(pc1, false, 'the play has not been cancelled in middleware 1'); + assert.equal(pc2, false, 'the play has not been cancelled in middleware 2'); +}); + +QUnit.test('middleware mediate allows and can detect cancellation', function(assert) { + let playsToTech = 0; + let playsToPlayer = 0; + let techPlays = 0; + let pv1; + let pv2; + let pc1; + let pc2; + + const mws = [{ + callPlay() { + playsToTech++; + }, + play(cancelled, value) { + playsToPlayer++; + pv1 = value; + pc1 = cancelled; + } + }, { + callPlay() { + playsToTech++; + return middleware.TERMINATOR; + }, + play(cancelled, value) { + playsToPlayer++; + pv2 = value; + pc2 = cancelled; + } + }]; + const tech = { + play() { + techPlays++; + return {then: () => {}}; + } + }; + + const pp = middleware.mediate(mws, tech, 'play'); + + assert.equal(playsToTech, 2, 'both middleware run until middleware terminates'); + assert.equal(techPlays, 0, 'the tech should not be called if a middleware terminates'); + assert.equal(playsToPlayer, 2, 'both middleware run after the tech'); + + assert.equal(pv1, null, 'null is returned through the middleware if a middleware terminated previously'); + assert.equal(pv2, null, 'null is returned through the middleware if a middleware terminated previously'); + assert.equal(pp, null, 'null is returned to the player if a middleware terminated previously'); + assert.equal(pc1, true, 'the play has been cancelled in middleware 1'); + assert.equal(pc2, true, 'the play has been cancelled in middleware 2'); +}); + +QUnit.test('setSource is run asynchronously', function(assert) { + let src; + let acc; + + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, { src: 'foo', type: 'video/foo' }, function(_src, _acc) { + src = _src; + acc = _acc; + }); + + assert.equal(src, undefined, 'no src was returned yet'); + assert.equal(acc, undefined, 'no accumulator was returned yet'); + + this.clock.tick(1); + + assert.deepEqual(src, {src: 'foo', type: 'video/foo'}, 'we got the same source back'); + assert.equal(acc.length, 0, 'we did not accumulate any middleware since there were none'); +}); + +QUnit.test('setSource selects a source based on the middleware given', function(assert) { + let src; + let acc; + const mw = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const fooFactory = () => mw; + + middleware.use('video/foo', fooFactory); + + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + src = _src; + acc = _acc; + }); + + this.clock.tick(1); + + assert.equal(src.type, 'video/mp4', 'we selected a new type of video/mp4'); + assert.equal(src.src, 'http://example.com/video.mp4', 'we selected a new src of video.mp4'); + assert.equal(acc.length, 1, 'we got one middleware'); + assert.equal(acc[0], mw, 'we chose the one middleware'); + + middleware.getMiddleware('video/foo').pop(); +}); + +QUnit.test('setSource can select multiple middleware from multiple types', function(assert) { + let src; + let acc; + const foomw = { + setSource(_src, next) { + next(null, { + src: 'bar', + type: 'video/bar' + }); + } + }; + const barmw = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const fooFactory = () => foomw; + const barFactory = () => barmw; + + middleware.use('video/foo', fooFactory); + middleware.use('video/bar', barFactory); + + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + src = _src; + acc = _acc; + }); + + this.clock.tick(1); + + assert.equal(src.type, 'video/mp4', 'we selected a new type of video/mp4'); + assert.equal(src.src, 'http://example.com/video.mp4', 'we selected a new src of video.mp4'); + assert.equal(acc.length, 2, 'we got two middleware'); + assert.equal(acc[0], foomw, 'foomw is the first middleware'); + assert.equal(acc[1], barmw, 'barmw is the first middleware'); + + middleware.getMiddleware('video/foo').pop(); + middleware.getMiddleware('video/bar').pop(); +}); + +QUnit.test('setSource will select all middleware of a given type, until src change', function(assert) { + let src; + let acc; + const foomw1 = { + setSource(_src, next) { + next(null, { + src: 'bar', + type: 'video/foo' + }); + } + }; + const foomw2 = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const foomw3 = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const fooFactory1 = () => foomw1; + const fooFactory2 = () => foomw2; + const fooFactory3 = () => foomw3; + + middleware.use('video/foo', fooFactory1); + middleware.use('video/foo', fooFactory2); + middleware.use('video/foo', fooFactory3); + + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(_src, _acc) { + src = _src; + acc = _acc; + }); + + this.clock.tick(1); + + assert.equal(src.type, 'video/mp4', 'we selected a new type of video/mp4'); + assert.equal(src.src, 'http://example.com/video.mp4', 'we selected a new src of video.mp4'); + assert.equal(acc.length, 2, 'we got two middleware'); + assert.equal(acc[0], foomw1, 'foomw is the first middleware'); + assert.equal(acc[1], foomw2, 'foomw is the first middleware'); + + middleware.getMiddleware('video/foo').pop(); + middleware.getMiddleware('video/foo').pop(); + middleware.getMiddleware('video/foo').pop(); +}); + +QUnit.test('a middleware without a mediator method will not throw an error', function(assert) { + let pauseCalled = 0; + const myMw = {}; + const mwFactory = () => myMw; + const mwFactory2 = () => ({ + pause() { + pauseCalled++; + } + }); + + middleware.mediate([mwFactory(), mwFactory2()], {pause: () => {}}, 'pause'); + + assert.equal(pauseCalled, 1, 'pauseCalled was called once and no error was thrown'); +}); + +QUnit.test('a middleware factory is not called on source change', function(assert) { + let mwfactoryCalled = 0; + const mw = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const fooFactory = () => { + mwfactoryCalled++; + return mw; + }; + + middleware.use('video/foo', fooFactory); + + // set "initial" source" + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function() {}); + + this.clock.tick(1); + + assert.equal(mwfactoryCalled, 1, 'the factory was called once'); + + // "change" source + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'bar', type: 'video/foo'}, function() {}); + + this.clock.tick(1); + + assert.equal(mwfactoryCalled, 1, 'the factory was not called again'); + + middleware.getMiddleware('video/foo').pop(); +}); + +QUnit.test('a middleware factory is called on a new source with a new player', function(assert) { + let mwfactoryCalled = 0; + const mw = { + setSource(_src, next) { + next(null, { + src: 'http://example.com/video.mp4', + type: 'video/mp4' + }); + } + }; + const fooFactory = () => { + mwfactoryCalled++; + return mw; + }; + + middleware.use('video/foo', fooFactory); + + // set "initial" source with player vid1 + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function() {}); + + this.clock.tick(1); + + assert.equal(mwfactoryCalled, 1, 'the factory was called once'); + + // set "initial" source with player vid2 + middleware.setSource({ + id() { + return 'vid2'; + }, + setTimeout: window.setTimeout + }, {src: 'bar', type: 'video/foo'}, function() {}); + + this.clock.tick(1); + + assert.equal(mwfactoryCalled, 2, 'the factory was called again'); + + middleware.getMiddleware('video/foo').pop(); +}); + +QUnit.test('a middleware without a setSource gets chosen implicitly', function(assert) { + let mws = []; + const mw = { + currentTime(ct) { + } + }; + const mwFactory = () => mw; + + middleware.use('video/foo', mwFactory); + + middleware.setSource({ + id() { + return 'vid1'; + }, + setTimeout: window.setTimeout + }, {src: 'foo', type: 'video/foo'}, function(src, _mws) { + mws = _mws; + }); + + this.clock.tick(1); + + assert.equal(mws.length, 1, 'we have 1 middleware set'); + + middleware.getMiddleware('video/foo').pop(); +}); |
