| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "os" |
| 5 | "path/filepath" |
| 6 | "testing" |
| 7 | |
| 8 | "reasonix/internal/control" |
| 9 | "reasonix/internal/session" |
| 10 | ) |
| 11 | |
| 12 | func TestFormalComposerTargetPreservesFileBrowserAndIdentity(t *testing.T) { |
| 13 | a := newManualSessionTestApp(t) |
| 14 | view, err := a.BeginManualSessionCreation(ManualSessionCreationRequest{OperationID: "target-wiring-session", Scope: "global"}) |
| 15 | if err != nil { |
| 16 | t.Fatal(err) |
| 17 | } |
| 18 | a.manualCreationTasks.Wait() |
| 19 | meta := a.metaForDraftSession(view.Ref.SessionID) |
| 20 | if meta == nil { |
| 21 | t.Fatal("missing created tab") |
| 22 | } |
| 23 | _, api := a.tabAndCtrlByID(meta.ID) |
| 24 | ctrl := api.(*control.Controller) |
| 25 | external := t.TempDir() |
| 26 | if err := os.WriteFile(filepath.Join(external, "outside.txt"), []byte("outside"), 0600); err != nil { |
| 27 | t.Fatal(err) |
| 28 | } |
| 29 | token, _, err := ctrl.RegisterExternalFolderRef(external) |
| 30 | if err != nil { |
| 31 | t.Fatal(err) |
| 32 | } |
| 33 | target := ComposerTarget{Kind: "session", TabID: meta.ID, Session: &view.Ref} |
| 34 | listed := a.ListDirForTarget(target, token+"/") |
| 35 | if len(listed) != 1 || listed[0].Name != "outside.txt" { |
| 36 | t.Fatalf("lost registered external directory: %+v", listed) |
| 37 | } |
| 38 | found := false |
| 39 | for _, hit := range a.SearchFileRefsForTarget(target, "outside") { |
| 40 | if hit.Path == token+"/outside.txt" { |
| 41 | found = true |
| 42 | } |
| 43 | } |
| 44 | if !found { |
| 45 | t.Fatal("external search omitted formal session controller") |
| 46 | } |
| 47 | |
| 48 | captured, err := a.CaptureAttachmentTarget(target) |
| 49 | if err != nil { |
| 50 | t.Fatal(err) |
| 51 | } |
| 52 | a.ReleaseAttachmentTarget(captured.Token) |
| 53 | wrong := session.SessionRef{HostID: "local", SessionID: "other-session"} |
| 54 | target.Session = &wrong |
| 55 | if _, err := a.CaptureAttachmentTarget(target); err == nil { |
| 56 | t.Fatal("mismatched SessionRef accepted for image staging") |
| 57 | } |
| 58 | if _, _, err := a.composerTargetWorkspace(target); err == nil { |
| 59 | t.Fatal("mismatched SessionRef accepted for file browsing") |
| 60 | } |
| 61 | |
| 62 | // Recovery can read a persisted path without relying on a resident tab. |
| 63 | data := "data:image/png;base64," + desktopTinyPNG |
| 64 | path, err := a.SavePastedImageForComposerTarget(ComposerTarget{Kind: "session", Session: &view.Ref}, data) |
| 65 | if err != nil { |
| 66 | t.Fatal(err) |
| 67 | } |
| 68 | if preview, err := a.AttachmentDataURLForComposerTarget(ComposerTarget{Kind: "session", Session: &view.Ref}, path); err != nil || preview != data { |
| 69 | t.Fatalf("durable image source: %q %v", preview, err) |
| 70 | } |
| 71 | } |
| 72 |