summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2023-06-12 14:31:13 +0200
committerOskar Nyberg <oskar@mullvad.net>2023-06-12 14:31:13 +0200
commita6193ecb0974af6fc8677208e204b9064a9484dd (patch)
tree2147ecef22e855b69aa8569120ad14d82f2061fa
parent601109ac7845bf603e4b2d17bb72f30401706b71 (diff)
parent2eecab47023011f96d9f76ce13bfd05e113a6c5b (diff)
downloadmullvadvpn-a6193ecb0974af6fc8677208e204b9064a9484dd.tar.xz
mullvadvpn-a6193ecb0974af6fc8677208e204b9064a9484dd.zip
Merge branch 'too-many-devices-view-isnt-shown-des-186'
-rw-r--r--gui/locales/messages.pot11
-rw-r--r--gui/src/main/account-data-cache.ts47
-rw-r--r--gui/src/main/account.ts23
-rw-r--r--gui/src/main/daemon-rpc.ts27
-rw-r--r--gui/src/main/errors.ts37
-rw-r--r--gui/src/renderer/app.tsx15
-rw-r--r--gui/src/renderer/components/Login.tsx25
-rw-r--r--gui/src/renderer/redux/account/actions.ts10
-rw-r--r--gui/src/renderer/redux/account/reducers.ts8
-rw-r--r--gui/src/shared/daemon-rpc-types.ts8
-rw-r--r--gui/src/shared/ipc-schema.ts3
-rw-r--r--gui/test/unit/account-data-cache.spec.ts55
12 files changed, 126 insertions, 143 deletions
diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot
index d8d1019060..7d4e03e504 100644
--- a/gui/locales/messages.pot
+++ b/gui/locales/messages.pot
@@ -155,9 +155,6 @@ msgstr ""
msgid "Got it!"
msgstr ""
-msgid "Invalid account number"
-msgstr ""
-
msgid "IPv4"
msgstr ""
@@ -685,8 +682,8 @@ msgctxt "login-view"
msgid "Finishing upgrade."
msgstr ""
-#. Error message shown above login input when trying to login with a non-existent
-#. account number.
+#. Error message shown above login input when trying to login with a
+#. non-existent account number.
msgctxt "login-view"
msgid "Invalid account number"
msgstr ""
@@ -717,8 +714,8 @@ msgctxt "login-view"
msgid "Please wait"
msgstr ""
-#. Error message shown above login input when trying to login to an account with
-#. too many registered devices.
+#. Error message shown above login input when trying to login to an account
+#. with too many registered devices.
msgctxt "login-view"
msgid "Too many devices"
msgstr ""
diff --git a/gui/src/main/account-data-cache.ts b/gui/src/main/account-data-cache.ts
index 38d2cb8a01..a5860f9073 100644
--- a/gui/src/main/account-data-cache.ts
+++ b/gui/src/main/account-data-cache.ts
@@ -1,13 +1,20 @@
import { closeToExpiry, hasExpired } from '../shared/account-expiry';
-import { AccountToken, IAccountData, VoucherResponse } from '../shared/daemon-rpc-types';
+import {
+ AccountDataError,
+ AccountDataResponse,
+ AccountToken,
+ IAccountData,
+ VoucherResponse,
+} from '../shared/daemon-rpc-types';
import { dateByAddingComponent, DateComponent } from '../shared/date-helper';
import log from '../shared/logging';
import { Scheduler } from '../shared/scheduler';
-import { InvalidAccountError } from './errors';
+
+export type AccountFetchError = AccountDataError['error'] | 'cancelled';
interface IAccountFetchWatcher {
onFinish: () => void;
- onError: (error: Error) => void;
+ onError: (error: AccountFetchError) => void;
}
// Account data is valid for 1 minute unless the account has expired.
@@ -26,7 +33,7 @@ export default class AccountDataCache {
private watchers: IAccountFetchWatcher[] = [];
constructor(
- private fetchHandler: (token: AccountToken) => Promise<IAccountData>,
+ private fetchHandler: (token: AccountToken) => Promise<AccountDataResponse>,
private updateHandler: (data?: IAccountData) => void,
) {}
@@ -64,7 +71,7 @@ export default class AccountDataCache {
this.validUntil = undefined;
this.updateHandler();
this.notifyWatchers((watcher) => {
- watcher.onError(new Error('Cancelled'));
+ watcher.onError('cancelled');
});
}
@@ -94,16 +101,20 @@ export default class AccountDataCache {
private async performFetch(accountToken: AccountToken) {
this.performingFetch = true;
- try {
- // it's possible for invalidate() to be called or for a fetch for a different account token
- // to start before this fetch completes, so checking if the current account token is the one
- // used is necessary below.
- const accountData = await this.fetchHandler(accountToken);
-
+ // it's possible for invalidate() to be called or for a fetch for a different account token
+ // to start before this fetch completes, so checking if the current account token is the one
+ // used is necessary below.
+ const response = await this.fetchHandler(accountToken);
+ if ('error' in response) {
if (this.currentAccount === accountToken) {
- this.setValue(accountData);
+ this.handleFetchError(accountToken, response.error);
+ this.performingFetch = false;
+ }
+ } else {
+ if (this.currentAccount === accountToken) {
+ this.setValue(response);
- const refetchDelay = this.calculateRefetchDelay(accountData.expiry);
+ const refetchDelay = this.calculateRefetchDelay(response.expiry);
if (refetchDelay) {
this.scheduleFetch(accountToken, refetchDelay);
}
@@ -111,12 +122,6 @@ export default class AccountDataCache {
this.waitStrategy.reset();
this.performingFetch = false;
}
- } catch (e) {
- const error = e as Error;
- if (this.currentAccount === accountToken) {
- this.handleFetchError(accountToken, error);
- this.performingFetch = false;
- }
}
}
@@ -131,9 +136,9 @@ export default class AccountDataCache {
}
}
- private handleFetchError(accountToken: AccountToken, error: Error) {
+ private handleFetchError(accountToken: AccountToken, error: AccountDataError['error']) {
this.notifyWatchers((w) => w.onError(error));
- if (!(error instanceof InvalidAccountError)) {
+ if (error !== 'invalid-account') {
this.scheduleRetry(accountToken);
}
}
diff --git a/gui/src/main/account.ts b/gui/src/main/account.ts
index 6ee2aafcde..1690445fb2 100644
--- a/gui/src/main/account.ts
+++ b/gui/src/main/account.ts
@@ -1,5 +1,6 @@
import { closeToExpiry } from '../shared/account-expiry';
import {
+ AccountDataError,
AccountToken,
DeviceEvent,
DeviceState,
@@ -7,7 +8,6 @@ import {
IDeviceRemoval,
TunnelState,
} from '../shared/daemon-rpc-types';
-import { messages } from '../shared/gettext';
import log from '../shared/logging';
import {
AccountExpiredNotificationProvider,
@@ -17,7 +17,6 @@ import {
import { Scheduler } from '../shared/scheduler';
import AccountDataCache from './account-data-cache';
import { DaemonRpc } from './daemon-rpc';
-import { InvalidAccountError } from './errors';
import { IpcMainEventChannel } from './ipc-event-channel';
import { NotificationSender } from './notification-controller';
import { TunnelStateProvider } from './tunnel-state';
@@ -70,7 +69,9 @@ export default class Account {
public registerIpcListeners() {
IpcMainEventChannel.account.handleCreate(() => this.createNewAccount());
- IpcMainEventChannel.account.handleLogin((token: AccountToken) => this.login(token));
+ IpcMainEventChannel.account.handleLogin(
+ async (token: AccountToken) => (await this.login(token)) ?? undefined,
+ );
IpcMainEventChannel.account.handleLogout(() => this.logout());
IpcMainEventChannel.account.handleGetWwwAuthToken(() => this.daemonRpc.getWwwAuthToken());
IpcMainEventChannel.account.handleSubmitVoucher(async (voucherCode: string) => {
@@ -162,18 +163,12 @@ export default class Account {
}
}
- private async login(accountToken: AccountToken): Promise<void> {
- try {
- await this.daemonRpc.loginAccount(accountToken);
- } catch (e) {
- const error = e as Error;
- log.error(`Failed to login: ${error.message}`);
+ private async login(accountToken: AccountToken): Promise<AccountDataError | void> {
+ const error = await this.daemonRpc.loginAccount(accountToken);
- if (error instanceof InvalidAccountError) {
- throw Error(messages.gettext('Invalid account number'));
- } else {
- throw error;
- }
+ if (error) {
+ log.error(`Failed to login: ${error.error}`);
+ return error;
}
}
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 40794e765c..f3b744e522 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -8,6 +8,8 @@ import {
import { promisify } from 'util';
import {
+ AccountDataError,
+ AccountDataResponse,
AccountToken,
AfterDisconnect,
AuthFailedError,
@@ -23,7 +25,6 @@ import {
ErrorStateCause,
FirewallPolicyError,
FirewallPolicyErrorType,
- IAccountData,
IAppVersionInfo,
IBridgeConstraints,
IDevice,
@@ -61,12 +62,6 @@ import {
VoucherResponse,
} from '../shared/daemon-rpc-types';
import log from '../shared/logging';
-import {
- CommunicationError,
- InvalidAccountError,
- ListDevicesError,
- TooManyDevicesError,
-} from './errors';
import { ManagementServiceClient } from './management_interface/management_interface_grpc_pb';
import * as grpcTypes from './management_interface/management_interface_pb';
@@ -200,22 +195,22 @@ export class DaemonRpc {
}
}
- public async getAccountData(accountToken: AccountToken): Promise<IAccountData> {
+ public async getAccountData(accountToken: AccountToken): Promise<AccountDataResponse> {
try {
const response = await this.callString<grpcTypes.AccountData>(
this.client.getAccountData,
accountToken,
);
const expiry = response.getExpiry()!.toDate().toISOString();
- return { expiry };
+ return { type: 'success', expiry };
} catch (e) {
const error = e as grpc.ServiceError;
if (error.code) {
switch (error.code) {
case grpc.status.UNAUTHENTICATED:
- throw new InvalidAccountError();
+ return { type: 'error', error: 'invalid-account' };
default:
- throw new CommunicationError();
+ return { type: 'error', error: 'communication' };
}
}
throw error;
@@ -277,18 +272,18 @@ export class DaemonRpc {
return response.getValue();
}
- public async loginAccount(accountToken: AccountToken): Promise<void> {
+ public async loginAccount(accountToken: AccountToken): Promise<AccountDataError | void> {
try {
await this.callString(this.client.loginAccount, accountToken);
} catch (e) {
const error = e as grpc.ServiceError;
switch (error.code) {
case grpc.status.RESOURCE_EXHAUSTED:
- throw new TooManyDevicesError();
+ return { type: 'error', error: 'too-many-devices' };
case grpc.status.UNAUTHENTICATED:
- throw new InvalidAccountError();
+ return { type: 'error', error: 'invalid-account' };
default:
- throw new CommunicationError();
+ return { type: 'error', error: 'communication' };
}
}
}
@@ -603,7 +598,7 @@ export class DaemonRpc {
return response.getDevicesList().map(convertFromDevice);
} catch {
- throw new ListDevicesError();
+ throw new Error('Failed to list devices');
}
}
diff --git a/gui/src/main/errors.ts b/gui/src/main/errors.ts
deleted file mode 100644
index 86b482f7bd..0000000000
--- a/gui/src/main/errors.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { messages } from '../shared/gettext';
-
-export class InvalidAccountError extends Error {
- constructor() {
- super(
- // TRANSLATORS: Error message shown above login input when trying to login with a non-existent
- // TRANSLATORS: account number.
- messages.pgettext('login-view', 'Invalid account number'),
- );
- }
-}
-
-export class CommunicationError extends Error {
- constructor() {
- super('api.mullvad.net is blocked, please check your firewall');
- }
-}
-
-export class TooManyDevicesError extends Error {
- constructor() {
- super(
- // TRANSLATORS: Error message shown above login input when trying to login to an account with
- // TRANSLATORS: too many registered devices.
- messages.pgettext('login-view', 'Too many devices'),
- );
- }
-}
-
-export class ListDevicesError extends Error {
- constructor() {
- super(
- // TRANSLATORS: Error message shown above login input when trying to login but the app fails
- // TRANSLATORS: to fetch the list of registered devices.
- messages.pgettext('login-view', 'Failed to fetch list of devices'),
- );
- }
-}
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index c5377b5d54..6efcd81887 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -345,25 +345,22 @@ export default class AppRenderer {
this.previousLoginState = this.loginState;
this.loginState = 'logging in';
- try {
- await IpcRendererEventChannel.account.login(accountToken);
- } catch (e) {
- const error = e as Error;
- if (error.message === 'Too many devices') {
+ const response = await IpcRendererEventChannel.account.login(accountToken);
+ if (response?.type === 'error') {
+ if (response.error === 'too-many-devices') {
try {
await this.fetchDevices(accountToken);
- actions.account.loginTooManyDevices(error);
+ actions.account.loginTooManyDevices();
this.loginState = 'too many devices';
this.history.reset(RoutePath.tooManyDevices, { transition: transitions.push });
} catch (e) {
- const error = e as Error;
log.error('Failed to fetch device list');
- actions.account.loginFailed(error);
+ actions.account.loginFailed('list-devices');
}
} else {
- actions.account.loginFailed(error);
+ actions.account.loginFailed(response.error);
}
}
};
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 4219c0572f..07d4814f1b 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { sprintf } from 'sprintf-js';
import { colors } from '../../config.json';
-import { AccountToken } from '../../shared/daemon-rpc-types';
+import { AccountDataError, AccountToken } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import { formatAccountToken } from '../lib/account';
@@ -180,7 +180,7 @@ export default class Login extends React.Component<IProps, IState> {
switch (this.props.loginState.type) {
case 'failed':
return this.props.loginState.method === 'existing_account'
- ? this.props.loginState.error.message || messages.pgettext('login-view', 'Unknown error')
+ ? this.errorString(this.props.loginState.error)
: messages.pgettext('login-view', 'Failed to create account');
case 'too many devices':
return messages.pgettext('login-view', 'Too many devices');
@@ -197,6 +197,27 @@ export default class Login extends React.Component<IProps, IState> {
}
}
+ private errorString(error: AccountDataError['error']): string {
+ switch (error) {
+ case 'invalid-account':
+ // TRANSLATORS: Error message shown above login input when trying to login with a
+ // TRANSLATORS: non-existent account number.
+ return messages.pgettext('login-view', 'Invalid account number');
+ case 'too-many-devices':
+ // TRANSLATORS: Error message shown above login input when trying to login to an account
+ // TRANSLATORS: with too many registered devices.
+ return messages.pgettext('login-view', 'Too many devices');
+ case 'list-devices':
+ // TRANSLATORS: Error message shown above login input when trying to login but the app fails
+ // TRANSLATORS: to fetch the list of registered devices.
+ return messages.pgettext('login-view', 'Failed to fetch list of devices');
+ case 'communication':
+ return 'api.mullvad.net is blocked, please check your firewall';
+ default:
+ return messages.pgettext('login-view', 'Unknown error');
+ }
+ }
+
private getStatusIcon() {
const statusIconPath = this.getStatusIconPath();
return (
diff --git a/gui/src/renderer/redux/account/actions.ts b/gui/src/renderer/redux/account/actions.ts
index 2b186fb831..61fc09d981 100644
--- a/gui/src/renderer/redux/account/actions.ts
+++ b/gui/src/renderer/redux/account/actions.ts
@@ -1,4 +1,4 @@
-import { AccountToken, IDevice } from '../../../shared/daemon-rpc-types';
+import { AccountDataError, AccountToken, IDevice } from '../../../shared/daemon-rpc-types';
interface IStartLoginAction {
type: 'START_LOGIN';
@@ -13,12 +13,11 @@ interface ILoggedInAction {
interface ILoginFailedAction {
type: 'LOGIN_FAILED';
- error: Error;
+ error: AccountDataError['error'];
}
interface ILoginTooManyDevicesAction {
type: 'TOO_MANY_DEVICES';
- error: Error;
}
interface IPrepareLogoutAction {
@@ -115,17 +114,16 @@ function loggedIn(accountToken: AccountToken, device?: IDevice): ILoggedInAction
};
}
-function loginFailed(error: Error): ILoginFailedAction {
+function loginFailed(error: AccountDataError['error']): ILoginFailedAction {
return {
type: 'LOGIN_FAILED',
error,
};
}
-function loginTooManyDevices(error: Error): ILoginTooManyDevicesAction {
+function loginTooManyDevices(): ILoginTooManyDevicesAction {
return {
type: 'TOO_MANY_DEVICES',
- error,
};
}
diff --git a/gui/src/renderer/redux/account/reducers.ts b/gui/src/renderer/redux/account/reducers.ts
index a017d16be7..a78a777c0a 100644
--- a/gui/src/renderer/redux/account/reducers.ts
+++ b/gui/src/renderer/redux/account/reducers.ts
@@ -1,11 +1,13 @@
-import { AccountToken, IDevice } from '../../../shared/daemon-rpc-types';
+import { AccountDataError, AccountToken, IDevice } from '../../../shared/daemon-rpc-types';
import { ReduxAction } from '../store';
type LoginMethod = 'existing_account' | 'new_account';
export type LoginState =
| { type: 'none'; deviceRevoked: boolean }
| { type: 'logging in' | 'ok'; method: LoginMethod }
- | { type: 'failed' | 'too many devices'; method: LoginMethod; error: Error };
+ | { type: 'too many devices'; method: LoginMethod }
+ | { type: 'failed'; method: 'existing_account'; error: AccountDataError['error'] }
+ | { type: 'failed'; method: 'new_account'; error: Error };
export interface IAccountReduxState {
accountToken?: AccountToken;
deviceName?: string;
@@ -52,7 +54,7 @@ export default function (
case 'TOO_MANY_DEVICES':
return {
...state,
- status: { type: 'too many devices', method: 'existing_account', error: action.error },
+ status: { type: 'too many devices', method: 'existing_account' },
};
case 'PREPARE_LOG_OUT':
return {
diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts
index f8c9fa5fff..a1997d06ad 100644
--- a/gui/src/shared/daemon-rpc-types.ts
+++ b/gui/src/shared/daemon-rpc-types.ts
@@ -1,6 +1,14 @@
export interface IAccountData {
expiry: string;
}
+
+export type AccountDataError = {
+ type: 'error';
+ error: 'invalid-account' | 'too-many-devices' | 'list-devices' | 'communication';
+};
+
+export type AccountDataResponse = ({ type: 'success' } & IAccountData) | AccountDataError;
+
export type AccountToken = string;
export type Ip = string;
export interface ILocation {
diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts
index 1dc7d82701..5a50fa315a 100644
--- a/gui/src/shared/ipc-schema.ts
+++ b/gui/src/shared/ipc-schema.ts
@@ -2,6 +2,7 @@ import { GetTextTranslations } from 'gettext-parser';
import { ILinuxSplitTunnelingApplication, IWindowsApplication } from './application-types';
import {
+ AccountDataError,
AccountToken,
BridgeSettings,
BridgeState,
@@ -183,7 +184,7 @@ export const ipcSchema = {
device: notifyRenderer<DeviceEvent>(),
devices: notifyRenderer<Array<IDevice>>(),
create: invoke<void, string>(),
- login: invoke<AccountToken, void>(),
+ login: invoke<AccountToken, AccountDataError | undefined>(),
logout: invoke<void, void>(),
getWwwAuthToken: invoke<void, string>(),
submitVoucher: invoke<string, VoucherResponse>(),
diff --git a/gui/test/unit/account-data-cache.spec.ts b/gui/test/unit/account-data-cache.spec.ts
index 68595b5586..f3d6df3142 100644
--- a/gui/test/unit/account-data-cache.spec.ts
+++ b/gui/test/unit/account-data-cache.spec.ts
@@ -1,11 +1,12 @@
-import AccountDataCache from '../../src/main/account-data-cache';
-import { IAccountData } from '../../src/shared/daemon-rpc-types';
+import AccountDataCache, { AccountFetchError } from '../../src/main/account-data-cache';
+import { AccountDataResponse, IAccountData } from '../../src/shared/daemon-rpc-types';
import sinon from 'sinon';
import { expect, spy } from 'chai';
describe('IAccountData cache', () => {
const dummyAccountToken = '9876543210';
- const dummyAccountData: IAccountData = {
+ const dummyAccountData: AccountDataResponse = {
+ type: 'success',
expiry: new Date('2038-01-01').toISOString(),
};
@@ -28,7 +29,7 @@ describe('IAccountData cache', () => {
const watcher = new Promise<void>((resolve, reject) => {
cache.fetch(dummyAccountToken, {
onFinish: () => resolve(),
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});
@@ -37,14 +38,14 @@ describe('IAccountData cache', () => {
it('should notify when fetch fails on the first attempt', async () => {
const cache = new AccountDataCache(
- (_token) => Promise.reject(new Error('Fetch fail')),
+ (_token) => Promise.resolve({ type: 'error', error: 'invalid-account' }),
(_data) => {},
);
const watcher = new Promise<void>((resolve, reject) => {
cache.fetch(dummyAccountToken, {
onFinish: (_reason?: any) => resolve(),
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});
@@ -60,7 +61,7 @@ describe('IAccountData cache', () => {
cache.fetch(dummyAccountToken, {
onFinish: () => {},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});
@@ -85,7 +86,7 @@ describe('IAccountData cache', () => {
cache.fetch(dummyAccountToken, {
onFinish: () => reject(),
- onError: (_error: Error) => {},
+ onError: (_error: AccountFetchError) => {},
});
});
@@ -93,7 +94,7 @@ describe('IAccountData cache', () => {
});
it('should cancel first fetch', async () => {
- const firstError = spy((_error: Error) => {});
+ const firstError = spy((_error: AccountFetchError) => {});
const secondSuccess = spy();
const update = new Promise<IAccountData | void>((resolve, reject) => {
@@ -107,7 +108,7 @@ describe('IAccountData cache', () => {
onError: () => reject(),
});
- return new Promise<IAccountData>((resolve) => {
+ return new Promise<AccountDataResponse>((resolve) => {
setTimeout(() => resolve(dummyAccountData), 1000);
});
} else {
@@ -142,10 +143,10 @@ describe('IAccountData cache', () => {
const update = new Promise((resolve, reject) => {
let attempts = 0;
- const fetch = () => {
+ const fetch = (): Promise<AccountDataResponse> => {
attempts++;
if (attempts === 1) {
- return Promise.reject(new Error('First attempt fails'));
+ return Promise.resolve({ type: 'error', error: 'invalid-account' });
} else if (attempts === 2) {
setTimeout(() => clock.tick(8000));
return Promise.resolve(dummyAccountData);
@@ -159,7 +160,7 @@ describe('IAccountData cache', () => {
cache.fetch(dummyAccountToken, {
onFinish: () => {},
- onError: (_error: Error) => firstError(),
+ onError: (_error: AccountFetchError) => firstError(),
});
setTimeout(() => {
cache.fetch(dummyAccountToken, {
@@ -167,7 +168,7 @@ describe('IAccountData cache', () => {
secondSuccess();
setTimeout(resolve);
},
- onError: (_error: Error) => {},
+ onError: (_error: AccountFetchError) => {},
});
});
});
@@ -188,7 +189,7 @@ describe('IAccountData cache', () => {
};
const cache = new AccountDataCache(fetch, () => {});
- const onError = (_error: Error) => {};
+ const onError = (_error: AccountFetchError) => {};
cache.fetch(dummyAccountToken, { onFinish: () => {}, onError });
cache.fetch(dummyAccountToken, { onFinish: () => resolve(), onError });
});
@@ -205,14 +206,14 @@ describe('IAccountData cache', () => {
const update = new Promise<void>((resolve, reject) => {
let firstAttempt = true;
- const fetch = () => {
+ const fetch = (_accountToken: string): Promise<AccountDataResponse> => {
if (firstAttempt) {
firstAttempt = false;
setTimeout(() => clock.tick(120_000), 0);
- return Promise.resolve({ expiry });
+ return Promise.resolve({ type: 'success', expiry });
} else {
resolve();
- return Promise.resolve({ expiry });
+ return Promise.resolve({ type: 'success', expiry });
}
};
@@ -220,7 +221,7 @@ describe('IAccountData cache', () => {
cache.fetch(dummyAccountToken, {
onFinish: () => {},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});
@@ -235,7 +236,7 @@ describe('IAccountData cache', () => {
const cache = new AccountDataCache(
(_accountToken) => {
fetchSpy();
- return Promise.resolve({ expiry });
+ return Promise.resolve<AccountDataResponse>({ type: 'success', expiry });
},
() => {},
);
@@ -256,13 +257,13 @@ describe('IAccountData cache', () => {
onFinish: async () => {
resolve();
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});
@@ -279,7 +280,7 @@ describe('IAccountData cache', () => {
const cache = new AccountDataCache(
(_accountToken) => {
fetchSpy();
- return Promise.resolve({ expiry });
+ return Promise.resolve<AccountDataResponse>({ type: 'success', expiry });
},
() => {},
);
@@ -300,13 +301,13 @@ describe('IAccountData cache', () => {
onFinish: async () => {
resolve();
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
},
- onError: (_error: Error) => reject(),
+ onError: (_error: AccountFetchError) => reject(),
});
});