Files
pad/internal/cli/builtin_format_test.go
T
xarmian 99aac1687b feat(cli): pad library diff and pad library update for built-in conventions and playbooks (TASK-3462 U3c) (#1875)
* test: pad library diff/update and the builtin_update capability (TASK-3462 U3c, red)

* feat(cli): pad library diff and pad library update for built-in conventions and playbooks (TASK-3462 U3c)

- diff shows what Pad's library changed since the item was made, what the
  user changed (or a plain comparison when that is unknown), and the
  settings an update would replace.
- update takes the library's text, guarded by the seq read just before. It
  refuses content_pending_flush unless --overwrite-pending-edits, explains
  update_conflict, and reports a current item without sending.
- The server advertises builtin_update; both commands refuse without it,
  since an older server's bare 404 reads like not_builtin.
Not on MCP, per the design.

* test: pad library diff/update codex r1 findings (TASK-3462 U3c, red)

* fix(cli): pad library diff/update codex r1 findings (TASK-3462 U3c)

- The JSON diff carries the current text from a server that does not send it.
- A no-op under --format json is a JSON result.
- A failed capabilities probe says so; it is no longer reported as an older
  server.
- An update prints the write's warnings: applied to an open editor, and
  pending edits pruned.
- content_pending_flush is rendered by the shared helper, which names
  set-aside rows apart from an open editor's; the flag's help covers both.
- The diff names an end-of-file newline change.

* test(cli): built-in diff keeps large numbers and refuses a mixed-version fallback (TASK-3462 U3c, codex r2, red)

* fix(cli): built-in diff keeps numbers as written and refuses a fallback from another version (TASK-3462 U3c, codex r2)

BuiltinText decodes its fields keeping numbers, and the fallback read of the
item does the same, with status and nulls dropped to match the server's
current. A fallback whose seq differs from the state's is refused instead of
mixed in.

* test(cli): built-in update reports undeclared fields (TASK-3462 U3c, codex r5, red)

* fix(cli): built-in update reports undeclared fields like any item update (TASK-3462 U3c, codex r5)
2026-10-08 05:05:04 -04:00

53 lines
1.7 KiB
Go

package cli
import (
"strings"
"testing"
)
func TestFormatLineDiffMarksChangesAndElidesDistantContext(t *testing.T) {
var old, next []string
for i := 0; i < 20; i++ {
old = append(old, "line "+string(rune('a'+i)))
}
next = append(next, old...)
next[10] = "line k, changed"
got := FormatLineDiff(strings.Join(old, "\n")+"\n", strings.Join(next, "\n")+"\n", 2)
for _, want := range []string{"-line k\n", "+line k, changed\n", " line i\n", " line m\n", " …\n"} {
if !strings.Contains(got, want) {
t.Errorf("diff lacks %q:\n%s", want, got)
}
}
if strings.Contains(got, " line a\n") {
t.Errorf("a line far from the change was not elided:\n%s", got)
}
if FormatLineDiff("same\n", "same\n", 3) != "" {
t.Error("equal texts produced a diff")
}
}
func TestBuiltinFieldChanges(t *testing.T) {
changes := BuiltinFieldChanges(
map[string]any{"trigger": "on-release", "n": 1e3, "status": "deprecated", "legacy": "x"},
map[string]any{"trigger": "manual", "n": 1000.0, "status": "active"},
map[string]any{"legacy": "x"},
)
if len(changes) != 2 {
t.Fatalf("changes %+v, want trigger and the dropped legacy only", changes)
}
if changes[0].Key != "legacy" || changes[0].HasLib {
t.Errorf("dropped field not reported as removed: %+v", changes[0])
}
if changes[1].Key != "trigger" || changes[1].Current != "on-release" || changes[1].Library != "manual" {
t.Errorf("trigger change wrong: %+v", changes[1])
}
}
// codex r1 (P3): a change to the final newline alone is visible.
func TestFormatLineDiffShowsAnEndOfFileNewlineChange(t *testing.T) {
got := FormatLineDiff("a\n", "a", 3)
if !strings.Contains(got, "No newline at end of file") {
t.Fatalf("newline change hidden:\n%q", got)
}
}