Skip to content

Commit a97701b

Browse files
author
SqlRush
committed
Accept focus action payloads in scripts
1 parent cf2a898 commit a97701b

5 files changed

Lines changed: 37 additions & 5 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
614614

615615
本轮补充:interaction script 的 direct focus bool alias 字段现在也递归解包 wrapper;`focus``focused``focusIn``focusOut``blur`/`blurred` 可从 wrapped `enabled``value``selected` 等字段恢复焦点事件控制,避免 direct field fixture 在 bool decode 阶段失败。
616616

617+
本轮补充:interaction script 的 focus/blur action-discriminator 现在也接受 `value`/`payload`/`data` 中的 wrapped bool;`action:"focus"``kind:"blur"``operation:"focusState"``name:"setFocus"` 可用 `focused:false``blurred:false` 或非严格 bool payload 明确发出 focus-out/focus-in。
618+
617619
本轮补充:interaction script 的 direct expectation bool alias 字段现在也递归解包 wrapper;`expectNoEvent``expectNoDialogResult(s)``expectFocused` 可从 wrapped `value`/`enabled`/`selected` 恢复断言控制,避免 direct expectation fixture 在 bool decode 阶段失败。
618620

619621
本轮补充:interaction script 的 direct expectation count alias 字段现在也递归解包 wrapper;`expectEventCount``expectTotalEventCount``expectDialogResultCount``expectTotalDialogResultCount` 可从 wrapped `value`/`count`/`total` 恢复计数断言,避免 direct expectation fixture 在 int decode 阶段失败。

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ test/parity/ # golden tests against TS/official behavior
331331
- 本轮补充:interaction script resize/terminalSize/screenSize action payload 现在递归解包 `value`/`payload`/`data`/`resource`/`attributes`/`properties`/`attrs`/`edge.node` 等 wrapper,官方/API fixture 可把 columns/rows 放在 JSON:API 或 GraphQL envelope 内。
332332
- 本轮补充:interaction script 的 direct resize 数字 alias 字段现在也递归解包 wrapper;`resizeWidth`/`resizeHeight``screenWidth`/`screenHeight` 和 terminal width/height 相邻别名可从 wrapped `value``columns``rows` 中恢复尺寸。
333333
- 本轮补充:interaction script 的 direct focus bool alias 字段现在也递归解包 wrapper;`focus``focused``focusIn``focusOut``blur`/`blurred` 可从 wrapped `enabled``value``selected` 等字段恢复焦点事件控制。
334+
- 本轮补充:interaction script 的 focus/blur action-discriminator 现在也接受 `value`/`payload`/`data` 中的 wrapped bool;`action:"focus"``kind:"blur"``operation:"focusState"``name:"setFocus"` 可用 `focused:false``blurred:false` 或非严格 bool payload 明确发出 focus-out/focus-in。
334335
- 本轮补充:interaction script 的 direct expectation bool alias 字段现在也递归解包 wrapper;`expectNoEvent``expectNoDialogResult(s)``expectFocused` 可从 wrapped `value`/`enabled`/`selected` 恢复断言控制。
335336
- 本轮补充:interaction script 的 direct expectation count alias 字段现在也递归解包 wrapper;`expectEventCount``expectTotalEventCount``expectDialogResultCount``expectTotalDialogResultCount` 可从 wrapped `value`/`count`/`total` 恢复计数断言。
336337
- 本轮补充:interaction script 的 direct expectation string-list alias 字段现在也递归解包 wrapper;`expectStatusContains`/`NotContains``expectSnapshotContains`/`NotContains` 可从 wrapped `value`/`values`/`contains`/`items` 恢复断言列表。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ M7 progress now includes:
310310
- `internal/tui`: direct scripted string alias fields such as `text`, `pasteText`, `setStatus`, and `snapshotName` now accept JSON:API/GraphQL-style wrapper objects without failing strong scalar decoding.
311311
- `internal/tui`: direct scripted resize aliases such as `resizeWidth`/`resizeHeight` and `screenWidth`/`screenHeight` now recursively unwrap numeric JSON:API/GraphQL-style wrapper objects.
312312
- `internal/tui`: direct scripted focus aliases such as `focus`, `focused`, `focusIn`, `focusOut`, and `blurred` now recursively unwrap boolean JSON:API/GraphQL-style wrapper objects.
313+
- `internal/tui`: scripted focus/blur action discriminators now honor wrapped boolean payloads such as `payload.focused:false`, `payload.blurred:false`, `data.focus:false`, and non-strict string booleans for `action:"focus"`, `kind:"blur"`, `operation:"focusState"`, and `name:"setFocus"`.
313314
- `internal/tui`: direct scripted expectation bool aliases such as `expectNoEvent`, `expectNoDialogResult(s)`, and `expectFocused` now recursively unwrap JSON:API/GraphQL-style wrapper objects.
314315
- `internal/tui`: direct scripted expectation count aliases such as `expectEventCount`, `expectTotalEventCount`, `expectDialogResultCount`, and `expectTotalDialogResultCount` now recursively unwrap numeric JSON:API/GraphQL-style wrapper objects.
315316
- `internal/tui`: direct scripted expectation string-list aliases such as `expectStatusContains`, `expectStatusNotContains`, `expectSnapshotContains`, and `expectSnapshotNotContains` now recursively unwrap JSON:API/GraphQL-style wrapper objects.

