Difference between revisions of "Module:List/testcases"
Jump to navigation
Jump to search
blackwiki>Mr. Stradivarius (start rewriting the test cases) |
m (43 revisions imported) |
||
| (18 intermediate revisions by 3 users not shown) | |||
| Line 21: | Line 21: | ||
d.item1 = 'Foo' | d.item1 = 'Foo' | ||
d.item2 = 'Bar' | d.item2 = 'Bar' | ||
| + | d.itemNested = '\n*Subitem 1\n*Subitem 2' -- The leading LF must not be trimmed from such item | ||
| − | -- Styles | + | -- Styles and classes |
d.arbitraryStyle = 'text-align: right' | d.arbitraryStyle = 'text-align: right' | ||
| + | d.arbitraryValue = 'some value' | ||
| + | d.arbitraryClass = 'someclass' | ||
| + | d.arbitraryClass2 = 'someclass2' | ||
| + | d.hlist = 'hlist hlist-separated' | ||
| + | d.plainlist = 'plainlist' | ||
-- Parameter names | -- Parameter names | ||
| − | d.itemStyleParam1 = ' | + | d.itemStyleParam1 = 'item1_style' |
| + | d.itemValueParam1 = 'item1_value' | ||
| + | |||
| + | -- Attributes | ||
| + | d.arbitraryStart = '5' | ||
| + | |||
| + | -- Tracking categories | ||
| + | d.trackingCategory = '[[Category:List templates with deprecated parameters]]' | ||
| + | |||
| + | -------------------------------------------------------------------------------- | ||
| + | -- Helper functions | ||
| + | -------------------------------------------------------------------------------- | ||
| + | |||
| + | function suite:assertArrayContainsString(expected, t) | ||
| + | -- This only works on arrays that only contain strings. | ||
| + | local sep = '|SEPARATOR|' | ||
| + | local concatenated = sep .. table.concat(t, sep) .. sep | ||
| + | self:assertStringContains(sep .. expected .. sep, concatenated, true) | ||
| + | end | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
| Line 46: | Line 70: | ||
self:assertEquals(d.item1, data.items[1].content) | self:assertEquals(d.item1, data.items[1].content) | ||
self:assertEquals(d.item2, data.items[2].content) | self:assertEquals(d.item2, data.items[2].content) | ||
| + | end | ||
| + | |||
| + | function suite:testDataItemStyle1() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {d.item1, [d.itemStyleParam1] = d.arbitraryStyle}) | ||
| + | self:assertEquals(d.arbitraryStyle, data.items[1].style) | ||
| + | end | ||
| + | |||
| + | function suite:testDataItemStyle1NoContent() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {[d.itemStyleParam1] = d.arbitraryStyle}) | ||
| + | self:assertEquals(nil, data.items[1]) | ||
| + | end | ||
| + | |||
| + | function suite:testDataItemValue1() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {d.item1, [d.itemValueParam1] = d.arbitraryValue}) | ||
| + | self:assertEquals(d.arbitraryValue, data.items[1].value) | ||
| + | end | ||
| + | |||
| + | function suite:testDataItemValue1NoContent() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {[d.itemValueParam1] = d.arbitraryValue}) | ||
| + | self:assertEquals(nil, data.items[1]) | ||
end | end | ||
function suite:testDataItemStyle() | function suite:testDataItemStyle() | ||
| − | local data = mList.makeListData(d.bulletedFunc, {d. | + | local data = mList.makeListData(d.bulletedFunc, {item_style = d.arbitraryStyle}) |
| + | self:assertEquals(d.arbitraryStyle, data.itemStyle) | ||
| + | end | ||
| + | |||
| + | function suite:testDataListStyle() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {list_style = d.arbitraryStyle}) | ||
| + | self:assertEquals(d.arbitraryStyle, data.listStyle) | ||
| + | end | ||
| + | |||
| + | function suite:testDataStart() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {start = d.arbitraryStart}) | ||
| + | self:assertEquals(d.arbitraryStart, data.start) | ||
| + | end | ||
| + | |||
| + | function suite:testDataHorizontalNumberingFix() | ||
| + | local data = mList.makeListData(d.horizontalOrderedFunc, {start = '5'}) | ||
| + | self:assertEquals('5', data.start) | ||
| + | self:assertEquals('listitem 4', data.counterReset) | ||
| + | end | ||
| + | |||
| + | function suite:testDataHorizontalNumberingFixBadInput() | ||
| + | local data = mList.makeListData(d.horizontalOrderedFunc, {start = 'foo'}) | ||
| + | self:assertEquals('foo', data.start) | ||
| + | self:assertEquals(nil, data.counterReset) | ||
| + | end | ||
| + | |||
| + | function suite:testDataHorizontalNumberingFixNumberInput() | ||
| + | local data = mList.makeListData(d.horizontalOrderedFunc, {start = 6}) | ||
| + | self:assertEquals(6, data.start) | ||
| + | self:assertEquals('listitem 5', data.counterReset) | ||
| + | end | ||
| + | |||
| + | function suite:testDataListTag() | ||
| + | self:assertEquals('ul', mList.makeListData(d.bulletedFunc, {}).listTag) | ||
| + | self:assertEquals('ul', mList.makeListData(d.horizontalFunc, {}).listTag) | ||
| + | self:assertEquals('ul', mList.makeListData(d.unbulletedFunc, {}).listTag) | ||
| + | self:assertEquals('ol', mList.makeListData(d.orderedFunc, {}).listTag) | ||
| + | self:assertEquals('ol', mList.makeListData(d.horizontalOrderedFunc, {}).listTag) | ||
| + | end | ||
| + | |||
| + | function suite:testDataListStyleType() | ||
| + | self:assertEquals('foo', mList.makeListData(d.orderedFunc, {list_style_type = 'foo'}).listStyleType) | ||
| + | self:assertEquals('foo', mList.makeListData(d.horizontalOrderedFunc, {list_style_type = 'foo'}).listStyleType) | ||
| + | self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {list_style_type = 'foo'}).listStyleType) | ||
| + | end | ||
| + | |||
| + | function suite:testDataListStyleTypeAltSyntax() | ||
| + | self:assertEquals('foo', mList.makeListData(d.orderedFunc, {['list-style-type'] = 'foo'}).listStyleType) | ||
| + | self:assertEquals('foo', mList.makeListData(d.horizontalOrderedFunc, {['list-style-type'] = 'foo'}).listStyleType) | ||
| + | self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {['list-style-type'] = 'foo'}).listStyleType) | ||
| + | end | ||
| + | |||
| + | function suite:testDataValidType() | ||
| + | self:assertEquals('1', mList.makeListData(d.orderedFunc, {type = '1'}).type) | ||
| + | self:assertEquals('A', mList.makeListData(d.orderedFunc, {type = 'A'}).type) | ||
| + | self:assertEquals('a', mList.makeListData(d.orderedFunc, {type = 'a'}).type) | ||
| + | self:assertEquals('I', mList.makeListData(d.orderedFunc, {type = 'I'}).type) | ||
| + | self:assertEquals('i', mList.makeListData(d.orderedFunc, {type = 'i'}).type) | ||
| + | end | ||
| + | |||
| + | function suite:testDataInvalidType() | ||
| + | local data = mList.makeListData(d.orderedFunc, {type = 'foo'}) | ||
| + | self:assertEquals(nil, data.type) | ||
| + | self:assertEquals('foo', data.listStyleType) | ||
| + | end | ||
| + | |||
| + | function suite:testDataTypeByListType() | ||
| + | self:assertEquals('1', mList.makeListData(d.orderedFunc, {type = '1'}).type) | ||
| + | self:assertEquals('1', mList.makeListData(d.horizontalOrderedFunc, {type = '1'}).type) | ||
| + | self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {type = '1'}).type) | ||
| + | end | ||
| + | |||
| + | function suite:testDataIndent() | ||
| + | self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = 1}).marginLeft) | ||
| + | self:assertEquals('3.2em', mList.makeListData(d.horizontalFunc, {indent = 2}).marginLeft) | ||
| + | self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = '1'}).marginLeft) | ||
| + | self:assertEquals(nil, mList.makeListData(d.horizontalFunc, {}).marginLeft) | ||
| + | end | ||
| + | |||
| + | function suite:testDataIndentByListType() | ||
| + | self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = 1}).marginLeft) | ||
| + | self:assertEquals('1.6em', mList.makeListData(d.horizontalOrderedFunc, {indent = 1}).marginLeft) | ||
| + | self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {indent = 1}).marginLeft) | ||
| + | self:assertEquals(nil, mList.makeListData(d.unbulletedFunc, {indent = 1}).marginLeft) | ||
| + | self:assertEquals(nil, mList.makeListData(d.orderedFunc, {indent = 1}).marginLeft) | ||
| + | end | ||
| + | |||
| + | function suite:testDataStyle() | ||
| + | self:assertEquals(d.arbitraryStyle, mList.makeListData(d.horizontalFunc, {style = d.arbitraryStyle}).style) | ||
| + | end | ||
| + | |||
| + | function suite:testDataClass() | ||
| + | self:assertArrayContainsString(d.arbitraryClass, mList.makeListData(d.bulletedFunc, {class = d.arbitraryClass}).classes) | ||
| + | end | ||
| + | |||
| + | function suite:testDataListTypeClasses() | ||
| + | self:assertArrayContainsString(d.hlist, mList.makeListData(d.horizontalFunc, {}).classes) | ||
| + | self:assertArrayContainsString(d.hlist, mList.makeListData(d.horizontalOrderedFunc, {}).classes) | ||
| + | self:assertArrayContainsString(d.plainlist, mList.makeListData(d.unbulletedFunc, {}).classes) | ||
| + | end | ||
| + | |||
| + | -------------------------------------------------------------------------------- | ||
| + | -- Test deprecated parameters | ||
| + | -------------------------------------------------------------------------------- | ||
| + | |||
| + | function suite:testDeprecatedItemStyle1() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {d.item1, item_style1 = d.arbitraryStyle}) | ||
self:assertEquals(d.arbitraryStyle, data.items[1].style) | self:assertEquals(d.arbitraryStyle, data.items[1].style) | ||
| + | end | ||
| + | |||
| + | function suite:testDeprecatedItemStyle1NoContent() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {item_style1 = d.arbitraryStyle}) | ||
| + | self:assertEquals(nil, data.items[1]) | ||
| + | end | ||
| + | |||
| + | function suite:testDeprecatedValueStyle1() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {d.item1, item_value1 = d.arbitraryStyle}) | ||
| + | self:assertEquals(d.arbitraryStyle, data.items[1].value) | ||
| + | end | ||
| + | |||
| + | function suite:testDeprecatedValueStyle1NoContent() | ||
| + | local data = mList.makeListData(d.bulletedFunc, {item_value1 = d.arbitraryStyle}) | ||
| + | self:assertEquals(nil, data.items[1]) | ||
| + | end | ||
| + | |||
| + | -------------------------------------------------------------------------------- | ||
| + | -- Test tracking categories | ||
| + | -------------------------------------------------------------------------------- | ||
| + | |||
| + | function suite:testTrackingCategoriesItem1Style() | ||
| + | local result = mList.renderTrackingCategories{item1_style = d.arbitraryStyle} | ||
| + | self:assertEquals('', result) | ||
| + | end | ||
| + | |||
| + | function suite:testTrackingCategoriesItemStyle1() | ||
| + | local result = mList.renderTrackingCategories{item_style1 = d.arbitraryStyle} | ||
| + | self:assertEquals(d.trackingCategory, result) | ||
| + | end | ||
| + | |||
| + | function suite:testTrackingCategoriesItemStyle4() | ||
| + | local result = mList.renderTrackingCategories{item_style4 = d.arbitraryStyle} | ||
| + | self:assertEquals(d.trackingCategory, result) | ||
| + | end | ||
| + | |||
| + | function suite:testTrackingCategoriesItemValue1() | ||
| + | local result = mList.renderTrackingCategories{item_value1 = d.arbitraryValue} | ||
| + | self:assertEquals(d.trackingCategory, result) | ||
| + | end | ||
| + | |||
| + | -------------------------------------------------------------------------------- | ||
| + | -- Test renderList | ||
| + | -------------------------------------------------------------------------------- | ||
| + | |||
| + | function suite.makeDataWithOneItem(args) | ||
| + | local data = {} | ||
| + | data.classes = {} | ||
| + | data.items = {} | ||
| + | data.items[1] = {content = d.item1} | ||
| + | for k, v in pairs(args or {}) do | ||
| + | data[k] = v | ||
| + | end | ||
| + | return data | ||
| + | end | ||
| + | |||
| + | function suite.cleanPattern(s) | ||
| + | -- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally. | ||
| + | s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1') | ||
| + | return s | ||
| + | end | ||
| + | |||
| + | function suite.makePattern(tag, attr, s1, s2) | ||
| + | -- For making a pattern to use with assertStringContains inside a specific attribute and HTML tag. | ||
| + | s1 = suite.cleanPattern(s1) | ||
| + | if s2 then | ||
| + | s2 = suite.cleanPattern(s2) | ||
| + | end | ||
| + | local ssep = '' | ||
| + | if s2 then | ||
| + | ssep = '%s*:%s*' | ||
| + | end | ||
| + | s2 = s2 or '' | ||
| + | return string.format( | ||
| + | '<%s[^>]-%s="[^">]-%s%s%s[^">]-"[^>]->', | ||
| + | tag, | ||
| + | attr, | ||
| + | s1, | ||
| + | ssep, | ||
| + | s2 | ||
| + | ) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderNoItems() | ||
| + | self:assertEquals('', mList.renderList{}) | ||
| + | self:assertEquals('', mList.renderList{items = {}}) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderOneItem() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | self:assertStringContains('^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$', mList.renderList(data)) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderTwoItems() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | data.items[2] = {content = d.item2} | ||
| + | self:assertStringContains('^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*<li>%s*' .. self.cleanPattern(d.item2) .. '%s*</li>%s*</ul>%s*</div>$', mList.renderList(data)) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderOneClass() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | data.classes[1] = d.arbitraryClass | ||
| + | self:assertStringContains('<div class="' .. d.arbitraryClass .. '">', mList.renderList(data), true) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderTwoClasses() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | data.classes[1] = d.arbitraryClass | ||
| + | data.classes[2] = d.arbitraryClass2 | ||
| + | local pattern = self.makePattern('div', 'class', d.arbitraryClass .. ' ' .. d.arbitraryClass2) | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderMarginLeft() | ||
| + | local data = self.makeDataWithOneItem{marginLeft = '5px'} | ||
| + | local pattern = self.makePattern('div', 'style', 'margin-left', '5px') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderStyle() | ||
| + | local data = self.makeDataWithOneItem{style = 'foo:bar'} | ||
| + | local pattern = self.makePattern('div', 'style', 'foo:bar') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderListTag() | ||
| + | local data = self.makeDataWithOneItem{listTag = 'ol'} | ||
| + | self:assertEquals('<div><ol><li>' .. d.item1 .. '</li></ol></div>', mList.renderList(data)) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderStart() | ||
| + | local data = self.makeDataWithOneItem{start = '7'} | ||
| + | local pattern = self.makePattern('ul', 'start', '7') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderStartNumber() | ||
| + | local data = self.makeDataWithOneItem{start = 7} | ||
| + | local pattern = self.makePattern('ul', 'start', '7') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderType() | ||
| + | local data = self.makeDataWithOneItem{type = 'i'} | ||
| + | local pattern = self.makePattern('ul', 'type', 'i') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderCounterReset() | ||
| + | local data = self.makeDataWithOneItem{counterReset = 'item 3'} | ||
| + | local pattern = self.makePattern('ul', 'style', 'counter-reset', 'item 3') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderListStyleType() | ||
| + | local data = self.makeDataWithOneItem{listStyleType = 'roman'} | ||
| + | local pattern = self.makePattern('ul', 'style', 'list-style-type', 'roman') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderListStyle() | ||
| + | local data = self.makeDataWithOneItem{listStyle = 'bar:baz'} | ||
| + | local pattern = self.makePattern('ul', 'style', 'bar:baz') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderItemStyle() | ||
| + | local data = self.makeDataWithOneItem{itemStyle = 'qux:foo'} | ||
| + | local pattern = self.makePattern('li', 'style', 'qux:foo') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderItemStyleTwoItems() | ||
| + | local data = self.makeDataWithOneItem{itemStyle = 'bar:foo'} | ||
| + | data.items[2] = {content = d.item2} | ||
| + | local tagPattern = self.makePattern('li', 'style', 'bar:foo') | ||
| + | local pattern = tagPattern .. d.item1 .. '</li>' .. tagPattern .. d.item2 | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderItem1Style() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | data.items[1].style = 'baz:foo' | ||
| + | local pattern = self.makePattern('li', 'style', 'baz:foo') | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | function suite:testRenderItem1Value() | ||
| + | local data = self.makeDataWithOneItem() | ||
| + | data.items[1].value = d.arbitraryValue | ||
| + | local pattern = self.makePattern('li', 'value', d.arbitraryValue) | ||
| + | self:assertStringContains(pattern, mList.renderList(data), false) | ||
| + | end | ||
| + | |||
| + | -------------------------------------------------------------------------------- | ||
| + | -- Whole-module tests | ||
| + | -------------------------------------------------------------------------------- | ||
| + | |||
| + | function suite:testBulleted() | ||
| + | local actual = mList[d.bulletedFunc]{d.item1} | ||
| + | local pattern = '^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testUnbulleted() | ||
| + | local actual = mList[d.unbulletedFunc]{d.item1} | ||
| + | local pattern = '^' .. self.makePattern('div', 'class', 'plainlist') .. '%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testHorizontal() | ||
| + | local actual = mList[d.horizontalFunc]{d.item1} | ||
| + | local pattern = '^' .. self.makePattern('div', 'class', 'hlist') .. '%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testOrdered() | ||
| + | local actual = mList[d.orderedFunc]{d.item1} | ||
| + | local pattern = '^<div>%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ol>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testHorizontalOrdered() | ||
| + | local actual = mList[d.horizontalOrderedFunc]{d.item1} | ||
| + | local pattern = '^' .. self.makePattern('div', 'class', 'hlist') .. '%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ol>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testTrimming() | ||
| + | local actual = mList[d.orderedFunc]{'\n Foo \n'} | ||
| + | -- Now many templates expect the arguments to be trimmed | ||
| + | local pattern = '^<div>%s*<ol>%s*<li>' .. self.cleanPattern('Foo') .. '</li>%s*</ol>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
| + | end | ||
| + | |||
| + | function suite:testNested() | ||
| + | local actual = mList[d.orderedFunc]{d.itemNested} | ||
| + | local pattern = '^<div>%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.itemNested) .. '%s*</li>%s*</ol>%s*</div>$' | ||
| + | self:assertStringContains(pattern, actual, false) | ||
end | end | ||
return suite | return suite | ||
Latest revision as of 06:18, 27 September 2020
Documentation for this module may be created at Module:List/testcases/doc
-- Unit tests for [[Module:List]]. Click talk page to run tests.
local mList = require('Module:List/sandbox')
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()
--------------------------------------------------------------------------------
-- Default values
--------------------------------------------------------------------------------
local d = {}
-- Function names
d.bulletedFunc = 'bulleted'
d.unbulletedFunc = 'unbulleted'
d.horizontalFunc = 'horizontal'
d.orderedFunc = 'ordered'
d.horizontalOrderedFunc = 'horizontal_ordered'
-- List items
d.item1 = 'Foo'
d.item2 = 'Bar'
d.itemNested = '\n*Subitem 1\n*Subitem 2' -- The leading LF must not be trimmed from such item
-- Styles and classes
d.arbitraryStyle = 'text-align: right'
d.arbitraryValue = 'some value'
d.arbitraryClass = 'someclass'
d.arbitraryClass2 = 'someclass2'
d.hlist = 'hlist hlist-separated'
d.plainlist = 'plainlist'
-- Parameter names
d.itemStyleParam1 = 'item1_style'
d.itemValueParam1 = 'item1_value'
-- Attributes
d.arbitraryStart = '5'
-- Tracking categories
d.trackingCategory = '[[Category:List templates with deprecated parameters]]'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
function suite:assertArrayContainsString(expected, t)
-- This only works on arrays that only contain strings.
local sep = '|SEPARATOR|'
local concatenated = sep .. table.concat(t, sep) .. sep
self:assertStringContains(sep .. expected .. sep, concatenated, true)
end
--------------------------------------------------------------------------------
-- Test makeListData
--------------------------------------------------------------------------------
function suite:testDataBlank()
local data = mList.makeListData(d.bulletedFunc, {})
self:assertEquals('table', type(data))
end
function suite:testDataOneItem()
local data = mList.makeListData(d.bulletedFunc, {d.item1})
self:assertEquals(d.item1, data.items[1].content)
end
function suite:testDataTwoItems()
local data = mList.makeListData(d.bulletedFunc, {d.item1, d.item2})
self:assertEquals(d.item1, data.items[1].content)
self:assertEquals(d.item2, data.items[2].content)
end
function suite:testDataItemStyle1()
local data = mList.makeListData(d.bulletedFunc, {d.item1, [d.itemStyleParam1] = d.arbitraryStyle})
self:assertEquals(d.arbitraryStyle, data.items[1].style)
end
function suite:testDataItemStyle1NoContent()
local data = mList.makeListData(d.bulletedFunc, {[d.itemStyleParam1] = d.arbitraryStyle})
self:assertEquals(nil, data.items[1])
end
function suite:testDataItemValue1()
local data = mList.makeListData(d.bulletedFunc, {d.item1, [d.itemValueParam1] = d.arbitraryValue})
self:assertEquals(d.arbitraryValue, data.items[1].value)
end
function suite:testDataItemValue1NoContent()
local data = mList.makeListData(d.bulletedFunc, {[d.itemValueParam1] = d.arbitraryValue})
self:assertEquals(nil, data.items[1])
end
function suite:testDataItemStyle()
local data = mList.makeListData(d.bulletedFunc, {item_style = d.arbitraryStyle})
self:assertEquals(d.arbitraryStyle, data.itemStyle)
end
function suite:testDataListStyle()
local data = mList.makeListData(d.bulletedFunc, {list_style = d.arbitraryStyle})
self:assertEquals(d.arbitraryStyle, data.listStyle)
end
function suite:testDataStart()
local data = mList.makeListData(d.bulletedFunc, {start = d.arbitraryStart})
self:assertEquals(d.arbitraryStart, data.start)
end
function suite:testDataHorizontalNumberingFix()
local data = mList.makeListData(d.horizontalOrderedFunc, {start = '5'})
self:assertEquals('5', data.start)
self:assertEquals('listitem 4', data.counterReset)
end
function suite:testDataHorizontalNumberingFixBadInput()
local data = mList.makeListData(d.horizontalOrderedFunc, {start = 'foo'})
self:assertEquals('foo', data.start)
self:assertEquals(nil, data.counterReset)
end
function suite:testDataHorizontalNumberingFixNumberInput()
local data = mList.makeListData(d.horizontalOrderedFunc, {start = 6})
self:assertEquals(6, data.start)
self:assertEquals('listitem 5', data.counterReset)
end
function suite:testDataListTag()
self:assertEquals('ul', mList.makeListData(d.bulletedFunc, {}).listTag)
self:assertEquals('ul', mList.makeListData(d.horizontalFunc, {}).listTag)
self:assertEquals('ul', mList.makeListData(d.unbulletedFunc, {}).listTag)
self:assertEquals('ol', mList.makeListData(d.orderedFunc, {}).listTag)
self:assertEquals('ol', mList.makeListData(d.horizontalOrderedFunc, {}).listTag)
end
function suite:testDataListStyleType()
self:assertEquals('foo', mList.makeListData(d.orderedFunc, {list_style_type = 'foo'}).listStyleType)
self:assertEquals('foo', mList.makeListData(d.horizontalOrderedFunc, {list_style_type = 'foo'}).listStyleType)
self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {list_style_type = 'foo'}).listStyleType)
end
function suite:testDataListStyleTypeAltSyntax()
self:assertEquals('foo', mList.makeListData(d.orderedFunc, {['list-style-type'] = 'foo'}).listStyleType)
self:assertEquals('foo', mList.makeListData(d.horizontalOrderedFunc, {['list-style-type'] = 'foo'}).listStyleType)
self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {['list-style-type'] = 'foo'}).listStyleType)
end
function suite:testDataValidType()
self:assertEquals('1', mList.makeListData(d.orderedFunc, {type = '1'}).type)
self:assertEquals('A', mList.makeListData(d.orderedFunc, {type = 'A'}).type)
self:assertEquals('a', mList.makeListData(d.orderedFunc, {type = 'a'}).type)
self:assertEquals('I', mList.makeListData(d.orderedFunc, {type = 'I'}).type)
self:assertEquals('i', mList.makeListData(d.orderedFunc, {type = 'i'}).type)
end
function suite:testDataInvalidType()
local data = mList.makeListData(d.orderedFunc, {type = 'foo'})
self:assertEquals(nil, data.type)
self:assertEquals('foo', data.listStyleType)
end
function suite:testDataTypeByListType()
self:assertEquals('1', mList.makeListData(d.orderedFunc, {type = '1'}).type)
self:assertEquals('1', mList.makeListData(d.horizontalOrderedFunc, {type = '1'}).type)
self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {type = '1'}).type)
end
function suite:testDataIndent()
self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = 1}).marginLeft)
self:assertEquals('3.2em', mList.makeListData(d.horizontalFunc, {indent = 2}).marginLeft)
self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = '1'}).marginLeft)
self:assertEquals(nil, mList.makeListData(d.horizontalFunc, {}).marginLeft)
end
function suite:testDataIndentByListType()
self:assertEquals('1.6em', mList.makeListData(d.horizontalFunc, {indent = 1}).marginLeft)
self:assertEquals('1.6em', mList.makeListData(d.horizontalOrderedFunc, {indent = 1}).marginLeft)
self:assertEquals(nil, mList.makeListData(d.bulletedFunc, {indent = 1}).marginLeft)
self:assertEquals(nil, mList.makeListData(d.unbulletedFunc, {indent = 1}).marginLeft)
self:assertEquals(nil, mList.makeListData(d.orderedFunc, {indent = 1}).marginLeft)
end
function suite:testDataStyle()
self:assertEquals(d.arbitraryStyle, mList.makeListData(d.horizontalFunc, {style = d.arbitraryStyle}).style)
end
function suite:testDataClass()
self:assertArrayContainsString(d.arbitraryClass, mList.makeListData(d.bulletedFunc, {class = d.arbitraryClass}).classes)
end
function suite:testDataListTypeClasses()
self:assertArrayContainsString(d.hlist, mList.makeListData(d.horizontalFunc, {}).classes)
self:assertArrayContainsString(d.hlist, mList.makeListData(d.horizontalOrderedFunc, {}).classes)
self:assertArrayContainsString(d.plainlist, mList.makeListData(d.unbulletedFunc, {}).classes)
end
--------------------------------------------------------------------------------
-- Test deprecated parameters
--------------------------------------------------------------------------------
function suite:testDeprecatedItemStyle1()
local data = mList.makeListData(d.bulletedFunc, {d.item1, item_style1 = d.arbitraryStyle})
self:assertEquals(d.arbitraryStyle, data.items[1].style)
end
function suite:testDeprecatedItemStyle1NoContent()
local data = mList.makeListData(d.bulletedFunc, {item_style1 = d.arbitraryStyle})
self:assertEquals(nil, data.items[1])
end
function suite:testDeprecatedValueStyle1()
local data = mList.makeListData(d.bulletedFunc, {d.item1, item_value1 = d.arbitraryStyle})
self:assertEquals(d.arbitraryStyle, data.items[1].value)
end
function suite:testDeprecatedValueStyle1NoContent()
local data = mList.makeListData(d.bulletedFunc, {item_value1 = d.arbitraryStyle})
self:assertEquals(nil, data.items[1])
end
--------------------------------------------------------------------------------
-- Test tracking categories
--------------------------------------------------------------------------------
function suite:testTrackingCategoriesItem1Style()
local result = mList.renderTrackingCategories{item1_style = d.arbitraryStyle}
self:assertEquals('', result)
end
function suite:testTrackingCategoriesItemStyle1()
local result = mList.renderTrackingCategories{item_style1 = d.arbitraryStyle}
self:assertEquals(d.trackingCategory, result)
end
function suite:testTrackingCategoriesItemStyle4()
local result = mList.renderTrackingCategories{item_style4 = d.arbitraryStyle}
self:assertEquals(d.trackingCategory, result)
end
function suite:testTrackingCategoriesItemValue1()
local result = mList.renderTrackingCategories{item_value1 = d.arbitraryValue}
self:assertEquals(d.trackingCategory, result)
end
--------------------------------------------------------------------------------
-- Test renderList
--------------------------------------------------------------------------------
function suite.makeDataWithOneItem(args)
local data = {}
data.classes = {}
data.items = {}
data.items[1] = {content = d.item1}
for k, v in pairs(args or {}) do
data[k] = v
end
return data
end
function suite.cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
return s
end
function suite.makePattern(tag, attr, s1, s2)
-- For making a pattern to use with assertStringContains inside a specific attribute and HTML tag.
s1 = suite.cleanPattern(s1)
if s2 then
s2 = suite.cleanPattern(s2)
end
local ssep = ''
if s2 then
ssep = '%s*:%s*'
end
s2 = s2 or ''
return string.format(
'<%s[^>]-%s="[^">]-%s%s%s[^">]-"[^>]->',
tag,
attr,
s1,
ssep,
s2
)
end
function suite:testRenderNoItems()
self:assertEquals('', mList.renderList{})
self:assertEquals('', mList.renderList{items = {}})
end
function suite:testRenderOneItem()
local data = self.makeDataWithOneItem()
self:assertStringContains('^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$', mList.renderList(data))
end
function suite:testRenderTwoItems()
local data = self.makeDataWithOneItem()
data.items[2] = {content = d.item2}
self:assertStringContains('^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*<li>%s*' .. self.cleanPattern(d.item2) .. '%s*</li>%s*</ul>%s*</div>$', mList.renderList(data))
end
function suite:testRenderOneClass()
local data = self.makeDataWithOneItem()
data.classes[1] = d.arbitraryClass
self:assertStringContains('<div class="' .. d.arbitraryClass .. '">', mList.renderList(data), true)
end
function suite:testRenderTwoClasses()
local data = self.makeDataWithOneItem()
data.classes[1] = d.arbitraryClass
data.classes[2] = d.arbitraryClass2
local pattern = self.makePattern('div', 'class', d.arbitraryClass .. ' ' .. d.arbitraryClass2)
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderMarginLeft()
local data = self.makeDataWithOneItem{marginLeft = '5px'}
local pattern = self.makePattern('div', 'style', 'margin-left', '5px')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderStyle()
local data = self.makeDataWithOneItem{style = 'foo:bar'}
local pattern = self.makePattern('div', 'style', 'foo:bar')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderListTag()
local data = self.makeDataWithOneItem{listTag = 'ol'}
self:assertEquals('<div><ol><li>' .. d.item1 .. '</li></ol></div>', mList.renderList(data))
end
function suite:testRenderStart()
local data = self.makeDataWithOneItem{start = '7'}
local pattern = self.makePattern('ul', 'start', '7')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderStartNumber()
local data = self.makeDataWithOneItem{start = 7}
local pattern = self.makePattern('ul', 'start', '7')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderType()
local data = self.makeDataWithOneItem{type = 'i'}
local pattern = self.makePattern('ul', 'type', 'i')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderCounterReset()
local data = self.makeDataWithOneItem{counterReset = 'item 3'}
local pattern = self.makePattern('ul', 'style', 'counter-reset', 'item 3')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderListStyleType()
local data = self.makeDataWithOneItem{listStyleType = 'roman'}
local pattern = self.makePattern('ul', 'style', 'list-style-type', 'roman')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderListStyle()
local data = self.makeDataWithOneItem{listStyle = 'bar:baz'}
local pattern = self.makePattern('ul', 'style', 'bar:baz')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderItemStyle()
local data = self.makeDataWithOneItem{itemStyle = 'qux:foo'}
local pattern = self.makePattern('li', 'style', 'qux:foo')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderItemStyleTwoItems()
local data = self.makeDataWithOneItem{itemStyle = 'bar:foo'}
data.items[2] = {content = d.item2}
local tagPattern = self.makePattern('li', 'style', 'bar:foo')
local pattern = tagPattern .. d.item1 .. '</li>' .. tagPattern .. d.item2
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderItem1Style()
local data = self.makeDataWithOneItem()
data.items[1].style = 'baz:foo'
local pattern = self.makePattern('li', 'style', 'baz:foo')
self:assertStringContains(pattern, mList.renderList(data), false)
end
function suite:testRenderItem1Value()
local data = self.makeDataWithOneItem()
data.items[1].value = d.arbitraryValue
local pattern = self.makePattern('li', 'value', d.arbitraryValue)
self:assertStringContains(pattern, mList.renderList(data), false)
end
--------------------------------------------------------------------------------
-- Whole-module tests
--------------------------------------------------------------------------------
function suite:testBulleted()
local actual = mList[d.bulletedFunc]{d.item1}
local pattern = '^<div>%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testUnbulleted()
local actual = mList[d.unbulletedFunc]{d.item1}
local pattern = '^' .. self.makePattern('div', 'class', 'plainlist') .. '%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testHorizontal()
local actual = mList[d.horizontalFunc]{d.item1}
local pattern = '^' .. self.makePattern('div', 'class', 'hlist') .. '%s*<ul>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ul>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testOrdered()
local actual = mList[d.orderedFunc]{d.item1}
local pattern = '^<div>%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ol>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testHorizontalOrdered()
local actual = mList[d.horizontalOrderedFunc]{d.item1}
local pattern = '^' .. self.makePattern('div', 'class', 'hlist') .. '%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.item1) .. '%s*</li>%s*</ol>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testTrimming()
local actual = mList[d.orderedFunc]{'\n Foo \n'}
-- Now many templates expect the arguments to be trimmed
local pattern = '^<div>%s*<ol>%s*<li>' .. self.cleanPattern('Foo') .. '</li>%s*</ol>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
function suite:testNested()
local actual = mList[d.orderedFunc]{d.itemNested}
local pattern = '^<div>%s*<ol>%s*<li>%s*' .. self.cleanPattern(d.itemNested) .. '%s*</li>%s*</ol>%s*</div>$'
self:assertStringContains(pattern, actual, false)
end
return suite