Skip to content

Commit

Permalink
fix(test): Refactored and fixed test for background-script. Also upda…
Browse files Browse the repository at this point in the history
…ted dependencies.
  • Loading branch information
xtangle committed Mar 2, 2018
1 parent 4362fb3 commit d660bc7
Show file tree
Hide file tree
Showing 13 changed files with 595 additions and 311 deletions.
2 changes: 1 addition & 1 deletion karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = function (config) {
'test/**/*.ts': ['karma-typescript']
},
client: {
captureConsole: false,
captureConsole: true,
mocha: {
opts: 'mocha.opts'
}
Expand Down
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"private": true,
"description": "Adds download buttons to SoundCloud pages.",
"main": "index.js",
"engines": {
"node": ">=7.6"
},
"scripts": {
"build": "webpack --config webpack.dev.js",
"build:prod": "webpack --config webpack.prod.js",
Expand All @@ -30,36 +33,38 @@
},
"devDependencies": {
"@types/chai": "^4.1.2",
"@types/chrome": "^0.0.59",
"@types/chrome": "^0.0.60",
"@types/jquery": "^3.3.0",
"@types/mocha": "^2.2.48",
"@types/mocha-each": "^1.1.0",
"@types/node": "^9.4.6",
"@types/sinon": "^4.1.3",
"@types/sinon": "^4.3.0",
"@types/sinon-chai": "^2.7.29",
"@types/sinon-chrome": "^2.2.0",
"chai": "^4.1.2",
"clean-webpack-plugin": "^0.1.18",
"copy-webpack-plugin": "^4.4.2",
"copy-webpack-plugin": "^4.5.0",
"fork-ts-checker-webpack-plugin": "^0.4.0",
"karma": "^2.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"karma-spec-reporter": "^0.0.32",
"karma-typescript": "^3.0.12",
"mocha": "^5.0.0",
"mocha-each": "^1.1.0",
"npm-run-all": "^4.1.2",
"rxjs": "^5.5.6",
"sinon": "^4.4.2",
"sinon-chai": "^2.14.0",
"sinon-chrome": "^2.2.4",
"sinon-chrome": "^2.3.0",
"ts-loader": "^4.0.0",
"tslint": "^5.9.1",
"tslint-eslint-rules": "^5.1.0",
"typescript": "^2.7.1",
"uglifyjs-webpack-plugin": "^1.2.2",
"webpack": "^4.0.1",
"webpack-chrome-extension-reloader": "^0.7.0",
"webpack-cli": "^2.0.9",
"webpack-cli": "^2.0.10",
"webpack-merge": "^4.1.2",
"yargs": "^11.0.0"
}
Expand Down
33 changes: 33 additions & 0 deletions src/service/download-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'rxjs/add/observable/fromEventPattern';
import 'rxjs/add/observable/of';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import DownloadOptions = chrome.downloads.DownloadOptions;

/**
* Downloads tracks
*/
export interface IDownloadService {
// noinspection JSUnusedLocalSymbols
downloadTrack(trackUrl: string): Observable<number>;
}

export const DownloadService: IDownloadService = {

downloadTrack(trackUrl: string): Observable<number> {
const downloadId$: Subject<number> = new Subject<number>();
const downloadOptions: DownloadOptions = {saveAs: false, url: trackUrl};

chrome.downloads.download(downloadOptions, (id: number) => {
if (id !== undefined) {
downloadId$.next(id);
downloadId$.complete();
} else {
downloadId$.error(chrome.runtime.lastError.message);
}
});

return downloadId$.asObservable();
}

};
Empty file.
1 change: 1 addition & 0 deletions src/util/logger.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* tslint:disable no-console */
class Logger {
private readonly MSG_PREFIX = 'ZC';
public log(message?: any, ...optionalParams: any[]): void {
Expand Down
20 changes: 10 additions & 10 deletions test/page/track-content-page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {ZC_DL_BUTTON_CLASS} from '../../src/constants';
import {TrackContentPage, ZC_TRACK_DL_BUTTON_ID} from '../../src/page/track-content-page';
import {UrlService} from '../../src/service/url-service';

const forEach = require('mocha-each');

describe('track content page', () => {
chai.use(sinonChai);

Expand Down Expand Up @@ -48,12 +50,12 @@ describe('track content page', () => {
stubGetUrl.restore();
});

const trackPageUrls = [
const validTrackPageUrls = [
'https://soundcloud.com/some-user/some-track',
'https://soundcloud.com/abcdefg/some-track?in=user/sets/playlist',
];

const nonTrackPageUrls = [
const invalidTrackPageUrls = [
'https://soundcloud.com/you/sets',
'https://soundcloud.com/charts/top',
'https://soundcloud.com/jobs/2017-12-18-ux-prototyper-berlin',
Expand Down Expand Up @@ -82,19 +84,17 @@ describe('track content page', () => {
'https://soundcloud.com/discover/sets/new-for-you:140983555'
];

it('should load when URL matches a track page', () => {
trackPageUrls.forEach((url, index) => {
stubGetUrl.onCall(index).returns(url);
forEach(validTrackPageUrls)
.it('should test true when the URL is %s', (url: string) => {
stubGetUrl.onFirstCall().returns(url);
expect(fixture.test()).to.be.true;
});
});

it('should not load when URL does not match a track page', () => {
nonTrackPageUrls.forEach((url, index) => {
stubGetUrl.onCall(index).returns(url);
forEach(invalidTrackPageUrls)
.it('should test false when the URL is %s', (url: string) => {
stubGetUrl.onFirstCall().returns(url);
expect(fixture.test()).to.be.false;
});
});

});

Expand Down
118 changes: 56 additions & 62 deletions test/script/background-script.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as chai from 'chai';
import {expect} from 'chai';
import 'rxjs/add/observable/interval';
import 'rxjs/add/observable/timer';
import 'rxjs/add/operator/take';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {Subscription} from 'rxjs/Subscription';
import {match, SinonMatcher, SinonSpy, SinonStub, spy, stub} from 'sinon';
Expand All @@ -13,6 +13,8 @@ import {BackgroundScript} from '../../src/script/background-script';
import {doNothingIfMatch} from '../test-utils';
import WebNavigationUrlCallbackDetails = chrome.webNavigation.WebNavigationUrlCallbackDetails;

const forEach = require('mocha-each');

describe('background script', () => {
chai.use(sinonChai);

Expand All @@ -39,27 +41,26 @@ describe('background script', () => {
context('triggering the SoundCloud page visited observable', () => {

const callback: SinonSpy = spy();
const expectedDebounceTime = 50;

let stubOnCompleted: SinonStub;
let stubOnHistoryStateUpdated: SinonStub;
let subscription: Subscription;

before(() => {
/**
* Do not emit event (by doing a noop) if url does not match an SoundCloud url.
* This has to be patched in manually because sinon-chrome's addListener does not implement event filters.
* This has to be patched in manually because sinon-chrome's addListeners do not implement event filters.
*/
const doesNotHaveScUrl: SinonMatcher = match((details: WebNavigationUrlCallbackDetails) =>
const doesNotMatchScUrl: SinonMatcher = match((details: WebNavigationUrlCallbackDetails) =>
!details.url.match(SC_URL_PATTERN));
stubOnCompleted = stub(sinonChrome.webNavigation.onCompleted, 'trigger');
stubOnHistoryStateUpdated = stub(sinonChrome.webNavigation.onHistoryStateUpdated, 'trigger');
doNothingIfMatch(stubOnCompleted, doesNotHaveScUrl);
doNothingIfMatch(stubOnHistoryStateUpdated, doesNotHaveScUrl);
doNothingIfMatch(stubOnCompleted, doesNotMatchScUrl);
doNothingIfMatch(stubOnHistoryStateUpdated, doesNotMatchScUrl);
});

beforeEach(() => {
subscription = fixture.scPageVisited$.subscribe((val) => callback(val));
subscription = fixture.scPageVisited$.subscribe(callback);
fixture.run();
});

afterEach(() => {
Expand All @@ -72,75 +73,69 @@ describe('background script', () => {
stubOnHistoryStateUpdated.restore();
});

const scUrls = [
const validScUrls = [
'https://soundcloud.com/',
'https://soundcloud.com/some-user/some-track',
'https://soundcloud.com/abcdefg/some-track?in=user/sets/playlist',
'https://soundcloud.com/search?q=qwe%20rty'
'https://soundcloud.com/search?q=qwe%20rty',
];

const nonScUrls = [
const invalidScUrls = [
'https://not.soundcloud.com/',
'https://soundcloud.org/',
'https://soundcloud.com.abc/',
];

it('should trigger when Web Navigation On Completed emits with a SoundCloud URL', () => {
fixture.run();
scUrls.forEach((url, index) => {
const details = {tabId: index, timeStamp: 123, url};
sinonChrome.webNavigation.onCompleted.trigger(details);
expect(callback.withArgs(details)).to.have.been.calledOnce;
});
context('through the Web Navigation On Completed event', () => {
forEach(validScUrls)
.it('should trigger when the URL is %s', (url: string) => {
const details = {tabId: 1, timeStamp: 123, url};
sinonChrome.webNavigation.onCompleted.trigger(details);
expect(callback).to.have.been.calledOnce.calledWithExactly(details);
});

forEach(invalidScUrls)
.it('should not trigger when the URL is %s', (url: string) => {
const details = {tabId: 1, timeStamp: 123, url};
sinonChrome.webNavigation.onCompleted.trigger(details);
expect(callback).to.not.have.been.called;
});
});

it('should not trigger when Web Navigation On Completed doesn\'t emit with a SoundCloud URL', () => {
fixture.run();
nonScUrls.forEach((url, index) => {
sinonChrome.webNavigation.onCompleted.trigger({tabId: index, timeStamp: 123, url});
});
expect(callback).to.not.have.been.called;
});
context('through the Web Navigation On History Updated event', () => {
const debounceWaitTime = 25;

it('should trigger when Web Navigation On History Updated emits a SoundCloud URL', (done) => {
fixture.run();
/**
* Wait 'expectedDebounceTime' ms between each test so that no events are filtered by the de-bounce
*/
Observable.interval(expectedDebounceTime)
.take(scUrls.length)
.forEach((index) => {
const details = {tabId: index, timeStamp: 123, url: scUrls[index]};
forEach(validScUrls)
.it('should trigger when the URL is %s', (url: string, done: MochaDone) => {
const details = {tabId: 1, timeStamp: 123, url};
sinonChrome.webNavigation.onHistoryStateUpdated.trigger(details);
expect(callback.withArgs(details)).to.have.been.calledOnce;
})
.then(() => done())
.catch(() => done());
});

it('should not trigger when Web Navigation On History Updated doesn\'t emit with a SoundCloud URL', (done) => {
fixture.run();
Observable.interval(expectedDebounceTime)
.take(nonScUrls.length)
.forEach((index) => {
sinonChrome.webNavigation.onHistoryStateUpdated
.trigger({tabId: index, timeStamp: 123, url: nonScUrls[index]});
})
.then(() => {
expect(callback).to.not.have.been.called;
setTimeout(() => {
expect(callback).to.have.been.calledOnce.calledWithExactly(details);
done();
}, debounceWaitTime);
});

forEach(invalidScUrls)
.it('should not trigger when the URL is %s', (url: string, done: MochaDone) => {
const details = {tabId: 1, timeStamp: 123, url};
sinonChrome.webNavigation.onHistoryStateUpdated.trigger(details);
setTimeout(() => {
expect(callback).to.not.have.been.called;
done();
}, debounceWaitTime);
});

it('should de-bounce events when they are emitted close together', (done) => {
validScUrls.forEach((url) => {
sinonChrome.webNavigation.onHistoryStateUpdated.trigger({tabId: 1, timeStamp: 123, url});
});

const expectedDetails = {tabId: 1, timeStamp: 123, url: validScUrls[validScUrls.length - 1]};
setTimeout(() => {
expect(callback).to.have.been.calledOnce.calledWithExactly(expectedDetails);
done();
})
.catch(() => done());
});

it('should de-bounce events emitted by Web Navigation On History Updated', () => {
fixture.run();
scUrls.forEach((url, index) => {
sinonChrome.webNavigation.onCompleted.trigger({tabId: index, timeStamp: 123, url});
}, debounceWaitTime);
});
const expectedDetails = {tabId: scUrls.length - 1, timeStamp: 123, url: scUrls[scUrls.length - 1]};
expect(callback).to.not.have.been.calledOnce;
expect(callback).to.have.been.calledWithExactly(expectedDetails);
});

});
Expand Down Expand Up @@ -199,7 +194,6 @@ describe('background script', () => {

expect(spyUnsubscribe).to.have.been.called;
});

});

});
Loading

0 comments on commit d660bc7

Please sign in to comment.