mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-11-26 17:20:07 +00:00
8d1d5ac84c
Some functions in mw.html accept numbers as arguments, but later fail when constructing the string. This disallows numbers in attribute names, since they aren't valid anyway, and fixes the remainder of the cases to properly build the string. Bug: 67201 Change-Id: Ie7bcbb9d8df580dd8793681f78a8b0719d8a287a
339 lines
13 KiB
Lua
339 lines
13 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', 123, 'bar' },
|
|
expect = 'Invalid name given: The name must be a string'
|
|
},
|
|
{ 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 (numeric argument)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'addClass', 123 },
|
|
expect = { '<div class="123"></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 (numeric arguments)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'css', 123, 456 },
|
|
expect = { '<div style="123:456;"></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 (numeric argument)', func = testHelper, type='ToString',
|
|
args = { getEmptyTestDiv(), 'cssText', 123 },
|
|
expect = { '<div style="123;"></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 )
|