Skip to content

Commit

Permalink
Add support for custom dialogs in snaps-jest (#2526)
Browse files Browse the repository at this point in the history
This PR adds the support for the new `default` type dialog.

- Add a new dialog to the dialog test snap.
- Add logic to handle custom dialogs.
- Add assertion utils
  • Loading branch information
GuillaumeRx authored Jul 1, 2024
1 parent 7a4cb03 commit 882232c
Show file tree
Hide file tree
Showing 55 changed files with 715 additions and 97 deletions.
2 changes: 1 addition & 1 deletion packages/examples/packages/bip32/snap.manifest.json
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": "Ard/F/8RqOYcKlxb3xx6OB5XLtmv7t/Asrn8bhkCooQ=",
"shasum": "te1oZPWHfniZ/ST6D/blxr8w6yhoR4qaJeeNoOP7O6A=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
8 changes: 5 additions & 3 deletions packages/examples/packages/bip32/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { expect } from '@jest/globals';
import { installSnap } from '@metamask/snaps-jest';
import { assertIsConfirmationDialog, installSnap } from '@metamask/snaps-jest';
import { copyable, heading, panel, text } from '@metamask/snaps-sdk';
import { assert } from '@metamask/utils';

describe('onRpcRequest', () => {
it('throws an error if the requested method does not exist', async () => {
Expand Down Expand Up @@ -109,6 +108,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assertIsConfirmationDialog(ui);
expect(ui).toRender(
panel([
heading('Signature request'),
Expand Down Expand Up @@ -141,6 +141,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assertIsConfirmationDialog(ui);
expect(ui).toRender(
panel([
heading('Signature request'),
Expand Down Expand Up @@ -173,6 +174,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assertIsConfirmationDialog(ui);
expect(ui).toRender(
panel([
heading('Signature request'),
Expand Down Expand Up @@ -205,7 +207,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'confirmation');
assertIsConfirmationDialog(ui);
await ui.cancel();

expect(await response).toRespondWithError({
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/bip44/snap.manifest.json
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": "jJuoqF4p++cEfWb3YdEfuwlOEw7bByfpEMh6adH8sOI=",
"shasum": "yzw5UM4aWmD8vLglR9gazcNC0yKntyPp5A5sPSmouL4=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
10 changes: 7 additions & 3 deletions packages/examples/packages/bip44/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { expect } from '@jest/globals';
import { installSnap } from '@metamask/snaps-jest';
import { assertIsConfirmationDialog, installSnap } from '@metamask/snaps-jest';
import { copyable, heading, panel, text } from '@metamask/snaps-sdk';
import { assert } from '@metamask/utils';

describe('onRpcRequest', () => {
it('throws an error if the requested method does not exist', async () => {
Expand Down Expand Up @@ -84,6 +83,8 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assertIsConfirmationDialog(ui);

expect(ui).toRender(
panel([
heading('Signature request'),
Expand Down Expand Up @@ -114,6 +115,8 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assertIsConfirmationDialog(ui);

expect(ui).toRender(
panel([
heading('Signature request'),
Expand Down Expand Up @@ -144,7 +147,8 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'confirmation');
assertIsConfirmationDialog(ui);

await ui.cancel();

expect(await response).toRespondWithError({
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": "nBoIUO4s8aakybthHavEuRjxCoNVzevKVv1mr1u2uNM=",
"shasum": "a+jOIwfxC3ITF6MbF5ltQvM0ZvCJ5/NQJlbEsqWTQrk=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/browserify/snap.manifest.json
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": "Kq4I9q6BdkSUrUsjysqqsfjlQ1gu6vM4sXSo7pgNruI=",
"shasum": "HPCtZ7reZrbut7cl09SnaoAHkzrvlvjc60leUfkcsVI=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
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": "RNHnGSZaZRAEkH7h4eqFfmic8Ixq30CXj4JWnhWkQbI=",
"shasum": "7BLeIk79FlkIK9fNKHcCdX8UChmjU7kOkGVLxOc29Kw=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/cronjobs/snap.manifest.json
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": "0YLZlM7w5GpjDWYmmJFxiYB2kJnNG55ru3/8ywKVT9I=",
"shasum": "DMmgoUR+Q1/eYJTjZQ96jI406CpgObFs454UR1nKGM4=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
1 change: 0 additions & 1 deletion packages/examples/packages/dialogs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"@metamask/eslint-config-typescript": "^12.1.0",
"@metamask/snaps-cli": "workspace:^",
"@metamask/snaps-jest": "workspace:^",
"@metamask/utils": "^8.3.0",
"@swc/core": "1.3.78",
"@swc/jest": "^0.2.26",
"@typescript-eslint/eslint-plugin": "^5.42.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/dialogs/snap.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { SnapConfig } from '@metamask/snaps-cli';
import { resolve } from 'path';

const config: SnapConfig = {
input: resolve(__dirname, 'src/index.ts'),
input: resolve(__dirname, 'src/index.tsx'),
server: {
port: 8005,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/packages/dialogs/snap.manifest.json
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": "5cc1fSlz4S5sDjlkjWhBUNjOQu6VdCqS5ln/DJjssSk=",
"shasum": "F5K30FZGcmERlgvw8D8v4Vuqh2FP2fxSeq0KVOT4LYg=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
32 changes: 32 additions & 0 deletions packages/examples/packages/dialogs/src/components/custom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
Box,
Button,
Container,
Footer,
Heading,
Input,
Text,
type SnapComponent,
} from '@metamask/snaps-sdk/jsx';

/**
* A custom dialog component.
*
* @returns The custom dialog component.
*/
export const CustomDialog: SnapComponent = () => (
<Container>
<Box>
<Heading>Custom Dialog</Heading>
<Text>
This is a custom dialog. It has a custom Footer and can be resolved to
any value.
</Text>
<Input name="custom-input" placeholder="Enter something..." />
</Box>
<Footer>
<Button name="cancel">Cancel</Button>
<Button name="confirm">Confirm</Button>
</Footer>
</Container>
);
1 change: 1 addition & 0 deletions packages/examples/packages/dialogs/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './custom';
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { expect } from '@jest/globals';
import { installSnap } from '@metamask/snaps-jest';
import {
assertIsAlertDialog,
assertIsConfirmationDialog,
assertIsCustomDialog,
assertIsPromptDialog,
installSnap,
} from '@metamask/snaps-jest';
import { heading, panel, text } from '@metamask/snaps-sdk';
import { assert } from '@metamask/utils';

import { CustomDialog } from './components';

describe('onRpcRequest', () => {
it('throws an error if the requested method does not exist', async () => {
Expand Down Expand Up @@ -31,7 +38,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'alert');
assertIsAlertDialog(ui);

expect(ui).toRender(
panel([
Expand All @@ -55,7 +62,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'confirmation');
assertIsConfirmationDialog(ui);

expect(ui).toRender(
panel([
Expand All @@ -79,7 +86,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'confirmation');
assertIsConfirmationDialog(ui);
await ui.cancel();

expect(await response).toRespondWith(false);
Expand All @@ -95,7 +102,7 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'prompt');
assertIsPromptDialog(ui);

expect(ui).toRender(
panel([
Expand All @@ -119,10 +126,34 @@ describe('onRpcRequest', () => {
});

const ui = await response.getInterface();
assert(ui.type === 'prompt');
assertIsPromptDialog(ui);

await ui.cancel();

expect(await response).toRespondWith(null);
});
});

describe('showCustom', () => {
it('shows a custom dialog and can return the input value', async () => {
const value = 'Hello, world!';

const { request } = await installSnap();

const response = request({
method: 'showCustom',
});

const ui = await response.getInterface();
assertIsCustomDialog(ui);

expect(ui).toRender(<CustomDialog />);

await ui.typeInField('custom-input', value);

await ui.clickElement('confirm');

expect(await response).toRespondWith(value);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import type { OnRpcRequestHandler } from '@metamask/snaps-sdk';
import type {
OnRpcRequestHandler,
OnUserInputHandler,
} from '@metamask/snaps-sdk';
import {
DialogType,
panel,
text,
heading,
MethodNotFoundError,
UserInputEventType,
} from '@metamask/snaps-sdk';

import { CustomDialog } from './components';

/**
* Handle incoming JSON-RPC requests from the dapp, sent through the
* `wallet_invokeSnap` method. This handler handles three methods, one for each
Expand All @@ -15,6 +21,7 @@ import {
* - `showAlert`: Show an alert dialog.
* - `showConfirmation`: Show a confirmation dialog.
* - `showPrompt`: Show a prompt dialog.
* - `showCustom`: Show a custom dialog with the resolution handled by the snap.
*
* The dialogs are shown using the [`snap_dialog`](https://docs.metamask.io/snaps/reference/rpc-api/#snap_dialog)
* method.
Expand Down Expand Up @@ -75,7 +82,62 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
},
});

case 'showCustom':
return snap.request({
method: 'snap_dialog',
params: {
content: <CustomDialog />,
},
});

default:
throw new MethodNotFoundError({ method: request.method });
}
};

/**
* Handle incoming user events coming from the MetaMask clients open interfaces.
*
* @param params - The event parameters.
* @param params.id - The Snap interface ID where the event was fired.
* @param params.event - The event object containing the event type, name and value.
* @see https://docs.metamask.io/snaps/reference/exports/#onuserinput
*/
export const onUserInput: OnUserInputHandler = async ({ id, event }) => {
if (event.type === UserInputEventType.ButtonClickEvent) {
switch (event.name) {
case 'cancel':
await snap.request({
method: 'snap_resolveInterface',
params: {
id,
value: null,
},
});
break;

case 'confirm': {
const state = await snap.request({
method: 'snap_getInterfaceState',
params: {
id,
},
});

const value = state['custom-input'];

await snap.request({
method: 'snap_resolveInterface',
params: {
id,
value,
},
});
break;
}

default:
break;
}
}
};
3 changes: 3 additions & 0 deletions packages/examples/packages/dialogs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": "./",
"jsx": "react-jsxdev",
"paths": {
"@metamask/*/jsx": ["../../../*/src/jsx"],
"@metamask/*/jsx-dev-runtime": ["../../../*/src/jsx"],
"@metamask/*": ["../../../*/src"]
}
},
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": "8L6HiuUzKAQVeog5uIIYiqBOuEb2Qm3+9HH+fXs5PlM=",
"shasum": "iHt9Se2I/fFZeIQW6p5qyNGt+wD7S2NKlNPLYjSTZMc=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
Loading

0 comments on commit 882232c

Please sign in to comment.