Quest Ready for Turn In

Using the API, how can I tell if a quest is ready for turn in? In the quest log on screen, it shows with a yellow ? the same as for completed quests which are also ready for turnin.
Example: Quest 53160 “Ancient Crypt Key” shows with a yellow ? but the API calls I’ve tried do not return it being complete.
Example: Quest 29433 “Test Your Strength” shows with a yellow ? and the API calls return that it is complete.
I’ve using GetQuestLogTitle to return the isComplete field.

GetQuestLogTitle really should return what you want, I think

GetQuestTagInfo gets the isComplete parameter from GetQuestLogTitle so afaik if it shows a yellow ? it should be ready for turn-in as well

https://github.com/Gethe/wow-ui-source/blob/live/FrameXML/QuestMapFrame.lua#L547-L548

I haven’t had a chance to dig into what’s actually going on (gathering additional information for quests that are part of a series) but this shows what Blizzard is doing vs. just using GetQuestLogTitle (/QL to run)

local questTrackerOrderingFlags = {
	{ isWarCampaign = true },
	{ isWarCampaign = false },
};

local function EnumQuestWatchDataHelper(func, orderingInfo, questID, ...)
	if questID then
		local isWarCampaign = select(17, ...);
		if orderingInfo.isWarCampaign == isWarCampaign then
			local done = func(questID, ...);
			if done then
				return true;
			end
		end
	end
	return false;
end

local function EnumQuestWatchData(func)
	for _, orderingInfo in ipairs(questTrackerOrderingFlags) do
		for i = 1, GetNumQuestWatches() do
			if EnumQuestWatchDataHelper(func, orderingInfo, GetQuestWatchInfo(i)) then
				return;
			end
		end
	end
end

SLASH_FizzleQuestList1 = "/ql"
SlashCmdList["FizzleQuestList"] = function(msg)
	local playerMoney = GetMoney();
	local numPOINumeric = 0;
	
	local Titles = {}
	EnumQuestWatchData(
		function(questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, startEvent, isAutoComplete, failureTime, timeElapsed, questType, isTask, isBounty, isStory, isOnMap, hasLocalPOI, isHidden, isWarCampaign)
			-- see if we already have a block for this quest
			local block = QUEST_TRACKER_MODULE:GetExistingBlock(questID);
			if ( block ) then
				if ( isComplete and isComplete < 0 ) then
					isComplete = false;
				elseif ( numObjectives == 0 and playerMoney >= requiredMoney and not startEvent ) then
					isComplete = true;
				end
				local poiButton;
				if ( hasLocalPOI ) then
					if ( isComplete ) then
						poiButton = QuestPOI_GetButton(ObjectiveTrackerFrame.BlocksFrame, questID, "normal", nil);
					else
						numPOINumeric = numPOINumeric + 1;
						poiButton = QuestPOI_GetButton(ObjectiveTrackerFrame.BlocksFrame, questID, "numeric", numPOINumeric);
					end
				elseif ( isComplete ) then
					poiButton = QuestPOI_GetButton(ObjectiveTrackerFrame.BlocksFrame, questID, "remote", nil);
				end
				if ( poiButton ) then
					poiButton:SetPoint("TOPRIGHT", block.HeaderText, "TOPLEFT", -6, 2);
				end
			end
			if isComplete then -- FizzleCheck
				print(title, isComplete) 
				Titles[title] = true
			end
			return false;
		end
	);

	print("-----============== ==============-----")
	for i=1, GetNumQuestLogEntries() do
		local title, _, _, _, _, complete, _, _, _, _, _, _, task = GetQuestLogTitle(i)
		if Titles[title] then
			print(title, complete)
		end
	end
end

Requires a character with at least one of the “partial” quests, 111-118ish should have one or more from BfA.