mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
d3d30fd373
* fix(settings): fixed two IPFS gateway issues - adds back in two bugfixes that were originally in #19283 - fixes #16871 - fixes #18140 - achieves 100% code coverage for /ui/pages/settings/security-tab - removes the npm package `valid-url`, which has not been updated in 10 years * changes after #20172 was merged * improved URL validation (specifically spaces) * better Jest coverage * response to legobeat review * fixing lint and Jest
349 lines
11 KiB
JavaScript
349 lines
11 KiB
JavaScript
import {
|
|
ENVIRONMENT_TYPE_BACKGROUND,
|
|
ENVIRONMENT_TYPE_FULLSCREEN,
|
|
ENVIRONMENT_TYPE_NOTIFICATION,
|
|
ENVIRONMENT_TYPE_POPUP,
|
|
PLATFORM_CHROME,
|
|
PLATFORM_EDGE,
|
|
PLATFORM_FIREFOX,
|
|
PLATFORM_OPERA,
|
|
} from '../../../shared/constants/app';
|
|
import {
|
|
TransactionEnvelopeType,
|
|
TransactionStatus,
|
|
TransactionType,
|
|
} from '../../../shared/constants/transaction';
|
|
import { isPrefixedFormattedHexString } from '../../../shared/modules/network.utils';
|
|
import {
|
|
addUrlProtocolPrefix,
|
|
deferredPromise,
|
|
formatTxMetaForRpcResult,
|
|
getEnvironmentType,
|
|
getPlatform,
|
|
getValidUrl,
|
|
isWebUrl,
|
|
} from './util';
|
|
|
|
describe('app utils', () => {
|
|
describe('getEnvironmentType', () => {
|
|
it('should return popup type', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/popup.html',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_POPUP);
|
|
});
|
|
|
|
it('should return notification type', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/notification.html',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_NOTIFICATION);
|
|
});
|
|
|
|
it('should return fullscreen type for home.html', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/home.html',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_FULLSCREEN);
|
|
});
|
|
|
|
it('should return background type', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/_generated_background_page.html',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_BACKGROUND);
|
|
});
|
|
|
|
it('should return the correct type for a URL with a hash fragment', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/popup.html#hash',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_POPUP);
|
|
});
|
|
|
|
it('should return the correct type for a URL with query parameters', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/popup.html?param=foo',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_POPUP);
|
|
});
|
|
|
|
it('should return the correct type for a URL with query parameters and a hash fragment', () => {
|
|
const environmentType = getEnvironmentType(
|
|
'http://extension-id/popup.html?param=foo#hash',
|
|
);
|
|
expect(environmentType).toStrictEqual(ENVIRONMENT_TYPE_POPUP);
|
|
});
|
|
});
|
|
|
|
describe('URL utils', () => {
|
|
it('should test addUrlProtocolPrefix', () => {
|
|
expect(addUrlProtocolPrefix('http://example.com')).toStrictEqual(
|
|
'http://example.com',
|
|
);
|
|
expect(addUrlProtocolPrefix('https://example.com')).toStrictEqual(
|
|
'https://example.com',
|
|
);
|
|
expect(addUrlProtocolPrefix('example.com')).toStrictEqual(
|
|
'https://example.com',
|
|
);
|
|
expect(addUrlProtocolPrefix('exa mple.com')).toStrictEqual(null);
|
|
});
|
|
|
|
it('should test isWebUrl', () => {
|
|
expect(isWebUrl('http://example.com')).toStrictEqual(true);
|
|
expect(isWebUrl('https://example.com')).toStrictEqual(true);
|
|
expect(isWebUrl('https://exa mple.com')).toStrictEqual(false);
|
|
expect(isWebUrl('')).toStrictEqual(false);
|
|
});
|
|
|
|
it('should test getValidUrl', () => {
|
|
expect(getValidUrl('http://example.com').toString()).toStrictEqual(
|
|
'http://example.com/',
|
|
);
|
|
expect(getValidUrl('https://example.com').toString()).toStrictEqual(
|
|
'https://example.com/',
|
|
);
|
|
expect(getValidUrl('https://exa%20mple.com')).toStrictEqual(null);
|
|
expect(getValidUrl('')).toStrictEqual(null);
|
|
});
|
|
});
|
|
|
|
describe('isPrefixedFormattedHexString', () => {
|
|
it('should return true for valid hex strings', () => {
|
|
expect(isPrefixedFormattedHexString('0x1')).toStrictEqual(true);
|
|
|
|
expect(isPrefixedFormattedHexString('0xa')).toStrictEqual(true);
|
|
|
|
expect(
|
|
isPrefixedFormattedHexString('0xabcd1123fae909aad87452'),
|
|
).toStrictEqual(true);
|
|
});
|
|
|
|
it('should return false for invalid hex strings', () => {
|
|
expect(isPrefixedFormattedHexString('0x')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString('0x0')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString('0x01')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString(' 0x1')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString('0x1 ')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString('0x1afz')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString('z')).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString(2)).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString(['0x1'])).toStrictEqual(false);
|
|
|
|
expect(isPrefixedFormattedHexString()).toStrictEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('getPlatform', () => {
|
|
let userAgent, setBrowserSpecificWindow;
|
|
|
|
beforeEach(() => {
|
|
userAgent = jest.spyOn(window.navigator, 'userAgent', 'get');
|
|
|
|
setBrowserSpecificWindow = (browser) => {
|
|
switch (browser) {
|
|
case 'firefox': {
|
|
userAgent.mockReturnValue(
|
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0',
|
|
);
|
|
break;
|
|
}
|
|
case 'edge': {
|
|
userAgent.mockReturnValue(
|
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30',
|
|
);
|
|
break;
|
|
}
|
|
case 'opera': {
|
|
userAgent.mockReturnValue(
|
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 OPR/80.0.4170.63',
|
|
);
|
|
|
|
break;
|
|
}
|
|
default: {
|
|
userAgent.mockReturnValue(
|
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
});
|
|
|
|
it('should detect Firefox', () => {
|
|
setBrowserSpecificWindow('firefox');
|
|
expect(getPlatform()).toStrictEqual(PLATFORM_FIREFOX);
|
|
});
|
|
|
|
it('should detect Edge', () => {
|
|
setBrowserSpecificWindow('edge');
|
|
expect(getPlatform()).toStrictEqual(PLATFORM_EDGE);
|
|
});
|
|
|
|
it('should detect Opera', () => {
|
|
setBrowserSpecificWindow('opera');
|
|
expect(getPlatform()).toStrictEqual(PLATFORM_OPERA);
|
|
});
|
|
|
|
it('should detect Chrome', () => {
|
|
setBrowserSpecificWindow('chrome');
|
|
expect(getPlatform()).toStrictEqual(PLATFORM_CHROME);
|
|
});
|
|
});
|
|
|
|
describe('deferredPromise', () => {
|
|
it('should allow rejecting a deferred Promise', async () => {
|
|
const { promise, reject } = deferredPromise();
|
|
|
|
reject(new Error('test'));
|
|
|
|
await expect(promise).rejects.toThrow('test');
|
|
});
|
|
|
|
it('should allow resolving a deferred Promise', async () => {
|
|
const { promise, resolve } = deferredPromise();
|
|
|
|
resolve('test');
|
|
|
|
await expect(promise).resolves.toBe('test');
|
|
});
|
|
|
|
it('should still be rejected after reject is called twice', async () => {
|
|
const { promise, reject } = deferredPromise();
|
|
|
|
reject(new Error('test'));
|
|
reject(new Error('different message'));
|
|
|
|
await expect(promise).rejects.toThrow('test');
|
|
});
|
|
|
|
it('should still be rejected after resolve is called post-rejection', async () => {
|
|
const { promise, resolve, reject } = deferredPromise();
|
|
|
|
reject(new Error('test'));
|
|
resolve('different message');
|
|
|
|
await expect(promise).rejects.toThrow('test');
|
|
});
|
|
|
|
it('should still be resolved after resolve is called twice', async () => {
|
|
const { promise, resolve } = deferredPromise();
|
|
|
|
resolve('test');
|
|
resolve('different message');
|
|
|
|
await expect(promise).resolves.toBe('test');
|
|
});
|
|
|
|
it('should still be resolved after reject is called post-resolution', async () => {
|
|
const { promise, resolve, reject } = deferredPromise();
|
|
|
|
resolve('test');
|
|
reject(new Error('different message'));
|
|
|
|
await expect(promise).resolves.toBe('test');
|
|
});
|
|
});
|
|
|
|
describe('formatTxMetaForRpcResult', () => {
|
|
it('should correctly format the tx meta object (EIP-1559)', () => {
|
|
const txMeta = {
|
|
id: 1,
|
|
status: TransactionStatus.unapproved,
|
|
txParams: {
|
|
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
|
|
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
|
maxFeePerGas: '0x77359400',
|
|
maxPriorityFeePerGas: '0x77359400',
|
|
gas: '0x7b0d',
|
|
nonce: '0x4b',
|
|
},
|
|
type: TransactionType.simpleSend,
|
|
origin: 'other',
|
|
chainId: '0x5',
|
|
time: 1624408066355,
|
|
metamaskNetworkId: '5',
|
|
hash: '0x4bcb6cd6b182209585f8ad140260ddb35c81a575dd40f508d9767e652a9f60e7',
|
|
r: '0x4c3111e42ed5eec3dcecba1e234700f387e8693c373c61c3e54a762a26f1570e',
|
|
s: '0x18bfc4eeb7ebcfacc3bd59ea100a6834ea3265e65945dbec69aa2a06564fafff',
|
|
v: '0x29',
|
|
};
|
|
const expectedResult = {
|
|
accessList: null,
|
|
blockHash: null,
|
|
blockNumber: null,
|
|
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
|
|
gas: '0x7b0d',
|
|
gasPrice: '0x77359400',
|
|
hash: '0x4bcb6cd6b182209585f8ad140260ddb35c81a575dd40f508d9767e652a9f60e7',
|
|
input: '0x',
|
|
maxFeePerGas: '0x77359400',
|
|
maxPriorityFeePerGas: '0x77359400',
|
|
nonce: '0x4b',
|
|
r: '0x4c3111e42ed5eec3dcecba1e234700f387e8693c373c61c3e54a762a26f1570e',
|
|
s: '0x18bfc4eeb7ebcfacc3bd59ea100a6834ea3265e65945dbec69aa2a06564fafff',
|
|
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
|
transactionIndex: null,
|
|
type: '0x2',
|
|
v: '0x29',
|
|
value: '0x0',
|
|
};
|
|
const result = formatTxMetaForRpcResult(txMeta);
|
|
expect(result).toStrictEqual(expectedResult);
|
|
});
|
|
|
|
it('should correctly format the tx meta object (non EIP-1559)', () => {
|
|
const txMeta = {
|
|
id: 1,
|
|
status: TransactionStatus.unapproved,
|
|
txParams: {
|
|
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
|
|
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
|
gasPrice: '0x77359400',
|
|
gas: '0x7b0d',
|
|
nonce: '0x4b',
|
|
},
|
|
type: TransactionType.simpleSend,
|
|
origin: 'other',
|
|
chainId: '0x5',
|
|
time: 1624408066355,
|
|
metamaskNetworkId: '5',
|
|
hash: '0x4bcb6cd6b182209585f8ad140260ddb35c81a575dd40f508d9767e652a9f60e7',
|
|
r: '0x4c3111e42ed5eec3dcecba1e234700f387e8693c373c61c3e54a762a26f1570e',
|
|
s: '0x18bfc4eeb7ebcfacc3bd59ea100a6834ea3265e65945dbec69aa2a06564fafff',
|
|
v: '0x29',
|
|
};
|
|
const expectedResult = {
|
|
accessList: null,
|
|
blockHash: null,
|
|
blockNumber: null,
|
|
from: '0xc684832530fcbddae4b4230a47e991ddcec2831d',
|
|
gas: '0x7b0d',
|
|
hash: '0x4bcb6cd6b182209585f8ad140260ddb35c81a575dd40f508d9767e652a9f60e7',
|
|
input: '0x',
|
|
gasPrice: '0x77359400',
|
|
nonce: '0x4b',
|
|
r: '0x4c3111e42ed5eec3dcecba1e234700f387e8693c373c61c3e54a762a26f1570e',
|
|
s: '0x18bfc4eeb7ebcfacc3bd59ea100a6834ea3265e65945dbec69aa2a06564fafff',
|
|
to: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
|
transactionIndex: null,
|
|
type: TransactionEnvelopeType.legacy,
|
|
v: '0x29',
|
|
value: '0x0',
|
|
};
|
|
const result = formatTxMetaForRpcResult(txMeta);
|
|
expect(result).toStrictEqual(expectedResult);
|
|
});
|
|
});
|
|
});
|