summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorErik Larkö <erik@mullvad.net>2017-07-28 11:38:41 +0200
committerErik Larkö <erik@mullvad.net>2017-07-28 11:38:41 +0200
commite13fe630fce123981e502939aafc3569a9412e0c (patch)
treec45c1e6ae79c1702c7285820e8823a9b94b2ebca
parenta196629083e1fb634a1d65e816a1b4bdfbdeb072 (diff)
parent5616dddc92d76a121d10cbbab5b6404c71ffc25b (diff)
downloadmullvadvpn-e13fe630fce123981e502939aafc3569a9412e0c.tar.xz
mullvadvpn-e13fe630fce123981e502939aafc3569a9412e0c.zip
Merge branch 'login-actions'
-rw-r--r--app/lib/backend.js21
-rw-r--r--app/redux/account/actions.js45
-rw-r--r--app/redux/account/reducers.js20
-rw-r--r--app/redux/store.js4
-rw-r--r--test/login.spec.js29
5 files changed, 79 insertions, 40 deletions
diff --git a/app/lib/backend.js b/app/lib/backend.js
index 3c322afa6d..a58a12a0cd 100644
--- a/app/lib/backend.js
+++ b/app/lib/backend.js
@@ -148,16 +148,12 @@ export class Backend {
}
- login(accountNumber: string) {
+ login(accountNumber: string): Promise<void> {
log.info('Attempting to login with account number', accountNumber);
- this._store.dispatch(accountActions.loginChange({
- accountNumber: accountNumber,
- status: 'logging in',
- error: null,
- }));
+ this._store.dispatch(accountActions.startLogin(accountNumber));
- this._ipc.getAccountData(accountNumber)
+ return this._ipc.getAccountData(accountNumber)
.then( response => {
log.info('Account exists', response);
@@ -167,11 +163,7 @@ export class Backend {
}).then( accountData => {
log.info('Log in complete');
- this._store.dispatch(accountActions.loginChange({
- status: 'ok',
- paidUntil: accountData.paid_until,
- error: null,
- }));
+ this._store.dispatch(accountActions.loginSuccessful(accountData.paid_until));
// Redirect the user after some time to allow for
// the 'Login Successful' screen to be visible
@@ -183,10 +175,7 @@ export class Backend {
// TODO: This is not true. If there is a communication link failure the promise will be rejected too
const err = new BackendError('INVALID_ACCOUNT');
- this._store.dispatch(accountActions.loginChange({
- status: 'failed',
- error: err,
- }));
+ this._store.dispatch(accountActions.loginFailed(err));
});
}
diff --git a/app/redux/account/actions.js b/app/redux/account/actions.js
index 0b828c678a..1be1d4c10d 100644
--- a/app/redux/account/actions.js
+++ b/app/redux/account/actions.js
@@ -1,13 +1,52 @@
// @flow
-import type { Backend } from '../../lib/backend';
+import type { Backend, BackendError } from '../../lib/backend';
import type { AccountReduxState } from './reducers.js';
-export type LoginChangeAction = {
+type StartLoginAction = {
+ type: 'START_LOGIN',
+ accountNumber: string,
+};
+type LoginSuccessfulAction = {
+ type: 'LOGIN_SUCCESSFUL',
+ paidUntil: string,
+};
+type LoginFailedAction = {
+ type: 'LOGIN_FAILED',
+ error: BackendError,
+};
+
+type LoginChangeAction = {
type:'LOGIN_CHANGE',
newData: $Shape<AccountReduxState>,
};
+export type AccountAction = StartLoginAction
+ | LoginSuccessfulAction
+ | LoginFailedAction
+ | LoginChangeAction;
+
+function startLogin(accountNumber: string): StartLoginAction {
+ return {
+ type: 'START_LOGIN',
+ accountNumber: accountNumber,
+ };
+}
+
+function loginSuccessful(paidUntil: string): LoginSuccessfulAction {
+ return {
+ type: 'LOGIN_SUCCESSFUL',
+ paidUntil: paidUntil,
+ };
+}
+
+function loginFailed(error: BackendError): LoginFailedAction {
+ return {
+ type: 'LOGIN_FAILED',
+ error: error,
+ };
+}
+
function loginChange(data: $Shape<AccountReduxState>): LoginChangeAction {
return {
type: 'LOGIN_CHANGE',
@@ -18,4 +57,4 @@ function loginChange(data: $Shape<AccountReduxState>): LoginChangeAction {
const login = (backend: Backend, account: string) => () => backend.login(account);
const logout = (backend: Backend) => () => backend.logout();
-export default { login, logout, loginChange };
+export default { login, logout, loginChange, startLogin, loginSuccessful, loginFailed };
diff --git a/app/redux/account/reducers.js b/app/redux/account/reducers.js
index d1fd284ee5..dedddd35b7 100644
--- a/app/redux/account/reducers.js
+++ b/app/redux/account/reducers.js
@@ -20,8 +20,26 @@ const initialState: AccountReduxState = {
export default function(state: AccountReduxState = initialState, action: ReduxAction): AccountReduxState {
- if (action.type === 'LOGIN_CHANGE') {
+ switch (action.type) {
+ case 'LOGIN_CHANGE':
return { ...state, ...action.newData };
+ case 'START_LOGIN':
+ return { ...state, ...{
+ status: 'logging in',
+ accountNumber: action.accountNumber,
+ error: null,
+ }};
+ case 'LOGIN_SUCCESSFUL':
+ return { ...state, ...{
+ status: 'ok',
+ error: null,
+ paidUntil: action.paidUntil,
+ }};
+ case 'LOGIN_FAILED':
+ return { ...state, ...{
+ status: 'failed',
+ error: action.error,
+ }};
}
return state;
diff --git a/app/redux/store.js b/app/redux/store.js
index 0a72a1869a..b4aa0375e1 100644
--- a/app/redux/store.js
+++ b/app/redux/store.js
@@ -17,7 +17,7 @@ import type { ConnectionReduxState } from './connection/reducers.js';
import type { SettingsReduxState } from './settings/reducers.js';
import type { ConnectionAction } from './connection/actions.js';
-import type { LoginChangeAction } from './account/actions.js';
+import type { AccountAction } from './account/actions.js';
import type { UpdateSettingsAction } from './settings/actions.js';
export type ReduxState = {
@@ -26,7 +26,7 @@ export type ReduxState = {
settings: SettingsReduxState
};
-export type ReduxAction = LoginChangeAction
+export type ReduxAction = AccountAction
| UpdateSettingsAction
| ConnectionAction;
diff --git a/test/login.spec.js b/test/login.spec.js
index 950205804c..5c7e0fe540 100644
--- a/test/login.spec.js
+++ b/test/login.spec.js
@@ -25,25 +25,22 @@ describe('Logging in', () => {
chain.onSuccessOrFailure(done);
- const action: any = accountActions.login(backend, '123');
- store.dispatch(action);
+ store.dispatch(accountActions.login(backend, '123'));
});
- it('should put the account data in the state', (done) => {
+ it('should put the account data in the state', () => {
const { store, backend, mockIpc } = setupBackendAndStore();
mockIpc.getAccountData = () => new Promise(r => r({
paid_until: '2001-01-01T00:00:00',
}));
- const action: any = accountActions.login(backend, '123');
- store.dispatch(action);
-
- checkNextTick( () => {
- const state = store.getState().account;
- expect(state.status).to.equal('ok');
- expect(state.accountNumber).to.equal('123');
- expect(state.paidUntil).to.equal('2001-01-01T00:00:00');
- }, done);
+ return backend.login('123')
+ .then( () => {
+ const state = store.getState().account;
+ expect(state.status).to.equal('ok');
+ expect(state.accountNumber).to.equal('123');
+ expect(state.paidUntil).to.equal('2001-01-01T00:00:00');
+ });
});
it('should indicate failure for non-existing accounts', (done) => {
@@ -54,9 +51,7 @@ describe('Logging in', () => {
});
- const action: any = accountActions.login(backend, '123');
- store.dispatch(action);
-
+ store.dispatch(accountActions.login(backend, '123'));
checkNextTick(() => {
const state = store.getState().account;
@@ -68,9 +63,7 @@ describe('Logging in', () => {
it('should redirect to /connect after 1s after successful login', (done) => {
const { store, backend } = setupBackendAndMockStore();
- const action: any = accountActions.login(backend, '123');
- store.dispatch(action);
-
+ store.dispatch(accountActions.login(backend, '123'));
setTimeout(() => {