Thiemo Mättig (WMDE) has submitted this change and it was merged. 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 --- M .jshintrc M README.md M src/RepoApi.js A tests/.jshintrc M tests/RepoApi.tests.js 5 files changed, 557 insertions(+), 149 deletions(-) Approvals: Thiemo Mättig (WMDE): Verified; Looks good to me, approved diff --git a/.jshintrc b/.jshintrc index 09f9407..239b121 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,52 +1,52 @@ { - "bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.). + "bitwise": true, // Prohibit bitwise operators (&, |, ^, etc.). "camelcase": true, // Force variable names to be camelcase - "curly" : true, // Require {} for every new block or scope. - "eqeqeq" : true, // Require triple equals i.e. `===`. + "curly": true, // Require {} for every new block or scope. + "eqeqeq": true, // Require triple equals i.e. `===`. "es3": true, // Prohibit trailing comma in object literals (breaks older versions of IE) - "forin" : false, // Don't expect `for in` loops to call `hasOwnPrototype`. + "forin": false, // Don't expect `for in` loops to call `hasOwnPrototype`. "freeze": true, // Prohibit overwriting prototypes of native objects such as Array, Date and so on. - "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` - "latedef" : true, // Prohibit variable use before definition. - "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`. - "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. - "noempty" : true, // Prohibit use of empty blocks. + "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` + "latedef": true, // Prohibit variable use before definition. + "newcap": true, // Require capitalization of all constructor functions e.g. `new F()`. + "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. + "noempty": true, // Prohibit use of empty blocks. "nonbsp": true, // Prohibit nbsp - "nonew" : true, // Prohibit use of constructors for side-effects. - "plusplus" : false, // Allow use of `++` & `--`. - "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions. - "undef" : true, // Require all non-global variables be declared before they are used. - "unused" : false, // Don't warn about unused variables - "strict" : true, // Require `use strict` pragma in every file. - "trailing" : true, // Prohibit trailing whitespaces. + "nonew": true, // Prohibit use of constructors for side-effects. + "plusplus": false, // Allow use of `++` & `--`. + "regexp": true, // Prohibit `.` and `[^...]` in regular expressions. + "undef": true, // Require all non-global variables be declared before they are used. + "unused": false, // Don't warn about unused variables + "strict": true, // Require `use strict` pragma in every file. + "trailing": true, // Prohibit trailing whitespaces. - "asi" : false, // Don't tolerate Automatic Semicolon Insertion (no semicolons). - "boss" : false, // Don't tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. - "debug" : false, // Don't allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // Don't tolerate use of `== null`. - "es5" : false, // Don't allow EcmaScript 5 syntax. - "esnext" : false, // Don't allow ES.next specific features such as `const` and `let`. - "evil" : false, // Don't tolerate use of `eval`. - "expr" : false, // Don't tolerate `ExpressionStatement` as Programs. - "funcscope" : false, // Don't tolerate declarations of variables inside of control structures while accessing them later from the outside. - "globalstrict" : false, // Don't allow global "use strict" (also enables 'strict'). - "iterator" : false, // Don't allow usage of __iterator__ property. - "lastsemic" : false, // Don't tolerat missing semicolons when the it is omitted for the last statement in a one-line block. - "laxbreak" : true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. - "laxcomma" : false, // Don't suppress warnings about comma-first coding style. - "loopfunc" : false, // Don't allow functions to be defined within loops. - "multistr" : false, // Don't tolerate multi-line strings. - "onecase" : false, // Don't tolerate switches with just one case. - "proto" : false, // Don't tolerate __proto__ property. This property is deprecated. - "regexdash" : false, // Don't tolerate unescaped last dash i.e. `[-...]`. - "scripturl" : false, // Don't tolerate script-targeted URLs. - "smarttabs" : false, // Don't tolerate mixed tabs and spaces when the latter are used for alignmnent only. - "shadow" : false, // Don't allows re-define variables later in code e.g. `var x=1; x=2;`. - "sub" : false, // Don't tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. - "supernew" : false, // Don't tolerate `new function () { ... };` and `new Object;`. - "validthis" : false, // Don't tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function. + "asi": false, // Don't tolerate Automatic Semicolon Insertion (no semicolons). + "boss": false, // Don't tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. + "debug": false, // Don't allow debugger statements e.g. browser breakpoints. + "eqnull": false, // Don't tolerate use of `== null`. + "es5": false, // Don't allow EcmaScript 5 syntax. + "esnext": false, // Don't allow ES.next specific features such as `const` and `let`. + "evil": false, // Don't tolerate use of `eval`. + "expr": false, // Don't tolerate `ExpressionStatement` as Programs. + "funcscope": false, // Don't tolerate declarations of variables inside of control structures while accessing them later from the outside. + "globalstrict": false, // Don't allow global "use strict" (also enables 'strict'). + "iterator": false, // Don't allow usage of __iterator__ property. + "lastsemic": false, // Don't tolerat missing semicolons when the it is omitted for the last statement in a one-line block. + "laxbreak": true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. + "laxcomma": false, // Don't suppress warnings about comma-first coding style. + "loopfunc": false, // Don't allow functions to be defined within loops. + "multistr": false, // Don't tolerate multi-line strings. + "onecase": false, // Don't tolerate switches with just one case. + "proto": false, // Don't tolerate __proto__ property. This property is deprecated. + "regexdash": false, // Don't tolerate unescaped last dash i.e. `[-...]`. + "scripturl": false, // Don't tolerate script-targeted URLs. + "smarttabs": false, // Don't tolerate mixed tabs and spaces when the latter are used for alignmnent only. + "shadow": false, // Don't allows re-define variables later in code e.g. `var x=1; x=2;`. + "sub": false, // Don't tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. + "supernew": false, // Don't tolerate `new function () { ... };` and `new Object;`. + "validthis": false, // Don't tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function. - "browser" : true, // Standard browser globals e.g. `window`, `document`. + "browser": true, // Standard browser globals e.g. `window`, `document`. "quotmark": false, "maxlen": 100, @@ -56,8 +56,6 @@ "predef": [ "jQuery", "mediaWiki", - "QUnit", - "sinon", "util", "wikibase" ] 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..09d9fc1 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 {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 {boolean} [clear] Whether to clear whole entity before editing. * @return {Object} jQuery.Promise * @return {Function} return.done * @return {*} return.done.result @@ -78,8 +84,19 @@ * @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' + || clear && typeof clear !== 'boolean' + ) { + throw new Error( 'Parameter not specified properly' ); + } + var params = { action: 'wbeditentity', id: id, @@ -87,8 +104,8 @@ data: JSON.stringify( data ) }; - if ( clear ) { - params.clear = true; + if( clear ) { + 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 ), @@ -133,14 +161,15 @@ * @see wikibase.api.RepoApi._post * * @param {string|string[]} ids `Entity` id(s). - * @param {string|string[]|null} [props=null] Key(s) of property/ies to retrieve from the API. - * `null` will return all properties. - * @param {string|string[]|null} [languages=null] Language code(s) of the languages the - * 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 + * @param {string|string[]|null} [props] Key(s) of property/ies to retrieve from the API. + * Omitting/`null` will return all properties. + * @param {string|string[]|null} [languages] Language code(s) of the languages the + * property/ies values should be retrieved in. Omitting/`null` returns values in all + * languages. + * @param {string|string[]|null} [sort] Key(s) of property/ies to sort on. Omitting/`null` will * result in unsorted output. - * @param {string|null} [dir=null] Sort direction, may be 'ascending' or 'descending'. - * `null` resolves to 'ascending'. + * @param {string} [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 +177,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 ); @@ -166,18 +207,19 @@ * Gets an `Entity` which is linked with on or more specific sites/pages. * @see wikibase.api.RepoApi._post * - * @param {string|string[]} [sites] `Site`(s). May be used with `titles`. May not be a list when + * @param {string|string[]} sites `Site`(s). May be used with `titles`. May not be a list when * `titles` is a list. - * @param {string|string[]} [titles] Linked page(s). May be used with `sites`. May not be a list + * @param {string|string[]} titles Linked page(s). May be used with `sites`. May not be a list * when `sites` is a list. - * @param {string|string[]|null} [props=null] Key(s) of property/ies to retrieve from the API. - * `null` returns all properties. - * @param {string|string[]|null} [languages=null] Language code(s) of the languages the - * 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 + * @param {string|string[]|null} [props] Key(s) of property/ies to retrieve from the API. + * Omitting/`null` returns all properties. + * @param {string|string[]|null} [languages] Language code(s) of the languages the + * property/ies values should be retrieved in. Omitting/`null` returns values in all + * languages. + * @param {string|string[]|null} [sort] Key(s) of property/ies to sort on. Omitting/`null` will * result in unsorted output. - * @param {string|null} [dir=null] Sort direction, may be 'ascending' or 'descending'. - * `null` resolves to 'ascending'. + * @param {string} [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 +228,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 +254,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 +275,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 +303,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 +312,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 +351,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 +371,7 @@ language: language, baserevid: baseRevId }; + return this._post( params ); }, @@ -299,8 +390,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 +410,7 @@ language: language, baserevid: baseRevId }; + return this._post( params ); }, @@ -328,18 +431,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 +472,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 +500,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 +510,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 +552,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 +580,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 +593,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 +631,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 +641,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,10 +662,10 @@ 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 ) { + if( value ) { params.value = JSON.stringify( value ); } @@ -505,8 +680,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 +693,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 +746,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 +784,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, @@ -596,7 +806,7 @@ baserevid: baseRevId }; - if ( badges ) { + if( badges ) { params.badges = this._normalizeParam( badges ); } @@ -607,8 +817,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 +828,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/.jshintrc b/tests/.jshintrc new file mode 100644 index 0000000..e0b52ce --- /dev/null +++ b/tests/.jshintrc @@ -0,0 +1,64 @@ +{ + "bitwise": true, // Prohibit bitwise operators (&, |, ^, etc.). + "camelcase": true, // Force variable names to be camelcase + "curly": true, // Require {} for every new block or scope. + "eqeqeq": true, // Require triple equals i.e. `===`. + "es3": true, // Prohibit trailing comma in object literals (breaks older versions of IE) + "forin": false, // Don't expect `for in` loops to call `hasOwnPrototype`. + "freeze": true, // Prohibit overwriting prototypes of native objects such as Array, Date and so on. + "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` + "latedef": true, // Prohibit variable use before definition. + "newcap": true, // Require capitalization of all constructor functions e.g. `new F()`. + "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. + "noempty": true, // Prohibit use of empty blocks. + "nonbsp": true, // Prohibit nbsp + "nonew": true, // Prohibit use of constructors for side-effects. + "plusplus": false, // Allow use of `++` & `--`. + "regexp": true, // Prohibit `.` and `[^...]` in regular expressions. + "undef": true, // Require all non-global variables be declared before they are used. + "unused": false, // Don't warn about unused variables + "strict": true, // Require `use strict` pragma in every file. + "trailing": true, // Prohibit trailing whitespaces. + + "asi": false, // Don't tolerate Automatic Semicolon Insertion (no semicolons). + "boss": false, // Don't tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. + "debug": false, // Don't allow debugger statements e.g. browser breakpoints. + "eqnull": false, // Don't tolerate use of `== null`. + "es5": false, // Don't allow EcmaScript 5 syntax. + "esnext": false, // Don't allow ES.next specific features such as `const` and `let`. + "evil": false, // Don't tolerate use of `eval`. + "expr": false, // Don't tolerate `ExpressionStatement` as Programs. + "funcscope": false, // Don't tolerate declarations of variables inside of control structures while accessing them later from the outside. + "globalstrict": false, // Don't allow global "use strict" (also enables 'strict'). + "iterator": false, // Don't allow usage of __iterator__ property. + "lastsemic": false, // Don't tolerat missing semicolons when the it is omitted for the last statement in a one-line block. + "laxbreak": true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. + "laxcomma": false, // Don't suppress warnings about comma-first coding style. + "loopfunc": false, // Don't allow functions to be defined within loops. + "multistr": false, // Don't tolerate multi-line strings. + "onecase": false, // Don't tolerate switches with just one case. + "proto": false, // Don't tolerate __proto__ property. This property is deprecated. + "regexdash": false, // Don't tolerate unescaped last dash i.e. `[-...]`. + "scripturl": false, // Don't tolerate script-targeted URLs. + "smarttabs": false, // Don't tolerate mixed tabs and spaces when the latter are used for alignmnent only. + "shadow": false, // Don't allows re-define variables later in code e.g. `var x=1; x=2;`. + "sub": false, // Don't tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. + "supernew": false, // Don't tolerate `new function () { ... };` and `new Object;`. + "validthis": false, // Don't tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function. + + "browser": true, // Standard browser globals e.g. `window`, `document`. + + "quotmark": false, + "maxlen": 100, + "maxparams": 7, + "maxdepth": 4, + "maxstatements": 100, + "predef": [ + "jQuery", + "mediaWiki", + "QUnit", + "sinon", + "util", + "wikibase" + ] +} diff --git a/tests/RepoApi.tests.js b/tests/RepoApi.tests.js index bea05e1..e97ecdb 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,23 +79,15 @@ 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 ); assert.ok( mock.spy.calledOnce, 'Triggered API call.' ); @@ -109,20 +99,22 @@ 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 ); } ); 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 +124,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 +147,7 @@ ['property1', 'property2'], ['language code 1', 'language code 2'], ['sort property 1', 'sort property 2'], - 'sort direction' + 'ascending' ); mock.api.getEntities( @@ -155,10 +155,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 +172,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 +192,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 +216,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 +233,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 +289,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 +302,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 +327,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 +384,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 +400,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 +428,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 +452,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 +476,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 +503,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 +521,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 +536,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 +570,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 +591,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 +614,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 +639,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: merged Gerrit-Change-Id: I4d043f5cc43852970a489014bc5c106592ccfdc3 Gerrit-PatchSet: 9 Gerrit-Project: mediawiki/extensions/WikibaseJavaScriptApi Gerrit-Branch: master Gerrit-Owner: Henning Snater <henning.sna...@wikimedia.de> Gerrit-Reviewer: Hashar <has...@free.fr> Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits