Skip to content

Commit

Permalink
Merge branch 'main' into feat/disable-signing-buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
k-g-j authored Sep 26, 2024
2 parents 19ec196 + 4b8abcf commit f5d01a6
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 66 deletions.
31 changes: 30 additions & 1 deletion app/components/UI/AccountSelectorList/AccountSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import { View } from 'react-native';
import { ACCOUNT_BALANCE_BY_ADDRESS_TEST_ID } from '../../../../wdio/screen-objects/testIDs/Components/AccountListComponent.testIds';
import { backgroundState } from '../../../util/test/initial-root-state';
import { regex } from '../../../../app/util/regex';
import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils';
import {
createMockAccountsControllerState,
createMockAccountsControllerStateWithSnap,
MOCK_ADDRESS_1,
MOCK_ADDRESS_2,
} from '../../../util/test/accountsControllerTestUtils';
import { mockNetworkState } from '../../../util/test/network';
import { CHAIN_IDS } from '@metamask/transaction-controller';

Expand Down Expand Up @@ -200,4 +205,28 @@ describe('AccountSelectorList', () => {
expect(within(accountNameItems[1]).getByText('Account 2')).toBeDefined();
});
});
it('renders "Snaps (beta)" tag for Snap accounts', async () => {
const mockAccountsWithSnap = createMockAccountsControllerStateWithSnap([
MOCK_ADDRESS_1,
MOCK_ADDRESS_2,
]);

const stateWithSnapAccount = {
...initialState,
engine: {
...initialState.engine,
backgroundState: {
...initialState.engine.backgroundState,
AccountsController: mockAccountsWithSnap,
},
},
};

const { queryByText } = renderComponent(stateWithSnapAccount);

await waitFor(async () => {
const snapTag = await queryByText('Snaps (beta)');
expect(snapTag).toBeDefined();
});
});
});
29 changes: 2 additions & 27 deletions app/core/__mocks__/MockedEngine.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
import { KeyringTypes } from '@metamask/keyring-controller';
import { CHAIN_IDS } from '@metamask/transaction-controller';
import { mockNetworkState } from '../../util/test/network';
import { NetworkClientId } from '@metamask/network-controller';
import Engine from '../../core/Engine';
import { MOCK_KEYRING_CONTROLLER_STATE } from '../../util/test/keyringControllerTestUtils';

