Merge "mw.rcfilters.ui.SaveFiltersPopupButtonWidget: Remove pointless option"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.rcfilters / UriProcessor.test.js
1 /* eslint-disable camelcase */
2 /* eslint no-underscore-dangle: "off" */
3 ( function ( mw, $ ) {
4 var mockFilterStructure = [ {
5 name: 'group1',
6 title: 'Group 1',
7 type: 'send_unselected_if_any',
8 filters: [
9 { name: 'filter1', cssClass: 'filter1class', default: true },
10 { name: 'filter2', cssClass: 'filter2class' }
11 ]
12 }, {
13 name: 'group2',
14 title: 'Group 2',
15 type: 'send_unselected_if_any',
16 filters: [
17 { name: 'filter3', cssClass: 'filter3class' },
18 { name: 'filter4', cssClass: 'filter4class', default: true }
19 ]
20 }, {
21 name: 'group3',
22 title: 'Group 3',
23 type: 'string_options',
24 filters: [
25 { name: 'filter5', cssClass: 'filter5class' },
26 { name: 'filter6' } // Not supporting highlights
27 ]
28 }, {
29 name: 'group4',
30 title: 'Group 4',
31 type: 'boolean',
32 sticky: true,
33 filters: [
34 { name: 'stickyFilter7', cssClass: 'filter7class' },
35 { name: 'stickyFilter8', cssClass: 'filter8class' }
36 ]
37 } ],
38 minimalDefaultParams = {
39 filter1: '1',
40 filter4: '1'
41 };
42
43 QUnit.module( 'mediawiki.rcfilters - UriProcessor' );
44
45 QUnit.test( 'getVersion', function ( assert ) {
46 var uriProcessor = new mw.rcfilters.UriProcessor( new mw.rcfilters.dm.FiltersViewModel() );
47
48 assert.ok(
49 uriProcessor.getVersion( { param1: 'foo', urlversion: '2' } ),
50 2,
51 'Retrieving the version from the URI query'
52 );
53
54 assert.ok(
55 uriProcessor.getVersion( { param1: 'foo' } ),
56 1,
57 'Getting version 1 if no version is specified'
58 );
59 } );
60
61 QUnit.test( 'getUpdatedUri', function ( assert ) {
62 var uriProcessor,
63 filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
64 makeUri = function ( queryParams ) {
65 var uri = new mw.Uri();
66 uri.query = queryParams;
67 return uri;
68 };
69
70 filtersModel.initializeFilters( mockFilterStructure );
71 uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
72
73 assert.deepEqual(
74 ( uriProcessor.getUpdatedUri( makeUri( {} ) ) ).query,
75 { urlversion: '2' },
76 'Empty model state with empty uri state, assumes the given uri is already normalized, and adds urlversion=2'
77 );
78
79 assert.deepEqual(
80 ( uriProcessor.getUpdatedUri( makeUri( { foo: 'bar' } ) ) ).query,
81 { urlversion: '2', foo: 'bar' },
82 'Empty model state with unrecognized params retains unrecognized params'
83 );
84
85 // Update the model
86 filtersModel.toggleFiltersSelected( {
87 group1__filter1: true, // Param: filter2: '1'
88 group3__filter5: true // Param: group3: 'filter5'
89 } );
90
91 assert.deepEqual(
92 ( uriProcessor.getUpdatedUri( makeUri( {} ) ) ).query,
93 { urlversion: '2', filter2: '1', group3: 'filter5' },
94 'Model state is reflected in the updated URI'
95 );
96
97 assert.deepEqual(
98 ( uriProcessor.getUpdatedUri( makeUri( { foo: 'bar' } ) ) ).query,
99 { urlversion: '2', filter2: '1', group3: 'filter5', foo: 'bar' },
100 'Model state is reflected in the updated URI with existing uri params'
101 );
102 } );
103
104 QUnit.test( 'updateModelBasedOnQuery', function ( assert ) {
105 var uriProcessor,
106 filtersModel = new mw.rcfilters.dm.FiltersViewModel();
107
108 filtersModel.initializeFilters( mockFilterStructure );
109 uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
110
111 uriProcessor.updateModelBasedOnQuery( {} );
112 assert.deepEqual(
113 filtersModel.getCurrentParameterState(),
114 minimalDefaultParams,
115 'Version 1: Empty url query sets model to defaults'
116 );
117
118 uriProcessor.updateModelBasedOnQuery( { urlversion: '2' } );
119 assert.deepEqual(
120 filtersModel.getCurrentParameterState(),
121 {},
122 'Version 2: Empty url query sets model to all-false'
123 );
124
125 uriProcessor.updateModelBasedOnQuery( { filter1: '1', urlversion: '2' } );
126 assert.deepEqual(
127 filtersModel.getCurrentParameterState(),
128 $.extend( true, {}, { filter1: '1' } ),
129 'Parameters in Uri query set parameter value in the model'
130 );
131 } );
132
133 QUnit.test( 'isNewState', function ( assert ) {
134 var uriProcessor,
135 filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
136 cases = [
137 {
138 states: {
139 curr: {},
140 new: {}
141 },
142 result: false,
143 message: 'Empty objects are not new state.'
144 },
145 {
146 states: {
147 curr: { filter1: '1' },
148 new: { filter1: '0' }
149 },
150 result: true,
151 message: 'Nulified parameter is a new state'
152 },
153 {
154 states: {
155 curr: { filter1: '1' },
156 new: { filter1: '1', filter2: '1' }
157 },
158 result: true,
159 message: 'Added parameters are a new state'
160 },
161 {
162 states: {
163 curr: { filter1: '1' },
164 new: { filter1: '1', filter2: '0' }
165 },
166 result: false,
167 message: 'Added null parameters are not a new state (normalizing equals old state)'
168 },
169 {
170 states: {
171 curr: { filter1: '1' },
172 new: { filter1: '1', foo: 'bar' }
173 },
174 result: true,
175 message: 'Added unrecognized parameters are a new state'
176 },
177 {
178 states: {
179 curr: { filter1: '1', foo: 'bar' },
180 new: { filter1: '1', foo: 'baz' }
181 },
182 result: true,
183 message: 'Changed unrecognized parameters are a new state'
184 }
185 ];
186
187 filtersModel.initializeFilters( mockFilterStructure );
188 uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
189
190 cases.forEach( function ( testCase ) {
191 assert.equal(
192 uriProcessor.isNewState( testCase.states.curr, testCase.states.new ),
193 testCase.result,
194 testCase.message
195 );
196 } );
197 } );
198
199 QUnit.test( 'doesQueryContainRecognizedParams', function ( assert ) {
200 var uriProcessor,
201 filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
202 cases = [
203 {
204 query: {},
205 result: false,
206 message: 'Empty query is not valid for load.'
207 },
208 {
209 query: { highlight: '1' },
210 result: false,
211 message: 'Highlight state alone is not valid for load'
212 },
213 {
214 query: { urlversion: '2' },
215 result: true,
216 message: 'urlversion=2 state alone is valid for load as an empty state'
217 },
218 {
219 query: { filter1: '1', foo: 'bar' },
220 result: true,
221 message: 'Existence of recognized parameters makes the query valid for load'
222 },
223 {
224 query: { foo: 'bar', debug: true },
225 result: false,
226 message: 'Only unrecognized parameters makes the query invalid for load'
227 }
228 ];
229
230 filtersModel.initializeFilters( mockFilterStructure );
231 uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
232
233 cases.forEach( function ( testCase ) {
234 assert.equal(
235 uriProcessor.doesQueryContainRecognizedParams( testCase.query ),
236 testCase.result,
237 testCase.message
238 );
239 } );
240 } );
241
242 QUnit.test( '_getNormalizedQueryParams', function ( assert ) {
243 var uriProcessor,
244 filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
245 cases = [
246 {
247 query: {},
248 result: $.extend( true, { urlversion: '2' }, minimalDefaultParams ),
249 message: 'Empty query returns defaults (urlversion 1).'
250 },
251 {
252 query: { urlversion: '2' },
253 result: { urlversion: '2' },
254 message: 'Empty query returns empty (urlversion 2)'
255 },
256 {
257 query: { filter1: '0' },
258 result: { urlversion: '2', filter4: '1' },
259 message: 'urlversion 1 returns query that overrides defaults'
260 },
261 {
262 query: { filter3: '1' },
263 result: { urlversion: '2', filter1: '1', filter4: '1', filter3: '1' },
264 message: 'urlversion 1 with an extra param value returns query that is joined with defaults'
265 }
266 ];
267
268 filtersModel.initializeFilters( mockFilterStructure );
269 uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
270
271 cases.forEach( function ( testCase ) {
272 assert.deepEqual(
273 uriProcessor._getNormalizedQueryParams( testCase.query ),
274 testCase.result,
275 testCase.message
276 );
277 } );
278 } );
279
280 QUnit.test( '_normalizeTargetInUri', function ( assert ) {
281 var uriProcessor = new mw.rcfilters.UriProcessor( null ),
282 cases = [
283 {
284 input: 'http://host/wiki/Special:RecentChangesLinked/Moai',
285 output: 'http://host/wiki/Special:RecentChangesLinked?target=Moai',
286 message: 'Target as subpage in path'
287 },
288 {
289 input: 'http://host/wiki/Special:RecentChangesLinked/Château',
290 output: 'http://host/wiki/Special:RecentChangesLinked?target=Château',
291 message: 'Target as subpage in path with special characters'
292 },
293 {
294 input: 'http://host/wiki/Special:RecentChangesLinked/Moai/Sub1',
295 output: 'http://host/wiki/Special:RecentChangesLinked?target=Moai/Sub1',
296 message: 'Target as subpage also has a subpage'
297 },
298 {
299 input: 'http://host/wiki/Special:RecentChangesLinked/Category:Foo',
300 output: 'http://host/wiki/Special:RecentChangesLinked?target=Category:Foo',
301 message: 'Target as subpage in path (with namespace)'
302 },
303 {
304 input: 'http://host/wiki/Special:RecentChangesLinked/Category:Foo/Bar',
305 output: 'http://host/wiki/Special:RecentChangesLinked?target=Category:Foo/Bar',
306 message: 'Target as subpage in path also has a subpage (with namespace)'
307 },
308 {
309 input: 'http://host/w/index.php?title=Special:RecentChangesLinked/Moai',
310 output: 'http://host/w/index.php?title=Special:RecentChangesLinked&target=Moai',
311 message: 'Target as subpage in title param'
312 },
313 {
314 input: 'http://host/w/index.php?title=Special:RecentChangesLinked/Moai/Sub1',
315 output: 'http://host/w/index.php?title=Special:RecentChangesLinked&target=Moai/Sub1',
316 message: 'Target as subpage in title param also has a subpage'
317 },
318 {
319 input: 'http://host/w/index.php?title=Special:RecentChangesLinked/Category:Foo/Bar',
320 output: 'http://host/w/index.php?title=Special:RecentChangesLinked&target=Category:Foo/Bar',
321 message: 'Target as subpage in title param also has a subpage (with namespace)'
322 },
323 {
324 input: 'http://host/wiki/Special:Watchlist',
325 output: 'http://host/wiki/Special:Watchlist',
326 message: 'No target specified'
327 }
328 ];
329
330 cases.forEach( function ( testCase ) {
331 assert.equal(
332 uriProcessor._normalizeTargetInUri( new mw.Uri( testCase.input ) ).toString(),
333 new mw.Uri( testCase.output ).toString(),
334 testCase.message
335 );
336 } );
337 } );
338
339 }( mediaWiki, jQuery ) );