Cypress - Working with div tables - Validating text on each row - javascript

I want to check if the first column of each row's text starts with "AA", "BB" or "CC". But I couldn't manage it on div table. I can only select and check the first row (code below). But I also tried with selecting the whole column and tried with using cy.each & cy.wrap and got errors too.
How can I check the first column for each row's text? (Table has 40-45 rows.)
The table looks like this:
Right now I can only check the first row with the code below. How can I check all the rows like this? Is the code below clear to you by the way?
cy.get('div[row-index="0"]')
.eq(1)
.invoke('text')
.then(text => {
const productID = text.trim();
let correctProductIDPrefix = false;
['AA', 'BB', 'CC'].forEach(possibleProductIDPrefix => {
if (!correctProductIDPrefix) {
correctProductIDPrefix = productID.startsWith(possibleProductIDPrefix);
}
});
expect(correctProductIDPrefix).to.be.true;
});
Thanks in advance!

To perform the same test on all rows
select all the rows (change [row-index="0"] to [row-index])
use .each() to run test on all rows
sub-select just the column you want, in case some other column also has the prefix and gives you a false-positive result
use Array.some() method to check at least one prefix matches
const possibleProductPrefixes = ['AA', 'BB', 'CC'] // define once outside test
cy.get('div[row-index]') // selects every row
.each($row => {
const $col = $row.find('[col-id="orderNumber"]') // pick out the column
const productId = $col.text().trim()
const correctProductIDPrefix = possibleProductPrefixes.some(prefix => {
return productId.startsWith(prefix)
})
expect(correctProductIDPrefix).to.be.true;
});
Ref Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.

You can do something like this:
let prefix = ['AA', 'BB', 'CC']
cy.get('.ag-cell-value').each(($ele, index) => {
expect($ele.text().trim().startsWith(prefix[index])).to.be.true
})

Related

Super Search in AG GRID-> Angular

I am using AG grid.
TextFilter is working fine. but i want my ag grid to show rows when i search with string seperated with commas(",").
Eg : when i search with "abc,def,xyz", it should give the result that rows contains abc or def or xyz.
Thanks in advance
Look at using the textCustomComparator option, documented here: https://www.ag-grid.com/javascript-grid-filter-text/#text-custom-comparator
Here is an example of how it could be accomplished:
filterParams: {
filterOptions: ["contains"],
textCustomComparator: function(filter, value, filterText) {
// get array of comma separated values
const filterValues = filterText.split(',');
// loop through filterValues and see if the value contains any of them
return filterValues.some((item) => {
return value.indexOf(item) >= 0;
});
}
}
Another option is to use a custom filter, which is documented here: https://www.ag-grid.com/javascript-grid-filter-custom/

Javascript filter and match all elements in array

I have an array that looks like:
var testArr = ["40", "A1", "B9", "58"]
I want to loop over all div elements of a certain class and return only the elements where the data attribute matches ANY of the items in that array.
If I do something like this:
$("div.prodCodes").filter(function(e) {
var x1 = $(this);
var x2 = $(this).data("prodCode");
testArr.forEach(function(e) { if (e == x2) { console.log("MATCH"); } });
});
That console outputs the correct number of matches, but I cannot return those elements from the filter function.
What on earth am I missing here? I've tried creating a new array and pushing each item onto it and returning that, but it's always empty. I'm sure I'm missing something obvious here. I've also tried rewriting this using .grep() and getting nowhere. Help is appreciated.
You need to return a truthy value in filter() to have an item included.
Try :
$("div.prodCodes").filter(function(e) {
return testArr.indexOf($(this).attr('data-prodCode')) >-1;
}).doSomething();
Without a return all items will be excluded
I would use a Set for constant-time lookup.
Be aware that jQuery reads the attribute value "58" as a number when using the data method, so it won't match unless you make sure the data type is the same:
// Use a set
var testSet = new Set(["40", "A1", "B9", "58"]);
var texts = $("div.prodCodes").filter(function() {
var x = $(this).data("prodCode").toString(); // data type must match
// Return a boolean to indicate whether the div element should be kept
return testSet.has(x); // Set#has() is fast
}).map(function(){
// For demo only: get the text content of the matching div elements
return $(this).text();
}).get(); // convert that to a plain array
console.log(texts);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="prodCodes" data-prod-code="A1">Hello</div>
<div class="prodCodes" data-prod-code="XX">Not this one</div>
<div class="prodCodes" data-prod-code="58">There</div>

SlickGrid javascript get current row data

