Module:Arguments/testcases explained

local getArgs = require('Module:Arguments/sandbox').getArgslocal ScribuntoUnit = require('Module:ScribuntoUnit')local suite = ScribuntoUnit:new

---------------------------------------------------------------------------- Default values--------------------------------------------------------------------------

local d = d.frameTitle = 'Frame title'd.parentTitle = 'Parent title'

-- Precedence-testing valuesd.firstFrameArg = 'first frame argument'd.firstParentArg = 'first parent argument'd.secondParentArg = 'second parent argument'd.uniqueFrameArg = 'unique frame argument'd.uniqueFrameArgKey = 'uniqueFrameArgKey'd.uniqueParentArg = 'unique parent argument'd.uniqueParentArgKey = 'uniqueParentArgKey'

-- Trimming and whitespace values.-- Whitespace gets trimmed from named parameters, so keys for these need-- to be numbers to make this a proper test.d.blankArg = d.blankArgKey = 100 d.spacesArg = '\n 'd.spacesArgKey = 101d.untrimmedArg = '\n foo bar 'd.untrimmedArgKey = 102d.trimmedArg = 'foo bar'd.valueFuncValue = 'valueFuncValue'd.defaultValueFunc = function return d.valueFuncValue endd.translate =

---------------------------------------------------------------------------- Helper functions--------------------------------------------------------------------------

function suite.getFrames(frameTitle, frameArgs, parentTitle, parentArgs) frameTitle = frameTitle or d.frameTitle frameArgs = frameArgs or parentTitle = parentTitle or d.parentTitle parentArgs = parentArgs or local currentFrame = mw.getCurrentFrame local parent = currentFrame:newChild local frame = parent:newChild return frame, parentend

function suite.getDefaultArgs(options, frameTitle, frameArgs, parentTitle, parentArgs) local frame, parent = suite.getFrames(frameTitle, frameArgs, parentTitle, parentArgs) local args = getArgs(frame, options) return argsend

function suite:assertError(func, ...) -- Asserts that executing the function func results in an error. -- Parameters after func are func's arguments. local success, msg = pcall(func, ...) self:assertFalse(success)end

function suite:assertNumberOfIterations(expected, iterator, t) local noIterations = 0 for k, v in iterator(t) do noIterations = noIterations + 1 end self:assertEquals(expected, noIterations)end

---------------------------------------------------------------------------- Test precedence--------------------------------------------------------------------------

function suite:assertDefaultPrecedence(args) self:assertEquals(d.firstFrameArg, args[1]) self:assertEquals(d.secondParentArg, args[2]) self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey]) self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])end

function suite:testDefaultPrecedence self:assertDefaultPrecedence(suite.getDefaultArgs)end

function suite:testDefaultPrecedenceThroughWrapper self:assertDefaultPrecedence(suite.getDefaultArgs)end

function suite:testDefaultPrecedenceThroughNonWrapper self:assertDefaultPrecedence(suite.getDefaultArgs(nil, nil, 'Not the parent title'))end

function suite:assertParentFirst(args) self:assertEquals(d.firstParentArg, args[1]) self:assertEquals(d.secondParentArg, args[2]) self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey]) self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])end

function suite:testParentFirst self:assertParentFirst(suite.getDefaultArgs)end

function suite:testParentFirstThroughWrapper self:assertParentFirst(suite.getDefaultArgs)end

function suite:testParentFirstThroughNonWrapper self:assertParentFirst(suite.getDefaultArgs(nil, nil, 'Not the parent title'))end

function suite:assertParentOnly(args) self:assertEquals(d.firstParentArg, args[1]) self:assertEquals(d.secondParentArg, args[2]) self:assertEquals(nil, args[d.uniqueFrameArgKey]) self:assertEquals(d.uniqueParentArg, args[d.uniqueParentArgKey])end

function suite:testParentOnly self:assertParentOnly(suite.getDefaultArgs)end

function suite:testParentOnlyThroughWrapper self:assertParentOnly(suite.getDefaultArgs)end

function suite:testParentOnlyThroughSandboxWrapper self:assertParentOnly(suite.getDefaultArgs(nil, nil, d.parentTitle .. '/sandbox'))end

function suite:assertFrameOnly(args) self:assertEquals(d.firstFrameArg, args[1]) self:assertEquals(nil, args[2]) self:assertEquals(d.uniqueFrameArg, args[d.uniqueFrameArgKey]) self:assertEquals(nil, args[d.uniqueParentArgKey])end

function suite:testFrameOnly self:assertFrameOnly(suite.getDefaultArgs)end

function suite:testFrameOnlyThroughNonWrapper self:assertFrameOnly(suite.getDefaultArgs(nil, nil, 'Not the parent title'))end

function suite:testDefaultPrecedenceWithWhitespace local frame, parent = suite.getFrames(d.frameTitle, , d.parentTitle, ) local args = getArgs(frame) self:assertEquals(d.firstParentArg, args[1])end

