<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.stiles.casa/index.php?action=history&amp;feed=atom&amp;title=Module%3AArguments%2Ftestcases</id>
	<title>Module:Arguments/testcases - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.stiles.casa/index.php?action=history&amp;feed=atom&amp;title=Module%3AArguments%2Ftestcases"/>
	<link rel="alternate" type="text/html" href="https://wiki.stiles.casa/index.php?title=Module:Arguments/testcases&amp;action=history"/>
	<updated>2026-04-07T11:06:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.2</generator>
	<entry>
		<id>https://wiki.stiles.casa/index.php?title=Module:Arguments/testcases&amp;diff=6662&amp;oldid=prev</id>
		<title>imported&gt;Pppery: Not what module testcases pages are for</title>
		<link rel="alternate" type="text/html" href="https://wiki.stiles.casa/index.php?title=Module:Arguments/testcases&amp;diff=6662&amp;oldid=prev"/>
		<updated>2021-03-30T03:47:29Z</updated>

		<summary type="html">&lt;p&gt;Not what module testcases pages are for&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local getArgs = require(&amp;#039;Module:Arguments/sandbox&amp;#039;).getArgs&lt;br /&gt;
local ScribuntoUnit = require(&amp;#039;Module:ScribuntoUnit&amp;#039;)&lt;br /&gt;
local suite = ScribuntoUnit:new()&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Default values&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local d = {} &lt;br /&gt;
d.frameTitle = &amp;#039;Frame title&amp;#039;&lt;br /&gt;
d.parentTitle = &amp;#039;Parent title&amp;#039;&lt;br /&gt;
&lt;br /&gt;
-- Precedence-testing values&lt;br /&gt;
d.firstFrameArg = &amp;#039;first frame argument&amp;#039;&lt;br /&gt;
d.firstParentArg = &amp;#039;first parent argument&amp;#039;&lt;br /&gt;
d.secondParentArg = &amp;#039;second parent argument&amp;#039;&lt;br /&gt;
d.uniqueFrameArg = &amp;#039;unique frame argument&amp;#039;&lt;br /&gt;
d.uniqueFrameArgKey = &amp;#039;uniqueFrameArgKey&amp;#039;&lt;br /&gt;
d.uniqueParentArg = &amp;#039;unique parent argument&amp;#039;&lt;br /&gt;
d.uniqueParentArgKey = &amp;#039;uniqueParentArgKey&amp;#039;&lt;br /&gt;
&lt;br /&gt;
-- Trimming and whitespace values.&lt;br /&gt;
-- Whitespace gets trimmed from named parameters, so keys for these need&lt;br /&gt;
-- to be numbers to make this a proper test.&lt;br /&gt;
d.blankArg = &amp;#039;&amp;#039;&lt;br /&gt;
d.blankArgKey = 100 &lt;br /&gt;
d.spacesArg = &amp;#039;\n   &amp;#039;&lt;br /&gt;
d.spacesArgKey = 101&lt;br /&gt;
d.untrimmedArg = &amp;#039;\n   foo bar   &amp;#039;&lt;br /&gt;
d.untrimmedArgKey = 102&lt;br /&gt;
d.trimmedArg = &amp;#039;foo bar&amp;#039;&lt;br /&gt;
d.valueFuncValue = &amp;#039;valueFuncValue&amp;#039;&lt;br /&gt;
d.defaultValueFunc = function() return d.valueFuncValue end&lt;br /&gt;
d.translate = {&lt;br /&gt;
	foo = &amp;#039;F00&amp;#039;,&lt;br /&gt;
	bar = &amp;#039;8@r&amp;#039;,&lt;br /&gt;
	baz = &amp;#039;8@z&amp;#039;,&lt;br /&gt;
	qux = &amp;#039;qUx&amp;#039;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite.getFrames(frameTitle, frameArgs, parentTitle, parentArgs)&lt;br /&gt;
	frameTitle = frameTitle or d.frameTitle&lt;br /&gt;
	frameArgs = frameArgs or {&lt;br /&gt;
		d.firstFrameArg,&lt;br /&gt;
		[d.uniqueFrameArgKey] = d.uniqueFrameArg,&lt;br /&gt;
		[d.blankArgKey] = d.blankArg,&lt;br /&gt;
		[d.spacesArgKey] = d.spacesArg,&lt;br /&gt;
		[d.untrimmedArgKey] = d.untrimmedArg&lt;br /&gt;
	}&lt;br /&gt;
	parentTitle = parentTitle or d.parentTitle&lt;br /&gt;
	parentArgs = parentArgs or {&lt;br /&gt;
		d.firstParentArg,&lt;br /&gt;
		d.secondParentArg,&lt;br /&gt;
		[d.uniqueParentArgKey] = d.uniqueParentArg&lt;br /&gt;
	}&lt;br /&gt;
	local currentFrame = mw.getCurrentFrame()&lt;br /&gt;
	local parent = currentFrame:newChild{title = parentTitle, args = parentArgs}&lt;br /&gt;
	local frame = parent:newChild{title = frameTitle, args = frameArgs}&lt;br /&gt;
	return frame, parent&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite.getDefaultArgs(options, frameTitle, frameArgs, parentTitle, parentArgs)&lt;br /&gt;
	local frame, parent = suite.getFrames(frameTitle, frameArgs, parentTitle, parentArgs)&lt;br /&gt;
	local args = getArgs(frame, options)&lt;br /&gt;
	return args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:assertError(func, ...)&lt;br /&gt;
	-- Asserts that executing the function func results in an error.&lt;br /&gt;
	-- Parameters after func are func&amp;#039;s arguments.&lt;br /&gt;
	local success, msg = pcall(func, ...)&lt;br /&gt;
	self:assertFalse(success)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:assertNumberOfIterations(expected, iterator, t)&lt;br /&gt;
	local noIterations = 0&lt;br /&gt;
	for k, v in iterator(t) do&lt;br /&gt;
		noIterations = noIterations + 1&lt;br /&gt;
	end&lt;br /&gt;
	self:assertEquals(expected, noIterations)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test precedence&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:assertDefaultPrecedence(args)&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	self:assertEquals(d.secondParentArg, args[2])&lt;br /&gt;
	self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey])&lt;br /&gt;
	self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDefaultPrecedence()&lt;br /&gt;
	self:assertDefaultPrecedence(suite.getDefaultArgs())&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDefaultPrecedenceThroughWrapper()&lt;br /&gt;
	self:assertDefaultPrecedence(suite.getDefaultArgs{wrappers = {d.parentTitle}, parentOnly = false})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDefaultPrecedenceThroughNonWrapper()&lt;br /&gt;
	self:assertDefaultPrecedence(suite.getDefaultArgs({wrappers = d.parentTitle, frameOnly = false}, nil, nil, &amp;#039;Not the parent title&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:assertParentFirst(args)&lt;br /&gt;
	self:assertEquals(d.firstParentArg, args[1])&lt;br /&gt;
	self:assertEquals(d.secondParentArg, args[2])&lt;br /&gt;
	self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey])&lt;br /&gt;
	self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentFirst()&lt;br /&gt;
	self:assertParentFirst(suite.getDefaultArgs{parentFirst = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentFirstThroughWrapper()&lt;br /&gt;
	self:assertParentFirst(suite.getDefaultArgs{wrappers = {d.parentTitle}, parentOnly = false, parentFirst = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentFirstThroughNonWrapper()&lt;br /&gt;
	self:assertParentFirst(suite.getDefaultArgs({wrappers = d.parentTitle, frameOnly = false, parentFirst = true}, nil, nil, &amp;#039;Not the parent title&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:assertParentOnly(args)&lt;br /&gt;
	self:assertEquals(d.firstParentArg, args[1])&lt;br /&gt;
	self:assertEquals(d.secondParentArg, args[2])&lt;br /&gt;
	self:assertEquals(nil, args[d.uniqueFrameArgKey])&lt;br /&gt;
	self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentOnly()&lt;br /&gt;
	self:assertParentOnly(suite.getDefaultArgs{parentOnly = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentOnlyThroughWrapper()&lt;br /&gt;
	self:assertParentOnly(suite.getDefaultArgs{wrappers = {d.parentTitle}})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testParentOnlyThroughSandboxWrapper()&lt;br /&gt;
	self:assertParentOnly(suite.getDefaultArgs({wrappers = d.parentTitle}, nil, nil, d.parentTitle .. &amp;#039;/sandbox&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:assertFrameOnly(args)&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	self:assertEquals(nil, args[2])&lt;br /&gt;
	self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey])&lt;br /&gt;
	self:assertEquals(nil, args[d.uniqueParentArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testFrameOnly()&lt;br /&gt;
	self:assertFrameOnly(suite.getDefaultArgs{frameOnly = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testFrameOnlyThroughNonWrapper()&lt;br /&gt;
	self:assertFrameOnly(suite.getDefaultArgs({wrappers = d.parentTitle}, nil, nil, &amp;#039;Not the parent title&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDefaultPrecedenceWithWhitespace()&lt;br /&gt;
	local frame, parent = suite.getFrames(&lt;br /&gt;
		d.frameTitle,&lt;br /&gt;
		{&amp;#039;  &amp;#039;},&lt;br /&gt;
		d.parentTitle,&lt;br /&gt;
		{d.firstParentArg}&lt;br /&gt;
	)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	self:assertEquals(d.firstParentArg, args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test trimming and blank removal&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testDefaultTrimmingAndBlankRemoval()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(nil, args[d.blankArgKey])&lt;br /&gt;
	self:assertEquals(nil, args[d.spacesArgKey])&lt;br /&gt;
	self:assertEquals(d.trimmedArg, args[d.untrimmedArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testRemoveBlanksButNoTrimming()&lt;br /&gt;
	local args = suite.getDefaultArgs{trim = false}&lt;br /&gt;
	self:assertEquals(nil, args[d.blankArgKey])&lt;br /&gt;
	self:assertEquals(nil, args[d.spacesArgKey])&lt;br /&gt;
	self:assertEquals(d.untrimmedArg, args[d.untrimmedArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testTrimButNoBlankRemoval()&lt;br /&gt;
	local args = suite.getDefaultArgs{removeBlanks = false}&lt;br /&gt;
	self:assertEquals(d.blankArg, args[d.blankArgKey])&lt;br /&gt;
	self:assertEquals(&amp;#039;&amp;#039;, args[d.spacesArgKey])&lt;br /&gt;
	self:assertEquals(d.trimmedArg, args[d.untrimmedArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoTrimOrBlankRemoval()&lt;br /&gt;
	local args = suite.getDefaultArgs{trim = false, removeBlanks = false}&lt;br /&gt;
	self:assertEquals(d.blankArg, args[d.blankArgKey])&lt;br /&gt;
	self:assertEquals(d.spacesArg, args[d.spacesArgKey])&lt;br /&gt;
	self:assertEquals(d.untrimmedArg, args[d.untrimmedArgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test valueFunc&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testValueFunc()&lt;br /&gt;
	local args = suite.getDefaultArgs{valueFunc = d.defaultValueFunc}&lt;br /&gt;
	self:assertEquals(d.valueFuncValue, args[&amp;#039;some random key: sdfaliwyda&amp;#039;])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testValueFuncPrecedence()&lt;br /&gt;
	local args = suite.getDefaultArgs{&lt;br /&gt;
		trim = false,&lt;br /&gt;
		removeBlanks = false,&lt;br /&gt;
		valueFunc = d.defaultValueFunc&lt;br /&gt;
	}&lt;br /&gt;
	self:assertEquals(d.valueFuncValue, args[1])&lt;br /&gt;
	self:assertEquals(d.valueFuncValue, args[&amp;#039;some random key: gekjabawyvy&amp;#039;])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testValueFuncKey()&lt;br /&gt;
	local args = suite.getDefaultArgs{valueFunc = function(key, value)&lt;br /&gt;
		return &amp;#039;valueFunc key: &amp;#039;.. key&lt;br /&gt;
	end}&lt;br /&gt;
	self:assertEquals(&amp;#039;valueFunc key: foo&amp;#039;, args.foo)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testValueFuncValue()&lt;br /&gt;
	local args = suite.getDefaultArgs{valueFunc = function(key, value)&lt;br /&gt;
		return &amp;#039;valueFunc value: &amp;#039;.. value&lt;br /&gt;
	end}&lt;br /&gt;
	self:assertEquals(&lt;br /&gt;
		&amp;#039;valueFunc value: &amp;#039; .. d.uniqueFrameArg,&lt;br /&gt;
		args[d.uniqueFrameArgKey]&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test adding new arguments&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testAddingNewArgs()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(nil, args.newKey)&lt;br /&gt;
	args.newKey = &amp;#039;some new key&amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039;some new key&amp;#039;, args.newKey)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testAddingNewBlankArgs()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(nil, args.newKey)&lt;br /&gt;
	args.newKey = &amp;#039;&amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039;&amp;#039;, args.newKey)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testAddingNewSpacesArgs()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(nil, args.newKey)&lt;br /&gt;
	args.newKey = &amp;#039; &amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039; &amp;#039;, args.newKey)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testOverwriting()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	args[1] = &amp;#039;a new first frame argument&amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039;a new first frame argument&amp;#039;, args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testOverwritingWithNil()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	args[1] = nil&lt;br /&gt;
	self:assertEquals(nil, args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testOverwritingWithBlank()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	args[1] = &amp;#039;&amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039;&amp;#039;, args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testOverwritingWithSpaces()&lt;br /&gt;
	local args = suite.getDefaultArgs()&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	args[1] = &amp;#039; &amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039; &amp;#039;, args[1])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testReadOnly()&lt;br /&gt;
	local args = suite.getDefaultArgs{readOnly = true}&lt;br /&gt;
	local function testFunc()&lt;br /&gt;
		args.newKey = &amp;#039;some new value&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	self:assertError(testFunc)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoOverwriteExistingKey()&lt;br /&gt;
	local args = suite.getDefaultArgs{noOverwrite = true}&lt;br /&gt;
	self:assertEquals(d.firstFrameArg, args[1])&lt;br /&gt;
	local function testFunc()&lt;br /&gt;
		args[1] = &amp;#039;a new first frame argument&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	self:assertError(testFunc)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoOverwriteNewKey()&lt;br /&gt;
	local args = suite.getDefaultArgs{noOverwrite = true}&lt;br /&gt;
	self:assertEquals(nil, args.newKey)&lt;br /&gt;
	args.newKey = &amp;#039;some new value&amp;#039;&lt;br /&gt;
	self:assertEquals(&amp;#039;some new value&amp;#039;, args.newKey)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test bad input&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testBadFrameInput()&lt;br /&gt;
	self:assertError(getArgs, &amp;#039;foo&amp;#039;)&lt;br /&gt;
	self:assertError(getArgs, 9)&lt;br /&gt;
	self:assertError(getArgs, true)&lt;br /&gt;
	self:assertError(getArgs, function() return true end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testBadOptionsInput()&lt;br /&gt;
	self:assertError(getArgs, {}, &amp;#039;foo&amp;#039;)&lt;br /&gt;
	self:assertError(getArgs, {}, 9)&lt;br /&gt;
	self:assertError(getArgs, {}, true)&lt;br /&gt;
	self:assertError(getArgs, {}, function() return true end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testBadValueFuncInput()&lt;br /&gt;
	self:assertError(getArgs, {}, {valueFunc = &amp;#039;foo&amp;#039;})&lt;br /&gt;
	self:assertError(getArgs, {}, {valueFunc = 9})&lt;br /&gt;
	self:assertError(getArgs, {}, {valueFunc = true})&lt;br /&gt;
	self:assertError(getArgs, {}, {valueFunc = {}})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test iterator metamethods&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testPairs()&lt;br /&gt;
	local args = getArgs{&amp;#039;foo&amp;#039;, &amp;#039;bar&amp;#039;, baz = &amp;#039;qux&amp;#039;}&lt;br /&gt;
	self:assertNumberOfIterations(3, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testIpairs()&lt;br /&gt;
	local args = getArgs{&amp;#039;foo&amp;#039;, &amp;#039;bar&amp;#039;, baz = &amp;#039;qux&amp;#039;}&lt;br /&gt;
	self:assertNumberOfIterations(2, ipairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoNilsinPairs()&lt;br /&gt;
	-- Test that when we use pairs, we don&amp;#039;t iterate over any nil values&lt;br /&gt;
	-- that have been memoized.&lt;br /&gt;
	local args = getArgs{&amp;#039;&amp;#039;}&lt;br /&gt;
	local temp = args[1] -- Memoizes the nil&lt;br /&gt;
	self:assertNumberOfIterations(0, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoNilsinIpairs()&lt;br /&gt;
	-- Test that when we use ipairs, we don&amp;#039;t iterate over any nil values&lt;br /&gt;
	-- that have been memoized.&lt;br /&gt;
	local args = getArgs{&amp;#039;&amp;#039;}&lt;br /&gt;
	local temp = args[1] -- Memoizes the nil&lt;br /&gt;
	self:assertNumberOfIterations(0, ipairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDeletedArgsInPairs()&lt;br /&gt;
	-- Test that when we use pairs, we don&amp;#039;t iterate over any values that have&lt;br /&gt;
	-- been explicitly set to nil.&lt;br /&gt;
	local args = getArgs{&amp;#039;foo&amp;#039;}&lt;br /&gt;
	args[1] = nil&lt;br /&gt;
	self:assertNumberOfIterations(0, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testDeletedArgsInIpairs()&lt;br /&gt;
	-- Test that when we use ipairs, we don&amp;#039;t iterate over any values that have&lt;br /&gt;
	-- been explicitly set to nil.&lt;br /&gt;
	local args = getArgs{&amp;#039;foo&amp;#039;}&lt;br /&gt;
	args[1] = nil&lt;br /&gt;
	self:assertNumberOfIterations(0, ipairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoNilsInPairsAfterIndex()&lt;br /&gt;
	-- Test that when we use pairs, we don&amp;#039;t iterate over any nils that&lt;br /&gt;
	-- might have been memoized after a value that is not present in the&lt;br /&gt;
	-- original args table is indexed.&lt;br /&gt;
	local args = getArgs{}&lt;br /&gt;
	local temp = args.someRandomValue -- Memoizes the nil&lt;br /&gt;
	self:assertNumberOfIterations(0, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoNilsInPairsAfterNewindex()&lt;br /&gt;
	-- Test that when we use pairs, we don&amp;#039;t iterate over any nils that&lt;br /&gt;
	-- might have been memoized after a value that is not present in the&lt;br /&gt;
	-- original args table is added to the args table.&lt;br /&gt;
	local args = getArgs{}&lt;br /&gt;
	args.newKey = nil -- The nil is memoized&lt;br /&gt;
	self:assertNumberOfIterations(0, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testNoTableLengthChangeWhileIterating()&lt;br /&gt;
	-- Test that the number of arguments doesn&amp;#039;t change if we index the&lt;br /&gt;
	-- args table while iterating.&lt;br /&gt;
	-- (Note that the equivalent test is not needed for new arg table&lt;br /&gt;
	-- indexes, as that would be a user error - doing so produces&lt;br /&gt;
	-- undetermined behaviour in Lua&amp;#039;s next() function.)&lt;br /&gt;
	local args = getArgs{&amp;#039;foo&amp;#039;, &amp;#039;bar&amp;#039;, baz = &amp;#039;qux&amp;#039;}&lt;br /&gt;
	self:assertNumberOfIterations(3, pairs, args)&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		local temp = args[k .. &amp;#039;foo&amp;#039;]&lt;br /&gt;
	end&lt;br /&gt;
	self:assertNumberOfIterations(3, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testPairsPrecedenceWithWhitespace()&lt;br /&gt;
	local frame, parent = suite.getFrames(&lt;br /&gt;
		d.frameTitle,&lt;br /&gt;
		{&amp;#039;  &amp;#039;},&lt;br /&gt;
		d.parentTitle,&lt;br /&gt;
		{d.firstParentArg}&lt;br /&gt;
	)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local actual&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		actual = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertEquals(d.firstParentArg, actual)&lt;br /&gt;
	-- Check that we have actually iterated.&lt;br /&gt;
	self:assertNumberOfIterations(1, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testPairsPrecedenceWithNil()&lt;br /&gt;
	local frame, parent = suite.getFrames(&lt;br /&gt;
		d.frameTitle,&lt;br /&gt;
		{},&lt;br /&gt;
		d.parentTitle,&lt;br /&gt;
		{d.firstParentArg}&lt;br /&gt;
	)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local actual&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		actual = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertEquals(d.firstParentArg, actual)&lt;br /&gt;
	-- Check that we have actually iterated.&lt;br /&gt;
	self:assertNumberOfIterations(1, pairs, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testIpairsEarlyExit()&lt;br /&gt;
	local mt = {}&lt;br /&gt;
	function mt.__index(t, k)&lt;br /&gt;
		if k == 1 then&lt;br /&gt;
			return &amp;#039;foo&amp;#039;&lt;br /&gt;
		elseif k == 2 then&lt;br /&gt;
			return &amp;#039;bar&amp;#039;&lt;br /&gt;
		elseif k == 3 then&lt;br /&gt;
			error(&amp;#039;Expanded argument 3 unnecessarily&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	function mt.__pairs(t)&lt;br /&gt;
		error(&amp;#039;Called pairs unnecessarily&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	function mt.__ipairs(t)&lt;br /&gt;
		-- Works just like the default ipairs, except respecting __index&lt;br /&gt;
		return function(t, i)&lt;br /&gt;
			local v = t[i + 1]&lt;br /&gt;
			if v ~= nil then&lt;br /&gt;
				return i + 1, v&lt;br /&gt;
			end&lt;br /&gt;
		end, t, 0&lt;br /&gt;
	end&lt;br /&gt;
	local args = getArgs(setmetatable({}, mt))&lt;br /&gt;
	for k,v in ipairs(args) do&lt;br /&gt;
		if v == &amp;#039;bar&amp;#039; then&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
-- Test argument translation&lt;br /&gt;
--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function suite:testTranslationIndex()&lt;br /&gt;
	local args = getArgs({F00 = &amp;#039;one&amp;#039;, [&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;, [&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;, qUx = &amp;#039;four&amp;#039;, foo = &amp;#039;nope&amp;#039;, untranslated = &amp;#039;yep&amp;#039;}, {translate = d.translate})&lt;br /&gt;
	self:assertEquals(&amp;#039;one&amp;#039;, args.foo)&lt;br /&gt;
	self:assertEquals(&amp;#039;two&amp;#039;, args.bar)&lt;br /&gt;
	self:assertEquals(&amp;#039;three&amp;#039;, args.baz)&lt;br /&gt;
	self:assertEquals(&amp;#039;four&amp;#039;, args.qux)&lt;br /&gt;
	self:assertEquals(&amp;#039;yep&amp;#039;, args.untranslated)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testTranslationPairsWithAutoBacktranslate()&lt;br /&gt;
	local args = getArgs({F00 = &amp;#039;one&amp;#039;, [&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;, [&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;, qUx = &amp;#039;four&amp;#039;, foo = &amp;#039;nope&amp;#039;, untranslated = &amp;#039;yep&amp;#039;}, {translate = d.translate})&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for k,v in pairs(args) do&lt;br /&gt;
		cleanArgs[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertDeepEquals(&lt;br /&gt;
		{&lt;br /&gt;
			foo = &amp;#039;one&amp;#039;,&lt;br /&gt;
			bar = &amp;#039;two&amp;#039;,&lt;br /&gt;
			baz = &amp;#039;three&amp;#039;,&lt;br /&gt;
			qux = &amp;#039;four&amp;#039;,&lt;br /&gt;
			untranslated = &amp;#039;yep&amp;#039;&lt;br /&gt;
		},&lt;br /&gt;
		cleanArgs&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testTranslationPairsWithBacktranslate()&lt;br /&gt;
	local args = getArgs({F00 = &amp;#039;one&amp;#039;, [&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;, [&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;, qUx = &amp;#039;four&amp;#039;, foo = &amp;#039;nope&amp;#039;, untranslated = &amp;#039;yep&amp;#039;}, {translate = d.translate, backtranslate = {F00 = &amp;#039;foo&amp;#039;}})&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for k,v in pairs(args) do&lt;br /&gt;
		cleanArgs[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertDeepEquals(&lt;br /&gt;
		{&lt;br /&gt;
			foo = &amp;#039;one&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;,&lt;br /&gt;
			qUx = &amp;#039;four&amp;#039;,&lt;br /&gt;
			untranslated = &amp;#039;yep&amp;#039;&lt;br /&gt;
		},&lt;br /&gt;
		cleanArgs&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testTranslationPairsWithoutBacktranslate()&lt;br /&gt;
	local args = getArgs({F00 = &amp;#039;one&amp;#039;, [&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;, [&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;, qUx = &amp;#039;four&amp;#039;, foo = &amp;#039;nope&amp;#039;, untranslated = &amp;#039;yep&amp;#039;}, {translate = d.translate, backtranslate = false})&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for k,v in pairs(args) do&lt;br /&gt;
		cleanArgs[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertDeepEquals(&lt;br /&gt;
		{&lt;br /&gt;
			F00 = &amp;#039;one&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;,&lt;br /&gt;
			qUx = &amp;#039;four&amp;#039;,&lt;br /&gt;
			foo = &amp;#039;nope&amp;#039;,&lt;br /&gt;
			untranslated = &amp;#039;yep&amp;#039;&lt;br /&gt;
		},&lt;br /&gt;
		cleanArgs&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:testTranslationNewindex()&lt;br /&gt;
	local args = getArgs({F00 = &amp;#039;one&amp;#039;, [&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;, [&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;, qUx = &amp;#039;four&amp;#039;, foo = &amp;#039;nope&amp;#039;, untranslated = &amp;#039;yep&amp;#039;}, {translate = d.translate, backtranslate = false})&lt;br /&gt;
	args.foo = &amp;#039;changed1&amp;#039;&lt;br /&gt;
	args.untranslated = &amp;#039;changed2&amp;#039;&lt;br /&gt;
	local cleanArgs = {}&lt;br /&gt;
	for k,v in pairs(args) do&lt;br /&gt;
		cleanArgs[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	self:assertDeepEquals(&lt;br /&gt;
		{&lt;br /&gt;
			F00 = &amp;#039;changed1&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@r&amp;#039;] = &amp;#039;two&amp;#039;,&lt;br /&gt;
			[&amp;#039;8@z&amp;#039;] = &amp;#039;three&amp;#039;,&lt;br /&gt;
			qUx = &amp;#039;four&amp;#039;,&lt;br /&gt;
			foo = &amp;#039;nope&amp;#039;,&lt;br /&gt;
			untranslated = &amp;#039;changed2&amp;#039;&lt;br /&gt;
		},&lt;br /&gt;
		cleanArgs&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function suite:test_argument()&lt;br /&gt;
	local currentFrame = mw.getCurrentFrame()&lt;br /&gt;
	currentFrame.args[5] = 555;&lt;br /&gt;
	local args = getArgs(currentFrame)&lt;br /&gt;
	self:assertEquals(&amp;#039;nil&amp;#039;, type(args.foo))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return suite&lt;/div&gt;</summary>
		<author><name>imported&gt;Pppery</name></author>
	</entry>
</feed>