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
4 changes: 2 additions & 2 deletions packages/snaps-controllers/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ const baseConfig = require('../../jest.config.base');
module.exports = deepmerge(baseConfig, {
coverageThreshold: {
global: {
branches: 88.85,
functions: 96.58,
branches: 88.74,
functions: 97.6,
lines: 96.74,
statements: 96.74,
},
Expand Down
225 changes: 29 additions & 196 deletions packages/snaps-controllers/src/cronjob/CronjobController.test.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,19 @@
import {
SnapCaveatType,
HandlerType,
deepClone,
TruncatedSnap,
SemVerVersion,
TruncatedSnap,
} from '@metamask/snaps-utils';
import {
MOCK_ORIGIN,
MOCK_SNAP_ID,
getTruncatedSnap,
} from '@metamask/snaps-utils/test-utils';
import { MOCK_SNAP_ID } from '@metamask/snaps-utils/test-utils';
import { Duration, inMilliseconds } from '@metamask/utils';

import { SnapEndowments } from '../snaps';
import {
getRestrictedCronjobControllerMessenger,
getRootCronjobControllerMessenger,
} from '../test-utils';
import { getCronjobPermission } from '../test-utils/cronjob';
import { CronjobController } from './CronjobController';

const MOCK_CRONJOB_PERMISSION = {
caveats: [
{
type: SnapCaveatType.SnapCronjob,
value: {
jobs: [
{
expression: {
minute: '*',
hour: '*',
dayOfMonth: '*',
month: '*',
dayOfWeek: '*',
},
request: {
method: 'exampleMethodOne',
params: ['p1'],
},
},
{
expression: '* * * * *',
request: {
method: 'exampleMethodTwo',
params: ['p1'],
},
},
],
},
},
],
date: 1664187844588,
id: 'izn0WGUO8cvq_jqvLQuQP',
invoker: MOCK_ORIGIN,
parentCapability: SnapEndowments.Cronjob,
};

const MOCK_CRONJOB_SINGLE_JOB_PERMISSION = {
caveats: [
{
type: SnapCaveatType.SnapCronjob,
value: {
jobs: [
{
expression: '59 6 * * *',
request: {
method: 'exampleMethod',
params: ['p1'],
},
},
],
},
},
],
date: 1664187844588,
id: 'izn0WGUO8cvq_jqvLQuQP',
invoker: MOCK_ORIGIN,
parentCapability: SnapEndowments.Cronjob,
};

const MOCK_VERSION = '1.0' as SemVerVersion;

describe('CronjobController', () => {
Expand All @@ -94,31 +30,20 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest
.spyOn(controllerMessenger, 'call')
.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});

cronjobController.register(MOCK_SNAP_ID);

expect(callActionMock).toHaveBeenCalledWith(
expect(rootMessenger.call).toHaveBeenCalledWith(
'PermissionController:getPermissions',
MOCK_SNAP_ID,
);

jest.advanceTimersByTime(inMilliseconds(1, Duration.Minute));

expect(callActionMock).toHaveBeenNthCalledWith(
expect(rootMessenger.call).toHaveBeenNthCalledWith(
4,
'SnapController:handleRequest',
{
Expand All @@ -140,17 +65,6 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest
.spyOn(controllerMessenger, 'call')
.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});
Expand All @@ -160,7 +74,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(1, Duration.Minute));

expect(callActionMock).not.toHaveBeenNthCalledWith(
expect(rootMessenger.call).not.toHaveBeenNthCalledWith(
4,
'SnapController:handleRequest',
{
Expand All @@ -182,18 +96,12 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest
.spyOn(controllerMessenger, 'call')
.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return {
[SnapEndowments.Cronjob]: MOCK_CRONJOB_SINGLE_JOB_PERMISSION,
} as any;
}
return false;
});
rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => {
return { [SnapEndowments.Cronjob]: getCronjobPermission() };
},
);

const cronjobController = new CronjobController({
messenger: controllerMessenger,
Expand All @@ -213,7 +121,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(24, Duration.Hour));

expect(callActionMock).toHaveBeenCalledWith(
expect(rootMessenger.call).toHaveBeenCalledWith(
'SnapController:handleRequest',
{
snapId: MOCK_SNAP_ID,
Expand All @@ -230,53 +138,35 @@ describe('CronjobController', () => {
});

it('does not schedule cronjob that is too far in the future', () => {
const cronExpression = '59 23 29 2 *'; // At 11:59pm on February 29th
const expression = '59 23 29 2 *'; // At 11:59pm on February 29th

const MOCK_TOO_FAR_CRONJOB_PERMISSION = deepClone(
MOCK_CRONJOB_SINGLE_JOB_PERMISSION,
);
MOCK_TOO_FAR_CRONJOB_PERMISSION.caveats[0].value = {
jobs: [
{
expression: cronExpression,
request: {
method: 'exampleMethod',
params: ['p1'],
},
},
],
};
const rootMessenger = getRootCronjobControllerMessenger();
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest
.spyOn(controllerMessenger, 'call')
.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return {
[SnapEndowments.Cronjob]: MOCK_TOO_FAR_CRONJOB_PERMISSION,
} as any;
}
return false;
});
rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => {
return {
[SnapEndowments.Cronjob]: getCronjobPermission({ expression }),
};
},
);

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});

cronjobController.register(MOCK_SNAP_ID);

expect(callActionMock).toHaveBeenCalledWith(
expect(rootMessenger.call).toHaveBeenCalledWith(
'PermissionController:getPermissions',
MOCK_SNAP_ID,
);

jest.runOnlyPendingTimers();

expect(callActionMock).not.toHaveBeenCalledWith(
expect(rootMessenger.call).not.toHaveBeenCalledWith(
'SnapController:handleRequest',
{
snapId: MOCK_SNAP_ID,
Expand All @@ -297,17 +187,6 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest.spyOn(controllerMessenger, 'call');

callActionMock.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});
Expand All @@ -325,7 +204,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(1, Duration.Minute));

expect(callActionMock).toHaveBeenNthCalledWith(
expect(rootMessenger.call).toHaveBeenNthCalledWith(
4,
'SnapController:handleRequest',
{
Expand All @@ -347,17 +226,6 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest.spyOn(controllerMessenger, 'call');

callActionMock.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});
Expand All @@ -378,7 +246,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(1, Duration.Minute));

expect(callActionMock).not.toHaveBeenCalledWith(
expect(rootMessenger.call).not.toHaveBeenCalledWith(
'SnapController:handleRequest',
{
snapId: MOCK_SNAP_ID,
Expand All @@ -395,34 +263,10 @@ describe('CronjobController', () => {
});

it('handles SnapUpdated event', () => {
const MOCK_ANOTHER_CRONJOB_PERMISSION = deepClone(MOCK_CRONJOB_PERMISSION);
MOCK_ANOTHER_CRONJOB_PERMISSION.caveats[0].value = {
jobs: [
{
expression: '*/15 * * * *',
request: {
method: 'exampleMethodOne',
params: ['p1'],
},
},
],
};

const rootMessenger = getRootCronjobControllerMessenger();
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest.spyOn(controllerMessenger, 'call');

callActionMock.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});
Expand All @@ -443,7 +287,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(15, Duration.Minute));

expect(callActionMock).toHaveBeenNthCalledWith(
expect(rootMessenger.call).toHaveBeenNthCalledWith(
5,
'SnapController:handleRequest',
{
Expand All @@ -465,24 +309,13 @@ describe('CronjobController', () => {
const controllerMessenger =
getRestrictedCronjobControllerMessenger(rootMessenger);

const callActionMock = jest
.spyOn(controllerMessenger, 'call')
.mockImplementation((method, ..._params: unknown[]) => {
if (method === 'SnapController:getAll') {
return [getTruncatedSnap()];
} else if (method === 'PermissionController:getPermissions') {
return { [SnapEndowments.Cronjob]: MOCK_CRONJOB_PERMISSION } as any;
}
return false;
});

const cronjobController = new CronjobController({
messenger: controllerMessenger,
});

cronjobController.register(MOCK_SNAP_ID);

expect(callActionMock).toHaveBeenCalledWith(
expect(rootMessenger.call).toHaveBeenCalledWith(
'PermissionController:getPermissions',
MOCK_SNAP_ID,
);
Expand All @@ -491,7 +324,7 @@ describe('CronjobController', () => {

jest.advanceTimersByTime(inMilliseconds(1, Duration.Minute));

expect(callActionMock).not.toHaveBeenCalledWith(
expect(rootMessenger.call).not.toHaveBeenCalledWith(
'SnapController:handleRequest',
{
snapId: MOCK_SNAP_ID,
Expand Down
Loading