Merge "Test what happens with Konqueror 3.5 against the blacklist"
[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( 'Deprecated callback methods', function ( assert ) {
65 QUnit.expect( 3 );
66
67 var api = new mw.Api();
68
69 this.suppressWarnings();
70
71 api.get( {}, function () {
72 assert.ok( true, 'Function argument treated as success callback.' );
73 } );
74
75 api.get( {}, {
76 ok: function () {
77 assert.ok( true, '"ok" property treated as success callback.' );
78 }
79 } );
80
81 api.get( { action: 'doesntexist' }, {
82 err: function () {
83 assert.ok( true, '"err" property treated as error callback.' );
84 }
85 } );
86
87 this.restoreWarnings();
88
89 this.server.respondWith( /action=query/, function ( request ) {
90 request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
91 } );
92
93 this.server.respondWith( /action=doesntexist/, function ( request ) {
94 request.respond( 200, { 'Content-Type': 'application/json' },
95 '{ "error": { "code": "unknown_action" } }'
96 );
97 } );
98
99 this.server.respond();
100 } );
101
102 QUnit.test( 'getToken( pre-populated )', function ( assert ) {
103 QUnit.expect( 2 );
104
105 var api = new mw.Api();
106
107 // Get editToken for local wiki, this should not make
108 // a request as it should be retrieved from user.tokens.
109 api.getToken( 'edit' )
110 .done( function ( token ) {
111 assert.ok( token.length, 'Got a token' );
112 } )
113 .fail( function ( err ) {
114 assert.equal( '', err, 'API error' );
115 } );
116
117 assert.equal( this.server.requests.length, 0, 'Requests made' );
118 } );
119
120 QUnit.test( 'getToken()', function ( assert ) {
121 QUnit.expect( 5 );
122
123 var test = this,
124 api = new mw.Api();
125
126 // Get a token of a type that isn't prepopulated by user.tokens.
127 // Could use "block" or "delete" here, but those could in theory
128 // be added to user.tokens, use a fake one instead.
129 api.getToken( 'testaction' )
130 .done( function ( token ) {
131 assert.ok( token.length, 'Got testaction token' );
132 } )
133 .fail( function ( err ) {
134 assert.equal( err, '', 'API error' );
135 } );
136 api.getToken( 'testaction' )
137 .done( function ( token ) {
138 assert.ok( token.length, 'Got testaction token (cached)' );
139 } )
140 .fail( function ( err ) {
141 assert.equal( err, '', 'API error' );
142 } );
143
144 // Don't cache error (bug 65268)
145 api.getToken( 'testaction2' )
146 .fail( function ( err ) {
147 assert.equal( err, 'bite-me', 'Expected error' );
148 } )
149 .always( function () {
150 // Make this request after the first one has finished.
151 // If we make it simultaneously we still want it to share
152 // the cache, but as soon as it is fulfilled as error we
153 // reject it so that the next one tries fresh.
154 api.getToken( 'testaction2' )
155 .done( function ( token ) {
156 assert.ok( token.length, 'Got testaction2 token (error was not be cached)' );
157 } )
158 .fail( function ( err ) {
159 assert.equal( err, '', 'API error' );
160 } );
161
162 assert.equal( test.server.requests.length, 3, 'Requests made' );
163
164 test.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
165 '{ "tokens": { "testaction2token": "0123abc" } }'
166 );
167 } );
168
169 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
170 '{ "tokens": { "testactiontoken": "0123abc" } }'
171 );
172
173 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
174 '{ "error": { "code": "bite-me", "info": "Smite me, O Mighty Smiter" } }'
175 );
176 } );
177
178 QUnit.test( 'postWithToken( tokenType, params )', function ( assert ) {
179 QUnit.expect( 1 );
180
181 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
182
183 // - Requests token
184 // - Performs action=example
185 api.postWithToken( 'testsimpletoken', { action: 'example', key: 'foo' } )
186 .done( function ( data ) {
187 assert.deepEqual( data, { example: { foo: 'quux' } } );
188 } );
189
190 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
191 '{ "tokens": { "testsimpletokentoken": "a-bad-token" } }'
192 );
193
194 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
195 '{ "example": { "foo": "quux" } }'
196 );
197 } );
198
199 QUnit.test( 'postWithToken( tokenType, params with assert )', function ( assert ) {
200 QUnit.expect( 2 );
201
202 var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
203
204 api.postWithToken( 'testasserttoken', { action: 'example', key: 'foo', assert: 'user' } )
205 .fail( function ( errorCode ) {
206 assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
207 } );
208
209 assert.equal( this.server.requests.length, 1, 'Request for token made' );
210 this.server.respondWith( /assert=user/, function ( request ) {
211 request.respond(
212 200,
213 { 'Content-Type': 'application/json' },
214 '{ "error": { "code": "assertuserfailed", "info": "Assertion failed" } }'
215 );
216 } );
217
218 this.server.respond();
219 } );
220
221 QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
222 QUnit.expect( 3 );
223
224 var api = new mw.Api();
225
226 api.postWithToken(
227 'edit',
228 {
229 action: 'example'
230 },
231 {
232 headers: {
233 'X-Foo': 'Bar'
234 }
235 }
236 );
237
238 api.postWithToken(
239 'edit',
240 {
241 action: 'example'
242 },
243 function () {
244 assert.ok( false, 'This parameter cannot be a callback' );
245 }
246 )
247 .always( function ( data ) {
248 assert.equal( data.example, 'quux' );
249 } );
250
251 assert.equal( this.server.requests.length, 2, 'Request made' );
252 assert.equal( this.server.requests[0].requestHeaders['X-Foo'], 'Bar', 'Header sent' );
253
254 this.server.respond( function ( request ) {
255 request.respond( 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' );
256 } );
257 } );
258
259 QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
260 QUnit.expect( 1 );
261
262 var api = new mw.Api();
263
264 // - Request: token
265 // - Request: action=example -> badtoken error
266 // - Request: new token
267 // - Request: action=example
268 api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
269 .done( function ( data ) {
270 assert.deepEqual( data, { example: { foo: 'quux' } } );
271 } );
272
273 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
274 '{ "tokens": { "testbadtokentoken": "a-bad-token" } }'
275 );
276
277 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
278 '{ "error": { "code": "badtoken" } }'
279 );
280
281 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
282 '{ "tokens": { "testbadtokentoken": "a-good-token" } }'
283 );
284
285 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
286 '{ "example": { "foo": "quux" } }'
287 );
288
289 } );
290
291 QUnit.test( 'postWithToken() - badtoken-cached', function ( assert ) {
292 QUnit.expect( 2 );
293
294 var api = new mw.Api();
295
296 // - Request: token
297 // - Request: action=example
298 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'foo' } )
299 .done( function ( data ) {
300 assert.deepEqual( data, { example: { foo: 'quux' } } );
301 } );
302
303 // - Cache: Try previously cached token
304 // - Request: action=example -> badtoken error
305 // - Request: new token
306 // - Request: action=example
307 api.postWithToken( 'testbadtokencache', { action: 'example', key: 'bar' } )
308 .done( function ( data ) {
309 assert.deepEqual( data, { example: { bar: 'quux' } } );
310 } );
311
312 this.server.requests[0].respond( 200, { 'Content-Type': 'application/json' },
313 '{ "tokens": { "testbadtokencachetoken": "a-good-token-once" } }'
314 );
315
316 this.server.requests[1].respond( 200, { 'Content-Type': 'application/json' },
317 '{ "example": { "foo": "quux" } }'
318 );
319
320 this.server.requests[2].respond( 200, { 'Content-Type': 'application/json' },
321 '{ "error": { "code": "badtoken" } }'
322 );
323
324 this.server.requests[3].respond( 200, { 'Content-Type': 'application/json' },
325 '{ "tokens": { "testbadtokencachetoken": "a-good-new-token" } }'
326 );
327
328 this.server.requests[4].respond( 200, { 'Content-Type': 'application/json' },
329 '{ "example": { "bar": "quux" } }'
330 );
331
332 } );
333
334 }( mediaWiki ) );