From efa3dd04ea32692e96ec3b97047b3a3d67821679 Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Fri, 3 Nov 2017 16:47:18 +0100 Subject: [PATCH] Adds tests --- app/browser/api/ledger.js | 31 ++- app/common/cache/ledgerVideoCache.js | 14 + app/common/lib/ledgerUtil.js | 68 +++-- app/sessionStore.js | 3 +- docs/state.md | 3 + test/unit/app/browser/api/ledgerTest.js | 243 ++++++++++++++++++ .../app/common/cache/ledgerVideoCacheTest.js | 61 +++++ test/unit/app/common/lib/ledgerUtilTest.js | 120 +++++++++ 8 files changed, 511 insertions(+), 32 deletions(-) create mode 100644 test/unit/app/common/cache/ledgerVideoCacheTest.js diff --git a/app/browser/api/ledger.js b/app/browser/api/ledger.js index 3711b52adfa..ad2aa5443d7 100644 --- a/app/browser/api/ledger.js +++ b/app/browser/api/ledger.js @@ -44,7 +44,7 @@ const request = require('../../../js/lib/request') const ledgerUtil = require('../../common/lib/ledgerUtil') const tabState = require('../../common/state/tabState') const pageDataUtil = require('../../common/lib/pageDataUtil') -const ledgerVideoCahce = require('../../common/cache/ledgerVideoCache') +const ledgerVideoCache = require('../../common/cache/ledgerVideoCache') // Caching let locationDefault = 'NOOP' @@ -562,7 +562,7 @@ const getPublisherData = (result, scorekeeper) => { weight: result.pinPercentage } - data.publisherURL = result.publisherURL || (result.protocol || 'http:') + '//' + result.publisherKey + data.publisherURL = result.publisherURL || ((result.protocol || 'http:') + '//' + result.publisherKey) // media publisher if (result.faviconName) { @@ -935,7 +935,7 @@ const saveVisit = (state, publisherKey, duration, revisited) => { synopsis.addPublisher(publisherKey, {duration: duration, revisitP: revisited}) state = ledgerState.setPublisher(state, publisherKey, synopsis.publishers[publisherKey]) state = updatePublisherInfo(state) - state = verifiedP(state, publisherKey, (error, result) => { + state = module.exports.verifiedP(state, publisherKey, (error, result) => { if (!error) { appActions.onPublisherOptionUpdate(publisherKey, 'verified', result) savePublisherOption(publisherKey, 'verified', result) @@ -2340,7 +2340,7 @@ const saveOptionSynopsis = (prop, value) => { } const savePublisherOption = (publisherKey, prop, value) => { - if (synopsis.publishers && synopsis.publishers[publisherKey]) { + if (synopsis.publishers && synopsis.publishers[publisherKey] && synopsis.publishers[publisherKey].options) { synopsis.publishers[publisherKey].options[prop] = value } } @@ -2469,7 +2469,7 @@ const transitionWalletToBat = () => { let currentMediaKey = null const onMediaRequest = (state, xhr, type) => { - if (!xhr) { + if (!xhr || type == null) { return state } @@ -2492,10 +2492,10 @@ const onMediaRequest = (state, xhr, type) => { currentMediaKey = mediaKey } - const cache = ledgerVideoCahce.getDataByVideoId(state, mediaKey) + const cache = ledgerVideoCache.getDataByVideoId(state, mediaKey) if (!cache.isEmpty()) { - return saveVisit(state, cache.get('publisher'), duration, revisited) + return module.exports.saveVisit(state, cache.get('publisherKey'), duration, revisited) } const options = underscore.extend({roundtrip: roundtrip}, clientOptions) @@ -2522,7 +2522,7 @@ const onMediaRequest = (state, xhr, type) => { } const onMediaPublisher = (state, mediaKey, response, duration, revisited) => { - const publisherKey = response.get('publisher') + const publisherKey = response ? response.get('publisher') : null if (publisherKey == null) { return state } @@ -2562,14 +2562,18 @@ const onMediaPublisher = (state, mediaKey, response, duration, revisited) => { } else { synopsis.publishers[publisherKey].faviconName = faviconName synopsis.publishers[publisherKey].faviconURL = faviconURL + synopsis.publishers[publisherKey].publisherURL = publisherURL state = ledgerState.setPublishersProp(state, publisherKey, 'faviconName', faviconName) state = ledgerState.setPublishersProp(state, publisherKey, 'faviconURL', faviconURL) + state = ledgerState.setPublishersProp(state, publisherKey, 'publisherURL', publisherURL) } // Add to cache - state = ledgerVideoCahce.setCacheByVideoId(state, mediaKey, response) + state = ledgerVideoCache.setCacheByVideoId(state, mediaKey, Immutable.fromJS({ + publisherKey: response + })) - state = saveVisit(state, publisherKey, duration, revisited) + state = module.exports.saveVisit(state, publisherKey, duration, revisited) return state } @@ -2628,8 +2632,13 @@ const getMethods = () => { setSynopsis: (data) => { synopsis = data }, + setCurrentMediaKey: (key) => { + currentMediaKey = key + }, + getCurrentMediaKey: (key) => currentMediaKey, synopsisNormalizer, - pruneSynopsis + pruneSynopsis, + saveVisit } } diff --git a/app/common/cache/ledgerVideoCache.js b/app/common/cache/ledgerVideoCache.js index 63c22f1ae3c..c7f0ae3fcb1 100644 --- a/app/common/cache/ledgerVideoCache.js +++ b/app/common/cache/ledgerVideoCache.js @@ -2,8 +2,19 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ const Immutable = require('immutable') +const assert = require('assert') + +const { makeImmutable, isMap } = require('../state/immutableUtil') + +const validateState = function (state) { + state = makeImmutable(state) + assert.ok(isMap(state), 'state must be an Immutable.Map') + assert.ok(isMap(state.getIn(['cache', 'ledgerVideos'])), 'state must contain ledgerVideos as Immutable.Map') + return state +} const getDataByVideoId = (state, key) => { + state = validateState(state) if (key == null) { return Immutable.Map() } @@ -12,10 +23,13 @@ const getDataByVideoId = (state, key) => { } const setCacheByVideoId = (state, key, data) => { + state = validateState(state) if (key == null) { return state } + data = makeImmutable(data) + return state.setIn(['cache', 'ledgerVideos', key], data) } diff --git a/app/common/lib/ledgerUtil.js b/app/common/lib/ledgerUtil.js index 6e7b4c12b74..48238677fa4 100644 --- a/app/common/lib/ledgerUtil.js +++ b/app/common/lib/ledgerUtil.js @@ -188,6 +188,11 @@ const stickyP = (state, publisherKey) => { const getMediaId = (data, type) => { let id = null + + if (type == null || data == null) { + return id + } + switch (type) { case ledgerMediaProviders.YOUTUBE: { @@ -204,11 +209,16 @@ const getMediaKey = (id, type) => { return null } - return `${type.toLowerCase()}_${id.toLowerCase()}` + return `${type.toLowerCase()}_${id}` } const getMediaData = (xhr, type) => { let result = null + + if (xhr == null || type == null) { + return result + } + switch (type) { case ledgerMediaProviders.YOUTUBE: { @@ -253,18 +263,22 @@ const getYoutubeDuration = (data) => { } for (let i = 0; i < startTime.length; i++) { - time += parseInt(endTime[i]) - parseInt(startTime[i]) + time += parseFloat(endTime[i]) - parseFloat(startTime[i]) } // we get seconds back, so we need to convert it into ms time = time * 1000 - return time + return parseInt(time) } const isMediaProvider = (url) => { let provider = null + if (url == null) { + return provider + } + // Youtube if (url.startsWith('https://www.youtube.com/api/stats/watchtime?')) { provider = ledgerMediaProviders.YOUTUBE @@ -273,21 +287,35 @@ const isMediaProvider = (url) => { return provider } -module.exports = { - shouldTrackView, - batToCurrencyString, - formattedTimeFromNow, - formattedDateFromTimestamp, - walletStatus, - blockedP, - contributeP, - visibleP, - eligibleP, - stickyP, - formatCurrentBalance, - getMediaId, - getMediaDuration, - isMediaProvider, - getMediaData, - getMediaKey +const getMethods = () => { + const publicMethods = { + shouldTrackView, + batToCurrencyString, + formattedTimeFromNow, + formattedDateFromTimestamp, + walletStatus, + blockedP, + contributeP, + visibleP, + eligibleP, + stickyP, + formatCurrentBalance, + getMediaId, + getMediaDuration, + isMediaProvider, + getMediaData, + getMediaKey + } + + let privateMethods = {} + + if (process.env.NODE_ENV === 'test') { + privateMethods = { + getYoutubeDuration + } + } + + return Object.assign({}, publicMethods, privateMethods) } + +module.exports = getMethods() diff --git a/app/sessionStore.js b/app/sessionStore.js index 129d36d6cb8..cc3255606a4 100644 --- a/app/sessionStore.js +++ b/app/sessionStore.js @@ -925,7 +925,8 @@ module.exports.defaultAppState = () => { }, cache: { bookmarkLocation: undefined, - bookmarkOrder: {} + bookmarkOrder: {}, + ledgerVideos: {} }, pinnedSites: {}, bookmarks: {}, diff --git a/docs/state.md b/docs/state.md index 03cb56662f3..c9315db7e48 100644 --- a/docs/state.md +++ b/docs/state.md @@ -89,6 +89,9 @@ AppStore order: number, type: string // siteTags.BOOKMARK or siteTags.BOOKMARK_FOLDER }] + }, + ledgerVideos: { + [mediaKey]: string // publisher key } } clearBrowsingDataDefaults: { diff --git a/test/unit/app/browser/api/ledgerTest.js b/test/unit/app/browser/api/ledgerTest.js index 47e8ff9e0f1..06cb345802d 100644 --- a/test/unit/app/browser/api/ledgerTest.js +++ b/test/unit/app/browser/api/ledgerTest.js @@ -9,8 +9,12 @@ const sinon = require('sinon') const mockery = require('mockery') const settings = require('../../../../../js/constants/settings') const appActions = require('../../../../../js/actions/appActions') +const ledgerMediaProviders = require('../../../../../app/common/constants/ledgerMediaProviders') const defaultAppState = Immutable.fromJS({ + cache: { + ledgerVideos: {} + }, ledger: {}, migrations: {} }) @@ -19,6 +23,12 @@ describe('ledger api unit tests', function () { let ledgerApi let isBusy = false let ledgerClient + let ledgerPublisher + + // constants + const xhr = 'https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=11.338&et=21.339' + const videoId = 'youtube_kLiLOkzLetE' + const publisherKey = 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg' // settings let paymentsEnabled @@ -52,6 +62,8 @@ describe('ledger api unit tests', function () { } const fakeElectron = require('../../../lib/fakeElectron') const fakeAdBlock = require('../../../lib/fakeAdBlock') + ledgerPublisher = require('bat-publisher') + mockery.registerMock('bat-publisher', ledgerPublisher) mockery.registerMock('electron', fakeElectron) mockery.registerMock('level', fakeLevel) mockery.registerMock('ad-block', fakeAdBlock) @@ -149,12 +161,19 @@ describe('ledger api unit tests', function () { describe('initialize', function () { let notificationsInitSpy + beforeEach(function () { notificationsInitSpy = sinon.spy(ledgerApi.notifications, 'init') }) + afterEach(function () { notificationsInitSpy.restore() }) + + after(function () { + ledgerApi.setSynopsis(undefined) + }) + it('calls notifications.init', function () { ledgerApi.initialize(defaultAppState, true) assert(notificationsInitSpy.calledOnce) @@ -323,6 +342,10 @@ describe('ledger api unit tests', function () { }) describe('transitionWalletToBat', function () { + after(function () { + ledgerApi.setSynopsis(undefined) + }) + describe('when client is not busy', function () { before(function () { const batState = ledgerApi.onBootStateFile(defaultAppState) @@ -630,6 +653,10 @@ describe('ledger api unit tests', function () { }) describe('synopsisNormalizer', function () { + after(function () { + ledgerApi.setSynopsis(undefined) + }) + describe('prune synopsis', function () { let pruneSynopsisSpy @@ -654,6 +681,10 @@ describe('ledger api unit tests', function () { }) describe('pruneSynopsis', function () { + after(function () { + ledgerApi.setSynopsis(undefined) + }) + it('null case', function () { const result = ledgerApi.pruneSynopsis(defaultAppState) assert.deepEqual(result.toJS(), defaultAppState.toJS()) @@ -681,6 +712,9 @@ describe('ledger api unit tests', function () { }) const expectedResult = { + cache: { + ledgerVideos: {} + }, ledger: { synopsis: { publishers: { @@ -697,4 +731,213 @@ describe('ledger api unit tests', function () { assert.deepEqual(result.toJS(), expectedResult) }) }) + + describe('onMediaRequest', function () { + let publisherFromMediaPropsSpy, saveVisitSpy + + beforeEach(function () { + publisherFromMediaPropsSpy = sinon.stub(ledgerPublisher.getMedia, 'getPublisherFromMediaProps') + saveVisitSpy = sinon.spy(ledgerApi, 'saveVisit') + }) + + afterEach(function () { + publisherFromMediaPropsSpy.restore() + saveVisitSpy.restore() + ledgerApi.setCurrentMediaKey(null) + }) + + after(function () { + ledgerApi.setSynopsis(undefined) + }) + + it('null case', function () { + const result = ledgerApi.onMediaRequest(defaultAppState) + assert.deepEqual(result.toJS(), defaultAppState.toJS()) + assert(publisherFromMediaPropsSpy.notCalled) + assert(saveVisitSpy.notCalled) + }) + + it('set currentMediaKey when it is different than saved', function () { + ledgerApi.onMediaRequest(defaultAppState, xhr, ledgerMediaProviders.YOUTUBE) + assert.equal(ledgerApi.getCurrentMediaKey(), videoId) + assert(publisherFromMediaPropsSpy.calledOnce) + assert(saveVisitSpy.notCalled) + }) + + it('get data from cache', function () { + const state = defaultAppState.setIn(['cache', 'ledgerVideos', videoId], Immutable.fromJS({ + publisherKey: publisherKey + })) + ledgerApi.onMediaRequest(state, xhr, ledgerMediaProviders.YOUTUBE) + assert(publisherFromMediaPropsSpy.notCalled) + assert(saveVisitSpy.withArgs(state, publisherKey, 10001, false).calledOnce) + }) + + it('revisited if visiting the same media', function () { + const state = defaultAppState.setIn(['cache', 'ledgerVideos', videoId], Immutable.fromJS({ + publisherKey: publisherKey + })) + // first call, revisit false + ledgerApi.onMediaRequest(state, xhr, ledgerMediaProviders.YOUTUBE) + assert.equal(ledgerApi.getCurrentMediaKey(), videoId) + assert(saveVisitSpy.withArgs(state, publisherKey, 10001, false).calledOnce) + + // second call, revisit true + ledgerApi.onMediaRequest(state, xhr, ledgerMediaProviders.YOUTUBE) + assert(publisherFromMediaPropsSpy.notCalled) + assert(saveVisitSpy.withArgs(state, publisherKey, 10001, true).calledOnce) + }) + }) + + describe('onMediaPublisher', function () { + let saveVisitSpy, verifiedPStub + + const expectedState = Immutable.fromJS({ + cache: { + ledgerVideos: { + 'youtube_kLiLOkzLetE': { + publisherKey: { + publisher: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg', + faviconName: 'Brave', + providerName: 'Youtube', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com' + } + } + } + }, + ledger: { + about: { + synopsis: [], + synopsisOptions: {} + }, + synopsis: { + publishers: { + 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg': { + exclude: false, + options: { + exclude: true + }, + providerName: 'Youtube', + faviconName: 'Brave', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com' + } + } + } + }, + migrations: {} + }) + + before(function () { + verifiedPStub = sinon.stub(ledgerApi, 'verifiedP', (state, publisherKey, fn) => state) + }) + + after(function () { + verifiedPStub.restore() + }) + + beforeEach(function () { + ledgerApi.setSynopsis({ + initPublisher: () => {}, + addPublisher: () => {}, + publishers: { + [publisherKey]: { + exclude: false, + options: { + exclude: true + }, + providerName: 'Youtube' + } + } + }) + saveVisitSpy = sinon.spy(ledgerApi, 'saveVisit') + }) + + afterEach(function () { + ledgerApi.setSynopsis(undefined) + saveVisitSpy.restore() + }) + + it('null case', function () { + const result = ledgerApi.onMediaPublisher(defaultAppState) + assert.deepEqual(result.toJS(), defaultAppState.toJS()) + }) + + it('min duration is set to minimum visit time if below that threshold', function () { + const response = Immutable.fromJS({ + publisher: publisherKey, + faviconName: 'Brave', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com', + providerName: 'Youtube' + }) + + ledgerApi.onMediaPublisher(defaultAppState, videoId, response, 1000, false) + assert(saveVisitSpy.calledOnce) + assert.equal(saveVisitSpy.args[0][1], publisherKey) + assert.equal(saveVisitSpy.args[0][2], paymentsMinVisitTime) + assert.equal(saveVisitSpy.args[0][3], false) + }) + + it('create publisher if new and add cache', function () { + const response = Immutable.fromJS({ + publisher: publisherKey, + faviconName: 'Brave', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com', + providerName: 'Youtube' + }) + + const state = ledgerApi.onMediaPublisher(defaultAppState, videoId, response, 1000, false) + assert(saveVisitSpy.calledOnce) + assert.deepEqual(state.toJS(), expectedState.toJS()) + }) + + it('update publisher if exists', function () { + const newState = Immutable.fromJS({ + cache: { + ledgerVideos: { + 'youtube_kLiLOkzLetE': { + publisherKey: { + publisher: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg', + faviconName: 'Brave', + providerName: 'Youtube', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com' + } + } + } + }, + ledger: { + synopsis: { + publishers: { + 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg': { + options: { + exclude: true + }, + faviconName: 'old Brave', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.io', + providerName: 'Youtube' + } + } + } + }, + migrations: {} + }) + + const response = Immutable.fromJS({ + publisher: publisherKey, + faviconName: 'Brave', + faviconURL: 'data:image/jpeg;base64,...', + publisherURL: 'https://brave.com', + providerName: 'Youtube' + }) + + const state = ledgerApi.onMediaPublisher(newState, videoId, response, 1000, false) + assert(saveVisitSpy.calledOnce) + assert.deepEqual(state.toJS(), expectedState.toJS()) + }) + }) }) diff --git a/test/unit/app/common/cache/ledgerVideoCacheTest.js b/test/unit/app/common/cache/ledgerVideoCacheTest.js new file mode 100644 index 00000000000..c340c1ec89e --- /dev/null +++ b/test/unit/app/common/cache/ledgerVideoCacheTest.js @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* global describe, it */ + +const Immutable = require('immutable') +const assert = require('assert') +const ledgerVideoCache = require('../../../../../app/common/cache/ledgerVideoCache') + +const baseState = Immutable.fromJS({ + cache: { + ledgerVideos: {} + } +}) +const stateWithData = Immutable.fromJS({ + cache: { + ledgerVideos: { + 'youtube_kLiLOkzLetE': { + publisherKey: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg' + } + } + } +}) + +describe('ledgerVideoCache unit test', function () { + describe('getDataByVideoId', function () { + it('key is not provided', function () { + const result = ledgerVideoCache.getDataByVideoId(baseState) + assert.deepEqual(result.toJS(), {}) + }) + + it('key does not exist in the cache', function () { + const result = ledgerVideoCache.getDataByVideoId(baseState, 'key') + assert.deepEqual(result.toJS(), {}) + }) + + it('data is ok', function () { + const result = ledgerVideoCache.getDataByVideoId(stateWithData, 'youtube_kLiLOkzLetE') + assert.deepEqual(result.toJS(), { + publisherKey: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg' + }) + }) + }) + + describe('setCacheByVideoId', function () { + it('key is not provided', function () { + const state = ledgerVideoCache.setCacheByVideoId(baseState) + assert.deepEqual(state.toJS(), baseState.toJS()) + }) + + it('data is ok', function () { + const state = ledgerVideoCache.setCacheByVideoId(baseState, 'youtube_kLiLOkzLetE', Immutable.fromJS({ + publisherKey: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg' + })) + const expectedState = state.setIn(['cache', 'ledgerVideos', 'youtube_kLiLOkzLetE'], Immutable.fromJS({ + publisherKey: 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg' + })) + assert.deepEqual(state.toJS(), expectedState.toJS()) + }) + }) +}) diff --git a/test/unit/app/common/lib/ledgerUtilTest.js b/test/unit/app/common/lib/ledgerUtilTest.js index 3e068702fa6..22c1459e4cc 100644 --- a/test/unit/app/common/lib/ledgerUtilTest.js +++ b/test/unit/app/common/lib/ledgerUtilTest.js @@ -3,6 +3,7 @@ const mockery = require('mockery') const assert = require('assert') const Immutable = require('immutable') require('../../../braveUnit') +const ledgerMediaProviders = require('../../../../../app/common/constants/ledgerMediaProviders') describe('ledgerUtil test', function () { let ledgerUtil @@ -171,4 +172,123 @@ describe('ledgerUtil test', function () { describe('walletStatus', function () { }) + + describe('getMediaId', function () { + it('null case', function () { + const result = ledgerUtil.getMediaId() + assert.equal(result, null) + }) + + it('unknown type', function () { + const result = ledgerUtil.getMediaData({}, 'test') + assert.equal(result, null) + }) + + describe('Youtube', function () { + it('null case', function () { + const result = ledgerUtil.getMediaId(null, ledgerMediaProviders.YOUTUBE) + assert.equal(result, null) + }) + + it('id is provided', function () { + const result = ledgerUtil.getMediaId({docid: 'kLiLOkzLetE'}, ledgerMediaProviders.YOUTUBE) + assert.equal(result, 'kLiLOkzLetE') + }) + }) + }) + + describe('getMediaKey', function () { + it('null case', function () { + const result = ledgerUtil.getMediaKey() + assert.equal(result, null) + }) + + it('type is missing', function () { + const result = ledgerUtil.getMediaKey('kLiLOkzLetE') + assert.equal(result, null) + }) + + it('id is null', function () { + const result = ledgerUtil.getMediaKey(null, ledgerMediaProviders.YOUTUBE) + assert.equal(result, null) + }) + + it('data is ok', function () { + const result = ledgerUtil.getMediaKey('kLiLOkzLetE', ledgerMediaProviders.YOUTUBE) + assert.equal(result, 'youtube_kLiLOkzLetE') + }) + }) + + describe('getMediaData', function () { + it('null case', function () { + const result = ledgerUtil.getMediaData() + assert.equal(result, null) + }) + + it('unknown type', function () { + const result = ledgerUtil.getMediaData('https://youtube.com', 'test') + assert.equal(result, null) + }) + + describe('Youtube', function () { + it('null case', function () { + const result = ledgerUtil.getMediaData(null, ledgerMediaProviders.YOUTUBE) + assert.equal(result, null) + }) + + it('query is not present', function () { + const result = ledgerUtil.getMediaData('https://youtube.com', ledgerMediaProviders.YOUTUBE) + assert.equal(result, null) + }) + + it('query is present', function () { + const result = ledgerUtil.getMediaData('https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=11.338&et=21.339', ledgerMediaProviders.YOUTUBE) + assert.deepEqual(result, { + docid: 'kLiLOkzLetE', + st: '11.338', + et: '21.339' + }) + }) + }) + }) + + describe('getYoutubeDuration', function () { + it('null case', function () { + const result = ledgerUtil.getYoutubeDuration() + assert.equal(result, 0) + }) + + it('multiple times', function () { + const result = ledgerUtil.getYoutubeDuration({ + st: '11.338,21.339,25.000', + et: '21.339,25.000,26.100' + }) + assert.equal(result, 14762) + }) + + it('single time', function () { + const result = ledgerUtil.getYoutubeDuration({ + st: '11.338', + et: '21.339' + }) + assert.equal(result, 10001) + }) + }) + + describe('isMediaProvider', function () { + it('null case', function () { + const result = ledgerUtil.isMediaProvider() + assert.equal(result, null) + }) + + it('unknown provider', function () { + const result = ledgerUtil.isMediaProvider('https://www.brave.com') + assert.equal(result, null) + }) + + it('youtube', function () { + const result = ledgerUtil.isMediaProvider('https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=11.338&et=21.339') + assert.equal(result, ledgerMediaProviders.YOUTUBE) + }) + }) })