mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-11-30 02:54:26 +00:00
d1030989bc
Rather than calling error() when nils get passed to mw.html methods, either remove whatever it was that the nil would go to (if that makes sense), or just do nothing. The seemingly inconsistent use of "not x" and "x ~= nil" is to allow any falsey value where it wouldn't be ambiguous (such as class names), but not where it could be (such as attribute values). Bug: 62982 Change-Id: I76773abbb4394aa9bb8c8a08445e019cade3b2bf
327 lines
12 KiB
Lua
327 lines
12 KiB
Lua
--[[
|
|
Tests for the mw.html module
|
|
|
|
@license GNU GPL v2+
|
|
@author Marius Hoch < hoo@online.de >
|
|
]]
|
|
|
|
local testframework = require 'Module:TestFramework'
|
|
|
|
local function getEmptyTestDiv()
|
|
return mw.html.create( 'div' )
|
|
end
|
|
|
|
local function testHelper( obj, method, ... )
|
|
return obj[method]( obj, ... )
|
|
end
|
|
|
|
-- Test attrbutes which will always be paired in the same order
|
|
local testAttrs = { foo = 'bar', ab = 'cd' }
|
|
setmetatable( testAttrs, { __pairs = function ( t )
|
|
local keys = { 'ab', 'foo' }
|
|
local i = 0
|
|
return function()
|
|
i = i + 1
|
|
if i <= #keys then
|
|
return keys[i], t[keys[i]]
|
|
end
|
|
end
|
|
end } )
|
|
|
|
|
|
-- More complex test functions
|
|
|
|
local function testMultiAddClass()
|
|
return getEmptyTestDiv():addClass( 'foo' ):addClass( 'bar' )
|
|
end
|
|
|
|
local function testCssAndCssText()
|
|
return getEmptyTestDiv():css( 'foo', 'bar' ):cssText( 'abc:def' ):css( 'g', 'h' )
|
|
end
|
|
|
|
local function testTagDone()
|
|
return getEmptyTestDiv():tag( 'span' ):done()
|
|
end
|
|
|
|
local function testNodeDone()
|
|
return getEmptyTestDiv():node( getEmptyTestDiv() ):done()
|
|
end
|
|
|
|
local function testTagNodeAllDone()
|
|
return getEmptyTestDiv():tag( 'p' ):node( getEmptyTestDiv() ):allDone()
|
|
end
|
|
|
|
local function testAttributeOverride()
|
|
return getEmptyTestDiv():attr( 'good', 'MediaWiki' ):attr( 'good', 'Wikibase' )
|
|
end
|
|
|
|
local function testAttributeRemoval()
|
|
return getEmptyTestDiv():attr( 'a', 'b' ):attr( 'a', nil )
|
|
end
|
|
|
|
local function testGetAttribute()
|
|
return getEmptyTestDiv():attr( 'town', 'Berlin' ):getAttr( 'town' )
|
|
end
|
|
|
|
local function testGetAttributeEscaping()
|
|
return getEmptyTestDiv():attr( 'foo', '<ble"&rgh>' ):getAttr( 'foo' )
|
|
end
|
|
|
|
local function testNodeSelfClosingDone()
|
|
return getEmptyTestDiv():node( mw.html.create( 'br' ) ):done()
|
|
end
|
|
|
|
local function testNodeAppendToSelfClosing()
|
|
return mw.html.create( 'img' ):node( getEmptyTestDiv() )
|
|
end
|
|
|
|
local function testWikitextAppendToSelfClosing()
|
|
return mw.html.create( 'hr' ):wikitext( 'foo' )
|
|
end
|
|
|
|
local function testCreateWithValue( val )
|
|
return mw.html.create( val ):wikitext( 'foo' ):tag( 'div' ):attr( 'a', 'b' ):allDone()
|
|
end
|
|
|
|
local function testCssRemoval()
|
|
return getEmptyTestDiv():css( 'color', 'red' ):css( 'color', nil )
|
|
end
|
|
|
|
local function testComplex()
|
|
local builder = getEmptyTestDiv()
|
|
|
|
builder:addClass( 'firstClass' ):attr( 'what', 'ever' )
|
|
|
|
builder:tag( 'meh' ):attr( 'whynot', 'Русский' ):tag( 'hr' ):attr( 'a', 'b' )
|
|
|
|
builder:node( mw.html.create( 'hr' ) )
|
|
|
|
builder:node( getEmptyTestDiv():attr( 'abc', 'def' ):css( 'width', '-1px' ) )
|
|
|
|
return builder
|
|
end
|
|
|
|
-- Tests
|
|
local tests = {
|
|
-- Simple (inline) tests
|
|
{ name = 'mw.html.create', func = mw.html.create, type='ToString',
|
|
args = { 'table' },
|
|
expect = { '<table></table>' }
|
|
},
|
|
{ name = 'mw.html.create (self closing)', func = mw.html.create, type='ToString',
|
|
args = { 'br' },
|
|
expect = { '<br />' }
|
|
},
|
|
{ name = 'mw.html.create (self closing - forced)', func = mw.html.create, type='ToString',
|
|
args = { 'div', { selfClosing = true } },
|
|
expect = { '<div />' }
|
|
},
|
|
{ name = 'mw.html.create (invalid tag 1)', func = mw.html.create, type='ToString',
|
|
args = { '$$$$' },
|
|
expect = 'Invalid tag name: $$$$'
|
|
},
|
|
{ name = 'mw.html.create (invalid tag 2)', func = mw.html.create, type='ToString',
|
|
args = { {} },
|
|
expect = 'Tag name must be a string'
|
|
},
|
|
{ name = 'mw.html.wikitext', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'wikitext', 'Plain text' },
|
|
expect = { '<div>Plain text</div>' }
|
|
},
|
|
{ name = 'mw.html.wikitext (invalid input)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'wikitext', 'Plain text', {} },
|
|
expect = 'Invalid wikitext given: Must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.newline', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'newline' },
|
|
expect = { '<div>\n</div>' }
|
|
},
|
|
{ name = 'mw.html.tag', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'tag', 'span' },
|
|
-- tag is only supposed to return the new (inner) node
|
|
expect = { '<span></span>' }
|
|
},
|
|
{ name = 'mw.html.attr', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', 'bar' },
|
|
expect = { '<div foo="bar"></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (nil noop)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', nil },
|
|
expect = { '<div></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (table 1)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', { foo = 'bar' } },
|
|
expect = { '<div foo="bar"></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (table 2)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', testAttrs },
|
|
expect = { '<div ab="cd" foo="bar"></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (invalid name 1)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', true, 'bar' },
|
|
expect = 'Invalid name given: The name must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.attr (invalid name 2)', func = testHelper,
|
|
args = { getEmptyTestDiv(), 'attr', '§§§§', 'foo' },
|
|
expect = 'Invalid attribute name: §§§§'
|
|
},
|
|
{ name = 'mw.html.attr (table no value)', func = testHelper,
|
|
args = { getEmptyTestDiv(), 'attr', { foo = 'bar' }, 'foo' },
|
|
expect = 'If a key->value table is given as first parameter, value must be left empty'
|
|
},
|
|
{ name = 'mw.html.attr (invalid value)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', true },
|
|
expect = 'Invalid value given: The value must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.attr (invalid table 1)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', { foo = {} } },
|
|
expect = 'Invalid table given: Must be name (string) value (string|number) pairs'
|
|
},
|
|
{ name = 'mw.html.attr (invalid table 2)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', { 1, 2 ,3 } },
|
|
expect = 'Invalid table given: Must be name (string) value (string|number) pairs'
|
|
},
|
|
{ name = 'mw.html.attr (invalid table 3)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', { foo = 'bar', blah = true } },
|
|
expect = 'Invalid table given: Must be name (string) value (string|number) pairs'
|
|
},
|
|
{ name = 'mw.html.attr (invalid table 4)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', { [{}] = 'foo' } },
|
|
expect = 'Invalid table given: Must be name (string) value (string|number) pairs'
|
|
},
|
|
{ name = 'mw.html.getAttr (nil)', func = testHelper,
|
|
args = { getEmptyTestDiv(), 'getAttr', 'foo' },
|
|
expect = { nil }
|
|
},
|
|
{ name = 'mw.html.addClass', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'addClass', 'foo' },
|
|
expect = { '<div class="foo"></div>' }
|
|
},
|
|
{ name = 'mw.html.addClass (invalid value)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'addClass', {} },
|
|
expect = 'Invalid class given: The name must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.css', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', 'foo', 'bar' },
|
|
expect = { '<div style="foo:bar;"></div>' }
|
|
},
|
|
{ name = 'mw.html.css (nil noop)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', 'foo', nil },
|
|
expect = { '<div></div>' }
|
|
},
|
|
{ name = 'mw.html.css (invalid name 1)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', function() end, 'bar' },
|
|
expect = 'Invalid CSS given: The name must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.css (table no value)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', {}, 'bar' },
|
|
expect = 'If a key->value table is given as first parameter, value must be left empty'
|
|
},
|
|
{ name = 'mw.html.css (invalid value)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', 'foo', {} },
|
|
expect = 'Invalid CSS given: The value must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html.css (table)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', testAttrs },
|
|
expect = { '<div style="ab:cd;foo:bar;"></div>' }
|
|
},
|
|
{ name = 'mw.html.css (invalid table)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', { foo = 'bar', ab = true } },
|
|
expect = 'Invalid table given: Must be name (string|number) value (string|number) pairs'
|
|
},
|
|
{ name = 'mw.html.cssText', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'cssText', 'Unit tests, ftw' },
|
|
expect = { '<div style="Unit tests, ftw;"></div>' }
|
|
},
|
|
{ name = 'mw.html.cssText (invalid value)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'cssText', {} },
|
|
expect = 'Invalid CSS given: Must be either a string or a number'
|
|
},
|
|
{ name = 'mw.html attribute escaping (value with double quotes)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', 'ble"rgh' },
|
|
expect = { '<div foo="ble"rgh"></div>' }
|
|
},
|
|
{ name = 'mw.html attribute escaping 1', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', 'ble<rgh' },
|
|
expect = { '<div foo="ble<rgh"></div>' }
|
|
},
|
|
{ name = 'mw.html attribute escaping 2', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'attr', 'foo', '<ble"&rgh>' },
|
|
expect = { '<div foo="<ble"&rgh>"></div>' }
|
|
},
|
|
{ name = 'mw.html attribute escaping (CSS)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', 'mu"ha', 'ha"ha' },
|
|
expect = { '<div style="mu"ha:ha"ha;"></div>' }
|
|
},
|
|
{ name = 'mw.html attribute escaping (CSS raw)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'cssText', 'mu"ha:-ha"ha' },
|
|
expect = { '<div style="mu"ha:-ha"ha;"></div>' }
|
|
},
|
|
{ name = 'mw.html.addClass (nil)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'addClass' },
|
|
expect = { '<div></div>' }
|
|
},
|
|
{ name = 'mw.html.cssText (nil)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'cssText' },
|
|
expect = { '<div></div>' }
|
|
},
|
|
|
|
-- Tests defined above
|
|
|
|
{ name = 'mw.html.addClass (twice) ', func = testMultiAddClass, type='ToString',
|
|
expect = { '<div class="foo bar"></div>' }
|
|
},
|
|
{ name = 'mw.html.css.cssText.css', func = testCssAndCssText, type='ToString',
|
|
expect = { '<div style="foo:bar;abc:def;g:h;"></div>' }
|
|
},
|
|
{ name = 'mw.html.tag (using done)', func = testTagDone, type='ToString',
|
|
expect = { '<div><span></span></div>' }
|
|
},
|
|
{ name = 'mw.html.node (using done)', func = testNodeDone, type='ToString',
|
|
expect = { '<div><div></div></div>' }
|
|
},
|
|
{ name = 'mw.html.node (self closing, using done)', func = testNodeSelfClosingDone, type='ToString',
|
|
expect = { '<div><br /></div>' }
|
|
},
|
|
{ name = 'mw.html.node (append to self closing)', func = testNodeAppendToSelfClosing, type='ToString',
|
|
expect = "Self-closing tags can't have child nodes"
|
|
},
|
|
{ name = 'mw.html.wikitext (append to self closing)', func = testWikitextAppendToSelfClosing, type='ToString',
|
|
expect = "Self-closing tags can't have child nodes"
|
|
},
|
|
{ name = 'mw.html.tag.node (using allDone)', func = testTagNodeAllDone, type='ToString',
|
|
expect = { '<div><p><div></div></p></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (overrides)', func = testAttributeOverride, type='ToString',
|
|
expect = { '<div good="Wikibase"></div>' }
|
|
},
|
|
{ name = 'mw.html.attr (removal)', func = testAttributeRemoval, type='ToString',
|
|
expect = { '<div></div>' }
|
|
},
|
|
{ name = 'mw.html.getAttr', func = testGetAttribute, type='ToString',
|
|
expect = { 'Berlin' }
|
|
},
|
|
{ name = 'mw.html.getAttr (escaping)', func = testGetAttributeEscaping, type='ToString',
|
|
expect = { '<ble"&rgh>' }
|
|
},
|
|
{ name = 'mw.html.create (empty string)', func = testCreateWithValue, type='ToString',
|
|
args = {''},
|
|
expect = { 'foo<div a="b"></div>' }
|
|
},
|
|
{ name = 'mw.html.create (nil)', func = testCreateWithValue, type='ToString',
|
|
args = {nil},
|
|
expect = { 'foo<div a="b"></div>' }
|
|
},
|
|
{ name = 'mw.html.css (removal)', func = testCssRemoval, type='ToString',
|
|
expect = { '<div></div>' }
|
|
},
|
|
{ name = 'mw.html complex test', func = testComplex, type='ToString',
|
|
expect = {
|
|
'<div class="firstClass" what="ever"><meh whynot="Русский"><hr a="b" /></meh>' ..
|
|
'<hr /><div abc="def" style="width:-1px;"></div></div>'
|
|
}
|
|
},
|
|
}
|
|
|
|
return testframework.getTestProvider( tests )
|