diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-09-02 16:21:22 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-09-02 16:21:22 +0200 |
| commit | a139acd570c3e07aa93dd749e9a9b18b50aefcea (patch) | |
| tree | d8ac8cc9ccdeebe90bb11c94de8beae58060c3bd | |
| parent | a51484e55bed300c981caa4985667ba1ed960d7e (diff) | |
| parent | 5737f0c5a6335447d4e18d78151973e82e3a970a (diff) | |
| download | mullvadvpn-a139acd570c3e07aa93dd749e9a9b18b50aefcea.tar.xz mullvadvpn-a139acd570c3e07aa93dd749e9a9b18b50aefcea.zip | |
Merge branch 'tunnel-state-unit-test'
| -rw-r--r-- | gui/test/tunnel-state.spec.ts | 107 |
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'); + }); +}); + |
