To reproduce the problem:
import { Selector, ClientFunction } from 'testcafe';
fixture `Editors - Overview`
.page(`http://builder03/Demos-18.1/bootstrap/Editors`);
const getSelectionStart = ClientFunction(() => {
return document.getElementById('Content_RegisterForm_FormLayout1_PhoneNumberTextBox_I').selectionStart;
});
test("Register form - non-complete phone number is not allowed", async t => {
const phoneNumberTextBox = Selector('#Content_RegisterForm_FormLayout1_PhoneNumberTextBox_I');
const registerButton = Selector('#Content_RegisterForm_FormLayout1_RegisterButton');
const error = Selector('#Content_RegisterForm_FormLayout1_PhoneNumberTextBox').find('.dxbs-icon-error');
await t.typeText(phoneNumberTextBox, "012")
.click(registerButton)
.expect(error.visible).ok()
.typeText(phoneNumberTextBox, "3456789", { caretPos: 8 })
.click(registerButton)
.expect(error.visible).notOk();
});
The first typeText action types only 12 instead of 012. There is a focus event handler for input with a timeout for setCaret and it breaks typing. This timeout is 50ms but we have only 10ms between click and typing.
var setCaret = ASPx.Selection.SetCaretPosition.bind(this, input, pos);
setTimeout(function() {
if (document.activeElement === input) {
setCaret();
setTimeout(setCaret, 50);
}
}, 0);
But the workaround is use click action before typeText. It means we have extra code between actions which make possible to expaire setCaret timeout.
We need to organize work of .click('').typeText('') and .typeText('') with internal click action in it consistently. Including required barriers.
And also we probably need to include in our doc information about way for focusing element in type action, because now it is not obvious.
hi @helen-dikareva, @AndreyBelym, this topic is quite interesting and I would like to give here some feedback about our use of TestCafe in our organisation.
TestCafe fluent syntax enables to write actions and assertions in a very few lines of code. This syntax leads to write tests with as few lines as possible. The less we write the more we are happy.
At first we run the tests on our own developer machine and everything is working great.
Then tests are automated on our CI environment and they target our DEV and PRE-PROD.
Problems then start arising: many tests that were green on our machine are randomly red on the CI.
Then we entered a very painfull period to make all tests green for our DEV CI, and an even more painfull period to make all tests green for our PRE-PROD CI.
After hours and hours of analysing red tests, we found a very simple recipe to make tests pass on the CI environments :
A test should always do what a real user does on the UI
For example to enter a text in a field:
What we do with TestCafe is typeText();
What the User does is:
TAB key or by clicking another buttonObviously the function typeText is not equivalent and should never be equivalent to the five above steps.
To type a text in a field we typically do the following sequence:
await t
.setTestSpeed(0.7) //start with 0.7 but ideal target is 1.0
.hover(input)
.expect(input.hasAttribute("disabled")).notOk({timeout: 5000})
.click(input)
.typeText(input, "john doe", {replace: true})
.pressKey("tab");
Hi @hdorgeval,
Thanks a lot for your detailed feedback. Just interesting have you tried to use only setTestSpeed and typeText without splitting typeText into several actions?
By default TestCafe works with a page like a robot with tiny delays between actions. It's ok in most cases and helps to decrease test run time. And we added the test speed option to allow to use the human-like behavior.
.expect(input.hasAttribute("disabled")).notOk({timeout: 5000})
Is your inputs has some specific behavior with dynamic adding/removing the disable attribute? I am interesting because this info may help us to add some 'smart' check during action execution in future.
Hi @AlexanderMoskovkin,
we have found that typing text in an input field by only using t.typeText() is not a solid enough strategy. In our app, fields may be in a disabled, enabled, hidden state, or even removed from the dom due to local validation, remote server validation or until a response is received from the server. The amount of time to wait for an enabled state may vary from some ms up to several minutes. To handle this, we have created a configuration object with different timeout values (have a look at the testcafe-starter repo and the default-config.ts :
await t
.setTestSpeed(config.testcafe.testSpeed)
.hover(selector.userNameInputBox)
.expect(selector.userNameInputBox.hasAttribute("disabled")).notOk({timeout: config.testcafe.timeout.customTimeout})
I'm having what I believe are similar issues with typeText. Using the following snippet:
await t
.typeText('input[name="ItemID"]', "4732100")
.click(Selector('a.x-btn').withText('Filter'));
The above code sometimes performs the click action before typeText has finished typing. This occurs most often in the provided TestCafe Docker container when using Chromium, and more often when the test speed is set to 1, but has still occurred when the speed of typeText is set to 0.5.
Firefox seems to be more reliable in regards to typeText, though I don't know why.
Most helpful comment
hi @helen-dikareva, @AndreyBelym, this topic is quite interesting and I would like to give here some feedback about our use of TestCafe in our organisation.
TestCafe fluent syntax enables to write actions and assertions in a very few lines of code. This syntax leads to write tests with as few lines as possible. The less we write the more we are happy.
At first we run the tests on our own developer machine and everything is working great.
Then tests are automated on our CI environment and they target our DEV and PRE-PROD.
Problems then start arising: many tests that were green on our machine are randomly red on the CI.
Then we entered a very painfull period to make all tests green for our DEV CI, and an even more painfull period to make all tests green for our PRE-PROD CI.
After hours and hours of analysing red tests, we found a very simple recipe to make tests pass on the CI environments :
A test should always do what a real user does on the UI
For example to enter a text in a field:
What we do with TestCafe is
typeText();What the User does is:
TABkey or by clicking another buttonObviously the function
typeTextis not equivalent and should never be equivalent to the five above steps.To type a text in a field we typically do the following sequence: