Difference between revisions of "Module:Protection banner/testcases"
Jump to navigation
Jump to search
en>ProcrastinatingReader (fix tests) |
m (1 revision imported) |
(No difference)
|
Latest revision as of 11:20, 2 February 2022
Documentation for this module may be created at Module:Protection banner/testcases/doc
-- Load necessary modules local mProtectionBanner = require('Module:Protection banner/sandbox') local ScribuntoUnit = require('Module:ScribuntoUnit') -- Get the classes local Protection = mProtectionBanner._exportClasses().Protection local Blurb = mProtectionBanner._exportClasses().Blurb local BannerTemplate = mProtectionBanner._exportClasses().BannerTemplate local Banner = mProtectionBanner._exportClasses().Banner local Padlock = mProtectionBanner._exportClasses().Padlock -- Initialise test suite local suite = ScribuntoUnit:new() -------------------------------------------------------------------------------- -- Default values -------------------------------------------------------------------------------- local d = {} d.reason = 'vandalism' d.action = 'edit' d.level = 'sysop' d.page = 'User:Example' d.talkPage = 'User talk:Example' d.baseText = 'Example' d.namespace = 2 -- Namespace of d.page d.namespaceFragment = 'user' -- namespace fragment of d.page for makeProtectionCategory d.categoryNamespaceKeys = {[d.namespace] = d.namespaceFragment} -- namespace key config table d.expiry = '1 January 9999' d.expiryU = 253370764800 -- d.expiry in Unix time d.expiryFragment = 'temp' -- expiry fragment of d.expiry for makeProtectionCategory d.protectionDate = '1 January 2000' d.protectionDateU = 946684800 -- d.protectionDate in Unix time -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- function suite:assertError(func, args, msg) args = args or {} local success, result = pcall(func, unpack(args)) self:assertFalse(success) if msg then self:assertStringContains(msg, result, true) -- does a plain match end end function suite:assertNotError(func, args) args = args or {} local success, result = pcall(func, unpack(args)) self:assertTrue(success) end local function makeTitleObject(options) local title = mw.title.new(options.page) -- Set protection levels local levels = { edit = {}, move = {}, autoreview = {} } for _, action in ipairs{'edit', 'move', 'autoreview'} do local level = options[action] if level then levels[action][1] = level end end rawset(title, 'protectionLevels', levels) -- Set content model rawset(title, 'contentModel', options.contentModel or 'wikitext') return title end local function makeDefaultTitleObject() return makeTitleObject{page = d.page, [d.action] = d.level} end -- Make an alias, to be clear the object is for a protected page. local makeProtectedTitleObject = makeDefaultTitleObject local function makeConfig(t) local cfg = { masterBanner = {}, padlockIndicatorNames = {}, indefImageReasons = {}, reasonsWithNamespacePriority = {}, categoryNamespaceKeys = {}, protectionCategories = {}, reasonsWithoutExpiryCheck = {}, expiryCheckActions = {}, pagetypes = {}, indefStrings = {}, hierarchy = { sysop = {}, reviewer = {'sysop'}, filemover = {'sysop'}, templateeditor = {'sysop'}, extendedconfirmed = {'sysop'}, autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'}, user = {'autoconfirmed'}, ['*'] = {'user'} }, wrappers = {}, msg = {} } local protLevelFields = { 'defaultBanners', 'banners', 'protectionBlurbs', 'explanationBlurbs', 'protectionLevels', 'images', 'imageLinks' } for _, field in ipairs(protLevelFields) do cfg[field] = { edit = {}, move = {}, autoreview = {} } end -- Add fields that cause errors if not present cfg.masterBanner.text = 'reason text' -- Add custom fields for k, v in pairs(t or {}) do cfg[k] = v end return cfg end local function makeDefaultProtectionObject(cfg) cfg = makeConfig(cfg) if next(cfg.categoryNamespaceKeys) == nil then -- cfg.categoryNamespaceKeys is empty cfg.categoryNamespaceKeys = d.categoryNamespaceKeys end local obj = Protection.new( {d.reason, action = d.action, expiry = d.expiry}, cfg, makeDefaultTitleObject() ) obj.expiry = d.expiryU -- Hack to override [[Module:Effective protection expiry]] return obj end local function makeProtectionCategoryKey(testFragments, defaults) local fragments = { expiry = 'all', namespace = 'all', reason = 'all', level = 'all', action = 'all' } for i, t in ipairs{defaults or {}, testFragments} do for k, v in pairs(t) do fragments[k] = v end end local key = { fragments.expiry, fragments.namespace, fragments.reason, fragments.level, fragments.action } return table.concat(key, '|') end local function makeDefaultProtectionCategoryKey(testFragments) local defaults = { expiry = d.expiryFragment, namespace = d.namespaceFragment, reason = d.reason, level = d.level, action = d.action } return makeProtectionCategoryKey(testFragments, defaults) end local function makeDefaultBlurbObject(cfg) cfg = makeConfig(cfg) return Blurb.new( makeDefaultProtectionObject(), {}, cfg ) end local function makeDefaultBannerTemplateObject(cfg) cfg = makeConfig(cfg) return BannerTemplate.new( makeDefaultProtectionObject(), cfg ) end local function makeDefaultBannerObject(cfg) cfg = makeConfig(cfg) return Banner.new( makeDefaultProtectionObject(), makeDefaultBlurbObject(), cfg ) end local function makeDefaultPadlockObject(cfg) cfg = makeConfig(cfg) return Padlock.new( makeDefaultProtectionObject(), makeDefaultBlurbObject(), cfg ) end local padlockPattern = '\127[^\127]*UNIQ%-%-indicator%-%x+%-QINU[^\127]*\127' function suite:assertIsPadlock(s, msg) self:assertStringContains( padlockPattern, s, false, msg ) end function suite:assertNoPadlock(s, msg) self:assertNotStringContains( padlockPattern, s, false, msg ) end function suite:assertIsBanner(s, msg) self:assertStringContains( 'class="[^"]*mbox[^"]*"', s, false, msg ) self:assertStringContains( 'role="presentation"', s, true, msg ) self:assertNotStringContains( 'id="protected-icon"', s, true, msg ) self:assertNotStringContains( 'topicon', s, true, msg ) end function suite:assertNoBanner(s, msg) self:assertNotStringContains( 'class="[^"]*mbox[^"]*"', s, false, msg ) self:assertNotStringContains( 'role="presentation"', s, true, msg ) self:assertNotStringContains( 'id="protected-icon"', s, true, msg ) self:assertNotStringContains( 'topicon', s, true, msg ) end -------------------------------------------------------------------------------- -- Protection object tests -------------------------------------------------------------------------------- -- Protection action function suite:testProtectionActionError() suite:assertError( Protection.new, {{action = 'foo'}, makeConfig()}, 'invalid action: foo' ) end function suite:testProtectionActionEdit() local obj = Protection.new({action = 'edit'}, makeConfig()) suite:assertEquals('edit', obj.action) end function suite:testProtectionActionMove() local obj = Protection.new({action = 'move'}, makeConfig()) suite:assertEquals('move', obj.action) end function suite:testProtectionActionAutoreview() local obj = Protection.new({action = 'autoreview'}, makeConfig()) suite:assertEquals('autoreview', obj.action) end function suite:testProtectionActionUpload() local obj = Protection.new({action = 'upload'}, makeConfig()) suite:assertEquals('upload', obj.action) end function suite:testProtectionNoAction() local obj = Protection.new({}, makeConfig()) suite:assertEquals('edit', obj.action) end -- Protection level function suite:testProtectionSemi() local obj = Protection.new( {action = 'edit'}, makeConfig(), makeTitleObject{page = 'Foo', edit = 'autoconfirmed'} ) self:assertEquals('autoconfirmed', obj.level) end function suite:testProtectionFull() local obj = Protection.new( {action = 'edit'}, makeConfig(), makeTitleObject{page = 'Foo', edit = 'sysop'} ) self:assertEquals('sysop', obj.level) end function suite:testProtectionUnprotected() local obj = Protection.new( {action = 'edit'}, makeConfig(), makeTitleObject{page = 'Foo', edit = nil} ) self:assertEquals('*', obj.level) end function suite:testProtectionSemiMove() local obj = Protection.new( {action = 'move'}, makeConfig(), makeTitleObject{page = 'Foo', move = 'autoconfirmed'} ) self:assertEquals('*', obj.level) end function suite:testProtectionTemplate() local obj = Protection.new( {action = 'edit'}, makeConfig(), makeTitleObject{page = 'Template:Foo', edit = 'templateeditor'} ) self:assertEquals('templateeditor', obj.level) end function suite:testProtectionTitleBlacklist() local obj = Protection.new( {action = 'edit'}, makeConfig(), makeTitleObject{page = 'Template:Editnotices/Page/Foo', edit = nil} ) self:assertEquals('templateeditor', obj.level) end -- Reason function suite:testProtectionReason() local obj = Protection.new( {'foo'}, makeConfig() ) self:assertEquals('foo', obj.reason) end function suite:testProtectionReasonLowerCase() local obj = Protection.new( {'fOO'}, makeConfig() ) self:assertEquals('foo', obj.reason) end function suite:testProtectionBadReason() self:assertError( Protection.new, {{'foo|bar'}, makeConfig()}, 'reasons cannot contain the pipe character ("|")' ) end function suite:testProtectionNoReason() local obj = Protection.new( {}, makeConfig() ) self:assertEquals(nil, obj.reason) end -- Protection date function suite:testProtectionProtectionDateIndef() self:assertError( Protection.new, { {date = 'indefinite'}, makeConfig{indefStrings = {indefinite = true}} }, 'invalid protection date: indefinite' ) end function suite:testProtectionProtectionDateTemp() local obj = Protection.new( {date = d.protectionDate}, makeConfig() ) self:assertEquals(d.protectionDateU, obj.protectionDate) end function suite:testProtectionNoProtectionDate() local obj = Protection.new( {}, makeConfig() ) self:assertEquals(nil, obj.protectionDate) end function suite:testProtectionBadProtectionDate() self:assertError( Protection.new, { {date = 'foobar'}, makeConfig{indefStrings = {indefinite = true}} }, 'invalid protection date: foobar' ) end -- bannerConfig function suite:testProtectionMasterBannerConfigPrecedence1() local masterBanner = {text = 'master banner text'} local obj = makeDefaultProtectionObject{masterBanner = masterBanner} self:assertEquals('master banner text', obj.bannerConfig.text) end function suite:testProtectionMasterBannerConfigPrecedence2() local masterBanner = {text = 'master banner text'} local defaultBanners = {[d.action] = {default = {text = 'defaultBanners default text'}}} local obj = makeDefaultProtectionObject(makeConfig{ masterBanner = masterBanner, defaultBanners = defaultBanners }) self:assertEquals('defaultBanners default text', obj.bannerConfig.text) end function suite:testProtectionMasterBannerConfigPrecedence3() local defaultBanners = {[d.action] = { [d.level] = {text = 'defaultBanners level text'}, default = {text = 'defaultBanners default text'} }} local obj = makeDefaultProtectionObject(makeConfig{defaultBanners = defaultBanners}) self:assertEquals('defaultBanners level text', obj.bannerConfig.text) end function suite:testProtectionMasterBannerConfigPrecedence4() local defaultBanners = {[d.action] = { [d.level] = {text = 'defaultBanners level text'} }} local banners = {[d.action] ={ [d.reason] = {text = 'banners text'} }} local obj = makeDefaultProtectionObject(makeConfig{ defaultBanners = defaultBanners, banners = banners }) self:assertEquals('banners text', obj.bannerConfig.text) end function suite:testProtectionMasterBannerConfigFields() local masterBanner = { text = 'master banner text', explanation = 'master banner explanation', tooltip = 'master banner tooltip', alt = 'master banner alt', link = 'master banner link', image = 'master banner image' } local obj = makeDefaultProtectionObject{masterBanner = masterBanner} self:assertEquals('master banner text', obj.bannerConfig.text) self:assertEquals('master banner explanation', obj.bannerConfig.explanation) self:assertEquals('master banner tooltip', obj.bannerConfig.tooltip) self:assertEquals('master banner alt', obj.bannerConfig.alt) self:assertEquals('master banner link', obj.bannerConfig.link) self:assertEquals('master banner image', obj.bannerConfig.image) end -- isUserScript function suite:testProtectionIsUserScriptWithUserCSS() local protection = Protection.new( {}, makeConfig(), mw.title.new('User:Example/common.css') ) self:assertTrue(protection:isUserScript()) end function suite:testProtectionIsUserScriptWithUserJS() local protection = Protection.new( {}, makeConfig(), mw.title.new('User:Example/common.js') ) self:assertTrue(protection:isUserScript()) end function suite:testProtectionIsUserScriptWithUserPage() local protection = Protection.new( {}, makeConfig(), mw.title.new('User:Example') ) self:assertFalse(protection:isUserScript()) end function suite:testProtectionIsUserScriptWithNormalSubpage() local protection = Protection.new( {}, makeConfig(), mw.title.new('User:Example/common') ) self:assertFalse(protection:isUserScript()) end function suite:testProtectionIsUserScriptWithUsernameEndingInCSS() local protection = Protection.new( {}, makeConfig(), mw.title.new('User:My username ends in .css') ) self:assertFalse(protection:isUserScript()) end function suite:testProtectionIsUserScriptWithUsernameEndingInJS() self:assertFalse( Protection.new( {}, makeConfig(), mw.title.new('User:My username ends in .js') ):isUserScript() ) end function suite:testProtectionIsUserScriptWithSubpageContainingCSS() self:assertFalse( Protection.new( {}, makeConfig(), mw.title.new('User:Example/common.css.txt') ):isUserScript() ) end function suite:testProtectionIsUserScriptWithNoSubpagePrefix() self:assertTrue( Protection.new( {}, makeConfig(), mw.title.new('User:Example/.css') ):isUserScript() ) end function suite:testProtectionIsUserScriptWithBlankUsernameAndNoSubpagePrefix() self:assertTrue( Protection.new( {}, makeConfig(), mw.title.new('User:/.css') ):isUserScript() ) end function suite:testProtectionIsUserScriptWhenUsernameIsOnlyCSS() self:assertFalse( Protection.new( {}, makeConfig(), mw.title.new('User:.css') ):isUserScript() ) end function suite:testProtectionIsUserScriptWithNonstandardCSSContentModel() self:assertTrue( Protection.new( {}, makeConfig(), makeTitleObject{page='User:Example/foo', contentModel='css'} ):isUserScript() ) end function suite:testProtectionIsUserScriptWithNonstandardJSContentModel() self:assertTrue( Protection.new( {}, makeConfig(), makeTitleObject{page='User:Example/foo', contentModel='javascript'} ):isUserScript() ) end function suite:testProtectionIsUserScriptWithNonstandardWikitextContentModel() self:assertFalse( Protection.new( {}, makeConfig(), makeTitleObject{page='User:Example/foo.css', contentModel='wikitext'} ):isUserScript() ) end function suite:testProtectionIsUserScriptWithNonUserspacePage() self:assertFalse( Protection.new( {}, makeConfig(), makeTitleObject{page='Wikipedia:Example.css', contentModel='css'} ):isUserScript() ) end -- isProtected function suite:testProtectionIsProtectedTrue() local obj = makeDefaultProtectionObject() obj.level = 'autoconfirmed' self:assertTrue(obj:isProtected()) end function suite:testProtectionIsProtectedFalse() local obj = makeDefaultProtectionObject() obj.level = '*' self:assertFalse(obj:isProtected()) end -- shouldShowLock function suite:testProtectionShouldShowLockWithProtectedPage() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='Foo', edit='sysop'} ) self:assertTrue(obj:shouldShowLock()) end function suite:testProtectionShouldShowLockWithProtectedUserScript() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='User:Example/common.css', contentModel='css', edit='sysop'} ) self:assertFalse(obj:shouldShowLock()) end function suite:testProtectionShouldShowLockWithUnprotectedPage() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='Foo'} ) self:assertFalse(obj:shouldShowLock()) end -- shouldHaveProtectionCategory function suite:testProtectionShouldHaveProtectionCategoryWithProtectedPage() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='Foo', edit='sysop'} ) self:assertTrue(obj:shouldHaveProtectionCategory()) end function suite:testProtectionShouldHaveProtectionCategoryWithProtectedUserScript() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='User:Example/common.css', contentModel='css', edit='sysop'} ) self:assertFalse(obj:shouldHaveProtectionCategory()) end function suite:testProtectionShouldHaveProtectionCategoryWithUnprotectedPage() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='Foo'} ) self:assertFalse(obj:shouldHaveProtectionCategory()) end -- isTemporary function suite:testProtectionIsProtectedTrue() local obj = makeDefaultProtectionObject() obj.expiry = 123456789012 self:assertTrue(obj:isTemporary()) end function suite:testProtectionIsProtectedFalse1() local obj = makeDefaultProtectionObject() obj.expiry = 'indef' self:assertFalse(obj:isTemporary()) end function suite:testProtectionIsProtectedFalse2() local obj = makeDefaultProtectionObject() obj.expiry = nil self:assertFalse(obj:isTemporary()) end -- makeProtectionCategory -- function suite:testProtectionCategoryWithUnprotectedPage() local obj = Protection.new( {}, makeConfig(), makeTitleObject{page='Foo'} ) self:assertEquals(obj:makeProtectionCategory(), '') end function suite:testProtectionCategoryPrecedence1() -- Test that expiry has the lowest priority. local protectionCategories = { [makeDefaultProtectionCategoryKey{expiry = 'all'}] = 'all expiries allowed', [makeDefaultProtectionCategoryKey{namespace = 'all'}] = 'all namespaces allowed', [makeDefaultProtectionCategoryKey{reason = 'all'}] = 'all reasons allowed', [makeDefaultProtectionCategoryKey{level = 'all'}] = 'all levels allowed', [makeDefaultProtectionCategoryKey{action = 'all'}] = 'all actions allowed' } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'all expiries allowed', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence2() -- Test that reason has the highest priority. local protectionCategories = { [makeProtectionCategoryKey{expiry = d.expiryFragment}] = 'expiry only', [makeProtectionCategoryKey{namespace = d.namespaceFragment}] = 'namespace only', [makeProtectionCategoryKey{reason = d.reason}] = 'reason only', [makeProtectionCategoryKey{level = d.level}] = 'level only', [makeProtectionCategoryKey{action = d.action}] = 'action only' } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'reason only', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence3() -- Test that namespace has the highest priority if the reason is set in -- cfg.reasonsWithNamespacePriority. local protectionCategories = { [makeProtectionCategoryKey{expiry = d.expiryFragment}] = 'expiry only', [makeProtectionCategoryKey{namespace = d.namespaceFragment}] = 'namespace only', [makeProtectionCategoryKey{reason = d.reason}] = 'reason only', [makeProtectionCategoryKey{level = d.level}] = 'level only', [makeProtectionCategoryKey{action = d.action}] = 'action only' } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, reasonsWithNamespacePriority = {[d.reason] = true} } self:assertStringContains( 'namespace only', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence4() -- Test that level has a higher priority than namespace. local protectionCategories = { [makeDefaultProtectionCategoryKey{namespace = 'all'}] = 'all namespaces allowed', [makeDefaultProtectionCategoryKey{level = 'all'}] = 'all levels allowed', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'all namespaces allowed', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence5() -- Test that action has a higher priority than level. local protectionCategories = { [makeDefaultProtectionCategoryKey{level = 'all'}] = 'all levels allowed', [makeDefaultProtectionCategoryKey{action = 'all'}] = 'all actions allowed', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'all levels allowed', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence6() -- Test that an exact match will be first. local protectionCategories = { [makeDefaultProtectionCategoryKey()] = 'exact match', [makeDefaultProtectionCategoryKey{action = 'all'}] = 'all actions allowed', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'exact match', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence7() -- Test that matching 4 keys will come before matching 3 keys local protectionCategories = { [makeDefaultProtectionCategoryKey{action = 'all'}] = 'four keys', [makeDefaultProtectionCategoryKey{action = 'all', level = 'all'}] = 'three keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'four keys', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence8() -- Test that matching 3 keys will come before matching 2 keys local protectionCategories = { [makeProtectionCategoryKey{reason = d.reason, action = d.action, level = d.level}] = 'three keys', [makeProtectionCategoryKey{reason = d.reason, action = d.action}] = 'two keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'three keys', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence9() -- Test that matching 2 keys will come before matching 1 key local protectionCategories = { [makeProtectionCategoryKey{action = d.action, level = d.level}] = 'two keys', [makeProtectionCategoryKey{action = d.action}] = 'one key', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'two keys', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryPrecedence10() -- Test that matching 1 keys will come before matching 0 keys local protectionCategories = { [makeProtectionCategoryKey{action = d.action}] = 'one key', [makeProtectionCategoryKey()] = 'no keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'one key', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryAllAlls() -- Test that 'all|all|all|all|all' works local protectionCategories = { [makeProtectionCategoryKey()] = 'no keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'no keys', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryNoFalseMatches() -- Test that we don't match things that we aren't supposed to. local protectionCategories = { [makeProtectionCategoryKey{expiry = 'foo'}] = 'expiry foo', [makeProtectionCategoryKey{namespace = 'foo'}] = 'namespace foo', [makeProtectionCategoryKey{reason = 'foo'}] = 'reason foo', [makeProtectionCategoryKey{level = 'foo'}] = 'level foo', [makeProtectionCategoryKey{action = 'foo'}] = 'action foo', [makeProtectionCategoryKey()] = 'no keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( 'no keys', obj:makeProtectionCategory(), true ) end function suite:testProtectionCategoryProtected() -- Test that protected pages produce some kind of category link. local protectionCategories = { [makeProtectionCategoryKey()] = 'no keys', } local obj = makeDefaultProtectionObject{ protectionCategories = protectionCategories, } self:assertStringContains( '^%[%[Category:.*%]%]$', obj:makeProtectionCategory() ) end function suite:testProtectionCategoryNotProtected() -- Test that unprotected pages produce the blank string. local protectionCategories = { [makeProtectionCategoryKey()] = 'no keys', } local obj = Protection.new( {}, makeConfig{protectionCategories = protectionCategories}, makeTitleObject{page = d.page, 'edit', nil} ) self:assertEquals('', obj:makeProtectionCategory()) end function suite:testProtectionCategoryNoMatch() -- Test that protected pages that don't match any categories -- produce the blank string. local obj = makeDefaultProtectionObject() self:assertEquals('', obj:makeProtectionCategory()) end function suite:testProtectionCategoryExpiryIndef() -- Test that indefinite protection matches the "indef" expiry fragment. local obj = makeDefaultProtectionObject() obj._cfg.protectionCategories = { [makeProtectionCategoryKey{expiry = 'indef', action = 'autoreview'}] = 'indef expiry', } obj.action = 'autoreview' obj.level = 'autoconfirmed' obj.expiry = 'indef' self:assertStringContains('indef expiry', obj:makeProtectionCategory(), true) end function suite:testProtectionCategoryExpiryTemp() -- Test that temporary protection matches the "temp" expiry fragment. local obj = makeDefaultProtectionObject() obj._cfg.protectionCategories = { [makeProtectionCategoryKey{expiry = 'temp', action = 'autoreview'}] = 'temporary expiry', } obj.action = 'autoreview' obj.level = 'autoconfirmed' obj.expiry = d.expiryU self:assertStringContains('temporary expiry', obj:makeProtectionCategory(), true) end function suite:testProtectionCategoryNoExpiry() -- Test that pages with no expiry set don't match "indef" or "temp". local protectionCategories = { [makeProtectionCategoryKey{expiry = 'temp', action = 'autoreview' }] = 'temporary expiry', [makeProtectionCategoryKey{expiry = 'indef', action = 'autoreview' }] = 'indefinite expiry', [makeProtectionCategoryKey()] = 'no matches' } local obj = Protection.new( {}, makeConfig{protectionCategories = protectionCategories}, makeProtectedTitleObject() ) self:assertStringContains('no matches', obj:makeProtectionCategory(), true) end function suite:testProtectionCategoryNamespaceFragment() -- Test that values in cfg.categoryNamespaceKeys will work. local protectionCategories = { [makeProtectionCategoryKey{namespace = 'foobar'}] = 'we found a match', } local obj = Protection.new( {}, makeConfig{ protectionCategories = protectionCategories, categoryNamespaceKeys = {[10] = 'foobar'} -- Template namespace }, makeTitleObject{page = 'Template:Foo', edit = 'autoconfirmed'} ) self:assertStringContains('we found a match', obj:makeProtectionCategory(), true) end function suite:testProtectionCategoryTalk() -- Test that talk pages match the "talk" namespace fragment. local protectionCategories = { [makeProtectionCategoryKey{namespace = 'talk'}] = 'talk namespace', } local obj = Protection.new( {}, makeConfig{protectionCategories = protectionCategories}, makeTitleObject{page = 'Template talk:Example', edit = 'autoconfirmed'} ) self:assertStringContains('talk namespace', obj:makeProtectionCategory(), true) end -- isIncorrect function suite:testProtectionIsIncorrectTrue1() local obj = makeDefaultProtectionObject() function obj:isProtected() return false end self:assertTrue(obj:isIncorrect(), 'Protection:isProtected() returned false') end function suite:testProtectionIsIncorrectTrue2() local obj = makeDefaultProtectionObject() function obj:isProtected() return true end obj.expiry = 0 self:assertTrue(obj:isIncorrect(), 'the page is protected and expiry is in the past') end function suite:testProtectionIsIncorrectFalse1() local obj = makeDefaultProtectionObject() function obj:isProtected() return true end obj.expiry = d.expiryU self:assertFalse(obj:isIncorrect(), 'the page is protected and expiry is in the future') end function suite:testProtectionIsIncorrectFalse2() local obj = makeDefaultProtectionObject() obj.expiry = nil function obj:isProtected() return true end self:assertFalse(obj:isIncorrect(), 'the page is protected and no expiry is set') end -- isTemplateProtectedNonTemplate function suite:testProtectionIsTemplateProtectedNonTemplateFalse1() local obj = makeDefaultProtectionObject() obj.level = 'autoconfirmed' self:assertFalse(obj:isTemplateProtectedNonTemplate(), 'the page is semi-protected') end function suite:testProtectionIsTemplateProtectedNonTemplateFalse2() local obj = makeDefaultProtectionObject() obj.level = 'templateeditor' obj.action = 'edit' rawset(obj.title, 'namespace', 10) -- template space self:assertFalse(obj:isTemplateProtectedNonTemplate(), 'template-protected template') end function suite:testProtectionIsTemplateProtectedNonTemplateFalse3() local obj = makeDefaultProtectionObject() obj.level = 'templateeditor' obj.action = 'edit' rawset(obj.title, 'namespace', 828) -- module space self:assertFalse(obj:isTemplateProtectedNonTemplate(), 'template-protected module') end function suite:testProtectionIsTemplateProtectedNonTemplateFalse4() local obj = makeDefaultProtectionObject() obj.level = 'templatemoveor' obj.action = 'move' rawset(obj.title, 'namespace', 10) -- template space self:assertFalse(obj:isTemplateProtectedNonTemplate(), 'template-move-protected template') end function suite:testProtectionIsTemplateProtectedNonTemplateFalse5() local obj = makeDefaultProtectionObject() obj.level = 'templatemoveor' obj.action = 'move' rawset(obj.title, 'namespace', 828) -- module space self:assertFalse(obj:isTemplateProtectedNonTemplate(), 'template-move-protected module') end function suite:testProtectionIsTemplateProtectedNonTemplateTrue1() local obj = makeDefaultProtectionObject() obj.level = 'templateeditor' obj.action = 'autoreview' self:assertTrue(obj:isTemplateProtectedNonTemplate(), 'the action is not edit or move') end function suite:testProtectionIsTemplateProtectedNonTemplateTrue2() local obj = makeDefaultProtectionObject() obj.level = 'templateeditor' rawset(obj.title, 'namespace', 2) -- user space self:assertTrue(obj:isTemplateProtectedNonTemplate(), 'the action is not in template or module space') end -- makeCategoryLinks function suite:testProtectionMakeCategoryLinksAllPresent() local obj = makeDefaultProtectionObject() obj._cfg.msg = { ['tracking-category-incorrect'] = 'Incorrect category', ['tracking-category-template'] = 'Template category' } function obj:makeProtectionCategory() return '[[Category:Protection category|' .. d.baseText .. ']]' end for _, field in ipairs{'isIncorrect', 'isTemplateProtectedNonTemplate'} do obj[field] = function () return true end end self:assertEquals( '[[Category:Protection category|' .. d.baseText .. ']]' .. '[[Category:Incorrect category|' .. d.baseText .. ']]' .. '[[Category:Template category|' .. d.baseText .. ']]', obj:makeCategoryLinks() ) end function suite:testProtectionMakeCategoryLinksAllAbsent() local obj = makeDefaultProtectionObject() obj._cfg.msg = { ['tracking-category-expiry'] = 'Expiry category', ['tracking-category-incorrect'] = 'Incorrect category', ['tracking-category-template'] = 'Template category' } function obj:makeProtectionCategory() return '' end for _, field in ipairs{'needsExpiry', 'isIncorrect', 'isTemplateProtectedNonTemplate'} do obj[field] = function () return false end end self:assertEquals('', obj:makeCategoryLinks()) end -------------------------------------------------------------------------------- -- Blurb class tests -------------------------------------------------------------------------------- -- initialize function suite:testBlurbNew() local obj = Blurb.new({'foo'}, {'bar'}, {'baz'}) self:assertEquals('foo', obj._protectionObj[1]) self:assertEquals('bar', obj._args[1]) self:assertEquals('baz', obj._cfg[1]) end -- _formatDate function suite:testBlurbFormatDateStandard() local obj = makeDefaultBlurbObject() self:assertEquals('1 January 1970', obj:_formatDate(0)) end function suite:testBlurbFormatDateCustom() local obj = makeDefaultBlurbObject{msg = {['expiry-date-format'] = 'Y Y F F j'}} self:assertEquals('1970 1970 January January 1', obj:_formatDate(0)) end function suite:testBlurbFormatDateError() local obj = makeDefaultBlurbObject() self:assertEquals(nil, obj:_formatDate('foo')) end -- _getExpandedMessage function suite:testBlurbGetExpandedMessage() local obj = makeDefaultBlurbObject() function obj:_substituteParameters(s) return 'testing ' .. s end obj._cfg.msg = {['test-key'] = 'test message'} self:assertEquals('testing test message', obj:_getExpandedMessage('test-key')) end -- _substituteParameters function suite:testBlurbSubstituteParameters() local obj = makeDefaultBlurbObject() obj._makeCurrentVersionParameter = function () return '1' end obj._makeEditRequestParameter = function () return '2' end obj._makeExpiryParameter = function () return '3' end obj._makeExplanationBlurbParameter = function () return '4' end obj._makeImageLinkParameter = function () return '5' end obj._makeIntroBlurbParameter = function () return '6' end obj._makeIntroFragmentParameter = function () return '7' end obj._makePagetypeParameter = function () return '8' end obj._makeProtectionBlurbParameter = function () return '9' end obj._makeProtectionDateParameter = function () return '10' end obj._makeProtectionLevelParameter = function () return '11' end obj._makeProtectionLogParameter = function () return '12' end obj._makeTalkPageParameter = function () return '13' end obj._makeTooltipBlurbParameter = function () return '14' end obj._makeTooltipFragmentParameter = function () return '15' end obj._makeVandalTemplateParameter = function () return '16' end local msg = '${CURRENTVERSION}-' .. '${EDITREQUEST}-' .. '${EXPIRY}-' .. '${EXPLANATIONBLURB}-' .. '${IMAGELINK}-' .. '${INTROBLURB}-' .. '${INTROFRAGMENT}-' .. '${PAGETYPE}-' .. '${PROTECTIONBLURB}-' .. '${PROTECTIONDATE}-' .. '${PROTECTIONLEVEL}-' .. '${PROTECTIONLOG}-' .. '${TALKPAGE}-' .. '${TOOLTIPBLURB}-' .. '${TOOLTIPFRAGMENT}-' .. '${VANDAL}' local expected = '1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16' self:assertEquals(expected, obj:_substituteParameters(msg)) end -- makeCurrentVersionParameter function suite:testBlurbMakeCurrentVersionParameterEdit() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'edit' obj._cfg.msg['current-version-edit-display'] = 'edit display' self:assertEquals( '[//en.wikipedia.org/w/index.php?title=' .. mw.uri.encode(d.page) .. '&action=history edit display]', obj:_makeCurrentVersionParameter() ) end function suite:testBlurbMakeCurrentVersionParameterMove() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'move' obj._cfg.msg['current-version-move-display'] = 'move display' self:assertEquals( '[//en.wikipedia.org/w/index.php?title=' .. mw.uri.encode('Special:Log') .. '&page=' .. mw.uri.encode(d.page) .. '&type=move move display]', obj:_makeCurrentVersionParameter() ) end -- _makeEditRequestParameter function suite:testBlurbMakeEditRequestParameterLevels() -- We can't test the edit requests directly as that is the responsibility of -- [[Module:Submit an edit request]], but we can check that we get different -- outputs for different protection levels. local function makeBlurbObjectWithLevels(action, level) local obj = makeDefaultBlurbObject() obj._protectionObj.action = action obj._protectionObj.level = level obj._cfg.msg['edit-request-display'] = 'display' return obj end local obj1 = makeBlurbObjectWithLevels('edit', 'autoconfirmed') local obj2 = makeBlurbObjectWithLevels('edit', 'templateeditor') local obj3 = makeBlurbObjectWithLevels('edit', 'sysop') local obj4 = makeBlurbObjectWithLevels('move', 'templateeditor') self:assertFalse(obj1:_makeEditRequestParameter() == obj2:_makeEditRequestParameter()) self:assertFalse(obj2:_makeEditRequestParameter() == obj3:_makeEditRequestParameter()) self:assertEquals(obj3:_makeEditRequestParameter(), obj4:_makeEditRequestParameter()) end function suite:testBlurbMakeEditRequestParameterLink() -- Check that the edit request links have features that we can always expect -- to be there. The rest is subject to be changed by [[Module:Submit an edit request]] -- at any time, so we won't test that here. local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'edit' obj._protectionObj.level = 'autoconfirmed' obj._cfg.msg['edit-request-display'] = 'the edit request display' self:assertStringContains( '//en.wikipedia.org/w/index.php?', obj:_makeEditRequestParameter(), true ) self:assertStringContains( 'action=edit', obj:_makeEditRequestParameter(), true ) self:assertStringContains( 'title=[a-zA-Z0-9%%_]*[tT]alk', obj:_makeEditRequestParameter(), false ) self:assertStringContains( 'the edit request display', obj:_makeEditRequestParameter(), true ) end -- _makeExpiryParameter function suite:testBlurbMakeExpiryParameterTemp() local obj = makeDefaultBlurbObject() obj._protectionObj.expiry = 0 function obj:_formatDate(num) return 'unix date is ' .. tostring(num) end self:assertEquals('unix date is 0', obj:_makeExpiryParameter()) end function suite:testBlurbMakeExpiryParameterOther() local obj = makeDefaultBlurbObject() obj._protectionObj.expiry = 'indef' function obj:_formatDate(num) return 'unix date is ' .. tostring(num) end self:assertEquals('indef', obj:_makeExpiryParameter()) end -- _makeExplanationBlurbParameter function suite:testBlurbMakeExplanationBlurbParameter() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'edit' obj._protectionObj.level = 'autoconfirmed' rawset(obj._protectionObj.title, 'isTalkPage', true) obj._cfg.explanationBlurbs = { edit = { autoconfirmed = { talk = 'edit-autoconfirmed-talk', default = 'edit-autoconfirmed-default' }, default = { talk = 'edit-default-talk', default = 'edit-default-default' } } } function obj:_substituteParameters(msg) return msg end self:assertEquals( 'edit-autoconfirmed-talk', obj:_makeExplanationBlurbParameter() ) obj._cfg.explanationBlurbs.edit.autoconfirmed.talk = nil self:assertEquals( 'edit-autoconfirmed-default', obj:_makeExplanationBlurbParameter() ) obj._cfg.explanationBlurbs.edit.autoconfirmed.default = nil self:assertEquals( 'edit-default-talk', obj:_makeExplanationBlurbParameter() ) obj._cfg.explanationBlurbs.edit.default.talk = nil self:assertEquals( 'edit-default-default', obj:_makeExplanationBlurbParameter() ) obj._cfg.explanationBlurbs.edit.default.default = nil self:assertError( obj._makeExplanationBlurbParameter, {obj}, 'could not find explanation blurb for action "edit",' .. ' level "autoconfirmed" and talk key "talk"' ) end function suite:testBlurbMakeExplanationBlurbParameterSpecialCases() local obj = makeDefaultBlurbObject() rawset(obj._protectionObj.title, 'namespace', 8) function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( 'the key is explanation-blurb-nounprotect', obj:_makeExplanationBlurbParameter() ) end -- _makeImageLinkParameter function suite:testBlurbMakeImageLinkParameter() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'move' obj._protectionObj.level = 'sysop' obj._cfg.imageLinks = { edit = { sysop = 'edit-sysop', default = 'edit-default' }, move = { sysop = 'move-sysop', default = 'move-default' } } function obj:_substituteParameters(msg) return msg end self:assertEquals( 'move-sysop', obj:_makeImageLinkParameter() ) obj._cfg.imageLinks.move.sysop = nil self:assertEquals( 'move-default', obj:_makeImageLinkParameter() ) obj._cfg.imageLinks.move.default = nil self:assertEquals( 'edit-default', obj:_makeImageLinkParameter() ) end -- _makeIntroBlurbParameter function suite:testBlurbMakeIntroBlurbParameter() local obj = makeDefaultBlurbObject() function obj._protectionObj:isTemporary() return true end function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( 'the key is intro-blurb-expiry', obj:_makeIntroBlurbParameter() ) function obj._protectionObj:isTemporary() return false end self:assertEquals( 'the key is intro-blurb-noexpiry', obj:_makeIntroBlurbParameter() ) end -- _makeIntroFragmentParameter function suite:testBlurbMakeIntroFragmentParameter() local obj = makeDefaultBlurbObject() function obj._protectionObj:isTemporary() return true end function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( 'the key is intro-fragment-expiry', obj:_makeIntroFragmentParameter() ) function obj._protectionObj:isTemporary() return false end self:assertEquals( 'the key is intro-fragment-noexpiry', obj:_makeIntroFragmentParameter() ) end -- _makePagetypeParameter function suite:testPagetypeParameter() local obj = makeDefaultBlurbObject() rawset(obj._protectionObj.title, 'namespace', 3) obj._cfg.pagetypes = { [3] = 'user talk page', default = 'default page' } self:assertEquals( 'user talk page', obj:_makePagetypeParameter() ) obj._cfg.pagetypes[3] = nil self:assertEquals( 'default page', obj:_makePagetypeParameter() ) obj._cfg.pagetypes.default = nil self:assertError( obj._makePagetypeParameter, {obj}, 'no default pagetype defined' ) end -- _makeProtectionBlurbParameter function suite:testBlurbMakeProtectionBlurbParameter() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'move' obj._protectionObj.level = 'sysop' obj._cfg.protectionBlurbs = { edit = { sysop = 'edit-sysop', default = 'edit-default' }, move = { sysop = 'move-sysop', default = 'move-default' } } function obj:_substituteParameters(msg) return msg end self:assertEquals( 'move-sysop', obj:_makeProtectionBlurbParameter() ) obj._cfg.protectionBlurbs.move.sysop = nil self:assertEquals( 'move-default', obj:_makeProtectionBlurbParameter() ) obj._cfg.protectionBlurbs.move.default = nil self:assertEquals( 'edit-default', obj:_makeProtectionBlurbParameter() ) obj._cfg.protectionBlurbs.edit.default = nil self:assertError( obj._makeProtectionBlurbParameter, {obj}, 'no protection blurb defined for protectionBlurbs.edit.default' ) end -- _makeProtectionDateParameter function suite:testBlurbMakeProtectionDateParameter() local obj = makeDefaultBlurbObject() obj._protectionObj.protectionDate = 0 function obj:_formatDate(num) return 'unix date is ' .. tostring(num) end self:assertEquals('unix date is 0', obj:_makeProtectionDateParameter()) obj._protectionObj.protectionDate = 'indef' self:assertEquals('indef', obj:_makeProtectionDateParameter()) end -- _makeProtectionLevelParameter function suite:testBlurbMakeProtectionLevelParameter() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'move' obj._protectionObj.level = 'sysop' obj._cfg.protectionLevels = { edit = { sysop = 'edit-sysop', default = 'edit-default' }, move = { sysop = 'move-sysop', default = 'move-default' } } function obj:_substituteParameters(msg) return msg end self:assertEquals( 'move-sysop', obj:_makeProtectionLevelParameter() ) obj._cfg.protectionLevels.move.sysop = nil self:assertEquals( 'move-default', obj:_makeProtectionLevelParameter() ) obj._cfg.protectionLevels.move.default = nil self:assertEquals( 'edit-default', obj:_makeProtectionLevelParameter() ) obj._cfg.protectionLevels.edit.default = nil self:assertError( obj._makeProtectionLevelParameter, {obj}, 'no protection level defined for protectionLevels.edit.default' ) end -- _makeProtectionLogParameter function suite:testBlurbMakeProtectionLogParameterPC() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'autoreview' function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertStringContains( '^%[//en%.wikipedia%.org/w/index%.php?', obj:_makeProtectionLogParameter(), false ) self:assertStringContains( 'title=' .. mw.uri.encode('Special:Log'), obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'type=stable', obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'page=' .. mw.uri.encode(d.page), obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'the key is pc%-log%-display%]$', obj:_makeProtectionLogParameter(), false ) end function suite:testBlurbMakeProtectionLogParameterProtection() local obj = makeDefaultBlurbObject() obj._protectionObj.action = 'edit' function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertStringContains( '^%[//en%.wikipedia%.org/w/index%.php?', obj:_makeProtectionLogParameter(), false ) self:assertStringContains( 'title=' .. mw.uri.encode('Special:Log'), obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'type=protect', obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'page=' .. mw.uri.encode(d.page), obj:_makeProtectionLogParameter(), true ) self:assertStringContains( 'the key is protection%-log%-display%]$', obj:_makeProtectionLogParameter(), false ) end -- _makeTalkPageParameter function suite:testBlurbMakeTalkPageParameter() local obj = makeDefaultBlurbObject() function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( '[[' .. d.talkPage .. '#top|' .. 'the key is talk-page-link-display' .. ']]', obj:_makeTalkPageParameter() ) obj._args.section = 'talk section' self:assertEquals( '[[' .. d.talkPage .. '#talk section|' .. 'the key is talk-page-link-display' .. ']]', obj:_makeTalkPageParameter() ) end -- _makeTooltipBlurbParameter function suite:testBlurbMakeTooltipBlurbParameter() local obj = makeDefaultBlurbObject() function obj._protectionObj:isTemporary() return true end function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( 'the key is tooltip-blurb-expiry', obj:_makeTooltipBlurbParameter() ) function obj._protectionObj:isTemporary() return false end self:assertEquals( 'the key is tooltip-blurb-noexpiry', obj:_makeTooltipBlurbParameter() ) end -- _makeTooltipFragmentParameter function suite:testBlurbMakeTooltipFragmentParameter() local obj = makeDefaultBlurbObject() function obj._protectionObj:isTemporary() return true end function obj:_getExpandedMessage(key) return 'the key is ' .. key end self:assertEquals( 'the key is tooltip-fragment-expiry', obj:_makeTooltipFragmentParameter() ) function obj._protectionObj:isTemporary() return false end self:assertEquals( 'the key is tooltip-fragment-noexpiry', obj:_makeTooltipFragmentParameter() ) end -- _makeVandalTemplateParameter function suite:testBlurbMakeVandalTemplateParameter() local obj = makeDefaultBlurbObject() self:assertStringContains( d.baseText, obj:_makeVandalTemplateParameter(), true ) obj._args.user = 'Some user' self:assertStringContains( 'Some user', obj:_makeVandalTemplateParameter(), true ) end -- makeBannerText function suite:testBlurbMakeBannerTextBadInput() local obj = makeDefaultBlurbObject() self:assertError( obj.makeBannerText, {obj, 'foo'}, '"foo" is not a valid banner config field' ) self:assertError( obj.makeBannerText, {obj, nil}, '"nil" is not a valid banner config field' ) end function suite:testBlurbMakeBannerTextGoodInput() local obj = makeDefaultBlurbObject() obj._protectionObj.bannerConfig = { text = 'banner text', explanation = 'banner explanation', tooltip = 'banner tooltip', alt = 'banner alt', link = 'banner link' } self:assertNotError(obj.makeBannerText, {obj, 'text'}) self:assertNotError(obj.makeBannerText, {obj, 'explanation'}) self:assertNotError(obj.makeBannerText, {obj, 'tooltip'}) self:assertNotError(obj.makeBannerText, {obj, 'alt'}) self:assertNotError(obj.makeBannerText, {obj, 'link'}) end function suite:testBlurbMakeBannerTextString() local obj = makeDefaultBlurbObject() function obj:_substituteParameters(msg) return msg end obj._protectionObj.bannerConfig = { text = 'banner text', } self:assertEquals('banner text', obj:makeBannerText('text')) end function suite:testBlurbMakeBannerTextBadFunction() local obj = makeDefaultBlurbObject() function obj:_substituteParameters(msg) return msg end obj._protectionObj.bannerConfig = { text = function () return 9 end, } self:assertError( obj.makeBannerText, {obj, 'text'}, 'bad output from banner config function with key "text"' .. ' (expected string, got number)' ) end function suite:testBlurbMakeBannerTextGoodFunction() local obj = makeDefaultBlurbObject() function obj:_substituteParameters(msg) return msg end obj._protectionObj.bannerConfig = { text = function () return 'some text' end, } self:assertEquals('some text', obj:makeBannerText('text')) end -------------------------------------------------------------------------------- -- BannerTemplate class tests -------------------------------------------------------------------------------- -- BannerTemplate.new function suite:testBannerTemplateNewCfg() local protectionObj = makeDefaultProtectionObject() local obj = BannerTemplate.new(protectionObj, makeConfig{foo = 'bar'}) self:assertEquals('bar', obj._cfg.foo) end function suite:testBannerTemplateNewImageIndefTemplateOrModule() local cfg = { msg = {['image-filename-indef'] = 'red padlock'} } local protectionObj = makeDefaultProtectionObject() protectionObj.action = 'edit' protectionObj.level = 'sysop' function protectionObj:isTemporary() return false end rawset(protectionObj.title, 'namespace', 10) local obj1 = BannerTemplate.new(protectionObj, makeConfig(cfg)) self:assertEquals('red padlock', obj1._imageFilename) rawset(protectionObj.title, 'namespace', 828) local obj2 = BannerTemplate.new(protectionObj, makeConfig(cfg)) self:assertEquals('red padlock', obj2._imageFilename) end function suite:testBannerTemplateNewImageUsesIndefReason() local cfg = { indefImageReasons = {[d.reason] = true}, msg = {['image-filename-indef'] = 'red padlock'} } local protectionObj = makeDefaultProtectionObject() protectionObj.action = 'edit' protectionObj.level = 'sysop' function protectionObj:isTemporary() return false end rawset(protectionObj.title, 'namespace', 2) local obj = BannerTemplate.new(protectionObj, makeConfig(cfg)) self:assertEquals('red padlock', obj._imageFilename) end function suite:testBannerTemplateNewImageDefault() local images = { move = { sysop = 'foo', default = 'bar' } } local protectionObj = makeDefaultProtectionObject() protectionObj.action = 'move' protectionObj.level = 'sysop' local obj = BannerTemplate.new(protectionObj, makeConfig{ images = images }) self:assertEquals('foo', obj._imageFilename) images.move.sysop = nil obj = BannerTemplate.new(protectionObj, makeConfig{ images = images }) self:assertEquals('bar', obj._imageFilename) images.move.default = nil obj = BannerTemplate.new(protectionObj, makeConfig{ images = images }) self:assertEquals(nil, obj._imageFilename) end -- renderImage function suite:testBannerTemplateRenderImageFilename() local obj = makeDefaultBannerTemplateObject() obj._imageFilename = 'ImageFilename.png' self:assertStringContains('ImageFilename.png', obj:renderImage(), true) end function suite:testBannerTemplateRenderImageDefault() local obj = makeDefaultBannerTemplateObject() obj._cfg.msg['image-filename-default'] = 'Defaultfilename.png' self:assertStringContains('Defaultfilename.png', obj:renderImage(), true) end function suite:testBannerTemplateRenderImageDefaultNoConfig() local obj = makeDefaultBannerTemplateObject() self:assertStringContains('Transparent.gif', obj:renderImage(), true) end function suite:testBannerTemplateRenderImageDefaultWidth() local obj = makeDefaultBannerTemplateObject() self:assertStringContains('20px', obj:renderImage(), true) end function suite:testBannerTemplateRenderImageCustomWidth() local obj = makeDefaultBannerTemplateObject() obj.imageWidth = 50 self:assertStringContains('50px', obj:renderImage(), true) end function suite:testBannerTemplateRenderImageAlt() local obj = makeDefaultBannerTemplateObject() obj._imageAlt = 'the alt text' self:assertStringContains('alt%s*=%s*the alt text', obj:renderImage(), false) end function suite:testBannerTemplateRenderImageLink() local obj = makeDefaultBannerTemplateObject() obj._imageLink = 'the link text' self:assertStringContains('link%s*=%s*the link text', obj:renderImage(), false) end function suite:testBannerTemplateRenderImageCaption() local obj = makeDefaultBannerTemplateObject() obj.imageCaption = 'the caption text' self:assertStringContains('the caption text', obj:renderImage(), true) end -------------------------------------------------------------------------------- -- Banner class tests -------------------------------------------------------------------------------- function suite:testBannerNew() local protectionObj = makeDefaultProtectionObject() local blurbObj = makeDefaultBlurbObject() local cfg = makeConfig() function blurbObj:makeBannerText(key) if key == 'alt' then return 'the alt text' elseif key == 'text' then return 'the main text' elseif key == 'explanation' then return 'the explanation text' end end local obj = Banner.new(protectionObj, blurbObj, cfg) self:assertEquals(40, obj.imageWidth) self:assertEquals('the alt text', obj.imageCaption) self:assertEquals('the main text', obj._reasonText) self:assertEquals('the explanation text', obj._explanationText) self:assertEquals(d.page, obj._page) end -- __tostring function suite:testBannerToStringError() local obj = makeDefaultBannerObject() obj._reasonText = nil self:assertError(obj.__tostring, {obj}, 'no reason text set') end function suite:testBannerToString() local obj = makeDefaultBannerObject() obj._reasonText = 'the reason text' obj._explanationText = 'the explanation text' function obj:renderImage() return '[[File:Example.png|30px]]' end self:assertStringContains('[[File:Example.png|30px]]', tostring(obj), true) self:assertStringContains( "'''the reason text'''<br />the explanation text", tostring(obj), true ) obj._explanationText = nil self:assertStringContains("'''the reason text'''", tostring(obj), true) end -------------------------------------------------------------------------------- -- Padlock class tests -------------------------------------------------------------------------------- function suite:testPadlockNew() local protectionObj = makeDefaultProtectionObject() local blurbObj = makeDefaultBlurbObject() local cfg = makeConfig() function blurbObj:makeBannerText(key) if key == 'alt' then return 'the alt text' elseif key == 'tooltip' then return 'the tooltip text' elseif key == 'link' then return 'the link text' end end local obj = Padlock.new(protectionObj, blurbObj, cfg) self:assertEquals(20, obj.imageWidth) self:assertEquals('the tooltip text', obj.imageCaption) self:assertEquals('the alt text', obj._imageAlt) self:assertEquals('the link text', obj._imageLink) end function suite:testPadlockNewIndicators() local protectionObj = makeDefaultProtectionObject() protectionObj.action = 'move' protectionObj.level = 'sysop' local blurbObj = makeDefaultBlurbObject() local cfg = makeConfig{padlockIndicatorNames = { move = 'move-indicator', default = 'default-indicator' }} local obj = Padlock.new(protectionObj, blurbObj, cfg) self:assertEquals(obj._indicatorName, 'move-indicator') cfg.padlockIndicatorNames.move = nil obj = Padlock.new(protectionObj, blurbObj, cfg) self:assertEquals(obj._indicatorName, 'default-indicator') cfg.padlockIndicatorNames.default = nil obj = Padlock.new(protectionObj, blurbObj, cfg) self:assertEquals(obj._indicatorName, 'pp-default') end -- __tostring function suite:testPadlockToString() local obj = makeDefaultPadlockObject() self:assertIsPadlock(tostring(obj)) end -------------------------------------------------------------------------------- -- Export tests -------------------------------------------------------------------------------- -- _main function suite:test_mainError() local args = {action = 'foobar'} local cfg = makeConfig() local title = makeDefaultTitleObject() local success, result = pcall(mProtectionBanner._main, args, cfg, title) self:assertFalse(success) self:assertEquals( 'invalid action: foobar', result, false ) end function suite:testCatOnlyHidesOutput() local args1 = {catonly = 'yes'} local args2 = {catonly = 'yes', small = 'yes'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertNoBanner(mProtectionBanner._main(args1, cfg, title)) self:assertNoPadlock(mProtectionBanner._main(args2, cfg, title)) end function suite:testCatOnlyShowsCategory() local args = {catonly = 'yes'} local cfg = makeConfig() cfg.protectionCategories = { [makeProtectionCategoryKey{expiry = 'indef', action = 'edit'}] = 'indef expiry', } local title = makeDefaultTitleObject() self:assertStringContains("Category:indef expiry", mProtectionBanner._main(args, cfg, title), true) end function suite:testCatOnlyNoGivesOutput() local args = {catonly = 'no'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsBanner(mProtectionBanner._main(args, cfg, title)) end function suite:testCatOnlyNoShowsCategory() local args = {catonly = 'no'} local cfg = makeConfig() cfg.protectionCategories = { [makeProtectionCategoryKey{expiry = 'indef', action = 'edit'}] = 'indef expiry', } local title = makeDefaultTitleObject() self:assertStringContains("Category:indef expiry", mProtectionBanner._main(args, cfg, title), true) end function suite:test_mainSmall1() local args = {small = 'yes'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsPadlock(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainSmall2() local args = {small = 'Yes'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsPadlock(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainSmall3() local args = {small = 'true'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsPadlock(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainLarge1() local args = {} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsBanner(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainLarge2() local args = {small = 'no'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsBanner(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainLarge3() local args = {small = 'No'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsBanner(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainLarge4() local args = {small = 'false'} local cfg = makeConfig() local title = makeDefaultTitleObject() self:assertIsBanner(mProtectionBanner._main(args, cfg, title)) end function suite:test_mainNoBanner() local args = {} local cfg = makeConfig() local title = makeTitleObject{page = d.page, edit = nil} self:assertNoBanner(mProtectionBanner._main(args, cfg, title), 'page unprotected') end function suite:test_mainNoBannerForUserScripts() local args = {} local cfg = makeConfig() local title = makeTitleObject{page = 'User:Example/common.css', contentType = 'css'} self:assertNoBanner(mProtectionBanner._main(args, cfg, title), 'page is a user script') end function suite:test_mainCategories() local args = {} local cfg -- Use main config module local title = makeTitleObject{page = d.page, 'edit', nil} self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner._main(args, cfg, title), false, 'page unprotected' ) end -- p.main function suite:testMainHasOutput() local frame = mw.getCurrentFrame() local parent = frame:newChild{args = {}} local child = parent:newChild{args = {}} local cfg -- Use main config module self:assertStringContains('%S', mProtectionBanner.main(child, cfg), false) end function suite:testMainWrapper() local frame = mw.getCurrentFrame() local parent = frame:newChild{title = 'Template:Pp-example', args = {}} local child = parent:newChild{args = {}} local cfg = makeConfig{ msg = {['tracking-category-incorrect'] = 'Incorrect'}, wrappers = {['Template:Pp-example'] = {category = false}} } self:assertNotStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(child, cfg), false ) self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(parent, cfg), false ) end function suite:testMainWrapperOverride() local frame = mw.getCurrentFrame() local parent = frame:newChild{title = 'Template:Pp-example', args = {category = 'yes'}} local child = parent:newChild{args = {}} local cfg = makeConfig{ msg = {['tracking-category-incorrect'] = 'Incorrect'}, wrappers = {['Template:Pp-example'] = {category = false}} } self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(child, cfg), false ) end function suite:testMainWrapperSandbox() local frame = mw.getCurrentFrame() local parent = frame:newChild{title = 'Template:Pp-example/sandbox', args = {}} local child = parent:newChild{args = {}} local cfg = makeConfig{ msg = {['tracking-category-incorrect'] = 'Incorrect'}, wrappers = {['Template:Pp-example'] = {category = false}} } self:assertNotStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(child, cfg), false ) self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(parent, cfg), false ) end function suite:testMainNoWrapper() local frame = mw.getCurrentFrame() local parent = frame:newChild{title = 'Template:Some template', args = {}} local child = parent:newChild{args = {}} local cfg = makeConfig{ msg = {['tracking-category-incorrect'] = 'Incorrect'}, wrappers = {['Template:Pp-example'] = {category = false}} } self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(child, cfg), false ) self:assertStringContains( '%[%[Category:.-%]%]', mProtectionBanner.main(parent, cfg), false ) end return suite