Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TestCafe - Tests executed before useRole completely finished

TestCafe 1.8.0, Firefox 76.0 (any will do), macOS 10.15.4.

My TestCafe tests (steps after useRole) are trying to execute even before useRole is completely done. Example:

import { Role } from 'testcafe';

const role = Role('http://example.com/login', async t => {
    await t
        .typeText('#login', 'username')
        .typeText('#password', 'password')
        .click('#sign-in'); // Redirects to http://example.com/session
});

fixture `My Fixture`;

test('My test', async t => {
    await t
        .navigateTo('http://example.com/')
        .useRole(role);
        .click()
        .typeText('#search', 'query')
        // Further tests.
        ....... 
  1. Role is being used -> user is redirected to: http://example.com/session at the end.
  2. Once role execution is finished -> TestCafe goes back to My test AND it reloads http://example.com/ again.

This is a huge problem because between this one page reload for just a moment 'page is ready' and since TestCafe is working rapidly .click() is executed. Now page reloads so test execution stops. Once page loaded test brakes because it is trying to .typeText(...) without a .click().

Tried this solutions:

  1. Wait until will work only first time. Second time when useRole used (from cache) code will execute even before this second page reload. .expect(getUrl()).eql('desiredurl', { timeout: 10000 })
  2. As we all know hard wait .wait(3000) or slowing down tests .setTestSpeed(0.7) will work but it is not a good solution from code perspective. Tests still might fail from time to time and I need and want stability here.
  3. With { preserveUrl: true } it would just reload http://example.com/session so it doesn't matter if this option is used. Reload is still happening.

Any ideas? How can I let my test know to wait for exactly the same page reload without using any hardcoded waits, code sleep?

like image 465
bart Avatar asked Oct 23 '25 17:10

bart


1 Answers

As far as I understand, the main issue is that the click action is executed on the wrong page for some reason. It does not wait until the page is completely reloaded. This behavior is unexpected. We would really appreciate it if you create a reproducible sample.

I agree that the use of wait or setTestSpeed is not a suitable solution.

I see that you tried to use assertions: .expect(getUrl()).eql('desiredurl', { timeout: 10000 }). I think this approach should work, but I cannot be sure because I couldn't reproduce the issue.

You can define your role with preserveUrl: true. Then, extract the useRole method as follows:

async function useRole (t, role) {
    await t.useRole(role);

    await t.expect(getUrl()).eql('http://example.com/session', {timeout: 10000 });
}

Now, you can use the new useRole(t, role) method, which will wait until the page is completely loaded.

like image 195
Alex Kamaev Avatar answered Oct 26 '25 06:10

Alex Kamaev