I would like to remove a row when I press the Delete key. But I can't get any data from the source below:
var selectedrows = grid.getSelectedRows();
grid.onKeyDown.subscribe(function(event) {
var item = data[selectedrows.cell];
if (event.keyCode == 46) {
alert(item.hostname);
}
});
First, the getSelectedRows() function returns an Array of the selected column numbers. The way you are trying will return undefined, since that Array doesn't contain any property called cells.
Open this official SlickGrid example demo and try the following:
Select the first row in grid.
Try issuing the following command in your JS debugger console:
grid.getSelectedRows()
Will return you an Array with the selected row number as:
Array [ 0 ]
The returned Array'sfirst element is the row number that you have just selected.
Now that we know the selected row number issue this:
data[grid.getSelectedRows()[0]]
Will return you the selected Object as:
Object { name: "Make a list", complete: true }
If you want to reach a property of the returned Object you could do it as:
var selectedRow = data[grid.getSelectedRows()[0]];
console.log(selectedRow.name);
Will return the property name's value as:
Make a list
Hope this clears up your confusion.

Getting a row from a data attribute in datatables.js

I am struggling trying to find the right method to do this. Basically, I have an array of id values that correspond to which rows have been selected in my table. To construct this list, I use the following code. this.options.ajaxId is the key that accesses my Id value in the data object passed to the table.
this.getRowData(target)[this.options.ajaxId]
where my getRowData function is:
getRowData: function (HTMLrow) {
return this.dataTable.row(HTMLrow).data();
},
This works great, but then I am stumped on my next step which is re-selecting the correct rows when the table is re-drawn via paging, sorting, or searching. My plan was to cycle through the ID's and find which table row corresponded to that ID value, but I cannot find a function to input a key value search pair and return the html row. Something like the following is what I was thinking,
this.dataTable.findRow( key, value );
// then my usage would be the following:
var that = this;
_.each(this.selectedList, function (id) {
var row = that.dataTable.findRow( that.options.ajaxId, id );
// code to select the row
});
I haven't written it yet, but I know I can cycle through each of the rows, get the data for that row, and check it against what I am looking for, but in cases where the user is viewing 100 rows and has only one selection I would like to avoid that.
Any insight?
Thanks
SOLUTION #1
You can use the following code to locate and highlight rows based on row IDs if row ID is stored in one of the fields.
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
// Find indexes of rows which have IDs in the desired column
var rowIndexes = table.rows().eq(0).filter( function (rowIdx) {
return ($.inArray(table.cell( rowIdx, colIdIndex ).data(), rowIds) !== -1)
? true
: false;
});
// Select rows based on array of found row indexes
table.rows(rowIndexes)
.nodes()
.to$()
.addClass('selected');
See filter() API method for more details.
Please note that this method will work for client-side processing mode only.
DEMO
See this jsFiddle for code and demonstration.
SOLUTION #2
Alternative approach that would work both in client-side and server-side processing modes would be to use createdRow callback.
For example:
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
var table = $('#example').DataTable({
createdRow: function( row, data, dataIndex ) {
if ( $.inArray(data[colIdIndex], rowIds) !== -1) {
$(row).addClass('selected');
}
}
});
DEMO
See this jsFiddle for code and demonstration.

AngularJs: programmatically filter by either of 2 columns

I have the following code in my controller:
$scope.filteredTransactions = $scope.invoiceTransactionsObject.transactions.concat(); // make a copy of the initial array
if ($scope.searchTerm.message)
{
var search = $scope.searchTerm.message;
$scope.filteredTransactions = $filter('filter')($scope.filteredTransactions, ({ message: search } || { item: search }));
}
I want to be able to filter by typing some value and search either in the message column or item column. According to How to filter multiple values (OR operation) in angularJS it should work, but it doesn't and if I type something that can be found in the message, it works, but when I type something from the item, it returns empty array.
Do you see where is my mistake?
Update Deleted irrelevant/mistaken initial answer
Since you're applying $filter inside a JS script, and it doesn't use any of the advanced features of $filter, I'd switch over to the JS-native method of filtering an array:
$scope.filteredTransactions = $scope.invoiceTransactionsObject.transactions.concat(); // make a copy of the initial array
if ($scope.searchTerm.message)
{
var search = $scope.searchTerm.message;
$scope.filteredTransactions = $scope.filteredTransactions.filter(function (trans) {
return trans.message.toLowerCase().indexOf(search) >= 0 || trans.item.toLowerCase().indexOf(search) >= 0;
});
}
...assuming that $filter is case-insensitive and matches anywhere in the string. If that's not the functionality of $filter and/or not what you want, you'd adjust the code accordingly.

Categories