config: packages,table,selection (3 files)

This commit is contained in:
Richard Ward
2025-12-30 14:15:18 +00:00
parent 3f654ef2a6
commit 52d94f7a02
3 changed files with 256 additions and 18 deletions

View File

@@ -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]
}
]
}

View File

@@ -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)

View File

@@ -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