Files
2026-05-27 22:12:14 -05:00

128 lines
3.9 KiB
Go

package bootstrap
import (
"context"
"errors"
"strings"
"testing"
)
func TestCustomActionsNoAIStillKeepsPlaywrightAndExtension(t *testing.T) {
actions := CustomActions(Options{NoAI: true})
names := make(map[string]bool)
for _, action := range actions {
if action.AI {
t.Fatalf("AI action was included with --no-ai: %s", action.Name)
}
names[action.Name] = true
}
for _, want := range []string{"Playwright CLI", "GitHub CLI gh-repo-bootstrap extension"} {
if !names[want] {
t.Fatalf("missing non-AI action %s", want)
}
}
if names["agy"] {
t.Fatal("agy should be skipped with --no-ai")
}
}
func TestRuntimeAndCustomDependencyOrdering(t *testing.T) {
host := HostActions()
if len(host) != 4 || host[0].Name != "Node.js LTS through fnm" || host[1].Name != "pyenv-win through Scoop or Chocolatey" || host[2].Name != "latest stable Python through pyenv-win" || host[3].Name != "VLC default media player associations" {
t.Fatalf("unexpected host action order: %#v", host)
}
pyenvInstall := strings.Join(host[1].Commands[0].Args, " ")
for _, want := range []string{"scoop", "Invoke-Native 'choco' @('install', 'pyenv-win'", "Chocolatey.Chocolatey"} {
if !strings.Contains(pyenvInstall, want) {
t.Fatalf("pyenv install command missing %q: %s", want, pyenvInstall)
}
}
custom := CustomActions(Options{})
if len(custom) == 0 || custom[0].Name != "agy" {
t.Fatalf("unexpected custom action order: %#v", custom)
}
foundPlaywright := false
foundAI := false
for _, action := range custom {
if action.Name == "Playwright CLI" {
foundPlaywright = true
}
if action.AI {
foundAI = true
}
}
if !foundPlaywright || !foundAI {
t.Fatalf("custom actions missing playwright or AI actions: %#v", custom)
}
}
func TestVLCDefaultMediaActionCoversCommonAudioVideoExtensions(t *testing.T) {
host := HostActions()
vlc := host[len(host)-1]
script := strings.Join(vlc.Commands[0].Args, " ")
for _, want := range []string{
"VideoLAN\\VLC\\vlc.exe",
"VlcDefaultAssociations.xml",
"/Import-DefaultAppAssociations",
".mp3",
".flac",
".mp4",
".mkv",
".avi",
".webm",
".wmv",
"vlc-default-media.done",
} {
if !strings.Contains(script, want) {
t.Fatalf("VLC default media action missing %q", want)
}
}
}
func TestPendingActionsFiltersInstalledActions(t *testing.T) {
actions := []Action{
{Name: "done"},
{Name: "pending"},
}
pending := PendingActions([]ActionState{
{Action: actions[0], Installed: true},
{Action: actions[1]},
})
if len(pending) != 1 || pending[0].Name != "pending" {
t.Fatalf("pending = %#v, want only pending action", pending)
}
}
func TestExecuteActionsRunsCommandsAndStopsCurrentActionOnFailure(t *testing.T) {
first := CommandSpec{Name: "first", Args: []string{"ok"}}
fail := CommandSpec{Name: "second", Args: []string{"fail"}}
skipped := CommandSpec{Name: "third", Args: []string{"skipped"}}
runner := &fakeRunner{responses: map[string]CommandResult{
commandKey(fail.Name, fail.Args...): {Err: errors.New("boom"), Stderr: "failed"},
}}
issues := ExecuteActions(context.Background(), runner, []Action{{
Name: "compound action",
Commands: []CommandSpec{first, fail, skipped},
}})
if len(issues) != 1 || !strings.Contains(issues[0].Err.Error(), "failed") {
t.Fatalf("issues = %#v, want second command failure", issues)
}
if !runner.called(first.Name, first.Args...) || !runner.called(fail.Name, fail.Args...) {
t.Fatal("expected first and failing commands to run")
}
if runner.called(skipped.Name, skipped.Args...) {
t.Fatal("commands after a failing command should not run for the same action")
}
}
func TestExecuteActionsReturnsNoIssuesOnSuccess(t *testing.T) {
command := CommandSpec{Name: "ok"}
issues := ExecuteActions(context.Background(), &fakeRunner{}, []Action{{
Name: "successful action",
Commands: []CommandSpec{command},
}})
if err := issues.Err(); err != nil {
t.Fatal(err)
}
}