mediawiki.api: Add #badToken for invalidating bad cached tokens
authorBartosz Dziewoński <matma.rex@gmail.com>
Thu, 30 Apr 2015 23:54:13 +0000 (01:54 +0200)
committerBartosz Dziewoński <matma.rex@gmail.com>
Tue, 5 May 2015 14:17:49 +0000 (16:17 +0200)
Bug: T71691
Change-Id: I9a270e5ed030513f62dc75ba4e6edc78f4da63a1

resources/src/mediawiki.api/mediawiki.api.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js

index 3a19e02..c1fe187 100644 (file)
                                        // Error handler
                                        function ( code ) {
                                                if ( code === 'badtoken' ) {
-                                                       // Clear from cache
-                                                       promises[ api.defaults.ajax.url ][ tokenType + 'Token' ] =
-                                                               params.token = undefined;
-
+                                                       api.badToken( tokenType );
                                                        // Try again, once
+                                                       params.token = undefined;
                                                        return api.getToken( tokenType, params.assert ).then( function ( token ) {
                                                                params.token = token;
                                                                return api.post( params, ajaxOptions );
 
                                d = apiPromise
                                        .then( function ( data ) {
-                                               // If token type is not available for this user,
-                                               // key '...token' is either missing or set to boolean false
                                                if ( data.tokens && data.tokens[type + 'token'] ) {
                                                        return data.tokens[type + 'token'];
                                                }
 
+                                               // If token type is not available for this user,
+                                               // key '...token' is either missing or set to boolean false
                                                return $.Deferred().reject( 'token-missing', data );
                                        }, function () {
                                                // Clear promise. Do not cache errors.
                                                delete promiseGroup[ type + 'Token' ];
-
                                                // Pass on to allow the caller to handle the error
                                                return this;
                                        } )
                        }
 
                        return d;
+               },
+
+               /**
+                * Indicate that the cached token for a certain action of the API is bad.
+                *
+                * Call this if you get a 'badtoken' error when using the token returned by #getToken.
+                * You may also want to use #postWithToken instead, which invalidates bad cached tokens
+                * automatically.
+                *
+                * @param {string} type Token type
+                * @since 1.26
+                */
+               badToken: function ( type ) {
+                       var promiseGroup = promises[ this.defaults.ajax.url ];
+                       if ( promiseGroup ) {
+                               delete promiseGroup[ type + 'Token' ];
+                       }
                }
        };
 
index b89526f..4f199bd 100644 (file)
@@ -80,6 +80,7 @@
 
                // Get editToken for local wiki, this should not make
                // a request as it should be retrieved from user.tokens.
+               // This means that this test must run before the #badToken test below.
                api.getToken( 'edit' )
                        .done( function ( token ) {
                                assert.ok( token.length, 'Got a token' );
                assert.equal( this.server.requests.length, 0, 'Requests made' );
        } );
 
+       QUnit.test( 'badToken()', function ( assert ) {
+               QUnit.expect( 2 );
+
+               var api = new mw.Api();
+
+               // Clear the default cached token
+               api.badToken( 'edit' );
+
+               api.getToken( 'edit' )
+                       .done( function ( token ) {
+                               assert.equal( token, '0123abc', 'Got a non-cached token' );
+                       } )
+                       .fail( function ( err ) {
+                               assert.equal( '', err, 'API error' );
+                       } );
+
+               this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
+                       '{ "tokens": { "edittoken": "0123abc" } }'
+               );
+
+               assert.equal( this.server.requests.length, 1, 'Requests made' );
+       } );
+
        QUnit.test( 'getToken()', function ( assert ) {
                QUnit.expect( 5 );