@@ -1199,28 +1199,6 @@ describe('IgxGrid - Advanced Filtering', () => {
11991199 expect ( GridFunctions . getAdvancedFilteringComponent ( fix ) ) . not . toBeNull ( 'Advanced Filtering dialog is not opened.' ) ;
12001200 } ) ) ;
12011201
1202- it ( 'Should discard added group when clicking its operator line without having a single expression.' , fakeAsync ( ( ) => {
1203- // Open Advanced Filtering dialog.
1204- GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1205- fix . detectChanges ( ) ;
1206-
1207- // Add initial 'and' group.
1208- const initialAddAndGroupBtn = GridFunctions . getAdvancedFilteringInitialAddGroupButtons ( fix ) [ 0 ] ;
1209- initialAddAndGroupBtn . click ( ) ;
1210- tick ( 100 ) ;
1211- fix . detectChanges ( ) ;
1212-
1213- // Click operator line.
1214- const rootOperatorLine = GridFunctions . getAdvancedFilteringTreeRootGroupOperatorLine ( fix ) ;
1215- rootOperatorLine . click ( ) ;
1216- tick ( 200 ) ;
1217- fix . detectChanges ( ) ;
1218-
1219- // Verify group is discarded and the context menu was not opened.
1220- expect ( GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ) . toBeNull ( 'Group is not discarded.' ) ;
1221- verifyContextMenuVisibility ( fix , false ) ;
1222- } ) ) ;
1223-
12241202 it ( 'Should display the adding buttons and the cancel button when trying to add a new condition/group to existing group.' ,
12251203 fakeAsync ( ( ) => {
12261204 // Apply advanced filter through API.
@@ -1396,6 +1374,272 @@ describe('IgxGrid - Advanced Filtering', () => {
13961374 'incorrect all children count of group with path [0]' ) ;
13971375 } ) ) ;
13981376
1377+ describe ( 'Context Menu' , ( ) => {
1378+ it ( 'Should discard added group when clicking its operator line without having a single expression.' , fakeAsync ( ( ) => {
1379+ // Open Advanced Filtering dialog.
1380+ GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1381+ fix . detectChanges ( ) ;
1382+
1383+ // Add initial 'and' group.
1384+ const initialAddAndGroupBtn = GridFunctions . getAdvancedFilteringInitialAddGroupButtons ( fix ) [ 0 ] ;
1385+ initialAddAndGroupBtn . click ( ) ;
1386+ tick ( 100 ) ;
1387+ fix . detectChanges ( ) ;
1388+
1389+ // Click operator line.
1390+ const rootOperatorLine = GridFunctions . getAdvancedFilteringTreeRootGroupOperatorLine ( fix ) ;
1391+ rootOperatorLine . click ( ) ;
1392+ tick ( 200 ) ;
1393+ fix . detectChanges ( ) ;
1394+
1395+ // Verify group is discarded and the context menu was not opened.
1396+ expect ( GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ) . toBeNull ( 'Group is not discarded.' ) ;
1397+ verifyContextMenuVisibility ( fix , false ) ;
1398+ } ) ) ;
1399+
1400+ it ( 'Selecting multiple conditions should display the (create group)/(delete filters) context menu.' , fakeAsync ( ( ) => {
1401+ // Apply advanced filter through API.
1402+ const tree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
1403+ tree . filteringOperands . push ( {
1404+ fieldName : 'Downloads' , searchVal : 100 , condition : IgxNumberFilteringOperand . instance ( ) . condition ( 'greaterThan' )
1405+ } ) ;
1406+ const orTree = new FilteringExpressionsTree ( FilteringLogic . Or ) ;
1407+ orTree . filteringOperands . push ( {
1408+ fieldName : 'ProductName' , searchVal : 'angular' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1409+ ignoreCase : true
1410+ } ) ;
1411+ orTree . filteringOperands . push ( {
1412+ fieldName : 'ProductName' , searchVal : 'script' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1413+ ignoreCase : true
1414+ } ) ;
1415+ tree . filteringOperands . push ( orTree ) ;
1416+ grid . advancedFilteringExpressionsTree = tree ;
1417+ fix . detectChanges ( ) ;
1418+
1419+ // Open Advanced Filtering dialog.
1420+ GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1421+ fix . detectChanges ( ) ;
1422+
1423+ // Verify context menu is not visible.
1424+ verifyContextMenuVisibility ( fix , false ) ;
1425+
1426+ // Select two chips.
1427+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 0 ] ) ;
1428+ tick ( 400 ) ;
1429+ fix . detectChanges ( ) ;
1430+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 1 , 1 ] ) ;
1431+ tick ( 400 ) ;
1432+ fix . detectChanges ( ) ;
1433+
1434+ // Verify context menu is visible.
1435+ verifyContextMenuVisibility ( fix , true ) ;
1436+ verifyContextMenuType ( fix , false ) ;
1437+
1438+ // Unselect one of the two selected chips.
1439+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 0 ] ) ;
1440+ tick ( 400 ) ;
1441+ fix . detectChanges ( ) ;
1442+
1443+ // Verify context menu is no longer visible.
1444+ verifyContextMenuVisibility ( fix , false ) ;
1445+ } ) ) ;
1446+
1447+ it ( 'Should create an \'and\' group from multiple selected conditions when respective context menu button is clicked.' ,
1448+ fakeAsync ( ( ) => {
1449+ // Apply advanced filter through API.
1450+ const tree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
1451+ tree . filteringOperands . push ( {
1452+ fieldName : 'Downloads' , searchVal : 100 , condition : IgxNumberFilteringOperand . instance ( ) . condition ( 'greaterThan' )
1453+ } ) ;
1454+ const orTree = new FilteringExpressionsTree ( FilteringLogic . Or ) ;
1455+ orTree . filteringOperands . push ( {
1456+ fieldName : 'ProductName' , searchVal : 'angular' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1457+ ignoreCase : true
1458+ } ) ;
1459+ orTree . filteringOperands . push ( {
1460+ fieldName : 'ProductName' , searchVal : 'script' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1461+ ignoreCase : true
1462+ } ) ;
1463+ tree . filteringOperands . push ( orTree ) ;
1464+ grid . advancedFilteringExpressionsTree = tree ;
1465+ fix . detectChanges ( ) ;
1466+
1467+ // Open Advanced Filtering dialog.
1468+ GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1469+ fix . detectChanges ( ) ;
1470+
1471+ // Verify tree layout before the creation of a new group with context menu.
1472+ let rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1473+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 2 ) ;
1474+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 4 ) ;
1475+
1476+ let firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // expression
1477+ expect ( firstItem . classList . contains ( 'igx-filter-tree__expression-item' ) ) . toBe ( true ) ;
1478+
1479+ let secondItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 1 ] ) ; // group
1480+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , true ) . length ) . toBe ( 2 ) ;
1481+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , false ) . length ) . toBe ( 2 ) ;
1482+
1483+ // Select two chips.
1484+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 0 ] ) ;
1485+ tick ( 400 ) ;
1486+ fix . detectChanges ( ) ;
1487+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 1 , 1 ] ) ;
1488+ tick ( 400 ) ;
1489+ fix . detectChanges ( ) ;
1490+
1491+ // Click "Create And Group" in context menu.
1492+ const buttons = GridFunctions . getAdvancedFilteringContextMenuButtons ( fix ) ;
1493+ buttons [ 1 ] . click ( ) ;
1494+ tick ( 100 ) ;
1495+ fix . detectChanges ( ) ;
1496+
1497+ // Verify tree layout after the creation of a new group with context menu.
1498+ rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1499+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 2 ) ;
1500+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 5 ) ;
1501+
1502+ firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // the new group
1503+ verifyOperatorLine ( GridFunctions . getAdvancedFilteringTreeGroupOperatorLine ( fix , [ 0 ] ) , 'and' ) ;
1504+ expect ( firstItem . classList . contains ( 'igx-filter-tree__expression-item' ) ) . toBe ( false ) ;
1505+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , true ) . length ) . toBe ( 2 ) ;
1506+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , false ) . length ) . toBe ( 2 ) ;
1507+
1508+ secondItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 1 ] ) ; // group
1509+ verifyOperatorLine ( GridFunctions . getAdvancedFilteringTreeGroupOperatorLine ( fix , [ 1 ] ) , 'or' ) ;
1510+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , true ) . length ) . toBe ( 1 ) ;
1511+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , false ) . length ) . toBe ( 1 ) ;
1512+ } ) ) ;
1513+
1514+ it ( 'Should create an \'or\' group from multiple selected conditions when respective context menu button is clicked.' ,
1515+ fakeAsync ( ( ) => {
1516+ // Apply advanced filter through API.
1517+ const tree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
1518+ tree . filteringOperands . push ( {
1519+ fieldName : 'Downloads' , searchVal : 100 , condition : IgxNumberFilteringOperand . instance ( ) . condition ( 'greaterThan' )
1520+ } ) ;
1521+ const orTree = new FilteringExpressionsTree ( FilteringLogic . Or ) ;
1522+ orTree . filteringOperands . push ( {
1523+ fieldName : 'ProductName' , searchVal : 'angular' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1524+ ignoreCase : true
1525+ } ) ;
1526+ orTree . filteringOperands . push ( {
1527+ fieldName : 'ProductName' , searchVal : 'script' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1528+ ignoreCase : true
1529+ } ) ;
1530+ tree . filteringOperands . push ( orTree ) ;
1531+ grid . advancedFilteringExpressionsTree = tree ;
1532+ fix . detectChanges ( ) ;
1533+
1534+ // Open Advanced Filtering dialog.
1535+ GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1536+ fix . detectChanges ( ) ;
1537+
1538+ // Verify tree layout before the creation of a new group with context menu.
1539+ let rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1540+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 2 ) ;
1541+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 4 ) ;
1542+
1543+ let firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // expression
1544+ expect ( firstItem . classList . contains ( 'igx-filter-tree__expression-item' ) ) . toBe ( true ) ;
1545+
1546+ let secondItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 1 ] ) ; // group
1547+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , true ) . length ) . toBe ( 2 ) ;
1548+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , false ) . length ) . toBe ( 2 ) ;
1549+
1550+ // Select two chips.
1551+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 0 ] ) ;
1552+ tick ( 400 ) ;
1553+ fix . detectChanges ( ) ;
1554+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 1 , 1 ] ) ;
1555+ tick ( 400 ) ;
1556+ fix . detectChanges ( ) ;
1557+
1558+ // Click "Create Or Group" in context menu.
1559+ const buttons = GridFunctions . getAdvancedFilteringContextMenuButtons ( fix ) ;
1560+ buttons [ 2 ] . click ( ) ;
1561+ tick ( 100 ) ;
1562+ fix . detectChanges ( ) ;
1563+
1564+ // Verify tree layout after the creation of a new group with context menu.
1565+ rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1566+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 2 ) ;
1567+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 5 ) ;
1568+
1569+ firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // the new group
1570+ verifyOperatorLine ( GridFunctions . getAdvancedFilteringTreeGroupOperatorLine ( fix , [ 0 ] ) , 'or' ) ;
1571+ expect ( firstItem . classList . contains ( 'igx-filter-tree__expression-item' ) ) . toBe ( false ) ;
1572+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , true ) . length ) . toBe ( 2 ) ;
1573+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , false ) . length ) . toBe ( 2 ) ;
1574+
1575+ secondItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 1 ] ) ; // group
1576+ verifyOperatorLine ( GridFunctions . getAdvancedFilteringTreeGroupOperatorLine ( fix , [ 1 ] ) , 'or' ) ;
1577+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , true ) . length ) . toBe ( 1 ) ;
1578+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , false ) . length ) . toBe ( 1 ) ;
1579+ } ) ) ;
1580+
1581+ it ( 'Should delete all selected conditions when the \'delete filters\' option from context menu is clicked.' ,
1582+ fakeAsync ( ( ) => {
1583+ // Apply advanced filter through API.
1584+ const tree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
1585+ tree . filteringOperands . push ( {
1586+ fieldName : 'Downloads' , searchVal : 100 , condition : IgxNumberFilteringOperand . instance ( ) . condition ( 'greaterThan' )
1587+ } ) ;
1588+ const orTree = new FilteringExpressionsTree ( FilteringLogic . Or ) ;
1589+ orTree . filteringOperands . push ( {
1590+ fieldName : 'ProductName' , searchVal : 'angular' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1591+ ignoreCase : true
1592+ } ) ;
1593+ orTree . filteringOperands . push ( {
1594+ fieldName : 'ProductName' , searchVal : 'script' , condition : IgxStringFilteringOperand . instance ( ) . condition ( 'contains' ) ,
1595+ ignoreCase : true
1596+ } ) ;
1597+ tree . filteringOperands . push ( orTree ) ;
1598+ grid . advancedFilteringExpressionsTree = tree ;
1599+ fix . detectChanges ( ) ;
1600+
1601+ // Open Advanced Filtering dialog.
1602+ GridFunctions . clickAdvancedFilteringButton ( fix ) ;
1603+ fix . detectChanges ( ) ;
1604+
1605+ // Verify tree layout before the creation of a new group with context menu.
1606+ let rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1607+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 2 ) ;
1608+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 4 ) ;
1609+
1610+ let firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // expression
1611+ expect ( firstItem . classList . contains ( 'igx-filter-tree__expression-item' ) ) . toBe ( true ) ;
1612+
1613+ const secondItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 1 ] ) ; // group
1614+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , true ) . length ) . toBe ( 2 ) ;
1615+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( secondItem , false ) . length ) . toBe ( 2 ) ;
1616+
1617+ // Select two chips.
1618+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 0 ] ) ;
1619+ tick ( 400 ) ;
1620+ fix . detectChanges ( ) ;
1621+ GridFunctions . clickAdvancedFilteringTreeExpressionChip ( fix , [ 1 , 1 ] ) ;
1622+ tick ( 400 ) ;
1623+ fix . detectChanges ( ) ;
1624+
1625+ // Click "Delete Filters" in context menu.
1626+ const buttons = GridFunctions . getAdvancedFilteringContextMenuButtons ( fix ) ;
1627+ buttons [ 3 ] . click ( ) ;
1628+ tick ( 100 ) ;
1629+ fix . detectChanges ( ) ;
1630+
1631+ // Verify tree layout after deleting some expressions with the context menu.
1632+ rootGroup = GridFunctions . getAdvancedFilteringTreeRootGroup ( fix ) ; // group
1633+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , true ) . length ) . toBe ( 1 ) ;
1634+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( rootGroup , false ) . length ) . toBe ( 2 ) ;
1635+
1636+ firstItem = GridFunctions . getAdvancedFilteringTreeItem ( fix , [ 0 ] ) ; // group
1637+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , true ) . length ) . toBe ( 1 ) ;
1638+ expect ( GridFunctions . getAdvancedFilteringTreeChildItems ( firstItem , false ) . length ) . toBe ( 1 ) ;
1639+ verifyExpressionChipContent ( fix , [ 0 , 0 ] , 'ProductName' , 'Contains' , 'angular' ) ;
1640+ } ) ) ;
1641+ } ) ;
1642+
13991643 describe ( 'Localization' , ( ) => {
14001644 it ( 'Should correctly change resource strings for Advanced Filtering dialog.' , fakeAsync ( ( ) => {
14011645 fix = TestBed . createComponent ( IgxGridAdvancedFilteringComponent ) ;
@@ -1757,6 +2001,29 @@ function verifyContextMenuVisibility(fix, shouldBeVisible: boolean) {
17572001 expect ( contextMenuRect . width === 0 && contextMenuRect . height === 0 ) . toBe ( ! shouldBeVisible , 'incorrect context menu dimensions' ) ;
17582002}
17592003
2004+ /**
2005+ * Verifies the type of the context menu (menu for specific group or menu for combining expressions).
2006+ * If contextual group is expected, the context menu should contain buttons for operator change, ungroup and delete.
2007+ * If contextual group is not expected, the context menu should contain buttons for creating new group by combining expressions.
2008+ */
2009+ function verifyContextMenuType ( fix , shouldBeContextualGroup : boolean ) {
2010+ const contextMenuButtons = GridFunctions . getAdvancedFilteringContextMenuButtons ( fix ) ;
2011+ expect ( GridFunctions . getAdvancedFilteringContextMenuButtonGroup ( fix ) !== null ) . toBe ( shouldBeContextualGroup ) ;
2012+
2013+ if ( shouldBeContextualGroup ) {
2014+ expect ( contextMenuButtons . length ) . toBe ( 3 , 'incorrect buttons count in context menu' ) ;
2015+ expect ( contextMenuButtons [ 0 ] . innerText . toLowerCase ( ) ) . toBe ( 'close' ) ;
2016+ expect ( contextMenuButtons [ 1 ] . innerText . toLowerCase ( ) ) . toBe ( 'ungroup' ) ;
2017+ expect ( contextMenuButtons [ 2 ] . innerText . toLowerCase ( ) ) . toBe ( 'delete' ) ;
2018+ } else {
2019+ expect ( contextMenuButtons . length ) . toBe ( 4 , 'incorrect buttons count in context menu' ) ;
2020+ expect ( contextMenuButtons [ 0 ] . innerText . toLowerCase ( ) ) . toBe ( 'close' ) ;
2021+ expect ( contextMenuButtons [ 1 ] . innerText . toLowerCase ( ) ) . toBe ( 'create "and" group' ) ;
2022+ expect ( contextMenuButtons [ 2 ] . innerText . toLowerCase ( ) ) . toBe ( 'create "or" group' ) ;
2023+ expect ( contextMenuButtons [ 3 ] . innerText . toLowerCase ( ) ) . toBe ( 'delete filters' ) ;
2024+ }
2025+ }
2026+
17602027function verifyEqualArrays ( firstArr : any [ ] , secondArr : any [ ] ) {
17612028 expect ( firstArr . length ) . toEqual ( secondArr . length , 'Array lengths mismatch.' ) ;
17622029 firstArr = firstArr . sort ( ) ;
0 commit comments