testcafe higher order selector - javascript

I am trying to create a higher order selector which I can reuse by changing a text parameter. In the snippet below, when I am trying to perform t.click using actualSelector, it's not working as expected. When I console log the value for the actualSelector, i see whole item values are printed.
Seems I am not using it right way. Can you please help me with this.
e.g
const testItemNameGenericSelector = (itemName) =>
Selector(
".ms-Callout-container .ms-Callout-main div div"
)
.withText(itemName);
...
const itemNameToSelect = "Test Item-8ab1ec12-e719-4ab6-a0a3-ed538143d6d3";
const actualSelector = testItemNameGenericSelector(itemNameToSelect)
...
console.log(`selecting ${await actualSelector().textContent}`)
Below is full testcafe code for this test.
fixture`Getting Started`
.page // declare the fixture
`https://hasans30.github.io/testpage/dropdown.html`; // specify the start page
//then create a test and place your code there
test("My first test", async (t) => {
const testItemNameGenericSelector = (itemName) =>
Selector(
".ms-Callout-container .ms-Callout-main div div"
)
.withText(itemName);
const buttonSelector = Selector('.ms-Button-label');
const selectedValue = Selector('.ms-Dropdown-title');
const itemNameToSelect = "Test Item-8ab1ec12-e719-4ab6-a0a3-ed538143d6d3";
const actualSelector = testItemNameGenericSelector(itemNameToSelect);
await t.click(buttonSelector,{speed:0.51})
console.log(`selecting ${await actualSelector().textContent}`)
await t.click(actualSelector,{speed:0.51})
await t.expect(await selectedValue().textContent).eql(itemNameToSelect);
});

Related

How to access individual object in array using Javascript

Hi I have exported using data (hawkers collection) using getDocs() from Firebase.
After that I put each hawker data as an object in an array called allStall as shown in the screenshot of the console log below.
Question 1 - How do I access each individual object in my allStall array. I try to use .map() to access each of it, but i am getting nothing.
Do note that I already have data inside my allStall array, see screenshot above.
[Update] map doesn't work in code below because field is stallname not stallName. However, it needs to be async + await if using/call in/from other function.
Question 2 - Why is there [[Prototype]]: Array(0) in my allStall array
export /*Soln add async*/function getAllStall(){
var allStall = [];
try
{
/*Soln add await */getDocs(collection(db, "hawkers")).then((querySnapshot) =>
{
querySnapshot.forEach((doc) =>
{
var stall = doc.data();
var name = stall.stallname;
var category = stall.category;
var description = stall.description;
var stallData = {
stallName:name,
stallCategory:category,
stallDescription:description
};
allStall.push(stallData);
});});
console.log(allStall);
//Unable to access individual object in Array of objects
allStall.map(stall =>{console.log(stall.stallName);});}
catch (e) {console.error("Error get all document: ", e);}
return allStall;
}
In my main js file, i did the following:
useEffect(/*Soln add await*/() =>
{
getAllStall();
/*Soln:replace the statement above with the code below
const allStall = await getAllStall();
allStall.map((stall)=>console.log(stall.stallname));
*/
}
);
You are getting nothing because allStall is empty since you are not waiting for the promise to be fullfilled
try this
export const getAllStall = () => getDocs(collection(db, "hawkers"))
.then((querySnapshot) =>
querySnapshot.map((doc) =>
{
const {stallName, category, description} = doc.data();
return {
stallName:name,
stallCategory:category,
stallDescription:description
};
});
)
try to change use effect like this
useEffect(async () =>
{
const allStats = await getAllStall();
console.log(allStats)
allStats.forEach(console.log)
}
);
A very big thanks to R4ncid, you have been an inspiration!
And thank you all who commented below!
I managed to get it done with async and await. Latest update, I figure out what's wrong with my previous code too. I commented the solution in my question, which is adding the async to the function and await to getDocs.
Also map doesn't work in code above because field is stallname not stallName. However, it needs to be async + await if using in/calling from other function.
Helper function
export async function getAllStall(){
const querySnapshot = await getDocs(collection(db, "hawkers"));
var allStall = [];
querySnapshot.forEach(doc =>
{
var stall = doc.data();
var name = stall.stallname;
var category = stall.category;
var description = stall.description;
var stallData = {
stallName:name,
stallCategory:category,
stallDescription:description
};
allStall.push(stall);
}
);
return allStall;
}
Main JS file
useEffect(async () =>
{
const allStall = await getAllStall();
allStall.map((stall)=>console.log(stall.stallname));
}
);
Hurray

To set data in attribute "VALUE" using puppeteer

