mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/TemplateData
synced 2024-09-25 11:17:40 +00:00
5c7f50de62
It looks like this is how the code was originally intended, but 'name' and 'key' are the same thing. Move the key to the 'alias' list where CSS already exists to colour it differently. Change-Id: Ieade122633cec14203f7959121e9cd7250bb9f7a
643 lines
17 KiB
JavaScript
643 lines
17 KiB
JavaScript
/**
|
|
* TemplateData Generator GUI Unit Tests
|
|
*/
|
|
|
|
( function () {
|
|
'use strict';
|
|
|
|
var i, testVars, finalJsonStringParams, finalJsonStringOnly,
|
|
resultDescCurrLang, resultDescMockLang, resultDescBothLang, currLanguage, originalWikitext;
|
|
|
|
QUnit.module( 'ext.templateData', QUnit.newMwEnvironment() );
|
|
|
|
resultDescCurrLang = {};
|
|
resultDescMockLang = {};
|
|
resultDescBothLang = {};
|
|
currLanguage = mw.config.get( 'wgContentLanguage' ) || 'en';
|
|
originalWikitext = 'Some text here that is not templatedata information.' +
|
|
'<templatedata>' +
|
|
'{' +
|
|
' "description": {\n' +
|
|
' "' + currLanguage + '": "Label unsigned comments in a conversation.",\n' +
|
|
' "blah": "Template description in some blah language."\n' +
|
|
' },' +
|
|
' "params": {' +
|
|
' "user": {' +
|
|
' "label": "Username",' +
|
|
' "type": "wiki-user-name",' +
|
|
' "required": true,' +
|
|
' "description": "User name of person who forgot to sign their comment.",' +
|
|
' "aliases": ["1"]' +
|
|
' },' +
|
|
' "date": {' +
|
|
' "label": "Date",' +
|
|
' "description": {' +
|
|
' "en": "Timestamp of when the comment was posted, in YYYY-MM-DD format."' +
|
|
' },' +
|
|
' "aliases": ["2"],' +
|
|
' "autovalue": "{{subst:CURRENTMONTHNAME}}",' +
|
|
' "suggested": true' +
|
|
' },' +
|
|
' "year": {' +
|
|
' "label": "Year",' +
|
|
' "type": "number"' +
|
|
' },' +
|
|
' "month": {' +
|
|
' "label": "Month",' +
|
|
' "inherits": "year"' +
|
|
' },' +
|
|
' "day": {' +
|
|
' "label": "Day",' +
|
|
' "inherits": "year"' +
|
|
' },' +
|
|
' "comment": {' +
|
|
' "required": false' +
|
|
' }' +
|
|
' },' +
|
|
' "sets": [' +
|
|
' {' +
|
|
' "label": "Date",' +
|
|
' "params": ["year", "month", "day"]' +
|
|
' }' +
|
|
' ]' +
|
|
'}' +
|
|
'</templatedata>' +
|
|
'Trailing text at the end.';
|
|
|
|
// Prepare description language objects
|
|
resultDescCurrLang[ currLanguage ] = 'Some string here in ' + currLanguage + ' language.';
|
|
resultDescMockLang.blah = 'Some string here in blah language.';
|
|
resultDescBothLang = $.extend( {}, resultDescCurrLang, resultDescMockLang );
|
|
finalJsonStringParams = ' "params": {\n' +
|
|
' "user": {\n' +
|
|
' "label": "Username",\n' +
|
|
' "type": "wiki-user-name",\n' +
|
|
' "required": true,\n' +
|
|
' "description": "User name of person who forgot to sign their comment.",\n' +
|
|
' "aliases": [\n' +
|
|
' "1"\n' +
|
|
' ]\n' +
|
|
' },\n' +
|
|
' "date": {\n' +
|
|
' "label": "Date",\n' +
|
|
' "description": {\n' +
|
|
' "en": "Timestamp of when the comment was posted, in YYYY-MM-DD format."\n' +
|
|
' },\n' +
|
|
' "aliases": [\n' +
|
|
' "2"\n' +
|
|
' ],\n' +
|
|
' "autovalue": "{{subst:CURRENTMONTHNAME}}",\n' +
|
|
' "suggested": true\n' +
|
|
' },\n' +
|
|
' "year": {\n' +
|
|
' "label": "Year",\n' +
|
|
' "type": "number"\n' +
|
|
' },\n' +
|
|
' "month": {\n' +
|
|
' "label": "Month",\n' +
|
|
' "inherits": "year"\n' +
|
|
' },\n' +
|
|
' "comment": {\n' +
|
|
' "required": false,\n' +
|
|
' "type": "wiki-page-name"\n' +
|
|
' },\n' +
|
|
' "newParam1": {\n' +
|
|
' "description": {\n' +
|
|
' "' + currLanguage + '": "Some string here in ' + currLanguage + ' language.",\n' +
|
|
' "blah": "Some string here in blah language."\n' +
|
|
' },\n' +
|
|
' "required": true\n' +
|
|
' },\n' +
|
|
' "newParam2": {},\n' +
|
|
' "newParam3": {\n' +
|
|
' "description": "Some string here in ' + currLanguage + ' language.",\n' +
|
|
' "deprecated": "This is deprecated."\n' +
|
|
' },\n' +
|
|
' "newParam4": {\n' +
|
|
' "description": {\n' +
|
|
' "' + currLanguage + '": "' + resultDescBothLang[ currLanguage ] + '",\n' +
|
|
' "blah": "' + resultDescBothLang.blah + '"\n' +
|
|
' }\n' +
|
|
' }\n' +
|
|
' },\n';
|
|
finalJsonStringOnly = '{\n' +
|
|
' "description": {\n' +
|
|
' "' + currLanguage + '": "Label unsigned comments in a conversation.",\n' +
|
|
' "blah": "Template description in some blah language."\n' +
|
|
' },\n' + finalJsonStringParams +
|
|
' "sets": [\n' +
|
|
' {\n' +
|
|
' "label": "Date",\n' +
|
|
' "params": [\n' +
|
|
' "year",\n' +
|
|
' "month",\n' +
|
|
' "day"\n' +
|
|
' ]\n' +
|
|
' }\n' +
|
|
' ],\n' +
|
|
' "format": "inline"\n' +
|
|
'}';
|
|
|
|
// Test validation tools
|
|
QUnit.test( 'Validation tools', function ( assert ) {
|
|
var tests = {
|
|
compare: [
|
|
{
|
|
obj1: {},
|
|
obj2: [],
|
|
result: false,
|
|
msg: 'Compare: object vs array'
|
|
},
|
|
{
|
|
obj1: null,
|
|
obj2: undefined,
|
|
result: false,
|
|
msg: 'Compare: null vs undefined'
|
|
},
|
|
{
|
|
obj1: 'string',
|
|
obj2: undefined,
|
|
result: false,
|
|
msg: 'Compare: string vs undefined'
|
|
},
|
|
{
|
|
obj1: undefined,
|
|
obj2: undefined,
|
|
result: true,
|
|
msg: 'Compare: undefined vs undefined'
|
|
},
|
|
{
|
|
obj1: null,
|
|
obj2: null,
|
|
result: true,
|
|
msg: 'Compare: null vs null'
|
|
},
|
|
{
|
|
obj1: 'A proper string.',
|
|
obj2: 'A proper string.',
|
|
result: true,
|
|
msg: 'Compare: strings'
|
|
},
|
|
{
|
|
obj1: true,
|
|
obj2: true,
|
|
result: true,
|
|
msg: 'Compare: booleans'
|
|
},
|
|
{
|
|
obj1: { 1: 'string', 2: 'another', 4: 'and another' },
|
|
obj2: { 1: 'string', 2: 'another', 4: 'and another' },
|
|
result: true,
|
|
allowSubset: true,
|
|
msg: 'Compare: plain object full equality'
|
|
},
|
|
{
|
|
obj1: { 1: 'string', 2: 'another', 4: 'and another' },
|
|
obj2: { 1: 'another', 2: 'and another', 4: 'string' },
|
|
result: false,
|
|
allowSubset: true,
|
|
msg: 'Compare: plain object full inequality'
|
|
},
|
|
{
|
|
obj1: { 1: 'string', 2: 'another', 4: 'and another' },
|
|
obj2: { 4: 'and another' },
|
|
result: true,
|
|
allowSubset: true,
|
|
msg: 'Compare: plain object subset equality'
|
|
},
|
|
{
|
|
obj1: [ 'val1', 'val2', 'val3' ],
|
|
obj2: [ 'val1', 'val2', 'val3' ],
|
|
result: true,
|
|
msg: 'Compare: arrays'
|
|
},
|
|
{
|
|
obj1: [ 'val1', 'val2', 'val3' ],
|
|
obj2: [ 'val1' ],
|
|
result: true,
|
|
allowSubset: true,
|
|
msg: 'Compare: array subset: true'
|
|
},
|
|
{
|
|
obj1: [ 'val1', 'val2', 'val3' ],
|
|
obj2: [ 'val1' ],
|
|
result: false,
|
|
allowSubset: false,
|
|
msg: 'Compare: array subset: false'
|
|
},
|
|
{
|
|
obj1: {
|
|
param1: {
|
|
type: 'undefined',
|
|
aliases: [ 'alias2', 'alias1', 'alias3' ],
|
|
description: 'Some description',
|
|
required: true,
|
|
suggested: false
|
|
},
|
|
param2: {
|
|
required: true
|
|
}
|
|
},
|
|
obj2: {
|
|
param1: {
|
|
type: 'undefined',
|
|
aliases: [ 'alias2', 'alias1', 'alias3' ],
|
|
description: 'Some description',
|
|
required: true,
|
|
suggested: false
|
|
},
|
|
param2: {
|
|
required: true
|
|
}
|
|
},
|
|
result: true,
|
|
allowSubset: true,
|
|
msg: 'Compare: complex objects'
|
|
},
|
|
{
|
|
obj1: {
|
|
param1: {
|
|
type: 'undefined',
|
|
aliases: [ 'alias1', 'alias2', 'alias3' ],
|
|
description: 'Some description',
|
|
required: true,
|
|
suggested: false
|
|
},
|
|
param2: {
|
|
required: true
|
|
}
|
|
},
|
|
obj2: {
|
|
param1: {
|
|
aliases: [ 'alias1', 'alias2', 'alias3' ],
|
|
suggested: false
|
|
}
|
|
},
|
|
result: true,
|
|
allowSubset: true,
|
|
msg: 'Compare: complex objects subset'
|
|
}
|
|
],
|
|
splitAndTrimArray: [
|
|
{
|
|
string: 'str1 , str2 ',
|
|
delim: ',',
|
|
result: [ 'str1', 'str2' ],
|
|
msg: 'splitAndTrimArray: split and trim'
|
|
},
|
|
{
|
|
string: 'str1, str2, , , , str3',
|
|
delim: ',',
|
|
result: [ 'str1', 'str2', 'str3' ],
|
|
msg: 'splitAndTrimArray: remove empty values'
|
|
},
|
|
{
|
|
string: 'str1|str2|str3',
|
|
delim: '|',
|
|
result: [ 'str1', 'str2', 'str3' ],
|
|
msg: 'splitAndTrimArray: different delimeter'
|
|
}
|
|
],
|
|
arrayUnionWithoutEmpty: [
|
|
{
|
|
arrays: [ [ 'en', 'he', '' ], [ 'he', 'de', '' ], [ 'en', 'de' ] ],
|
|
result: [ 'en', 'he', 'de' ],
|
|
msg: 'arrayUnionWithoutEmpty: Remove duplications'
|
|
},
|
|
{
|
|
arrays: [ [ 'en', '', '' ], [ 'he', '', '' ], [ 'de', '' ] ],
|
|
result: [ 'en', 'he', 'de' ],
|
|
msg: 'arrayUnionWithoutEmpty: Remove empty values'
|
|
}
|
|
],
|
|
props: {
|
|
all: [
|
|
'name',
|
|
'aliases',
|
|
'label',
|
|
'description',
|
|
'example',
|
|
'type',
|
|
'default',
|
|
'autovalue',
|
|
'deprecated',
|
|
'deprecatedValue',
|
|
'required',
|
|
'suggested'
|
|
],
|
|
language: [
|
|
'label',
|
|
'description',
|
|
'example',
|
|
'default'
|
|
]
|
|
}
|
|
};
|
|
|
|
QUnit.expect(
|
|
tests.compare.length +
|
|
tests.splitAndTrimArray.length +
|
|
tests.arrayUnionWithoutEmpty.length +
|
|
Object.keys( tests.props ).length
|
|
);
|
|
|
|
// Compare
|
|
for ( i = 0; i < tests.compare.length; i++ ) {
|
|
testVars = tests.compare[ i ];
|
|
assert.equal(
|
|
mw.TemplateData.Model.static.compare( testVars.obj1, testVars.obj2, testVars.allowSubset ),
|
|
testVars.result,
|
|
testVars.msg
|
|
);
|
|
}
|
|
|
|
// Split and trim
|
|
for ( i = 0; i < tests.splitAndTrimArray.length; i++ ) {
|
|
testVars = tests.splitAndTrimArray[ i ];
|
|
assert.deepEqual(
|
|
mw.TemplateData.Model.static.splitAndTrimArray( testVars.string, testVars.delim ),
|
|
testVars.result,
|
|
testVars.msg
|
|
);
|
|
}
|
|
|
|
// arrayUnionWithoutEmpty
|
|
for ( i = 0; i < tests.arrayUnionWithoutEmpty.length; i++ ) {
|
|
testVars = tests.arrayUnionWithoutEmpty[ i ];
|
|
assert.deepEqual(
|
|
mw.TemplateData.Model.static.arrayUnionWithoutEmpty.apply( testVars, testVars.arrays ),
|
|
testVars.result,
|
|
testVars.msg
|
|
);
|
|
}
|
|
|
|
// Props
|
|
assert.deepEqual(
|
|
mw.TemplateData.Model.static.getAllProperties( false ),
|
|
tests.props.all,
|
|
'All properties'
|
|
);
|
|
assert.deepEqual(
|
|
mw.TemplateData.Model.static.getPropertiesWithLanguage(),
|
|
tests.props.language,
|
|
'Language properties'
|
|
);
|
|
} );
|
|
|
|
// Test model load
|
|
QUnit.asyncTest( 'TemplateData model', function ( assert ) {
|
|
var i,
|
|
sourceHandler = new mw.TemplateData.SourceHandler(),
|
|
paramAddTest = [
|
|
{
|
|
key: 'newParam1',
|
|
data: { required: true },
|
|
result: { name: 'newParam1', required: true },
|
|
description: '',
|
|
msg: 'Adding a simple parameter.'
|
|
},
|
|
{
|
|
key: 'newParam2',
|
|
data: null,
|
|
result: { name: 'newParam2' },
|
|
description: '',
|
|
msg: 'Adding new parameter without data.'
|
|
},
|
|
{
|
|
key: 'newParam3',
|
|
data: { description: 'Some string here in ' + currLanguage + ' language.' },
|
|
result: { name: 'newParam3', description: resultDescCurrLang },
|
|
description: 'Some string here in ' + currLanguage + ' language.',
|
|
msg: 'Adding parameter with language prop: original without language.'
|
|
},
|
|
{
|
|
key: 'newParam4',
|
|
data: {
|
|
description: resultDescBothLang
|
|
},
|
|
result: { name: 'newParam4', description: resultDescBothLang },
|
|
description: 'Some string here in ' + currLanguage + ' language.',
|
|
msg: 'Adding parameter with language prop: original with multiple languages.'
|
|
}
|
|
],
|
|
paramChangeTest = [
|
|
{
|
|
key: 'newParam1',
|
|
property: 'description',
|
|
language: 'en',
|
|
value: resultDescCurrLang[ currLanguage ],
|
|
result: $.extend( {}, paramAddTest[ 0 ].result, {
|
|
description: resultDescCurrLang
|
|
} ),
|
|
msg: 'Adding description in current language.'
|
|
},
|
|
{
|
|
key: 'newParam1',
|
|
property: 'description',
|
|
language: 'blah',
|
|
value: resultDescMockLang.blah,
|
|
result: $.extend( {}, paramAddTest[ 0 ].result, {
|
|
description: $.extend( {}, resultDescCurrLang, resultDescMockLang )
|
|
} ),
|
|
msg: 'Adding description in mock language.'
|
|
},
|
|
{
|
|
key: 'comment',
|
|
property: 'type',
|
|
value: 'wiki-page-name',
|
|
result: {
|
|
name: 'comment',
|
|
type: 'wiki-page-name',
|
|
required: false
|
|
},
|
|
msg: 'Adding type to comment.'
|
|
},
|
|
{
|
|
key: 'newParam2',
|
|
property: 'description',
|
|
language: 'blah',
|
|
value: '',
|
|
result: $.extend( {}, paramAddTest[ 1 ].result, {
|
|
description: { blah: '' }
|
|
} ),
|
|
msg: 'Adding empty description in mock language.'
|
|
},
|
|
{
|
|
key: 'newParam3',
|
|
property: 'deprecated',
|
|
value: true,
|
|
result: $.extend( {}, paramAddTest[ 2 ].result, {
|
|
deprecated: true
|
|
} ),
|
|
msg: 'Adding deprecated property (boolean).'
|
|
},
|
|
{
|
|
key: 'newParam3',
|
|
property: 'deprecatedValue',
|
|
value: 'This is deprecated.',
|
|
result: $.extend( {}, paramAddTest[ 2 ].result, {
|
|
deprecated: true,
|
|
deprecatedValue: 'This is deprecated.'
|
|
} ),
|
|
msg: 'Adding deprecated property (string).'
|
|
}
|
|
];
|
|
|
|
QUnit.expect(
|
|
// Description and parameter list
|
|
3 +
|
|
// Add parameter tests
|
|
2 * paramAddTest.length +
|
|
// Change properties tests
|
|
paramChangeTest.length +
|
|
// Json output
|
|
3
|
|
);
|
|
|
|
sourceHandler.buildModel( originalWikitext )
|
|
.done( function ( model ) {
|
|
|
|
// Check description
|
|
assert.equal(
|
|
model.getTemplateDescription(),
|
|
'Label unsigned comments in a conversation.',
|
|
'Description in default language.'
|
|
);
|
|
assert.equal(
|
|
model.getTemplateDescription( 'blah' ),
|
|
'Template description in some blah language.',
|
|
'Description in mock language.'
|
|
);
|
|
|
|
// Check parameters
|
|
assert.deepEqual(
|
|
Object.keys( model.getParams() ),
|
|
[ 'user', 'date', 'year', 'month', 'day', 'comment' ],
|
|
'Parameters retention.'
|
|
);
|
|
|
|
for ( i = 0; i < paramAddTest.length; i++ ) {
|
|
// Add parameter
|
|
model.addParam( paramAddTest[ i ].key, paramAddTest[ i ].data );
|
|
|
|
// Test new param data
|
|
assert.deepEqual(
|
|
model.getParamData( paramAddTest[ i ].key ),
|
|
paramAddTest[ i ].result,
|
|
paramAddTest[ i ].msg + ' (parameter data)'
|
|
);
|
|
|
|
// Check description in current language
|
|
assert.equal(
|
|
model.getParamValue( paramAddTest[ i ].key, 'description', currLanguage ),
|
|
paramAddTest[ i ].description,
|
|
paramAddTest[ i ].msg + ' (description in current language)'
|
|
);
|
|
}
|
|
|
|
// Change parameter properties
|
|
for ( i = 0; i < paramChangeTest.length; i++ ) {
|
|
testVars = paramChangeTest[ i ];
|
|
model.setParamProperty( testVars.key, testVars.property, testVars.value, testVars.language );
|
|
assert.deepEqual(
|
|
model.getParamData( testVars.key ),
|
|
paramChangeTest[ i ].result,
|
|
paramChangeTest[ i ].msg
|
|
);
|
|
}
|
|
|
|
// Delete parameter
|
|
model.deleteParam( 'day' );
|
|
|
|
// Ouput a final templatedata string
|
|
assert.equal(
|
|
model.outputTemplateDataString(),
|
|
finalJsonStringOnly,
|
|
'Final templatedata output'
|
|
);
|
|
|
|
// Move 'user' to offset 3 (in original array), i.e. after 'year'
|
|
model.reorderParamOrderKey( 'user', 3 );
|
|
assert.deepEqual(
|
|
model.paramOrder,
|
|
[ 'date', 'year', 'user', 'month', 'comment', 'newParam1', 'newParam2', 'newParam3', 'newParam4' ],
|
|
'Final templatedata output with paramOrder'
|
|
);
|
|
|
|
// Move 'month' to offset 2, i.e. after 'year'
|
|
model.reorderParamOrderKey( 'month', 2 );
|
|
assert.deepEqual(
|
|
model.paramOrder,
|
|
[ 'date', 'year', 'month', 'user', 'comment', 'newParam1', 'newParam2', 'newParam3', 'newParam4' ],
|
|
'Final templatedata output with paramOrder'
|
|
);
|
|
|
|
} )
|
|
.always( function () {
|
|
QUnit.start();
|
|
} );
|
|
} );
|
|
|
|
// Test model fail
|
|
QUnit.asyncTest( 'TemplateData sourceHandler', function ( assert ) {
|
|
var sourceHandler = new mw.TemplateData.SourceHandler(),
|
|
erronousString = '<templatedata>{\n' +
|
|
' "params": {\n' +
|
|
// Open quote
|
|
' "user: {\n' +
|
|
' "label": "Username",\n' +
|
|
' "type": "wiki-user-name",\n' +
|
|
' "required": true,\n' +
|
|
' "description": "User name of person who forgot to sign their comment.",\n' +
|
|
' "aliases": [\n' +
|
|
' "1"\n' +
|
|
' ]\n' +
|
|
' },\n' +
|
|
' "date": {\n' +
|
|
' "label": "Date",\n' +
|
|
' "description": {\n' +
|
|
// Forgotten quotes
|
|
' en: "Timestamp of when the comment was posted, in YYYY-MM-DD format."\n' +
|
|
' }\n' +
|
|
' "suggested": true\n' +
|
|
' }\n' +
|
|
' }\n' +
|
|
'}</templatedata>';
|
|
|
|
QUnit.expect( 1 );
|
|
|
|
sourceHandler.buildModel( erronousString )
|
|
.always( function () {
|
|
assert.ok( this.state() === 'rejected', 'Promise rejected on erronous json string.' );
|
|
QUnit.start();
|
|
} );
|
|
} );
|
|
|
|
// Test model gets default format
|
|
QUnit.asyncTest( 'TemplateData sourceHandler adding default format', function ( assert ) {
|
|
var sourceHandler = new mw.TemplateData.SourceHandler(),
|
|
simpleTemplateDataNoFormat = '<templatedata>{\n' +
|
|
' "params": {}\n' +
|
|
'}</templatedata>',
|
|
simpleTemplateDataDefaultFormat = '{\n' +
|
|
' "params": {},\n' +
|
|
' "format": "inline"\n' + // default format
|
|
'}';
|
|
|
|
QUnit.expect( 1 );
|
|
|
|
sourceHandler.buildModel( simpleTemplateDataNoFormat )
|
|
.done( function ( model ) {
|
|
assert.equal(
|
|
model.outputTemplateDataString(),
|
|
simpleTemplateDataDefaultFormat,
|
|
'Final templatedata output'
|
|
);
|
|
} )
|
|
.always( function () {
|
|
QUnit.start();
|
|
} );
|
|
} );
|
|
|
|
}() );
|