diff options
| author | tsne <tsne.dev@outlook.com> | 2026-07-06 16:52:20 +0200 |
|---|---|---|
| committer | tsne <tsne.dev@outlook.com> | 2026-07-06 19:21:15 +0200 |
| commit | 2c41acab4c97f584e8e199b31dc456194b8d7e6c (patch) | |
| tree | 42381deb6c4f6da0f32945432207a31b4d86664e /internal/cli/dryrun_test.go | |
| download | hopper-2c41acab4c97f584e8e199b31dc456194b8d7e6c.tar.gz | |
initial
Diffstat (limited to 'internal/cli/dryrun_test.go')
| -rw-r--r-- | internal/cli/dryrun_test.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/internal/cli/dryrun_test.go b/internal/cli/dryrun_test.go new file mode 100644 index 0000000..c2538d6 --- /dev/null +++ b/internal/cli/dryrun_test.go @@ -0,0 +1,78 @@ +package cli + +import ( + "context" + "strings" + "testing" + + "tsne.dev/hopper/internal/bunny" +) + +// TestDryRunPushStubsUploads asserts that under dry-run the push flow performs +// NO uploads against the wrapped API, yet prints the normal per-file action +// line and summary (logging is owned by the command, not the decorator). The +// recording fake is the wrapped (real-stand-in) API, so a zero put-count +// provably shows the write side was never invoked. +func TestDryRunPushStubsUploads(t *testing.T) { + arc := makeArchive(t, []tarEntry{ + {name: "index.html", body: "<html>"}, + {name: "assets/app.abc.js", body: "console.log(1)"}, + }) + + spy := newFakeAPI() + out, _ := captureLogs(t) + dryRun = true + + if err := runPush(arc, dryRunStorageAPI{spy}); err != nil { + t.Fatalf("push: %v", err) + } + + if got := spy.paths(); len(got) != 0 { + t.Fatalf("expected no real uploads, got %v", got) + } + + s := out.String() + for _, want := range []string{ + "[dryrun] uploading index.html", + "[dryrun] uploading assets/app.abc.js", + "uploaded: 2", + } { + if !strings.Contains(s, want) { + t.Fatalf("output missing %q; got:\n%s", want, s) + } + } +} + +// TestDryRunDeleteStubbed asserts Delete never reaches the wrapped API +// (reused by prune in issue 008, which will own the delete log line). +func TestDryRunDeleteStubbed(t *testing.T) { + spy := newFakeAPI() + api := dryRunStorageAPI{spy} + + if err := api.Delete(context.Background(), "old/file.js"); err != nil { + t.Fatalf("Delete: %v", err) + } + if len(spy.deletes) != 0 { + t.Fatalf("expected no real deletes, got %v", spy.deletes) + } +} + +// TestDryRunListDelegates asserts the read side still reaches the wrapped API +// (real Bunny in production), unaffected by the write stubbing. +func TestDryRunListDelegates(t *testing.T) { + spy := newFakeAPI() + spy.lists[""] = []bunny.Object{{Path: "a.js", Size: 3}} + api := dryRunStorageAPI{spy} + + it := api.List(context.Background(), "") + var got []bunny.Object + for it.Next() { + got = append(got, it.Object()) + } + if err := it.Err(); err != nil { + t.Fatalf("List: %v", err) + } + if len(got) != 1 || got[0].Path != "a.js" { + t.Fatalf("List delegate = %v", got) + } +} |