2

I'm investigating TestCafe to use as my test automation framework, and I've hit a bit of a stumbling block in regards to executing a function using the Rendr App on my AUT. With Cypress.io, Protractor and Puppeteer etc I'm able to run the same command... so I'm not too sure where I'm going wrong with TestCafe.

Essentially what I'm trying to execute is: window.App.get('currentUser').set('login_state', 'someLoginState');

Cypress

  cy.window().then((win) => {
    win.App.get('currentUser').set('login_state', 'someState');
  });

Protractor

  function changeUserState() {
    App.get('currentUser').set('login_state', 'someState');
  }

  browser.executeScript(changeUserState);

Puppeteer

  function changeUserState() {
    window.App.get('currentUser').set('login_state', 'someState');
  }

  await page.evaluate(changeUserState);

For TestCafe I've tried to use:

const changeUserState = ClientFunction((desiredState) => {
    return App.get('currentUser').set('login_state', desiredState);
});

fixture `User states`
    .page(url)
    .afterEach( async t => {
        await t
            logout();
    });

test('Change a users log in state', async t => {

    await loginForm.loginViaUrl(userEmail, userPassword);
    await changeUserState('SomeState');
    await checkUserState('SomeState');  // Just an example of what I would do next
}

When running this, it throws a ReferenceError: App is not defined error.

(I've also attempted the above options using 'window.App.get...': TypeError: Cannot read property 'get' of undefined - Adding a wait prior to the calling the ClientFunction doesn't affect the oucome)

UPDATE Based on comments, the t.eval(...) option shouldn't be used as I'm accessing client side functionality.

Rob C
  • 662
  • 5
  • 15
  • 2
    Can't comment on the error, but certainly you need to use ClientFunction, because test code is executed on the server, not in browser. And you need to use window like described here: https://devexpress.github.io/testcafe/documentation/test-api/obtaining-data-from-the-client/examples-of-using-client-functions.html#checking-a-page-url – Roman Eremin Apr 24 '19 at 09:16
  • Thanks, I thought that was the case, I just wanted to cover all bases :). – Rob C Apr 24 '19 at 15:50
  • 1
    Could you provide a sample page for reproducing it? Your code with `ClientFunction` looks valid. If you try to execute it in the begging of a test, it can be possible that your app is not initialized yet, try to add `t.wait` before executing `changeUserState`. Using `window.App` or switching to a specific iframe or the top window can help you too. – Andrey Belym Apr 25 '19 at 12:30
  • Hi @AndreyBelym, I'll update with more detail on the test case. Essentially I log in to our site, and then run this code to change the login_state to something like "unverified" etc. I don't have a sample page, but you can visit www.change.org and run the code there using the Chrome dev tools console – Rob C Apr 25 '19 at 18:05
  • Updated my question to show results from using `t.wait` and using `window.App` don't change the outcome – Rob C Apr 25 '19 at 18:28
  • I guess `loginForm.loginViaUrl` can reload the page. `ClientFunction` won't wait for page loading and initialization if you call it immediately after a page reload. I tried to reproduce it with `change.org`, but my test works, check this gist: https://gist.github.com/AndreyBelym/1f39b9ae4d122592ab5cd22854f0e39c – Andrey Belym Apr 26 '19 at 09:58
  • @AndreyBelym, the login function does redirect back to the homepage. It looks like the client function behaves differently depending on whether I start the test at the login page (like you have done in your example), or if I start at the baseUrl and navigate to the login page... not sure if you'd like to take this offline to discuss in more detail, but if you want to make your above comment an answer then I will accept it. – Rob C Apr 26 '19 at 22:04
  • @RobC I still think that it is better to create a working example that demonstrates the issue. Thus we can solve the problem and improve TestCafe. Please create a separate ticket in the TestCafe repository using this form: https://github.com/DevExpress/testcafe/issues/new?template=bug-report.md – Alex Kamaev Apr 29 '19 at 09:56

1 Answers1

3

I think the problem is related to the fact that the App variable is not defined. So you should wait until it becomes available. You can use the wait action with the fixed waiting time or use the following selector to wait until an element appears on the page:

await Selector('element that tells us that App exists')

UPD: Having examined the test example you provided in your Github issue, we found a solution for you. It is necessary to wait until the App variable appears. Add the following code before the changeUserState function call:

// first case
const getPageUrl = ClientFunction(() => location.toString());

await t.expect(getPageUrl()).eql('https://www.change.org/', { timeout: 5000 });
// second case
const isAppExists = ClientFunction(() => !!window.App);

await t.expect(isAppExists()).ok({ timeout: 5000 });

UPD from the GitHub comment:

import { Selector, ClientFunction } from 'testcafe';

fixture`Change User State`.page('www.change.org');

const isAppExists = ClientFunction(() => !!window.App);

const changeUserState = ClientFunction((desiredState) => {
    const initialState = App.get('currentUser').get('login_state');
    App.get('currentUser').set('login_state', desiredState);
    const currentState = App.get('currentUser').get('login_state');
    return { initialState, currentState };
});

test
    ('Start from homepage', async t => {
        await t
            .maximizeWindow()
            .navigateTo('/login_or_join')
            .typeText(Selector('#content input[type="email"]'), '*****')
            .typeText(Selector('#content input[type="password"]'), '*****')
            .click(Selector('#content input[type="submit"]'))
            .expect(isAppExists()).ok(); // wait for App

        console.log(await changeUserState('guest'));
});

Result:

Running tests in:
- Chrome 74.0.3729 / Windows 10.0.0

Change User State
{ initialState: 'authenticated', currentState: 'guest' }
 √ Start from homepage


 1 passed (15s)
Vladimir A.
  • 2,202
  • 2
  • 10
  • 28
Artem
  • 921
  • 4
  • 11