From ee198d15de74b4dd9e7b040a300b4bb2b0170034 Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 7 Jun 2026 16:43:46 +0530 Subject: [PATCH] feat(ioscompanion): expose native typing with an explicit replace flag --- .../driver/ioscompanion/transport/runner.go | 6 +++++- .../ioscompanion/transport/runner_test.go | 19 +++++++++++++++++++ .../ioscompanion/transport/transport.go | 8 ++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/internal/driver/ioscompanion/transport/runner.go b/internal/driver/ioscompanion/transport/runner.go index a2093e1..be64387 100644 --- a/internal/driver/ioscompanion/transport/runner.go +++ b/internal/driver/ioscompanion/transport/runner.go @@ -282,7 +282,11 @@ func (c *runnerCompanion) Uninstall(ctx context.Context, bundleID string) error } func (c *runnerCompanion) InputText(ctx context.Context, text string) error { - _, err := c.call(ctx, "typeText", map[string]any{"text": text, "replace": true}) + return c.TypeText(ctx, text, true) +} + +func (c *runnerCompanion) TypeText(ctx context.Context, text string, replace bool) error { + _, err := c.call(ctx, "typeText", map[string]any{"text": text, "replace": replace}) return err } diff --git a/internal/driver/ioscompanion/transport/runner_test.go b/internal/driver/ioscompanion/transport/runner_test.go index 3e767a0..5788c5f 100644 --- a/internal/driver/ioscompanion/transport/runner_test.go +++ b/internal/driver/ioscompanion/transport/runner_test.go @@ -467,3 +467,22 @@ func TestResponseIDMismatchIsSentinel(t *testing.T) { t.Fatalf("id mismatch must wrap the sentinel: %v", err) } } + +func TestTypeTextAppendsWithoutReplace(t *testing.T) { + server := startFakeServer(t, nil) + companion := dialFake(t, server, "com.example.app") + typer := companion.(TextTyper) + + if err := typer.TypeText(context.Background(), "héllo 🌟", false); err != nil { + t.Fatalf("TypeText: %v", err) + } + + requests := server.recorded() + if len(requests) != 1 { + t.Fatalf("recorded %d requests, want 1", len(requests)) + } + request := requests[0] + if request.Method != "typeText" || request.Params["text"] != "héllo 🌟" || request.Params["replace"] != false { + t.Fatalf("typeText request = %+v", request) + } +} diff --git a/internal/driver/ioscompanion/transport/transport.go b/internal/driver/ioscompanion/transport/transport.go index 6a678bb..7412ebc 100644 --- a/internal/driver/ioscompanion/transport/transport.go +++ b/internal/driver/ioscompanion/transport/transport.go @@ -62,6 +62,14 @@ type TextEditor interface { PressKey(ctx context.Context, key string) error } +// TextTyper is an optional companion capability: the transport types text +// natively into whatever holds keyboard focus. Unlike TextEditor it exposes +// the replace flag, so a caller can clear the field through another channel +// and append with replace false. +type TextTyper interface { + TypeText(ctx context.Context, text string, replace bool) error +} + // ErrCompanionUnavailable marks a connection-level failure that a companion // restart can recover from. Transports wrap dropped-connection errors with it. var ErrCompanionUnavailable = errors.New("companion connection unavailable")