mediawiki.api.watch: Don't use deprecated 'title' parameter
authorTimo Tijhof <krinklemail@gmail.com>
Mon, 10 Mar 2014 19:14:30 +0000 (20:14 +0100)
committerBartosz Dziewoński <matma.rex@gmail.com>
Wed, 12 Mar 2014 12:57:12 +0000 (13:57 +0100)
* Instead handle it client side, and not as a deprecated feature.
* Rename 'page' parameter to 'pages'.
* Add unit tests.

Change-Id: I81ec4282aedd91e3f0bb2ed0d6dd34e437b54f5d

resources/mediawiki.api/mediawiki.api.watch.js
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js [new file with mode: 0644]

index 5a24247..653c90a 100644 (file)
@@ -8,19 +8,20 @@
         * @private
         * @context mw.Api
         *
-        * @param {string|mw.Title|string[]|mw.Title[]} page Full page name or instance of mw.Title, or an
+        * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
         *  array thereof. If an array is passed, the return value passed to the promise will also be an
         *  array of appropriate objects.
         * @param {Function} [ok] Success callback (deprecated)
         * @param {Function} [err] Error callback (deprecated)
         * @return {jQuery.Promise}
         * @return {Function} return.done
-        * @return {Object|Object[]} return.done.watch
+        * @return {Object|Object[]} return.done.watch Object or list of objects (depends on the `pages`
+        *  parameter)
         * @return {string} return.done.watch.title Full pagename
-        * @return {boolean} return.done.watch.watched
+        * @return {boolean} return.done.watch.watched Whether the page is now watched or unwatched
         * @return {string} return.done.watch.message Parsed HTML of the confirmational interface message
         */
-       function doWatchInternal( page, ok, err, addParams ) {
+       function doWatchInternal( pages, ok, err, addParams ) {
                // XXX: Parameter addParams is undocumented because we inherit this
                // documentation in the public method..
                var params, apiPromise,
                params = {
                        action: 'watch',
                        token: mw.user.tokens.get( 'watchToken' ),
-                       uselang: mw.config.get( 'wgUserLanguage' )
+                       uselang: mw.config.get( 'wgUserLanguage' ),
+                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages )
                };
 
-               if ( $.isArray( page ) ) {
-                       params.titles = page.join( '|' );
-               } else {
-                       // The 'title' parameter is deprecated, keeping this for compatibility instead of
-                       // converting to array because the API response changes from object to array of objects
-                       // as well (bug 62422).
-                       params.title = String( page );
-               }
-
                if ( addParams ) {
                        $.extend( params, addParams );
                }
 
                apiPromise = this.post( params )
                        .done( function ( data ) {
-                               d.resolve( data.watch );
+                               // If a single page was given (not an array) respond with a single item as well.
+                               d.resolve( $.isArray( pages ) ? data.watch : data.watch[0] );
                        } )
                        .fail( d.reject );
 
                 *
                 * @inheritdoc #doWatchInternal
                 */
-               watch: function ( page, ok, err ) {
-                       return doWatchInternal.call( this, page, ok, err );
+               watch: function ( pages, ok, err ) {
+                       return doWatchInternal.call( this, pages, ok, err );
                },
                /**
                 * Convenience method for `action=watch&unwatch=1`.
                 *
                 * @inheritdoc #doWatchInternal
                 */
-               unwatch: function ( page, ok, err ) {
-                       return doWatchInternal.call( this, page, ok, err, { unwatch: 1 } );
+               unwatch: function ( pages, ok, err ) {
+                       return doWatchInternal.call( this, pages, ok, err, { unwatch: 1 } );
                }
 
        } );
index 58509c1..f6b6c6d 100644 (file)
@@ -65,6 +65,7 @@ return array(
                        'tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js',
                        'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js',
                        'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js',
+                       'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js',
                        'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js',
@@ -90,6 +91,7 @@ return array(
                        'mediawiki',
                        'mediawiki.api',
                        'mediawiki.api.parse',
+                       'mediawiki.api.watch',
                        'mediawiki.jqueryMsg',
                        'mediawiki.Title',
                        'mediawiki.Uri',
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js
new file mode 100644 (file)
index 0000000..e178090
--- /dev/null
@@ -0,0 +1,50 @@
+( function ( mw ) {
+       QUnit.module( 'mediawiki.api.watch', QUnit.newMwEnvironment( {
+               setup: function () {
+                       this.clock = this.sandbox.useFakeTimers();
+                       this.server = this.sandbox.useFakeServer();
+               },
+               teardown: function () {
+                       this.clock.tick( 1 );
+               }
+       } ) );
+
+       QUnit.test( '.watch()', function ( assert ) {
+               QUnit.expect( 4 );
+
+               var api = new mw.Api();
+
+               // Ensure we don't mistake a single item array for a single item and vice versa.
+               // The query parameter in request is the same either way (separated by pipe).
+               api.watch( 'Foo' ).done( function ( item ) {
+                       assert.equal( item.title, 'Foo' );
+               } );
+
+               api.watch( [ 'Foo' ] ).done( function ( items ) {
+                       assert.equal( items[0].title, 'Foo' );
+               } );
+
+               api.watch( [ 'Foo', 'Bar' ] ).done( function ( items ) {
+                       assert.equal( items[0].title, 'Foo' );
+                       assert.equal( items[1].title, 'Bar' );
+               } );
+
+               // Requests are POST, match requestBody instead of url
+               this.server.respond( function ( req ) {
+                       if ( /action=watch.*&titles=Foo(&|$)/.test( req.requestBody ) ) {
+                               req.respond( 200, { 'Content-Type': 'application/json' },
+                                       '{ "watch": [ { "title": "Foo", "watched": true, "message": "<b>Added</b>" } ] }'
+                               );
+                       }
+
+                       if ( /action=watch.*&titles=Foo%7CBar/.test( req.requestBody ) ) {
+                               req.respond( 200, { 'Content-Type': 'application/json' },
+                                       '{ "watch": [ ' +
+                                               '{ "title": "Foo", "watched": true, "message": "<b>Added</b>" },' +
+                                               '{ "title": "Bar", "watched": true, "message": "<b>Added</b>" }' +
+                                               '] }'
+                               );
+                       }
+               } );
+       } );
+}( mediaWiki ) );