Henning Snater has uploaded a new change for review. https://gerrit.wikimedia.org/r/177517
Change subject: Added type checks to wikibase.api.RepoApi functions ...................................................................... Added type checks to wikibase.api.RepoApi functions Actually reflecting parameter documentation in the code instead of relying on the back-end handling. This resolves some wrong documentation as well. Added tests testing the minimum of parameters required by each function. Change-Id: I4d043f5cc43852970a489014bc5c106592ccfdc3 --- A .jshintignore M README.md M src/RepoApi.js M tests/RepoApi.tests.js 4 files changed, 445 insertions(+), 94 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseJavaScriptApi refs/changes/17/177517/1 diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..711939d --- /dev/null +++ b/.jshintignore @@ -0,0 +1 @@ +./tests \ No newline at end of file diff --git a/README.md b/README.md index f2f54c4..0069924 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,11 @@ * Updated code documentation to be able to generate documentation using JSDuck. * `wikibase.api.RepoApi` QUnit tests have been rewritten to not execute actual API requests anymore. * Added `wikibase.api.RepoApi` QUnit tests for functions not yet tested. +* Added type checks to `wikibase.api.RepoApi` functions to actually reflect parameter documentation in the code instead of relying on the back-end handling. ### Bugfixes * An empty `Entity` may be created by omitting the `data` parameter on `wikibase.api.RepoApi.createEntity()` again. -* `wikibase.api.RepoApi` always submits `normalize` parameter if it is specified explicitly (before, `false` resolved to `undefined`). +* `wikibase.api.RepoApi` functions explicitly submit default parameters if not set otherwise. ### 1.0.1 (2014-11-28) diff --git a/src/RepoApi.js b/src/RepoApi.js index 6306dce..7d1f97b 100644 --- a/src/RepoApi.js +++ b/src/RepoApi.js @@ -53,8 +53,14 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ createEntity: function( type, data ) { + if( typeof type !== 'string' || data && typeof data !== 'object' ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbeditentity', 'new': type, @@ -67,10 +73,10 @@ * Edits an `Entity`. * @see wikibase.api.RepoApi._post * - * @param {String} id `Entity` id. - * @param {Number} baseRevId Revision id the edit shall be performed on. - * @param {Object} data The `Entity`'s structure. - * @param {Boolean} [clear=false] Whether to clear whole entity before editing. + * @param {string} id `Entity` id. + * @param {number} baseRevId Revision id the edit shall be performed on. + * @param {Object} [data] The `Entity`'s structure. + * @param {boolean} [clear] Whether to clear whole entity before editing. * @return {Object} jQuery.Promise * @return {Function} return.done * @return {*} return.done.result @@ -78,17 +84,28 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ editEntity: function( id, baseRevId, data, clear ) { + if( + typeof id !== 'string' + || typeof baseRevId !== 'number' + || typeof data !== 'object' + || data && typeof data !== 'object' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbeditentity', id: id, baserevid: baseRevId, - data: JSON.stringify( data ) + data: JSON.stringify( data || {} ) }; - if ( clear ) { - params.clear = true; + if( typeof clear === 'boolean' ) { + params.clear = clear; } return this._post( params ); @@ -109,8 +126,19 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ formatValue: function( dataValue, options, dataType, outputFormat ) { + if( + typeof dataValue !== 'object' + || options && typeof options !== 'object' + || dataType && typeof dataType !== 'string' + || outputFormat && typeof outputFormat !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbformatvalue', datavalue: JSON.stringify( dataValue ), @@ -139,8 +167,8 @@ * property/ies values should be retrieved in. `null` returns values in all languages. * @param {string|string[]|null} [sort=null] Key(s) of property/ies to sort on. `null` will * result in unsorted output. - * @param {string|null} [dir=null] Sort direction, may be 'ascending' or 'descending'. - * `null` resolves to 'ascending'. + * @param {string|null} [dir] Sort direction, may be 'ascending' or 'descending'. + * Anything but 'descending' resolves to 'ascending'. * @return {Object} jQuery.Promise * @return {Function} return.done * @return {*} return.done.result @@ -148,15 +176,27 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ getEntities: function( ids, props, languages, sort, dir ) { + if( + ( typeof ids !== 'string' && !$.isArray( ids ) ) + || props && ( typeof props !== 'string' && !$.isArray( props ) ) + || languages && ( typeof languages !== 'string' && !$.isArray( languages ) ) + || sort && ( typeof sort !== 'string' && !$.isArray( sort ) ) + || dir && typeof dir !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbgetentities', ids: this._normalizeParam( ids ), props: this._normalizeParam( props ), languages: this._normalizeParam( languages ), sort: this._normalizeParam( sort ), - dir: dir || undefined + dir: dir === 'descending' ? 'descending' : 'ascending' }; return this._api.get( params ); @@ -176,8 +216,8 @@ * property/ies values should be retrieved in. `null` returns values in all languages. * @param {string|string[]|null} [sort=null] Key(s) of property/ies to sort on. `null` will * result in unsorted output. - * @param {string|null} [dir=null] Sort direction, may be 'ascending' or 'descending'. - * `null` resolves to 'ascending'. + * @param {string|null} [dir] Sort direction, may be 'ascending' or 'descending'. + * Anything but 'descending' resolves to 'ascending'. * @param {boolean} [normalize] Whether to normalize titles server side * @return {Object} jQuery.Promise * @return {Function} return.done @@ -186,8 +226,25 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. + * @throws {Error} if both, `sites` and `titles`, are passed as `array`s. */ getEntitiesByPage: function( sites, titles, props, languages, sort, dir, normalize ) { + if( + ( typeof sites !== 'string' && !$.isArray( sites ) ) + || ( typeof titles !== 'string' && !$.isArray( titles ) ) + || props && ( typeof props !== 'string' && !$.isArray( props ) ) + || languages && ( typeof languages !== 'string' && !$.isArray( languages ) ) + || sort && ( typeof sort !== 'string' && !$.isArray( sort ) ) + ) { + throw new Error( 'Parameter not specified properly' ); + } + + if( $.isArray( sites ) && $.isArray( titles ) ) { + throw new Error( 'sites and titles may not be passed as arrays at the same time' ); + } + var params = { action: 'wbgetentities', sites: this._normalizeParam( sites ), @@ -195,7 +252,7 @@ props: this._normalizeParam( props ), languages: this._normalizeParam( languages ), sort: this._normalizeParam( sort ), - dir: dir || undefined, + dir: dir === 'descending' ? 'descending' : 'ascending', normalize: typeof normalize === 'boolean' ? normalize : undefined }; @@ -216,8 +273,18 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ parseValue: function( parser, values, options ) { + if( + typeof parser !== 'string' + || !$.isArray( values ) + || options && typeof options !== 'object' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbparsevalue', parser: parser, @@ -234,8 +301,8 @@ * @param {string} search Text to search for. * @param {string} language Language code of the language to search in. * @param {string} type `Entity` type to search for. - * @param {number} limit Maximum number of results to return. - * @param {number} offset Offset where to continue returning the search results. + * @param {number} [limit] Maximum number of results to return. + * @param {number} [offset] Offset where to continue returning the search results. * @return {Object} jQuery.Promise * @return {Function} return.done * @return {*} return.done.result @@ -243,15 +310,25 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ searchEntities: function( search, language, type, limit, offset ) { + if( + typeof search !== 'string' + || typeof language !== 'string' + || typeof type !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsearchentities', search: search, language: language, type: type, - limit: limit || undefined, - 'continue': offset || undefined + limit: typeof limit === 'number' ? limit : undefined, + 'continue': typeof offset === 'number' ? offset : undefined }; return this._api.get( params ); @@ -272,8 +349,19 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setLabel: function( id, baseRevId, label, language ) { + if( + typeof id !== 'string' + || typeof baseRevId !== 'number' + || typeof label !== 'string' + || typeof language !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetlabel', id: id, @@ -281,6 +369,7 @@ language: language, baserevid: baseRevId }; + return this._post( params ); }, @@ -299,8 +388,19 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setDescription: function( id, baseRevId, description, language ) { + if( + typeof id !== 'string' + || typeof baseRevId !== 'number' + || typeof description !== 'string' + || typeof language !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetdescription', id: id, @@ -308,6 +408,7 @@ language: language, baserevid: baseRevId }; + return this._post( params ); }, @@ -328,18 +429,29 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setAliases: function( id, baseRevId, add, remove, language ) { - add = this._normalizeParam( add ); - remove = this._normalizeParam( remove ); + if( + typeof id !== 'string' + || typeof baseRevId !== 'number' + || !$.isArray( add ) + || !$.isArray( remove ) + || typeof language !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetaliases', id: id, - add: add, - remove: remove, + add: this._normalizeParam( add ), + remove: this._normalizeParam( remove ), language: language, baserevid: baseRevId }; + return this._post( params ); }, @@ -358,15 +470,21 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setClaim: function( claim, baseRevId, index ) { + if( typeof claim !== 'object' || typeof baseRevId !== 'number' ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetclaim', claim: JSON.stringify( claim ), baserevid: baseRevId }; - if( index !== undefined ) { + if( typeof index === 'number' ) { params.index = index; } @@ -380,7 +498,7 @@ * @param {string} entityId `Entity` id. * @param {number} baseRevId Revision id the edit shall be performed on. * @param {string} snakType The type of the `Snak` (see `wikibase.datamodel.Snak.TYPE`). - * @param {string} property Id of the `Snak`'s `Property`. + * @param {string} propertyId Id of the `Snak`'s `Property`. * @param {Object|string} [value] `DataValue` serialization that needs to be provided when the * specified `Snak` type requires a value. * @return {Object} jQuery.Promise @@ -390,17 +508,29 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ - createClaim: function( entityId, baseRevId, snakType, property, value ) { + createClaim: function( entityId, baseRevId, snakType, propertyId, value ) { + if( + typeof entityId !== 'string' + || typeof baseRevId !== 'number' + || typeof snakType !== 'string' + || typeof propertyId !== 'string' + || value && typeof value !== 'string' && typeof value !== 'object' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbcreateclaim', entity: entityId, baserevid: baseRevId, snaktype: snakType, - property: property + property: propertyId }; - if ( value ) { + if( value ) { params.value = JSON.stringify( value ); } @@ -420,13 +550,27 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ removeClaim: function( claimGuid, claimRevisionId ) { - return this._post( { + if( + typeof claimGuid !== 'string' + || claimRevisionId && typeof claimRevisionId !== 'number' + ) { + throw new Error( 'Parameter not specified properly' ); + } + + var params = { action: 'wbremoveclaims', - claim: claimGuid, - baserevid: claimRevisionId - } ); + claim: claimGuid + }; + + if( claimRevisionId ) { + params.baserevid = claimRevisionId; + } + + return this._post( params ); }, /** @@ -434,7 +578,7 @@ * providing a `Claim` GUID. * @see wikibase.api.RepoApi._post * - * @param {string|null} entityId `Entity` id. + * @param {string|null} entityId `Entity` id. May be `null` if `claimGuid` is specified. * @param {string} [propertyId] Only return `Claim`s featuring this `Property`. * @param {string} [claimGuid] GUID of the `Claim` to return. Either `claimGuid` or `entityID` * has to be provided. @@ -447,8 +591,25 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. + * @throws {Error} if neither `entityId` nor `claimGuid` is provided. */ getClaims: function( entityId, propertyId, claimGuid, rank, props ) { + if( + entityId && typeof entityId !== 'string' + || propertyId && typeof propertyId !== 'string' + || claimGuid && typeof claimGuid !== 'string' + || rank && typeof rank !== 'string' + || props && typeof props !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + + if( !entityId && !claimGuid ) { + throw new Error( 'Either entity id or claim GUID needs to be provided.' ); + } + var params = { action: 'wbgetclaims', entity: entityId, @@ -468,7 +629,7 @@ * @param {string} claimGuid The GUID of the `Claim` to be changed. * @param {number} baseRevId Revision id the edit shall be performed on. * @param {string} snakType The type of the `Snak` (see `wikibase.datamodel.Snak.TYPE`). - * @param {string} property Id of the `Snak`'s `Property`. + * @param {string} propertyId Id of the `Snak`'s `Property`. * @param {Object|string} [value] `DataValue` serialization that needs to be provided when the * specified `Snak` type requires a value. * @return {Object} jQuery.Promise @@ -478,8 +639,20 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ - setClaimValue: function( claimGuid, baseRevId, snakType, property, value ) { + setClaimValue: function( claimGuid, baseRevId, snakType, propertyId, value ) { + if( + typeof claimGuid !== 'string' + || typeof baseRevId !== 'number' + || typeof snakType !== 'string' + || typeof propertyId !== 'string' + || value && typeof value !== 'string' && typeof value !== 'object' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetclaimvalue', claim: claimGuid, @@ -487,7 +660,7 @@ snaktype: snakType, // NOTE: currently 'wbsetclaimvalue' API allows to change snak type but not property, // set it anyhow. The abstracted API won't propagate the API warning we will get here. - property: property + property: propertyId }; if ( value ) { @@ -505,8 +678,9 @@ * should be added to or changed of. * @param {Object} snaks `snak` portion of a serialized `Reference`. * @param {number} baseRevId Revision id the edit shall be performed on. - * @param {string} [referenceHash] A hash of the reference that should be updated. + * @param {string|number} [referenceHash] A hash of the reference that should be updated. * If not provided, a new reference is created. + * Assumed to be `index` if of type `number`. * @param {number} [index] The `Reference` index. Only needs to be specified if the * `Reference`'s index within the list of all `Reference`s of the parent `Statement` * shall be changed or when the `Reference` should be inserted at a specific position. @@ -517,19 +691,31 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setReference: function( statementGuid, snaks, baseRevId, referenceHash, index ) { + if( index === undefined && typeof referenceHash === 'number' ) { + index = referenceHash; + referenceHash = undefined; + } + + if( + typeof statementGuid !== 'string' + || typeof snaks !== 'object' + || typeof baseRevId !== 'number' + || referenceHash && typeof referenceHash !== 'string' + || index && typeof index !== 'number' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetreference', statement: statementGuid, snaks: JSON.stringify( snaks ), baserevid: baseRevId }; - - if( index === undefined && typeof referenceHash === 'number' ) { - index = referenceHash; - referenceHash = undefined; - } if( referenceHash ) { params.reference = referenceHash; @@ -558,8 +744,18 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ removeReferences: function( statementGuid, referenceHashes, baseRevId ) { + if( + typeof statementGuid !== 'string' + || typeof referenceHashes !== 'string' && !$.isArray( referenceHashes ) + || typeof baseRevId !== 'number' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbremovereferences', statement: statementGuid, @@ -586,8 +782,20 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ setSitelink: function( id, baseRevId, site, title, badges ) { + if( + typeof id !== 'string' + || typeof baseRevId !== 'number' + || typeof site !== 'string' + || typeof title !== 'string' + || badges && typeof badges !== 'string' && !$.isArray( badges ) + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbsetsitelink', id: id, @@ -607,8 +815,8 @@ * Sets a site link for an item via the API. * @see wikibase.api.RepoApi._post * - * @param {string} [fromId] `Entity` id to merge from. - * @param {string} [toId] `Entity` id to merge to. + * @param {string} fromId `Entity` id to merge from. + * @param {string} toId `Entity` id to merge to. * @param {string[]|string} [ignoreConflicts] Elements of the `Item` to ignore conflicts for. * @param {string} [summary] Summary for the edit. * @return {Object} jQuery.Promise @@ -618,19 +826,32 @@ * @return {Function} return.fail * @return {string} return.fail.code * @return {*} return.fail.error + * + * @throws {Error} if a parameter is not specified properly. */ mergeItems: function( fromId, toId, ignoreConflicts, summary ) { + if( + typeof fromId !== 'string' + || typeof toId !== 'string' + || ignoreConflicts + && typeof ignoreConflicts !== 'string' + && !$.isArray( ignoreConflicts ) + || summary && typeof summary !== 'string' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbmergeitems', fromid: fromId, toid: toId }; - if ( ignoreConflicts ) { + if( ignoreConflicts ) { params.ignoreconflicts = this._normalizeParam( ignoreConflicts ); } - if ( summary ) { + if( summary ) { params.summary = summary; } diff --git a/tests/RepoApi.tests.js b/tests/RepoApi.tests.js index 6578d0f..cb0a196 100644 --- a/tests/RepoApi.tests.js +++ b/tests/RepoApi.tests.js @@ -55,9 +55,7 @@ var mock = mockApi(); mock.api.createEntity( 'item' ); - mock.api.createEntity( 'property', { - datatype: 'string' - } ); + mock.api.createEntity( 'property', { 'I am': 'data' } ); assert.ok( mock.spy.calledTwice, 'Triggered API calls.' ); @@ -81,25 +79,18 @@ assert.equal( getParam( mock.spy, 'data', 1 ), - JSON.stringify( { datatype: 'string' } ), - 'Verified submitting "datatype" field.' + JSON.stringify( { 'I am': 'data' } ), + 'Verified submitting "data" field.' ); } ); QUnit.test( 'editEntity()', function( assert ) { - var mock = mockApi(), - data = { - labels: { - de: { - language: 'de', - value: 'label' - } - } - }; + var mock = mockApi(); - mock.api.editEntity( 'entity id', 12345, data ); + mock.api.editEntity( 'entity id', 12345, { 'I am': 'entity data' }, true ); + mock.api.editEntity( 'entity id', 12345, {} ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -109,20 +100,27 @@ assert.equal( getParam( mock.spy, 'id' ), 'entity id' ); assert.equal( getParam( mock.spy, 'baserevid' ), 12345 ); - assert.equal( getParam( mock.spy, 'data' ), JSON.stringify( data ) ); + assert.equal( getParam( mock.spy, 'data' ), JSON.stringify( { 'I am': 'entity data' } ) ); + assert.equal( getParam( mock.spy, 'clear' ), true ); + + assert.equal( getParam( mock.spy, 'id', 1 ), 'entity id' ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.equal( getParam( mock.spy, 'data', 1 ), JSON.stringify( {} ) ); + assert.strictEqual( getParam( mock.spy, 'clear', 1 ), undefined ); } ); QUnit.test( 'formatValue()', function( assert ) { var mock = mockApi( 'get' ); mock.api.formatValue( - { datavalue: 'serialization' }, - { option: 'option value'}, + { 'I am': 'DataValue serialization' }, + { option: 'option value' }, 'data type id', 'output format' ); + mock.api.formatValue( { 'I am': 'DataValue serialization' } ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -132,11 +130,19 @@ assert.equal( getParam( mock.spy, 'datavalue' ), - JSON.stringify( { datavalue: 'serialization' } ) + JSON.stringify( { 'I am': 'DataValue serialization' } ) ); - assert.equal( getParam( mock.spy, 'options' ), JSON.stringify( { option: 'option value'} ) ); + assert.equal( getParam( mock.spy, 'options' ), JSON.stringify( { option: 'option value' } ) ); assert.equal( getParam( mock.spy, 'datatype' ), 'data type id' ); assert.equal( getParam( mock.spy, 'generate' ), 'output format' ); + + assert.equal( + getParam( mock.spy, 'datavalue', 1 ), + JSON.stringify( { 'I am': 'DataValue serialization' } ) + ); + assert.equal( getParam( mock.spy, 'options', 1 ), JSON.stringify( {} ) ); + assert.strictEqual( getParam( mock.spy, 'datatype', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'generate', 1 ), undefined ); } ); QUnit.test( 'getEntities()', function( assert ) { @@ -147,7 +153,7 @@ ['property1', 'property2'], ['language code 1', 'language code 2'], ['sort property 1', 'sort property 2'], - 'sort direction' + 'ascending' ); mock.api.getEntities( @@ -155,10 +161,12 @@ 'property', 'language code', 'sort property', - 'sort direction' + 'descending' ); - assert.ok( mock.spy.calledTwice, 'Triggered API calls.' ); + mock.api.getEntities( 'entity id' ); + + assert.ok( mock.spy.calledThrice, 'Triggered API calls.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -170,13 +178,19 @@ assert.equal( getParam( mock.spy, 'props' ), 'property1|property2' ); assert.equal( getParam( mock.spy, 'languages' ), 'language code 1|language code 2' ); assert.equal( getParam( mock.spy, 'sort' ), 'sort property 1|sort property 2' ); - assert.equal( getParam( mock.spy, 'dir' ), 'sort direction' ); + assert.equal( getParam( mock.spy, 'dir' ), 'ascending' ); assert.equal( getParam( mock.spy, 'ids', 1 ), 'entity id' ); assert.equal( getParam( mock.spy, 'props', 1 ), 'property' ); assert.equal( getParam( mock.spy, 'languages', 1 ), 'language code' ); assert.equal( getParam( mock.spy, 'sort', 1 ), 'sort property' ); - assert.equal( getParam( mock.spy, 'dir', 1 ), 'sort direction' ); + assert.equal( getParam( mock.spy, 'dir', 1 ), 'descending' ); + + assert.equal( getParam( mock.spy, 'ids', 2 ), 'entity id' ); + assert.strictEqual( getParam( mock.spy, 'props', 2 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'languages', 2 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'sort', 2 ), undefined ); + assert.equal( getParam( mock.spy, 'dir', 2 ), 'ascending' ); } ); QUnit.test( 'getEntitiesByPage()', function( assert ) { @@ -184,11 +198,21 @@ mock.api.getEntitiesByPage( ['site id 1', 'site id 2'], + 'title', + ['property1', 'property2'], + ['language code 1', 'language code 2'], + ['sort property 1', 'sort property 2'], + 'ascending', + true + ); + + mock.api.getEntitiesByPage( + 'site id', ['title1', 'title2'], ['property1', 'property2'], ['language code 1', 'language code 2'], ['sort property 1', 'sort property 2'], - 'sort direction', + 'ascending', true ); @@ -198,11 +222,15 @@ 'property', 'language code', 'sort property', - 'sort direction', + 'descending', false ); - assert.ok( mock.spy.calledTwice, 'Triggered API calls.' ); + mock.api.getEntitiesByPage( 'site id', 'title' ); + mock.api.getEntitiesByPage( ['site id'], 'title' ); + mock.api.getEntitiesByPage( 'site id', ['title'] ); + + assert.equal( mock.spy.callCount, 6, 'Triggered API calls.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -211,20 +239,52 @@ ); assert.equal( getParam( mock.spy, 'sites' ), 'site id 1|site id 2' ); - assert.equal( getParam( mock.spy, 'titles' ), 'title1|title2' ); + assert.equal( getParam( mock.spy, 'titles' ), 'title' ); assert.equal( getParam( mock.spy, 'props' ), 'property1|property2' ); assert.equal( getParam( mock.spy, 'languages' ), 'language code 1|language code 2' ); assert.equal( getParam( mock.spy, 'sort' ), 'sort property 1|sort property 2' ); - assert.equal( getParam( mock.spy, 'dir' ), 'sort direction' ); + assert.equal( getParam( mock.spy, 'dir' ), 'ascending' ); assert.strictEqual( getParam( mock.spy, 'normalize' ), true ); assert.equal( getParam( mock.spy, 'sites', 1 ), 'site id' ); - assert.equal( getParam( mock.spy, 'titles', 1 ), 'title' ); - assert.equal( getParam( mock.spy, 'props', 1 ), 'property' ); - assert.equal( getParam( mock.spy, 'languages', 1 ), 'language code' ); - assert.equal( getParam( mock.spy, 'sort', 1 ), 'sort property' ); - assert.equal( getParam( mock.spy, 'dir', 1 ), 'sort direction' ); - assert.strictEqual( getParam( mock.spy, 'normalize', 1 ), false ); + assert.equal( getParam( mock.spy, 'titles', 1 ), 'title1|title2' ); + assert.equal( getParam( mock.spy, 'props', 1 ), 'property1|property2' ); + assert.equal( getParam( mock.spy, 'languages' ), 'language code 1|language code 2' ); + assert.equal( getParam( mock.spy, 'sort' ), 'sort property 1|sort property 2' ); + assert.equal( getParam( mock.spy, 'dir', 1 ), 'ascending' ); + assert.strictEqual( getParam( mock.spy, 'normalize', 1 ), true ); + + assert.equal( getParam( mock.spy, 'sites', 2 ), 'site id' ); + assert.equal( getParam( mock.spy, 'titles', 2 ), 'title' ); + assert.equal( getParam( mock.spy, 'props', 2 ), 'property' ); + assert.equal( getParam( mock.spy, 'languages', 2 ), 'language code' ); + assert.equal( getParam( mock.spy, 'sort', 2 ), 'sort property' ); + assert.equal( getParam( mock.spy, 'dir', 2 ), 'descending' ); + assert.strictEqual( getParam( mock.spy, 'normalize', 2 ), false ); + + assert.equal( getParam( mock.spy, 'sites', 3 ), 'site id' ); + assert.equal( getParam( mock.spy, 'titles', 3 ), 'title' ); + assert.strictEqual( getParam( mock.spy, 'props', 3 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'languages', 3 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'sort', 3 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'dir', 3 ), 'ascending' ); + assert.strictEqual( getParam( mock.spy, 'normalize', 3 ), undefined ); + + assert.equal( getParam( mock.spy, 'sites', 4 ), 'site id' ); + assert.equal( getParam( mock.spy, 'titles', 4 ), 'title' ); + assert.strictEqual( getParam( mock.spy, 'props', 4 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'languages', 4 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'sort', 4 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'dir', 4 ), 'ascending' ); + assert.strictEqual( getParam( mock.spy, 'normalize', 4 ), undefined ); + + assert.equal( getParam( mock.spy, 'sites', 5 ), 'site id' ); + assert.equal( getParam( mock.spy, 'titles', 5 ), 'title' ); + assert.strictEqual( getParam( mock.spy, 'props', 5 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'languages', 5 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'sort', 5 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'dir', 5 ), 'ascending' ); + assert.strictEqual( getParam( mock.spy, 'normalize', 5 ), undefined ); } ); QUnit.test( 'parseValue()', function( assert ) { @@ -235,8 +295,9 @@ ['serialization1', 'serialization2'], { option: 'option value'} ); + mock.api.parseValue( 'parser id', ['serialization'] ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -247,14 +308,19 @@ assert.equal( getParam( mock.spy, 'parser' ), 'parser id' ); assert.equal( getParam( mock.spy, 'values' ), 'serialization1|serialization2'); assert.equal( getParam( mock.spy, 'options' ), JSON.stringify( { option: 'option value'} ) ); + + assert.equal( getParam( mock.spy, 'parser', 1 ), 'parser id' ); + assert.equal( getParam( mock.spy, 'values', 1 ), 'serialization'); + assert.strictEqual( getParam( mock.spy, 'options', 1 ), undefined ); } ); QUnit.test( 'searchEntities()', function( assert ) { var mock = mockApi( 'get' ); mock.api.searchEntities( 'label', 'language code', 'entity type', 10, 5 ); + mock.api.searchEntities( 'label', 'language code', 'entity type' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -267,6 +333,12 @@ assert.equal( getParam( mock.spy, 'type' ), 'entity type' ); assert.equal( getParam( mock.spy, 'limit' ), 10 ); assert.equal( getParam( mock.spy, 'continue' ), 5 ); + + assert.equal( getParam( mock.spy, 'search', 1 ), 'label' ); + assert.equal( getParam( mock.spy, 'language', 1 ), 'language code' ); + assert.equal( getParam( mock.spy, 'type', 1 ), 'entity type' ); + assert.strictEqual( getParam( mock.spy, 'limit', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'continue', 1 ), undefined ); } ); QUnit.test( 'setLabel(), setDescription()', function( assert ) { @@ -318,8 +390,9 @@ var mock = mockApi(); mock.api.setClaim( { 'I am': 'a Claim serialization' }, 12345, 67890 ); + mock.api.setClaim( { 'I am': 'a Claim serialization' }, 12345 ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -333,14 +406,22 @@ ); assert.equal( getParam( mock.spy, 'baserevid' ), 12345 ); assert.equal( getParam( mock.spy, 'index' ), 67890 ); + + assert.equal( + getParam( mock.spy, 'claim', 1 ), + JSON.stringify( { 'I am': 'a Claim serialization' } ) + ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.strictEqual( getParam( mock.spy, 'index', 1 ), undefined ); } ); QUnit.test( 'createClaim()', function( assert ) { var mock = mockApi(); mock.api.createClaim( 'entity id', 12345, 'snak type', 'property id', 'snak value' ); + mock.api.createClaim( 'entity id', 12345, 'snak type', 'property id' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -353,14 +434,21 @@ assert.equal( getParam( mock.spy, 'snaktype' ), 'snak type' ); assert.equal( getParam( mock.spy, 'property' ), 'property id' ); assert.equal( getParam( mock.spy, 'value' ), JSON.stringify( 'snak value' ) ); + + assert.equal( getParam( mock.spy, 'entity', 1 ), 'entity id' ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.equal( getParam( mock.spy, 'snaktype', 1 ), 'snak type' ); + assert.equal( getParam( mock.spy, 'property', 1 ), 'property id' ); + assert.strictEqual( getParam( mock.spy, 'value', 1 ), undefined ); } ); QUnit.test( 'removeClaim()', function( assert ) { var mock = mockApi(); mock.api.removeClaim( 'claim GUID', 12345 ); + mock.api.removeClaim( 'claim GUID' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -370,14 +458,18 @@ assert.equal( getParam( mock.spy, 'claim' ), 'claim GUID' ); assert.equal( getParam( mock.spy, 'baserevid' ), 12345 ); + + assert.equal( getParam( mock.spy, 'claim', 1 ), 'claim GUID' ); + assert.strictEqual( getParam( mock.spy, 'baserevid', 1 ), undefined ); } ); QUnit.test( 'getClaims()', function( assert ) { var mock = mockApi( 'get' ); mock.api.getClaims( 'entity id', 'property id', 'claim GUID', 'rank', 'claim props' ); + mock.api.getClaims( 'entity id' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -390,14 +482,21 @@ assert.equal( getParam( mock.spy, 'claim' ), 'claim GUID' ); assert.equal( getParam( mock.spy, 'rank' ), 'rank' ); assert.equal( getParam( mock.spy, 'props' ), 'claim props' ); + + assert.equal( getParam( mock.spy, 'entity', 1 ), 'entity id' ); + assert.strictEqual( getParam( mock.spy, 'property', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'claim', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'rank', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'props', 1 ), undefined ); } ); QUnit.test( 'setClaimValue()', function( assert ) { var mock = mockApi(); mock.api.setClaimValue( 'claim GUID', 12345, 'snak type', 'property id', 'snak value' ); + mock.api.setClaimValue( 'claim GUID', 12345, 'snak type', 'property id' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -410,6 +509,12 @@ assert.equal( getParam( mock.spy, 'snaktype' ), 'snak type' ); assert.equal( getParam( mock.spy, 'property' ), 'property id' ); assert.equal( getParam( mock.spy, 'value' ), JSON.stringify( 'snak value' ) ); + + assert.equal( getParam( mock.spy, 'claim', 1 ), 'claim GUID' ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.equal( getParam( mock.spy, 'snaktype', 1 ), 'snak type' ); + assert.equal( getParam( mock.spy, 'property', 1 ), 'property id' ); + assert.strictEqual( getParam( mock.spy, 'value', 1 ), undefined ); } ); QUnit.test( 'setReference()', function( assert ) { @@ -422,8 +527,9 @@ 'reference hash', 67890 ); + mock.api.setReference( 'statement GUID', {'I am': 'serialized Snaks'}, 12345 ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -436,6 +542,15 @@ assert.equal( getParam( mock.spy, 'baserevid' ), 12345 ); assert.equal( getParam( mock.spy, 'reference' ), 'reference hash' ); assert.equal( getParam( mock.spy, 'index' ), 67890 ); + + assert.equal( getParam( mock.spy, 'statement', 1 ), 'statement GUID' ); + assert.equal( + getParam( mock.spy, 'snaks', 1 ), + JSON.stringify( {'I am': 'serialized Snaks'} ) + ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.strictEqual( getParam( mock.spy, 'reference', 1 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'index', 1 ), undefined ); } ); QUnit.test( 'removeReferences()', function( assert ) { @@ -461,14 +576,15 @@ assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); } ); -QUnit.test( 'setSiteLink()', function( assert ) { +QUnit.test( 'setSitelink()', function( assert ) { var mock = mockApi(); mock.api.setSitelink( 'entity id', 12345, 'site id', 'page name', ['entity id of badge1', 'entity id of badge 2'] ); + mock.api.setSitelink( 'entity id', 12345, 'site id', 'page name' ); - assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); + assert.ok( mock.spy.calledTwice, 'Triggered API call.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -481,6 +597,12 @@ assert.equal( getParam( mock.spy, 'linksite' ), 'site id' ); assert.equal( getParam( mock.spy, 'linktitle' ), 'page name' ); assert.equal( getParam( mock.spy, 'badges' ), 'entity id of badge1|entity id of badge 2' ); + + assert.equal( getParam( mock.spy, 'id', 1 ), 'entity id' ); + assert.equal( getParam( mock.spy, 'baserevid', 1 ), 12345 ); + assert.equal( getParam( mock.spy, 'linksite', 1 ), 'site id' ); + assert.equal( getParam( mock.spy, 'linktitle', 1 ), 'page name' ); + assert.strictEqual( getParam( mock.spy, 'badges', 1 ), undefined ); } ); QUnit.test( 'mergeItems()', function( assert ) { @@ -498,8 +620,9 @@ 'property to ignore conflict for', 'edit summary' ); + mock.api.mergeItems( 'entity id from', 'entity id to' ); - assert.ok( mock.spy.calledTwice, 'Triggered API calls.' ); + assert.ok( mock.spy.calledThrice, 'Triggered API calls.' ); assert.equal( getParam( mock.spy, 'action' ), @@ -522,6 +645,11 @@ 'property to ignore conflict for' ); assert.equal( getParam( mock.spy, 'summary', 1 ), 'edit summary' ); + + assert.equal( getParam( mock.spy, 'fromid', 2 ), 'entity id from' ); + assert.equal( getParam( mock.spy, 'toid', 2 ), 'entity id to' ); + assert.strictEqual( getParam( mock.spy, 'ignoreconflicts', 2 ), undefined ); + assert.strictEqual( getParam( mock.spy, 'summary', 2 ), undefined ); } ); }( mediaWiki, wikibase, QUnit, sinon ) ); -- To view, visit https://gerrit.wikimedia.org/r/177517 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I4d043f5cc43852970a489014bc5c106592ccfdc3 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikibaseJavaScriptApi Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits