I'm trying to input a date string formatted mm/dd/yyyy into a Kendo React DatePicker control using nightwatch setValue. It seems that no matter what approach I take to select the control it always sets the cursor on the year portion first and typing then only fills in those four characters.
(For example if I provide '05/06/2016', all I see typed into the input is 'mm/dd/0016' and month and day never update.)
The control seems to work fine in a normal scenario if I click with the mouse on the month field, the cursor will display there and if I type 2 characters, a / 2 more characters another / and then the last 4 the control is working properly. It just seems to be an issue with selenium selecting the control and DatePickers default behavior.
I've tried using browser.Key.LEFT_ARROW to see if I could move the cursor left twice first since the accessibility handling allows for it. I also tried calling clearValue() on the input first then typing from scratch but no success on either case.
I would rather not have select the date using the calendar control if I can avoid it.
Here's what my code looks like currently:
const consumerInfo = {
birthMonth: "05",
birthDay: "06",
birthYear: "2016",
birthDate: "05/06/2016",
};
const datePickerSelector = '.myDatePicker';
const datePickerInputSelector = '.myDatePicker .k-input';
browser.waitForElementVisible(datePickerSelector, DEFAULT_WAIT_TIME)
.waitForElementVisible(datePickerInputSelector, DEFAULT_WAIT_TIME)
.setValue('.myDatePicker .k-input, [
consumerInfo.birthYear,
browser.Keys.LEFT_ARROW,
consumerInfo.birthDay,
browser.Keys.LEFT_ARROW,
consumerInfo.birthMonth,
])
.assert.value(
datePickerInputSelector,
consumerInfo.birthDate,
`Birthdate is set to ${consumerInfo.birthDate}`
);
Any suggestions are appreciated.
While not perfect I came up with a solution so hopefully it helps some others should this come up.
The approach ended up being roughly similar to what I proposed above but allowing more time between each operation. I added it into a util function that accepts the selector to target the input control with along with the month/day/year to fill in the control with. It's possible the time intervals can be reduced in places to less than 500ms but without more exhausted testing that was better than 1000ms (which worked) and 100ms (which inconsistently worked).
See below:
const toDatePickerInsertion = (browser, pickerInputSelector) => ({
month,
day,
year,
}) => {
return browser
.click(pickerInputSelector)
.pause(500)
.keys(browser.Keys.LEFT_ARROW)
.pause(500)
.keys(browser.Keys.LEFT_ARROW)
.pause(500)
.keys(month)
.pause(500)
.keys(browser.Keys.RIGHT_ARROW)
.pause(500)
.keys(day)
.pause(500)
.keys(browser.Keys.RIGHT_ARROW)
.pause(500)
.keys(year);
};
Related
I would like to store the text from an object locator and use it for assertion. For instance, I have a trade number - 1234. This trade number only appears after a transaction, so it is not static on other screens. This number is located on several other screens and I need to validate that it appears. I am able to locate the element through inspect and Playwright accepts it, but having issues:
Grabbing the text (1234)
Then setting up an assertion statement to compare it
Below are my humble and naïve attempts:
async getConfirmNumber() {
//Store the contents in the page locator which has the trade number
const tradeNumber = page.locator('div:nth-of-type(2) > .col-md-9.display-value.ng-binding').textContent;
//Navigate to a different screen which now will display the trade number
await this.page.click('a[caption="History"]')
await this.page.click('a[href="#/trade-summary"]')
//Line of code that I am not sure how to correctly write. ".bidconfirmation" is the locator on the new screen which displays the trade number.
//If the contents or value of ".bidconfirmation" is NOT 1234 then an error needs to display.
await expect(tradeNumber).toHaveCSS('.bidconfirmation', tradeNumber);
}
Just to let you know I would change the tag on this post to playwright-JavaScript to better reach the intended audience.
However, if I understand your question correctly you are trying to get the text content of an element but the textContent() method is not working, I would try to use the innerText() method and see if that works.
Apologies if this is a little off as I work with the java version of Playwright but you could do:
const tradeNumber = page.locator('div:nth-of-type(2) > .col-md-9.display-value.ng-binding').innerText(); //BTW I would change this locator to something unique or a little more stable -- this should give you the tradeNumber
//then I'm not 100% sure what your trying to do here but if I understand correctly this might help
await expect(page.locator('.bidconfirmation').toHaveValue(tradeNumber));
I hope this helped a little, Im sorry I couldn't really get an understanding fully of the question you were asking but feel free to take a look at playwright.dev to find documentation surrounding Playwright.
I'm trying to run a playwright test that keeps failing the screenshot match because of timestamps (ex. 3 hours ago, 1 day ago, 5 days ago) that are posted on the page next to some content, not matching the current timestamps that have changed because the test is being run after the initial baseline screenshot is taken.
What is a way that I can store the current date and time at the time of capturing baseline screenshots and telling playwright this is always the timestamp I want to compare against in all tests?
As I see it, as long as you don't ignore the date comparison in your screenshots, they will keep throwing errors. Take into account your snapshot is just a moment in time, we may say. so if your baseline snapshot (the one you compare your current status against) contains the text "5 days ago", that's unchangeable unless you update the snapshot, but the whole comparing snapshots is all about comparing current state vs previous state to check there are no unwanted regressions, so updating the snapshot for this test every time would not make much sense.
In my opinion, you should ignore the given text. A good way to do it is using the option "mask" included in version 1.20. So imagine you want to ignore the number of stars the playwright repo has in its homepage. You could do this:
test('homepage', async({ page }) => {
await page.goto('https://playwright.dev/');
const stars = page.locator('.gh-count');
expect(await page.screenshot({ mask: [stars] })).toMatchSnapshot();
});
This would take a snapshot of playwright's homepage, masking the element with the stars count, sticking the element into a pink-coloured box. That would prevent the snapshots from failing, no matter how many stars the repo gets.
If for whatever reason you cannot update your version up to 1.20, you can also "fake" the element with the evaluate() function, from changing the text before you take the snapshot to a fixed text (with the innerHTML property) or even making the element itself disappear changing its visibility with the setAttribute property. It's all about getting creative on this regard.
I know the question is old, but maybe someone will find the answer useful. What we did to go around the issue is inject css to hide the time stamps:
await page.addStyleTag({
content: `
.timestamp { display: none !important; }
`})
You just need to find the selector for the timestamp and use this code to hide it.
I'm automating e2e tests with Protractor on an angular app.
However, I have an issue when sending keys on input fields.
The sendKeys would miss few characters everytime so I found a workaround :
static sendKeys(value, element){
value.split('').forEach((c) => element.sendKeys(c));
}
This works well but it takes more than 3 times the time the original sendKeys function would.
Well no problem my tests are still functionnal right ?
My app now has new fields with scripts behind them.
One of them is a datepicker input, you can either choose from the datePicker or type it manually. However, for today's date you would type 09022018 and the slashes are automatically appended at the right place (like so 09/02/2018). If you were to enter a wrong date the field is cleared.
Now back to the problem : it seems that both my implementation of sendKeys and the original one loose focus after each submitted key. This means that I can't enter a valid date in the input field as it's cleared after each simulated keypress.
I could use browser.executeScript to fix it but I wouldn't be able to test the functionnality adding slashes. Also, as you type, the datepicker is still open and refreshes after each keypress, you can select a date from it at any time and that is also a feature I want to test.
Thanks in advance
Use executeScript to set the date in backgrond, then use sendKeys to enter a space or Tab at the end to trigger the Keyborad event which will check the input and format the input with slash
function enterDate(date) {
var script = 'arguments[0].value=arguments[1]';
// input box for date
var dateBox = element(by.xxx(yyy));
browser.executeScript(script, dateBox, date);
dateBox.sendKeys(" ");
// or try send Tab
dateBox.sendKeys(protractor.Key.TAB);
}
enterDate('09022018');
You can try this solution on other fields you fixed but take 3 more time.
We wanted to use the portfolioitemstreegrid(https://github.com/RallySoftware/app-catalog/tree/master/src/apps/portfolioitemstreegrid) app since there was an issue with the old PortfolioDrilldownApp. we were able to add the edit app setting options by adding:
getSettingsFields: function () {
var fields = this.callParent(arguments);
fields.push({
type: 'query'
});
return fields;
},
but that doesn't filter anything it just shows the box.
What do we need to add to get the query box to work. The app has a filter already but it isn't flexible enough for us to run the queries we need.
I hoped too that doing something like this will allow wiring up of query into the treegrid filter, but it does not work. There is no storeConfig on a treegrid:
if (this.getSetting('query')) {
config.storeConfig.filters = [Rally.data.QueryFilter.fromQueryString(this.getSetting('query'))];
}
In a month or so a new hierarchical tree grid app will become available, and it will take a query from the app settings dialog. I would not suggest extending this portfolioitemstreegrid, also because it is using the head (unstable) version 'x' of AppSDK2.
I have this interactive chart here. As its data change depending on selected time period I wish to set the date range from Nov-10 to Jul-14, no matter the data. I know that I must use overrideMax on x axis, but I can't make it to work. I guess it's a matter of date formatting. Every single combination I've tried gives the following as result.
What is the right formatting? Thanks a lot.
EDIT: Thank you very much on your quick response, John. Now it is working. I'm loving Dimple more and more!
I have another question regarding this chart. Is there any way to arrange drawing order of series? I would like 'Previsión' to be sent to back. Now it is drawn depending on time period.
EDIT 2: Based on this other question I think I figured out a solution. With a 50ms delay after the chart is drawn I simple erase the circles and paths I wish to be at the front and then append them to the chart svg object.
setTimeout(function () {
var datoCircles = svg.selectAll('circle[id*=Dato]:not([id*=futuro])');
var prevCircles = svg.selectAll('circle[id*=Prev]');
var prevPaths = svg.selectAll('path[class*=Prev]');
datoCircles.remove();
prevCircles.remove();
prevPaths.remove();
// Convertimos la seleción d3 a objetos jQuery
$(svg.selectAll('svg > g')[0])
.append($(prevPaths[0]))
.append($(prevCircles[0]))
.append($(datoCircles[0]));
}, 50);
They need to be set with JavaScript date objects, as native date parsing in JavaScript causes cross browser problems, I recommend using the d3 method:
x.overrideMax = d3.time.format("%Y-%m-%d").parse("2014-05-09");
With this approach you can use whichever date format suits you.