Skip to content

Commit

Permalink
feat: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
montelaidev committed Feb 3, 2025
1 parent f2cdeb6 commit 37653b4
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 3 deletions.
6 changes: 3 additions & 3 deletions packages/keyring-controller/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ module.exports = merge(baseConfig, {
// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 95.51,
branches: 95.12,
functions: 100,
lines: 99.07,
statements: 99.08,
lines: 98.93,
statements: 98.94,
},
},

Expand Down
165 changes: 165 additions & 0 deletions packages/keyring-controller/src/KeyringController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import {
AccountImportStrategy,
KeyringController,
KeyringTypes,
displayForKeyring,
getKeyringByFingerprint,
isCustodyKeyring,
keyringBuilderFactory,
} from './KeyringController';
Expand Down Expand Up @@ -672,6 +674,43 @@ describe('KeyringController', () => {
});
});
});

describe('when fingerprint is provided', () => {
it('should export seed phrase for specific keyring', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
// @ts-expect-error TODO: fix type and add getFingerprint
const fingerprint = await keyring.getFingerprint();

const seed = await controller.exportSeedPhrase(password, fingerprint);
expect(seed).not.toBe('');
});
});

it('should throw error if keyring is not found', async () => {
await withController(async ({ controller }) => {
await expect(
controller.exportSeedPhrase(password, 'non-existent-fingerprint'),
).rejects.toThrow('KeyringController - Keyring not found.');
});
});

it('should throw error if fingerprint method is not available', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
// @ts-expect-error TODO: fix type and remove getFingerprint
delete keyring.getFingerprint;

await expect(
controller.exportSeedPhrase(password, 'some-fingerprint'),
).rejects.toThrow('KeyringController - Keyring not found.');
});
});
});
});

describe('exportAccount', () => {
Expand Down Expand Up @@ -978,6 +1017,7 @@ describe('KeyringController', () => {
const newKeyring = {
accounts: [address],
type: 'Simple Key Pair',
fingerprint: undefined,
};
const importedAccountAddress =
await controller.importAccountWithStrategy(
Expand Down Expand Up @@ -1056,6 +1096,7 @@ describe('KeyringController', () => {
const newKeyring = {
accounts: [address],
type: 'Simple Key Pair',
fingerprint: undefined,
};
const modifiedState = {
...initialState,
Expand Down Expand Up @@ -3524,6 +3565,130 @@ describe('KeyringController', () => {
});
});
});

describe('utils', () => {
describe('displayForKeyring', () => {
it('should return keyring info with fingerprint if available', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;

// @ts-expect-error TODO: fix type and add getFingerprint
const fingerprint = await keyring.getFingerprint();

const info = await displayForKeyring(keyring);

expect(info).toStrictEqual({
type: KeyringTypes.hd,
accounts: controller.state.keyrings[0].accounts,
fingerprint,
});
});
});

it('handles keyrings without the method', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
jest
// @ts-expect-error TODO: fix type and add getFingerprint
.spyOn(keyring, 'getFingerprint')
.mockImplementation(undefined);

const info = await displayForKeyring(keyring);

expect(info).toStrictEqual({
type: KeyringTypes.hd,
accounts: controller.state.keyrings[0].accounts,
fingerprint: undefined,
});
});
});
});

describe('getKeyringByFingerprint', () => {
it('should find keyring by fingerprint', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
// @ts-expect-error TODO: fix type and add getFingerprint
const fingerprint = await keyring.getFingerprint();

const found = await getKeyringByFingerprint([keyring], fingerprint);

expect(found).toBe(keyring);
});
});

it('should return undefined if no keyring matches fingerprint', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
const mockFingerprint = '0x123456';
jest
// @ts-expect-error TODO: fix type and add getFingerprint
.spyOn(keyring, 'getFingerprint')
// @ts-expect-error TODO: fix type and add getFingerprint
.mockResolvedValue(mockFingerprint);

const found = await getKeyringByFingerprint([keyring], '0xdifferent');

expect(found).toBeUndefined();
});
});

it('should handle keyrings without getFingerprint method', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
// @ts-expect-error mock missing method
delete keyring.getFingerprint;

const dummyFingerprint = '0x123456';

const found = await getKeyringByFingerprint(
[keyring],
dummyFingerprint,
);

expect(found).toBeUndefined();
});
});

it('should handle empty keyring array', async () => {
const dummyFingerprint = '0x123456';
const found = await getKeyringByFingerprint([], dummyFingerprint);
expect(found).toBeUndefined();
});

it('should handle undefined fingerprint from keyring', async () => {
await withController(async ({ controller }) => {
const keyring = controller.getKeyringsByType(
KeyringTypes.hd,
)[0] as EthKeyring<Json>;
const mockFingerprint = undefined;
jest
// @ts-expect-error TODO: fix type and add getFingerprint
.spyOn(keyring, 'getFingerprint')
// @ts-expect-error TODO: fix type and add getFingerprint
.mockResolvedValue(mockFingerprint);

const found = await getKeyringByFingerprint(
[keyring],
// @ts-expect-error forcing an undefined
mockFingerprint,
);

expect(found).toBeUndefined();
});
});
});
});
});

type WithControllerCallback<ReturnValue> = ({
Expand Down
5 changes: 5 additions & 0 deletions packages/keyring-controller/src/KeyringController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@ export async function getKeyringByFingerprint(
keyrings: EthKeyring<Json>[],
fingerprint: string,
): Promise<EthKeyring<Json> | undefined> {
// Do not attempt to return a keyring if the fingerprint is not provided
if (!fingerprint) {
return undefined;
}

const fingerprints = await Promise.all(
// @ts-expect-error TODO: update type in @metamask/utils
keyrings.map((kr) => kr?.getFingerprint?.()),
Expand Down

0 comments on commit 37653b4

Please sign in to comment.