Cypress - Assert only one element with a text exists - javascript

I have a table and I want to ensure that values are not repeated within a column using Cypress. Currently, I am doing
cy.get("#myTable")
.find(".table")
.contains("unique_value")
.should("exist")
This piece of code does check if a value in a column exists but it doesn't ensure that its the only entry with this value in the table. How do I check for uniqueness through Cypress?

Surprisingly, this
cy.get("#myTable")
.find(".table")
.contains("unique_value")
.should('have.length', 1);
or even this
cy.get("#myTable")
.find(".table td")
.contains("unique_value")
.should('have.length', 1);
will return a false positive - if you run it with two unique_value table cells it incorrectly passes.
Ref contains - yields indicates a single value is returned.
The best way I found was to shift the contains() up into the .find() selector,
cy.get("#myTable")
.find('.table td:contains("unique_value")')
.should('have.length', 1)
The above tests uniqueness between cells. If you want to also test the value within the cell, the simplest way is to invoke the text() method.
cy.get("#myTable")
.find('.table td:contains("unique_value")')
.should('have.length', 1) // ensure only one cell has value
.invoke('text')
.should('equal', 'unique_value') // check the exact content of the cell
See the first example on this page Assertions

sorry about the previous answer, I forgot with .contains it selects sorts out 1 element from the found list. anyway, there are two ways to do this.
1st :
it'll look like,
cy.get(".table")
.find(('td:contains("unique_value")'))
.should('have.length', 1)
Note: This might be problematic if the same table cell has repetitive unique_value
For example: Let's say you are expecting a unique id (1234) in a table cell, but the table looks as follows
<tr>
<td>1234, 1234<td>
<td>value<td>
<tr>
If we take this scenario, the above solution will make the test as passed even though the unique id is repeated in the same cell. If you want to validate those kinds of scenarios too, I think the best solution would be,
cy.get(".table")
.then($el => {
expect($el[0].innerText.split('unique_value').length).to.equal(2)
})
in this case, if the table does not contain unique_value the array length will be 1 and if it has more than 1 unique_value the array length will be more than 2 so, this will work with any string, paragraph, table, etc.
cheers.

Related

Target search results number in variable

I'm trying to target the number of search results on our website for each search term so that I can see how many results each one pulls in.
I'm working off of this article, but I can't get the javascript function correct to pull out the number (which could be as high as 2000) and put it into a variable.
<div class="search-results-text"><strong>732 results</strong> found for ‘<strong>search term</strong>’</div>
Hoping someone can help me out with the javascript function that would grab that number before "results". Thanks!
You would probably get away with a custom Javascript variable like this:
function() {
return document.querySelector('.search-results-text strong').innerText.split(" ")[0];
}
The querySelector with the CSS selector gets the Element, innerText is the text without the markup, the split splits the string up by whitespace, which gives you an array, and the first element of that array is your number (array are index starting with zero, so [0] refers to the first element).
This is not particularly elegant (for one you probably want to add some sort of error handling), and you could actually replace document.querySelector('.search-results-text strong').innerText with a DOM type variable in GTM (which by default returns the text of the element).
I don't think you can get the number with CSS selectors alone.

How to make sequalize update to return the updated object?

With the update function, I'm currently getting the number of the affected rows. Is there any way I can get the key and values of that row instead of the count?
It's possible in Postgres using the options.returning: true as documented in the update API.
Update multiple instances that match the where options. The promise
returns an array with one or two elements. The first element is always
the number of affected rows, while the second element is the actual
affected rows (only supported in postgres with options.returning
true.)
Together with the number of affected rows you are getting in the array, the second parameter is the affected rows you want.

Fastest way to search string for substring using jQuery

I am using DataTables plugin for jQuery. Within the DataTable I have approximately 16 tr rows with 4 td columns each. The DataTables plugin provides an API extension that allows searching for a string in all cells of the table or in all cells of a specified column.
The search extension returns an array of row indices where a match was found. For example, [3, 7, 10, 11]. The search extension originally supported an exact match search which I had to modify from:
if (val == sSearch)
to:
if (val.indexOf(sSearch) > 0)
My customization is certainly the cause of the performance issues I'm having, but it was necessary since the contents of the cells are updated dynamically and therefore unpredictable for performing an exact match search.
An example haystack:
<input id="_HeatOfRejection" class="form-control text-right text-box single-line" type="text" name="HeatOfRejection" measureid="HeatLoad" value="5000.0" uomid="MBH">
An example needle:
' measureid=\"HeatLoad\" '
The average time required to perform a search for needle is ~17.5ms and since the inner loop contains ~16 different needles with an outer loop causing additional loops of the inner loop, the processing time is too noticeable. It's not horrible, but can take 2-3 seconds. On that note, this is not a critical function.
What I am wanting to know is if there is a faster way than using indexOf() to perform this search. Using a jQuery selector might be faster, but the id is unknown/unimportant to the search. Multiple controls can contain the needle and so I have to search the entire column.
To search for an element having an attribute with a specific value, you can use
$("[measureid='HeatLoad']");
It will return all the elements having attribute 'measureid' with value 'HeatLoad'.

