Editing Module:Template test case
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
-- | -- This module provides several methods to generate test cases. | ||
-- Load required modules | -- Load required modules | ||
Line 54: | Line 33: | ||
getFullPage = true, | getFullPage = true, | ||
getName = true, | getName = true, | ||
makeHeading = true, | |||
getOutput = true | getOutput = true | ||
} | } | ||
Line 94: | Line 73: | ||
function Template:getFullPage() | function Template:getFullPage() | ||
if | if self.template then | ||
local strippedTemplate, hasColon = self.template:gsub('^:', '', 1) | local strippedTemplate, hasColon = self.template:gsub('^:', '', 1) | ||
hasColon = hasColon > 0 | hasColon = hasColon > 0 | ||
Line 110: | Line 85: | ||
return mw.site.namespaces[10].name .. ':' .. strippedTemplate | return mw.site.namespaces[10].name .. ':' .. strippedTemplate | ||
end | end | ||
else | |||
return self.title.prefixedText | |||
end | end | ||
end | end | ||
Line 135: | Line 112: | ||
end | end | ||
function Template: | function Template:makeHeading() | ||
return self.heading or self:makeBraceLink() | return self.heading or self:makeBraceLink() | ||
end | end | ||
function Template:getInvocation(format) | function Template:getInvocation(format) | ||
local invocation = self._invocation:getInvocation | local invocation = self._invocation:getInvocation(self:getName()) | ||
if format == 'code' then | if format == 'code' then | ||
invocation = '<code>' .. mw.text.nowiki(invocation) .. '</code>' | invocation = '<code>' .. mw.text.nowiki(invocation) .. '</code>' | ||
elseif format == 'plain' then | elseif format == 'plain' then | ||
invocation = mw.text.nowiki(invocation) | invocation = mw.text.nowiki(invocation) | ||
Line 160: | Line 132: | ||
function Template:getOutput() | function Template:getOutput() | ||
return self._invocation:getOutput(self:getName()) | |||
end | end | ||
Line 181: | Line 148: | ||
columns = 'renderColumns', | columns = 'renderColumns', | ||
rows = 'renderRows', | rows = 'renderRows', | ||
inline = 'renderInline', | inline = 'renderInline', | ||
default = 'renderDefault' | default = 'renderDefault' | ||
} | } | ||
Line 194: | Line 159: | ||
-- numbered, whereas general options are not. | -- numbered, whereas general options are not. | ||
local generalOptions, templateOptions = {}, {} | local generalOptions, templateOptions = {}, {} | ||
for k, v in pairs(options) do | do | ||
local optionNum = {} -- a unique key for option numbers inside templateOptions | |||
local rawTemplateOptions = {} | |||
for k, v in pairs(options) do | |||
local prefix, num | |||
if type(k) == 'string' then | |||
prefix, num = k:match('^(.-)([1-9][0-9]*)$') | |||
end | |||
if prefix then | |||
num = tonumber(num) | |||
rawTemplateOptions[num] = rawTemplateOptions[num] or {} | |||
rawTemplateOptions[num][prefix] = v | |||
rawTemplateOptions[num][optionNum] = num -- record for use in error messages | |||
else | |||
generalOptions[k] = v | |||
end | |||
end | end | ||
-- Set up first two template options tables, so that if only the | |||
-- "template3" is specified it isn't made the first template when the | |||
-- the table options array is compressed. | |||
rawTemplateOptions[1] = rawTemplateOptions[1] or {} | |||
rawTemplateOptions[2] = rawTemplateOptions[2] or {} | |||
-- Allow the "template" option to override the "template1" option for | |||
-- backwards compatibility with [[Module:Testcase table]]. | |||
rawTemplateOptions[1].template = generalOptions.template | |||
or rawTemplateOptions[1].template | |||
-- Add default template options | |||
if rawTemplateOptions[1].template and not rawTemplateOptions[2].template then | |||
if | rawTemplateOptions[2].template = rawTemplateOptions[1].template .. | ||
'/' .. obj.cfg.sandboxSubpage | |||
end | end | ||
if not rawTemplateOptions[1].template then | |||
rawTemplateOptions[1].title = mw.title.getCurrentTitle().basePageTitle | |||
end | end | ||
if not rawTemplateOptions[2].template then | |||
rawTemplateOptions[2].title = rawTemplateOptions[1].title:subPageTitle( | |||
obj.cfg.sandboxSubpage | |||
) | |||
if not | |||
end | end | ||
-- Remove gaps in the numbered options | |||
local nums = {} | local nums = {} | ||
for num in pairs( | for num in pairs(rawTemplateOptions) do | ||
nums[#nums + 1] = num | nums[#nums + 1] = num | ||
end | end | ||
table.sort(nums) | table.sort(nums) | ||
for i, num in ipairs(nums) do | for i, num in ipairs(nums) do | ||
templateOptions[i] = rawTemplateOptions[num] | |||
end | end | ||
-- Check that there are no missing template options. | |||
for i = 3, #templateOptions do -- Defaults have already been added for 1 and 2. | |||
local t = templateOptions[i] | |||
if not t.template then | |||
local num = t[optionNum] | |||
error(obj:message( | |||
'missing-template-option-error', | |||
num, num | |||
), 2) | |||
end | |||
end | |||
end | end | ||
-- Set general options | |||
generalOptions.showcode = yesno(generalOptions.showcode) | |||
generalOptions.collapsible = yesno(generalOptions.collapsible) | |||
obj.options = generalOptions | |||
-- Make the template objects | -- Make the template objects | ||
obj.templates = {} | obj.templates = {} | ||
for i, | for i, t in ipairs(templateOptions) do | ||
table.insert(obj.templates, Template.new(invocationObj, | table.insert(obj.templates, Template.new(invocationObj, t)) | ||
end | end | ||
Line 327: | Line 256: | ||
local out = obj:getOutput() | local out = obj:getOutput() | ||
-- Remove the random parts from strip markers. | -- Remove the random parts from strip markers. | ||
out = out:gsub('( | out = out:gsub('(%cUNIQ).-(QINU%c)', '%1%2') | ||
return out | return out | ||
end | end | ||
Line 341: | Line 270: | ||
function TestCase:makeCollapsible(s) | function TestCase:makeCollapsible(s) | ||
local isEqual = self:templateOutputIsEqual() | local isEqual = self:templateOutputIsEqual() | ||
local root = mw.html.create('table') | local root = mw.html.create('table') | ||
root | root | ||
:addClass(' | :addClass('collapsible') | ||
:addClass(isEqual and 'collapsed' or nil) | |||
:css('background-color', 'transparent') | :css('background-color', 'transparent') | ||
:css('width', '100%') | :css('width', '100%') | ||
Line 387: | Line 281: | ||
:tag('th') | :tag('th') | ||
:css('background-color', isEqual and 'lightgreen' or 'yellow') | :css('background-color', isEqual and 'lightgreen' or 'yellow') | ||
:wikitext(title) | :wikitext(self.options.title or self.templates[1]:makeHeading()) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 395: | Line 289: | ||
:wikitext(s) | :wikitext(s) | ||
:newline() | :newline() | ||
return tostring(root) | return tostring(root) | ||
end | end | ||
Line 408: | Line 301: | ||
local tableroot = root:tag('table') | local tableroot = root:tag('table') | ||
tableroot | |||
:addClass(self.options.class) | |||
:cssText(self.options.style) | |||
:tag('caption') | |||
:wikitext(self.options.caption or self:message('columns-header')) | |||
-- Headings | |||
local headingRow = tableroot:tag('tr') | |||
if self.options.rowheader then | |||
-- rowheader is correct here. We need to add another th cell if | |||
-- rowheader is set further down, even if heading0 is missing. | |||
headingRow:tag('th'):wikitext(self.options.heading0) | |||
end | |||
local width | |||
if #self.templates > 0 then | |||
width = tostring(math.floor(100 / #self.templates)) .. '%' | |||
else | |||
width = '100%' | |||
end | |||
for i, obj in ipairs(self.templates) do | |||
headingRow | |||
:tag('th') | |||
:css('width', width) | |||
:wikitext(obj:makeHeading()) | |||
end | end | ||
Line 450: | Line 337: | ||
-- Template output | -- Template output | ||
for i, obj in ipairs(self.templates) do | for i, obj in ipairs(self.templates) do | ||
dataRow:tag('td') | |||
:newline() | |||
:wikitext(self:getTemplateOutput(obj)) | |||
:wikitext(self.options.after) | |||
end | end | ||
Line 499: | Line 366: | ||
for _, obj in ipairs(self.templates) do | for _, obj in ipairs(self.templates) do | ||
-- Build the row HTML | |||
tableroot | |||
-- | :tag('tr') | ||
:tag('td') | |||
:css('text-align', 'center') | :css('text-align', 'center') | ||
:css('font-weight', 'bold') | :css('font-weight', 'bold') | ||
:wikitext(obj: | :wikitext(obj:makeHeading()) | ||
:done() | |||
:done() | |||
:tag('tr') | |||
:tag('td') | |||
:newline() | |||
:wikitext(self:getTemplateOutput(obj)) | |||
: | |||
end | end | ||
Line 546: | Line 386: | ||
function TestCase:renderInline() | function TestCase:renderInline() | ||
local arrow = mw.language.getContentLanguage():getArrow('forwards') | local arrow = mw.language.getContentLanguage():getArrow('forwards') | ||
local | local list = mw.html.create('ul') | ||
list | |||
:addClass(self.options.class) | |||
:cssText(self.options.style) | |||
for i, obj in ipairs(self.templates) do | for i, obj in ipairs(self.templates) do | ||
local line = {} | local line = {} | ||
if self.options.showcode then | if self.options.showcode then | ||
line[#line + 1] = obj:getInvocation('code') | line[#line + 1] = obj:getInvocation('code') | ||
Line 556: | Line 398: | ||
line[#line + 1] = ' ' | line[#line + 1] = ' ' | ||
end | end | ||
line[#line + 1] = self:getTemplateOutput(obj) | |||
list | |||
:tag('li') | |||
:newline() | :newline() | ||
:wikitext( | :wikitext(table.concat(line)) | ||
end | end | ||
return tostring(list) | |||
return tostring( | |||
end | end | ||
Line 646: | Line 414: | ||
for i, obj in ipairs(self.templates) do | for i, obj in ipairs(self.templates) do | ||
ret[#ret + 1] = '<div style="clear: both;"></div>' | ret[#ret + 1] = '<div style="clear: both;"></div>' | ||
ret[#ret + 1] = obj:makeBraceLink() | |||
ret[#ret + 1] = self:getTemplateOutput(obj) | |||
end | end | ||
return table.concat(ret, '\n\n') | return table.concat(ret, '\n\n') | ||
Line 666: | Line 426: | ||
if self.options.collapsible then | if self.options.collapsible then | ||
ret = self:makeCollapsible(ret) | ret = self:makeCollapsible(ret) | ||
end | end | ||
return ret | return ret | ||
Line 696: | Line 453: | ||
end | end | ||
function NowikiInvocation:getInvocation( | function NowikiInvocation:getInvocation(template) | ||
template = template:gsub('%%', '%%%%') -- Escape "%" with "%%" | |||
local invocation, count = self.invocation:gsub( | local invocation, count = self.invocation:gsub( | ||
self.cfg.templateNameMagicWordPattern, | self.cfg.templateNameMagicWordPattern, | ||
template | template | ||
) | ) | ||
if | if count < 1 then | ||
error(self:message( | error(self:message( | ||
'nowiki-magic-word-error', | 'nowiki-magic-word-error', | ||
Line 711: | Line 468: | ||
end | end | ||
function NowikiInvocation:getOutput( | function NowikiInvocation:getOutput(template) | ||
local invocation = self:getInvocation( | local invocation = self:getInvocation(template) | ||
return mw.getCurrentFrame():preprocess(invocation) | return mw.getCurrentFrame():preprocess(invocation) | ||
end | end | ||
Line 732: | Line 489: | ||
end | end | ||
function TableInvocation:getInvocation( | function TableInvocation:getInvocation(template) | ||
if self.code then | if self.code then | ||
local nowikiObj = NowikiInvocation.new(self.code, self.cfg) | local nowikiObj = NowikiInvocation.new(self.code, self.cfg) | ||
return nowikiObj:getInvocation( | return nowikiObj:getInvocation(template) | ||
else | else | ||
return require('Module:Template invocation').invocation( | return require('Module:Template invocation').invocation( | ||
template, | |||
self.invokeArgs | self.invokeArgs | ||
) | ) | ||
Line 744: | Line 501: | ||
end | end | ||
function TableInvocation:getOutput( | function TableInvocation:getOutput(template) | ||
return mw.getCurrentFrame():expandTemplate{ | return mw.getCurrentFrame():expandTemplate{ | ||
title = | title = template, | ||
args = self.invokeArgs | args = self.invokeArgs | ||
} | } | ||
Line 798: | Line 549: | ||
cfg = cfg or mw.loadData(DATA_MODULE) | cfg = cfg or mw.loadData(DATA_MODULE) | ||
local invocationObj = NowikiInvocation.new(args.code, cfg) | |||
local invocationObj = NowikiInvocation.new(code, cfg) | |||
args.code = nil | args.code = nil | ||
-- Assume we want to see the code as we already passed it in. | -- Assume we want to see the code as we already passed it in. | ||
args.showcode = args.showcode or true | args.showcode = args.showcode or true |