export const mockedEngine = {
init: () => Engine.init({}),
context: {
KeyringController: {
keyring: {
keyrings: [
{
mnemonic:
'one two three four five six seven eight nine ten eleven twelve',
},
],
},
state: {
keyrings: [
{
accounts: ['0xd018538C87232FF95acbCe4870629b75640a78E7'],
type: KeyringTypes.simple,
},
{
accounts: ['0xB374Ca013934e498e5baD3409147F34E6c462389'],
type: KeyringTypes.qr,
},
{
accounts: ['0x71C7656EC7ab88b098defB751B7401B5f6d8976F'],
type: KeyringTypes.hd,
},
],
},
},
KeyringController: MOCK_KEYRING_CONTROLLER_STATE,
NetworkController: {
getNetworkClientById: (networkClientId: NetworkClientId) => {
if (networkClientId === 'linea_goerli') {
Expand Down
89 changes: 56 additions & 33 deletions app/util/address/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ import {
getKeyringByAddress,
getLabelTextByAddress,
} from '.';
import {
mockHDKeyringAddress,
mockQrKeyringAddress,
mockSimpleKeyringAddress,
} from '../test/keyringControllerTestUtils';

const snapAddress = '0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272';

jest.mock('../../core/Engine', () => {
const { KeyringTypes } = jest.requireActual('@metamask/keyring-controller');
const { MOCK_KEYRING_CONTROLLER_STATE } = jest.requireActual(
'../test/keyringControllerTestUtils',
);
return {
context: {
KeyringController: {
...MOCK_KEYRING_CONTROLLER_STATE,
state: {
keyrings: [
...MOCK_KEYRING_CONTROLLER_STATE.state.keyrings,
{
accounts: [snapAddress],
index: 0,
type: KeyringTypes.snap,
},
],
},
},
},
};
});

describe('isENS', () => {
it('should return false by default', () => {
Expand Down Expand Up @@ -232,19 +263,13 @@ describe('isQRHardwareAccount', () => {
});

it('should return false if address is from keyring type simple', () => {
expect(
isQRHardwareAccount('0xd018538C87232FF95acbCe4870629b75640a78E7'),
).toBeFalsy();
expect(isQRHardwareAccount(mockSimpleKeyringAddress)).toBeFalsy();
});
it('should return false if address is from keyring type hd', () => {
expect(
isQRHardwareAccount('0x71C7656EC7ab88b098defB751B7401B5f6d8976F'),
).toBeFalsy();
expect(isQRHardwareAccount(mockHDKeyringAddress)).toBeFalsy();
});
it('should return true if address is from keyring type qr', () => {
expect(
isQRHardwareAccount('0xB374Ca013934e498e5baD3409147F34E6c462389'),
).toBeTruthy();
expect(isQRHardwareAccount(mockQrKeyringAddress)).toBeTruthy();
});
});
describe('getKeyringByAddress', () => {
Expand All @@ -257,9 +282,7 @@ describe('getKeyringByAddress', () => {
expect(getKeyringByAddress('ens.eth')).toBeUndefined();
});
it('should return address if found', () => {
expect(
getKeyringByAddress('0xB374Ca013934e498e5baD3409147F34E6c462389'),
).not.toBe(undefined);
expect(getKeyringByAddress(mockQrKeyringAddress)).not.toBe(undefined);
});
it('should return null if address not found', () => {
expect(
Expand All @@ -269,9 +292,7 @@ describe('getKeyringByAddress', () => {
});
describe('isHardwareAccount,', () => {
it('should return true if account is a QR keyring', () => {
expect(
isHardwareAccount('0xB374Ca013934e498e5baD3409147F34E6c462389'),
).toBeTruthy();
expect(isHardwareAccount(mockQrKeyringAddress)).toBeTruthy();
});

it('should return false if account is not a hardware keyring', () => {
Expand All @@ -281,16 +302,26 @@ describe('isHardwareAccount,', () => {
});
});
describe('getLabelTextByAddress,', () => {
beforeEach(() => {
jest.resetAllMocks();
});

it('should return accounts.qr_hardware if account is a QR keyring', () => {
expect(
getLabelTextByAddress('0xB374Ca013934e498e5baD3409147F34E6c462389'),
).toBe('accounts.qr_hardware');
expect(getLabelTextByAddress(mockQrKeyringAddress)).toBe(
'accounts.qr_hardware',
);
});

it('should return KeyringTypes.simple if address is a imported account', () => {
expect(
getLabelTextByAddress('0xd018538C87232FF95acbCe4870629b75640a78E7'),
).toBe('accounts.imported');
expect(getLabelTextByAddress(mockSimpleKeyringAddress)).toBe(
'accounts.imported',
);
});

it('returns "Snaps (beta)" if account is a Snap keyring', () => {
expect(getLabelTextByAddress(snapAddress)).toBe(
'accounts.snap_account_tag',
);
});

it('should return null if address is empty', () => {
Expand All @@ -312,19 +343,13 @@ describe('getAddressAccountType', () => {
);
});
it('should return QR if address is from a keyring type qr', () => {
expect(
getAddressAccountType('0xB374Ca013934e498e5baD3409147F34E6c462389'),
).toBe('QR');
expect(getAddressAccountType(mockQrKeyringAddress)).toBe('QR');
});
it('should return imported if address is from a keyring type simple', () => {
expect(
getAddressAccountType('0xd018538C87232FF95acbCe4870629b75640a78E7'),
).toBe('Imported');
expect(getAddressAccountType(mockSimpleKeyringAddress)).toBe('Imported');
});
it('should return MetaMask if address is not qr or simple', () => {
expect(
getAddressAccountType('0x71C7656EC7ab88b098defB751B7401B5f6d8976F'),
).toBe('MetaMask');
expect(getAddressAccountType(mockHDKeyringAddress)).toBe('MetaMask');
});
});
describe('resemblesAddress', () => {
Expand All @@ -337,8 +362,6 @@ describe('resemblesAddress', () => {
expect(resemblesAddress('address-stub-1')).toBeFalsy();
});
it('should return true if address resemble an eth address', () => {
expect(
resemblesAddress('0x71C7656EC7ab88b098defB751B7401B5f6d8976F'),
).toBeTruthy();
expect(resemblesAddress(mockHDKeyringAddress)).toBeTruthy();
});
});
11 changes: 10 additions & 1 deletion app/util/address/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ import { InternalAccount } from '@metamask/keyring-api';
import { AddressBookControllerState } from '@metamask/address-book-controller';
import { NetworkType, toChecksumHexAddress } from '@metamask/controller-utils';
import { NetworkClientId, NetworkState } from '@metamask/network-controller';
import { AccountImportStrategy } from '@metamask/keyring-controller';
import {
AccountImportStrategy,
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
KeyringTypes,
///: END:ONLY_INCLUDE_IF
} from '@metamask/keyring-controller';
import { Hex, isHexString } from '@metamask/utils';

const {
Expand Down Expand Up @@ -244,6 +249,10 @@ export function getLabelTextByAddress(address: string) {
return 'accounts.qr_hardware';
case ExtendedKeyringTypes.simple:
return 'accounts.imported';
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
case KeyringTypes.snap:
return 'accounts.snap_account_tag';
///: END:ONLY_INCLUDE_IF
}
}
return null;
Expand Down
28 changes: 28 additions & 0 deletions app/util/test/accountsControllerTestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { v4 as uuidV4 } from 'uuid';
import { EthMethod, InternalAccount } from '@metamask/keyring-api';
import { AccountsControllerState } from '@metamask/accounts-controller';
import { KeyringTypes } from '@metamask/keyring-controller';

export function createMockUuidFromAddress(address: string): string {
const fakeShaFromAddress = Array.from(
Expand Down Expand Up @@ -99,3 +100,30 @@ export function createMockAccountsControllerState(
},
};
}

export function createMockAccountsControllerStateWithSnap(
addresses: string[],
snapAccountIndex: number = 0,
): AccountsControllerState {
if (addresses.length === 0) {
throw new Error('At least one address is required');
}

if (snapAccountIndex < 0 || snapAccountIndex >= addresses.length) {
throw new Error('Invalid snapAccountIndex');
}

const state = createMockAccountsControllerState(
addresses,
addresses[snapAccountIndex],
);

const snapAccountUuid = createMockUuidFromAddress(
addresses[snapAccountIndex].toLowerCase(),
);
state.internalAccounts.accounts[snapAccountUuid].metadata.keyring = {
type: KeyringTypes.snap,
};

return state;
}
37 changes: 37 additions & 0 deletions app/util/test/keyringControllerTestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { KeyringObject, KeyringTypes } from '@metamask/keyring-controller';

export const mockSimpleKeyringAddress =
'0xd018538C87232FF95acbCe4870629b75640a78E7';
export const mockQrKeyringAddress =
'0xB374Ca013934e498e5baD3409147F34E6c462389';
export const mockHDKeyringAddress =
'0x71C7656EC7ab88b098defB751B7401B5f6d8976F';

const MOCK_DEFAULT_KEYRINGS: KeyringObject[] = [
{
accounts: [mockSimpleKeyringAddress],
type: KeyringTypes.simple,
},
{
accounts: [mockQrKeyringAddress],
type: KeyringTypes.qr,
},
{
accounts: [mockHDKeyringAddress],
type: KeyringTypes.hd,
},
];

export const MOCK_KEYRING_CONTROLLER_STATE = {
keyring: {
keyrings: [
{
mnemonic:
'one two three four five six seven eight nine ten eleven twelve',
},
],
},
state: {
keyrings: MOCK_DEFAULT_KEYRINGS,
},
};
6 changes: 3 additions & 3 deletions bitrise.yml
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,8 @@ workflows:
android_e2e_test:
before_run:
- setup
- install_detox
- prep_environment
- install_detox
after_run:
- notify_failure
steps:
Expand Down Expand Up @@ -737,8 +737,8 @@ workflows:
ios_api_specs:
before_run:
- setup
- install_detox
- prep_environment
- install_detox
after_run:
- notify_failure
steps:
Expand Down Expand Up @@ -890,8 +890,8 @@ workflows:
ios_e2e_test:
before_run:
- setup
- install_detox
- prep_environment
- install_detox
after_run:
- notify_failure
steps:
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ sonar.exclusions=**.stories.**, e2e/**, wdio/**
sonar.test.inclusions=**.test.**

# Excluded project files from coverage.
sonar.coverage.exclusions=**AccountConnectMultiSelector**, **AccountPermissionsConfirmRevokeAll**, **PermissionsSettings**, **NetworkConnectMultiSelector**, **NetworkSelectorList**, **PermissionsSummary**, **AccountConnect.tsx
sonar.coverage.exclusions=**AccountConnectMultiSelector**, **AccountPermissionsConfirmRevokeAll**, **PermissionsSettings**, **NetworkConnectMultiSelector**, **NetworkSelectorList**, **PermissionsSummary**, **AccountConnect.tsx, **util/test**

# Test coverage path in GitHub action
sonar.javascript.lcov.reportPaths=/coverage/lcov.info
Expand Down

0 comments on commit f5d01a6

Please sign in to comment.