Merge "Remove unused 'XMPGetInfo' and 'XMPGetResults' hooks"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.api / mediawiki.api.test.js
1 ( function ( mw ) {
2 QUnit.module( 'mediawiki.api', QUnit.newMwEnvironment( {
3 setup: function () {
4 this.server = this.sandbox.useFakeServer();
5 }
6 } ) );
7
8 QUnit.test( 'Basic functionality', function ( assert ) {
9 QUnit.expect( 2 );
10
11 var api = new mw.Api();
12
13 api.get( {} )
14 .done( function ( data ) {
15 assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
16 } );
17
18 api.post( {} )
19 .done( function ( data ) {
20 assert.deepEqual( data, [], 'Simple POST request' );
21 } );
22
23 this.server.respond( function ( request ) {
24 request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
25 } );
26 } );
27
28 QUnit.test( 'API error', function ( assert ) {
29 QUnit.expect( 1 );
30
31 var api = new mw.Api();
32
33 api.get( { action: 'doesntexist' } )
34 .fail( function ( errorCode ) {
35 assert.equal( errorCode, 'unknown_action', 'API error should reject the deferred' );
36 } );
37
38 this.server.respond( function ( request ) {
39 request.respond( 200, { 'Content-Type': 'application/json' },
40 '{ "error": { "code": "unknown_action" } }'
41 );
42 } );
43 } );
44
45 QUnit.test( 'FormData support', function ( assert ) {
46 QUnit.expect( 2 );
47
48 var api = new mw.Api();
49
50 api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
51
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 } );
63
64 QUnit.test( 'Converting arrays to pipe-separated', function ( assert ) {
65 QUnit.expect( 1 );
66
67 var api = new mw.Api();
68 api.get( { test: [ 'foo', 'bar', 'baz' ] } );
69
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 } );
75
76 QUnit.test( 'getToken( pre-populated )', function ( assert ) {
77 QUnit.expect( 2 );
78
79 var api = new mw.Api();
80
81 // Get editToken for local wiki, this should not make
82 // a request as it should be retrieved from user.tokens.
83 // This means that this test must run before the #badToken test below.
84 api.getToken( 'edit' )
85 .done( function ( token ) {
86 assert.ok( token.length, 'Got a token' );
87 } )
88 .fail( function ( err ) {
89 assert.equal( '', err, 'API error' );
90 } );
91
92 assert.equal( this.server.requests.length, 0, 'Requests made' );
93 } );
94
95 QUnit.test( 'badToken()', function ( assert ) {
96 QUnit.expect( 2 );
97
98 var api = new mw.Api();
99
100 // Clear the default cached token
101 api.badToken( 'edit' );
102
103 api.getToken( 'edit' )
104 .done( function ( token ) {
105 assert.equal( token, '0123abc', 'Got a non-cached token' );
106 } )
107 .fail( function ( err ) {
108 assert.equal( '', err, 'API error' );
109 } );
110
111 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
112 '{ "tokens": { "edittoken": "0123abc" } }'
113 );
114
115 assert.equal( this.server.requests.length, 1, 'Requests made' );
116 } );
117
118 QUnit.test( 'getToken()', function ( assert ) {
119 QUnit.expect( 5 );
120
121 var test = this,
122 api = new mw.Api();
123
124 // Get a token of a type that isn't prepopulated by user.tokens.
125 // Could use "block" or "delete" here, but those could in theory
126 // be added to user.tokens, use a fake one instead.
127 api.getToken( 'testaction' )
128 .done( function ( token ) {
129 assert.ok( token.length, 'Got testaction token' );
130 } )
131 .fail( function ( err ) {
132 assert.equal( err, '', 'API error' );
133 } );
134 api.getToken( 'testaction' )
135 .done( function ( token ) {
136 assert.ok( token.length, 'Got testaction token (cached)' );
137 } )
138 .fail( function ( err ) {
139 assert.equal( err, '', 'API error' );
140 } );
141
142 // Don't cache error (bug 65268)
143 api.getToken( 'testaction2' )
144 .fail( function ( err ) {
145 assert.equal( err, 'bite-me', 'Expected error' );
146 } )
147 .always( function () {
148 // Make this request after the first one has finished.
149 // If we make it simultaneously we still want it to share
150 // the cache, but as soon as it is fulfilled as error we
151 // reject it so that the next one tries fresh.
152 api.getToken( 'testaction2' )
153 .done( function ( token ) {
154 assert.ok( token.length, 'Got testaction2 token (error was not be cached)' );
155 } )
156 .fail( function ( err ) {
157 assert.equal( err, '', 'API error' );
158 } );
159
160 assert.equal( test.server.requests.length, 3, 'Requests made' );
161
162 test.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
163 '{ "tokens": { "testaction2token": "0123abc" } }'
164 );
165 } );
166
167 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
168 '{ "tokens": { "testactiontoken": "0123abc" } }'
169 );
170
171 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
172 '{ "error": { "code": "bite-me", "info": "Smite me, O Mighty Smiter" } }'
173 );
174 } );
175
176 QUnit.test( 'postWithToken( tokenType, params )', function ( assert ) {
177 QUnit.expect( 1 );
178
179 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
180
181 // - Requests token
182 // - Performs action=example
183 api.postWithToken( 'testsimpletoken', { action: 'example', key: 'foo' } )
184 .done( function ( data ) {
185 assert.deepEqual( data, { example: { foo: 'quux' } } );
186 } );
187
188 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
189 '{ "tokens": { "testsimpletokentoken": "a-bad-token" } }'
190 );
191
192 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
193 '{ "example": { "foo": "quux" } }'
194 );
195 } );
196
197 QUnit.test( 'postWithToken( tokenType, params with assert )', function ( assert ) {
198 QUnit.expect( 2 );
199
200 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
201
202 api.postWithToken( 'testasserttoken', { action: 'example', key: 'foo', assert: 'user' } )
203 .fail( function ( errorCode ) {
204 assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
205 } );
206
207 assert.equal( this.server.requests.length, 1, 'Request for token made' );
208 this.server.respondWith( /assert=user/, function ( request ) {
209 request.respond(
210 200,
211 { 'Content-Type': 'application/json' },
212 '{ "error": { "code": "assertuserfailed", "info": "Assertion failed" } }'
213 );
214 } );
215
216 this.server.respond();
217 } );
218
219 QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
220 QUnit.expect( 3 );
221
222 var api = new mw.Api();
223
224 api.postWithToken(
225 'edit',
226 {
227 action: 'example'
228 },
229 {
230 headers: {
231 'X-Foo': 'Bar'
232 }
233 }
234 );
235
236 api.postWithToken(
237 'edit',
238 {
239 action: 'example'
240 },
241 function () {
242 assert.ok( false, 'This parameter cannot be a callback' );
243 }
244 )
245 .always( function ( data ) {
246 assert.equal( data.example, 'quux' );
247 } );
248
249 assert.equal( this.server.requests.length, 2, 'Request made' );
250 assert.equal( this.server.requests[0].requestHeaders['X-Foo'], 'Bar', 'Header sent' );
251
252 this.server.respond( function ( request ) {
253 request.respond( 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' );
254 } );
255 } );
256
257 QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
258 QUnit.expect( 1 );
259
260 var api = new mw.Api();
261
262 // - Request: token
263 // - Request: action=example -> badtoken error
264 // - Request: new token
265 // - Request: action=example
266 api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
267 .done( function ( data ) {
268 assert.deepEqual( data, { example: { foo: 'quux' } } );
269 } );
270
271 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
272 '{ "tokens": { "testbadtokentoken": "a-bad-token" } }'
273 );
274
275 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
276 '{ "error": { "code": "badtoken" } }'
277 );
278
279 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
280 '{ "tokens": { "testbadtokentoken": "a-good-token" } }'
281 );
282
283 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
284 '{ "example": { "foo": "quux" } }'
285 );
286
287 } );
288
289 QUnit.test( 'postWithToken() - badtoken-cached', function ( assert ) {
290 QUnit.expect( 2 );
291
292 var api = new mw.Api();
293
294 // - Request: token
295 // - Request: action=example
296 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'foo' } )
297 .done( function ( data ) {
298 assert.deepEqual( data, { example: { foo: 'quux' } } );
299 } );
300
301 // - Cache: Try previously cached token
302 // - Request: action=example -> badtoken error
303 // - Request: new token
304 // - Request: action=example
305 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'bar' } )
306 .done( function ( data ) {
307 assert.deepEqual( data, { example: { bar: 'quux' } } );
308 } );
309
310 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
311 '{ "tokens": { "testbadtokencachetoken": "a-good-token-once" } }'
312 );
313
314 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
315 '{ "example": { "foo": "quux" } }'
316 );
317
318 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
319 '{ "error": { "code": "badtoken" } }'
320 );
321
322 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
323 '{ "tokens": { "testbadtokencachetoken": "a-good-new-token" } }'
324 );
325
326 this.server.requests[4].respond( 200, { 'Content-Type': 'application/json' },
327 '{ "example": { "bar": "quux" } }'
328 );
329
330 } );
331
332 }( mediaWiki ) );