Modul:Protection banner/kasus uji
Modul Lua ini digunakan pada sekitar 500 halaman dan perubahannya kemungkinan dipantau. Uji cobalah di subhalaman /bak pasir atau /kasus uji modul, atau bak pasir modul Anda. Pertimbangkan untuk mendiskusikan perubahan di halaman pembicaraan sebelum mengimplementasikannya. |
Modul ini dilindungi. Modul ini sangat mencolok yang digunakan oleh banyak halaman, atau sangat sering disubstitusikan. Karena vandalisme atau kesalahan akan mempengaruhi banyak halaman, dan suntingan kecil dapat memberi beban besar pada server, modul ini dilindungi dari penyuntingan. |
Modul ini menggunakan Lua: |
Modul ini digunakan untuk membuat tajuk pelindungan dan ikon gembok yang ditempatkan di atas halaman pelindungan.
Penggunaan
suntingTidak dapat digunakan secara langsung. Templat pelindungan memerlukan templat {{pp}}, atau menggunakan daftar templat di bawah
Dari teks wiki
sunting{{#invoke:Protection banner|main | 1 = reason | small = yes/no | action = action | date = protection date | user = username | section = talk page section name | category = no }}
Sintaksis #invoke digunakan untuk templat yang lebih spesifik daripada {{pp}}. Misalnya, it is possible to create a protection template which always shows a padlock icon by using the code {{#invoke:Protection banner|main|small=yes}}
. Pages which call this template will still be able to use other arguments, like action. However, this only works one level deep; a page calling a template which calls another template containing the above code will not automatically be able to use parameters like action.
Note: You should no longer specify the expiry, as it is automatically retrieved in all cases.
Dari lua
suntingFirst, load the module.
local mProtectionBanner = require('Module:Protection banner')
Then you can make protection banners by using the _main function.
mProtectionBanner._main(args, cfg, titleObj)
args is a table of arguments to pass to the module. For possible keys and values for this table, see the parameters section. The cfg and titleObj variables are intended only for testing; cfg specifies a customised config table to use instead of Module:Protection banner/config, and titleObj specifies a mw.title object to use instead of the current title. args, cfg and titleObj are all optional.
Parameters
suntingAll parameters are optional.
- 1 – the reason that the page was protected. If set, this must be one of the values listed in the reasons table.
- small – if set to "yes", "y", "1", or "true", a padlock icon is generated instead of a full protection banner.
- action – the protection action. Must be one of "edit" (for normal protection), "move" (for move-protection) or "autoreview" (for pending changes). The default value is "edit".
- date – the protection date. This must be valid input to the second parameter of the #time parser function. This argument has an effect for reasons that use the PROTECTIONDATE parameter in their configuration. As of July 2014, those were the "office" and "reset" reasons.
- user – the username of the user to generate links for. As of July 2014, this only has an effect when the "usertalk" reason is specified.
- section – the section name of the protected page's talk page where discussion is taking place. This works for most, but not all, values of reason.
- category – categories are suppressed if this is set to "no", "n", "0", or "false".
Reasons
suntingThe following table contains the available reasons, plus the actions for which they are available.
Galat skrip: tidak ada modul tersebut "Protection banner/documentation".
Errors
suntingBelow is a list of some of the common errors that this module can produce, and how to fix them.
Invalid protection date
suntingError: invalid protection date ("abc")
This error is produced if you supply an |date=
parameter value that is not recognised as a valid date by the #time parser function. If in doubt, you can just use a date in the format "dd Month YYYY", e.g. "24 Desember 2024". To see a full range of valid inputs, see the #time documentation (only the first parameter, the format string, may be specified).
Invalid action
suntingError: invalid action ("abc")
This error is produced if you specify an invalid protection action. There are only three valid actions: edit
(the default, for normal protection), move
(for move-protection), and autoreview
(for pending changes). This should only be possible if you are using a template that supports manually specifying the protection action, such as {{pp}}, or if you are using #invoke directly. If this is not the case, please leave a message on Module talk:Protection banner.
Reasons cannot contain the pipe character
suntingError: reasons cannot contain the pipe character ("|")
Galat ini dihasilkan jika Anda memberikan alasan pada parameter |1=
mengandung karakter pipa ("|"). Periksa bahwa Anda tidak memasukkan templat {{!}} ke parameter ini. Karakter ini dilarang karena modul ini menggunakan karakter tersebut secara internal. Alasan yang valid dapat dilihat di bagian alasan.
Galat yang lain
suntingJika Anda melihat galat selain hal di atas, kemungkinan itu adalah kekutu atau kesalahan konfigurasi. Kirim pesan mengenai masalah ini di Pembicaraan Modul:Protection banner.
Detail teknis
suntingModul ini menggunakan konfigurasi Module:Protection banner/config. Kebanyakan perilaku modul, dikonfigurasi di sana sehingga sangat portabel di antara wiki dalam berbagai bahasa
Kasus uji umum modul ini dapat dilakukan di Modul:Protection banner/kasus uji, dan konfigurasinya dapat dilakukan di Modul:Protection banner/config/kasus uji.
Masalah kekutu dan fitur baru dapat dibicarakan di halaman pembicaraan modul ini.
-- 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(page, action, level)
local levels = {
edit = {},
move = {},
autoreview = {}
}
levels[action][1] = level
local title = mw.title.new(page)
return rawset(title, 'protectionLevels', levels)
end
local function makeDefaultTitleObject()
return makeTitleObject(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 = {},
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
function suite:assertIsPadlock(s, msg)
self:assertStringContains(
'^%cUNIQ.-QINU%c$',
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('Foo', 'edit', 'autoconfirmed')
)
self:assertEquals('autoconfirmed', obj.level)
end
function suite:testProtectionFull()
local obj = Protection.new(
{action = 'edit'},
makeConfig(),
makeTitleObject('Foo', 'edit', 'sysop')
)
self:assertEquals('sysop', obj.level)
end
function suite:testProtectionUnprotected()
local obj = Protection.new(
{action = 'edit'},
makeConfig(),
makeTitleObject('Foo', 'edit', nil)
)
self:assertEquals('*', obj.level)
end
function suite:testProtectionSemiMove()
local obj = Protection.new(
{action = 'move'},
makeConfig(),
makeTitleObject('Foo', 'move', 'autoconfirmed')
)
self:assertEquals('*', obj.level)
end
function suite:testProtectionTemplate()
local obj = Protection.new(
{action = 'edit'},
makeConfig(),
makeTitleObject('Template:Foo', 'edit', 'templateeditor')
)
self:assertEquals('templateeditor', obj.level)
end
function suite:testProtectionTitleBlacklist()
local obj = Protection.new(
{action = 'edit'},
makeConfig(),
makeTitleObject('Template:Editnotices/Page/Foo', 'edit', nil)
)
self:assertEquals('templateeditor', obj.level)
end
-- Expiry
function suite:testProtectionExpiryIndef()
local obj = Protection.new(
{expiry = 'indefinite'},
makeConfig{indefStrings = {indefinite = true}}
)
self:assertEquals('indef', obj.expiry)
end
function suite:testProtectionExpiryTemp()
local obj = Protection.new(
{expiry = d.expiry, action = 'autoreview' },
makeConfig()
)
self:assertEquals(d.expiryU, obj.expiry)
end
function suite:testProtectionNoExpiry()
local obj = Protection.new(
{ action = 'autoreview' },
makeConfig()
)
self:assertEquals(nil, obj.expiry)
end
function suite:testProtectionBadExpiry()
self:assertError(
Protection.new,
{{expiry = 'foobar', action = 'autoreview' }, makeConfig()},
'invalid expiry date: foobar'
)
end
function suite:testProtectionPastExpiry()
local obj = Protection.new(
{expiry = d.protectionDate, action = 'autoreview' },
makeConfig()
)
self:assertEquals(d.protectionDateU, obj.expiry)
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
-- 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
-- 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: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(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('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('Template talk:Example', 'edit', 'autoconfirmed')
)
self:assertStringContains('talk namespace', obj:makeProtectionCategory(), true)
end
-- needsExpiry
function suite:testProtectionNeedsExpiryFalse1()
local obj = makeDefaultProtectionObject()
obj.expiry = d.expiryU
self:assertFalse(
obj:needsExpiry(),
'expiry is already set'
)
end
function suite:testProtectionNeedsExpiryFalse2()
local obj = makeDefaultProtectionObject()
obj.expiry = nil
obj.action = 'move'
obj._cfg.expiryCheckActions.move = false
self:assertFalse(
obj:needsExpiry(),
'action is blacklisted in cfg.expiryCheckActions'
)
end
function suite:testProtectionNeedsExpiryFalse3()
local obj = makeDefaultProtectionObject()
obj.expiry = nil
obj.action = 'move'
obj._cfg.expiryCheckActions.move = nil
obj.reason = nil
self:assertFalse(
obj:needsExpiry(),
'cfg.expiryCheckActions is nil, and no reason is set'
)
end
function suite:testProtectionNeedsExpiryFalse4()
local obj = makeDefaultProtectionObject()
obj.expiry = nil
obj.action = 'move'
obj._cfg.expiryCheckActions.move = nil
obj.reason = 'vandalism'
obj._cfg.reasonsWithoutExpiryCheck.vandalism = true
self:assertFalse(
obj:needsExpiry(),
'cfg.expiryCheckActions is nil, and the reason is blacklisted'
)
end
function suite:testProtectionNeedsExpiryTrue1()
local obj = makeDefaultProtectionObject()
obj.expiry = nil
obj.action = 'move'
obj._cfg.expiryCheckActions.move = true
self:assertTrue(
obj:needsExpiry(),
'expiry is nil and action is whitelisted in cfg.expiryCheckActions'
)
end
function suite:testProtectionNeedsExpiryTrue2()
local obj = makeDefaultProtectionObject()
obj.expiry = nil
obj.action = 'move'
obj._cfg.expiryCheckActions.move = nil
obj.reason = 'vandalism'
obj._cfg.reasonsWithoutExpiryCheck.vandalism = nil
self:assertTrue(
obj:needsExpiry(),
'expiry and expiryCheckActions are nil, and the reason is present and'
.. ' not blacklisted.'
)
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-expiry'] = 'Expiry category',
['tracking-category-incorrect'] = 'Incorrect category',
['tracking-category-template'] = 'Template category'
}
function obj:makeProtectionCategory()
return '[[Category:Protection category|' .. d.baseText .. ']]'
end
for _, field in ipairs{'needsExpiry', 'isIncorrect', 'isTemplateProtectedNonTemplate'} do
obj[field] = function () return true end
end
self:assertEquals(
'[[Category:Protection category|' .. d.baseText .. ']]' ..
'[[Category:Expiry 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 = {expiry = 'foo', action = 'autoreview' }
local cfg = makeConfig()
local title
local success, result = pcall(mProtectionBanner._main, args, cfg, title)
self:assertFalse(success)
self:assertEquals(
'invalid expiry date: foo',
result,
false
)
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(d.page, 'edit', nil)
self:assertNoBanner(mProtectionBanner._main(args, cfg, title), 'page unprotected')
end
function suite:test_mainCategories()
local args = {}
local cfg -- Use main config module
local title = makeTitleObject(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