Skip to content

Commit 83241f6

Browse files
grypezclaude
andcommitted
test(wallet): add tests for AccountsController and ConnectivityController initialization
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7897187 commit 83241f6

6 files changed

Lines changed: 120 additions & 3 deletions

File tree

packages/wallet/src/Wallet.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller';
12
import { Messenger } from '@metamask/messenger';
23
import { Json } from '@metamask/utils';
34
import { webcrypto } from 'crypto';
45

56
import MockEncryptor from '../../keyring-controller/tests/mocks/mockEncryptor';
67
import * as initializationModule from './initialization/initialization';
7-
import { importSecretRecoveryPhrase } from './utilities';
8+
import {
9+
createSecretRecoveryPhrase,
10+
importSecretRecoveryPhrase,
11+
} from './utilities';
812
import { Wallet } from './Wallet';
913

1014
const TEST_SRP = 'test test test test test test test test test test test ball';
@@ -176,6 +180,34 @@ describe('Wallet', () => {
176180
expect(spy).toHaveBeenCalledTimes(1);
177181
});
178182

183+
describe('AccountsController', () => {
184+
it('tracks accounts created via KeyringController', async () => {
185+
const wallet = new Wallet({});
186+
await createSecretRecoveryPhrase(wallet, TEST_PASSWORD);
187+
188+
const keyringAccounts = await wallet.messenger.call(
189+
'KeyringController:getAccounts',
190+
);
191+
const trackedAddresses = Object.values(
192+
wallet.state.AccountsController.internalAccounts.accounts,
193+
).map((account) => account.address);
194+
195+
expect(trackedAddresses).toStrictEqual(keyringAccounts);
196+
});
197+
});
198+
199+
describe('ConnectivityController', () => {
200+
it('reports online connectivity status', async () => {
201+
const wallet = new Wallet({});
202+
203+
await new Promise<void>((resolve) => process.nextTick(resolve));
204+
205+
expect(wallet.state.ConnectivityController.connectivityStatus).toBe(
206+
CONNECTIVITY_STATUSES.Online,
207+
);
208+
});
209+
});
210+
179211
describe('KeyringController', () => {
180212
it('can unlock and populate accounts', async () => {
181213
const wallet = await setupWallet();

packages/wallet/src/initialization/instances/accounts-controller.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
AccountsController,
33
AccountsControllerMessenger,
4+
AccountsControllerState,
45
} from '@metamask/accounts-controller';
56
import {
67
Messenger,
@@ -26,7 +27,7 @@ export const accountsController: InitializationConfiguration<
2627
name: 'AccountsController',
2728
init: ({ state, messenger }) =>
2829
new AccountsController({
29-
state,
30+
state: (state ?? {}) as AccountsControllerState,
3031
messenger,
3132
}),
3233
getMessenger: (parent: RootMessenger<DefaultActions, DefaultEvents>) => {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { CONNECTIVITY_STATUSES } from '@metamask/connectivity-controller';
2+
import { Messenger } from '@metamask/messenger';
3+
4+
import {
5+
AlwaysOnlineAdapter,
6+
connectivityController,
7+
} from './connectivity-controller';
8+
9+
describe('AlwaysOnlineAdapter', () => {
10+
it('returns Online from getStatus', async () => {
11+
const adapter = new AlwaysOnlineAdapter();
12+
const status = await adapter.getStatus();
13+
14+
expect(status).toBe(CONNECTIVITY_STATUSES.Online);
15+
});
16+
17+
it('onConnectivityChange is a no-op', () => {
18+
const adapter = new AlwaysOnlineAdapter();
19+
const callback = jest.fn();
20+
21+
adapter.onConnectivityChange(callback);
22+
23+
expect(callback).not.toHaveBeenCalled();
24+
});
25+
26+
it('destroy is a no-op', () => {
27+
const adapter = new AlwaysOnlineAdapter();
28+
29+
expect(() => adapter.destroy()).not.toThrow();
30+
});
31+
});
32+
33+
describe('connectivityController', () => {
34+
it('reports online status after initialization', async () => {
35+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
36+
const parent = new Messenger<'Root', any, any>({ namespace: 'Root' });
37+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
38+
const messenger = connectivityController.getMessenger(parent as any);
39+
const controller = connectivityController.init({
40+
messenger,
41+
state: undefined,
42+
options: {},
43+
});
44+
45+
await controller.init();
46+
47+
expect(controller.state.connectivityStatus).toBe(
48+
CONNECTIVITY_STATUSES.Online,
49+
);
50+
});
51+
});

packages/wallet/src/initialization/instances/connectivity-controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { DefaultActions, DefaultEvents, RootMessenger } from '../defaults';
1111
import type { InitializationConfiguration } from '../types';
1212

1313
// TODO: For now, we assume we are always online.
14-
class AlwaysOnlineAdapter implements ConnectivityAdapter {
14+
export class AlwaysOnlineAdapter implements ConnectivityAdapter {
1515
async getStatus(): Promise<ConnectivityStatus> {
1616
return CONNECTIVITY_STATUSES.Online;
1717
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { webcrypto } from 'crypto';
2+
3+
import { createSecretRecoveryPhrase } from './utilities';
4+
import { Wallet } from './Wallet';
5+
6+
const TEST_PASSWORD = 'testpass';
7+
8+
describe('createSecretRecoveryPhrase', () => {
9+
beforeAll(() => {
10+
// We can remove this once we drop Node 18
11+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
12+
globalThis.crypto ??= webcrypto as typeof globalThis.crypto;
13+
14+
// eslint-disable-next-line no-restricted-syntax
15+
if (!('CryptoKey' in globalThis)) {
16+
Object.defineProperty(globalThis, 'CryptoKey', {
17+
value: webcrypto.CryptoKey,
18+
});
19+
}
20+
});
21+
22+
it('creates a vault and populates accounts', async () => {
23+
const wallet = new Wallet({});
24+
25+
await createSecretRecoveryPhrase(wallet, TEST_PASSWORD);
26+
27+
expect(
28+
await wallet.messenger.call('KeyringController:getAccounts'),
29+
).toHaveLength(1);
30+
});
31+
});

packages/wallet/tsconfig.build.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"rootDir": "./src"
77
},
88
"references": [
9+
{ "path": "../accounts-controller/tsconfig.build.json" },
910
{ "path": "../base-controller/tsconfig.build.json" },
11+
{ "path": "../connectivity-controller/tsconfig.build.json" },
1012
{ "path": "../keyring-controller/tsconfig.build.json" },
1113
{ "path": "../messenger/tsconfig.build.json" }
1214
],

0 commit comments

Comments
 (0)