Skip to content

Commit ec71ed6

Browse files
mcagnionclaude
andauthored
Guard Trader result dropdown tooltip against stale state (#9742)
* fix(trade): guard nil sortedResultTbl in dropdown tooltipFunc The nil guard lost during the vaisest/trader-improvements merge caused a crash when hovering the result dropdown after clearing search results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(trade): cover stale result dropdown tooltip guards * style(spec): use tab indentation in TradeQuery test --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 12ea1a4 commit ec71ed6

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
describe("TradeQuery", function()
2+
describe("result dropdown tooltipFunc", function()
3+
-- Builds a TradeQuery with the strict minimum needed for
4+
-- PriceItemRowDisplay to construct row 1 without exploding. Only the
5+
-- two itemsTab subtables read by the slot lookup at the top of
6+
-- PriceItemRowDisplay need to be created here; everything else either
7+
-- lives behind a callback we never trigger, or is already initialized
8+
-- by the TradeQuery constructor.
9+
local function newTradeQuery(state)
10+
local tq = new("TradeQuery", { itemsTab = {} })
11+
tq.itemsTab.activeItemSet = {}
12+
tq.itemsTab.slots = {}
13+
tq.slotTables[1] = { slotName = "Ring 1" }
14+
if state.resultTbl then tq.resultTbl = state.resultTbl end
15+
if state.sortedResultTbl then tq.sortedResultTbl = state.sortedResultTbl end
16+
return tq
17+
end
18+
19+
-- Builds row 1 of the trader UI and returns the dropdown that owns the
20+
-- tooltipFunc we want to exercise.
21+
local function buildRow1Dropdown(tq)
22+
tq:PriceItemRowDisplay(1, nil, 0, 20)
23+
return tq.controls.resultDropdown1
24+
end
25+
26+
it("returns early when sortedResultTbl[row_idx] is missing", function()
27+
-- No sorted results at all -> first guard must short-circuit.
28+
local tq = newTradeQuery({})
29+
local dropdown = buildRow1Dropdown(tq)
30+
local tooltip = new("Tooltip")
31+
32+
assert.has_no.errors(function()
33+
dropdown.tooltipFunc(tooltip, "DROP", 1, nil)
34+
end)
35+
assert.are.equal(0, #tooltip.lines)
36+
end)
37+
38+
it("returns early when the backing result entry has been cleared", function()
39+
-- The dropdown must be built against a valid result so that
40+
-- PriceItemRowDisplay's construction loop succeeds; we wipe
41+
-- resultTbl[1] only afterwards, to simulate a stale tooltip
42+
-- callback firing after the results were invalidated.
43+
local tq = newTradeQuery({
44+
resultTbl = { [1] = { [1] = { item_string = "Rarity: RARE\nBehemoth Hold\nGold Ring" } } },
45+
sortedResultTbl = { [1] = { { index = 1 } } },
46+
})
47+
local dropdown = buildRow1Dropdown(tq)
48+
tq.resultTbl[1] = {}
49+
local tooltip = new("Tooltip")
50+
51+
assert.has_no.errors(function()
52+
dropdown.tooltipFunc(tooltip, "DROP", 1, nil)
53+
end)
54+
assert.are.equal(0, #tooltip.lines)
55+
end)
56+
end)
57+
end)

src/Classes/TradeQuery.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,8 +1093,15 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro
10931093
end
10941094
end
10951095
controls["resultDropdown"..row_idx].tooltipFunc = function(tooltip, dropdown_mode, dropdown_index, dropdown_display_string)
1096-
local pb_index = self.sortedResultTbl[row_idx][dropdown_index].index
1097-
local result = self.resultTbl[row_idx][pb_index]
1096+
local sortedRow = self.sortedResultTbl[row_idx]
1097+
if not sortedRow or not sortedRow[dropdown_index] then
1098+
return
1099+
end
1100+
local pb_index = sortedRow[dropdown_index].index
1101+
local result = self.resultTbl[row_idx] and self.resultTbl[row_idx][pb_index]
1102+
if not result then
1103+
return
1104+
end
10981105
local item = new("Item", result.item_string)
10991106
tooltip:Clear()
11001107
if slotTbl.slotName == "Watcher's Eye" then

0 commit comments

Comments
 (0)