diff --git a/packages/kernel-ui/src/components/SendMessageForm.test.tsx b/packages/kernel-ui/src/components/SendMessageForm.test.tsx
index 5e1abd13dc..6d24a8df5c 100644
--- a/packages/kernel-ui/src/components/SendMessageForm.test.tsx
+++ b/packages/kernel-ui/src/components/SendMessageForm.test.tsx
@@ -17,7 +17,7 @@ import { useRegistry } from '../hooks/useRegistry.ts';
import type { ObjectRegistry } from '../types.ts';
import { SendMessageForm } from './SendMessageForm.tsx';
-setupOcapKernelMock();
+const { setMockBehavior } = setupOcapKernelMock();
vi.mock('../context/PanelContext.tsx', () => ({
usePanelContext: vi.fn(),
@@ -27,7 +27,8 @@ vi.mock('../hooks/useRegistry.ts', () => ({
useRegistry: vi.fn(),
}));
-vi.mock('@metamask/kernel-utils', () => ({
+vi.mock('@metamask/kernel-utils', async (importOriginal) => ({
+ ...(await importOriginal()),
stringify: vi.fn(),
}));
@@ -45,14 +46,14 @@ describe('SendMessageForm Component', () => {
overview: { name: 'TestVat1', bundleSpec: '' },
ownedObjects: [
{
- kref: 'kref1',
+ kref: 'ko1',
eref: 'eref1',
refCount: '1',
toVats: [],
revoked: 'false',
},
{
- kref: 'kref2',
+ kref: 'ko2',
eref: 'eref2',
refCount: '1',
toVats: [],
@@ -67,7 +68,7 @@ describe('SendMessageForm Component', () => {
overview: { name: 'TestVat2', bundleSpec: '' },
ownedObjects: [
{
- kref: 'kref3',
+ kref: 'ko3',
eref: 'eref3',
refCount: '1',
toVats: [],
@@ -76,7 +77,7 @@ describe('SendMessageForm Component', () => {
],
importedObjects: [
{
- kref: 'kref4',
+ kref: 'ko4',
eref: 'eref4',
refCount: '1',
fromVat: 'vat1',
@@ -144,10 +145,10 @@ describe('SendMessageForm Component', () => {
expect(options).toHaveLength(5); // 1 placeholder + 4 options from mock registry
// Check dropdown options include objects from the registry
- expect(screen.getByText('kref1 (TestVat1)')).toBeInTheDocument();
- expect(screen.getByText('kref2 (TestVat1)')).toBeInTheDocument();
- expect(screen.getByText('kref3 (TestVat2)')).toBeInTheDocument();
- expect(screen.getByText('kref4 (TestVat1)')).toBeInTheDocument();
+ expect(screen.getByText('ko1 (TestVat1)')).toBeInTheDocument();
+ expect(screen.getByText('ko2 (TestVat1)')).toBeInTheDocument();
+ expect(screen.getByText('ko3 (TestVat2)')).toBeInTheDocument();
+ expect(screen.getByText('ko4 (TestVat1)')).toBeInTheDocument();
});
it('updates form values when inputs change', async () => {
@@ -155,8 +156,8 @@ describe('SendMessageForm Component', () => {
// Change target
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
- expect(targetSelect).toHaveValue('kref1');
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
+ expect(targetSelect).toHaveValue('ko1');
// Change method
const methodInput = getByTestId('message-method');
@@ -179,7 +180,7 @@ describe('SendMessageForm Component', () => {
// Select a target
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
// Button should now be enabled
expect(sendButton).not.toBeDisabled();
@@ -192,12 +193,26 @@ describe('SendMessageForm Component', () => {
expect(sendButton).toBeDisabled();
});
+ it('does not set target when value fails KRef validation', async () => {
+ setMockBehavior({ isKRef: false });
+ const { getByTestId } = render();
+
+ const targetSelect = getByTestId('message-target');
+ fireEvent.change(targetSelect, { target: { value: 'not-a-kref' } });
+
+ // Target should remain unset, button stays disabled
+ expect(targetSelect).toHaveValue('');
+ expect(getByTestId('message-send-button')).toBeDisabled();
+
+ setMockBehavior({ isKRef: true });
+ });
+
it('calls callKernelMethod with correct parameters when Send button is clicked', async () => {
const { getByTestId } = render();
// Set up form values
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
const methodInput = getByTestId('message-method');
fireEvent.change(methodInput, { target: { value: 'testMethod' } });
@@ -215,7 +230,7 @@ describe('SendMessageForm Component', () => {
// Check if callKernelMethod was called with correct parameters
expect(callKernelMethod).toHaveBeenCalledWith({
method: 'queueMessage',
- params: ['kref1', 'testMethod', expectedArgs],
+ params: ['ko1', 'testMethod', expectedArgs],
});
// Check if fetchObjectRegistry was called
@@ -232,7 +247,7 @@ describe('SendMessageForm Component', () => {
// Set up form values and submit
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
const sendButton = getByTestId('message-send-button');
await userEvent.click(sendButton);
@@ -255,7 +270,7 @@ describe('SendMessageForm Component', () => {
// Set up form values and submit
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
const sendButton = getByTestId('message-send-button');
await userEvent.click(sendButton);
@@ -277,7 +292,7 @@ describe('SendMessageForm Component', () => {
// Set up form values with invalid JSON
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
const paramsInput = getByTestId('message-params');
fireEvent.change(paramsInput, { target: { value: 'invalid json' } });
@@ -300,7 +315,7 @@ describe('SendMessageForm Component', () => {
// Set up form values - we need a valid target and valid JSON
const targetSelect = getByTestId('message-target');
- fireEvent.change(targetSelect, { target: { value: 'kref1' } });
+ fireEvent.change(targetSelect, { target: { value: 'ko1' } });
// Ensure we have valid JSON in the params field
const paramsInput = getByTestId('message-params');
diff --git a/packages/kernel-ui/src/components/SendMessageForm.tsx b/packages/kernel-ui/src/components/SendMessageForm.tsx
index b2fb34c197..d2834663e8 100644
--- a/packages/kernel-ui/src/components/SendMessageForm.tsx
+++ b/packages/kernel-ui/src/components/SendMessageForm.tsx
@@ -9,6 +9,7 @@ import {
TextColor,
} from '@metamask/design-system-react';
import { stringify } from '@metamask/kernel-utils';
+import { isKRef } from '@metamask/ocap-kernel';
import type { KRef } from '@metamask/ocap-kernel';
import type { Json } from '@metamask/utils';
import { useState, useMemo } from 'react';
@@ -27,7 +28,7 @@ const inputStyle =
export const SendMessageForm: React.FC = () => {
const { callKernelMethod, logMessage, objectRegistry } = usePanelContext();
const { fetchObjectRegistry } = useRegistry();
- const [target, setTarget] = useState('');
+ const [target, setTarget] = useState(null);
const [method, setMethod] = useState('__getMethodNames__');
const [paramsText, setParamsText] = useState('[]');
const [result, setResult] = useState(null);
@@ -64,12 +65,15 @@ export const SendMessageForm: React.FC = () => {
}, [objectRegistry]);
const handleSend = (): void => {
+ if (!target) {
+ return;
+ }
Promise.resolve()
.then(() => JSON.parse(paramsText) as Json[])
.then(async (args) =>
callKernelMethod({
method: 'queueMessage',
- params: [target as KRef, method, args],
+ params: [target, method, args],
}),
)
.then((response) => {
@@ -117,8 +121,11 @@ export const SendMessageForm: React.FC = () => {