feat: add contextual Target actions

This commit is contained in:
proxyctl coordinator
2026-07-17 23:14:57 +08:00
parent 2ca42bd4bd
commit 2ac088b388
16 changed files with 428 additions and 194 deletions
+10 -8
View File
@@ -18,7 +18,7 @@ type interactiveScriptModule struct {
intents []app.Intent
}
func (m *interactiveScriptModule) Snapshot() app.Snapshot { return withTestTargetActions(m.snapshot) }
func (m *interactiveScriptModule) Snapshot() app.Snapshot { return m.snapshot }
func (m *interactiveScriptModule) Dispatch(intent app.Intent) app.Result {
m.intents = append(m.intents, intent)
return app.Result{Snapshot: m.snapshot}
@@ -27,18 +27,18 @@ func (m *interactiveScriptModule) StartOperation(intent app.Intent) app.Operatio
m.intents = append(m.intents, intent)
stream := m.streams[0]
m.streams = m.streams[1:]
return app.OperationStream{Snapshot: withTestTargetActions(m.snapshot), Updates: stream}
return app.OperationStream{Snapshot: m.snapshot, Updates: stream}
}
func operationSnapshot() app.Snapshot {
return withTestTargetActions(app.Snapshot{
return app.Snapshot{
ActiveProfile: "office",
Profiles: []profile.Profile{{Name: "office"}, {Name: "remote"}},
Targets: []app.TargetSnapshot{
{ID: "shell", Description: target.Description{Name: "Shell", Summary: "Shell details"}, Available: true, State: target.Disabled},
{ID: "apt", Description: target.Description{Name: "APT", Summary: "APT details"}, Available: true, State: target.Enabled},
{ID: "shell", Description: target.Description{Name: "Shell", Summary: "Shell details"}, Available: true, State: target.Disabled, PrimaryAction: app.TargetAction{Kind: app.EnableTargetAction, Available: true}},
{ID: "apt", Description: target.Description{Name: "APT", Summary: "APT details"}, Available: true, State: target.Enabled, PrimaryAction: app.TargetAction{Kind: app.DisableTargetAction, Available: true}},
},
})
}
}
func applyOperationCommand(t *testing.T, model Model, command tea.Cmd) (Model, tea.Cmd) {
@@ -196,13 +196,15 @@ func TestCompleteModelExplainsDisabledTargetMutations(t *testing.T) {
model.snapshot.Targets[0].DetectionPhase = app.TargetChecking
model.snapshot.Targets[0].PrimaryAction.Available = false
model.snapshot.Targets[0].PrimaryAction.DisabledReason = "Target mutation is disabled while this Target is still being checked"
model.operation.active = true
updated, command := model.Update(tea.KeyMsg{Type: tea.KeySpace})
model = updated.(Model)
if command != nil || !strings.Contains(model.View(), "disabled while this Target is still being checked") {
t.Fatalf("Checking mutation lacked a visible reason:\n%s", model.View())
if command != nil || model.operation.status.Summary != "Target mutation is disabled while this Target is still being checked" {
t.Fatalf("Checking reason was masked by operation serialization: %q\n%s", model.operation.status.Summary, model.View())
}
model.operation.active = false
model.snapshot.Targets[0].DetectionPhase = app.TargetReady
model.snapshot.Targets[0].PrimaryAction.Available = false
model.snapshot.Targets[0].PrimaryAction.DisabledReason = "Target mutation is disabled because there is no Active Profile; open Profile management first"