Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/transaction-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"nock": "^13.3.1",
"sinon": "^9.2.4",
"ts-jest": "^29.2.5",
"typedoc": "^0.25.13",
"typedoc-plugin-missing-exports": "^2.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import type {
} from '@metamask/network-controller';
import type { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller';
import assert from 'assert';
import type { SinonFakeTimers } from 'sinon';
import { useFakeTimers } from 'sinon';
import { v4 as uuidV4 } from 'uuid';

import type {
Expand All @@ -44,7 +42,7 @@ import type {
import { TransactionController } from './TransactionController';
import type { InternalAccount } from './types';
import { TransactionStatus, TransactionType } from './types';
import { advanceTime } from '../../../tests/helpers';
import { jestAdvanceTime } from '../../../tests/helpers';
import { mockNetwork } from '../../../tests/mock-network';
import {
buildAddNetworkFields,
Expand Down Expand Up @@ -336,11 +334,10 @@ const setupController = async (
};

describe('TransactionController Integration', () => {
let clock: SinonFakeTimers;
let uuidCounter = 0;

beforeEach(() => {
clock = useFakeTimers();
jest.useFakeTimers({ doNotFake: ['nextTick', 'queueMicrotask'] });

uuidV4Mock.mockImplementation(() => {
const uuid = `UUID-${uuidCounter}`;
Expand All @@ -350,7 +347,7 @@ describe('TransactionController Integration', () => {
});

afterEach(() => {
clock.restore();
jest.useRealTimers();
});

describe('constructor', () => {
Expand Down Expand Up @@ -462,8 +459,8 @@ describe('TransactionController Integration', () => {
},
});

await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

expect(transactionController.state.transactions).toMatchObject([
expect.objectContaining({
Expand Down Expand Up @@ -539,7 +536,7 @@ describe('TransactionController Integration', () => {
);

await approvalController.accept(transactionMeta.id);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await result;

Expand Down Expand Up @@ -584,13 +581,13 @@ describe('TransactionController Integration', () => {
);

await approvalController.accept(transactionMeta.id);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await result;
// blocktracker polling is 20s
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

expect(transactionController.state.transactions).toHaveLength(1);
expect(transactionController.state.transactions[0].status).toBe(
Expand Down Expand Up @@ -663,15 +660,15 @@ describe('TransactionController Integration', () => {
approvalController.accept(firstTransaction.transactionMeta.id),
approvalController.accept(secondTransaction.transactionMeta.id),
]);
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

await Promise.all([firstTransaction.result, secondTransaction.result]);

// blocktracker polling is 20s
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

expect(transactionController.state.transactions).toHaveLength(2);
expect(transactionController.state.transactions[0].status).toBe(
Expand Down Expand Up @@ -729,7 +726,7 @@ describe('TransactionController Integration', () => {
);

await approvalController.accept(transactionMeta.id);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await result;

Expand Down Expand Up @@ -794,19 +791,19 @@ describe('TransactionController Integration', () => {
);

await approvalController.accept(transactionMeta.id);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await result;

await transactionController.stopTransaction(transactionMeta.id);

// blocktracker polling is 20s
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

expect(transactionController.state.transactions).toHaveLength(2);
expect(transactionController.state.transactions[0].status).toBe(
Expand Down Expand Up @@ -871,19 +868,19 @@ describe('TransactionController Integration', () => {
);

await approvalController.accept(transactionMeta.id);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await result;

await transactionController.speedUpTransaction(transactionMeta.id);

// blocktracker polling is 20s
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: BLOCK_TRACKER_POLLING_INTERVAL });
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: BLOCK_TRACKER_POLLING_INTERVAL });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

expect(transactionController.state.transactions).toHaveLength(2);
expect(transactionController.state.transactions[0].status).toBe(
Expand Down Expand Up @@ -1016,8 +1013,8 @@ describe('TransactionController Integration', () => {
approvalController.accept(addTx1.transactionMeta.id),
approvalController.accept(addTx2.transactionMeta.id),
]);
await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

await Promise.all([addTx1.result, addTx2.result]);

Expand Down Expand Up @@ -1075,7 +1072,7 @@ describe('TransactionController Integration', () => {
{ networkClientId: 'sepolia' },
);

await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const addTx2 = await transactionController.addTransaction(
{
Expand All @@ -1087,15 +1084,15 @@ describe('TransactionController Integration', () => {
},
);

await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

await Promise.all([
approvalController.accept(addTx1.transactionMeta.id),
approvalController.accept(addTx2.transactionMeta.id),
]);

await advanceTime({ clock, duration: 1 });
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });
await jestAdvanceTime({ duration: 1 });

await Promise.all([addTx1.result, addTx2.result]);

Expand Down Expand Up @@ -1271,7 +1268,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
networkClientId,
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const nonceLock = await nonceLockPromise;

Expand Down Expand Up @@ -1306,7 +1303,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
networkClientId,
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const firstNonceLock = await firstNonceLockPromise;

Expand All @@ -1320,7 +1317,7 @@ describe('TransactionController Integration', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
new Promise<null>(async (resolve) => {
await advanceTime({ clock, duration: 100 });
await jestAdvanceTime({ duration: 100 });
resolve(null);
});

Expand All @@ -1333,7 +1330,7 @@ describe('TransactionController Integration', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/await-thenable
await firstNonceLock.releaseLock();
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

secondNonceLockIfAcquired = await Promise.race([
secondNonceLockPromise,
Expand Down Expand Up @@ -1399,7 +1396,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
'sepolia',
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const firstNonceLock = await firstNonceLockPromise;

Expand All @@ -1413,7 +1410,7 @@ describe('TransactionController Integration', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
new Promise<null>(async (resolve) => {
await advanceTime({ clock, duration: 100 });
await jestAdvanceTime({ duration: 100 });
resolve(null);
});

Expand All @@ -1426,7 +1423,7 @@ describe('TransactionController Integration', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/await-thenable
await firstNonceLock.releaseLock();
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

secondNonceLockIfAcquired = await Promise.race([
secondNonceLockPromise,
Expand Down Expand Up @@ -1464,7 +1461,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
'linea-sepolia',
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const firstNonceLock = await firstNonceLockPromise;

Expand All @@ -1474,7 +1471,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
'sepolia',
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const secondNonceLock = await secondNonceLockPromise;

Expand Down Expand Up @@ -1513,7 +1510,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_MOCK,
networkClientId,
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const firstNonceLock = await firstNonceLockPromise;

Expand All @@ -1523,7 +1520,7 @@ describe('TransactionController Integration', () => {
ACCOUNT_2_MOCK,
networkClientId,
);
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

const secondNonceLock = await secondNonceLockPromise;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import type {
} from '@metamask/network-controller';
import type { NonceTracker } from '@metamask/nonce-tracker';
import type { Hex } from '@metamask/utils';
import { useFakeTimers } from 'sinon';

import {
MultichainTrackingHelper,
MultichainTrackingHelperOptions,
} from './MultichainTrackingHelper';
import type { PendingTransactionTracker } from './PendingTransactionTracker';
import { advanceTime } from '../../../../tests/helpers';
import { jestAdvanceTime } from '../../../../tests/helpers';

jest.mock(
'@metamask/eth-query',
Expand Down Expand Up @@ -473,7 +472,7 @@ describe('MultichainTrackingHelper', () => {
});

it('should block on attempts to get the lock for the same chainId and key combination', async () => {
const clock = useFakeTimers();
jest.useFakeTimers({ doNotFake: ['nextTick', 'queueMicrotask'] });
const { helper } = newMultichainTrackingHelper();

const firstReleaseLockPromise = helper.acquireNonceLockForChainIdKey({
Expand All @@ -492,7 +491,7 @@ describe('MultichainTrackingHelper', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
new Promise<null>(async (resolve) => {
await advanceTime({ clock, duration: 100 });
await jestAdvanceTime({ duration: 100 });
resolve(null);
});

Expand All @@ -505,7 +504,7 @@ describe('MultichainTrackingHelper', () => {
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
// eslint-disable-next-line @typescript-eslint/await-thenable
await firstReleaseLock();
await advanceTime({ clock, duration: 1 });
await jestAdvanceTime({ duration: 1 });

secondReleaseLockIfAcquired = await Promise.race([
secondReleaseLockPromise,
Expand All @@ -514,7 +513,7 @@ describe('MultichainTrackingHelper', () => {

expect(secondReleaseLockIfAcquired).toStrictEqual(expect.any(Function));

clock.restore();
jest.useRealTimers();
});
});

Expand Down
21 changes: 21 additions & 0 deletions tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,27 @@ export async function advanceTime({
} while (value > 0);
}

/**
* Like {@link advanceTime}, but uses Jest fake timers instead of Sinon.
*
* @param options - The options object.
* @param options.duration - The total amount of time (in milliseconds) to advance the timer by.
* @param options.stepSize - The incremental step size (in milliseconds) by which the timer is advanced in each iteration. Default is 1/4 of the duration.
*/
export async function jestAdvanceTime({
duration,
stepSize = duration / 4,
}: {
duration: number;
stepSize?: number;
}): Promise<void> {
let value = duration;
do {
await jest.advanceTimersByTimeAsync(stepSize);
value -= stepSize;
} while (value > 0);
}

/**
* Resolve all pending promises.
*
Expand Down
1 change: 0 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5037,7 +5037,6 @@ __metadata:
jest-environment-jsdom: "npm:^29.7.0"
lodash: "npm:^4.17.21"
nock: "npm:^13.3.1"
sinon: "npm:^9.2.4"
ts-jest: "npm:^29.2.5"
typedoc: "npm:^0.25.13"
typedoc-plugin-missing-exports: "npm:^2.0.0"
Expand Down