Module:String/testcases: Difference between revisions
Appearance
Content deleted Content added
Masoud.h1368 (talk | contribs) No edit summary Tag: Reverted |
Not what module testcases pages are for |
||
Line 1: | Line 1: | ||
-- Unit tests for [[Module:String]]. Click talk page to run tests. |
|||
--[[ |
|||
local p = require('Module:UnitTests') |
|||
function p:test_len() |
|||
This module is intended to provide access to basic string functions. |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|len|', '}}', { |
|||
{' foo ', '5'}, |
|||
Most of the functions provided here can be invoked with named parameters, |
|||
{'s= foo ', '3'}, |
|||
unnamed parameters, or a mixture. If named parameters are used, Mediawiki will |
|||
{'', '0'}, |
|||
automatically remove any leading or trailing whitespace from the parameter. |
|||
{'s=', '0'}, |
|||
Depending on the intended use, it may be advantageous to either preserve or |
|||
{' ', '3'}, |
|||
remove such whitespace. |
|||
{'最近の更新', '5'}, |
|||
}) |
|||
Global options |
|||
ignore_errors: If set to 'true' or 1, any error condition will result in |
|||
an empty string being returned rather than an error message. |
|||
error_category: If an error occurs, specifies the name of a category to |
|||
include with the error message. The default category is |
|||
[Category:Errors reported by Module String]. |
|||
no_category: If set to 'true' or 1, no category will be added if an error |
|||
is generated. |
|||
Unit tests for this module are available at Module:String/tests. |
|||
]] |
|||
local p = {} |
|||
--[[ |
|||
Helper function that populates the argument list given that user may need to use a mix of |
|||
named and unnamed parameters. This is relevant because named parameters are not |
|||
identical to unnamed parameters due to string trimming, and when dealing with strings |
|||
we sometimes want to either preserve or remove that whitespace depending on the application. |
|||
]] |
|||
local function _getParameters( frame_args, arg_list ) |
|||
local new_args = {} |
|||
local index = 1 |
|||
local value |
|||
for _, arg in ipairs( arg_list ) do |
|||
value = frame_args[arg] |
|||
if value == nil then |
|||
value = frame_args[index] |
|||
index = index + 1 |
|||
end |
|||
new_args[arg] = value |
|||
end |
|||
return new_args |
|||
end |
|||
--[[ |
|||
Helper Function to interpret boolean strings |
|||
]] |
|||
local function _getBoolean( boolean_str ) |
|||
local boolean_value |
|||
if type( boolean_str ) == 'string' then |
|||
boolean_str = boolean_str:lower() |
|||
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' |
|||
or boolean_str == '' then |
|||
boolean_value = false |
|||
else |
|||
boolean_value = true |
|||
end |
|||
elseif type( boolean_str ) == 'boolean' then |
|||
boolean_value = boolean_str |
|||
else |
|||
error( 'Cap valor booleà trobat' ) |
|||
end |
|||
return boolean_value |
|||
end |
end |
||
function p:test_replace() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|replace|', '}}', { |
|||
Helper function to handle error messages. |
|||
{'1.1.1.1|.|/', '1/1/1/1'}, |
|||
]] |
|||
{'alpha (beta)| (| gamma (', 'alpha gamma (beta)'}, |
|||
local function _error( error_str ) |
|||
{'Dog (cat)|%s%(.*%)||plain=false', 'Dog'}, |
|||
local frame = mw.getCurrentFrame() |
|||
}) |
|||
local error_category = frame.args.error_category or 'Errors detectats pel mòdul String' |
|||
local ignore_errors = frame.args.ignore_errors or false |
|||
local no_category = frame.args.no_category or false |
|||
if _getBoolean(ignore_errors) then |
|||
return '' |
|||
end |
|||
local error_str = '<strong class="error">Error del mòdul String: ' .. error_str .. '</strong>' |
|||
if error_category ~= '' and not _getBoolean( no_category ) then |
|||
error_str = '[[Categoria:' .. error_category .. ']]' .. error_str |
|||
end |
|||
return error_str |
|||
end |
end |
||
function p:test_match() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|match|', '}}', { |
|||
Helper function that escapes all pattern characters so that they will be treated |
|||
{'dog (cat)|%((%a-)%)', 'cat'}, |
|||
as plain text. |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'}, |
|||
]] |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'}, |
|||
local function _escapePattern( pattern_str ) |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'}, |
|||
return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ) |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'}, |
|||
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'}, |
|||
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''}, |
|||
}) |
|||
end |
end |
||
function p:test_match() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String|match|', '}}', { |
|||
len |
|||
{'dog (cat)|%((%a-)%)', 'cat'}, |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'}, |
|||
This function returns the length of the target string. |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'}, |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'}, |
|||
Usage: |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'}, |
|||
{{#invoke:String|len|target_string|}} |
|||
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'}, |
|||
OR |
|||
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''}, |
|||
{{#invoke:String|len|s=target_string}} |
|||
}) |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|match|', '}}', { |
|||
Parameters |
|||
{'dog (cat)|%((%a-)%)', 'cat'}, |
|||
s: The string whose length to report |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'}, |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'}, |
|||
If invoked using named parameters, Mediawiki will automatically remove any leading or |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'}, |
|||
trailing whitespace from the target string. |
|||
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'}, |
|||
]] |
|||
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'}, |
|||
function p.len( frame ) |
|||
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''}, |
|||
local new_args = _getParameters( frame.args, {'s'} ) |
|||
}) |
|||
local s = new_args['s'] or '' |
|||
return mw.ustring.len( s ) |
|||
end |
end |
||
function p:test_find() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|find|', '}}', { |
|||
sub |
|||
{'', '0'}, |
|||
{'source=', '0'}, |
|||
This function returns a substring of the target string at specified indices. |
|||
{'source=|target=', '0'}, |
|||
{'source=|target=Bob', '0'}, |
|||
Usage: |
|||
{'Bob|Joe', '0'}, |
|||
{{#invoke:String|sub|target_string|start_index|end_index}} |
|||
{'Bob|b', '3'}, |
|||
OR |
|||
{'Bob Joe|oe', '6'}, |
|||
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}} |
|||
{'source= Bob |o', '2'}, |
|||
{' Bob |o', '3'}, |
|||
Parameters |
|||
{'높지만 급격히|만', '3'}, |
|||
s: The string to return a subset of |
|||
{'source=BAAAB|target=%w|plain=false', '1'}, |
|||
i: The fist index of the substring to return, defaults to 1. |
|||
{'source=BAAAB|target=%w|start=3|plain=false', '3'}, |
|||
j: The last index of the string to return, defaults to the last character. |
|||
{'source=BAAAB|target=(%w)%1|plain=false', '2'}, |
|||
}) |
|||
The first character of the string is assigned an index of 1. If either i or j |
|||
is a negative value, it is interpreted the same as selecting a character by |
|||
counting from the end of the string. Hence, a value of -1 is the same as |
|||
selecting the last character of the string. |
|||
If the requested indices are out of range for the given string, an error is |
|||
reported. |
|||
]] |
|||
function p.sub( frame ) |
|||
local new_args = _getParameters( frame.args, { 's', 'i', 'j' } ) |
|||
local s = new_args['s'] or '' |
|||
local i = tonumber( new_args['i'] ) or 1 |
|||
local j = tonumber( new_args['j'] ) or -1 |
|||
local len = mw.ustring.len( s ) |
|||
-- Convert negatives for range checking |
|||
if i < 0 then |
|||
i = len + i + 1 |
|||
end |
|||
if j < 0 then |
|||
j = len + j + 1 |
|||
end |
|||
if i > len or j > len or i < 1 or j < 1 then |
|||
return _error( 'Índex fora del rang de la cadena' ) |
|||
end |
|||
if j < i then |
|||
return _error( 'Índexs de la cadena no ordenats' ) |
|||
end |
|||
return mw.ustring.sub( s, i, j ) |
|||
end |
end |
||
function p:test_rep() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String|rep|', '}}', { |
|||
match |
|||
{'abc|1', 'abc'}, |
|||
{'a b|7', 'a ba ba ba ba ba ba b'}, |
|||
This function returns a substring from the source string that matches a |
|||
{'bla|glug|no_category=true', '<strong class="error">String Module Error: function rep expects a number as second parameter, received "glug"</strong>'}, |
|||
specified pattern. |
|||
{'bla|glug|ignore_errors=true', ''}, |
|||
{'àèò|3', 'àèòàèòàèò'} |
|||
Usage: |
|||
}) |
|||
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}} |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|rep|', '}}', { |
|||
OR |
|||
{'abc|1', 'abc'}, |
|||
{{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index |
|||
{'a b|7', 'a ba ba ba ba ba ba b'}, |
|||
|match=match_number|plain=plain_flag|nomatch=nomatch_output}} |
|||
{'bla|glug|no_category=true', '<strong class="error">String Module Error: function rep expects a number as second parameter, received "glug"</strong>'}, |
|||
{'bla|glug|ignore_errors=true', ''}, |
|||
Parameters |
|||
{'àèò|3', 'àèòàèòàèò'} |
|||
s: The string to search |
|||
}) |
|||
pattern: The pattern or string to find within the string |
|||
start: The index within the source string to start the search. The first |
|||
character of the string has index 1. Defaults to 1. |
|||
match: In some cases it may be possible to make multiple matches on a single |
|||
string. This specifies which match to return, where the first match is |
|||
match= 1. If a negative number is specified then a match is returned |
|||
counting from the last match. Hence match = -1 is the same as requesting |
|||
the last match. Defaults to 1. |
|||
plain: A flag indicating that the pattern should be understood as plain |
|||
text. Defaults to false. |
|||
nomatch: If no match is found, output the "nomatch" value rather than an error. |
|||
If invoked using named parameters, Mediawiki will automatically remove any leading or |
|||
trailing whitespace from each string. In some circumstances this is desirable, in |
|||
other cases one may want to preserve the whitespace. |
|||
If the match_number or start_index are out of range for the string being queried, then |
|||
this function generates an error. An error is also generated if no match is found. |
|||
If one adds the parameter ignore_errors=true, then the error will be suppressed and |
|||
an empty string will be returned on any failure. |
|||
For information on constructing Lua patterns, a form of [regular expression], see: |
|||
* http://www.lua.org/manual/5.1/manual.html#5.4.1 |
|||
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns |
|||
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns |
|||
]] |
|||
-- This sub-routine is exported for use in other modules |
|||
function p._match( s, pattern, start, match_index, plain_flag, nomatch ) |
|||
if s == '' then |
|||
return _error( 'Cadena on cercar està buida' ) |
|||
end |
|||
if pattern == '' then |
|||
return _error( 'Cadena de cerca està buida' ) |
|||
end |
|||
start = tonumber(start) or 1 |
|||
if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then |
|||
return _error( 'Índex d\'inici fora del rang de la cadena' ) |
|||
end |
|||
if match_index == 0 then |
|||
return _error( 'Número de coincidència fora de rang' ) |
|||
end |
|||
if plain_flag then |
|||
pattern = str._escapePattern( pattern ) |
|||
end |
|||
local result |
|||
if match_index == 1 then |
|||
-- Find first match is simple case |
|||
result = mw.ustring.match( s, pattern, start ) |
|||
else |
|||
if start > 1 then |
|||
s = mw.ustring.sub( s, start ) |
|||
end |
|||
local iterator = mw.ustring.gmatch(s, pattern) |
|||
if match_index > 0 then |
|||
-- Forward search |
|||
for w in iterator do |
|||
match_index = match_index - 1 |
|||
if match_index == 0 then |
|||
result = w |
|||
break |
|||
end |
|||
end |
|||
else |
|||
-- Reverse search |
|||
local result_table = {} |
|||
local count = 1 |
|||
for w in iterator do |
|||
result_table[count] = w |
|||
count = count + 1 |
|||
end |
|||
result = result_table[ count + match_index ] |
|||
end |
|||
end |
|||
if result == nil then |
|||
if nomatch == nil then |
|||
return _error( 'Cap coincidència trobada' ) |
|||
else |
|||
return nomatch |
|||
end |
|||
else |
|||
return result |
|||
end |
|||
end |
end |
||
-- This is the entry point for #invoke:String|match |
|||
function p.match( frame ) |
|||
local new_args = _getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} ) |
|||
local s = new_args['s'] or '' |
|||
local start = tonumber( new_args['start'] ) or 1 |
|||
local plain_flag = _getBoolean( new_args['plain'] or false ) |
|||
local pattern = new_args['pattern'] or '' |
|||
local match_index = math.floor( tonumber(new_args['match']) or 1 ) |
|||
local nomatch = new_args['nomatch'] |
|||
return p._match( s, pattern, start, match_index, plain_flag, nomatch ) |
|||
end |
|||
--[[ |
|||
pos |
|||
This function returns a single character from the target string at position pos. |
|||
Usage: |
|||
{{#invoke:String|pos|target_string|index_value}} |
|||
OR |
|||
{{#invoke:String|pos|target=target_string|pos=index_value}} |
|||
Parameters |
|||
target: The string to search |
|||
pos: The index for the character to return |
|||
If invoked using named parameters, Mediawiki will automatically remove any leading or |
|||
trailing whitespace from the target string. In some circumstances this is desirable, in |
|||
other cases one may want to preserve the whitespace. |
|||
The first character has an index value of 1. |
|||
If one requests a negative value, this function will select a character by counting backwards |
|||
from the end of the string. In other words pos = -1 is the same as asking for the last character. |
|||
function p:test_escapePattern() |
|||
A requested value of zero, or a value greater than the length of the string returns an error. |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|escapePattern|', '}}', { |
|||
]] |
|||
{'foo', 'foo'}, |
|||
function p.pos( frame ) |
|||
{'A.D.', 'A%.D%.'}, |
|||
local new_args = _getParameters( frame.args, {'target', 'pos'} ) |
|||
{'0123', '0123'}, |
|||
local target_str = new_args['target'] or '' |
|||
{'^', '%^'}, |
|||
local pos = tonumber( new_args['pos'] ) or 0 |
|||
{'$', '%$'}, |
|||
{'(', '%('}, |
|||
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then |
|||
{')', '%)'}, |
|||
return _error( 'Índex fora del rang de la cadena' ) |
|||
{'%', '%%'}, |
|||
end |
|||
{'.', '%.'}, |
|||
{'[', '%['}, |
|||
return mw.ustring.sub( target_str, pos, pos ) |
|||
{']', '%]'}, |
|||
{'*', '%*'}, |
|||
{'+', '%+'}, |
|||
{'-', '%-'}, |
|||
{'?', '%?'}, |
|||
{'!', '!'}, |
|||
{'"', '"'}, |
|||
{'&', '&'}, |
|||
{"'", "'"}, |
|||
{'{', '{'}, |
|||
{'}', '}'}, |
|||
{'`', '`'}, |
|||
{'@', '@'}, |
|||
{',', ','}, |
|||
{'<', '<'}, |
|||
{'>', '>'}, |
|||
{'/', '/'}, |
|||
{'_', '_'}, |
|||
{'\\', '\\'}, |
|||
{'~', '~'}, |
|||
{' ', ' '}, |
|||
{'', ''}, |
|||
{'x#', 'x#'}, -- We can't just test "#" because it will be interpreted as a list |
|||
{'x;', 'x;'}, -- We can't just test ";" because it will be interpreted as a list |
|||
{'x:', 'x:'}, -- We can't just test ":" because it will be interpreted as a list |
|||
{'{{!}}', '|'}, -- Need to escape the template pipe syntax |
|||
{'1==', '='}, -- Need to escape the "foo = bar" template syntax |
|||
{'no_category=true', '<strong class="error">String Module Error: No pattern string specified</strong>'}, |
|||
}) |
|||
end |
end |
||
function p:test_join() |
|||
--[[ |
|||
self:preprocess_equals_many('{{#invoke:String/sandbox|join|', '}}', { |
|||
find |
|||
{'', ''}, |
|||
{'X', ''}, |
|||
{'X|a', 'a'}, |
|||
{'X|a|b', 'aXb'}, |
|||
{'X|a|b|c', 'aXbXc'}, |
|||
{'X|a|b|c|d', 'aXbXcXd'}, |
|||
{'X|a|b||d', 'aXbXd'}, |
|||
{'X|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z', 'aXbXcXdXeXfXgXhXiXjXkXlXmXnXoXpXqXrXsXtXuXvXwXxXyXz'} |
|||
}) |
|||
This function allows one to search for a target string or pattern within another |
|||
string. |
|||
Usage: |
|||
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}} |
|||
OR |
|||
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}} |
|||
Parameters |
|||
source: The string to search |
|||
target: The string or pattern to find within source |
|||
start: The index within the source string to start the search, defaults to 1 |
|||
plain: Boolean flag indicating that target should be understood as plain |
|||
text and not as a Lua style regular expression, defaults to true |
|||
If invoked using named parameters, Mediawiki will automatically remove any leading or |
|||
trailing whitespace from the parameter. In some circumstances this is desirable, in |
|||
other cases one may want to preserve the whitespace. |
|||
This function returns the first index >= "start" where "target" can be found |
|||
within "source". Indices are 1-based. If "target" is not found, then this |
|||
function returns 0. If either "source" or "target" are missing / empty, this |
|||
function also returns 0. |
|||
This function should be safe for UTF-8 strings. |
|||
]] |
|||
function p.find( frame ) |
|||
local new_args = _getParameters( frame.args, {'source', 'target', 'start', 'plain' } ) |
|||
local source_str = new_args['source'] or '' |
|||
local pattern = new_args['target'] or '' |
|||
local start_pos = tonumber(new_args['start']) or 1 |
|||
local plain = new_args['plain'] or true |
|||
if source_str == '' or pattern == '' then |
|||
return 0 |
|||
end |
|||
plain = _getBoolean( plain ) |
|||
local start = mw.ustring.find( source_str, pattern, start_pos, plain ) |
|||
if start == nil then |
|||
start = 0 |
|||
end |
|||
return start |
|||
end |
end |
||
--[[ |
|||
replace |
|||
This function allows one to replace a target string or pattern within another |
|||
string. |
|||
Usage: |
|||
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}} |
|||
OR |
|||
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string| |
|||
count=replacement_count|plain=plain_flag}} |
|||
Parameters |
|||
source: The string to search |
|||
pattern: The string or pattern to find within source |
|||
replace: The replacement text |
|||
count: The number of occurences to replace, defaults to all. |
|||
plain: Boolean flag indicating that pattern should be understood as plain |
|||
text and not as a Lua style regular expression, defaults to true |
|||
]] |
|||
function p.replace( frame ) |
|||
local new_args = _getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } ) |
|||
local source_str = new_args['source'] or '' |
|||
local pattern = new_args['pattern'] or '' |
|||
local replace = new_args['replace'] or '' |
|||
local count = tonumber( new_args['count'] ) |
|||
local plain = new_args['plain'] or true |
|||
if source_str == '' or pattern == '' then |
|||
return source_str |
|||
end |
|||
plain = _getBoolean( plain ) |
|||
if plain then |
|||
pattern = _escapePattern( pattern ) |
|||
replace = mw.ustring.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences. |
|||
end |
|||
local result |
|||
if count ~= nil then |
|||
result = mw.ustring.gsub( source_str, pattern, replace, count ) |
|||
else |
|||
result = mw.ustring.gsub( source_str, pattern, replace ) |
|||
end |
|||
return result |
|||
end |
|||
--[[ |
|||
simple function to pipe string.rep to templates. |
|||
]] |
|||
function p.rep( frame ) |
|||
local repetitions = tonumber( frame.args[2] ) |
|||
if not repetitions then |
|||
return _error( "s'esperava un número com a segon paràmetre; trobat: " .. ( frame.args[2] or '' )) |
|||
end |
|||
return string.rep( frame.args[1] or '', repetitions ) |
|||
end |
|||
--[[ |
|||
escapePattern |
|||
This function escapes special characters from a Lua string pattern. See [1] |
|||
for details on how patterns work. |
|||
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns |
|||
Usage: |
|||
{{#invoke:String|escapePattern|pattern_string}} |
|||
Parameters |
|||
pattern_string: The pattern string to escape. |
|||
]] |
|||
function p.escapePattern( frame ) |
|||
local pattern_str = frame.args[1] |
|||
if not pattern_str then |
|||
return _error( 'No pattern string specified' ) |
|||
end |
|||
local result = _escapePattern( pattern_str ) |
|||
return result |
|||
end |
|||
--[[ |
|||
count |
|||
This function counts the number of occurrences of one string in another. |
|||
]] |
|||
function p.count(frame) |
|||
local args = _getParameters(frame.args, {'source', 'pattern', 'plain'}) |
|||
local source = args.source or '' |
|||
local pattern = args.pattern or '' |
|||
local plain = _getBoolean(args.plain or true) |
|||
if plain then |
|||
pattern = _escapePattern(pattern) |
|||
end |
|||
local _, count = mw.ustring.gsub(source, pattern, '') |
|||
return count |
|||
end |
|||
--[[ |
|||
endswith |
|||
This function determines whether a string ends with another string. |
|||
]] |
|||
function p.endswith(frame) |
|||
local args = _getParameters(frame.args, {'source', 'pattern'}) |
|||
local source = args.source or '' |
|||
local pattern = args.pattern or '' |
|||
if pattern == '' then |
|||
-- All strings end with the empty string. |
|||
return "yes" |
|||
end |
|||
if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then |
|||
return "yes" |
|||
else |
|||
return "" |
|||
end |
|||
end |
|||
--[[ |
|||
join |
|||
Join all non empty arguments together; the first argument is the separator. |
|||
Usage: |
|||
{{#invoke:String|join|sep|one|two|three}} |
|||
]] |
|||
function p.join(frame) |
|||
local args = {} |
|||
local sep |
|||
for _, v in ipairs( frame.args ) do |
|||
if sep then |
|||
if v ~= '' then |
|||
table.insert(args, v) |
|||
end |
|||
else |
|||
sep = v |
|||
end |
|||
end |
|||
return table.concat( args, sep or '' ) |
|||
end |
|||
--[[ |
|||
Strip |
|||
This function Strips charecters from string |
|||
Usage: |
|||
{{#invoke:StringFunc|strip|source_string|charecters_to_strip|plain_flag}} |
|||
Parameters |
|||
source: The string to strip |
|||
chars: The pattern or list of charecters to strip from string, replaced with '' |
|||
plain: A flag indicating that the chars should be understood as plain text. defaults to true. |
|||
Leading and trailing whitespace is also automatically stripped from the string. |
|||
]] |
|||
function p.strip( frame ) |
|||
local new_args = _getParameters( frame.args, {'source', 'chars', 'plain'} ) |
|||
local source_str = new_args['source'] or '' |
|||
local chars = new_args['chars'] or '' |
|||
source_str = mw.text.trim(source_str) |
|||
if source_str == '' or chars == '' then |
|||
return source_str |
|||
end |
|||
local l_plain = _getBoolean( new_args['plain'] or true ) |
|||
if l_plain then |
|||
chars = _escapePattern( chars ) |
|||
end |
|||
local result |
|||
result = mw.ustring.gsub(source_str, "["..chars.."]", '') |
|||
return result |
|||
end |
|||
--[[ |
|||
Split |
|||
This function Splits a string based on a separator, returns nth substring based on count. |
|||
Usage: |
|||
{{#invoke:StringFunc|split|source_string|separator|count}} |
|||
Parameters: |
|||
source: The string to return a subset of |
|||
separator: The string to split on |
|||
count: The nth substring based on the separator to return |
|||
]] |
|||
function p.split( frame ) |
|||
local new_args = _getParameters( frame.args, {'source', 'separator', 'count'} ) |
|||
local source_str = new_args['source'] or '' |
|||
local separator = new_args['separator'] or '' |
|||
local separator_len = mw.ustring.len(separator) |
|||
if source_str == '' or separator == '' then |
|||
return source_str; |
|||
end |
|||
local ret_count = tonumber( new_args['count'] ) or 1 |
|||
if ret_count < 1 then |
|||
return "" |
|||
end |
|||
local start = 1 |
|||
local iter = mw.ustring.find(source_str, separator, start, true) |
|||
if iter == nil then |
|||
if ret_count == 1 then |
|||
return source_str |
|||
else |
|||
return "" |
|||
end |
|||
else |
|||
iter = iter - 1 |
|||
end |
|||
if ret_count == 1 then |
|||
return mw.ustring.sub( source_str, start, iter) |
|||
end |
|||
for i=2, ret_count do |
|||
start = iter+separator_len + 1 |
|||
iter = mw.ustring.find(source_str, separator, start, true) |
|||
if iter == nil then |
|||
if ret_count == i then |
|||
return mw.ustring.sub(source_str, start, mw.ustring.len(source_str)) |
|||
else |
|||
return "" |
|||
end |
|||
else |
|||
iter = iter - 1 |
|||
end |
|||
end |
|||
return mw.ustring.sub( source_str,start,iter) |
|||
end |
|||
function p.isNumber( frame ) |
|||
local new_args = _getParameters( frame.args, {'source'} ) |
|||
local source_str = new_args['source'] or '' |
|||
if source_str == '' then |
|||
return "false" |
|||
end |
|||
if tonumber(source_str) == nil and tonumber(string.gsub(source_str, ",", ".", 1) .. '') == nil then |
|||
return "false" |
|||
end |
|||
return "true" |
|||
end |
|||
return p |
return p |
Revision as of 03:49, 30 March 2021
![]() | This is the test cases page for the module Module:String. Results of the test cases. |
-- Unit tests for [[Module:String]]. Click talk page to run tests.
local p = require('Module:UnitTests')
function p:test_len()
self:preprocess_equals_many('{{#invoke:String/sandbox|len|', '}}', {
{' foo ', '5'},
{'s= foo ', '3'},
{'', '0'},
{'s=', '0'},
{' ', '3'},
{'最近の更新', '5'},
})
end
function p:test_replace()
self:preprocess_equals_many('{{#invoke:String/sandbox|replace|', '}}', {
{'1.1.1.1|.|/', '1/1/1/1'},
{'alpha (beta)| (| gamma (', 'alpha gamma (beta)'},
{'Dog (cat)|%s%(.*%)||plain=false', 'Dog'},
})
end
function p:test_match()
self:preprocess_equals_many('{{#invoke:String/sandbox|match|', '}}', {
{'dog (cat)|%((%a-)%)', 'cat'},
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'},
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'},
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'},
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''},
})
end
function p:test_match()
self:preprocess_equals_many('{{#invoke:String|match|', '}}', {
{'dog (cat)|%((%a-)%)', 'cat'},
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'},
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'},
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'},
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''},
})
self:preprocess_equals_many('{{#invoke:String/sandbox|match|', '}}', {
{'dog (cat)|%((%a-)%)', 'cat'},
{'dog (cat) (canary) (fish)|%((%a-)%)||-1', 'fish'},
{'dog (cat) (canary) (fish)|%((%a-)%)||2', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|1', 'canary'},
{'dog (cat) (canary) (fish)|%((%a-)%)|6|2', 'fish'},
{'dog (cat)|%((%a-)%)||2|no_category=true', '<strong class="error">String Module Error: Match not found</strong>'},
{'dog (cat)|%((%a-)%)||2|ignore_errors=true', ''},
})
end
function p:test_find()
self:preprocess_equals_many('{{#invoke:String/sandbox|find|', '}}', {
{'', '0'},
{'source=', '0'},
{'source=|target=', '0'},
{'source=|target=Bob', '0'},
{'Bob|Joe', '0'},
{'Bob|b', '3'},
{'Bob Joe|oe', '6'},
{'source= Bob |o', '2'},
{' Bob |o', '3'},
{'높지만 급격히|만', '3'},
{'source=BAAAB|target=%w|plain=false', '1'},
{'source=BAAAB|target=%w|start=3|plain=false', '3'},
{'source=BAAAB|target=(%w)%1|plain=false', '2'},
})
end
function p:test_rep()
self:preprocess_equals_many('{{#invoke:String|rep|', '}}', {
{'abc|1', 'abc'},
{'a b|7', 'a ba ba ba ba ba ba b'},
{'bla|glug|no_category=true', '<strong class="error">String Module Error: function rep expects a number as second parameter, received "glug"</strong>'},
{'bla|glug|ignore_errors=true', ''},
{'àèò|3', 'àèòàèòàèò'}
})
self:preprocess_equals_many('{{#invoke:String/sandbox|rep|', '}}', {
{'abc|1', 'abc'},
{'a b|7', 'a ba ba ba ba ba ba b'},
{'bla|glug|no_category=true', '<strong class="error">String Module Error: function rep expects a number as second parameter, received "glug"</strong>'},
{'bla|glug|ignore_errors=true', ''},
{'àèò|3', 'àèòàèòàèò'}
})
end
function p:test_escapePattern()
self:preprocess_equals_many('{{#invoke:String/sandbox|escapePattern|', '}}', {
{'foo', 'foo'},
{'A.D.', 'A%.D%.'},
{'0123', '0123'},
{'^', '%^'},
{'$', '%$'},
{'(', '%('},
{')', '%)'},
{'%', '%%'},
{'.', '%.'},
{'[', '%['},
{']', '%]'},
{'*', '%*'},
{'+', '%+'},
{'-', '%-'},
{'?', '%?'},
{'!', '!'},
{'"', '"'},
{'&', '&'},
{"'", "'"},
{'{', '{'},
{'}', '}'},
{'`', '`'},
{'@', '@'},
{',', ','},
{'<', '<'},
{'>', '>'},
{'/', '/'},
{'_', '_'},
{'\\', '\\'},
{'~', '~'},
{' ', ' '},
{'', ''},
{'x#', 'x#'}, -- We can't just test "#" because it will be interpreted as a list
{'x;', 'x;'}, -- We can't just test ";" because it will be interpreted as a list
{'x:', 'x:'}, -- We can't just test ":" because it will be interpreted as a list
{'{{!}}', '|'}, -- Need to escape the template pipe syntax
{'1==', '='}, -- Need to escape the "foo = bar" template syntax
{'no_category=true', '<strong class="error">String Module Error: No pattern string specified</strong>'},
})
end
function p:test_join()
self:preprocess_equals_many('{{#invoke:String/sandbox|join|', '}}', {
{'', ''},
{'X', ''},
{'X|a', 'a'},
{'X|a|b', 'aXb'},
{'X|a|b|c', 'aXbXc'},
{'X|a|b|c|d', 'aXbXcXd'},
{'X|a|b||d', 'aXbXd'},
{'X|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z', 'aXbXcXdXeXfXgXhXiXjXkXlXmXnXoXpXqXrXsXtXuXvXwXxXyXz'}
})
end
return p