turbo-editors/turbo-pythonpublic Fork 0
v1.0.1
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

📦 Turbo Python 6fc62ea · on v1.0.1 · k33g · 9h ago
acp_test.go · 128 lines · 4.2 KBGo Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package pythonlang

import (
	"errors"
	"os"
	"strings"
	"testing"

	"rickub.com/turbo-editors/turbo-core/acp"
)

// The agents file Turbo Python writes. What the *feature* does is turbo-core's to
// test; what is checked here is the one part that belongs to this editor —
// that the starter file is filled in correctly, loads back as the agent it
// describes, and says enough for somebody to point it at their own.

// readAgentsFile returns the agents file a project was given.
func readAgentsFile(t *testing.T, dir string) string {
	t.Helper()

	data, err := os.ReadFile(acp.ProjectPath(Profile(), dir))
	if err != nil {
		t.Fatalf("reading the agents file: %v", err)
	}
	return string(data)
}

// createAgents writes the starter agents file into a fresh project.
func createAgents(t *testing.T) string {
	t.Helper()

	dir := t.TempDir()
	if _, err := acp.Create(Profile(), dir); err != nil {
		t.Fatalf("acp.Create() error = %v", err)
	}
	return dir
}

func TestTheCreatedAgentsFileFillsBothOfItsBlanks(t *testing.T) {
	// Two different values — the project directory the example agent points
	// into, and the user's own file that a comment names. Go writes
	// %!s(MISSING) into the output rather than failing, so a miscounted verb
	// produces a starter file that is written, opened, and wrong.
	contents := readAgentsFile(t, createAgents(t))

	if strings.Contains(contents, "%!") {
		t.Errorf("the created file has an unfilled verb in it:\n%s", contents)
	}
	if want := Profile().ProjectDir() + "/agent.yaml"; !strings.Contains(contents, want) {
		t.Errorf("the example agent does not point at %q:\n%s", want, contents)
	}
	if want := acp.UserPath(Profile()); want != "" && !strings.Contains(contents, want) {
		t.Errorf("the created file never names the user's own file %q:\n%s", want, contents)
	}
}

func TestTheCreatedAgentsFileLoadsBackAsOneAgent(t *testing.T) {
	// The file is mostly comments, and a comment carrying an [[agent]] example
	// that the loader read as real would put an agent nobody configured into
	// the menu.
	dir := createAgents(t)

	list, err := acp.Load(Profile(), dir)
	if err != nil {
		t.Fatalf("acp.Load() error = %v", err)
	}
	if list.Len() != 1 {
		t.Fatalf("the created file holds %d agents, want 1: %v", list.Len(), list.Agents())
	}

	agent := list.Agents()[0]
	if agent.Command != "docker" {
		t.Errorf("the example agent runs %q, want docker", agent.Command)
	}
	if want := "agent serve acp"; !strings.Contains(agent.CommandLine(), want) {
		t.Errorf("the example command line is %q, want %q in it", agent.CommandLine(), want)
	}
}

func TestTheCreatedAgentsFileExplainsItself(t *testing.T) {
	// The keys, the window's keyboard and how to copy out of it are all
	// invisible otherwise: this is the only document the editor hands a user.
	contents := readAgentsFile(t, createAgents(t))

	for _, want := range []string{
		"[[agent]]", "name", "command", "args", "env", "cwd",
		"agentclientprotocol.com",
		"Alt-Enter", "Ctrl-W", "Esc", "Ctrl-C",
	} {
		if !strings.Contains(contents, want) {
			t.Errorf("the created file never mentions %q:\n%s", want, contents)
		}
	}
}

func TestTheCreatedAgentsFileNamesThisEditorsOwnLanguage(t *testing.T) {
	// The comment about coloured code blocks is the one line of this file that
	// is about Turbo Python rather than about the protocol, and a copy left naming
	// another editor's language would be the obvious way to get it wrong.
	contents := readAgentsFile(t, createAgents(t))

	if want := "```python"; !strings.Contains(contents, want) {
		t.Errorf("the created file never mentions a %q fence:\n%s", want, contents)
	}
	if want := ".py files"; !strings.Contains(contents, want) {
		t.Errorf("the created file never mentions %q:\n%s", want, contents)
	}
}

func TestCreatingAgentsTwiceLeavesTheFirstAlone(t *testing.T) {
	dir := createAgents(t)
	path := acp.ProjectPath(Profile(), dir)

	if err := os.WriteFile(path, []byte("# mine\n"), 0o644); err != nil {
		t.Fatalf("writing over it: %v", err)
	}
	if _, err := acp.Create(Profile(), dir); !errors.Is(err, acp.ErrExists) {
		t.Errorf("acp.Create() error = %v, want ErrExists", err)
	}

	data, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("reading it back: %v", err)
	}
	if string(data) != "# mine\n" {
		t.Errorf("the file was overwritten: %q", data)
	}
}