mediawiki-extensions-Visual.../modules/ve-mw/tests/dm/models/ve.dm.MWTemplateSpecModel.test.js
Thiemo Kreuz b8382513fc Use separate data structure to store aliases in spec
Wait, what's going on here? This patch looks like it changes the
behavior of this code. But it doesn't. Here is what happened
before:
* Let's say a template contains 2 parameters, A and B.
* We don't know yet if these names are aliases.
* getParameterNames() returns [ "A", "B" ].
* extend() is called. The TemplateData documentation contains
  the parameters "B" and "C". "C" does have an alias "A".
* extend() can't find "C" and adds it to the end, as if it's a
  new parameter.
* extend() also iterates the aliases. For each alias it creates
  a reference to the specification object. In this case a
  reference from "A" to "C" is created.
* But "A" already exists. The position of "A" doesn't change,
  but the specification now says it's an alias.
* getParameterNames() skips aliases. It skips "A" and instead
  returns the new "C" from the end of the list.

This was the behavior before. It's unchanged, proven by the tests.

Change-Id: I04b8a14fbec7be5a1c4defabf92e94f694c1e638
2021-06-25 08:29:48 +02:00

223 lines
12 KiB
JavaScript

( function () {
QUnit.module( 've.dm.MWTemplateSpecModel', ve.test.utils.mwEnvironment );
/**
* @param {string[]} [parameterNames]
* @return {ve.dm.MWTemplateModel} but it's a mock
*/
function createTemplateMock( parameterNames ) {
const x = {};
( parameterNames || [] ).forEach( ( name ) => {
x[ name ] = {};
} );
return {
params: x,
getTitle: () => null,
getTarget: () => {
return { wt: 'RawTemplateName' };
},
getParameters: function () {
return this.params;
}
};
}
QUnit.test( 'Basic behavior on empty template', ( assert ) => {
const template = createTemplateMock(),
spec = new ve.dm.MWTemplateSpecModel( template );
assert.strictEqual( spec.getLabel(), 'RawTemplateName', 'getLabel' );
assert.strictEqual( spec.getDescription(), null, 'getDescription' );
assert.deepEqual( spec.getCanonicalParameterOrder(), [], 'getCanonicalParameterOrder' );
assert.strictEqual( spec.isKnownParameterOrAlias( 'unknown' ), false, 'isKnownParameterOrAlias' );
assert.strictEqual( spec.isParameterAlias( 'unknown' ), false, 'isParameterAlias' );
assert.strictEqual( spec.getParameterDefaultValue( 'unknown' ), '', 'getParameterDefaultValue' );
assert.strictEqual( spec.getParameterAutoValue( 'unknown' ), '', 'getParameterAutoValue' );
assert.strictEqual( spec.getPrimaryParameterName( 'unknown' ), 'unknown', 'getPrimaryParameterName' );
assert.deepEqual( spec.getParameterNames(), [], 'getParameterNames' );
assert.deepEqual( spec.getParameterSets(), [], 'getParameterSets' );
assert.deepEqual( spec.getMaps(), {}, 'getMaps' );
} );
QUnit.test( 'Basic behavior on non-empty template', ( assert ) => {
const template = createTemplateMock( [ 'p1', 'p2' ] ),
spec = new ve.dm.MWTemplateSpecModel( template );
assert.strictEqual( spec.getLabel(), 'RawTemplateName', 'getLabel' );
assert.strictEqual( spec.getDescription(), null, 'getDescription' );
assert.deepEqual( spec.getCanonicalParameterOrder(), [], 'getCanonicalParameterOrder' );
assert.strictEqual( spec.isKnownParameterOrAlias( 'p2' ), true, 'isKnownParameterOrAlias' );
assert.strictEqual( spec.isParameterAlias( 'p2' ), false, 'isParameterAlias' );
assert.strictEqual( spec.getParameterLabel( 'p2' ), 'p2', 'getParameterLabel' );
assert.strictEqual( spec.getParameterDescription( 'p2' ), null, 'getParameterDescription' );
assert.deepEqual( spec.getParameterSuggestedValues( 'p2' ), [], 'getParameterSuggestedValues' );
assert.strictEqual( spec.getParameterDefaultValue( 'p2' ), '', 'getParameterDefaultValue' );
assert.strictEqual( spec.getParameterExampleValue( 'p2' ), null, 'getParameterExampleValue' );
assert.strictEqual( spec.getParameterAutoValue( 'p2' ), '', 'getParameterAutoValue' );
assert.strictEqual( spec.getParameterType( 'p2' ), 'string', 'getParameterType' );
assert.deepEqual( spec.getParameterAliases( 'p2' ), [], 'getParameterAliases' );
assert.strictEqual( spec.getPrimaryParameterName( 'p2' ), 'p2', 'getPrimaryParameterName' );
assert.strictEqual( spec.isParameterRequired( 'p2' ), false, 'isParameterRequired' );
assert.strictEqual( spec.isParameterSuggested( 'p2' ), false, 'isParameterSuggested' );
assert.strictEqual( spec.isParameterDeprecated( 'p2' ), false, 'isParameterDeprecated' );
assert.strictEqual( spec.getParameterDeprecationDescription( 'p2' ), '', 'getParameterDeprecationDescription' );
assert.deepEqual( spec.getParameterNames(), [ 'p1', 'p2' ], 'getParameterNames' );
assert.deepEqual( spec.getParameterSets(), [], 'getParameterSets' );
assert.deepEqual( spec.getMaps(), {}, 'getMaps' );
} );
QUnit.test( 'Basic behavior with later fillFromTemplate()', ( assert ) => {
const template = createTemplateMock( [ 'p1' ] ),
spec = new ve.dm.MWTemplateSpecModel( template );
template.params.p2 = {};
spec.fillFromTemplate();
assert.strictEqual( spec.getLabel(), 'RawTemplateName', 'getLabel' );
assert.strictEqual( spec.getDescription(), null, 'getDescription' );
assert.deepEqual( spec.getCanonicalParameterOrder(), [], 'getCanonicalParameterOrder' );
assert.strictEqual( spec.isKnownParameterOrAlias( 'p2' ), true, 'isKnownParameterOrAlias' );
assert.strictEqual( spec.isParameterAlias( 'p2' ), false, 'isParameterAlias' );
assert.strictEqual( spec.getParameterLabel( 'p2' ), 'p2', 'getParameterLabel' );
assert.strictEqual( spec.getParameterDescription( 'p2' ), null, 'getParameterDescription' );
assert.deepEqual( spec.getParameterSuggestedValues( 'p2' ), [], 'getParameterSuggestedValues' );
assert.strictEqual( spec.getParameterDefaultValue( 'p2' ), '', 'getParameterDefaultValue' );
assert.strictEqual( spec.getParameterExampleValue( 'p2' ), null, 'getParameterExampleValue' );
assert.strictEqual( spec.getParameterAutoValue( 'p2' ), '', 'getParameterAutoValue' );
assert.strictEqual( spec.getParameterType( 'p2' ), 'string', 'getParameterType' );
assert.deepEqual( spec.getParameterAliases( 'p2' ), [], 'getParameterAliases' );
assert.strictEqual( spec.getPrimaryParameterName( 'p2' ), 'p2', 'getPrimaryParameterName' );
assert.strictEqual( spec.isParameterRequired( 'p2' ), false, 'isParameterRequired' );
assert.strictEqual( spec.isParameterSuggested( 'p2' ), false, 'isParameterSuggested' );
assert.strictEqual( spec.isParameterDeprecated( 'p2' ), false, 'isParameterDeprecated' );
assert.strictEqual( spec.getParameterDeprecationDescription( 'p2' ), '', 'getParameterDeprecationDescription' );
assert.deepEqual( spec.getParameterNames(), [ 'p1', 'p2' ], 'getParameterNames' );
assert.deepEqual( spec.getParameterSets(), [], 'getParameterSets' );
assert.deepEqual( spec.getMaps(), {}, 'getMaps' );
} );
QUnit.test( 'Basic behavior with most minimal extend()', ( assert ) => {
const template = createTemplateMock( [ 'p1' ] ),
spec = new ve.dm.MWTemplateSpecModel( template );
spec.extend( { params: { p2: {} } } );
assert.strictEqual( spec.getLabel(), 'RawTemplateName', 'getLabel' );
assert.strictEqual( spec.getDescription(), null, 'getDescription' );
assert.deepEqual( spec.getCanonicalParameterOrder(), [ 'p2' ], 'getCanonicalParameterOrder' );
assert.strictEqual( spec.isKnownParameterOrAlias( 'p2' ), true, 'isKnownParameterOrAlias' );
assert.strictEqual( spec.isParameterAlias( 'p2' ), false, 'isParameterAlias' );
assert.strictEqual( spec.getParameterLabel( 'p2' ), 'p2', 'getParameterLabel' );
assert.strictEqual( spec.getParameterDescription( 'p2' ), null, 'getParameterDescription' );
assert.deepEqual( spec.getParameterSuggestedValues( 'p2' ), [], 'getParameterSuggestedValues' );
assert.strictEqual( spec.getParameterDefaultValue( 'p2' ), '', 'getParameterDefaultValue' );
assert.strictEqual( spec.getParameterExampleValue( 'p2' ), null, 'getParameterExampleValue' );
assert.strictEqual( spec.getParameterAutoValue( 'p2' ), '', 'getParameterAutoValue' );
assert.strictEqual( spec.getParameterType( 'p2' ), 'string', 'getParameterType' );
assert.deepEqual( spec.getParameterAliases( 'p2' ), [], 'getParameterAliases' );
assert.strictEqual( spec.getPrimaryParameterName( 'p2' ), 'p2', 'getPrimaryParameterName' );
assert.strictEqual( spec.isParameterRequired( 'p2' ), false, 'isParameterRequired' );
assert.strictEqual( spec.isParameterSuggested( 'p2' ), false, 'isParameterSuggested' );
assert.strictEqual( spec.isParameterDeprecated( 'p2' ), false, 'isParameterDeprecated' );
assert.strictEqual( spec.getParameterDeprecationDescription( 'p2' ), '', 'getParameterDeprecationDescription' );
assert.deepEqual( spec.getParameterNames(), [ 'p1', 'p2' ], 'getParameterNames' );
assert.deepEqual( spec.getParameterSets(), [], 'getParameterSets' );
assert.deepEqual( spec.getMaps(), {}, 'getMaps' );
} );
QUnit.test( 'Complex extend() with alias', ( assert ) => {
const template = createTemplateMock(),
spec = new ve.dm.MWTemplateSpecModel( template );
spec.extend( {
description: 'TemplateDescription',
params: {
p: {
label: 'ParamLabel',
description: 'ParamDescription',
suggestedvalues: [ 'SuggestedValue' ],
default: 'ParamDefault',
example: 'ParamExample',
autovalue: 'ParamAutoValue',
type: 'DummyType',
aliases: [ 'a' ],
required: true,
suggested: true,
deprecated: 'DeprecationText'
}
},
paramOrder: [ 'DummyOrder' ],
sets: [ 'DummySet' ],
maps: { dummyMap: true }
} );
assert.strictEqual( spec.getLabel(), 'RawTemplateName', 'getLabel' );
assert.strictEqual( spec.getDescription(), 'TemplateDescription', 'getDescription' );
assert.deepEqual( spec.getCanonicalParameterOrder(), [ 'DummyOrder' ], 'getCanonicalParameterOrder' );
assert.strictEqual( spec.isKnownParameterOrAlias( 'a' ), true, 'isKnownParameterOrAlias' );
assert.strictEqual( spec.isParameterAlias( 'a' ), true, 'isParameterAlias' );
assert.strictEqual( spec.getParameterLabel( 'a' ), 'ParamLabel', 'getParameterLabel' );
assert.strictEqual( spec.getParameterDescription( 'a' ), 'ParamDescription', 'getParameterDescription' );
assert.deepEqual( spec.getParameterSuggestedValues( 'a' ), [ 'SuggestedValue' ], 'getParameterSuggestedValues' );
assert.strictEqual( spec.getParameterDefaultValue( 'a' ), 'ParamDefault', 'getParameterDefaultValue' );
assert.strictEqual( spec.getParameterExampleValue( 'a' ), 'ParamExample', 'getParameterExampleValue' );
assert.strictEqual( spec.getParameterAutoValue( 'a' ), 'ParamAutoValue', 'getParameterAutoValue' );
assert.strictEqual( spec.getParameterType( 'a' ), 'DummyType', 'getParameterType' );
assert.deepEqual( spec.getParameterAliases( 'a' ), [ 'a' ], 'getParameterAliases' );
assert.strictEqual( spec.getPrimaryParameterName( 'a' ), 'p', 'getPrimaryParameterName' );
assert.strictEqual( spec.isParameterRequired( 'a' ), true, 'isParameterRequired' );
assert.strictEqual( spec.isParameterSuggested( 'a' ), true, 'isParameterSuggested' );
assert.strictEqual( spec.isParameterDeprecated( 'a' ), true, 'isParameterDeprecated' );
assert.strictEqual( spec.getParameterDeprecationDescription( 'a' ), 'DeprecationText', 'getParameterDeprecationDescription' );
assert.deepEqual( spec.getParameterNames(), [ 'p' ], 'getParameterNames' );
assert.deepEqual( spec.getParameterSets(), [ 'DummySet' ], 'getParameterSets' );
assert.deepEqual( spec.getMaps(), { dummyMap: true }, 'getMaps' );
} );
QUnit.test( 'Template uses aliases', ( assert ) => {
const template = createTemplateMock( [ 'p1-alias', 'p2' ] ),
spec = new ve.dm.MWTemplateSpecModel( template );
assert.strictEqual( spec.isParameterAlias( 'p1-alias' ), false );
assert.strictEqual( spec.getParameterLabel( 'p1-alias' ), 'p1-alias' );
assert.deepEqual( spec.getParameterNames(), [ 'p1-alias', 'p2' ] );
spec.extend( { params: { p1: { aliases: [ 'p1-alias' ] } } } );
assert.strictEqual( spec.isParameterAlias( 'p1-alias' ), true );
assert.strictEqual( spec.getParameterLabel( 'p1-alias' ), 'p1-alias' );
assert.deepEqual( spec.getParameterNames(), [ 'p2', 'p1' ] );
} );
QUnit.test( 'Alias conflicts with another parameter', ( assert ) => {
const template = createTemplateMock(),
spec = new ve.dm.MWTemplateSpecModel( template );
spec.extend( { params: {
p1: {
label: 'Parameter one'
},
p2: {
label: 'Parameter two',
// Note: This is impossible in real-world scenarios, but better be safe than sorry
aliases: [ 'p1' ]
}
} } );
assert.strictEqual( spec.getParameterLabel( 'p1' ), 'Parameter two' );
assert.strictEqual( spec.getParameterLabel( 'p2' ), 'Parameter two' );
} );
QUnit.test( 'Parameter deprecation with empty string', ( assert ) => {
const template = createTemplateMock(),
spec = new ve.dm.MWTemplateSpecModel( template );
spec.extend( { params: { p: { deprecated: '' } } } );
assert.strictEqual( spec.isParameterDeprecated( 'p' ), true );
assert.strictEqual( spec.getParameterDeprecationDescription( 'p' ), '' );
} );
}() );