Module:Template test case: Difference between revisions

    (Add a "before" parameter, similar to "after" but placed before template output. Only exists in column mode (function TestCase:renderColumns). See Template:Test case/testcases#Columns format with custom headings)
    (allow suppression of headers and of individual templates, and track any "heading" arguments in Category:Test cases using heading parameters)
    Line 54: Line 54:
    getFullPage = true,
    getFullPage = true,
    getName = true,
    getName = true,
    makeHeading = true,
    makeHeader = true,
    getOutput = true
    getOutput = true
    }
    }
    Line 133: Line 133:
    end
    end


    function Template:makeHeading()
    function Template:makeHeader()
    return self.heading or self:makeBraceLink()
    return self.heading or self:makeBraceLink()
    end
    end
    Line 180: Line 180:
    -- numbered, whereas general options are not.
    -- numbered, whereas general options are not.
    local generalOptions, templateOptions = {}, {}
    local generalOptions, templateOptions = {}, {}
    do
    for k, v in pairs(options) do
    local optionNum = {} -- a unique key for option numbers inside templateOptions
    local prefix, num
    local rawTemplateOptions = {}
    if type(k) == 'string' then
    for k, v in pairs(options) do
    prefix, num = k:match('^(.-)([1-9][0-9]*)$')
    local prefix, num
    end
    if type(k) == 'string' then
    if prefix then
    prefix, num = k:match('^(.-)([1-9][0-9]*)$')
    num = tonumber(num)
    end
    templateOptions[num] = templateOptions[num] or {}
    if prefix then
    templateOptions[num][prefix] = v
    num = tonumber(num)
    else
    rawTemplateOptions[num] = rawTemplateOptions[num] or {}
    generalOptions[k] = v
    rawTemplateOptions[num][prefix] = v
    end
    rawTemplateOptions[num][optionNum] = num -- record for use in error messages
    end
    else
     
    generalOptions[k] = v
    -- Set general options
    end
    generalOptions.showcode = yesno(generalOptions.showcode)
    generalOptions.showheader = yesno(generalOptions.showheader) ~= false
    generalOptions.collapsible = yesno(generalOptions.collapsible)
    obj.options = generalOptions
     
    -- Preprocess template args
    for num, t in pairs(templateOptions) do
    if t.showtemplate ~= nil then
    t.showtemplate = yesno(t.showtemplate)
    end
    end
    end


    -- Set up first two template options tables, so that if only the
    -- Set up first two template options tables, so that if only the
    -- "template3" is specified it isn't made the first template when the
    -- "template3" is specified it isn't made the first template when the
    -- the table options array is compressed.
    -- the table options array is compressed.
    rawTemplateOptions[1] = rawTemplateOptions[1] or {}
    templateOptions[1] = templateOptions[1] or {}
    rawTemplateOptions[2] = rawTemplateOptions[2] or {}
    templateOptions[2] = templateOptions[2] or {}


    -- Allow the "template" option to override the "template1" option for
    -- Allow the "template" option to override the "template1" option for
    -- backwards compatibility with [[Module:Testcase table]].
    -- backwards compatibility with [[Module:Testcase table]].
    rawTemplateOptions[1].template = generalOptions.template
    if generalOptions.template then
    or rawTemplateOptions[1].template
    templateOptions[1].template = generalOptions.template
    end


    -- Add default template options
    -- Add default template options
    if rawTemplateOptions[1].template and not rawTemplateOptions[2].template then
    if templateOptions[1].template and not templateOptions[2].template then
    rawTemplateOptions[2].template = rawTemplateOptions[1].template ..
    templateOptions[2].template = templateOptions[1].template ..
    '/' .. obj.cfg.sandboxSubpage
    '/' .. obj.cfg.sandboxSubpage
    end
    if not templateOptions[1].template then
    templateOptions[1].title = mw.title.getCurrentTitle().basePageTitle
    end
    if not templateOptions[2].template then
    templateOptions[2].title = templateOptions[1].title:subPageTitle(
    obj.cfg.sandboxSubpage
    )
    end
     
    -- Remove template options for any templates where the showtemplate
    -- argument is false. This prevents any output for that template.
    for num, t in pairs(templateOptions) do
    if t.showtemplate == false then
    templateOptions[num] = nil
    end
    end
    if not rawTemplateOptions[1].template then
    end
    rawTemplateOptions[1].title = mw.title.getCurrentTitle().basePageTitle
     
    end
    -- Check for missing template names.
    if not rawTemplateOptions[2].template then
    for num, t in pairs(templateOptions) do
    rawTemplateOptions[2].title = rawTemplateOptions[1].title:subPageTitle(
    if not t.template and not t.title then
    obj.cfg.sandboxSubpage
    error(obj:message(
    )
    'missing-template-option-error',
    num, num
    ), 2)
    end
    end
    end


    -- Remove gaps in the numbered options
    -- Compress templateOptions table so we can iterate over it with ipairs.
    templateOptions = (function (t)
    local nums = {}
    local nums = {}
    for num in pairs(rawTemplateOptions) do
    for num in pairs(t) do
    nums[#nums + 1] = num
    nums[#nums + 1] = num
    end
    end
    table.sort(nums)
    table.sort(nums)
    local ret = {}
    for i, num in ipairs(nums) do
    for i, num in ipairs(nums) do
    templateOptions[i] = rawTemplateOptions[num]
    ret[i] = t[num]
    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
    return ret
     
    end)(templateOptions)
    -- Set general options
    generalOptions.showcode = yesno(generalOptions.showcode)
    generalOptions.collapsible = yesno(generalOptions.collapsible)
    obj.options = generalOptions


    -- Make the template objects
    -- Make the template objects
    Line 255: Line 269:
    for i, t in ipairs(templateOptions) do
    for i, t in ipairs(templateOptions) do
    table.insert(obj.templates, Template.new(invocationObj, t))
    table.insert(obj.templates, Template.new(invocationObj, t))
    end
    -- Add tracking categories. At the moment we are only tracking templates
    -- that use any "heading" parameters.
    obj.categories = {}
    for k, v in pairs(options) do
    if type(k) == 'string' and k:find('heading') then
    categories['Test cases using heading parameters'] = true
    break
    end
    end
    end


    Line 302: Line 326:
    :tag('th')
    :tag('th')
    :css('background-color', isEqual and 'lightgreen' or 'yellow')
    :css('background-color', isEqual and 'lightgreen' or 'yellow')
    :wikitext(self.options.title or self.templates[1]:makeHeading())
    :wikitext(self.options.title or self.templates[1]:makeHeader())
    :done()
    :done()
    :done()
    :done()
    Line 322: Line 346:


    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
    if self.options.showheader then
    local headingRow = tableroot:tag('tr')
    -- Caption
    if self.options.rowheader then
    tableroot
    -- rowheader is correct here. We need to add another th cell if
    :addClass(self.options.class)
    -- rowheader is set further down, even if heading0 is missing.
    :cssText(self.options.style)
    headingRow:tag('th'):wikitext(self.options.heading0)
    :tag('caption')
    end
    :wikitext(self.options.caption or self:message('columns-header'))
    local width
     
    if #self.templates > 0 then
    -- Headers
    width = tostring(math.floor(100 / #self.templates)) .. '%'
    local headerRow = tableroot:tag('tr')
    else
    if self.options.rowheader then
    width = '100%'
    -- rowheader is correct here. We need to add another th cell if
    end
    -- rowheader is set further down, even if heading0 is missing.
    for i, obj in ipairs(self.templates) do
    headerRow:tag('th'):wikitext(self.options.heading0)
    headingRow
    end
    :tag('th')
    local width
    :css('width', width)
    if #self.templates > 0 then
    :wikitext(obj:makeHeading())
    width = tostring(math.floor(100 / #self.templates)) .. '%'
    else
    width = '100%'
    end
    for i, obj in ipairs(self.templates) do
    headerRow
    :tag('th')
    :css('width', width)
    :wikitext(obj:makeHeader())
    end
    end
    end


    Line 389: Line 417:
    for _, obj in ipairs(self.templates) do
    for _, obj in ipairs(self.templates) do
    -- Build the row HTML
    -- Build the row HTML
    tableroot
    if self.options.showheader then
    :tag('tr')
    tableroot:tag('tr'):tag('td')
    :tag('td')
    :css('text-align', 'center')
    :css('text-align', 'center')
    :css('font-weight', 'bold')
    :css('font-weight', 'bold')
    :wikitext(obj:makeHeader())
    :wikitext(obj:makeHeading())
    end
    :done()
    tableroot:tag('tr'):tag('td')
    :done()
    :newline()
    :tag('tr')
    :wikitext(self:getTemplateOutput(obj))
    :tag('td')
    :newline()
    :wikitext(self:getTemplateOutput(obj))
    end
    end


    Line 431: Line 456:
    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:makeHeading()
    if self.options.showheader then
    ret[#ret + 1] = obj:makeHeader()
    end
    ret[#ret + 1] = self:getTemplateOutput(obj)
    ret[#ret + 1] = self:getTemplateOutput(obj)
    end
    end
    Line 443: Line 470:
    if self.options.collapsible then
    if self.options.collapsible then
    ret = self:makeCollapsible(ret)
    ret = self:makeCollapsible(ret)
    end
    for cat in pairs(self.categories) do
    ret = ret .. string.format('[[Category:%s]]', cat)
    end
    end
    return ret
    return ret