返回 DeepSeek-Reasonix
screenshot_test.go
根目录 / internal / browser / screenshot_test.go
1 package browser
2
3 import (
4 "bytes"
5 "context"
6 "encoding/base64"
7 "encoding/json"
8 "image"
9 "image/png"
10 "os"
11 "path/filepath"
12 "reflect"
13 "strings"
14 "testing"
15
16 "reasonix/internal/tool"
17 )
18
19 func TestScreenshotReturnsPNGImage(t *testing.T) {
20 path := filepath.Join(t.TempDir(), "shot.png")
21 var buf bytes.Buffer
22 if err := png.Encode(&buf, image.NewRGBA(image.Rect(0, 0, 2, 2))); err != nil {
23 t.Fatal(err)
24 }
25 if err := os.WriteFile(path, buf.Bytes(), 0o600); err != nil {
26 t.Fatal(err)
27 }
28 fake := &fakeExecutor{screenshot: Screenshot{Path: path, Width: 2, Height: 2}}
29 shot := toolByName(t, fake, "browser_screenshot")
30 it, ok := shot.(tool.ImageTool)
31 if !ok {
32 t.Fatal("browser_screenshot does not implement ImageTool")
33 }
34 args := json.RawMessage(`{"tabId":"t1","ref":"e4","fullPage":true}`)
35 text, images, err := it.ExecuteWithImages(context.Background(), args)
36 if err != nil {
37 t.Fatal(err)
38 }
39 if len(images) != 1 || !strings.HasPrefix(images[0], "data:image/png;base64,") {
40 t.Fatalf("images = %v", images)
41 }
42 decoded, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(images[0], "data:image/png;base64,"))
43 if err != nil || !bytes.Equal(decoded, buf.Bytes()) {
44 t.Fatalf("image payload does not round-trip: err = %v", err)
45 }
46 if !strings.Contains(text, "[image: image/png, 2x2]") || !strings.Contains(text, "tab t1") || !strings.Contains(text, path) {
47 t.Fatalf("text = %q", text)
48 }
49 if !reflect.DeepEqual(fake.shots, []ScreenshotRequest{{TabID: "t1", Ref: "e4", FullPage: true}}) {
50 t.Fatalf("screenshot requests = %+v", fake.shots)
51 }
52 out, err := shot.Execute(context.Background(), args)
53 if err != nil || !strings.Contains(out, "structured image channel") || strings.Contains(out, "base64") {
54 t.Fatalf("Execute out = %q, err = %v", out, err)
55 }
56 }
57
58 func TestScreenshotRefusesOversizeFile(t *testing.T) {
59 path := filepath.Join(t.TempDir(), "big.png")
60 f, err := os.Create(path)
61 if err != nil {
62 t.Fatal(err)
63 }
64 if err := f.Truncate(screenshotMaxBytes + 1); err != nil {
65 t.Fatal(err)
66 }
67 f.Close()
68 fake := &fakeExecutor{screenshot: Screenshot{Path: path}}
69 text, images, err := toolByName(t, fake, "browser_screenshot").(tool.ImageTool).ExecuteWithImages(context.Background(), json.RawMessage(`{"tabId":"t1"}`))
70 if err != nil || len(images) != 0 || !strings.Contains(text, "over the 8 MiB limit") {
71 t.Fatalf("text = %q, images = %d, err = %v", text, len(images), err)
72 }
73 }
74
75 func TestScreenshotMissingFileIsError(t *testing.T) {
76 fake := &fakeExecutor{screenshot: Screenshot{Path: filepath.Join(t.TempDir(), "missing.png")}}
77 _, _, err := toolByName(t, fake, "browser_screenshot").(tool.ImageTool).ExecuteWithImages(context.Background(), json.RawMessage(`{"tabId":"t1"}`))
78 if err == nil || !strings.Contains(err.Error(), "read screenshot") {
79 t.Fatalf("err = %v", err)
80 }
81 if _, blocked := tool.BlockedMessage(err); blocked {
82 t.Fatalf("missing file rendered as blocked: %v", err)
83 }
84 }
85
85 lines GO