Skip to content

Commit

Permalink
Add onInstall and onUpdate to snaps-jest
Browse files Browse the repository at this point in the history
  • Loading branch information
david0xd committed Oct 18, 2024
1 parent 5d91160 commit f3fe260
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,6 @@ This will make it easier for developers to understand the examples, and to use
them as a starting point for their own snaps.

Each snap (if applicable) should have end-to-end tests that test the snap's
functionality. The tests should be located in the `src/index.test.ts` file, and
functionality. The tests should be located in the `src/index.test.tsx` file, and
make use of `@metamask/snaps-jest` to test the snap. You can have a look at the
existing E2E tests for inspiration.
2 changes: 1 addition & 1 deletion packages/examples/packages/lifecycle-hooks/snap.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { SnapConfig } from '@metamask/snaps-cli';

const config: SnapConfig = {
input: './src/index.ts',
input: './src/index.tsx',
server: {
port: 8022,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "TSu0FIqVXvJG6WzqtKPx5kN2fjveQ8EypKCk/jAShmM=",
"shasum": "NxdsbiJFepF/GbIIDoWSADDlHgbhhesJLtcsH35Vp1s=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
13 changes: 0 additions & 13 deletions packages/examples/packages/lifecycle-hooks/src/index.test.ts

This file was deleted.

41 changes: 41 additions & 0 deletions packages/examples/packages/lifecycle-hooks/src/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { describe, it } from '@jest/globals';
import { installSnap } from '@metamask/snaps-jest';
import { Box, Text } from '@metamask/snaps-sdk/jsx';

describe('onInstall', () => {
it('shows dialog when the snap is installed', async () => {
const { onInstall } = await installSnap();

const response = await onInstall();

const screen = response.getInterface();

expect(screen).toRender(
<Box>
<Text>
The Snap was installed successfully, and the "onInstall" handler was
called.
</Text>
</Box>,
);
});
});

describe('onUpdate', () => {
it('shows dialog when the snap is updated', async () => {
const { onUpdate } = await installSnap();

const response = await onUpdate();

const screen = response.getInterface();

expect(screen).toRender(
<Box>
<Text>
The Snap was updated successfully, and the "onUpdate" handler was
called.
</Text>
</Box>,
);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { OnInstallHandler, OnUpdateHandler } from '@metamask/snaps-sdk';
import { heading, panel, text } from '@metamask/snaps-sdk';
import { Box, Text } from '@metamask/snaps-sdk/jsx';

/**
* Handle installation of the snap. This handler is called when the snap is
Expand All @@ -15,12 +15,14 @@ export const onInstall: OnInstallHandler = async () => {
method: 'snap_dialog',
params: {
type: 'alert',
content: panel([
heading('Installation successful'),
text(
'The snap was installed successfully, and the "onInstall" handler was called.',
),
]),
content: (
<Box>
<Text>
The Snap was installed successfully, and the "onInstall" handler was
called.
</Text>
</Box>
),
},
});
};
Expand All @@ -39,12 +41,14 @@ export const onUpdate: OnUpdateHandler = async () => {
method: 'snap_dialog',
params: {
type: 'alert',
content: panel([
heading('Update successful'),
text(
'The snap was updated successfully, and the "onUpdate" handler was called.',
),
]),
content: (
<Box>
<Text>
The Snap was updated successfully, and the "onUpdate" handler was
called.
</Text>
</Box>
),
},
});
};
52 changes: 52 additions & 0 deletions packages/snaps-jest/src/helpers.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,58 @@ describe('installSnap', () => {
});
});

describe('onInstall', () => {
it('sends onInstall request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onInstall = async () => {
return { content: { type: 'text', value: 'Hello, world!' } };
};
`,
});

const { onInstall, close } = await installSnap(snapId);
const response = await onInstall();

expect(response).toStrictEqual(
expect.objectContaining({
getInterface: expect.any(Function),
}),
);

await close();
await closeServer();
});
});

describe('onUpdate', () => {
it('sends onUpdate request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onUpdate = async () => {
return { content: { type: 'text', value: 'Hello, world!' } };
};
`,
});

const { onUpdate, close } = await installSnap(snapId);
const response = await onUpdate();

expect(response).toStrictEqual(
expect.objectContaining({
getInterface: expect.any(Function),
}),
);

await close();
await closeServer();
});
});

describe('mockJsonRpc', () => {
it('mocks a JSON-RPC method', async () => {
jest.spyOn(console, 'log').mockImplementation();
Expand Down
4 changes: 4 additions & 0 deletions packages/snaps-jest/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ export async function installSnap<
runCronjob,
onHomePage,
onKeyringRequest,
onInstall,
onUpdate,
mockJsonRpc,
close,
} = await getEnvironment().installSnap(...resolvedOptions);
Expand All @@ -192,6 +194,8 @@ export async function installSnap<
runCronjob,
onHomePage,
onKeyringRequest,
onInstall,
onUpdate,
mockJsonRpc,
close: async () => {
log('Closing execution service.');
Expand Down
52 changes: 52 additions & 0 deletions packages/snaps-simulation/src/helpers.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,58 @@ describe('helpers', () => {
});
});

describe('onInstall', () => {
it('sends a OnInstall request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onInstall = async () => {
return { content: { type: 'text', value: 'Hello, world!' } };
};
`,
});

const { onInstall, close } = await installSnap(snapId);
const response = await onInstall();

expect(response).toStrictEqual(
expect.objectContaining({
getInterface: expect.any(Function),
}),
);

await close();
await closeServer();
});
});

describe('onUpdate', () => {
it('sends a OnUpdate request and returns the result', async () => {
jest.spyOn(console, 'log').mockImplementation();

const { snapId, close: closeServer } = await getMockServer({
sourceCode: `
module.exports.onUpdate = async () => {
return { content: { type: 'text', value: 'Hello, world!' } };
};
`,
});

const { onUpdate, close } = await installSnap(snapId);
const response = await onUpdate();

expect(response).toStrictEqual(
expect.objectContaining({
getInterface: expect.any(Function),
}),
);

await close();
await closeServer();
});
});

describe('mockJsonRpc', () => {
it('mocks a JSON-RPC method', async () => {
jest.spyOn(console, 'log').mockImplementation();
Expand Down
54 changes: 54 additions & 0 deletions packages/snaps-simulation/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ export type SnapHelpers = {
keyringRequest: KeyringOptions,
): Promise<SnapResponseWithoutInterface>;

/**
* Get the response from the Snap's `onInstall` handler.
*
* @returns The response.
*/
onInstall(): Promise<SnapResponseWithInterface>;

/**
* Get the response from the Snap's `onUpdate` handler.
*
* @returns The response.
*/
onUpdate(): Promise<SnapResponseWithInterface>;

/**
* Mock a JSON-RPC request. This will cause the snap to respond with the
* specified response when a request with the specified method is sent.
Expand Down Expand Up @@ -266,6 +280,46 @@ export function getHelpers({

onKeyringRequest,

onInstall: async (): Promise<SnapResponseWithInterface> => {
log('Running onInstall handler.');

const response = await handleRequest({
snapId,
store,
executionService,
controllerMessenger,
runSaga,
handler: HandlerType.OnInstall,
request: {
method: '',
},
});

assertIsResponseWithInterface(response);

return response;
},

onUpdate: async (): Promise<SnapResponseWithInterface> => {
log('Running onUpdate handler.');

const response = await handleRequest({
snapId,
store,
executionService,
controllerMessenger,
runSaga,
handler: HandlerType.OnUpdate,
request: {
method: '',
},
});

assertIsResponseWithInterface(response);

return response;
},

onSignature: async (
request: unknown,
): Promise<SnapResponseWithInterface> => {
Expand Down
14 changes: 14 additions & 0 deletions packages/snaps-simulation/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,20 @@ export type Snap = {
keyringRequest: KeyringOptions,
): Promise<SnapResponseWithoutInterface>;

/**
* Get the response from the Snap's `onInstall` handler.
*
* @returns The response.
*/
onInstall(): Promise<SnapResponseWithInterface>;

/**
* Get the response from the Snap's `onUpdate` handler.
*
* @returns The response.
*/
onUpdate(): Promise<SnapResponseWithInterface>;

/**
* Mock a JSON-RPC request. This will cause the snap to respond with the
* specified response when a request with the specified method is sent.
Expand Down

0 comments on commit f3fe260

Please sign in to comment.