summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-09-02 16:21:22 +0200
committerOskar Nyberg <oskar@mullvad.net>2022-09-02 16:21:22 +0200
commita139acd570c3e07aa93dd749e9a9b18b50aefcea (patch)
treed8ac8cc9ccdeebe90bb11c94de8beae58060c3bd
parenta51484e55bed300c981caa4985667ba1ed960d7e (diff)
parent5737f0c5a6335447d4e18d78151973e82e3a970a (diff)
downloadmullvadvpn-a139acd570c3e07aa93dd749e9a9b18b50aefcea.tar.xz
mullvadvpn-a139acd570c3e07aa93dd749e9a9b18b50aefcea.zip
Merge branch 'tunnel-state-unit-test'
-rw-r--r--gui/test/tunnel-state.spec.ts107
1 files changed, 107 insertions, 0 deletions
diff --git a/gui/test/tunnel-state.spec.ts b/gui/test/tunnel-state.spec.ts
new file mode 100644
index 0000000000..5720acda1d
--- /dev/null
+++ b/gui/test/tunnel-state.spec.ts
@@ -0,0 +1,107 @@
+import { expect, spy } from 'chai';
+import { it, describe } from 'mocha';
+import sinon from 'sinon';
+import TunnelStateHandler from '../src/main/tunnel-state';
+import { TunnelState } from '../src/shared/daemon-rpc-types';
+
+const connected: TunnelState = { state: 'connected' } as TunnelState;
+const connecting: TunnelState = { state: 'connecting' } as TunnelState;
+const disconnected: TunnelState = { state: 'disconnected' } as TunnelState;
+const disconnecting: TunnelState = { state: 'disconnecting' } as TunnelState;
+const error: TunnelState = { state: 'error' } as TunnelState;
+
+describe('Tunnel state', () => {
+ it('Should allow all updates', () => {
+ const stateUpdateSpy = spy();
+ // @ts-ignore
+ const handleTunnelStateUpdate = (tunnelState: TunnelState) => stateUpdateSpy(tunnelState.state);
+ const tunnelStateHandler = new TunnelStateHandler({ handleTunnelStateUpdate });
+
+ tunnelStateHandler.handleNewTunnelState(disconnecting);
+ tunnelStateHandler.handleNewTunnelState(connecting);
+ tunnelStateHandler.handleNewTunnelState(error);
+ tunnelStateHandler.handleNewTunnelState(disconnected);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(4);
+ expect(stateUpdateSpy).on.nth(1).to.have.been.called.with.exactly('disconnecting');
+ expect(stateUpdateSpy).on.nth(2).to.have.been.called.with.exactly('connecting');
+ expect(stateUpdateSpy).on.nth(3).to.have.been.called.with.exactly('error');
+ expect(stateUpdateSpy).on.nth(4).to.have.been.called.with.exactly('disconnected');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('disconnected');
+ });
+
+ it('Should ignore non-expected state update', () => {
+ const stateUpdateSpy = spy();
+ // @ts-ignore
+ const handleTunnelStateUpdate = (tunnelState: TunnelState) => stateUpdateSpy(tunnelState.state);
+ const tunnelStateHandler = new TunnelStateHandler({ handleTunnelStateUpdate });
+
+ tunnelStateHandler.expectNextTunnelState('connecting');
+ tunnelStateHandler.handleNewTunnelState(disconnecting);
+ tunnelStateHandler.handleNewTunnelState(connecting);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(2);
+ expect(stateUpdateSpy).on.nth(1).to.have.been.called.with.exactly('connecting');
+ expect(stateUpdateSpy).on.nth(2).to.have.been.called.with.exactly('connecting');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('connecting');
+ });
+
+ it('Should allow new states after expected state is reached', () => {
+ const stateUpdateSpy = spy();
+ // @ts-ignore
+ const handleTunnelStateUpdate = (tunnelState: TunnelState) => stateUpdateSpy(tunnelState.state);
+ const tunnelStateHandler = new TunnelStateHandler({ handleTunnelStateUpdate });
+
+ tunnelStateHandler.expectNextTunnelState('connecting');
+ tunnelStateHandler.handleNewTunnelState(disconnected);
+ tunnelStateHandler.handleNewTunnelState(connecting);
+ tunnelStateHandler.handleNewTunnelState(connected);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(3);
+ expect(stateUpdateSpy).on.nth(1).to.have.been.called.with.exactly('connecting');
+ expect(stateUpdateSpy).on.nth(2).to.have.been.called.with.exactly('connecting');
+ expect(stateUpdateSpy).on.nth(3).to.have.been.called.with.exactly('connected');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('connected');
+ });
+
+ it('Should allow error state update', () => {
+ const stateUpdateSpy = spy();
+ // @ts-ignore
+ const handleTunnelStateUpdate = (tunnelState: TunnelState) => stateUpdateSpy(tunnelState.state);
+ const tunnelStateHandler = new TunnelStateHandler({ handleTunnelStateUpdate });
+
+ tunnelStateHandler.expectNextTunnelState('connecting');
+ tunnelStateHandler.handleNewTunnelState(disconnected);
+ tunnelStateHandler.handleNewTunnelState(error);
+ tunnelStateHandler.handleNewTunnelState(disconnected);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(3);
+ expect(stateUpdateSpy).on.nth(1).to.have.been.called.with.exactly('connecting');
+ expect(stateUpdateSpy).on.nth(2).to.have.been.called.with.exactly('error');
+ expect(stateUpdateSpy).on.nth(3).to.have.been.called.with.exactly('disconnected');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('disconnected');
+ });
+
+ it('Should time out and use last ignored state', () => {
+ const clock = sinon.useFakeTimers({ shouldAdvanceTime: true });
+ const stateUpdateSpy = spy();
+ // @ts-ignore
+ const handleTunnelStateUpdate = (tunnelState: TunnelState) => stateUpdateSpy(tunnelState.state);
+ const tunnelStateHandler = new TunnelStateHandler({ handleTunnelStateUpdate });
+
+ tunnelStateHandler.expectNextTunnelState('connecting');
+ tunnelStateHandler.handleNewTunnelState(disconnected);
+ tunnelStateHandler.handleNewTunnelState(connected);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(1);
+ expect(stateUpdateSpy).on.nth(1).to.have.been.called.with.exactly('connecting');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('connecting');
+
+ clock.tick(3000);
+
+ expect(stateUpdateSpy).to.have.been.called.exactly(2);
+ expect(stateUpdateSpy).on.nth(2).to.have.been.called.with.exactly('connected');
+ expect(tunnelStateHandler.tunnelState.state).to.equal('connected');
+ });
+});
+