Merge branch 'tooltip-ascensiondb-precedence' into questie-learner-comms-improvements
This commit is contained in:
@@ -237,7 +237,8 @@ end
|
||||
---@param questLogIndex number
|
||||
---@param questId number
|
||||
function _QuestEventHandler:QuestAccepted(questLogIndex, questId)
|
||||
questId = questId or select(8, GetQuestLogTitle(questLogIndex))
|
||||
local _, _, _, _, _, _, _, questLogQuestId = GetQuestLogTitle(questLogIndex)
|
||||
questId = questId or questLogQuestId
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_ACCEPTED", questLogIndex, questId)
|
||||
|
||||
if questLog[questId] and questLog[questId].timer then
|
||||
|
||||
@@ -40,6 +40,10 @@ local function IsAscensionProtected(dbType, id, key)
|
||||
return protected and protected[key] == true
|
||||
end
|
||||
|
||||
local function HasAscensionQuestObjectiveData(questId)
|
||||
return IsAscensionProtected("QUEST", questId, 10)
|
||||
end
|
||||
|
||||
local function NormalizeSpawnZoneKey(zoneKey)
|
||||
-- Convert raw area IDs (e.g. 3431 from GetAreaID()) to the canonical map IDs
|
||||
-- used by AscensionDB and the rendering system (e.g. 1241 for Sunstrider Isle).
|
||||
@@ -1721,7 +1725,7 @@ function QuestieLearner:LearnQuestObjectiveNPC(questId, npcId, objText, objectiv
|
||||
-- 3. Register with tooltip system immediately. Preserve the objective icon so
|
||||
-- nameplates can render the correct learned slay/loot/talk marker.
|
||||
local QuestieTooltips = QuestieLoader:ImportModule("QuestieTooltips")
|
||||
if QuestieTooltips and QuestieTooltips.RegisterObjectiveTooltip then
|
||||
if QuestieTooltips and QuestieTooltips.RegisterObjectiveTooltip and not HasAscensionQuestObjectiveData(questId) then
|
||||
local objectiveIcon
|
||||
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
|
||||
local objectives = QuestLogCache and QuestLogCache.GetQuestObjectives and QuestLogCache.GetQuestObjectives(questId)
|
||||
|
||||
@@ -120,7 +120,8 @@ function QuestiePlayer:GetCurrentZoneId()
|
||||
return uiMapId
|
||||
end
|
||||
|
||||
return ZoneDB.instanceIdToUiMapId[select(8, GetInstanceInfo())]
|
||||
local _, _, _, _, _, _, _, instanceMapID = GetInstanceInfo()
|
||||
return ZoneDB.instanceIdToUiMapId[instanceMapID]
|
||||
end
|
||||
|
||||
function QuestiePlayer:GetCurrentUiMapId()
|
||||
@@ -129,7 +130,8 @@ function QuestiePlayer:GetCurrentUiMapId()
|
||||
if uiMapId then
|
||||
return uiMapId
|
||||
end
|
||||
return ZoneDB.instanceIdToUiMapId[select(8, GetInstanceInfo())]
|
||||
local _, _, _, _, _, _, _, instanceMapID = GetInstanceInfo()
|
||||
return ZoneDB.instanceIdToUiMapId[instanceMapID]
|
||||
end
|
||||
|
||||
---@return number
|
||||
|
||||
@@ -43,6 +43,31 @@ local _tooltipLastText = ""
|
||||
|
||||
local _InitObjectiveTexts
|
||||
|
||||
local function _GetQuestObjectiveSummary(questId)
|
||||
if not QuestieDB or not QuestieDB.GetQuest then
|
||||
return nil
|
||||
end
|
||||
|
||||
local quest = QuestieDB:GetQuest(questId)
|
||||
if not quest or not quest.ObjectiveData then
|
||||
return nil
|
||||
end
|
||||
|
||||
local summary = {}
|
||||
for _, objective in ipairs(quest.ObjectiveData) do
|
||||
local text = objective and (objective.Text or objective.Description)
|
||||
if type(text) == "string" and text ~= "" then
|
||||
tinsert(summary, text)
|
||||
end
|
||||
end
|
||||
|
||||
if table.getn(summary) == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return summary
|
||||
end
|
||||
|
||||
---@param questId number
|
||||
---@param key string monster: m_, items: i_, objects: o_ + string name of the objective
|
||||
---@param objective table
|
||||
@@ -205,7 +230,7 @@ function QuestieTooltips:GetTooltip(key)
|
||||
return nil
|
||||
end
|
||||
|
||||
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
|
||||
if (QuestiePlayer.numberOfGroupMembers or 0) > MAX_GROUP_MEMBER_COUNT then
|
||||
return nil -- temporary disable tooltips in raids, we should make a proper fix
|
||||
end
|
||||
|
||||
@@ -345,11 +370,27 @@ elseif key:sub(1,2) == "o_" then
|
||||
|
||||
if QuestieTooltips.lookupByKey[key] then
|
||||
local playerName = UnitName("player")
|
||||
local hasObjectiveEntries = false
|
||||
for _, tooltip in next, QuestieTooltips.lookupByKey[key] do
|
||||
if not tooltip.name then
|
||||
hasObjectiveEntries = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
for k, tooltip in next, QuestieTooltips.lookupByKey[key] do
|
||||
if tooltip.name then
|
||||
if Questie.db.profile.showQuestsInNpcTooltip then
|
||||
local questString = QuestieLib:GetColoredQuestName(tooltip.questId, Questie.db.profile.enableTooltipsQuestLevel, true, true)
|
||||
tinsert(tooltipLines, questString)
|
||||
if not hasObjectiveEntries then
|
||||
local objectiveSummary = _GetQuestObjectiveSummary(tooltip.questId)
|
||||
if objectiveSummary then
|
||||
for _, objectiveText in ipairs(objectiveSummary) do
|
||||
tinsert(tooltipLines, " |cFFcbcbcb" .. objectiveText .. "|r")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local objective = tooltip.objective
|
||||
|
||||
@@ -413,7 +413,7 @@ function QuestieTracker.Initialize()
|
||||
for i = 1, questsWatched do
|
||||
local questIndex = GetQuestIndexForWatch(i)
|
||||
if questIndex then
|
||||
local questId = select(8, GetQuestLogTitle(questIndex))
|
||||
local _, _, _, _, _, _, _, questId = GetQuestLogTitle(questIndex)
|
||||
if questId then
|
||||
tempQuestIDs[i] = questId
|
||||
end
|
||||
@@ -2277,7 +2277,7 @@ function QuestieTracker:HookBaseTracker()
|
||||
|
||||
-- Intercept and return a Questie boolean value
|
||||
IsQuestWatched = function(index)
|
||||
local questId = select(8, GetQuestLogTitle(index))
|
||||
local _, _, _, _, _, _, _, questId = GetQuestLogTitle(index)
|
||||
if questId == 0 then
|
||||
-- When an objective progresses in TBC "index" is the questId, but when a quest is manually added to the quest watch
|
||||
-- (e.g. shift clicking it in the quest log) "index" is the questLogIndex.
|
||||
|
||||
@@ -197,10 +197,21 @@ describe("Audit Pass 9 - file-by-file findings (snapshot at HEAD)", function()
|
||||
assert.is_true(has(d, "if(dbItem and dbItem.name and (not dbItem.Hidden)) then"))
|
||||
end)
|
||||
|
||||
it("[N5] select(8, GetInstanceInfo()) left in QuestiePlayer (5.0 rewrite unfinished)", function()
|
||||
assert.is_true(has(read("Modules/QuestiePlayer.lua"), "select(8, GetInstanceInfo())"))
|
||||
-- QuestieLearner was rewritten away from it:
|
||||
assert.is_true(has(read("Modules/QuestieLearner.lua"), "Lua 5.0 compat"))
|
||||
it("[N5] explicit unpack replaced select(8, ...) in live quest/instance lookups", function()
|
||||
local player = read("Modules/QuestiePlayer.lua")
|
||||
local handler = read("Modules/Quest/QuestEventHandler.lua")
|
||||
local tracker = read("Modules/Tracker/QuestieTracker.lua")
|
||||
|
||||
assert.is_true(has(player, "local _, _, _, _, _, _, _, instanceMapID = GetInstanceInfo()"))
|
||||
assert.is_false(has(player, "select(8, GetInstanceInfo())"))
|
||||
|
||||
assert.is_true(has(handler, "local _, _, _, _, _, _, _, questLogQuestId = GetQuestLogTitle(questLogIndex)"))
|
||||
assert.is_false(has(handler, "select(8, GetQuestLogTitle(questLogIndex))"))
|
||||
|
||||
assert.is_true(has(tracker, "local _, _, _, _, _, _, _, questId = GetQuestLogTitle(questIndex)"))
|
||||
assert.is_true(has(tracker, "local _, _, _, _, _, _, _, questId = GetQuestLogTitle(index)"))
|
||||
assert.is_false(has(tracker, "select(8, GetQuestLogTitle(questIndex))"))
|
||||
assert.is_false(has(tracker, "select(8, GetQuestLogTitle(index))"))
|
||||
end)
|
||||
|
||||
it("[9.1->11.1] CORRECTED: % modulo IS used (the 'avoided' claim was wrong)", function()
|
||||
|
||||
@@ -0,0 +1,618 @@
|
||||
describe("QuestieLearner kill-path batching", function()
|
||||
local queuedTimers
|
||||
local broadcasts
|
||||
local QuestieLearner
|
||||
|
||||
before_each(function()
|
||||
dofile("Tests/wow_api_mock.lua")
|
||||
|
||||
queuedTimers = {}
|
||||
broadcasts = {}
|
||||
QuestieCompat.C_Timer.After = function(_, fn)
|
||||
queuedTimers[table.getn(queuedTimers) + 1] = fn
|
||||
end
|
||||
|
||||
local originalImportModule = QuestieLoader.ImportModule
|
||||
QuestieLoader.ImportModule = function(self, name)
|
||||
if name == "QuestieLearnerComms" then
|
||||
return {
|
||||
BroadcastLearnedData = function(_, op, typ, id, data)
|
||||
broadcasts[table.getn(broadcasts) + 1] = {
|
||||
op = op,
|
||||
typ = typ,
|
||||
id = id,
|
||||
data = data,
|
||||
}
|
||||
end,
|
||||
}
|
||||
end
|
||||
return originalImportModule(self, name)
|
||||
end
|
||||
|
||||
Questie.dbLearner.global.settings.enabled = true
|
||||
Questie.dbLearner.global.settings.learnNpcs = true
|
||||
Questie.dbLearner.global.settings.learnQuests = true
|
||||
Questie.dbLearner.global.settings.learnItems = true
|
||||
Questie.dbLearner.global.settings.learnObjects = true
|
||||
Questie.dbLearner.global.settings.minConfidencePins = 1
|
||||
Questie.dbLearner.global.npcs = {}
|
||||
Questie.dbLearner.global.quests = {}
|
||||
Questie.dbLearner.global.items = {}
|
||||
Questie.dbLearner.global.objects = {}
|
||||
QuestieDB.npcDataOverrides = {}
|
||||
QuestieDB.questDataOverrides = {}
|
||||
QuestieDB.itemDataOverrides = {}
|
||||
QuestieDB.objectDataOverrides = {}
|
||||
QuestieDB.private = {
|
||||
npcCache = {
|
||||
[1001] = { name = "Cached Boar" },
|
||||
},
|
||||
}
|
||||
QuestiePlayer.currentQuestlog = {}
|
||||
|
||||
QuestieLearner = dofile("Modules/QuestieLearner.lua")
|
||||
end)
|
||||
|
||||
it("coalesces repeated NPC live updates instead of invalidating DB cache per kill", function()
|
||||
QuestieLearner:LearnNPC(1001, "Laggy Boar", nil, nil, nil, nil, 41.25, 52.5, 44)
|
||||
QuestieLearner:LearnNPC(1001, "Laggy Boar", nil, nil, nil, nil, 41.35, 52.6, 44)
|
||||
|
||||
assert.is_nil(QuestieDB.npcDataOverrides[1001])
|
||||
assert.is_table(QuestieDB.private.npcCache[1001])
|
||||
assert.equals(2, table.getn(queuedTimers))
|
||||
|
||||
queuedTimers[1]()
|
||||
|
||||
assert.is_table(QuestieDB.npcDataOverrides[1001])
|
||||
assert.is_nil(QuestieDB.private.npcCache[1001])
|
||||
assert.is_table(QuestieDB.npcDataOverrides[1001][7])
|
||||
|
||||
local flushedSpawnCount = table.getn(QuestieDB.npcDataOverrides[1001][7][44])
|
||||
|
||||
QuestieLearner:LearnNPC(1001, "Laggy Boar", nil, nil, nil, nil, 80.0, 80.0, 44)
|
||||
|
||||
assert.equals(flushedSpawnCount, table.getn(QuestieDB.npcDataOverrides[1001][7][44]))
|
||||
assert.equals(3, table.getn(queuedTimers))
|
||||
end)
|
||||
|
||||
it("coalesces repeated quest-pin refreshes into one flush", function()
|
||||
local updateCount = 0
|
||||
local originalUpdateQuest = QuestieQuest.UpdateQuest
|
||||
QuestieQuest.UpdateQuest = function(_, questId)
|
||||
updateCount = updateCount + 1
|
||||
end
|
||||
|
||||
QuestiePlayer.currentQuestlog = { [5001] = true }
|
||||
Questie.dbLearner.global.quests = {}
|
||||
QuestieDB.questDataOverrides = {}
|
||||
|
||||
QuestieLearner:LearnQuestObjectiveNPC(5001, 7001, "Pin Boar slain", 1)
|
||||
QuestieLearner:LearnQuestObjectiveNPC(5001, 7001, "Pin Boar slain", 1)
|
||||
|
||||
assert.is_true(table.getn(queuedTimers) >= 1)
|
||||
|
||||
for i = 1, table.getn(queuedTimers) do
|
||||
queuedTimers[i]()
|
||||
end
|
||||
|
||||
assert.equals(1, updateCount)
|
||||
|
||||
QuestieQuest.UpdateQuest = originalUpdateQuest
|
||||
end)
|
||||
|
||||
it("suppresses an already queued pin refresh after switching to manual mode", function()
|
||||
local updateCount = 0
|
||||
local originalUpdateQuest = QuestieQuest.UpdateQuest
|
||||
QuestieQuest.UpdateQuest = function(_, questId)
|
||||
updateCount = updateCount + 1
|
||||
end
|
||||
|
||||
QuestiePlayer.currentQuestlog = { [5003] = true }
|
||||
Questie.dbLearner.global.quests = {}
|
||||
QuestieDB.questDataOverrides = {}
|
||||
|
||||
QuestieLearner:LearnQuestObjectiveNPC(5003, 7003, "Manual Boar slain", 1)
|
||||
|
||||
assert.is_true(table.getn(queuedTimers) >= 1)
|
||||
|
||||
Questie.dbLearner.global.settings.pinRefreshMode = "manual"
|
||||
queuedTimers[1]()
|
||||
|
||||
assert.equals(0, updateCount)
|
||||
|
||||
QuestieQuest.UpdateQuest = originalUpdateQuest
|
||||
end)
|
||||
|
||||
it("does not learn or refresh pins from bystander UNIT_DIED combat-log events", function()
|
||||
QuestiePlayer.currentQuestlog = { [5002] = true }
|
||||
QuestieDB.GetQuest = function()
|
||||
return {
|
||||
Objectives = {
|
||||
{
|
||||
Id = 7002,
|
||||
Index = 1,
|
||||
spawnList = { [7002] = true },
|
||||
AlreadySpawned = {},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
QuestieLearner:OnCombatLogEvent(
|
||||
1234,
|
||||
"UNIT_DIED",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"Creature-0-0-0-0-7002-0000000001",
|
||||
"Bystander Boar",
|
||||
nil
|
||||
)
|
||||
|
||||
assert.is_nil(Questie.dbLearner.global.npcs[7002])
|
||||
assert.is_nil(QuestieDB.npcDataOverrides[7002])
|
||||
assert.equals(0, table.getn(queuedTimers))
|
||||
end)
|
||||
|
||||
it("still learns and batches local PARTY_KILL combat-log events", function()
|
||||
QuestieLearner:OnCombatLogEvent(
|
||||
1234,
|
||||
"PARTY_KILL",
|
||||
UnitGUID("player"),
|
||||
UnitName("player"),
|
||||
nil,
|
||||
"Creature-0-0-0-0-7003-0000000001",
|
||||
"Tagged Boar",
|
||||
nil
|
||||
)
|
||||
|
||||
assert.is_table(Questie.dbLearner.global.npcs[7003])
|
||||
assert.equals("Tagged Boar", Questie.dbLearner.global.npcs[7003][1])
|
||||
assert.equals(2, table.getn(queuedTimers))
|
||||
end)
|
||||
|
||||
it("cross-links quest giver NPCs and objects learned after the quest without duplicate pin flushes", function()
|
||||
local updateCount = 0
|
||||
local originalUpdateQuest = QuestieQuest.UpdateQuest
|
||||
QuestieQuest.UpdateQuest = function(_, questId)
|
||||
updateCount = updateCount + 1
|
||||
end
|
||||
Questie.db.profile.learnerBroadcast = false
|
||||
QuestiePlayer.currentQuestlog = { [6001] = true }
|
||||
|
||||
QuestieLearner:LearnQuest(6001, {
|
||||
[1] = "Cross Link Givers",
|
||||
[2] = { [1] = { 7101 }, [2] = { 8101 } },
|
||||
[3] = { [1] = { 7102 }, [2] = { 8102 } },
|
||||
})
|
||||
|
||||
queuedTimers = {}
|
||||
|
||||
QuestieLearner:LearnNPC(7101, "Starter Guard", nil, nil, nil, nil, 10, 20, 44)
|
||||
QuestieLearner:LearnNPC(7102, "Finisher Guard", nil, nil, nil, nil, 30, 40, 44)
|
||||
QuestieLearner:LearnObject(8101, "Starter Chest")
|
||||
QuestieLearner:LearnObject(8102, "Finisher Chest")
|
||||
|
||||
assert.same({ 6001 }, Questie.dbLearner.global.npcs[7101][10])
|
||||
assert.same({ 6001 }, Questie.dbLearner.global.npcs[7102][11])
|
||||
assert.same({ 6001 }, Questie.dbLearner.global.objects[8101][2])
|
||||
assert.same({ 6001 }, Questie.dbLearner.global.objects[8102][3])
|
||||
assert.same({ 6001 }, QuestieDB.npcDataOverrides[7101][10])
|
||||
assert.same({ 6001 }, QuestieDB.npcDataOverrides[7102][11])
|
||||
assert.same({ 6001 }, QuestieDB.objectDataOverrides[8101][2])
|
||||
assert.same({ 6001 }, QuestieDB.objectDataOverrides[8102][3])
|
||||
|
||||
for i = 1, table.getn(queuedTimers) do
|
||||
queuedTimers[i]()
|
||||
end
|
||||
|
||||
assert.equals(1, updateCount)
|
||||
|
||||
QuestieQuest.UpdateQuest = originalUpdateQuest
|
||||
end)
|
||||
|
||||
it("cross-links item objective drop NPCs into quest creature objectives", function()
|
||||
Questie.db.profile.learnerBroadcast = false
|
||||
QuestiePlayer.currentQuestlog = { [6002] = true }
|
||||
|
||||
QuestieLearner:LearnQuest(6002, {
|
||||
[1] = "Cross Link Drops",
|
||||
[10] = {
|
||||
[3] = {
|
||||
{ 2201, 0, 1, "Collect one tusk" },
|
||||
},
|
||||
},
|
||||
})
|
||||
QuestieLearner:LearnItem(2201, "Quest Tusk", 1, 1, 12, 0)
|
||||
QuestieLearner:LearnItemDrop(2201, 7201)
|
||||
|
||||
assert.equals(7201, Questie.dbLearner.global.quests[6002][10][1][1][1])
|
||||
assert.equals(7201, QuestieDB.questDataOverrides[6002][10][1][1][1])
|
||||
|
||||
QuestieLearner:LearnItemDrop(2201, 7201)
|
||||
|
||||
assert.equals(1, table.getn(Questie.dbLearner.global.quests[6002][10][1]))
|
||||
assert.equals(1, table.getn(QuestieDB.questDataOverrides[6002][10][1]))
|
||||
end)
|
||||
|
||||
it("defers learner objective tooltip registration to protected AscensionDB quest data", function()
|
||||
Questie.db.profile.learnerBroadcast = false
|
||||
QuestiePlayer.currentQuestlog = {}
|
||||
QuestieDB.ascensionOverrideKeys = {
|
||||
QUEST = {
|
||||
[8334] = {
|
||||
[10] = true,
|
||||
},
|
||||
},
|
||||
}
|
||||
_G._lastRegisteredTooltip = nil
|
||||
|
||||
QuestieLearner:LearnQuestObjectiveNPC(8334, 15271, "Tender slain", 1)
|
||||
|
||||
assert.is_table(Questie.dbLearner.global.quests[8334])
|
||||
assert.is_nil(_G._lastRegisteredTooltip)
|
||||
end)
|
||||
|
||||
it("coalesces repeated learner broadcasts into one latest update", function()
|
||||
QuestieLearner:LearnItem(2001, "Quest Tusk", 1, 1, 12, 0)
|
||||
QuestieLearner:LearnItem(2001, "Quest Tusk", 1, 1, 12, 0)
|
||||
|
||||
assert.equals(0, table.getn(broadcasts))
|
||||
assert.equals(1, table.getn(queuedTimers))
|
||||
|
||||
queuedTimers[1]()
|
||||
|
||||
assert.equals(1, table.getn(broadcasts))
|
||||
assert.equals("NEW", broadcasts[1].op)
|
||||
assert.equals("ITEM", broadcasts[1].typ)
|
||||
assert.equals(2001, broadcasts[1].id)
|
||||
end)
|
||||
|
||||
it("coalesces repeated inbound network merges into one inject pass", function()
|
||||
local injectCount = 0
|
||||
local originalInject = QuestieLearner.InjectLearnedData
|
||||
QuestieLearner.InjectLearnedData = function(self)
|
||||
injectCount = injectCount + 1
|
||||
QuestieLearner.data = Questie.dbLearner.global
|
||||
end
|
||||
|
||||
QuestieLearner:HandleNetworkData("NPC", 3001, { [1] = "Net Boar", [7] = { [44] = { { 11, 22 } } } }, "NEW")
|
||||
QuestieLearner:HandleNetworkData("NPC", 3001, { [1] = "Net Boar", [7] = { [44] = { { 11, 22 }, { 33, 44 } } } }, "UPDATE")
|
||||
|
||||
assert.equals(0, injectCount)
|
||||
assert.equals(1, table.getn(queuedTimers))
|
||||
|
||||
queuedTimers[1]()
|
||||
|
||||
assert.equals(1, injectCount)
|
||||
assert.equals("Net Boar", Questie.dbLearner.global.npcs[3001][1])
|
||||
assert.equals(2, table.getn(Questie.dbLearner.global.npcs[3001][7][44]))
|
||||
|
||||
QuestieLearner.InjectLearnedData = originalInject
|
||||
end)
|
||||
|
||||
it("forwards OnEvent payload arguments to learner handlers", function()
|
||||
local originalCreateFrame = _G.CreateFrame
|
||||
local originalStrsplit = _G.strsplit
|
||||
local createdFrame = nil
|
||||
local captured = {
|
||||
questTurnedIn = nil,
|
||||
questAccepted = nil,
|
||||
combatLog = nil,
|
||||
itemInfoReceived = nil,
|
||||
questTrackingCleared = nil,
|
||||
}
|
||||
|
||||
_G.CreateFrame = function()
|
||||
createdFrame = {
|
||||
RegisterEvent = function() end,
|
||||
SetScript = function(self, scriptName, fn)
|
||||
if scriptName == "OnEvent" then
|
||||
self._onEvent = fn
|
||||
end
|
||||
end,
|
||||
}
|
||||
return createdFrame
|
||||
end
|
||||
_G.strsplit = function(sep, str)
|
||||
local parts = {}
|
||||
local pattern = string.format("([^%s]+)", sep)
|
||||
for part in string.gmatch(str, pattern) do
|
||||
parts[#parts + 1] = part
|
||||
end
|
||||
return unpack(parts)
|
||||
end
|
||||
|
||||
QuestieLearner = dofile("Modules/QuestieLearner.lua")
|
||||
local originalOnQuestTurnedIn = QuestieLearner.OnQuestTurnedIn
|
||||
local originalOnQuestAccepted = QuestieLearner.OnQuestAccepted
|
||||
local originalOnCombatLogEvent = QuestieLearner.OnCombatLogEvent
|
||||
local originalOnGetItemInfoReceived = QuestieLearner.OnGetItemInfoReceived
|
||||
local originalClearQuestObjectiveTracking = QuestieLearner.ClearQuestObjectiveTracking
|
||||
|
||||
QuestieLearner.OnQuestTurnedIn = function(self, questId, npcId, questFlags)
|
||||
captured.questTurnedIn = { questId, npcId, questFlags }
|
||||
end
|
||||
QuestieLearner.OnQuestAccepted = function(self, questId, questGiver)
|
||||
captured.questAccepted = { questId, questGiver }
|
||||
end
|
||||
QuestieLearner.OnCombatLogEvent = function(self, timestamp, eventType, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName)
|
||||
captured.combatLog = { timestamp, eventType, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName }
|
||||
end
|
||||
QuestieLearner.OnGetItemInfoReceived = function(self, itemId)
|
||||
captured.itemInfoReceived = { itemId }
|
||||
end
|
||||
QuestieLearner.ClearQuestObjectiveTracking = function(self, questId)
|
||||
captured.questTrackingCleared = { questId }
|
||||
end
|
||||
|
||||
QuestieLearner:RegisterEvents()
|
||||
|
||||
local frame = createdFrame
|
||||
frame._onEvent(frame, "QUEST_TURNED_IN", 101, 202, 303)
|
||||
frame._onEvent(frame, "QUEST_ACCEPTED", 404, 505)
|
||||
frame._onEvent(frame, "COMBAT_LOG_EVENT_UNFILTERED", 1, "SPELL_DAMAGE", "src-guid", "Src", 2, "dst-guid", "Dst", 4, 777, "Fireball")
|
||||
frame._onEvent(frame, "GET_ITEM_INFO_RECEIVED", 888)
|
||||
frame._onEvent(frame, "QUEST_REMOVED", 999)
|
||||
|
||||
assert.same({ 101, 202, 303 }, captured.questTurnedIn)
|
||||
assert.same({ 404, 505 }, captured.questAccepted)
|
||||
assert.same({ 1, "SPELL_DAMAGE", "src-guid", "Src", 2, "dst-guid", "Dst", 4, 777, "Fireball" }, captured.combatLog)
|
||||
assert.same({ 888 }, captured.itemInfoReceived)
|
||||
assert.same({ 999 }, captured.questTrackingCleared)
|
||||
|
||||
QuestieLearner.OnQuestTurnedIn = originalOnQuestTurnedIn
|
||||
QuestieLearner.OnQuestAccepted = originalOnQuestAccepted
|
||||
QuestieLearner.OnCombatLogEvent = originalOnCombatLogEvent
|
||||
QuestieLearner.OnGetItemInfoReceived = originalOnGetItemInfoReceived
|
||||
QuestieLearner.ClearQuestObjectiveTracking = originalClearQuestObjectiveTracking
|
||||
_G.CreateFrame = originalCreateFrame
|
||||
_G.strsplit = originalStrsplit
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("QuestieLearnerComms queue draining", function()
|
||||
local sentMessages
|
||||
local processedMessages
|
||||
local QuestieLearnerComms
|
||||
local currentTime
|
||||
|
||||
before_each(function()
|
||||
dofile("Tests/wow_api_mock.lua")
|
||||
|
||||
sentMessages = {}
|
||||
processedMessages = {}
|
||||
currentTime = 1000
|
||||
|
||||
local originalImportModule = QuestieLoader.ImportModule
|
||||
QuestieLoader.ImportModule = function(self, name)
|
||||
if name == "QuestieLearner" then
|
||||
return _G.QuestieLearner
|
||||
end
|
||||
return originalImportModule(self, name)
|
||||
end
|
||||
QuestieLoader.CreateModule = function(self, name)
|
||||
_G[name] = { private = {} }
|
||||
return _G[name]
|
||||
end
|
||||
|
||||
_G.LibStub = function(name, silent)
|
||||
if name == "AceComm-3.0" then
|
||||
return { RegisterComm = function() end }
|
||||
elseif name == "LibDeflate" then
|
||||
return {
|
||||
CompressDeflate = function(_, s) return s end,
|
||||
EncodeForPrint = function(_, s) return s end,
|
||||
DecodeForPrint = function(_, s) return s end,
|
||||
DecompressDeflate = function(_, s) return s end,
|
||||
}
|
||||
elseif name == "AceSerializer-3.0" then
|
||||
return {
|
||||
Serialize = function(_, payload)
|
||||
return payload.op .. ":" .. tostring(payload.id)
|
||||
end,
|
||||
Deserialize = function(_, serialized)
|
||||
local op, id = string.match(serialized, "([^:]+):(.+)")
|
||||
return true, {
|
||||
_ver = 2,
|
||||
op = op,
|
||||
typ = "NPC",
|
||||
id = tonumber(id) or id,
|
||||
d = { [1] = "net" },
|
||||
}
|
||||
end,
|
||||
}
|
||||
elseif name == "XXH_Lua_Lib" then
|
||||
return nil
|
||||
elseif name == "HereBeDragonsQuestie-2.0" then
|
||||
return {}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
_G.QuestieLearner = {
|
||||
HandleNetworkData = function(_, typ, id, d, op)
|
||||
processedMessages[table.getn(processedMessages) + 1] = {
|
||||
typ = typ,
|
||||
id = id,
|
||||
op = op,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
_G.GetChannelName = function() return 1 end
|
||||
_G.JoinPermanentChannel = function() end
|
||||
_G.ChatFrame_RemoveChannel = function() end
|
||||
_G.DEFAULT_CHAT_FRAME = { GetID = function() return 1 end }
|
||||
_G.SendChatMessage = function(msg, mode, nilarg, channel)
|
||||
sentMessages[table.getn(sentMessages) + 1] = msg
|
||||
end
|
||||
_G.InCombatLockdown = function() return false end
|
||||
_G.random = function() return 0 end
|
||||
_G.GetTime = function()
|
||||
return currentTime
|
||||
end
|
||||
QuestieCompat.C_Timer.NewTicker = function(delay, fn)
|
||||
return { Cancel = function() end }
|
||||
end
|
||||
|
||||
dofile("Modules/Network/QuestieLearnerComms.lua")
|
||||
QuestieLearnerComms = _G.QuestieLearnerComms
|
||||
QuestieLearnerComms:Initialize()
|
||||
end)
|
||||
|
||||
it("drains outgoing and incoming queues in FIFO order without front-removal", function()
|
||||
QuestieLearnerComms:BroadcastLearnedData("NEW", "NPC", 101, { foo = "a" })
|
||||
QuestieLearnerComms:BroadcastLearnedData("UPDATE", "NPC", 102, { foo = "b" })
|
||||
|
||||
QuestieLearnerComms:OnCommReceived("QuestieLearner", "NEW:201", "CHANNEL", "Alice")
|
||||
QuestieLearnerComms:OnCommReceived("QuestieLearner", "UPDATE:202", "CHANNEL", "Bob")
|
||||
|
||||
QuestieLearnerComms.private:ProcessQueues()
|
||||
currentTime = currentTime + 4
|
||||
QuestieLearnerComms.private:ProcessQueues()
|
||||
currentTime = currentTime + 4
|
||||
QuestieLearnerComms.private:ProcessQueues()
|
||||
|
||||
assert.equals(2, table.getn(sentMessages))
|
||||
assert.equals("NEW:101", sentMessages[1])
|
||||
assert.equals("UPDATE:102", sentMessages[2])
|
||||
assert.equals(2, table.getn(processedMessages))
|
||||
assert.equals(201, processedMessages[1].id)
|
||||
assert.equals(202, processedMessages[2].id)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("QuestieComms packet sizing", function()
|
||||
local serializeCount
|
||||
local sendCount
|
||||
local QuestieComms
|
||||
|
||||
before_each(function()
|
||||
dofile("Tests/wow_api_mock.lua")
|
||||
|
||||
serializeCount = 0
|
||||
sendCount = 0
|
||||
|
||||
local originalCreateModule = QuestieLoader.CreateModule
|
||||
local originalImportModule = QuestieLoader.ImportModule
|
||||
QuestieLoader.CreateModule = function(self, name)
|
||||
_G[name] = { private = {} }
|
||||
return _G[name]
|
||||
end
|
||||
QuestieLoader.ImportModule = function(self, name)
|
||||
if name == "QuestieSerializer" then
|
||||
return {
|
||||
Serialize = function(_, payload)
|
||||
serializeCount = serializeCount + 1
|
||||
return "packet:" .. tostring(payload.id or payload[1] or "x")
|
||||
end,
|
||||
Deserialize = function() return true, {} end,
|
||||
}
|
||||
end
|
||||
return originalImportModule(self, name)
|
||||
end
|
||||
|
||||
_G.LibStub = function(name, silent)
|
||||
if name == "AceComm-3.0" then
|
||||
return { RegisterComm = function() end }
|
||||
elseif name == "LibDeflate" then
|
||||
return {
|
||||
CompressDeflate = function(_, s) return s end,
|
||||
EncodeForPrint = function(_, s) return s end,
|
||||
DecodeForPrint = function(_, s) return s end,
|
||||
DecompressDeflate = function(_, s) return s end,
|
||||
}
|
||||
elseif name == "AceSerializer-3.0" then
|
||||
return {
|
||||
Serialize = function(_, payload) return "packet:" .. tostring(payload.id or payload[1] or "x") end,
|
||||
Deserialize = function() return true, {} end,
|
||||
}
|
||||
elseif name == "XXH_Lua_Lib" then
|
||||
return nil
|
||||
elseif name == "HereBeDragonsQuestie-2.0" then
|
||||
return {}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
_G.QuestiePlayer.GetGroupType = function() return "party" end
|
||||
_G.QuestiePlayer.numberOfGroupMembers = 5
|
||||
_G.QuestieDB.QuestPointers = {
|
||||
[101] = true,
|
||||
[102] = true,
|
||||
[103] = true,
|
||||
}
|
||||
_G.QuestieDB.QueryQuestSingle = function()
|
||||
return 0
|
||||
end
|
||||
_G.QuestieDB.GetQuest = function(questId)
|
||||
return {
|
||||
Objectives = {
|
||||
[1] = { Id = questId * 10 },
|
||||
},
|
||||
}
|
||||
end
|
||||
_G.QuestLogCache.questLog_DO_NOT_MODIFY = {
|
||||
[101] = { questTag = "Normal" },
|
||||
[102] = { questTag = "Normal" },
|
||||
[103] = { questTag = "Normal" },
|
||||
}
|
||||
_G.QuestLogCache.GetQuestObjectives = function()
|
||||
return {
|
||||
{ type = "monster", numFulfilled = 0, numRequired = 1 },
|
||||
}
|
||||
end
|
||||
_G.ZoneDB.GetUiMapIdByAreaId = function()
|
||||
return 1
|
||||
end
|
||||
_G.HBD = {
|
||||
GetZoneDistance = function() return 1 end,
|
||||
GetPlayerZone = function() return 1 end,
|
||||
}
|
||||
_G.GetChannelName = function() return 1 end
|
||||
_G.SendChatMessage = function() end
|
||||
_G.Questie.SendCommMessage = function()
|
||||
sendCount = sendCount + 1
|
||||
end
|
||||
_G.UnitInBattleground = function() return false end
|
||||
_G.random = function() return 0 end
|
||||
_G.GetTime = function() return 0 end
|
||||
_G.tinsert = table.insert
|
||||
QuestieCompat.C_Timer.After = function(_, fn) end
|
||||
QuestieCompat.C_Timer.NewTicker = function(_, fn)
|
||||
return { Cancel = function() end }
|
||||
end
|
||||
|
||||
QuestieComms = dofile("Modules/Network/QuestieComms.lua")
|
||||
QuestieComms.private.CreatePacket = function()
|
||||
return {
|
||||
data = {},
|
||||
write = function() end,
|
||||
}
|
||||
end
|
||||
|
||||
serializeCount = 0
|
||||
end)
|
||||
|
||||
it("serializes each quest once while packing broadcast blocks", function()
|
||||
QuestieComms.private:BroadcastQuestLog("QC_ID_BROADCAST_FULL_QUESTLIST", "WHISPER", "Tester")
|
||||
assert.equals(3, serializeCount)
|
||||
|
||||
serializeCount = 0
|
||||
QuestieComms.private:BroadcastQuestLogV2("QC_ID_BROADCAST_FULL_QUESTLIST", "WHISPER", "Tester")
|
||||
assert.equals(3, serializeCount)
|
||||
end)
|
||||
|
||||
it("suppresses outgoing QuestieComms immediately when disabled", function()
|
||||
Questie.db.profile.questieCommsEnabled = false
|
||||
|
||||
local packet = QuestieComms.private:CreatePacket(QuestieComms.private.QC_ID_BROADCAST_QUEST_REMOVE)
|
||||
packet.data.writeMode = QuestieComms.private.QC_WRITE_ALLGROUP
|
||||
packet.data.priority = "NORMAL"
|
||||
packet.data.id = 101
|
||||
packet:write()
|
||||
|
||||
assert.equals(0, sendCount)
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,66 @@
|
||||
describe("Questie tooltip precedence", function()
|
||||
local function contains(lines, needle)
|
||||
for _, line in ipairs(lines or {}) do
|
||||
if string.find(line, needle, 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
dofile("Tests/wow_api_mock.lua")
|
||||
|
||||
local originalImportModule = QuestieLoader.ImportModule
|
||||
QuestieLoader.ImportModule = function(self, name)
|
||||
if name == "QuestieLib" then
|
||||
return {
|
||||
GetColoredQuestName = function(_, questId)
|
||||
return "Quest " .. tostring(questId)
|
||||
end,
|
||||
Colorize = function(_, text)
|
||||
return text
|
||||
end,
|
||||
}
|
||||
end
|
||||
return originalImportModule(self, name)
|
||||
end
|
||||
|
||||
Questie.db.profile.showQuestsInNpcTooltip = true
|
||||
Questie.db.profile.enableTooltipsQuestLevel = false
|
||||
Questie.db.profile.enableTooltipsNPCID = false
|
||||
QuestiePlayer.numberOfGroupMembers = 0
|
||||
QuestieCompat.IsInGroup = function() return false end
|
||||
QuestieCompat.UnitInParty = function() return false end
|
||||
|
||||
QuestieDB.GetQuest = function(_, questId)
|
||||
if questId ~= 8334 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return {
|
||||
ObjectiveData = {
|
||||
[1] = { Type = "monster", Id = 15271, Text = "Tender slain" },
|
||||
[2] = { Type = "monster", Id = 15294, Text = "Feral Tender slain" },
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
dofile("Modules/Tooltips/Tooltip.lua")
|
||||
QuestieTooltips.lookupByKey["m_15271"] = {
|
||||
["8334 Tender 15271"] = {
|
||||
questId = 8334,
|
||||
name = "Tender",
|
||||
starterId = 15271,
|
||||
},
|
||||
}
|
||||
end)
|
||||
|
||||
it("adds AscensionDB objective text under quest titles when no objective tooltip is registered", function()
|
||||
local lines = QuestieTooltips:GetTooltip("m_15271")
|
||||
|
||||
assert.is_true(contains(lines, "Quest 8334"))
|
||||
assert.is_true(contains(lines, "Tender slain"))
|
||||
assert.is_true(contains(lines, "Feral Tender slain"))
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user