From 2e7d6fa9524b4794d9dc8583360ec0908478bbc3 Mon Sep 17 00:00:00 2001 From: kaorun343 Date: Sat, 18 Mar 2017 12:25:21 +0900 Subject: [PATCH] add mute prop and improve test --- karma.conf.js | 12 +- src/index.js | 4 +- src/player.js | 44 ++++--- test/container.spec.js | 66 ++++++++++ test/index.spec.js | 276 +---------------------------------------- test/player.spec.js | 172 +++++++++++++++++++++++++ test/utils.spec.js | 69 +++++++++++ webpack.config.js | 2 +- 8 files changed, 343 insertions(+), 302 deletions(-) create mode 100644 test/container.spec.js create mode 100644 test/player.spec.js create mode 100644 test/utils.spec.js diff --git a/karma.conf.js b/karma.conf.js index 3a160c0..b1bf556 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,7 +1,7 @@ // Karma configuration // Generated on Wed Dec 16 2015 21:28:49 GMT+0900 (JST) -module.exports = function(config) { +module.exports = function (config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) @@ -13,7 +13,7 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - 'test/index.spec.js' + 'test/*.spec.js' ], // list of files to exclude @@ -23,7 +23,7 @@ module.exports = function(config) { // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - 'test/index.spec.js': 'webpack' + 'test/*.spec.js': 'webpack' }, // test results reporter to use @@ -75,11 +75,7 @@ module.exports = function(config) { { test: /\.js$/, exclude: /node_modules/, - loader: 'babel' - }, - { - test: /\.json$/, - loader: 'json' + loader: 'babel-loader' } ] }, diff --git a/src/index.js b/src/index.js index a969ebd..96413d7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,8 @@ -'use strict' - import { getIdFromURL, getTimeFromURL } from './utils' import container from './container' import YouTubePlayer from './player' -export { getIdFromURL, getTimeFromURL } +export { YouTubePlayer, getIdFromURL, getTimeFromURL } export function install (Vue) { container.Vue = Vue diff --git a/src/player.js b/src/player.js index b165c11..00813b4 100644 --- a/src/player.js +++ b/src/player.js @@ -3,7 +3,27 @@ import container from './container' let pid = 0 export default { - props: ['playerHeight', 'playerWidth', 'playerVars', 'videoId', 'mute'], + props: { + playerHeight: { + type: String, + default: '390' + }, + playerWidth: { + type: String, + default: '640' + }, + playerVars: { + type: Object, + default: () => ({ autoplay: 0, time: 0 }) + }, + videoId: { + type: String + }, + mute: { + type: Boolean, + default: false + } + }, render (h) { return h('div', [ h('div', { attrs: { id: this.elementId }}) @@ -25,20 +45,17 @@ export default { }, methods: { setSize () { - this.player.setSize(this.playerWidth || '640', this.playerHeight || '390') + this.player.setSize(this.playerWidth, this.playerHeight) }, - setMute () { - if (this.mute && this.player.isMuted()) { + setMute (value) { + if (value) { this.player.mute() } else { this.player.unMute() } }, update (videoId) { - const { - playerVars = { autoplay: 0 } - } = this - const name = `${playerVars.autoplay ? 'load' : 'cue'}VideoById` + const name = `${this.playerVars.autoplay ? 'load' : 'cue'}VideoById` if (this.player.hasOwnProperty(name)) { this.player[name](videoId) } else { @@ -50,16 +67,11 @@ export default { }, mounted () { container.register((YouTube) => { - const { - playerHeight: height = '390', - playerWidth: width = '640', - playerVars = { autoplay: 0, start: 0 }, - videoId - } = this + const { playerHeight, playerWidth, playerVars, videoId } = this this.player = new YouTube.Player(this.elementId, { - height, - width, + height: playerHeight, + width: playerWidth, playerVars, videoId, events: { diff --git a/test/container.spec.js b/test/container.spec.js new file mode 100644 index 0000000..b5d7a88 --- /dev/null +++ b/test/container.spec.js @@ -0,0 +1,66 @@ +import assert from 'power-assert' +import container from '../src/container' + +describe('container', () => { + context('when YouTube is not ready', () => { + describe('#register', () => { + it('should add a callback to scripts', () => { + const length = container.scripts.length + container.register(() => {}) + assert.equal(container.scripts.length, length + 1) + }) + }) + + after(() => { + container.scripts = [] + }) + }) + + context('when YouTube is ready', () => { + before(() => { + container.YT = { + Player () {} + } + container.Vue = { + nextTick (callback) { + callback() + } + } + }) + + describe('#run', () => { + it('should call calbacks and pass YT.Player to its scripts', () => { + const spy = sinon.spy() + container.scripts = [spy] + container.run() + assert.ok(spy.calledWith(container.YT)) + }) + + it('should remove elements from scripts', () => { + container.scripts.push(() => {}) + container.run() + assert.equal(container.scripts.length, 0) + }) + + afterEach(() => { + container.scripts = [] + }) + }) + + describe('#register', () => { + it('should call callback', () => { + sinon.spy(container.Vue, 'nextTick') + const callbackSpy = sinon.spy() + container.register(callbackSpy) + assert.ok(container.Vue.nextTick.called) + assert.ok(callbackSpy.called) + container.Vue.nextTick.restore() + }) + }) + }) + + after(() => { + delete container.YT + delete container.Vue + }) +}) diff --git a/test/index.spec.js b/test/index.spec.js index fe4e806..8e8d6f4 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1,283 +1,11 @@ -'use strict' import Vue from 'vue' import assert from 'power-assert' -import { YouTubePlayer, install } from '../src/index' -import container from '../src/container' +import VueYouTubeEmbed from '../src/index' import { getIdFromURL, getTimeFromURL } from '../src/utils' -// fork from https://github.com/brandly/angular-youtube-embed -describe('getIdFromURL', () => { - it('should handle regular query strings', () => { - const url = 'https://www.youtube.com/watch?v=nViWpVc1x_4&feature=youtu.be' - const id = 'nViWpVc1x_4' - assert.equal(getIdFromURL(url), id) - }) - - it('should handle attribution_link', () => { - const url = 'http://www.youtube.com/attribution_link?a=pxa6goHqzaA&u=%2Fwatch%3Fv%3DdPdgx30w9sU%26feature%3Dshare' - const id = 'dPdgx30w9sU' - assert.equal(getIdFromURL(url), id) - }) - - it('should handle almost a query string', () => { - const url = 'http://www.youtube.com/watch?feature=player_detailpage&v=93LvTKF_jW0#t=1' - const id = '93LvTKF_jW0' - assert.equal(getIdFromURL(url), id) - }) - - it('should handle "&feature=youtu.be"', () => { - const url = 'https://www.youtube.com/watch?v=VbNF9X1waSc&feature=youtu.be' - const id = 'VbNF9X1waSc' - assert.equal(getIdFromURL(url), id) - }) - - it('should handle http://youtu.be', () => { - const url = 'https://youtu.be/3FY4MRdQOdE' - const id = '3FY4MRdQOdE' - assert.equal(getIdFromURL(url), id) - }) - - it('should handle "edit" links from video manager page', () => { - const url = 'https://www.youtube.com/edit?o=U&video_id=3k2ZBu3kuiE' - const id = '3k2ZBu3kuiE' - assert.equal(getIdFromURL(url), id) - }) -}) - -// fork from https://github.com/brandly/angular-youtube-embed -describe('getTimeFromURL', () => { - it('should return 0 when time is not defined', () => { - const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo' - assert.equal(getTimeFromURL(url), 0) - }) - - it('should handle the url that contains "m" and "s"', () => { - const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4m20s' - assert.equal(getTimeFromURL(url), 20 + 4 * 60) - }) - - it('should handle the url that does not contain "s"', () => { - const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4m' - assert.equal(getTimeFromURL(url), 4 * 60) - }) - - it('should handle the url that does not contain "m"', () => { - const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4s' - assert.equal(getTimeFromURL(url), 4) - }) - - it('should handle the url that does not contain both "s" and "s"', () => { - const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4' - assert.equal(getTimeFromURL(url), 4) - }) -}) - -describe('container', () => { - context('when YouTube is not ready', () => { - describe('#register', () => { - it('should add a callback to scripts', () => { - const length = container.scripts.length - container.register(() => {}) - assert.equal(container.scripts.length, length + 1) - }) - }) - - after(() => { - container.scripts = [] - }) - }) - - context('when YouTube is ready', () => { - before(() => { - container.YT = { - Player () {} - } - container.Vue = { - nextTick (callback) { - callback() - } - } - }) - - describe('#run', () => { - it('should call calbacks and pass YT.Player to its scripts', () => { - const spy = sinon.spy() - container.scripts = [spy] - container.run() - assert.ok(spy.calledWith(container.YT)) - }) - - it('should remove elements from scripts', () => { - container.scripts.push(() => {}) - container.run() - assert.equal(container.scripts.length, 0) - }) - - afterEach(() => { - container.scripts = [] - }) - }) - - describe('#register', () => { - it('should call callback', () => { - sinon.spy(container.Vue, 'nextTick') - const callbackSpy = sinon.spy() - container.register(callbackSpy) - assert.ok(container.Vue.nextTick.called) - assert.ok(callbackSpy.called) - container.Vue.nextTick.restore() - }) - }) - }) - - after(() => { - delete container.YT - delete container.Vue - }) -}) - -describe('YouTubePlayer', () => { - before(() => { - class Player { - constructor (el, options) { - this.el = el - this.options = options - } - cueVideoById () {} - loadVideoById () {} - destroy () {} - } - container.YT = { - Player - } - container.Vue = { - nextTick (callback) { - callback() - } - } - }) - - describe('#ready', () => { - it('should call container.register', () => { - sinon.spy(container, 'register') - YouTubePlayer.mounted() - - assert.ok(container.register.called) - container.register.restore() - }) - - context('default values', () => { - it('should pass the default values', () => { - const videoId = 'videoId' - const component = { - mounted: YouTubePlayer.mounted, - videoId - } - component.mounted() - - const { options } = component.player - assert.equal(options.videoId, 'videoId') - assert.equal(options.width, '640') - assert.equal(options.height, '390') - }) - }) - - context('params are passed', () => { - it('should pass the params instead of default values', () => { - const videoId = 'videoId' - const playerWidth = '1280' - const playerHeight = '750' - const playerVars = { - start: 30, - autoplay: 1 - } - const component = { - mounted: YouTubePlayer.mounted, - videoId, - playerWidth, - playerHeight, - playerVars - } - component.mounted() - - const { options } = component.player - assert.equal(options.videoId, videoId) - assert.equal(options.width, playerWidth) - assert.equal(options.height, playerHeight) - assert.deepEqual(options.playerVars, playerVars) - }) - }) - }) - - describe('#update', () => { - context('default', () => { - it('should call YT.Player.prototype.cueVideoById()', () => { - const component = { - mounted: YouTubePlayer.mounted, - update: YouTubePlayer.methods.update - } - component.mounted() - sinon.spy(component.player, 'cueVideoById') - component.update('videoId') - assert.ok(component.player.cueVideoById.called) - }) - }) - - context('autoplay is 0', () => { - it('should call YT.Player.prototype.cueVideoById()', () => { - const component = { - mounted: YouTubePlayer.mounted, - update: YouTubePlayer.methods.update, - playerVars: { - autoplay: 0 - } - } - component.mounted() - sinon.spy(component.player, 'cueVideoById') - component.update('videoId') - assert.ok(component.player.cueVideoById.called) - }) - }) - - context('autoplay is 1', () => { - it('should call YT.Player.prototype.loadVideoById()', () => { - const component = { - mounted: YouTubePlayer.mounted, - update: YouTubePlayer.methods.update, - playerVars: { - autoplay: 1 - } - } - component.mounted() - sinon.spy(component.player, 'loadVideoById') - component.update('videoId') - assert.ok(component.player.loadVideoById.called) - }) - }) - }) - - describe('#beforeDestroy', () => { - it('should call YT.Player.prototype.destroy()', () => { - const component = { - beforeDestroy: YouTubePlayer.beforeDestroy - } - const player = new container.YT.Player(null, null) - component.player = player - sinon.spy(player, 'destroy') - component.beforeDestroy() - assert.ok(player.destroy.called) - assert.ok(typeof component.player === 'undefined') - }) - }) - - after(() => { - delete container.YT - }) -}) - describe('install', () => { before(() => { - Vue.use(install) + Vue.use(VueYouTubeEmbed) }) it('should add "youtube" component to Vue', () => { diff --git a/test/player.spec.js b/test/player.spec.js new file mode 100644 index 0000000..2e09dc3 --- /dev/null +++ b/test/player.spec.js @@ -0,0 +1,172 @@ +import assert from 'power-assert' +import Vue from 'vue' +import YouTubePlayer from '../src/player' + +import container from '../src/container' + +describe('YouTubePlayer', () => { + before(() => { + class Player { + constructor (el, options) { + this.el = el + this.options = options + this.muted = false + } + cueVideoById () {} + loadVideoById () {} + destroy () {} + mute () { this.muted = true } + unMute () { this.muted = false } + isMuted () { return this.muted } + } + container.YT = { + Player + } + container.Vue = { + nextTick (callback) { + callback() + } + } + }) + + describe('#ready', () => { + it('should call container.register', () => { + sinon.spy(container, 'register') + const vm = new Vue(YouTubePlayer) + vm.$mount() + + assert.ok(container.register.called) + container.register.restore() + }) + + context('default values', () => { + it('should pass the default values', () => { + const videoId = 'videoId' + + const vm = new Vue({ + mixins: [YouTubePlayer], + propsData: { + videoId + } + }) + vm.$mount() + + assert.equal(vm.videoId, 'videoId') + assert.equal(vm.playerWidth, '640') + assert.equal(vm.playerHeight, '390') + }) + }) + + context('params are passed', () => { + it('should pass the params instead of default values', () => { + const videoId = 'videoId' + const playerWidth = '1280' + const playerHeight = '750' + const playerVars = { + start: 30, + autoplay: 1 + } + + const vm = new Vue({ + mixins: [YouTubePlayer], + propsData: { + videoId, playerHeight, playerWidth, playerVars + } + }) + vm.$mount() + + assert.equal(vm.videoId, videoId) + assert.equal(vm.playerWidth, playerWidth) + assert.equal(vm.playerHeight, playerHeight) + assert.deepEqual(vm.playerVars, playerVars) + }) + }) + }) + + describe('#update', () => { + context('default', () => { + it('should call YT.Player.prototype.cueVideoById()', () => { + const vm = new Vue({ + mixins: [YouTubePlayer], + propsData: { + videoId: 'videoId' + } + }) + vm.$mount() + + sinon.spy(vm.player, 'cueVideoById') + vm.update('videoId') + assert.ok(vm.player.cueVideoById.called) + }) + }) + + context('autoplay is 0', () => { + it('should call YT.Player.prototype.cueVideoById()', () => { + const vm = new Vue({ + mixins: [YouTubePlayer], + propsData: { + videoId: 'videoId' + } + }) + vm.$mount() + + sinon.spy(vm.player, 'cueVideoById') + vm.update('videoId') + assert.ok(vm.player.cueVideoById.called) + }) + }) + + context('autoplay is 1', () => { + it('should call YT.Player.prototype.loadVideoById()', () => { + const vm = new Vue({ + mixins: [YouTubePlayer], + propsData: { + videoId: 'videoId', + playerVars: { + autoplay: 1 + } + } + }) + vm.$mount() + + sinon.spy(vm.player, 'loadVideoById') + vm.update('videoId') + assert.ok(vm.player.loadVideoById.called) + }) + }) + }) + + describe('#setMute', () => { + it('should update "mute"', (done) => { + const vm = new Vue({ + mixins: [YouTubePlayer] + }) + + vm.$mount() + + vm.mute = true + Vue.nextTick(() => { + assert.ok(vm.player.isMuted()) + done() + }) + }) + }) + + describe('#beforeDestroy', () => { + it('should call YT.Player.prototype.destroy()', () => { + const component = { + beforeDestroy: YouTubePlayer.beforeDestroy + } + const player = new container.YT.Player(null, null) + component.player = player + sinon.spy(player, 'destroy') + component.beforeDestroy() + assert.ok(player.destroy.called) + assert.ok(typeof component.player === 'undefined') + }) + }) + + after(() => { + delete container.YT + }) +}) diff --git a/test/utils.spec.js b/test/utils.spec.js new file mode 100644 index 0000000..93e4976 --- /dev/null +++ b/test/utils.spec.js @@ -0,0 +1,69 @@ +import assert from 'power-assert' +import { getIdFromURL, getTimeFromURL } from '../src/utils' + +// fork from https://github.com/brandly/angular-youtube-embed +describe('getIdFromURL', () => { + it('should handle regular query strings', () => { + const url = 'https://www.youtube.com/watch?v=nViWpVc1x_4&feature=youtu.be' + const id = 'nViWpVc1x_4' + assert.equal(getIdFromURL(url), id) + }) + + it('should handle attribution_link', () => { + const url = 'http://www.youtube.com/attribution_link?a=pxa6goHqzaA&u=%2Fwatch%3Fv%3DdPdgx30w9sU%26feature%3Dshare' + const id = 'dPdgx30w9sU' + assert.equal(getIdFromURL(url), id) + }) + + it('should handle almost a query string', () => { + const url = 'http://www.youtube.com/watch?feature=player_detailpage&v=93LvTKF_jW0#t=1' + const id = '93LvTKF_jW0' + assert.equal(getIdFromURL(url), id) + }) + + it('should handle "&feature=youtu.be"', () => { + const url = 'https://www.youtube.com/watch?v=VbNF9X1waSc&feature=youtu.be' + const id = 'VbNF9X1waSc' + assert.equal(getIdFromURL(url), id) + }) + + it('should handle http://youtu.be', () => { + const url = 'https://youtu.be/3FY4MRdQOdE' + const id = '3FY4MRdQOdE' + assert.equal(getIdFromURL(url), id) + }) + + it('should handle "edit" links from video manager page', () => { + const url = 'https://www.youtube.com/edit?o=U&video_id=3k2ZBu3kuiE' + const id = '3k2ZBu3kuiE' + assert.equal(getIdFromURL(url), id) + }) +}) + +// fork from https://github.com/brandly/angular-youtube-embed +describe('getTimeFromURL', () => { + it('should return 0 when time is not defined', () => { + const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo' + assert.equal(getTimeFromURL(url), 0) + }) + + it('should handle the url that contains "m" and "s"', () => { + const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4m20s' + assert.equal(getTimeFromURL(url), 20 + 4 * 60) + }) + + it('should handle the url that does not contain "s"', () => { + const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4m' + assert.equal(getTimeFromURL(url), 4 * 60) + }) + + it('should handle the url that does not contain "m"', () => { + const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4s' + assert.equal(getTimeFromURL(url), 4) + }) + + it('should handle the url that does not contain both "s" and "s"', () => { + const url = 'https://www.youtube.com/watch?v=3MteSlpxCpo&feature=youtu.be&t=4' + assert.equal(getTimeFromURL(url), 4) + }) +}) diff --git a/webpack.config.js b/webpack.config.js index 30fb421..337f3c8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -14,7 +14,7 @@ module.exports = { }, module: { loaders: [ - {test: /.\js$/, loader: 'babel?presets[]=es2015', exclude: /node_modules/} + { test: /.\js$/, loader: 'babel-loader', exclude: /node_modules/ } ] }, plugins: [