Skip to content

Commit a063fa4

Browse files
authored
feat: add hook and media ready expression context (#32)
1 parent eb2ddc5 commit a063fa4

4 files changed

Lines changed: 67 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.claude/
22
CLAUDE.md
3+
.pi/
34

45
# Test and coverage
56
coverage.out

exprenv_test.go

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@ func TestArgExprEnv_JSONSerialization(t *testing.T) {
3030
t.Parallel()
3131

3232
env := zapscript.ArgExprEnv{
33-
Platform: "mister",
34-
Version: "2.0.0",
35-
ScanMode: "hold",
33+
Platform: "mister",
34+
Version: "2.0.0",
35+
ScanMode: "hold",
36+
MediaPlaying: true,
37+
MediaReady: true,
38+
Hook: zapscript.ExprEnvHook{
39+
Name: "startup",
40+
FirstBootStart: true,
41+
},
3642
Device: zapscript.ExprEnvDevice{
3743
Hostname: "mister",
3844
OS: "linux",
@@ -43,7 +49,6 @@ func TestArgExprEnv_JSONSerialization(t *testing.T) {
4349
Value: "**launch:snes/mario",
4450
Data: "extra-data",
4551
},
46-
MediaPlaying: true,
4752
ActiveMedia: zapscript.ExprEnvActiveMedia{
4853
LauncherID: "retroarch",
4954
SystemID: "snes",
@@ -63,6 +68,9 @@ func TestArgExprEnv_JSONSerialization(t *testing.T) {
6368
assert.Contains(t, jsonStr, `"version"`, "should contain version field")
6469
assert.Contains(t, jsonStr, `"scan_mode"`, "should contain scan_mode field")
6570
assert.Contains(t, jsonStr, `"media_playing"`, "should contain media_playing field")
71+
assert.Contains(t, jsonStr, `"media_ready"`, "should contain media_ready field")
72+
assert.Contains(t, jsonStr, `"hook"`, "should contain hook field")
73+
assert.Contains(t, jsonStr, `"first_boot_start"`, "should contain first_boot_start field")
6674
assert.Contains(t, jsonStr, `"active_media"`, "should contain active_media field")
6775
assert.Contains(t, jsonStr, `"last_scanned"`, "should contain last_scanned field")
6876
assert.Contains(t, jsonStr, `"launcher_id"`, "should contain launcher_id field")
@@ -85,6 +93,11 @@ func TestArgExprEnv_JSONRoundTrip(t *testing.T) {
8593
Version: "1.0.0",
8694
ScanMode: "tap",
8795
MediaPlaying: true,
96+
MediaReady: true,
97+
Hook: zapscript.ExprEnvHook{
98+
Name: "startup",
99+
FirstBootStart: true,
100+
},
88101
Device: zapscript.ExprEnvDevice{
89102
Hostname: "testhost",
90103
OS: "linux",
@@ -115,6 +128,9 @@ func TestArgExprEnv_JSONRoundTrip(t *testing.T) {
115128
assert.Equal(t, original.Version, decoded.Version)
116129
assert.Equal(t, original.ScanMode, decoded.ScanMode)
117130
assert.Equal(t, original.MediaPlaying, decoded.MediaPlaying)
131+
assert.Equal(t, original.MediaReady, decoded.MediaReady)
132+
assert.Equal(t, original.Hook.Name, decoded.Hook.Name)
133+
assert.Equal(t, original.Hook.FirstBootStart, decoded.Hook.FirstBootStart)
118134
assert.Equal(t, original.Device.Hostname, decoded.Device.Hostname)
119135
assert.Equal(t, original.LastScanned.ID, decoded.LastScanned.ID)
120136
assert.Equal(t, original.ActiveMedia.Path, decoded.ActiveMedia.Path)
@@ -158,6 +174,22 @@ func TestExprEnvLaunching_JSONSerialization(t *testing.T) {
158174
assert.Contains(t, jsonStr, `"launcher_id"`)
159175
}
160176

177+
func TestExprEnvHook_JSONSerialization(t *testing.T) {
178+
t.Parallel()
179+
180+
hook := zapscript.ExprEnvHook{
181+
Name: "startup",
182+
FirstBootStart: true,
183+
}
184+
185+
jsonBytes, err := json.Marshal(hook)
186+
require.NoError(t, err)
187+
188+
jsonStr := string(jsonBytes)
189+
assert.Contains(t, jsonStr, `"name"`)
190+
assert.Contains(t, jsonStr, `"first_boot_start"`)
191+
}
192+
161193
// TestArgExprEnv_EmptyFieldsSerialization verifies that empty struct fields are serialized
162194
// (no omitempty behavior) for consistent JSON structure in external scripts.
163195
func TestArgExprEnv_EmptyFieldsSerialization(t *testing.T) {

expressions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ type ExprEnvLaunching struct {
6161
LauncherID string `expr:"launcher_id" json:"launcher_id"`
6262
}
6363

64+
// ExprEnvHook represents hook context for expression evaluation.
65+
//
66+
//nolint:tagliatelle // JSON uses snake_case to match expression env naming
67+
type ExprEnvHook struct {
68+
Name string `expr:"name" json:"name"`
69+
FirstBootStart bool `expr:"first_boot_start" json:"first_boot_start"`
70+
}
71+
6472
//nolint:tagliatelle // JSON uses snake_case to match expression env naming
6573
type ArgExprEnv struct {
6674
ActiveMedia ExprEnvActiveMedia `expr:"active_media" json:"active_media"`
@@ -71,7 +79,9 @@ type ArgExprEnv struct {
7179
Platform string `expr:"platform" json:"platform"`
7280
Version string `expr:"version" json:"version"`
7381
ScanMode string `expr:"scan_mode" json:"scan_mode"`
82+
Hook ExprEnvHook `expr:"hook" json:"hook,omitempty"`
7483
MediaPlaying bool `expr:"media_playing" json:"media_playing"`
84+
MediaReady bool `expr:"media_ready" json:"media_ready"`
7585
}
7686

7787
//nolint:tagliatelle // JSON uses snake_case to match expression env naming

parser_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,21 @@ func TestPostProcess(t *testing.T) {
398398
input: "something " + zapscript.TokExpStart + "true" + zapscript.TokExprEnd,
399399
want: `something true`,
400400
},
401+
{
402+
name: "test expression hook name",
403+
input: zapscript.TokExpStart + "hook.name" + zapscript.TokExprEnd,
404+
want: `startup`,
405+
},
406+
{
407+
name: "test expression hook first boot start",
408+
input: zapscript.TokExpStart + "hook.first_boot_start" + zapscript.TokExprEnd,
409+
want: `true`,
410+
},
411+
{
412+
name: "test expression media ready",
413+
input: zapscript.TokExpStart + "media_ready" + zapscript.TokExprEnd,
414+
want: `true`,
415+
},
401416
{
402417
name: "bad return type",
403418
input: zapscript.TokExpStart + "device" + zapscript.TokExprEnd,
@@ -422,7 +437,12 @@ func TestPostProcess(t *testing.T) {
422437
Platform: "mister",
423438
Version: "1.2.3",
424439
MediaPlaying: true,
440+
MediaReady: true,
425441
ScanMode: "tap",
442+
Hook: zapscript.ExprEnvHook{
443+
Name: "startup",
444+
FirstBootStart: true,
445+
},
426446
Device: zapscript.ExprEnvDevice{
427447
Hostname: "test-device",
428448
OS: "linux",

0 commit comments

Comments
 (0)