Merge "Add support for Argon2 password hashing"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.api / mediawiki.api.options.test.js
1 ( function () {
2 QUnit.module( 'mediawiki.api.options', QUnit.newMwEnvironment( {
3 config: {
4 wgUserName: 'Foo'
5 },
6 setup: function () {
7 this.server = this.sandbox.useFakeServer();
8 this.server.respondImmediately = true;
9 }
10 } ) );
11
12 QUnit.test( 'saveOption', function ( assert ) {
13 var api = new mw.Api(),
14 stub = this.sandbox.stub( mw.Api.prototype, 'saveOptions' );
15
16 api.saveOption( 'foo', 'bar' );
17
18 assert.ok( stub.calledOnce, '#saveOptions called once' );
19 assert.deepEqual( stub.getCall( 0 ).args, [ { foo: 'bar' } ], '#saveOptions called correctly' );
20 } );
21
22 QUnit.test( 'saveOptions without Unit Separator', function ( assert ) {
23 var api = new mw.Api( { useUS: false } );
24
25 // We need to respond to the request for token first, otherwise the other requests won't be sent
26 // until after the server.respond call, which confuses sinon terribly. This sucks a lot.
27 api.getToken( 'options' );
28 this.server.respond(
29 /meta=tokens&type=csrf/,
30 [ 200, { 'Content-Type': 'application/json' },
31 '{ "query": { "tokens": { "csrftoken": "+\\\\" } } }' ]
32 );
33
34 // Requests are POST, match requestBody instead of url
35 this.server.respond( function ( request ) {
36 if ( [
37 // simple
38 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
39 // two options
40 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
41 // not bundleable
42 'action=options&format=json&formatversion=2&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C',
43 'action=options&format=json&formatversion=2&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C',
44 'action=options&format=json&formatversion=2&change=baz%3Dquux&token=%2B%5C',
45 // reset an option
46 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
47 // reset an option, not bundleable
48 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
49 ].indexOf( request.requestBody ) !== -1 ) {
50 assert.ok( true, 'Repond to ' + request.requestBody );
51 request.respond( 200, { 'Content-Type': 'application/json' },
52 '{ "options": "success" }' );
53 } else {
54 assert.ok( false, 'Unexpected request: ' + request.requestBody );
55 }
56 } );
57
58 return QUnit.whenPromisesComplete(
59 api.saveOptions( {} ).then( function () {
60 assert.ok( true, 'Request completed: empty case' );
61 } ),
62 api.saveOptions( { foo: 'bar' } ).then( function () {
63 assert.ok( true, 'Request completed: simple' );
64 } ),
65 api.saveOptions( { foo: 'bar', baz: 'quux' } ).then( function () {
66 assert.ok( true, 'Request completed: two options' );
67 } ),
68 api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).then( function () {
69 assert.ok( true, 'Request completed: not bundleable' );
70 } ),
71 api.saveOptions( { foo: null } ).then( function () {
72 assert.ok( true, 'Request completed: reset an option' );
73 } ),
74 api.saveOptions( { 'foo|bar=quux': null } ).then( function () {
75 assert.ok( true, 'Request completed: reset an option, not bundleable' );
76 } )
77 );
78 } );
79
80 QUnit.test( 'saveOptions with Unit Separator', function ( assert ) {
81 var api = new mw.Api( { useUS: true } );
82
83 // We need to respond to the request for token first, otherwise the other requests won't be sent
84 // until after the server.respond call, which confuses sinon terribly. This sucks a lot.
85 api.getToken( 'options' );
86 this.server.respond(
87 /meta=tokens&type=csrf/,
88 [ 200, { 'Content-Type': 'application/json' },
89 '{ "query": { "tokens": { "csrftoken": "+\\\\" } } }' ]
90 );
91
92 // Requests are POST, match requestBody instead of url
93 this.server.respond( function ( request ) {
94 if ( [
95 // simple
96 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
97 // two options
98 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
99 // bundleable with unit separator
100 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc%1Fbaz%3Dquux&token=%2B%5C',
101 // not bundleable with unit separator
102 'action=options&format=json&formatversion=2&optionname=baz%3Dbaz&optionvalue=quux&token=%2B%5C',
103 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc&token=%2B%5C',
104 // reset an option
105 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
106 // reset an option, not bundleable
107 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
108 ].indexOf( request.requestBody ) !== -1 ) {
109 assert.ok( true, 'Repond to ' + request.requestBody );
110 request.respond(
111 200,
112 { 'Content-Type': 'application/json' },
113 '{ "options": "success" }'
114 );
115 } else {
116 assert.ok( false, 'Unexpected request: ' + request.requestBody );
117 }
118 } );
119
120 return QUnit.whenPromisesComplete(
121 api.saveOptions( {} ).done( function () {
122 assert.ok( true, 'Request completed: empty case' );
123 } ),
124 api.saveOptions( { foo: 'bar' } ).done( function () {
125 assert.ok( true, 'Request completed: simple' );
126 } ),
127 api.saveOptions( { foo: 'bar', baz: 'quux' } ).done( function () {
128 assert.ok( true, 'Request completed: two options' );
129 } ),
130 api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).done( function () {
131 assert.ok( true, 'Request completed: bundleable with unit separator' );
132 } ),
133 api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', 'baz=baz': 'quux' } ).done( function () {
134 assert.ok( true, 'Request completed: not bundleable with unit separator' );
135 } ),
136 api.saveOptions( { foo: null } ).done( function () {
137 assert.ok( true, 'Request completed: reset an option' );
138 } ),
139 api.saveOptions( { 'foo|bar=quux': null } ).done( function () {
140 assert.ok( true, 'Request completed: reset an option, not bundleable' );
141 } )
142 );
143 } );
144
145 QUnit.test( 'saveOptions (anonymous)', function ( assert ) {
146 var promise, test = this;
147
148 mw.config.set( 'wgUserName', null );
149 promise = new mw.Api().saveOptions( { foo: 'bar' } );
150
151 assert.rejects( promise, /notloggedin/, 'Can not save options while not logged in' );
152
153 return promise
154 .catch( function () {
155 return $.Deferred().resolve();
156 } )
157 .then( function () {
158 assert.strictEqual( test.server.requests.length, 0, 'No requests made' );
159 } );
160 } );
161 }() );