How does DataTables row-selector work?

I have a datatable with a number of rows:
var table = $('#mytable').DataTable(...)
And I'm trying to find the rows that contain <a>'s with specific data values.
From the documentation, I'd expect is that table.rows('<magic row-selector>') to work, for some value of <magic row-selector>. But even the simplest selectors don't seem to work the way I'd expect them to.
The docs say that if I pass a string to rows(), it is treated as a JQuery selector operating on the the <tr> elements.
http://datatables.net/reference/type/row-selector
Now I know for certain that each of these rows contains a number of 's - I can see them in the debugger if I examine the outerHTML of the elements returned by table.rows.nodes(). So I'd expect that this would return all rows:
table.rows('a')
But it returns none.
What am I not understanding?
What selector should I use, to find all of the rows that contain <a>'s with a specified value for a data attribute?
edited in response to answer
davidkonrad's answer provides some help - I need to pass a jQuery selector object, rather than a string.
Unfortunately, it seems that I need to construct the jQuery selector object before I define the table. I'm not sure I understand why, it seems an unreasonable restriction, but playing around with his fiddle, I did see differences in the rows returned by table.rows(selector) between when I defined the selector before or after I initialized the table.
In my case, then, that makes this approach unusable, because what I'm trying to do is to remove rows that have certain values set in data attributes. There is no way for me to know what values the user might have selected before I construct the table.
I also think the documentation is a little bit cryptic on that point :) The meaning is
By "jQuery selector" there is meant "the jQuery object returned by a $(selector)"
Only jQuery objects containing <tr>'s is allowed
On paginated tables, you must create the "jQuery selector" before instantiating the dataTable
So, if you want to pass a jQuery object to a dataTables API instance, that contains all rows where any <td> contains the text "test"
var selector = $('tr:contains("test")');
var table = $('#example').DataTable();
var rows = table.rows(selector).data();
//now you can iterate
for (var i=0;i<rows.length;i++) {
//each rows[i] is an array of the rows columns
console.dir(rows[i]);
}
if you want to pass a jQuery object to a dataTables API instance, that contains all rows where any <td> contains an <a> containing a certain text, like "test"
var selector = $('tr a:contains("test")').parent().parent();
...
var rows = table.rows(selector).data();
...
the above selectors in an example -> http://jsfiddle.net/q2p2n23m/

Why does .splice always delete the last element?

In the javascript, there are two arrays:tags[] and tags_java[]. I use .splice to delete certain items, which of the same index in the two arrays. The tags[] works fine, but tags_java doesn't, it seems always delete the last item.
Here is the code and the jsfiddle link.
var tag = $(this).text();
var index = $.inArray(tag, tags);
tags.splice(index,1);
tags_java.splice(index,1);
Nah, both don't work, because you're not actually finding the correct index of your tag.
Why not? Because $(this).text() includes the delete mark you added, × - e.g. "Morning×". Since that's not in your tags array, index will be -1. tags.splice(-1, 1); will remove 1 item from the end of the array.
In general, it's never a good idea to use presentation text (i.e. the text of your tag element) as data (e.g. using that text as a lookup value in an array). It's very likely that it'll be broken when something changes in the presentation - like here. So a suggestion would be to store the data (what you need to look up the tags) as data - e.g. using the jQuery-provided data() API - even if it seems redundant.
Here's a quick example - just adding/replacing two lines, which I've marked with comments starting with "JT": JSFiddle
Now, instead of looking up by $(this).text(), we're looking up by the data value "tagValue" stored with $(this).data() - that way, the lookup value is still bound to the element, but we're not relying on presentation text.
If the tag is not in the tags array, $.inArray will return -1, which would then cause the last item to be deleted.
You have to make sure that the item is actually in the array.

Categories

Resources