Checking button text matches a certain string in Nightwatch.js - selenium

I'm having a heck of a time trying to write a test where I check that text on a button matches a certain string. I tried ".valueContains", ".attributeContains" and got blank or null, and I've tried getText(), but that only seems to return an object.
I feel like it's something obvious I'm missing, so any help would be appreciated!

Based on what you have written so far in your question, I am wondering if there is there a reason you cannot use .containsText?
.waitForElementVisible('.yourclass', this.timeout)
.assert.containsText('.yourclass', 'Text of Button you expect to match')
http://nightwatchjs.org/api#assert-containsText

Without actually looking at the code its little difficult to predict whats going on. However all of the methods in selenium return a promise, so you need to wait for it to resolve.
function async getTextOfButton() {
const element = await driver.findElement(By.className('item-class'));
const text = await element.getText();
}
If you are not using async/await you could do
driver.findElement(By.className('item-class')).then(function(element) {
element.getText().then(function(text) {
console.log(text);
});
});

Related

storybook add message to interaction testing?

I was wondering if it is possible to add a message instead of showing the values when the interactions tests are run in storybook.
for example:
FilledForm.play = async ({ canvasElement }) => {
const buttonEl = getByRole('button')
await expect(buttonEl.textContent).toContain('some button text');
//this gives `expect('some button text').toContain('some button text')`
//would have been better if it gave: `expect textContent to contain 'some button text'`;
any clue if that is possible? FYI it is not a deal breaker for me, it a cheaper alternative to have the test-runner and it works on a case by case, just want to know if there is a way to put extra message when showing the test result.

Is there a way I can find an element in a FlatList using Detox E2E testing

So while testing my application, I am using a data set. Since the data set has many entries, I am using FlatList to display my list. After creating the list, I want to be able to verify and tap on certain list items. Below, I have attached the code which I am trying to use and it does not work for me. If anyone has a better idea to do this, please let me know.
The approach I think should be taken. I can't think of anything else to make the FlatList scroll and find the item I am looking for.
let isNotFound = true;
while (isNotFound) {
try {
await waitFor(element(by.id((edit_details.index).toString()))).toBeVisible().withTimeout(2000)
isNotFound = false;
} catch (e) {
await element(by.id('credit_history_list')).swipe('up', 'slow', 0.2)
}
}
await element(by.id((edit_details.index).toString())).tap();
It does help scroll the list and it keeps scrolling while it actually finds the entry I am looking for. But the .tap() function does not work. Instead, detox moves on with the next line of code.
Is there a better way to do this?
Thanks in advance!
This sounds spot-on with Detox' whileElement() API.
I think that what you're looking for is this:
const itemId = (edit_details.index).toString();
const listId = 'credit_history_list';
await waitFor(element(by.id(itemId))).toBeVisible()
.whileElement(by.id(listId))
.scroll(100, 'down');

How can I get string value of selector?

I mean when we initialize Selector like this:
let stringLocator = 'some element locator'
selector = new Selector(stringLocator)
is that possible to get original string locator somehow like this:
selector.locator
p.s. This question is related to this one where I've found some hacky workarounds to get testcafe display my xpath locators in error.
Testcafe does not support this, but you can use the following approach
function createSelector (locator) {
return Object.assign(Selector(locator), { locator });
}
const selector = createSelector('#button');
console.log(selector.locator)
I had the same issue yesterday. The apiFnChain contains the fnChain you used for the selector. It is behind a symbol. This is what helped me. Maybe this will help you too.
const selector = Selector('button.explore-button').withText('Explore the site')
const selectorFnChain = selector[Object.getOwnPropertySymbols(selector)[0]].options.apiFnChain
console.log(selectorFnChain)
This will give you this:
Selector('button.explore-button'),.withText('Explore the site')
You don't have to get the entire chain but this was the most helpful for me.

cy.clear() not clearing input field properly - Cypress

When I perform
cy.get('#fsp-name').clear().type('random text');
If the text already has value lets say 'assd asd adsdsd' and I perform above command I get something similar to 'random textassd'
I also tried using
cy.get('#fsp-name').clear().should('have.value', '').type('random text');
It works some time and in other times it complains it does not equal to ' '.
And I am trying to do this in a each loop like below
const data = [
{selector:'#name', newValue: 'John'},
{selector:'#phone', newValue: '1234567'}
];
cy.wrap(data).each(field => {
cy.get(field.selector).clear().should('have.value', '').type(field.newValue);
cy.contains('Save').click();
cy.visit('/abc/sdd');
cy.get(field.selector).invoke('val').should('equal', field.newValue);
});
Tried the solutions provided above, but all did not help.
I've ended up using this:
cy.get('#my-input-element').focus().clear();
If that doesn't work, the not so happy workaround is:
cy.get('#my-input-element').invoke('val', '');
When .type somehow did not finish the given string (rare cases):
cy.get('#my-input-element').invoke('val', 'Some text here');
I had a similar problem and It was related to focused and click related. I can suggest trying the following two option. I DON'T know it is right or wrong.
cy.get('#fsp-name').click().clear().type('random text');
OR
cy.get('#fsp-name').click().focused().clear().type('random text');
I was talking to the developer and according to him we are using MaterialUI and have some default component using focused and click event differently. After having both options resolved my problem
.clear() is an alias of .type('{selectall}{backspace}') however depending upon the input field set up this would not work in all cases.
I solved this by using .type('{selectall}{backspace}{selectall}{backspace}') instead of the .clear()
I'm using Cypress version 3.8.3 and I noticed that I have to invoke clear() sometimes two times in a row:
cy.get('#fsp-name').clear();
cy.get('#fsp-name').clear();
Seems like the cypress test runner is getting ahead of app initialization and some helpful article links below
https://www.cypress.io/blog/2018/02/05/when-can-the-test-start/
https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
As of now adding wait before clearing makes the test pass. Let me know if anyone has better solutions
I've had the same problem using Mui React with Cypress and when I called clear an ";" was added.
I've applied the same #Steven Vachon solution calling clear() function of cypress first.
Here my solution:
const clearInputElement = (input) => {
const input2Search = input;
cy.get(input2Search).clear();
cy.get(input2Search).then(($elm) => {
const event = new Event(input2Search, { bubbles: true, cancelable: true });
const input = $elm.get(0); // `as HTMLInputElement` for TypeScript
input.value = "";
input.dispatchEvent(event);
});
};
I ended up having to do clear manually via the DOM:
cy.get('input').then($elm => {
const event = new Event('input', { bubbles: true, cancelable: true });
const input = $elm.get(0); // `as HTMLInputElement` for TypeScript
input.value = '';
input.dispatchEvent(event);
});
I, too, faced a similar issue while using with react-ace editor. I wind up with
function typeContentOnSelectingExistingContent(elementId, content) {
return cy.get(`#${elementId}`).type(`{selectAll}{selectAll}${content}`)
}
Try this, it worked for me:
cy.get('#fsp-name').clear({ force: true }).then(() => {
cy.wait(3000)
cy.get('#fsp-name').invoke('val', '').type(`${valueToBeTyped}{enter}`)
})
Official docs states that:
It is unsafe to chain further commands that rely on the subject after .clear().
That's probably why the code in the original question didn't work, it was chaining clear and type commands:
cy.get('#fsp-name').clear().type('random text');
So, a simple alternative would be something like:
cy.get('#fsp-name').clear()
cy.get('#fsp-name').type('some text')
More about the clear command:
https://docs.cypress.io/api/commands/clear

dragAndDrop using webdriverio

I have tried every single thing to perform dragAndDrop using webdriverio but nothing works. I have also posted a question in the webdriverio gitter but no response. below posted code is one of the ways I tried and its supposed to work but it just doesn't!
` await this.driver.moveToObject(source);
await sleep(2000);
await this.driver.buttonDown(0);
await sleep(2000);
await this.driver.moveToObject(destination);
await sleep(2000);
await this.driver.buttonUp(0);`
I'm not sure what properties are on the source and destination objects you are using but here is an example of how I was able to get it to work using the same commands you are trying.
In my example I have a table with columns that can be re-ordered by dragging and dropping them wherever I want them to be. First I get the two column headers I want to switch
let docIdHeader = browser.element('div[colid="documentid1"]');
let pageCountHeader = browser.element('div[colid="_PAGE_COUNT1"]');
If I log these objects out to the console I can see the properties stored in them.
> docIdHeader
{ sessionId: 'e35ae3e81f1bcf95bbc09f120bfb36ae',
value:
{ ELEMENT: '0.3568346822568915-1',
'element-6066-11e4-a52e-4f735466cecf': '0.3568346822568915-1' },
selector: 'div[colid="documentid1"]',
_status: 0 }
> pageCountHeader
{ sessionId: 'e35ae3e81f1bcf95bbc09f120bfb36ae',
value:
{ ELEMENT: '0.3568346822568915-2',
'element-6066-11e4-a52e-4f735466cecf': '0.3568346822568915-2' },
selector: 'div[colid="_PAGE_COUNT1"]',
_status: 0 }
Now using the same technique you are using and the selector property off of these objects I can get it to work in two ways.
browser.dragAndDrop(docIdHeader.selector, pageCountHeader.selector);
Or
browser.moveToObject(docIdHeader.selector)
browser.buttonDown(0)
browser.moveToObject(pageCountHeader.selector)
browser.buttonUp(0)
I ran this in the REPL interface so I know it works as I could see each step being executed after I sent the commands. If you are not familiar with how to use the REPL I highly recommend learning. You can play around with commands in the console until you figure something out and then add those commands to your tests.
Also, as I stated in my comments above. dragAndDrop() and moveToObject() are going to be deprecated soon and you will likely see a lot of warnings about it when you use these. The correct way to implement a drag and drop action going forward is to use browser.actions(). Unfortunately, I don't have an example of how to do it that way as I haven't played with it yet. If no one provides an example by tonight I will try to get one together for you.
Even I faced this issue wherein the cursor doesn't move to the destination object after buttonDown and using moveToObject twice worked for me.
await this.driver.moveToObject(source);
await this.driver.buttonDown(0);
await this.driver.moveToObject(destination);
await this.driver.moveToObject(destination);
await this.driver.buttonUp(0);