summaryrefslogtreecommitdiff
path: root/tests/qunit/suites/resources/mediawiki.api
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qunit/suites/resources/mediawiki.api')
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js30
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js25
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js312
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js46
4 files changed, 413 insertions, 0 deletions
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js
new file mode 100644
index 00000000..a0c7daf1
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js
@@ -0,0 +1,30 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.api.category', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.server = this.sandbox.useFakeServer();
+ }
+ } ) );
+
+ QUnit.test( '.getCategoriesByPrefix()', function ( assert ) {
+ QUnit.expect( 1 );
+
+ var api = new mw.Api();
+
+ api.getCategoriesByPrefix( 'Foo' ).done( function ( matches ) {
+ assert.deepEqual(
+ matches,
+ [ 'Food', 'Fool Supermarine S.6', 'Fools' ]
+ );
+ } );
+
+ this.server.respond( function ( req ) {
+ req.respond( 200, { 'Content-Type': 'application/json' },
+ '{ "query": { "allpages": [ ' +
+ '{ "title": "Category:Food" },' +
+ '{ "title": "Category:Fool Supermarine S.6" },' +
+ '{ "title": "Category:Fools" }' +
+ '] } }'
+ );
+ } );
+ } );
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
new file mode 100644
index 00000000..cd0db7c9
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
@@ -0,0 +1,25 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.api.parse', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.server = this.sandbox.useFakeServer();
+ }
+ } ) );
+
+ QUnit.test( 'Hello world', function ( assert ) {
+ QUnit.expect( 1 );
+
+ var api = new mw.Api();
+
+ api.parse( '\'\'\'Hello world\'\'\'' ).done( function ( html ) {
+ assert.equal( html, '<p><b>Hello world</b></p>' );
+ } );
+
+ this.server.respondWith( /action=parse.*&text='''Hello\+world'''/, function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' },
+ '{ "parse": { "text": { "*": "<p><b>Hello world</b></p>" } } }'
+ );
+ } );
+
+ this.server.respond();
+ } );
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
new file mode 100644
index 00000000..f156c728
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
@@ -0,0 +1,312 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.api', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.server = this.sandbox.useFakeServer();
+ }
+ } ) );
+
+ QUnit.test( 'Basic functionality', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var api = new mw.Api();
+
+ api.get( {} )
+ .done( function ( data ) {
+ assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
+ } );
+
+ api.post( {} )
+ .done( function ( data ) {
+ assert.deepEqual( data, [], 'Simple POST request' );
+ } );
+
+ this.server.respond( function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+ } );
+ } );
+
+ QUnit.test( 'API error', function ( assert ) {
+ QUnit.expect( 1 );
+
+ var api = new mw.Api();
+
+ api.get( { action: 'doesntexist' } )
+ .fail( function ( errorCode ) {
+ assert.equal( errorCode, 'unknown_action', 'API error should reject the deferred' );
+ } );
+
+ this.server.respond( function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "unknown_action" } }'
+ );
+ } );
+ } );
+
+ QUnit.test( 'FormData support', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var api = new mw.Api();
+
+ api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
+
+ this.server.respond( function ( request ) {
+ if ( window.FormData ) {
+ assert.ok( !request.url.match( /action=/), 'Request has no query string' );
+ assert.ok( request.requestBody instanceof FormData, 'Request uses FormData body' );
+ } else {
+ assert.ok( !request.url.match( /action=test/), 'Request has no query string' );
+ assert.equal( request.requestBody, 'action=test&format=json', 'Request uses query string body' );
+ }
+ request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+ } );
+ } );
+
+ QUnit.test( 'Deprecated callback methods', function ( assert ) {
+ QUnit.expect( 3 );
+
+ var api = new mw.Api();
+
+ this.suppressWarnings();
+
+ api.get( {}, function () {
+ assert.ok( true, 'Function argument treated as success callback.' );
+ } );
+
+ api.get( {}, {
+ ok: function () {
+ assert.ok( true, '"ok" property treated as success callback.' );
+ }
+ } );
+
+ api.get( { action: 'doesntexist' }, {
+ err: function () {
+ assert.ok( true, '"err" property treated as error callback.' );
+ }
+ } );
+
+ this.restoreWarnings();
+
+ this.server.respondWith( /action=query/, function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+ } );
+
+ this.server.respondWith( /action=doesntexist/, function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "unknown_action" } }'
+ );
+ } );
+
+ this.server.respond();
+ } );
+
+ QUnit.test( 'getToken( pre-populated )', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var api = new mw.Api();
+
+ // Get editToken for local wiki, this should not make
+ // a request as it should be retrieved from user.tokens.
+ api.getToken( 'edit' )
+ .done( function ( token ) {
+ assert.ok( token.length, 'Got a token' );
+ } )
+ .fail( function ( err ) {
+ assert.equal( '', err, 'API error' );
+ } );
+
+ assert.equal( this.server.requests.length, 0, 'Requests made' );
+ } );
+
+ QUnit.test( 'getToken()', function ( assert ) {
+ QUnit.expect( 5 );
+
+ var test = this,
+ api = new mw.Api();
+
+ // Get a token of a type that isn't prepopulated by user.tokens.
+ // Could use "block" or "delete" here, but those could in theory
+ // be added to user.tokens, use a fake one instead.
+ api.getToken( 'testaction' )
+ .done( function ( token ) {
+ assert.ok( token.length, 'Got testaction token' );
+ } )
+ .fail( function ( err ) {
+ assert.equal( err, '', 'API error' );
+ } );
+ api.getToken( 'testaction' )
+ .done( function ( token ) {
+ assert.ok( token.length, 'Got testaction token (cached)' );
+ } )
+ .fail( function ( err ) {
+ assert.equal( err, '', 'API error' );
+ } );
+
+ // Don't cache error (bug 65268)
+ api.getToken( 'testaction2' )
+ .fail( function ( err ) {
+ assert.equal( err, 'bite-me', 'Expected error' );
+ } )
+ .always( function () {
+ // Make this request after the first one has finished.
+ // If we make it simultaneously we still want it to share
+ // the cache, but as soon as it is fulfilled as error we
+ // reject it so that the next one tries fresh.
+ api.getToken( 'testaction2' )
+ .done( function ( token ) {
+ assert.ok( token.length, 'Got testaction2 token (error was not be cached)' );
+ } )
+ .fail( function ( err ) {
+ assert.equal( err, '', 'API error' );
+ } );
+
+ assert.equal( test.server.requests.length, 3, 'Requests made' );
+
+ test.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testaction2token": "0123abc" } }'
+ );
+ } );
+
+ this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testactiontoken": "0123abc" } }'
+ );
+
+ this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "bite-me", "info": "Smite me, O Mighty Smiter" } }'
+ );
+ } );
+
+ QUnit.test( 'postWithToken( tokenType, params )', function ( assert ) {
+ QUnit.expect( 1 );
+
+ var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
+
+ // - Requests token
+ // - Performs action=example
+ api.postWithToken( 'testsimpletoken', { action: 'example', key: 'foo' } )
+ .done( function ( data ) {
+ assert.deepEqual( data, { example: { foo: 'quux' } } );
+ } );
+
+ this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testsimpletokentoken": "a-bad-token" } }'
+ );
+
+ this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "example": { "foo": "quux" } }'
+ );
+ } );
+
+ QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
+ QUnit.expect( 3 );
+
+ var api = new mw.Api();
+
+ api.postWithToken(
+ 'edit',
+ {
+ action: 'example'
+ },
+ {
+ headers: {
+ 'X-Foo': 'Bar'
+ }
+ }
+ );
+
+ api.postWithToken(
+ 'edit',
+ {
+ action: 'example'
+ },
+ function () {
+ assert.ok( false, 'This parameter cannot be a callback' );
+ }
+ )
+ .always( function ( data ) {
+ assert.equal( data.example, 'quux' );
+ } );
+
+ assert.equal( this.server.requests.length, 2, 'Request made' );
+ assert.equal( this.server.requests[0].requestHeaders['X-Foo'], 'Bar', 'Header sent' );
+
+ this.server.respond( function ( request ) {
+ request.respond( 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' );
+ } );
+ } );
+
+ QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
+ QUnit.expect( 1 );
+
+ var api = new mw.Api();
+
+ // - Request: token
+ // - Request: action=example -> badtoken error
+ // - Request: new token
+ // - Request: action=example
+ api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
+ .done( function ( data ) {
+ assert.deepEqual( data, { example: { foo: 'quux' } } );
+ } );
+
+ this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testbadtokentoken": "a-bad-token" } }'
+ );
+
+ this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "badtoken" } }'
+ );
+
+ this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testbadtokentoken": "a-good-token" } }'
+ );
+
+ this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "example": { "foo": "quux" } }'
+ );
+
+ } );
+
+ QUnit.test( 'postWithToken() - badtoken-cached', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var api = new mw.Api();
+
+ // - Request: token
+ // - Request: action=example
+ api.postWithToken( 'testbadtokencache', { action: 'example', key: 'foo' } )
+ .done( function ( data ) {
+ assert.deepEqual( data, { example: { foo: 'quux' } } );
+ } );
+
+ // - Cache: Try previously cached token
+ // - Request: action=example -> badtoken error
+ // - Request: new token
+ // - Request: action=example
+ api.postWithToken( 'testbadtokencache', { action: 'example', key: 'bar' } )
+ .done( function ( data ) {
+ assert.deepEqual( data, { example: { bar: 'quux' } } );
+ } );
+
+ this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testbadtokencachetoken": "a-good-token-once" } }'
+ );
+
+ this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "example": { "foo": "quux" } }'
+ );
+
+ this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "badtoken" } }'
+ );
+
+ this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "testbadtokencachetoken": "a-good-new-token" } }'
+ );
+
+ this.server.requests[4].respond( 200, { 'Content-Type': 'application/json' },
+ '{ "example": { "bar": "quux" } }'
+ );
+
+ } );
+
+}( mediaWiki ) );
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
index 00000000..5965ab7b
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js
@@ -0,0 +1,46 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.api.watch', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.server = this.sandbox.useFakeServer();
+ }
+ } ) );
+
+ 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 ) );