From 52d94f7a026dbee0855006d2753f6255e32afa85 Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 14:15:18 +0000 Subject: [PATCH] config: packages,table,selection (3 files) --- .../seed/scripts/tests/selection.cases.json | 167 ++++++++++++++++++ .../seed/scripts/tests/selection.test.lua | 71 ++++++++ .../seed/scripts/lua/retro_helpers.lua | 36 ++-- 3 files changed, 256 insertions(+), 18 deletions(-) create mode 100644 packages/data_table/seed/scripts/tests/selection.cases.json create mode 100644 packages/data_table/seed/scripts/tests/selection.test.lua diff --git a/packages/data_table/seed/scripts/tests/selection.cases.json b/packages/data_table/seed/scripts/tests/selection.cases.json new file mode 100644 index 000000000..e7883e8f3 --- /dev/null +++ b/packages/data_table/seed/scripts/tests/selection.cases.json @@ -0,0 +1,167 @@ +{ + "toggleRow": { + "single_mode": [ + { + "desc": "Select first row in single mode", + "initial_selected": {}, + "index": 1, + "expected_selected": { + "1": true + } + }, + { + "desc": "Switch selection in single mode", + "initial_selected": { + "1": true + }, + "index": 2, + "expected_selected": { + "2": true + } + }, + { + "desc": "Deselect same row in single mode", + "initial_selected": { + "1": true + }, + "index": 1, + "expected_selected": {} + }, + { + "desc": "Select row 5 in single mode", + "initial_selected": { + "3": true + }, + "index": 5, + "expected_selected": { + "5": true + } + } + ], + "multiple_mode": [ + { + "desc": "Select first row in multiple mode", + "initial_selected": {}, + "index": 1, + "expected_selected": { + "1": true + } + }, + { + "desc": "Select second row while first selected", + "initial_selected": { + "1": true + }, + "index": 2, + "expected_selected": { + "1": true, + "2": true + } + }, + { + "desc": "Deselect row 1 in multiple mode", + "initial_selected": { + "1": true, + "2": true + }, + "index": 1, + "expected_selected": { + "2": true + } + }, + { + "desc": "Toggle multiple selections", + "initial_selected": { + "1": true, + "3": true, + "5": true + }, + "index": 3, + "expected_selected": { + "1": true, + "5": true + } + }, + { + "desc": "Select non-consecutive rows", + "initial_selected": { + "2": true, + "5": true + }, + "index": 8, + "expected_selected": { + "2": true, + "5": true, + "8": true + } + } + ] + }, + "selectRange": [ + { + "desc": "Select range 1-5", + "initial_selected": {}, + "from_index": 1, + "to_index": 5, + "expected_start": 1, + "expected_end": 5 + }, + { + "desc": "Select reverse range 5-1", + "initial_selected": {}, + "from_index": 5, + "to_index": 1, + "expected_start": 1, + "expected_end": 5 + }, + { + "desc": "Select range 3-7", + "initial_selected": {}, + "from_index": 3, + "to_index": 7, + "expected_start": 3, + "expected_end": 7 + }, + { + "desc": "Extend selection with range", + "initial_selected": { + "1": true, + "2": true + }, + "from_index": 5, + "to_index": 8, + "expected_start": 5, + "expected_end": 8, + "preserve_indices": [1, 2] + }, + { + "desc": "Select single row as range", + "initial_selected": {}, + "from_index": 3, + "to_index": 3, + "expected_start": 3, + "expected_end": 3 + }, + { + "desc": "Select large range 1-20", + "initial_selected": {}, + "from_index": 1, + "to_index": 20, + "expected_start": 1, + "expected_end": 20 + }, + { + "desc": "Overlapping range preserves existing", + "initial_selected": { + "2": true, + "8": true, + "10": true + }, + "from_index": 5, + "to_index": 9, + "expected_start": 5, + "expected_end": 9, + "preserve_indices": [2, 10] + } + ] +} diff --git a/packages/data_table/seed/scripts/tests/selection.test.lua b/packages/data_table/seed/scripts/tests/selection.test.lua new file mode 100644 index 000000000..fc97bf524 --- /dev/null +++ b/packages/data_table/seed/scripts/tests/selection.test.lua @@ -0,0 +1,71 @@ +-- Selection tests +-- Uses lua_test framework with parameterized test cases + +describe("Data Table Selection", function() + local cases = load_cases("selection.cases.json") + local toggle_row = require("selection.toggle_row") + local select_range = require("selection.select_range") + + describe("toggleRow", function() + it_each(cases.toggleRow.single_mode, "$desc", function(tc) + local state = { + selected = tc.initial_selected, + mode = "single" + } + local result = toggle_row.toggleRow(state, tc.index) + expect(result.mode).toBe("single") + expect(result.lastSelected).toBe(tc.index) + + -- Check selected state + for idx, should_be_selected in pairs(tc.expected_selected) do + if should_be_selected then + expect(result.selected[idx]).toBe(true) + else + expect(result.selected[idx]).toBeNil() + end + end + end) + + it_each(cases.toggleRow.multiple_mode, "$desc", function(tc) + local state = { + selected = tc.initial_selected, + mode = "multiple" + } + local result = toggle_row.toggleRow(state, tc.index) + expect(result.mode).toBe("multiple") + expect(result.lastSelected).toBe(tc.index) + + -- Check selected state + for idx, should_be_selected in pairs(tc.expected_selected) do + if should_be_selected then + expect(result.selected[idx]).toBe(true) + else + expect(result.selected[idx]).toBeNil() + end + end + end) + end) + + describe("selectRange", function() + it_each(cases.selectRange, "$desc", function(tc) + local state = { + selected = tc.initial_selected, + mode = "multiple" + } + local result = select_range.selectRange(state, tc.from_index, tc.to_index) + expect(result.lastSelected).toBe(tc.to_index) + + -- Check all expected indices are selected + for idx = tc.expected_start, tc.expected_end do + expect(result.selected[idx]).toBe(true) + end + + -- Check preserved selections + if tc.preserve_indices then + for _, idx in ipairs(tc.preserve_indices) do + expect(result.selected[idx]).toBe(true) + end + end + end) + end) +end) diff --git a/packages/media_center/seed/scripts/lua/retro_helpers.lua b/packages/media_center/seed/scripts/lua/retro_helpers.lua index c82dd96e5..bf752a866 100644 --- a/packages/media_center/seed/scripts/lua/retro_helpers.lua +++ b/packages/media_center/seed/scripts/lua/retro_helpers.lua @@ -622,35 +622,35 @@ end -- Speed control ---- Set game speed multiplier ---- @param session_id string ---- @param speed number Speed multiplier (0.25 to 4.0) +---Set game speed multiplier +---@param session_id string Session identifier +---@param speed number Speed multiplier (0.25 to 4.0) function retro_helpers.set_speed(session_id, speed) http.patch("/api/v1/retro/sessions/" .. session_id, { speed = math.max(0.25, math.min(4.0, speed)) }) end ---- Toggle fast forward ---- @param session_id string ---- @param enabled boolean +---Toggle fast forward +---@param session_id string Session identifier +---@param enabled boolean True to enable, false to disable function retro_helpers.set_fast_forward(session_id, enabled) http.patch("/api/v1/retro/sessions/" .. session_id, { fast_forward = enabled }) end ---- Advance single frame (when paused) ---- @param session_id string +---Advance single frame (when paused) +---@param session_id string Session identifier function retro_helpers.frame_advance(session_id) http.post("/api/v1/retro/sessions/" .. session_id .. "/frame-advance") end -- Screenshots and recording ---- Take a screenshot ---- @param session_id string ---- @return string|nil path Path to screenshot +---Take a screenshot +---@param session_id string Session identifier +---@return string|nil path Path to screenshot or nil if failed function retro_helpers.take_screenshot(session_id) local response = http.post("/api/v1/retro/sessions/" .. session_id .. "/screenshot") if response.status == 201 then @@ -659,10 +659,10 @@ function retro_helpers.take_screenshot(session_id) return nil end ---- Start recording gameplay ---- @param session_id string ---- @param output_path string Where to save the recording ---- @return boolean success +---Start recording gameplay +---@param session_id string Session identifier +---@param output_path string Where to save the recording +---@return boolean success Whether recording started successfully function retro_helpers.start_recording(session_id, output_path) local response = http.post("/api/v1/retro/sessions/" .. session_id .. "/recording/start", { output_path = output_path @@ -670,9 +670,9 @@ function retro_helpers.start_recording(session_id, output_path) return response.status == 200 end ---- Stop recording ---- @param session_id string ---- @return string|nil path Path to recording +---Stop recording +---@param session_id string Session identifier +---@return string|nil path Path to recording or nil if failed function retro_helpers.stop_recording(session_id) local response = http.post("/api/v1/retro/sessions/" .. session_id .. "/recording/stop") if response.status == 200 then