Implement extension registration from an extension.json file
[mediawiki.git] / tests / qunit / suites / resources / mediawiki.api / mediawiki.api.test.js
blobb89526fb84d3ef22ac4d5f04271bf0202bf2d91d
1 ( function ( mw ) {
2         QUnit.module( 'mediawiki.api', QUnit.newMwEnvironment( {
3                 setup: function () {
4                         this.server = this.sandbox.useFakeServer();
5                 }
6         } ) );
8         QUnit.test( 'Basic functionality', function ( assert ) {
9                 QUnit.expect( 2 );
11                 var api = new mw.Api();
13                 api.get( {} )
14                         .done( function ( data ) {
15                                 assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
16                         } );
18                 api.post( {} )
19                         .done( function ( data ) {
20                                 assert.deepEqual( data, [], 'Simple POST request' );
21                         } );
23                 this.server.respond( function ( request ) {
24                         request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
25                 } );
26         } );
28         QUnit.test( 'API error', function ( assert ) {
29                 QUnit.expect( 1 );
31                 var api = new mw.Api();
33                 api.get( { action: 'doesntexist' } )
34                         .fail( function ( errorCode ) {
35                                 assert.equal( errorCode, 'unknown_action', 'API error should reject the deferred' );
36                         } );
38                 this.server.respond( function ( request ) {
39                         request.respond( 200, { 'Content-Type': 'application/json' },
40                                 '{ "error": { "code": "unknown_action" } }'
41                         );
42                 } );
43         } );
45         QUnit.test( 'FormData support', function ( assert ) {
46                 QUnit.expect( 2 );
48                 var api = new mw.Api();
50                 api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
52                 this.server.respond( function ( request ) {
53                         if ( window.FormData ) {
54                                 assert.ok( !request.url.match( /action=/ ), 'Request has no query string' );
55                                 assert.ok( request.requestBody instanceof FormData, 'Request uses FormData body' );
56                         } else {
57                                 assert.ok( !request.url.match( /action=test/ ), 'Request has no query string' );
58                                 assert.equal( request.requestBody, 'action=test&format=json', 'Request uses query string body' );
59                         }
60                         request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
61                 } );
62         } );
64         QUnit.test( 'Converting arrays to pipe-separated', function ( assert ) {
65                 QUnit.expect( 1 );
67                 var api = new mw.Api();
68                 api.get( { test: [ 'foo', 'bar', 'baz' ] } );
70                 this.server.respond( function ( request ) {
71                         assert.ok( request.url.match( /test=foo%7Cbar%7Cbaz/ ), 'Pipe-separated value was submitted' );
72                         request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
73                 } );
74         } );
76         QUnit.test( 'getToken( pre-populated )', function ( assert ) {
77                 QUnit.expect( 2 );
79                 var api = new mw.Api();
81                 // Get editToken for local wiki, this should not make
82                 // a request as it should be retrieved from user.tokens.
83                 api.getToken( 'edit' )
84                         .done( function ( token ) {
85                                 assert.ok( token.length, 'Got a token' );
86                         } )
87                         .fail( function ( err ) {
88                                 assert.equal( '', err, 'API error' );
89                         } );
91                 assert.equal( this.server.requests.length, 0, 'Requests made' );
92         } );
94         QUnit.test( 'getToken()', function ( assert ) {
95                 QUnit.expect( 5 );
97                 var test = this,
98                         api = new mw.Api();
100                 // Get a token of a type that isn't prepopulated by user.tokens.
101                 // Could use "block" or "delete" here, but those could in theory
102                 // be added to user.tokens, use a fake one instead.
103                 api.getToken( 'testaction' )
104                         .done( function ( token ) {
105                                 assert.ok( token.length, 'Got testaction token' );
106                         } )
107                         .fail( function ( err ) {
108                                 assert.equal( err, '', 'API error' );
109                         } );
110                 api.getToken( 'testaction' )
111                         .done( function ( token ) {
112                                 assert.ok( token.length, 'Got testaction token (cached)' );
113                         } )
114                         .fail( function ( err ) {
115                                 assert.equal( err, '', 'API error' );
116                         } );
118                 // Don't cache error (bug 65268)
119                 api.getToken( 'testaction2' )
120                         .fail( function ( err ) {
121                                 assert.equal( err, 'bite-me', 'Expected error' );
122                         } )
123                         .always( function () {
124                                 // Make this request after the first one has finished.
125                                 // If we make it simultaneously we still want it to share
126                                 // the cache, but as soon as it is fulfilled as error we
127                                 // reject it so that the next one tries fresh.
128                                 api.getToken( 'testaction2' )
129                                         .done( function ( token ) {
130                                                 assert.ok( token.length, 'Got testaction2 token (error was not be cached)' );
131                                         } )
132                                         .fail( function ( err ) {
133                                                 assert.equal( err, '', 'API error' );
134                                         } );
136                                 assert.equal( test.server.requests.length, 3, 'Requests made' );
138                                 test.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
139                                         '{ "tokens": { "testaction2token": "0123abc" } }'
140                                 );
141                         } );
143                 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
144                         '{ "tokens": { "testactiontoken": "0123abc" } }'
145                 );
147                 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
148                         '{ "error": { "code": "bite-me", "info": "Smite me, O Mighty Smiter" } }'
149                 );
150         } );
152         QUnit.test( 'postWithToken( tokenType, params )', function ( assert ) {
153                 QUnit.expect( 1 );
155                 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
157                 // - Requests token
158                 // - Performs action=example
159                 api.postWithToken( 'testsimpletoken', { action: 'example', key: 'foo' } )
160                         .done( function ( data ) {
161                                 assert.deepEqual( data, { example: { foo: 'quux' } } );
162                         } );
164                 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
165                         '{ "tokens": { "testsimpletokentoken": "a-bad-token" } }'
166                 );
168                 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
169                         '{ "example": { "foo": "quux" } }'
170                 );
171         } );
173         QUnit.test( 'postWithToken( tokenType, params with assert )', function ( assert ) {
174                 QUnit.expect( 2 );
176                 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
178                 api.postWithToken( 'testasserttoken', { action: 'example', key: 'foo', assert: 'user' } )
179                         .fail( function ( errorCode ) {
180                                 assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
181                         } );
183                 assert.equal( this.server.requests.length, 1, 'Request for token made' );
184                 this.server.respondWith( /assert=user/, function ( request ) {
185                         request.respond(
186                                 200,
187                                 { 'Content-Type': 'application/json' },
188                                 '{ "error": { "code": "assertuserfailed", "info": "Assertion failed" } }'
189                         );
190                 } );
192                 this.server.respond();
193         } );
195         QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
196                 QUnit.expect( 3 );
198                 var api = new mw.Api();
200                 api.postWithToken(
201                         'edit',
202                         {
203                                 action: 'example'
204                         },
205                         {
206                                 headers: {
207                                         'X-Foo': 'Bar'
208                                 }
209                         }
210                 );
212                 api.postWithToken(
213                         'edit',
214                         {
215                                 action: 'example'
216                         },
217                         function () {
218                                 assert.ok( false, 'This parameter cannot be a callback' );
219                         }
220                 )
221                 .always( function ( data ) {
222                         assert.equal( data.example, 'quux' );
223                 } );
225                 assert.equal( this.server.requests.length, 2, 'Request made' );
226                 assert.equal( this.server.requests[0].requestHeaders['X-Foo'], 'Bar', 'Header sent' );
228                 this.server.respond( function ( request ) {
229                         request.respond( 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' );
230                 } );
231         } );
233         QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
234                 QUnit.expect( 1 );
236                 var api = new mw.Api();
238                 // - Request: token
239                 // - Request: action=example -> badtoken error
240                 // - Request: new token
241                 // - Request: action=example
242                 api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
243                         .done( function ( data ) {
244                                 assert.deepEqual( data, { example: { foo: 'quux' } } );
245                         } );
247                 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
248                         '{ "tokens": { "testbadtokentoken": "a-bad-token" } }'
249                 );
251                 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
252                         '{ "error": { "code": "badtoken" } }'
253                 );
255                 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
256                         '{ "tokens": { "testbadtokentoken": "a-good-token" } }'
257                 );
259                 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
260                         '{ "example": { "foo": "quux" } }'
261                 );
263         } );
265         QUnit.test( 'postWithToken() - badtoken-cached', function ( assert ) {
266                 QUnit.expect( 2 );
268                 var api = new mw.Api();
270                 // - Request: token
271                 // - Request: action=example
272                 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'foo' } )
273                         .done( function ( data ) {
274                                 assert.deepEqual( data, { example: { foo: 'quux' } } );
275                         } );
277                 // - Cache: Try previously cached token
278                 // - Request: action=example -> badtoken error
279                 // - Request: new token
280                 // - Request: action=example
281                 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'bar' } )
282                         .done( function ( data ) {
283                                 assert.deepEqual( data, { example: { bar: 'quux' } } );
284                         } );
286                 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
287                         '{ "tokens": { "testbadtokencachetoken": "a-good-token-once" } }'
288                 );
290                 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
291                         '{ "example": { "foo": "quux" } }'
292                 );
294                 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
295                         '{ "error": { "code": "badtoken" } }'
296                 );
298                 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
299                         '{ "tokens": { "testbadtokencachetoken": "a-good-new-token" } }'
300                 );
302                 this.server.requests[4].respond( 200, { 'Content-Type': 'application/json' },
303                         '{ "example": { "bar": "quux" } }'
304                 );
306         } );
308 }( mediaWiki ) );