Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Template for new versions:
- `3dveins`: fix failure on embarks that cross midmap tiles
- `aquifer`: make ``--skip-top`` and top-relative ``--levels`` take effect for the ``drain``, ``convert``, and ``add`` actions instead of being silently ignored
- `autodump`: ``destroy`` no longer leaves the contents of destroyed containers in limbo or crashes when destroying unit-held items
- `sort`: fix justice filters applying to the hidden "Open cases" unit list when the "Cold cases" tab is active
- `timestream`: deal properly with units who have breathing difficulties

## Misc Improvements
Expand Down
12 changes: 9 additions & 3 deletions plugins/lua/sort/info.lua
Original file line number Diff line number Diff line change
Expand Up @@ -611,12 +611,18 @@ end

local function get_unit_list(which)
local tabs = dfhack.gui.getWidget(justice, 'Tabs')
return dfhack.gui.getWidget(tabs, 'Open cases', 'Right panel', which) or
dfhack.gui.getWidget(tabs, 'Cold cases', 'Right panel', which)
for _,tab in ipairs(dfhack.gui.getWidgetChildren(tabs)) do
if tab.flag.VISIBILITY_VISIBLE then
return dfhack.gui.getWidget(tab, 'Right panel', which)
end
end
end

local function poke_list(which)
get_unit_list(which).sort_flags.NEEDS_RESORTED = true
local list = get_unit_list(which)
if list then
list.sort_flags.NEEDS_RESORTED = true
end
end

JusticeOverlay = defclass(JusticeOverlay, overlay.OverlayWidget)
Expand Down
111 changes: 111 additions & 0 deletions test/plugins/sort.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
config.mode = 'fortress'
config.target = 'sort'

local info = require('plugins.sort.info')
local sort = require('plugins.sort')

local overlay_widgets = package.loaded['plugins.overlay']

local mocked_tabs

local function make_list()
return {sort_flags={NEEDS_RESORTED=false}}
end

local function make_tab(visible)
local lists = {
Interrogate=make_list(),
Convict=make_list(),
}
return {
flag={VISIBILITY_VISIBLE=visible},
children_by_name={
['Right panel']={children_by_name=lists},
},
}, lists
end

local function make_widget_tree(cold_visible)
local open_tab, open_lists = make_tab(not cold_visible)
local cold_tab, cold_lists = make_tab(cold_visible)
mocked_tabs = {
children={open_tab, cold_tab},
children_by_name={
['Open cases']=open_tab,
['Cold cases']=cold_tab,
},
}
return open_lists, cold_lists
end

local function get_widget(parent, ...)
local widget = parent
for _,key in ipairs{...} do
if type(widget) == 'table' then
widget = widget.children_by_name[key]
else
-- real df container: only the top-level justice Tabs lookup is mocked
widget = key == 'Tabs' and mocked_tabs or nil
end
if widget == nil then return nil end
end
return widget
end

local function get_widget_children(container)
return type(container) == 'table' and container.children or {}
end

local function with_mocks(fn, extra_patches)
local patches = {
{dfhack.gui, 'getWidget', get_widget},
{dfhack.gui, 'getWidgetChildren', get_widget_children},
{info, 'interrogate_instance', info.interrogate_instance},
{info, 'convict_instance', info.convict_instance},
}
for _,patch in ipairs(extra_patches or {}) do
table.insert(patches, patch)
end
mock.patch(patches, fn)
end

function test.justice_filter_pokes_visible_cold_cases_list()
local open_lists, cold_lists = make_widget_tree(true)
with_mocks(function()
info.InterrogationOverlay{}.subviews.subset.on_change()
end)
expect.false_(open_lists.Interrogate.sort_flags.NEEDS_RESORTED)
expect.true_(cold_lists.Interrogate.sort_flags.NEEDS_RESORTED)
end

function test.justice_filter_pokes_visible_open_cases_list()
local open_lists, cold_lists = make_widget_tree(false)
with_mocks(function()
info.InterrogationOverlay{}.subviews.subset.on_change()
end)
expect.true_(open_lists.Interrogate.sort_flags.NEEDS_RESORTED)
expect.false_(cold_lists.Interrogate.sort_flags.NEEDS_RESORTED)
end

function test.justice_conviction_pokes_visible_cold_cases_list()
local open_lists, cold_lists = make_widget_tree(true)
with_mocks(function()
info.ConvictionOverlay{}.subviews.subset.on_change()
end)
expect.false_(open_lists.Convict.sort_flags.NEEDS_RESORTED)
expect.true_(cold_lists.Convict.sort_flags.NEEDS_RESORTED)
end

function test.justice_filter_installed_on_visible_list()
local _, cold_lists = make_widget_tree(true)
local passed_list
local set_filter = mock.observe_func(function(list) passed_list = list end)
with_mocks(function()
info.InterrogationOverlay{}:render()
end, {
{sort, 'sort_set_justice_filter_fn', set_filter},
{overlay_widgets.OverlayWidget, 'render', mock.func()},
})
expect.eq(1, set_filter.call_count)
expect.eq(cold_lists.Interrogate, passed_list)
end
Loading