Cycle through test data from within a Testcafe test? How to? - testing

I'm wanting to log into an app, run several searches from test data, then log out. I don't want to login and out for each item in the data set, which would be the case if I coded this way...
dataSet.forEach(data =>{
test('Search Test', async t => {......
I would like to be able to...
test('Search Test', async t => {......
foreeach(data in Data set)
call a function to search
call a function to verify search return.
Something like this...
test('Simple Search Test', async t => {
//await t
await loginPage.login(loginName, password);
await t
.expect(getURL()).contains('home')
// Check logged in user display...
.expect(pageHeader.userName.withText(data.loggedInUser).visible).ok()
dataSet.forEach(data =>{
leftSidebar.searchWithCriteria(data.criteria, 'Filename');
recordNav.verifyTotal(data.srchresult);
});
// Log out
await pageHeader.logout();
await t
.expect(loginPage.copyRight.visible).ok();
});
enter code here
I've tried everything, but can't get it to work. Is this possible or does the entire test have to be run for each data record in the set?

TestCafe allows you to loop through test code in any manner, including iterating through custom data.
To help us determine why this does not work for you, please provide an example that I can run on my machine (including the test code, page object, and the tested page's URL).

I got it to work using this...
for (var i = 0; i < dataSet.length; i++){
leftSidebar.searchWithCriteria(dataSet[i].criteria, 'Filename');
recordNav.verifyTotal(dataSet[i].srchResult);
}

Related

playwright find child element(s) within locator

I'm trying to write a function to find child(ren) element(s) within a locator something like:
async findElements(locator: Locator){
return locator.querySelector(some/xpath/or/css);
}
However, I'm seeing the querySelector is not available in Locator. What is the equivalent of querySelector?
I figured it out,
locator.locator(some/xpath/)
I have just started working with playwright. So this may not be the exact answer that are looking for.
I am studying playwright with an existing repository.
[https://github.com/twerske/ng-tube/blob/main/src/app/video-grid/video-grid.component.html]
In this scenario I just want to know that I am getting a list of cards back.
<div class="videos-grid">
<mat-card *ngFor="let video of videos" class="video-card">
I don't need a reference to a parent for this situation. I am able to simply reference the child by class videos-grid. This all exists inside of a angular's For loop. I know Svelte and other frameworks iterate through lists in different ways.
test.only('ngTube has header and cardList', async ({browser}) => {
const page = await browser.newPage();
const context = await browser.newContext();
await page.goto("http://localhost:4200/")
const title = await page.locator('.header-title').textContent();
const videoList = (await page.locator('.video-card').allTextContents()).length;
// await page.pause();
expect(title).toStrictEqual('ngTube');
expect(videoList).toBeGreaterThan(0)
})
Because I want all text contents I can get everything with the classname '.video-card'.
I guess what I am getting at is as long as you can access an identifier you should be able to directly access it. As I run through the documentation more and scenarios I will update/add to this answer.

TestCafe : How can I make TestCafe to run some application code only once before all the fixtures

In my application, I want to set up some test data from the UI before running any Fixture. I want to do this set up only once and don't want to do this before each fixture.
Can someone please help me on how to do this ?
I tried to use approach mentioned on below thread but I cannot use test controller - t inside before.
https://testcafe-discuss.devexpress.com/t/run-the-same-before-and-after-hook-for-all-fixtures-and-configure-a-baseurl/551
I have an idea you can check if you feel it works for you as below, you will still use beforeEach in this case as you wish to access to t:
let didSetup = false;
fixture`yourFixture`
.beforeEach(async t => {
if (!didSetup) {
// You set up things here
await yourSetup();
didSetup = true;
}
// Otherwise won't do anything
})

ExpressJS - Small curiosity

My thing is a small project.
In main what it does is that the "server" will get a call from the link directly what will run some functions that will update the database and the data that has to be shown.
I will show what I mean:
function updateData(){
connection.query(`SELECT * FROM muzica WHERE melodie = "${updateList()}"`, function (error, rezultat, fields) {
if (error) {console.log('err la selectare')};
//express output
let data = {
melodie: rezultat[0].melodie,
likes: rezultat[0].likes
}
console.log(data.likes);
app.get('/like', (req,res) =>{
res.json(`${data.likes}`);
});
}
setInterval(()=>{
updateData();
}, 20000)
Uhh, how to explain it, I'm so bad at this...
So, in main, I'm new to back-end work, everything that I did was based on their Documentation as I learn way faster by my needs than some guides and so on.
So, when I or someone does my http://website/like it should show just data.likes, cause that is all that I need, don't count data.melodie (i will clean that later on) after I finish all the code.
Anyway, whenever I do website/like data.likes is not updating to the new database data.likes.
For example, data.likes before were 5, in a few minutes it can be 2 but whenever I call website/like show "5" than its new value 2.
Don't be hash on me, I'm new and I want to learn as much as I can, but I can't understand the above case, by my logic it should ALWAYS show what its in database when it refreshes each 10 seconds(I run this in localhost so I will not stress any online server).
But if there is any better way to check for databases update than "setInterval" please notice me.
It's hard to learn alone without a mentor or someone else to talk about this domain.
Thank you for your time!
Kind regards,
Pulsy
You have things a bit inside out. A request handler such as app.get('/like', ...) goes at the top level and you only ever call it once. What that statement does is register an event handler for any incoming requests with the /like path. When the server receives an incoming request for /like, it will then call the function for this route handler.
You then put inside that route handler the code that you want to run to generate the response and send the response back to the client.
app.get('/like', (req, res) => {
connection.query(`SELECT * FROM muzica WHERE melodie = "${updateList()}"`, function (error, rezultat, fields) {
if (error) {
console.log(error);
res.sendStatus(500);
} else {
//express output
let data = {
melodie: rezultat[0].melodie,
likes: rezultat[0].likes
}
res.json(data);
}
});
});
The endpoints need to be outside of any functions in express.
For example, if you look at the express "hello world" example here, you will see that they have a basic app that only has a single GET endpoint defined which is "/" so you would access it by running "localhost/" or "127.0.0.1/".
In your case, you want your endpoint to be "/like", so you must define something like:
const express = require('express')
const app = express()
const port = 3000
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
app.get('/like', (req, res) => {
// do database stuff and assign data variable
// res.json(data);
}

How to use ".contains" assertion to match one of the values

As per my application, clicking on one of the links can open one of the URLs from two URLs.
Eg: Clicking on Link - X, it can open one of the below URLs :
http://example.com/value1 or http://example.com/value2
I have to write an .contains assertions for this which can look something like this:
expect(currentUrl).contains(value1 or value2)
As per the TestCafe documentation, contains does not have support for a regular expression and I do not want to use Match as I have to pass incomplete URL there.
Please let me know how this can be done.
Thanks.
I have solved it using match assertion as below but still it would be good if this can be somehow done with contain assertion as well.
expect(currentUrl).match(/value1|value2$/)
Check the following "current location" example test:
import { ClientFunction } from 'testcafe';
fixture `Fixture`
.page `https://google.com`;
test('Check location', async t => {
// Some actions and assertions...
await t
.navigateTo(/*...*/)
.click(/*...*/);
// Then check our location
const getLocation = ClientFunction(() => document.location.href);
const location = await getLocation();
await t
.expect(location.includes('microsoft') || location.includes('google')).ok();
});

How do you poll for a condition in Intern / Leadfoot (not browser / client side)?

I'm trying to verify that an account was created successfully, but after clicking the submit button, I need to wait until the next page has loaded and verify that the user ended up at the correct URL.
I'm using pollUntil to check the URL client side, but that results in Detected a page unload event; script execution does not work across page loads. in Safari at least. I can add a sleep, but I was wondering if there is a better way.
Questions:
How can you poll on something like this.remote.getCurrentUrl()? Basically I want to do something like this.remote.waitForCurrentUrlToEqual(...), but I'm also curious how to poll on anything from Selenium commands vs using pollUntil which executes code in the remote browser.
I'm checking to see if the user ended up at a protected URL after logging in here. Is there a better way to check this besides polling?
Best practices: do I need to make an assertion with Chai or is it even possible when I'm polling and waiting for stuff as my test? For example, in this case, I'm just trying to poll to make sure we ended up at the right URL within 30 seconds and I don't have an explicit assertion. I'm just assuming the test will fail, but it won't say why. If the best practice is to make an assertion here, how would I do it here or any time I'm using wait?
Here's an example of my code:
'create new account': function() {
return this.remote
// Hidden: populate all account details
.findByClassName('nextButton')
.click()
.end()
.then(pollUntil('return location.pathname === "/protected-page" ? true : null', [], 30000));
}
The pollUntil helper works by running an asynchronous script in the browser to check a condition, so it's not going to work across page loads (because the script disappears when a page loads). One way to poll the current remote URL would be to write a poller that would run as part of your functional test, something like (untested):
function pollUrl(remote, targetUrl, timeout) {
return function () {
var dfd = new Deferred();
var endTime = Number(new Date()) + timeout;
(function poll() {
remote.getCurrentUrl().then(function (url) {
if (url === targetUrl) {
dfd.resolve();
}
else if (Number(new Date()) < endTime) {
setTimeout(poll, 500);
}
else {
var error = new Error('timed out; final url is ' + url);
dfd.reject(error);
}
});
})();
return dfd.promise;
}
}
You could call it as:
.then(pollUrl(this.remote, '/protected-page', 30000))
When you're using something like pollUntil, there's no need (or place) to make an assertion. However, with your own polling function you could have it reject its promise with an informative error.