diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-04-01 16:00:22 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-04-01 16:00:22 +0200 |
| commit | 33c7666cc6d03b393b4e003c04c4ca1d3a4ff5cc (patch) | |
| tree | 6a155396bedff004b0f733ad7fc304b8cc215336 /gui/test | |
| parent | bcf731749bddebb2eb25ccc6a5b83b45de8fdb0e (diff) | |
| parent | c54a8e8af8ed5e53151ded7f66d9eea7cf7a5d20 (diff) | |
| download | mullvadvpn-33c7666cc6d03b393b4e003c04c4ca1d3a4ff5cc.tar.xz mullvadvpn-33c7666cc6d03b393b4e003c04c4ca1d3a4ff5cc.zip | |
Merge branch 'fix-typescript-tests'
Diffstat (limited to 'gui/test')
| -rw-r--r-- | gui/test/account-data-cache.spec.ts | 41 | ||||
| -rw-r--r-- | gui/test/components/NotificationArea.spec.tsx | 102 | ||||
| -rw-r--r-- | gui/test/jsonrpc-transport.spec.ts | 119 | ||||
| -rw-r--r-- | gui/test/keyframe-animation.spec.ts | 22 | ||||
| -rw-r--r-- | gui/test/setup/main.js (renamed from gui/test/setup/main.ts) | 2 |
5 files changed, 187 insertions, 99 deletions
diff --git a/gui/test/account-data-cache.spec.ts b/gui/test/account-data-cache.spec.ts index 33cb80e556..f9838a6dbb 100644 --- a/gui/test/account-data-cache.spec.ts +++ b/gui/test/account-data-cache.spec.ts @@ -1,16 +1,11 @@ -import { AccountDataCache } from '../src/renderer/app'; -import { AccountData } from '../src/shared/daemon-rpc-types'; +import AccountDataCache, { AccountFetchRetryAction } from '../src/renderer/lib/account-data-cache'; +import { IAccountData } from '../src/shared/daemon-rpc-types'; import * as sinon from 'sinon'; -import chai from 'chai'; -import spies from 'chai-spies'; -import chaiAsPromised from 'chai-as-promised'; -import { it, describe, beforeEach, afterEach } from 'mocha'; +import { expect, spy } from 'chai'; -const { expect, spy } = chai; - -describe('AccountData cache', () => { +describe('IAccountData cache', () => { const dummyAccountToken = '9876543210'; - const dummyAccountData: AccountData = { + const dummyAccountData: IAccountData = { expiry: new Date('2038-01-01').toISOString(), }; @@ -35,7 +30,7 @@ describe('AccountData cache', () => { onFinish: () => resolve(), onError: (_error: Error) => { reject(); - return 'stop'; + return AccountFetchRetryAction.stop; }, }); }); @@ -54,7 +49,7 @@ describe('AccountData cache', () => { onFinish: (_reason?: any) => resolve(), onError: (_error: Error) => { reject(); - return 'stop'; + return AccountFetchRetryAction.stop; }, }); }); @@ -70,7 +65,7 @@ describe('AccountData cache', () => { onFinish: spy(), onError: (_error: Error) => { reject(); - return 'stop'; + return AccountFetchRetryAction.stop; }, }); }); @@ -96,7 +91,7 @@ describe('AccountData cache', () => { cache.fetch(dummyAccountToken, { onFinish: () => reject(), - onError: spy((_error: Error) => 'retry'), + onError: spy((_error: Error) => AccountFetchRetryAction.retry), }); }); @@ -123,7 +118,7 @@ describe('AccountData cache', () => { cache.fetch(dummyAccountToken, { onFinish: spy(), - onError: spy((_error: Error) => 'stop'), + onError: spy((_error: Error) => AccountFetchRetryAction.stop), }); }); @@ -131,12 +126,12 @@ describe('AccountData cache', () => { }); it('should cancel first fetch', async () => { - const firstError = spy((_) => 'stop'); + const firstError = spy((_error: Error) => AccountFetchRetryAction.stop); const secondSuccess = spy(); - const update = new Promise((resolve, reject) => { + const update = new Promise<IAccountData>((resolve, reject) => { let firstAttempt = true; - const fetch = () => { + const fetch = (_token: string) => { if (firstAttempt) { firstAttempt = false; @@ -144,18 +139,22 @@ describe('AccountData cache', () => { onFinish: secondSuccess, onError: () => { reject(); - return 'stop'; + return AccountFetchRetryAction.stop; }, }); - return new Promise((resolve) => setTimeout(() => resolve(dummyAccountData), 1000)); + return new Promise<IAccountData>((resolve) => { + setTimeout(() => resolve(dummyAccountData), 1000); + }); } else { reject(); return Promise.resolve(dummyAccountData); } }; - const cache = new AccountDataCache(fetch, () => resolve()); + const cache = new AccountDataCache(fetch, (_accountData?: IAccountData) => { + resolve(); + }); setTimeout(resolve, 12000); diff --git a/gui/test/components/NotificationArea.spec.tsx b/gui/test/components/NotificationArea.spec.tsx index 54aae1f8a6..c117db914e 100644 --- a/gui/test/components/NotificationArea.spec.tsx +++ b/gui/test/components/NotificationArea.spec.tsx @@ -2,7 +2,9 @@ import moment from 'moment'; import * as React from 'react'; import { shallow } from 'enzyme'; import NotificationArea from '../../src/renderer/components/NotificationArea'; +import { AfterDisconnect } from '../../src/shared/daemon-rpc-types'; import AccountExpiry from '../../src/renderer/lib/account-expiry'; +import { expect } from 'chai'; describe('components/NotificationArea', () => { const defaultVersion = { @@ -12,7 +14,6 @@ describe('components/NotificationArea', () => { current: '2018.2', latest: '2018.2-beta1', latestStable: '2018.2', - nextUpgrade: null, }; const defaultExpiry = new AccountExpiry( @@ -23,35 +24,90 @@ describe('components/NotificationArea', () => { ); it('handles disconnecting state', () => { - for (const reason of ['nothing', 'block', 'reconnect']) { + for (const reason of ['nothing', 'block'] as AfterDisconnect[]) { const component = shallow( <NotificationArea tunnelState={{ state: 'disconnecting', - details: { reason }, + details: reason, }} version={defaultVersion} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); expect(component.state('visible')).to.be.false; } }); - it('handles connected or disconnected states', () => { - for (const state of ['connected', 'disconnected']) { - const component = shallow( - <NotificationArea - tunnelState={{ - state, - }} - version={defaultVersion} - accountExpiry={defaultExpiry} - />, - ); + it('handles disconnecting state when reconnecting', () => { + const component = shallow( + <NotificationArea + tunnelState={{ + state: 'disconnecting', + details: 'reconnect', + }} + version={defaultVersion} + accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} + />, + ); + expect(component.state('visible')).to.be.true; + }); - expect(component.state('visible')).to.be.false; - } + it('handles connected state', () => { + const component = shallow( + <NotificationArea + tunnelState={{ + state: 'connected', + details: { + address: '1.2.3.4', + protocol: 'tcp', + tunnel: 'openvpn', + }, + }} + version={defaultVersion} + accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} + />, + ); + + expect(component.state('visible')).to.be.false; + }); + + it('handles disconnected state', () => { + const component = shallow( + <NotificationArea + tunnelState={{ + state: 'disconnected', + }} + version={defaultVersion} + accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} + />, + ); + + expect(component.state('visible')).to.be.false; + }); + + it('handles disconnected state, blocking when connected', () => { + const component = shallow( + <NotificationArea + tunnelState={{ + state: 'disconnected', + }} + version={defaultVersion} + accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={true} + />, + ); + + expect(component.state('visible')).to.be.true; }); it('handles connecting state', () => { @@ -62,6 +118,8 @@ describe('components/NotificationArea', () => { }} version={defaultVersion} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -80,6 +138,8 @@ describe('components/NotificationArea', () => { }} version={defaultVersion} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -98,6 +158,8 @@ describe('components/NotificationArea', () => { consistent: false, }} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -119,6 +181,8 @@ describe('components/NotificationArea', () => { nextUpgrade: '2018.2', }} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -141,6 +205,8 @@ describe('components/NotificationArea', () => { nextUpgrade: '2018.3', }} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -164,6 +230,8 @@ describe('components/NotificationArea', () => { nextUpgrade: '2018.4-beta3', }} accountExpiry={defaultExpiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); @@ -186,6 +254,8 @@ describe('components/NotificationArea', () => { }} version={defaultVersion} accountExpiry={expiry} + openExternalLink={() => {}} + blockWhenDisconnected={false} />, ); diff --git a/gui/test/jsonrpc-transport.spec.ts b/gui/test/jsonrpc-transport.spec.ts index 7e4e56c80a..26d812b793 100644 --- a/gui/test/jsonrpc-transport.spec.ts +++ b/gui/test/jsonrpc-transport.spec.ts @@ -1,56 +1,49 @@ import { expect } from 'chai'; -import { it, describe, beforeEach, afterEach } from 'mocha'; +import { it, describe, beforeEach } from 'mocha'; import jsonrpc from 'jsonrpc-lite'; -import { Server } from 'mock-socket'; -import JsonRpcClient, { WebsocketTransport, TimeOutError } from '../src/main/jsonrpc-client'; +import JsonRpcClient, { ITransport, TimeOutError } from '../src/main/jsonrpc-client'; describe('JSON RPC transport', () => { - const WEBSOCKET_URL = 'ws://localhost:8080'; - let server: Server, transport: JsonRpcClient<string>; + let client: JsonRpcClient<string>, transport: MockTransport; beforeEach(() => { - server = new Server(WEBSOCKET_URL); - transport = new JsonRpcClient(new WebsocketTransport()); - }); - - afterEach(() => { - server.close(); + transport = new MockTransport(); + client = new JsonRpcClient(transport); + return client.connect(''); }); it('should reject failed jsonrpc requests', async () => { - server.on('connection', (socket) => { - socket.on('message', (msg) => { - const { payload } = jsonrpc.parse(msg); - if (payload.method === 'invalid-method') { - socket.send( - JSON.stringify( - jsonrpc.error(payload.id, new jsonrpc.JsonRpcError('Method not found', -32601)), + transport.onServerMessage = (msg) => { + const parsedMessage = jsonrpc.parseObject(msg); + + if (parsedMessage.type === 'request' && parsedMessage.payload.method === 'invalid-method') { + transport.reply( + JSON.stringify( + jsonrpc.error( + parsedMessage.payload.id, + new jsonrpc.JsonRpcError('Method not found', -32601), ), - ); - } - }); - }); + ), + ); + } + }; - await transport.connect(WEBSOCKET_URL); - const sendPromise = transport.send('invalid-method'); + const sendPromise = client.send('invalid-method'); return expect(sendPromise).to.eventually.be.rejectedWith('Method not found'); }); it('should route reply to correct promise', async () => { - server.on('connection', (socket) => { - socket.on('message', (msg) => { - const { payload } = jsonrpc.parse(msg); - if (payload.method === 'a message') { - socket.send(JSON.stringify(jsonrpc.success(payload.id, 'a reply'))); - } - }); - }); + transport.onServerMessage = (msg) => { + const parsedMessage = jsonrpc.parseObject(msg); - await transport.connect(WEBSOCKET_URL); + if (parsedMessage.type === 'request' && parsedMessage.payload.method === 'a message') { + transport.reply(JSON.stringify(jsonrpc.success(parsedMessage.payload.id, 'a reply'))); + } + }; - const decoyPromise = transport.send('a decoy', [], 100); - const messagePromise = transport.send('a message', [], 100); + const decoyPromise = client.send('a decoy', [], 100); + const messagePromise = client.send('a message', [], 100); return Promise.all([ expect(messagePromise).to.eventually.be.equal('a reply'), @@ -59,26 +52,22 @@ describe('JSON RPC transport', () => { }); it('should timeout if no response is returned', async () => { - await transport.connect(WEBSOCKET_URL); - const sendPromise = transport.send('timeout-message', {}, 1); + const sendPromise = client.send('timeout-message', {}, 1); return expect(sendPromise).to.eventually.be.rejectedWith(TimeOutError, 'Request timed out'); }); it('should route notifications', async () => { - server.on('connection', (socket) => { - socket.on('message', (msg) => { - const { payload } = jsonrpc.parse(msg); - if (payload.method === 'event_subscribe') { - socket.send(JSON.stringify(jsonrpc.success(payload.id, 1))); - } - }); - }); + transport.onServerMessage = (msg) => { + const parsedMessage = jsonrpc.parseObject(msg); - await transport.connect(WEBSOCKET_URL); + if (parsedMessage.type === 'request' && parsedMessage.payload.method === 'event_subscribe') { + transport.reply(JSON.stringify(jsonrpc.success(parsedMessage.payload.id, 1))); + } + }; const eventPromiseHelper = (() => { - let borrowedResolve: (param: any) => void | undefined = undefined; + let borrowedResolve: ((param: any) => void) | undefined = undefined; const promise = new Promise((resolve) => (borrowedResolve = resolve)); /* Flow does not understand that the body of Promise runs immediately. see https://github.com/facebook/flow/issues/6711 */ @@ -91,13 +80,43 @@ describe('JSON RPC transport', () => { }; })(); - await transport.subscribe('event', eventPromiseHelper.resolve); + await client.subscribe('event', eventPromiseHelper.resolve); - server.emit( - 'message', + transport.reply( JSON.stringify(jsonrpc.notification('event', { subscription: 1, result: 'beacon' })), ); return expect(eventPromiseHelper.promise).to.eventually.be.equal('beacon'); }); }); + +class MockTransport implements ITransport<string> { + public onOpen = () => { + // no-op + }; + public onMessage = (_message: object) => { + // no-op + }; + public onServerMessage = (_message: object) => { + // no-op + }; + public onClose = (_error?: Error) => { + // no-op + }; + + public close() { + this.onClose(); + } + + public send(msg: string) { + this.onServerMessage(JSON.parse(msg)); + } + + public reply(msg: string) { + this.onMessage(JSON.parse(msg)); + } + + public connect(_params: string) { + this.onOpen(); + } +} diff --git a/gui/test/keyframe-animation.spec.ts b/gui/test/keyframe-animation.spec.ts index 05efa6ad76..11eeaf0c54 100644 --- a/gui/test/keyframe-animation.spec.ts +++ b/gui/test/keyframe-animation.spec.ts @@ -19,7 +19,7 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([0, 1, 2, 3, 4]); - expect(animation._currentFrame).to.be.equal(4); + expect(animation.currentFrame).to.be.equal(4); done(); }; @@ -34,7 +34,7 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([3]); - expect(animation._currentFrame).to.be.equal(3); + expect(animation.currentFrame).to.be.equal(3); done(); }; @@ -49,7 +49,7 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([2, 3, 4]); - expect(animation._currentFrame).to.be.equal(4); + expect(animation.currentFrame).to.be.equal(4); done(); }; @@ -64,7 +64,7 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([4, 3, 2]); - expect(animation._currentFrame).to.be.equal(2); + expect(animation.currentFrame).to.be.equal(2); done(); }; @@ -79,11 +79,11 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([0, 1, 2, 3, 4]); - expect(animation._currentFrame).to.be.equal(4); + expect(animation.currentFrame).to.be.equal(4); done(); }; - animation._currentFrame = 0; + animation.currentFrame = 0; animation.play({ end: 4 }); }); @@ -95,11 +95,11 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([4, 3, 2]); - expect(animation._currentFrame).to.be.equal(2); + expect(animation.currentFrame).to.be.equal(2); done(); }; - animation._currentFrame = 4; + animation.currentFrame = 4; animation.play({ end: 2 }); }); @@ -111,11 +111,11 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([4, 3, 2, 1]); - expect(animation._currentFrame).to.be.equal(1); + expect(animation.currentFrame).to.be.equal(1); done(); }; - animation._currentFrame = 4; + animation.currentFrame = 4; animation.play({ end: 1 }); }); @@ -127,7 +127,7 @@ describe('lib/keyframe-animation', function() { }; animation.onFinish = () => { expect(seq).to.be.deep.equal([4, 3, 2, 1, 0]); - expect(animation._currentFrame).to.be.equal(0); + expect(animation.currentFrame).to.be.equal(0); done(); }; diff --git a/gui/test/setup/main.ts b/gui/test/setup/main.js index 9b6ecc5ef7..dd458a30b6 100644 --- a/gui/test/setup/main.ts +++ b/gui/test/setup/main.js @@ -1,4 +1,4 @@ -import log from 'electron-log'; +const log = require('electron-log'); log.transports.console.level = false; log.transports.file.level = false; |