internal/tui/script_aliases.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,13 +1794,13 @@ func applyScriptStepActionAlias(step *ScriptStep, fields map[string]json.RawMess
17941794
if step.Dialog == nil {
17951795
step.Dialog = scriptDialogActionField(fields)
17961796
}
1797-
case "focus", "focusin", "focus-in":
1797+
case "focus", "focusin", "focus-in", "focused", "setfocus", "set-focus", "focusstate", "focus-state":
17981798
if !scriptStepHasFocusKey(step) {
1799-
step.Keys = append(step.Keys, "focus-in")
1799+
step.Keys = append(step.Keys, scriptFocusKey(scriptActionBoolField(fields, true)))
18001800
}
1801-
case "blur", "focusout", "focus-out":
1801+
case "blur", "focusout", "focus-out", "blurred":
18021802
if !scriptStepHasFocusKey(step) {
1803-
step.Keys = append(step.Keys, "focus-out")
1803+
step.Keys = append(step.Keys, scriptFocusKey(!scriptActionBoolField(fields, true)))
18041804
}
18051805
}
18061806
}
@@ -3151,7 +3151,7 @@ func scriptActionBoolFromJSON(raw json.RawMessage, depth int) (bool, bool) {
31513151
if err := json.Unmarshal(raw, &fields); err != nil {
31523152
return false, false
31533153
}
3154-
for _, name := range scriptRuntimePayloadWrapperNames("enabled", "active", "open", "visible", "checked", "selected", "value") {
3154+
for _, name := range scriptRuntimePayloadWrapperNames("enabled", "active", "open", "visible", "focused", "focus", "blurred", "blur", "checked", "selected", "value") {
31553155
nested, ok := fields[name]
31563156
if !ok {
31573157
continue

internal/tui/tui_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9314,6 +9314,34 @@ func TestRunInteractionScriptAcceptsStepStateAliases(t *testing.T) {
93149314
}
93159315
}
93169316

9317+
func TestRunInteractionScriptAcceptsFocusActionPayloads(t *testing.T) {
9318+
steps, err := ParseInteractionScript([]byte(`[
9319+
{"action": "focus", "payload": {"focused": false}, "expectEvent": {"type": "focus_out"}, "expectFocused": false},
9320+
{"kind": "blur", "payload": {"blurred": false}, "expectEvent": {"type": "focus_in"}, "expectFocused": true},
9321+
{"operation": "focusState", "data": {"focus": false}, "expectEvent": {"type": "focus_out"}, "expectFocused": false},
9322+
{"name": "setFocus", "value": "yes", "expectEvent": {"type": "focus_in"}, "expectFocused": true}
9323+
]`))
9324+
if err != nil {
9325+
t.Fatal(err)
9326+
}
9327+
screen := NewREPLScreen(30, 6, nil)
9328+
result, err := RunInteractionScriptChecked(&screen, steps)
9329+
if err != nil {
9330+
t.Fatal(err)
9331+
}
9332+
if len(result.Events) != 4 {
9333+
t.Fatalf("events = %#v", result.Events)
9334+
}
9335+
for i, want := range []ScreenEventType{ScreenEventFocusOut, ScreenEventFocusIn, ScreenEventFocusOut, ScreenEventFocusIn} {
9336+
if result.Events[i].Type != want {
9337+
t.Fatalf("event %d = %#v, want %s", i, result.Events[i], want)
9338+
}
9339+
}
9340+
if !screen.Focused {
9341+
t.Fatal("screen should end focused")
9342+
}
9343+
}
9344+
93179345
func TestRunInteractionScriptChecksFocusState(t *testing.T) {
93189346
screen := NewREPLScreen(30, 6, nil)
93199347
focused := true

0 commit comments

Comments
 (0)