Skip to content

Commit

Permalink
Add snaps-jest tests for Selector component
Browse files Browse the repository at this point in the history
  • Loading branch information
david0xd committed Sep 16, 2024
1 parent 04161a3 commit 19f10c3
Show file tree
Hide file tree
Showing 4 changed files with 323 additions and 1 deletion.
67 changes: 66 additions & 1 deletion packages/snaps-jest/src/internals/request.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { SnapInterfaceController } from '@metamask/snaps-controllers';
import type { SnapId } from '@metamask/snaps-sdk';
import { UserInputEventType, button, input, text } from '@metamask/snaps-sdk';
import { Dropdown, Option, Radio, RadioGroup } from '@metamask/snaps-sdk/jsx';
import {
Card,
Dropdown,
Option,
Radio,
RadioGroup,
Selector,
SelectorOption,
} from '@metamask/snaps-sdk/jsx';
import { getJsxElementFromComponent, HandlerType } from '@metamask/snaps-utils';
import { MOCK_SNAP_ID } from '@metamask/snaps-utils/test-utils';

Expand Down Expand Up @@ -517,4 +525,61 @@ describe('getInterfaceApi', () => {
},
);
});

it('sends the request to the snap when using `selectInSelector`', async () => {
const controllerMessenger = getRootControllerMessenger();

jest.spyOn(controllerMessenger, 'call');

// eslint-disable-next-line no-new
new SnapInterfaceController({
messenger:
getRestrictedSnapInterfaceControllerMessenger(controllerMessenger),
});

const content = (
<Selector name="foo" title="Choose an option" value="option1">
<SelectorOption value="option1">
<Card title="Option 1" value="option1" />
</SelectorOption>
<SelectorOption value="option2">
<Card title="Option 2" value="option2" />
</SelectorOption>
</Selector>
);

const getInterface = await getInterfaceApi(
{ content },
MOCK_SNAP_ID,
controllerMessenger,
);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const snapInterface = getInterface!();

await snapInterface.selectFromSelector('foo', 'option2');

expect(controllerMessenger.call).toHaveBeenNthCalledWith(
6,
'ExecutionService:handleRpcRequest',
MOCK_SNAP_ID,
{
origin: '',
handler: HandlerType.OnUserInput,
request: {
jsonrpc: '2.0',
method: ' ',
params: {
event: {
type: UserInputEventType.InputChangeEvent,
name: 'foo',
value: 'option2',
},
id: expect.any(String),
context: null,
},
},
},
);
});
});
164 changes: 164 additions & 0 deletions packages/snaps-jest/src/internals/simulation/interface.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import {
Form,
Container,
Footer,
SelectorOption,
Card,
Selector,
} from '@metamask/snaps-sdk/jsx';
import {
getJsxElementFromComponent,
Expand Down Expand Up @@ -59,6 +62,7 @@ import {
selectFromRadioGroup,
typeInField,
uploadFile,
selectFromSelector,
} from './interface';
import type { RunSagaFunction } from './store';
import { createStore, resolveInterface, setInterface } from './store';
Expand All @@ -83,6 +87,7 @@ describe('getInterfaceResponse', () => {
typeInField: jest.fn(),
selectInDropdown: jest.fn(),
selectFromRadioGroup: jest.fn(),
selectFromSelector: jest.fn(),
uploadFile: jest.fn(),
};

Expand All @@ -103,6 +108,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
});
Expand All @@ -129,6 +135,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
cancel: expect.any(Function),
Expand Down Expand Up @@ -156,6 +163,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
cancel: expect.any(Function),
Expand Down Expand Up @@ -183,6 +191,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
cancel: expect.any(Function),
Expand Down Expand Up @@ -210,6 +219,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
cancel: expect.any(Function),
Expand Down Expand Up @@ -237,6 +247,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
ok: expect.any(Function),
cancel: expect.any(Function),
Expand Down Expand Up @@ -283,6 +294,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
});
});
Expand Down Expand Up @@ -321,6 +333,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
cancel: expect.any(Function),
});
Expand Down Expand Up @@ -354,6 +367,7 @@ describe('getInterfaceResponse', () => {
typeInField: expect.any(Function),
selectInDropdown: expect.any(Function),
selectFromRadioGroup: expect.any(Function),
selectFromSelector: expect.any(Function),
uploadFile: expect.any(Function),
cancel: expect.any(Function),
ok: expect.any(Function),
Expand Down Expand Up @@ -1504,3 +1518,153 @@ describe('selectFromRadioGroup', () => {
);
});
});

