Merge "resourceloader: Introduce metric for backend response timing"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.rcfilters / dm.SavedQueriesModel.test.js
1 /* eslint-disable camelcase */
2 ( function ( mw ) {
3 var filterDefinition = [ {
4 name: 'group1',
5 type: 'send_unselected_if_any',
6 filters: [
7 // Note: The fact filter2 is default means that in the
8 // filter representation, filter1 and filter3 are 'true'
9 { name: 'filter1', cssClass: 'filter1class' },
10 { name: 'filter2', cssClass: 'filter2class', default: true },
11 { name: 'filter3', cssClass: 'filter3class' }
12 ]
13 }, {
14 name: 'group2',
15 type: 'string_options',
16 separator: ',',
17 filters: [
18 { name: 'filter4', cssClass: 'filter4class' },
19 { name: 'filter5' }, // NOTE: Not supporting highlights!
20 { name: 'filter6', cssClass: 'filter6class' }
21 ]
22 }, {
23 name: 'group3',
24 type: 'boolean',
25 isSticky: true,
26 filters: [
27 { name: 'group3option1', cssClass: 'filter1class' },
28 { name: 'group3option2', cssClass: 'filter1class' },
29 { name: 'group3option3', cssClass: 'filter1class' }
30 ]
31 }, {
32 // Copy of the way the controller defines invert
33 // to check whether the conversion works
34 name: 'invertGroup',
35 type: 'boolean',
36 hidden: true,
37 filters: [ {
38 name: 'invert',
39 default: '0'
40 } ]
41 } ],
42 queriesFilterRepresentation = {
43 queries: {
44 1234: {
45 label: 'Item converted',
46 data: {
47 filters: {
48 // - This value is true, but the original filter-representation
49 // of the saved queries ran against defaults. Since filter1 was
50 // set as default in the definition, the value would actually
51 // not appear in the representation itself.
52 // It is considered 'true', though, and should appear in the
53 // converted result in its parameter representation.
54 // >> group1__filter1: true,
55 // - The reverse is true for filter3. Filter3 is set as default
56 // but we don't want it in this representation of the saved query.
57 // Since the filter representation ran against default values,
58 // it will appear as 'false' value in this representation explicitly
59 // and the resulting parameter representation should have that
60 // as the result as well
61 group1__filter3: false,
62 group2__filter4: true,
63 group3__group3option1: true
64 },
65 highlights: {
66 highlight: true,
67 group1__filter1: 'c5',
68 group3__group3option1: 'c1'
69 },
70 invert: true
71 }
72 }
73 }
74 },
75 queriesParamRepresentation = {
76 version: '2',
77 queries: {
78 1234: {
79 label: 'Item converted',
80 data: {
81 params: {
82 // filter1 is 'true' so filter2 and filter3 are both '1'
83 // in param representation
84 filter2: '1', filter3: '1',
85 // Group type string_options
86 group2: 'filter4',
87 // Note - Group3 is sticky, so it won't show in output
88 // highlight toggle
89 highlight: '1'
90 },
91 highlights: {
92 group1__filter1_color: 'c5',
93 group3__group3option1_color: 'c1'
94 }
95 }
96 }
97 }
98 };
99
100 QUnit.module( 'mediawiki.rcfilters - SavedQueriesModel' );
101
102 QUnit.test( 'Initializing queries', function ( assert ) {
103 var filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
104 queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ),
105 exampleQueryStructure = {
106 version: '2',
107 default: '1234',
108 queries: {
109 1234: {
110 label: 'Query 1234',
111 data: {
112 params: {
113 filter2: '1'
114 },
115 highlights: {
116 group1__filter3_color: 'c2'
117 }
118 }
119 }
120 }
121 },
122 cases = [
123 {
124 input: {},
125 finalState: { version: '2', queries: {} },
126 msg: 'Empty initial query structure results in base saved queries structure.'
127 },
128 {
129 input: $.extend( true, {}, exampleQueryStructure ),
130 finalState: $.extend( true, {}, exampleQueryStructure ),
131 msg: 'Initialization of given query structure does not corrupt the structure.'
132 },
133 {
134 // Converting from old structure
135 input: $.extend( true, {}, queriesFilterRepresentation ),
136 finalState: $.extend( true, {}, queriesParamRepresentation ),
137 msg: 'Conversion from filter representation to parameters retains data.'
138 },
139 {
140 // Converting from old structure
141 input: $.extend( true, {}, queriesFilterRepresentation, { queries: { 1234: { data: {
142 filters: {
143 // Entire group true: normalize params
144 filter1: true,
145 filter2: true,
146 filter3: true
147 },
148 highlights: {
149 filter3: null // Get rid of empty highlight
150 }
151 } } } } ),
152 finalState: $.extend( true, {}, queriesParamRepresentation ),
153 msg: 'Conversion from filter representation to parameters normalizes params and highlights.'
154 },
155 {
156 // Converting from old structure with default
157 input: $.extend( true, { default: '1234' }, queriesFilterRepresentation ),
158 finalState: $.extend( true, { default: '1234' }, queriesParamRepresentation ),
159 msg: 'Conversion from filter representation to parameters, with default set up, retains data.'
160 },
161 {
162 // New structure
163 input: $.extend( true, {}, queriesParamRepresentation ),
164 finalState: $.extend( true, {}, queriesParamRepresentation ),
165 msg: 'Parameter representation retains its queries structure'
166 },
167 {
168 // Do not touch invalid color parameters from the initialization routine
169 // (Normalization, or "fixing" the query should only happen when we add new query or actively convert queries)
170 input: $.extend( true, { queries: { 1234: { data: { highlights: { group2__filter5_color: 'c2' } } } } }, exampleQueryStructure ),
171 finalState: $.extend( true, { queries: { 1234: { data: { highlights: { group2__filter5_color: 'c2' } } } } }, exampleQueryStructure ),
172 msg: 'Structure that contains invalid highlights remains the same in initialization'
173 }
174 ];
175
176 filtersModel.initializeFilters( filterDefinition );
177
178 cases.forEach( function ( testCase ) {
179 queriesModel.initialize( testCase.input );
180 assert.deepEqual(
181 queriesModel.getState(),
182 testCase.finalState,
183 testCase.msg
184 );
185 } );
186 } );
187
188 QUnit.test( 'Adding new queries', function ( assert ) {
189 var filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
190 queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ),
191 cases = [
192 {
193 methodParams: [
194 'label1', // Label
195 { // Data
196 filter1: '1',
197 filter2: '2',
198 group1__filter1_color: 'c2',
199 group1__filter3_color: 'c5'
200 },
201 true, // isDefault
202 '1234' // ID
203 ],
204 result: {
205 itemState: {
206 label: 'label1',
207 data: {
208 params: {
209 filter1: '1',
210 filter2: '2'
211 },
212 highlights: {
213 group1__filter1_color: 'c2',
214 group1__filter3_color: 'c5'
215 }
216 }
217 },
218 isDefault: true,
219 id: '1234'
220 },
221 msg: 'Given valid data is preserved.'
222 },
223 {
224 methodParams: [
225 'label2',
226 {
227 filter1: '1',
228 invert: '1',
229 filter15: '1', // Invalid filter - removed
230 filter2: '0', // Falsey value - removed
231 group1__filter1_color: 'c3',
232 foobar: 'w00t' // Unrecognized parameter - removed
233 }
234 ],
235 result: {
236 itemState: {
237 label: 'label2',
238 data: {
239 params: {
240 filter1: '1',
241 invert: '1'
242 },
243 highlights: {
244 group1__filter1_color: 'c3'
245 }
246 }
247 },
248 isDefault: false
249 },
250 msg: 'Given data with invalid filters and highlights is normalized'
251 }
252 ];
253
254 filtersModel.initializeFilters( filterDefinition );
255
256 // Start with an empty saved queries model
257 queriesModel.initialize( {} );
258
259 cases.forEach( function ( testCase ) {
260 var itemID = queriesModel.addNewQuery.apply( queriesModel, testCase.methodParams ),
261 item = queriesModel.getItemByID( itemID );
262
263 assert.deepEqual(
264 item.getState(),
265 testCase.result.itemState,
266 testCase.msg + ' (itemState)'
267 );
268
269 assert.equal(
270 item.isDefault(),
271 testCase.result.isDefault,
272 testCase.msg + ' (isDefault)'
273 );
274
275 if ( testCase.result.id !== undefined ) {
276 assert.equal(
277 item.getID(),
278 testCase.result.id,
279 testCase.msg + ' (item ID)'
280 );
281 }
282 } );
283 } );
284
285 QUnit.test( 'Manipulating queries', function ( assert ) {
286 var id1, id2, item1, matchingItem,
287 queriesStructure = {},
288 filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
289 queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel );
290
291 filtersModel.initializeFilters( filterDefinition );
292
293 // Start with an empty saved queries model
294 queriesModel.initialize( {} );
295
296 // Add items
297 id1 = queriesModel.addNewQuery(
298 'New query 1',
299 {
300 group2: 'filter5',
301 highlight: '1',
302 group1__filter1_color: 'c5',
303 group3__group3option1_color: 'c1'
304 }
305 );
306 id2 = queriesModel.addNewQuery(
307 'New query 2',
308 {
309 filter1: '1',
310 filter2: '1',
311 invert: '1'
312 }
313 );
314 item1 = queriesModel.getItemByID( id1 );
315
316 assert.equal(
317 item1.getID(),
318 id1,
319 'Item created and its data retained successfully'
320 );
321
322 // NOTE: All other methods that the item itself returns are
323 // tested in the dm.SavedQueryItemModel.test.js file
324
325 // Build the query structure we expect per item
326 queriesStructure[ id1 ] = {
327 label: 'New query 1',
328 data: {
329 params: {
330 group2: 'filter5',
331 highlight: '1'
332 },
333 highlights: {
334 group1__filter1_color: 'c5',
335 group3__group3option1_color: 'c1'
336 }
337 }
338 };
339 queriesStructure[ id2 ] = {
340 label: 'New query 2',
341 data: {
342 params: {
343 filter1: '1',
344 filter2: '1',
345 invert: '1'
346 },
347 highlights: {}
348 }
349 };
350
351 assert.deepEqual(
352 queriesModel.getState(),
353 {
354 version: '2',
355 queries: queriesStructure
356 },
357 'Full query represents current state of items'
358 );
359
360 // Add default
361 queriesModel.setDefault( id2 );
362
363 assert.deepEqual(
364 queriesModel.getState(),
365 {
366 version: '2',
367 default: id2,
368 queries: queriesStructure
369 },
370 'Setting default is reflected in queries state'
371 );
372
373 // Remove default
374 queriesModel.setDefault( null );
375
376 assert.deepEqual(
377 queriesModel.getState(),
378 {
379 version: '2',
380 queries: queriesStructure
381 },
382 'Removing default is reflected in queries state'
383 );
384
385 // Find matching query
386 matchingItem = queriesModel.findMatchingQuery(
387 {
388 highlight: '1',
389 group2: 'filter5',
390 group1__filter1_color: 'c5',
391 group3__group3option1_color: 'c1'
392 }
393 );
394 assert.deepEqual(
395 matchingItem.getID(),
396 id1,
397 'Finding matching item by identical state'
398 );
399
400 // Find matching query with 0-values (base state)
401 matchingItem = queriesModel.findMatchingQuery(
402 {
403 group2: 'filter5',
404 filter1: '0',
405 filter2: '0',
406 highlight: '1',
407 invert: '0',
408 group1__filter1_color: 'c5',
409 group3__group3option1_color: 'c1'
410 }
411 );
412 assert.deepEqual(
413 matchingItem.getID(),
414 id1,
415 'Finding matching item by "dirty" state with 0-base values'
416 );
417 } );
418 }( mediaWiki ) );