---------------------------------------------------------------------------- Test trimming and blank removal--------------------------------------------------------------------------

function suite:testDefaultTrimmingAndBlankRemoval local args = suite.getDefaultArgs self:assertEquals(nil, args[d.blankArgKey]) self:assertEquals(nil, args[d.spacesArgKey]) self:assertEquals(d.trimmedArg, args[d.untrimmedArgKey])end

function suite:testRemoveBlanksButNoTrimming local args = suite.getDefaultArgs self:assertEquals(nil, args[d.blankArgKey]) self:assertEquals(nil, args[d.spacesArgKey]) self:assertEquals(d.untrimmedArg, args[d.untrimmedArgKey])end

function suite:testTrimButNoBlankRemoval local args = suite.getDefaultArgs self:assertEquals(d.blankArg, args[d.blankArgKey]) self:assertEquals(, args[d.spacesArgKey]) self:assertEquals(d.trimmedArg, args[d.untrimmedArgKey])end

function suite:testNoTrimOrBlankRemoval local args = suite.getDefaultArgs self:assertEquals(d.blankArg, args[d.blankArgKey]) self:assertEquals(d.spacesArg, args[d.spacesArgKey]) self:assertEquals(d.untrimmedArg, args[d.untrimmedArgKey])end

---------------------------------------------------------------------------- Test valueFunc--------------------------------------------------------------------------

function suite:testValueFunc local args = suite.getDefaultArgs self:assertEquals(d.valueFuncValue, args['some random key: sdfaliwyda'])end

function suite:testValueFuncPrecedence local args = suite.getDefaultArgs self:assertEquals(d.valueFuncValue, args[1]) self:assertEquals(d.valueFuncValue, args['some random key: gekjabawyvy'])end

function suite:testValueFuncKey local args = suite.getDefaultArgs self:assertEquals('valueFunc key: foo', args.foo)end

function suite:testValueFuncValue local args = suite.getDefaultArgs self:assertEquals('valueFunc value: ' .. d.uniqueFrameArg, args[d.uniqueFrameArgKey] )end

---------------------------------------------------------------------------- Test adding new arguments--------------------------------------------------------------------------

function suite:testAddingNewArgs local args = suite.getDefaultArgs self:assertEquals(nil, args.newKey) args.newKey = 'some new key' self:assertEquals('some new key', args.newKey)end

function suite:testAddingNewBlankArgs local args = suite.getDefaultArgs self:assertEquals(nil, args.newKey) args.newKey = self:assertEquals(, args.newKey)end

function suite:testAddingNewSpacesArgs local args = suite.getDefaultArgs self:assertEquals(nil, args.newKey) args.newKey = ' ' self:assertEquals(' ', args.newKey)end

function suite:testOverwriting local args = suite.getDefaultArgs self:assertEquals(d.firstFrameArg, args[1]) args[1] = 'a new first frame argument' self:assertEquals('a new first frame argument', args[1])end

function suite:testOverwritingWithNil local args = suite.getDefaultArgs self:assertEquals(d.firstFrameArg, args[1]) args[1] = nil self:assertEquals(nil, args[1])end

function suite:testOverwritingWithBlank local args = suite.getDefaultArgs self:assertEquals(d.firstFrameArg, args[1]) args[1] = self:assertEquals(, args[1])end

function suite:testOverwritingWithSpaces local args = suite.getDefaultArgs self:assertEquals(d.firstFrameArg, args[1]) args[1] = ' ' self:assertEquals(' ', args[1])end

function suite:testReadOnly local args = suite.getDefaultArgs local function testFunc args.newKey = 'some new value' end self:assertError(testFunc)end

function suite:testNoOverwriteExistingKey local args = suite.getDefaultArgs self:assertEquals(d.firstFrameArg, args[1]) local function testFunc args[1] = 'a new first frame argument' end self:assertError(testFunc)end

function suite:testNoOverwriteNewKey local args = suite.getDefaultArgs self:assertEquals(nil, args.newKey) args.newKey = 'some new value' self:assertEquals('some new value', args.newKey)end

---------------------------------------------------------------------------- Test bad input--------------------------------------------------------------------------

function suite:testBadFrameInput self:assertError(getArgs, 'foo') self:assertError(getArgs, 9) self:assertError(getArgs, true) self:assertError(getArgs, function return true end)end

function suite:testBadOptionsInput self:assertError(getArgs,, 'foo') self:assertError(getArgs,, 9) self:assertError(getArgs,, true) self:assertError(getArgs,, function return true end)end

function suite:testBadValueFuncInput self:assertError(getArgs,,) self:assertError(getArgs,,) self:assertError(getArgs,,) self:assertError(getArgs,,)end

---------------------------------------------------------------------------- Test iterator metamethods--------------------------------------------------------------------------