describe('selectFromSelector', () => {
const rootControllerMessenger = getRootControllerMessenger();
const controllerMessenger = getRestrictedSnapInterfaceControllerMessenger(
rootControllerMessenger,
);

const interfaceController = new SnapInterfaceController({
messenger: controllerMessenger,
});

const handleRpcRequestMock = jest.fn();

rootControllerMessenger.registerActionHandler(
'ExecutionService:handleRpcRequest',
handleRpcRequestMock,
);

it('updates the interface state and sends an InputChangeEvent', async () => {
jest.spyOn(rootControllerMessenger, 'call');

const content = (
<Selector name="foo" title="Choose an option" value="option1">
<SelectorOption value="option1">
<Card title="Option 1" value="option1" />
</SelectorOption>
<SelectorOption value="option2">
<Card title="Option 2" value="option2" />
</SelectorOption>
</Selector>
);

const interfaceId = await interfaceController.createInterface(
MOCK_SNAP_ID,
content,
);

await selectFromSelector(
rootControllerMessenger,
interfaceId,
content,
MOCK_SNAP_ID,
'foo',
'option2',
);

expect(rootControllerMessenger.call).toHaveBeenCalledWith(
'SnapInterfaceController:updateInterfaceState',
interfaceId,
{ foo: 'option2' },
);

expect(handleRpcRequestMock).toHaveBeenCalledWith(MOCK_SNAP_ID, {
origin: '',
handler: HandlerType.OnUserInput,
request: {
jsonrpc: '2.0',
method: ' ',
params: {
event: {
type: UserInputEventType.InputChangeEvent,
name: 'foo',
value: 'option2',
},
id: interfaceId,
context: null,
},
},
});
});

it('throws if chosen option does not exist', async () => {
const content = (
<Selector name="foo" title="Choose an option" value="option1">
<SelectorOption value="option1">
<Card title="Option 1" value="option1" />
</SelectorOption>
<SelectorOption value="option2">
<Card title="Option 2" value="option2" />
</SelectorOption>
</Selector>
);

const interfaceId = await interfaceController.createInterface(
MOCK_SNAP_ID,
content,
);

await expect(
selectFromSelector(
rootControllerMessenger,
interfaceId,
content,
MOCK_SNAP_ID,
'foo',
'option3',
),
).rejects.toThrow(
'The Selector with the name "foo" does not contain "option3"',
);
});

it('throws if there is no Selector in the interface', async () => {
const content = (
<Box>
<Text>Foo</Text>
</Box>
);

const interfaceId = await interfaceController.createInterface(
MOCK_SNAP_ID,
content,
);

await expect(
selectFromSelector(
rootControllerMessenger,
interfaceId,
content,
MOCK_SNAP_ID,
'bar',
'baz',
),
).rejects.toThrow(
'Could not find an element in the interface with the name "bar".',
);
});

it('throws if the element is not a Selector', async () => {
const content = <Input name="foo" />;

const interfaceId = await interfaceController.createInterface(
MOCK_SNAP_ID,
content,
);

await expect(
selectFromSelector(
rootControllerMessenger,
interfaceId,
content,
MOCK_SNAP_ID,
'foo',
'baz',
),
).rejects.toThrow(
'Expected an element of type "Selector", but found "Input".',
);
});
});
Loading

0 comments on commit 19f10c3

Please sign in to comment.