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

Reply via email to