I have a use case where I need to set VALUE for a input tag.
'''
module.exports = async function(selectorId, inputString) {
const randomDate = inputString;
console.log(rdate)
await this.page.evaluate(((el) => {el.value = ""}), selector[0]);
await this.page.evaluate(((el,randomDate ) => {el.value = randomDate },randomDate ), selectorId[0]);
await this.page.waitForTimeout(1000);
};
'''
Here this code is working fine but it is not doing any action on UI, like not setting the selectorId.value as per definition, I am using xPath for the object. Can any one help on same.

Check if element class contains string using playwright

I am trying to get the element of day 18, and check if it has disabled on its class.
<div class="react-datepicker__day react-datepicker__day--tue" aria-label="day-16" role="option">16</div>
<div class="react-datepicker__day react-datepicker__day--wed react-datepicker__day--today" aria-label="day-17" role="option">17</div>
<div class="react-datepicker__day react-datepicker__day--thu react-datepicker__day--disabled" aria-label="day-18" role="option">18</div>
this is my code, assume
this.xpath = 'xpath=.//*[contains(#class, "react-datepicker__day") and not (contains(#class, "outside-month")) and ./text()="18"]'
async isDateAvailable () {
const dayElt = await this.page.$(this.xpath)
console.log(dayElt.classList.contains('disabled'))) \\this should return true
I can't seem to make it work. Error says TypeError: Cannot read property 'contains' of undefined. Can you help point what I am doing wrong here?
Looks like you can just write
await expect(page.locator('.selector-name')).toHaveClass(/target-class/)
/target-class/ - slashes is required because it's RegExp
For check few classes by one a call I use this helper (It's because api way doesn't work for me https://playwright.dev/docs/test-assertions#locator-assertions-to-have-class):
async function expectHaveClasses(locator: Locator, className: string) {
// get current classes of element
const attrClass = await locator.getAttribute('class')
const elementClasses: string[] = attrClass ? attrClass.split(' ') : []
const targetClasses: string[] = className.split(' ')
// Every class should be present in the current class list
const isValid = targetClasses.every(classItem => elementClasses.includes(classItem))
expect(isValid).toBeTruthy()
}
In className you can write few classes separated by space:
const result = await expectHaveClasses(page.locator('.item'), 'class-a class-b')
You have to evaluate it inside the browser. $ will return an ElementHandle which is a wrapper around the browser DOM element, so you have to use e.g. evaluate then on it. Or simply $eval which will lookup the element, pass it into a callback which gets executed inside the browsers JavaScript engine. This means something like that would work:
// #ts-check
const playwright = require("playwright");
(async () => {
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.setContent(`
<div id="a1" class="foo"></div>
`)
console.log(
await page.$eval("#a1", el => el.classList.contains("foo1"))
)
await browser.close();
})();

TestCafe: console.log() the value of a selector

I try to select the text value SR-12948 of the span below with a TestCafe selector and then assign it to a const. So I can add it as a string to the withAttribute method. That doesn't really work. So I want to check what the value of my const srCaseIDString is. Is it possible to do that with a console log? So it logs the value of that const in the same terminal as my test results and errors appear?
This is my test:
<span data-template="" data-test-id="2014100715101007275150" class="supporting_text_il" style="">SR-12948</span>
import { Selector, t } from "testcafe";
import XPathSelector from "../utils/xpath-selector";
const button= Selector("#button");
test("First Test", async (t) => {
await t
.click(button);
const srCaseID = await XPathSelector("//span[#data-test-id='2014100715101007275150']").innerText;
console.log(srCaseID);
const iframeCase = await Selector('iframe').withAttribute('title', srCaseIDString);
await t
.switchToIframe(iframeCase);
});
Thanks!
innertext != innerText, it is case sensitive.
This works just fine:
const elementInnerText = await Selector('#id').innerText;
console.log(elementInnerText);

Updating a field in an object in MongoDB

I have this code:
const project = await Project.findOne({"code":currentUser.groupcode}); // this works
const card = await Card.findOne({"id":req.body.id}); // this works
card.panel = req.body.newSection;
card.save(); // this works
project.cards[`${req.body.id}`].panel = req.body.newSection;
project.save(); // this does not work
I'm trying to update the panel field in both the cards collection and projects collection.
When I log project.cards[`${req.body.id}`].panel, it is the correct value, so it is the correct routing.
What's wrong here?
Try putting await before your save statements and see if it resolves the issue.
If I have guessed your schemas correctly this is the answer:
const project = await Project.findOne({ code: currentUser.groupcode }).populate("cards");
const card = await Card.findOne({ id: req.body.id }); // this works
card.panel = req.body.newSection;
await card.save(); // this works
const cardIndex = project.cards.findIndex(card => card._id.toString() === req.body.id);
project.cards[cardIndex].panel = req.body.newSection;
await project.save(); // this does not work
Ok
I needed to add
project.markModified(`cards.${req.body.id}.panel`)
before project.save();

Categories