Use Cypress functions on variables - cypress

I'm looping throw all of the .row and need to grab the inner elements within .row. Is there a way to do this? I wasn't able to find any documentation on this on Cypress' website.
let num = 0
cy.get('.row').each(row => {
let rowDiv = cy.get(row).get('div') // not correct
let rowBtn = cy.get(row).get('button') // not correct
cy.get(rowDiv).should('have.text', 'Task ' + num)
cy.get(rowBtn).should('have.text', "Btn ' + num)
num++
})

You can use cy.wrap() to turn the yielded JQuery elements back into Cypress Chainables. Additionally, cy.each() can yield you the index of the current iteration, so instead of having to use num, you could just use that index variable.
cy.get('.row')
.each((row, rowIndex) => { // yields JQuery element and current iteration
cy.wrap(row).find('div').should('have.text', `Task ${rowIndex}`);
cy.wrap(row).find('button').should('have.text', `Btn ${rowIndex}`);
});

Related

Getting the number of a specific elements inside a div on Cypress

How to get the number of divs that contain 'userid' from the div with id="chatListHolder"
https://i.stack.imgur.com/QzzLh.png
If a command that yields an element finds more than one element, it will yield all of them. So, we can then check the yielded array of element's length.
cy.get('#chatListHolder')
.should('have.length', 1); // we can change that 1 to whatever number we'd like
// or if we need to do something with that
cy.get('#chatListHolder')
.its('length').should('be.gt', 1);
// or another possibility
cy.get('#chatListHolder')
.its('length')
.then((length) => {
// whatever needs to be done with the length variable
});

CYPRESS - Making the ":contains()" in a filter selector case-insensitive

I am attempting to use the .filter command of cy.get() to return multiple instances of a DOM object that has the same word, but different cases, and can't get it working.
Eg: I want the following code example to return both Hello, hello and even heLLo
cy.get('tbody tr')
.filter(':contains("hello")')
Update: One further piece of information that may affect things is what I am doing after this. Here's a beefier piece of code example:
cy.get('tbody tr')
.filter(':contains("hello")')
.within(() => {
cy.get('td').then(($rows) => {
<do stuff>
};
};
Is this even possible? According to the documentation here the text selection is case-sensitive, but I'm hoping there is another option, eg: am I able to use Regex in this instance instead?
Many thanks in advance.
You are quite right, .contains(...) is not the way, it only returns one result, in the docs
.contains() yields the new DOM element it found.
One way to filter by text case-insensitive is to use a .filter() with callback.
Testing this
<table>
<tbody>
<tr><td>hello</td></tr>
<tr><td>Hello</td></tr>
<tr><td>heLLO</td></tr>
<tr><td>goodbye</td></tr>
</tbody>
</table>
this test succeeds
cy.get('tbody tr')
.filter((i, el) => el.innerText.toLowerCase().includes('hello'))
.should('have.length', 3) // 3 out of 4 rows
or you can add your own pseudo
Cypress.$.expr.pseudos.containsInsensitive = function(a, i, m) {
return Cypress.$(a).text().toLowerCase()
.indexOf(m[3].toLowerCase()) >= 0;
};
cy.get('tbody tr')
.filter(':containsInsensitive("hello")')
.should('have.length', 3) // 3 out of 4 rows
or if you prefer regex
Cypress.$.expr.pseudos.match = function(a, i, m) {
const expr = m[3].split('/')[1]
const flags = m[3].split('/')[2]
const regex = new RegExp(expr, flags)
return regex.test(Cypress.$(a).text())
};
cy.get('tbody tr')
.filter(':match(/hello/i)')
.should('have.length', 3) // 3 out of 4 rows
How about you just use .contains() then you can pass the case sensitivity flag matchCase as false. Cypress Docs
cy.get('tbody tr').contains('hello', { matchCase: false })

Is there any way to find the runtime values of a Selector with testcafe and VS Code

I am trying to debug a testcafe test with node from VSCode and want to verify that the selector used in the code identifies the correct element and retrieve the values of the variables that is declared in a function / variable assigned with a selector.
I start the test.js file in debug mode with command:
"C:\Program Files\nodejs\node.exe" --inspect-brk=21496 testcafe.js chrome tests.js --env=dev --skip-js-errors
The test stop at the breakpoint and when the below line is reached, i wanted to verify what exactly is inside that variable (element) such that i can verify if the selector is selecting the desired element.
let element= Selector(".unique_selector_class").parent(2);
I expect to find the properties of the selected element in the debug mode. e.x., length of the 'element' if its an array, outertext of the element.
Update:
I think what i said earlier was little confusing. I have a method like this which is called by a test.
`async deleteSelectedComponentsMethod()
{
let element = await Selector(".uniqueSelectorClass");
let numberOfSelectedComponents = element.length;
for (let i = 0; i < numberOfSelectedComponents; i++)
{
await t.click(deleteSelectedComponent.nth(i));
}
}`
In this method i wanted to see what is inside the variable 'element', so that i can write a logic as in the code. PS: the element am trying to identify will be visible only when the mouse is hovered.
The value in the variable 'element' returns a function that does not help to find the runtime values in the element
UPDATE:
Selector doesn't return an array when multiple elements match it. Use await selector.count to retrieve the number of matched elements and selector.nth() to enumerate them:
async deleteSelectedComponentsMethod()
{
let element = Selector(".uniqueSelectorClass");
let numberOfSelectedComponents = await selector.count;
for (let i = 0; i < numberOfSelectedComponents; i++)
{
await t.click(deleteSelectedComponent.nth(i));
}
}
Read more about the selector.count property in the Using Selectors article.
ORIGINAL ANSWER:
You can use the await keyword to retrieve information about elements represented by Selectors. Once we will implement this feature: #3244, you will be able to debug Selectors by typing selector expressions in the browser console.

RxJs, not display in dom, but console works

Why do the outputs only display in one of element
(#skip-result or #distinct-result) not both of them ?
but if i try outputting the result from those two observable
below to console it works
you can check code here
var input$ = Rx.Observable.fromEvent(input,'input')
var x$ = input$
.debounce(1000)
// skip two character in string, from input value
// then, display it in #skip-result
x$
.map(v=> v.target.value)
.filter(v=> v.length > 2)
.flatMap(v=>
Rx
.Observable
.from(v)
.skip(2)
.reduce((x,y)=> x + y)
)
.subscribe(s=>{
$('#skip-result').text('Skip Value is ' + s)
})
// search distinct in string, from input value
// then, display it in #distinct-result
x$
.map(e=> e.target.value)
.filter(e=> e.length > 0)
.flatMap(v=>
Rx
.Observable
.from(v)
.distinct()
.reduce((x,y)=> x + y)
)
.subscribe(x=>{
$('#distinct-result').text('Distinct value is ' +x)
})
In the JSBin you've referenced, you haven't imported jQuery, but you appear to be using the jQuery selector to set the contents of both the #skip-result and #distinct-result DOM elements. This will throw an error.
If instead you changed them to set the innerHTML property, which one subscription already looks to be doing, you should get your expected behaviour.
.subscribe(s => {
skipResult.innerHTML = 'Skip Value is ' + s
})
EDIT
After a second look, your markup isn't being closed properly. Specifically, #skip-result is being made a child of #distinct-result.

Dynamically assign variable in Go template [duplicate]

I have a Golang array I'm passing to my html file on the front end.
I know that
'{{ index .Array 0}}'
works and pulls the first element from the array. But I want to do a Javascript for-loop and print every element in the array like so
<script type="text/javascript">
function loop() {
html = ""
for(var i = 0; i<5; i++) {
html += "{{ index .Array " + i + "}}";
}
}
But this doesn't work. Something about separating the go array index string, HTML/Javascript doesn't like it and it won't load.
It's a syntactical error that I just can't pin down.
Any ideas?
You need to understand something:
Template actions such as {{index .Array 0}} are executed at server side in your Go application.
Javascript code is interpreted and run at client side in the browser.
The template parameter value used in template actions (Array in your example) does not exist at client side (e.g. as a Javascript object). And Javascript code is not run by the template engine. So the template parameter (value) and Javascript (execution) live in 2 different "spaces".
Having said that, it is not possible to mix template actions/variables and Javascript execution.
You have 2 options:
1) Do what you want to do with template actions.
2) Use the template to create Javascript code which when executed at the client side will construct/recreate the array as a Javascript object so it will be available for further Javascript processing.
Note that if you just want to loop over the array once, creating a Javascript array is not neccessary, you can simply render the JavaScript code that would be the loop body inside a {{range}} template action. See Simon's answer as an example to this.
Elaborating #1
You can use the {{range .Array}} action to loop over Array, and the block is executed for each element, pipeline set to the array element so you can output the array elements like this:
{{range .Array}}
{{.}}
{{end}}
Of course you can put anything else inside the block, not just the array elements. You can even access the current index like this:
{{range $idx, $value := .Array}}
Index = {{$idx}}; Element = {{$value}}<br>
{{end}}
Elaborating #2
Let's say your Array contains int numbers, you can recreate it in Javascript and loop over it in Javascript with a template like this:
<script>
var arr = [
{{range .Array}}
{{.}},
{{end}}
];
// Now you have a javascript array: arr, loop over it to do something:
html = "";
for(var i = 0; i < arr.length; i++) {
html += " " + arr[i];
}
</script>
Or since the template engine supports "rendering" arrays and slices as JavaScript arrays, you can simply write:
<script>
var arr = {{.Array}};
// Now you have a javascript array: arr, loop over it to do something:
html = "";
for(var i = 0; i < arr.length; i++) {
html += " " + arr[i];
}
</script>
You're not "passing a Golang array to the front end" .. your template is being rendered server side. That is an important distinction.
When you think about it like that .. the syntactic issue becomes clear. You are attempting to intermix Go's template syntax with Javascript right in the middle of expressions. That simply isn't correct. You should use a Go loop that, when rendered, produces valid Javascript for the client to consume:
var javaScriptHtmlVariable = "";
{{ range .Array }}
javaScriptHtmlVariable += '{{.}}';
{{ end }}
Which would render:
javaScriptHtmlVariable += 'One';
javaScriptHtmlVariable += 'Two';
javaScriptHtmlVariable += 'Three';
javaScriptHtmlVariable += 'Four';
// etc..

Resources