From 32111681986570c2ee951d0362db4f0af0cc6477 Mon Sep 17 00:00:00 2001 From: KayProject <109299010+KayProject@users.noreply.github.com> Date: Thu, 25 Jun 2026 23:51:52 +0100 Subject: [PATCH] test(SorobanPanel): cover non-array JSON args validation (#118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #118's SorobanPanel guard rejects valid JSON that is not an array (e.g. {} or 42) so a non-array is never forwarded to invokeContract. The existing test only covered malformed JSON syntax, leaving the non-array case — the actual security fix — untested. Add tests asserting: - a JSON object {} is rejected with 'Arguments must be a JSON array' - a JSON number 42 is rejected with the same error - a valid JSON array passes validation and reaches the success state SorobanPanel: 5 tests passing. Lint clean. Closes #118 --- src/components/SorobanPanel.test.tsx | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/components/SorobanPanel.test.tsx b/src/components/SorobanPanel.test.tsx index b5fb0b3..0c5f4ee 100644 --- a/src/components/SorobanPanel.test.tsx +++ b/src/components/SorobanPanel.test.tsx @@ -63,4 +63,47 @@ describe("SorobanPanel", () => { const errorText = await screen.findByText(/Invalid JSON in arguments/i); expect(errorText).toBeInTheDocument(); }); + + // ── Non-array JSON args (#118) ──────────────────────────────────────────── + // Valid JSON that is not an array (e.g. `{}` or `42`) must be rejected before + // it is forwarded to invokeContract, which expects an argument array. + async function invokeWithArgs(argsValue: string) { + const { rerender } = render( + {}} />, + ); + fireEvent.change(screen.getByPlaceholderText(/c\.\.\./i), { + target: { value: "C123" }, + }); + fireEvent.change(screen.getByPlaceholderText(/transfer/i), { + target: { value: "mint" }, + }); + fireEvent.change(screen.getByPlaceholderText(/\[.*\]/i), { + target: { value: argsValue }, + }); + rerender( {}} />); + fireEvent.click(screen.getByRole("button", { name: /invoke/i })); + } + + it("rejects a JSON object (non-array) with a 'must be a JSON array' error", async () => { + await invokeWithArgs("{}"); + expect( + await screen.findByText(/Arguments must be a JSON array/i), + ).toBeInTheDocument(); + }); + + it("rejects a JSON number (non-array) with a 'must be a JSON array' error", async () => { + await invokeWithArgs("42"); + expect( + await screen.findByText(/Arguments must be a JSON array/i), + ).toBeInTheDocument(); + }); + + it("accepts a valid JSON array and reaches the success state", async () => { + await invokeWithArgs('["arg1", 42]'); + // No validation error; the mocked invokeContract resolves successfully. + expect( + screen.queryByText(/Arguments must be a JSON array/i), + ).not.toBeInTheDocument(); + expect(await screen.findByText(/success/i)).toBeInTheDocument(); + }); });