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