function suite:testPairs local args = getArgs self:assertNumberOfIterations(3, pairs, args)end

function suite:testIpairs local args = getArgs self:assertNumberOfIterations(2, ipairs, args)end

function suite:testNoNilsinPairs -- Test that when we use pairs, we don't iterate over any nil values -- that have been memoized. local args = getArgs local temp = args[1] -- Memoizes the nil self:assertNumberOfIterations(0, pairs, args)end

function suite:testNoNilsinIpairs -- Test that when we use ipairs, we don't iterate over any nil values -- that have been memoized. local args = getArgs local temp = args[1] -- Memoizes the nil self:assertNumberOfIterations(0, ipairs, args)end

function suite:testDeletedArgsInPairs -- Test that when we use pairs, we don't iterate over any values that have -- been explicitly set to nil. local args = getArgs args[1] = nil self:assertNumberOfIterations(0, pairs, args)end

function suite:testDeletedArgsInIpairs -- Test that when we use ipairs, we don't iterate over any values that have -- been explicitly set to nil. local args = getArgs args[1] = nil self:assertNumberOfIterations(0, ipairs, args)end

function suite:testNoNilsInPairsAfterIndex -- Test that when we use pairs, we don't iterate over any nils that -- might have been memoized after a value that is not present in the -- original args table is indexed. local args = getArgs local temp = args.someRandomValue -- Memoizes the nil self:assertNumberOfIterations(0, pairs, args)end

function suite:testNoNilsInPairsAfterNewindex -- Test that when we use pairs, we don't iterate over any nils that -- might have been memoized after a value that is not present in the -- original args table is added to the args table. local args = getArgs args.newKey = nil -- The nil is memoized self:assertNumberOfIterations(0, pairs, args)end

function suite:testNoTableLengthChangeWhileIterating -- Test that the number of arguments doesn't change if we index the -- args table while iterating. -- (Note that the equivalent test is not needed for new arg table -- indexes, as that would be a user error - doing so produces -- undetermined behaviour in Lua's next function.) local args = getArgs self:assertNumberOfIterations(3, pairs, args) for k, v in pairs(args) do local temp = args[k .. 'foo'] end self:assertNumberOfIterations(3, pairs, args)end

function suite:testPairsPrecedenceWithWhitespace local frame, parent = suite.getFrames(d.frameTitle, , d.parentTitle, ) local args = getArgs(frame) local actual for k, v in pairs(args) do actual = v end self:assertEquals(d.firstParentArg, actual) -- Check that we have actually iterated. self:assertNumberOfIterations(1, pairs, args)end

function suite:testPairsPrecedenceWithNil local frame, parent = suite.getFrames(d.frameTitle, , d.parentTitle, ) local args = getArgs(frame) local actual for k, v in pairs(args) do actual = v end self:assertEquals(d.firstParentArg, actual) -- Check that we have actually iterated. self:assertNumberOfIterations(1, pairs, args)end

function suite:testIpairsEarlyExit local mt = function mt.__index(t, k) if k

1 then return 'foo' elseif k

2 then return 'bar' elseif k

3 then error('Expanded argument 3 unnecessarily') end end function mt.__pairs(t) error('Called pairs unnecessarily') end function mt.__ipairs(t) -- Works just like the default ipairs, except respecting __index return function(t, i) local v = t[i + 1] if v ~= nil then return i + 1, v end end, t, 0 end local args = getArgs(setmetatable(mt)) for k,v in ipairs(args) do if v

'bar' then break end endend

---------------------------------------------------------------------------- Test argument translation--------------------------------------------------------------------------

function suite:testTranslationIndex local args = getArgs self:assertEquals('one', args.foo) self:assertEquals('two', args.bar) self:assertEquals('three', args.baz) self:assertEquals('four', args.qux) self:assertEquals('yep', args.untranslated)end

function suite:testTranslationPairsWithAutoBacktranslate local args = getArgs local cleanArgs = for k,v in pairs(args) do cleanArgs[k] = v end self:assertDeepEquals(cleanArgs )end

function suite:testTranslationPairsWithBacktranslate local args = getArgs local cleanArgs = for k,v in pairs(args) do cleanArgs[k] = v end self:assertDeepEquals(cleanArgs )end

function suite:testTranslationPairsWithoutBacktranslate local args = getArgs local cleanArgs = for k,v in pairs(args) do cleanArgs[k] = v end self:assertDeepEquals(cleanArgs )end

function suite:testTranslationNewindex local args = getArgs args.foo = 'changed1' args.untranslated = 'changed2' local cleanArgs = for k,v in pairs(args) do cleanArgs[k] = v end self:assertDeepEquals(cleanArgs )end

function suite:test_argument local currentFrame = mw.getCurrentFrame currentFrame.args[5] = 555; local args = getArgs(currentFrame) self:assertEquals('nil', type(args.foo))end

return suite