diff options
Diffstat (limited to 'www/wiki/tests/qunit/suites/resources/mediawiki.rcfilters/dm.SavedQueriesModel.test.js')
-rw-r--r-- | www/wiki/tests/qunit/suites/resources/mediawiki.rcfilters/dm.SavedQueriesModel.test.js | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/www/wiki/tests/qunit/suites/resources/mediawiki.rcfilters/dm.SavedQueriesModel.test.js b/www/wiki/tests/qunit/suites/resources/mediawiki.rcfilters/dm.SavedQueriesModel.test.js new file mode 100644 index 00000000..ed054bd7 --- /dev/null +++ b/www/wiki/tests/qunit/suites/resources/mediawiki.rcfilters/dm.SavedQueriesModel.test.js @@ -0,0 +1,520 @@ +/* eslint-disable camelcase */ +( function ( mw ) { + var filterDefinition = [ { + name: 'group1', + type: 'send_unselected_if_any', + filters: [ + // Note: The fact filter2 is default means that in the + // filter representation, filter1 and filter3 are 'true' + { name: 'filter1', cssClass: 'filter1class' }, + { name: 'filter2', cssClass: 'filter2class', default: true }, + { name: 'filter3', cssClass: 'filter3class' } + ] + }, { + name: 'group2', + type: 'string_options', + separator: ',', + filters: [ + { name: 'filter4', cssClass: 'filter4class' }, + { name: 'filter5' }, // NOTE: Not supporting highlights! + { name: 'filter6', cssClass: 'filter6class' } + ] + }, { + name: 'group3', + type: 'boolean', + sticky: true, + filters: [ + { name: 'group3option1', cssClass: 'filter1class' }, + { name: 'group3option2', cssClass: 'filter1class' }, + { name: 'group3option3', cssClass: 'filter1class' } + ] + }, { + // Copy of the way the controller defines invert + // to check whether the conversion works + name: 'invertGroup', + type: 'boolean', + hidden: true, + filters: [ { + name: 'invert', + default: '0' + } ] + } ], + queriesFilterRepresentation = { + queries: { + 1234: { + label: 'Item converted', + data: { + filters: { + // - This value is true, but the original filter-representation + // of the saved queries ran against defaults. Since filter1 was + // set as default in the definition, the value would actually + // not appear in the representation itself. + // It is considered 'true', though, and should appear in the + // converted result in its parameter representation. + // >> group1__filter1: true, + // - The reverse is true for filter3. Filter3 is set as default + // but we don't want it in this representation of the saved query. + // Since the filter representation ran against default values, + // it will appear as 'false' value in this representation explicitly + // and the resulting parameter representation should have that + // as the result as well + group1__filter3: false, + group2__filter4: true, + group3__group3option1: true + }, + highlights: { + highlight: true, + group1__filter1: 'c5', + group3__group3option1: 'c1' + }, + invert: true + } + } + } + }, + queriesParamRepresentation = { + version: '2', + queries: { + 1234: { + label: 'Item converted', + data: { + params: { + // filter1 is 'true' so filter2 and filter3 are both '1' + // in param representation + filter2: '1', filter3: '1', + // Group type string_options + group2: 'filter4' + // Note - Group3 is sticky, so it won't show in output + }, + highlights: { + group1__filter1_color: 'c5', + group3__group3option1_color: 'c1' + } + } + } + } + }, + removeHighlights = function ( data ) { + var copy = $.extend( true, {}, data ); + copy.queries[ 1234 ].data.highlights = {}; + return copy; + }; + + QUnit.module( 'mediawiki.rcfilters - SavedQueriesModel' ); + + QUnit.test( 'Initializing queries', function ( assert ) { + var filtersModel = new mw.rcfilters.dm.FiltersViewModel(), + queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ), + exampleQueryStructure = { + version: '2', + default: '1234', + queries: { + 1234: { + label: 'Query 1234', + data: { + params: { + filter2: '1' + }, + highlights: { + group1__filter3_color: 'c2' + } + } + } + } + }, + cases = [ + { + input: {}, + finalState: { version: '2', queries: {} }, + msg: 'Empty initial query structure results in base saved queries structure.' + }, + { + input: $.extend( true, {}, exampleQueryStructure ), + finalState: $.extend( true, {}, exampleQueryStructure ), + msg: 'Initialization of given query structure does not corrupt the structure.' + }, + { + // Converting from old structure + input: $.extend( true, {}, queriesFilterRepresentation ), + finalState: $.extend( true, {}, queriesParamRepresentation ), + msg: 'Conversion from filter representation to parameters retains data.' + }, + { + // Converting from old structure + input: $.extend( true, {}, queriesFilterRepresentation, { queries: { 1234: { data: { + filters: { + // Entire group true: normalize params + filter1: true, + filter2: true, + filter3: true + }, + highlights: { + filter3: null // Get rid of empty highlight + } + } } } } ), + finalState: $.extend( true, {}, queriesParamRepresentation ), + msg: 'Conversion from filter representation to parameters normalizes params and highlights.' + }, + { + // Converting from old structure with default + input: $.extend( true, { default: '1234' }, queriesFilterRepresentation ), + finalState: $.extend( true, { default: '1234' }, queriesParamRepresentation ), + msg: 'Conversion from filter representation to parameters, with default set up, retains data.' + }, + { + // Converting from old structure and cleaning up highlights + input: $.extend( true, queriesFilterRepresentation, { queries: { 1234: { data: { highlights: { highlight: false } } } } } ), + finalState: removeHighlights( queriesParamRepresentation ), + msg: 'Conversion from filter representation to parameters and highlight cleanup' + }, + { + // New structure + input: $.extend( true, {}, queriesParamRepresentation ), + finalState: $.extend( true, {}, queriesParamRepresentation ), + msg: 'Parameter representation retains its queries structure' + }, + { + // Do not touch invalid color parameters from the initialization routine + // (Normalization, or "fixing" the query should only happen when we add new query or actively convert queries) + input: $.extend( true, { queries: { 1234: { data: { highlights: { group2__filter5_color: 'c2' } } } } }, exampleQueryStructure ), + finalState: $.extend( true, { queries: { 1234: { data: { highlights: { group2__filter5_color: 'c2' } } } } }, exampleQueryStructure ), + msg: 'Structure that contains invalid highlights remains the same in initialization' + }, + { + // Trim colors when highlight=false is stored + input: $.extend( true, { queries: { 1234: { data: { params: { highlight: '0' } } } } }, queriesParamRepresentation ), + finalState: removeHighlights( queriesParamRepresentation ), + msg: 'Colors are removed when highlight=false' + }, + { + // Remove highlight when it is true but no colors are specified + input: $.extend( true, { queries: { 1234: { data: { params: { highlight: '1' } } } } }, removeHighlights( queriesParamRepresentation ) ), + finalState: removeHighlights( queriesParamRepresentation ), + msg: 'remove highlight when it is true but there is no colors' + } + ]; + + filtersModel.initializeFilters( filterDefinition ); + + cases.forEach( function ( testCase ) { + queriesModel.initialize( testCase.input ); + assert.deepEqual( + queriesModel.getState(), + testCase.finalState, + testCase.msg + ); + } ); + } ); + + QUnit.test( 'Adding new queries', function ( assert ) { + var filtersModel = new mw.rcfilters.dm.FiltersViewModel(), + queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ), + cases = [ + { + methodParams: [ + 'label1', // Label + { // Data + filter1: '1', + filter2: '2', + group1__filter1_color: 'c2', + group1__filter3_color: 'c5' + }, + true, // isDefault + '1234' // ID + ], + result: { + itemState: { + label: 'label1', + data: { + params: { + filter1: '1', + filter2: '2' + }, + highlights: { + group1__filter1_color: 'c2', + group1__filter3_color: 'c5' + } + } + }, + isDefault: true, + id: '1234' + }, + msg: 'Given valid data is preserved.' + }, + { + methodParams: [ + 'label2', + { + filter1: '1', + invert: '1', + filter15: '1', // Invalid filter - removed + filter2: '0', // Falsey value - removed + group1__filter1_color: 'c3', + foobar: 'w00t' // Unrecognized parameter - removed + } + ], + result: { + itemState: { + label: 'label2', + data: { + params: { + filter1: '1' // Invert will be dropped because there are no namespaces + }, + highlights: { + group1__filter1_color: 'c3' + } + } + }, + isDefault: false + }, + msg: 'Given data with invalid filters and highlights is normalized' + } + ]; + + filtersModel.initializeFilters( filterDefinition ); + + // Start with an empty saved queries model + queriesModel.initialize( {} ); + + cases.forEach( function ( testCase ) { + var itemID = queriesModel.addNewQuery.apply( queriesModel, testCase.methodParams ), + item = queriesModel.getItemByID( itemID ); + + assert.deepEqual( + item.getState(), + testCase.result.itemState, + testCase.msg + ' (itemState)' + ); + + assert.equal( + item.isDefault(), + testCase.result.isDefault, + testCase.msg + ' (isDefault)' + ); + + if ( testCase.result.id !== undefined ) { + assert.equal( + item.getID(), + testCase.result.id, + testCase.msg + ' (item ID)' + ); + } + } ); + } ); + + QUnit.test( 'Manipulating queries', function ( assert ) { + var id1, id2, item1, matchingItem, + queriesStructure = {}, + filtersModel = new mw.rcfilters.dm.FiltersViewModel(), + queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ); + + filtersModel.initializeFilters( filterDefinition ); + + // Start with an empty saved queries model + queriesModel.initialize( {} ); + + // Add items + id1 = queriesModel.addNewQuery( + 'New query 1', + { + group2: 'filter5', + group1__filter1_color: 'c5', + group3__group3option1_color: 'c1' + } + ); + id2 = queriesModel.addNewQuery( + 'New query 2', + { + filter1: '1', + filter2: '1', + invert: '1' + } + ); + item1 = queriesModel.getItemByID( id1 ); + + assert.equal( + item1.getID(), + id1, + 'Item created and its data retained successfully' + ); + + // NOTE: All other methods that the item itself returns are + // tested in the dm.SavedQueryItemModel.test.js file + + // Build the query structure we expect per item + queriesStructure[ id1 ] = { + label: 'New query 1', + data: { + params: { + group2: 'filter5' + }, + highlights: { + group1__filter1_color: 'c5', + group3__group3option1_color: 'c1' + } + } + }; + queriesStructure[ id2 ] = { + label: 'New query 2', + data: { + params: { + filter1: '1', + filter2: '1' + }, + highlights: {} + } + }; + + assert.deepEqual( + queriesModel.getState(), + { + version: '2', + queries: queriesStructure + }, + 'Full query represents current state of items' + ); + + // Add default + queriesModel.setDefault( id2 ); + + assert.deepEqual( + queriesModel.getState(), + { + version: '2', + default: id2, + queries: queriesStructure + }, + 'Setting default is reflected in queries state' + ); + + // Remove default + queriesModel.setDefault( null ); + + assert.deepEqual( + queriesModel.getState(), + { + version: '2', + queries: queriesStructure + }, + 'Removing default is reflected in queries state' + ); + + // Find matching query + matchingItem = queriesModel.findMatchingQuery( + { + group2: 'filter5', + group1__filter1_color: 'c5', + group3__group3option1_color: 'c1' + } + ); + assert.deepEqual( + matchingItem.getID(), + id1, + 'Finding matching item by identical state' + ); + + // Find matching query with 0-values (base state) + matchingItem = queriesModel.findMatchingQuery( + { + group2: 'filter5', + filter1: '0', + filter2: '0', + group1__filter1_color: 'c5', + group3__group3option1_color: 'c1' + } + ); + assert.deepEqual( + matchingItem.getID(), + id1, + 'Finding matching item by "dirty" state with 0-base values' + ); + } ); + + QUnit.test( 'Testing invert property', function ( assert ) { + var itemID, item, + filtersModel = new mw.rcfilters.dm.FiltersViewModel(), + queriesModel = new mw.rcfilters.dm.SavedQueriesModel( filtersModel ), + viewsDefinition = { + namespace: { + label: 'Namespaces', + trigger: ':', + groups: [ { + name: 'namespace', + label: 'Namespaces', + type: 'string_options', + separator: ';', + filters: [ + { name: 0, label: 'Main', cssClass: 'namespace-0' }, + { name: 1, label: 'Talk', cssClass: 'namespace-1' }, + { name: 2, label: 'User', cssClass: 'namespace-2' }, + { name: 3, label: 'User talk', cssClass: 'namespace-3' } + ] + } ] + } + }; + + filtersModel.initializeFilters( filterDefinition, viewsDefinition ); + + // Start with an empty saved queries model + queriesModel.initialize( {} ); + + filtersModel.toggleFiltersSelected( { + group1__filter3: true, + invertGroup__invert: true + } ); + itemID = queriesModel.addNewQuery( + 'label1', // Label + filtersModel.getMinimizedParamRepresentation(), + true, // isDefault + '2345' // ID + ); + item = queriesModel.getItemByID( itemID ); + + assert.deepEqual( + item.getState(), + { + label: 'label1', + data: { + params: { + filter1: '1', + filter2: '1' + }, + highlights: {} + } + }, + 'Invert parameter is not saved if there are no namespaces.' + ); + + // Reset + filtersModel.initializeFilters( filterDefinition, viewsDefinition ); + filtersModel.toggleFiltersSelected( { + group1__filter3: true, + invertGroup__invert: true, + namespace__1: true + } ); + itemID = queriesModel.addNewQuery( + 'label1', // Label + filtersModel.getMinimizedParamRepresentation(), + true, // isDefault + '1234' // ID + ); + item = queriesModel.getItemByID( itemID ); + + assert.deepEqual( + item.getState(), + { + label: 'label1', + data: { + params: { + filter1: '1', + filter2: '1', + invert: '1', + namespace: '1' + }, + highlights: {} + } + }, + 'Invert parameter saved if there are namespaces.' + ); + } ); +}( mediaWiki ) ); |