Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Role accross tests with {preserveUrl : true} #2015

Closed
florentpeyrard opened this issue Dec 20, 2017 · 32 comments
Closed

Role accross tests with {preserveUrl : true} #2015

florentpeyrard opened this issue Dec 20, 2017 · 32 comments
Assignees
Labels
STATE: Auto-locked An issue has been automatically locked by the Lock bot. TYPE: bug The described behavior is considered as wrong (bug).
Milestone

Comments

@florentpeyrard
Copy link

Are you requesting a feature or reporting a bug?

Bug.

What is the current behavior?

Create role({preserveUrl : true})
Test1 : useRole(role) //performs login
Test2 : useRole(role) // doesn't perform login neither restore Test 1 loggedin state

What is the expected behavior?

Create role({preserveUrl : true})
Test1 : useRole(role) //performs login
Test2 : useRole(role) // perform "fresh" login or restore Test 1 loggedin state (an option to choose between the 2 options would be ideal)

How would you reproduce the current behavior (if this is a bug)?

Create role({preserveUrl : true})
Test1 : useRole(role)
Test2 : useRole(role)

Provide the test code and the tested page URL (if applicable)

import { Selector, Role } from 'testcafe'

const paul = Role(
'http://localhost:8080/main/login',
async t => {
await t
.typeText('#username', 'paul')
.typeText('#password', 'azertyui')
.click('#login')
},
{
preserveUrl : true
}
)

fixture Fix1

test('Test1', async t => {
await t
.useRole(paul)
.expect(Selector('#id1').innerText).eql("Connected - paul")
})

test("Test2", async t => {
await t
.useRole(paul)
.expect(Selector('#id1').innerText).eql("Connected - paul")
})

Specify your

  • operating system: Win 7
  • testcafe version: 0.18.5
  • node.js version: 8.8.1
@AlexanderMoskovkin
Copy link
Contributor

Hi @florentpeyrard,

Could you please clarify what's wrong with the current Roles implementation?
Roles were implemented to avoid excessive login actions performing. If you'd like to execute login actions directly in some tests but use a Role in others you can do it in the script:

import { Role, t } from 'testcafe';

const loginActions = async function () {
    await t
        .typeText('#username', 'paul')
        .typeText('#password', 'azertyui')
        .click('#login')
};

const myRole = Role('http://login-page', loginActions);

const login = async function (useRole) {
    if(useRole)
        await t.useRole(myRole);
    else
        await loginActions();
}

test('test1', async () => {
    await login(true);
});

test('test2', async () => {
    await login(false);
});

@AlexanderMoskovkin AlexanderMoskovkin added the TYPE: question The issue contains a question that won't be addressed. label Dec 20, 2017
@florentpeyrard
Copy link
Author

Hi @AlexanderMoskovkin ,

I think in Test2 in my example, local storage should be restored even when preserveUrl is set to true. Therefore, expect(Selector('#id1').innerText).eql("Connected - paul") should pass in Test2.

@AlexanderMoskovkin
Copy link
Contributor

Form your example I see that you didn't specify the Start WebPage.

So, your first test starts with about:blank page. Then it goes to the Role initializer and redirect to the login page (http://localhost:8080/main/login). The second test starts with about:blank page two. Since the role is already initialized it doesn't go to the login page, but just reload the current page with saved cookies and local storage values.
To fix you problem set the Start WebPage to the fixture or to tests.

@florentpeyrard
Copy link
Author

@AlexanderMoskovkin , from the docs, I can read : "Set the preserveUrl option to true to save the URL to which the browser was redirected after logging in. TestCafe will navigate to the saved URL each time after you switch to this role.". Am I missing something ?

@AlexanderMoskovkin
Copy link
Contributor

Yep, you are right. Thanks for the note. I'll double check the behavior.

@AlexanderMoskovkin
Copy link
Contributor

@florentpeyrard I've tried to reproduce this behavior on the GitHub site and it seems it works correctly:

import { Selector, Role } from 'testcafe';

fixture`github`;

const yourLogin = '****';
const yourPassword = '****';

const role = Role('https://github.com/login', async t => {
    await t
        .typeText(Selector('#login_field'), yourLogin)
        .typeText(Selector('#password'), yourPassword)
        .click(Selector('[value="Sign in"]'));
}, { preserveUrl: true })

test('Test 1', async t => {
    await t
        .useRole(role)
        .expect(Selector('.HeaderNavlink.name.mt-1').find('img').getAttribute('alt')).eql("@" + yourLogin);
});

test('Test 2', async t => {
    await t
        .useRole(role)
        .expect(Selector('.HeaderNavlink.name.mt-1').find('img').getAttribute('alt')).eql("@" + yourLogin);
});

Both tests go to the logged in page after the useRole call. Am I missing something?

@florentpeyrard
Copy link
Author

Hi @AlexanderMoskovkin,

thanks for your test.

My auth is based on local storage (and cookies). Hypothesis : cookies are restored but local storage isn't. Maybe Github uses cookies only, which would explain why it works on Github.

@AlexanderMoskovkin AlexanderMoskovkin added TYPE: bug The described behavior is considered as wrong (bug). and removed TYPE: question The issue contains a question that won't be addressed. labels Dec 28, 2017
@AlexanderMoskovkin AlexanderMoskovkin self-assigned this Dec 28, 2017
@AlexanderMoskovkin AlexanderMoskovkin added this to the Sprint #10 milestone Dec 28, 2017
@AlexanderMoskovkin
Copy link
Contributor

Hi @florentpeyrard,

I've reproduced the issue and we'll fix it.

Here is a simple example to reproduce the behavior:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>gh-2015</title>
</head>
<body>
    <button id="login">Login</button>
    <div id="status"></div>
    <script>
        var btn = document.getElementById('login');
        var statusDiv = document.getElementById('status');

        if(window.localStorage.loginKey)
        //if(document.cookie.indexOf('asdfg=hjkl') > -1)
            statusDiv.textContent = 'logged in';
        else
            statusDiv.textContent = 'please click the button to log in';

        btn.addEventListener('click', function () {
            window.localStorage.loginKey = 'login-key';
            //document.cookie = 'asdfg=hjkl';

            document.location = document.location.href;
        });
    </script>
</body>
</html>
import { Selector, Role } from 'testcafe';

fixture `local-storage`;

const user = Role('localhost:8080/1.html', async t => {
    await t.click(Selector('#login'));
}, { preserveUrl: true });

test('test 1', async t => {
    await t.useRole(user);
    await t.expect(Selector('#status').textContent).eql("logged in");
});

test('test 2', async t => {
    await t.useRole(user);
    await t.expect(Selector('#status').textContent).eql("logged in");
});

@florentpeyrard
Copy link
Author

Hi @AlexanderMoskovkin ,

thank you for the feedback !

@AlexanderMoskovkin
Copy link
Contributor

Hi @florentpeyrard,

We're working on this issue right now and it seems we've found the reason.
Could you please try to use a workaround? Just add await t.wait(500) at the start of each your test that use useRole and let us know how it works on your side.

@florentpeyrard
Copy link
Author

Hi @AlexanderMoskovkin ,

thanks for the update and the workaround. Actually, I was already using another workaround :

  • not using preserveUrl option
  • using navigateTo before useRole

This way, local storage is properly reloaded.

@rstudner
Copy link

@florentpeyrard do you have a code snippet for what yo mean there?

I have been using fixtures, with no .page, and then trying to have a .beforeEach that uses a role.

then each of my tests just do .navigateTo

But even with this, things aren't working for me (and I have localStorage involvement)

AlexanderMoskovkin pushed a commit to AlexanderMoskovkin/testcafe that referenced this issue Feb 10, 2018
… (DevExpress#2048)

* fix restore local storage correctly on UseRole with PreserveUrl (closes DevExpress#2015)

* fix local storage restore on useRole with preserveURL (DevExpress#2015)

* fix local storage restore on useRole with preserveURL (DevExpress#2015)

* fix 'test-server'

* Fix remarks
@markusguenther
Copy link

Are you sure that this is fixed? Trying to upgrade to 19.1.0 with node 8.11.0 and now I have the problem that the login does not work in the second test. But without preserveUrl I get a white blank page in the test :/

@AlexanderMoskovkin
Copy link
Contributor

Hi @markusguenther,

Thanks for the info. We've faced with such issue (#2282) and we are already working on the fix (#2285). Please subscribe to the #2282 to be notified about our progress

@Thejaswi05
Copy link

Thejaswi05 commented Jun 20, 2018

Hi, @AlexanderMoskovkin

are you sure this is fixed?

I'm currently on testcafe version 0.20.2 and node 8.11

My scenario is same as follows. But the user role doesn't work in test2 . I tried adding your workaround to add the wait time before the test but it didn't work. Can you please update me on this issue?

import { Selector, Role } from 'testcafe';

fixture local-storage;

const user = Role('localhost:8080/1.html', async t => {
await t.click(Selector('#login'));
}, { preserveUrl: true });

test('test 1', async t => {
await t.useRole(user);
await t.expect(Selector('#status').textContent).eql("logged in");
});

test('test 2', async t => {
await t.useRole(user);
await t.expect(Selector('#status').textContent).eql("logged in");
});

@AlexKamaev
Copy link
Contributor

Hi, @Thejaswi05
Your scenario looks valid, so it should work. Would you please provide me with your page to investigate the issue in detail?

@Thejaswi05
Copy link

@AlexKamaev do you need the page url ?

@AlexKamaev
Copy link
Contributor

@Thejaswi05 yes, a page URL or a very simple example which I could examine on my machine

@Thejaswi05
Copy link

Thejaswi05 commented Jun 22, 2018

Here is the page url: https://dev.bbidsdev.com/index.html#/joinnow

and test looks like this:

import { Selector, t, Role } from 'testcafe';
import { config, SummaryPage, RegistrationPage, dataHelper } from '../support/import_helper'
import * as mixins from './../modules/reg_helpers.js';

const summaryPage = new SummaryPage();
const registrationPage = new RegistrationPage();
var testData = dataHelper.testData();
const password = testData.password;
var randomNumber = Math.round((new Date()).getTime() / 1000);

//Email Signup user
export const regularAccUser = Role(${config.baseUrl}index.html#/joinnow, async t => {
const emailId = 'lnaraepic+' + randomNumber + '@gmail.com'
await t
.expect(registrationPage.btnLogin).ok()
.typeText(registrationPage.emailId, emailId)
.typeText(registrationPage.password, password.valid)
.click(registrationPage.btnLogin)
.expect(registrationPage.bidPackPg.innerText).contains('Purchase a Bidpack and get free bids!', 'input text contains Purchase Bidpack')
}, { preserveUrl: true });

fixtureEmail User Registration

test('Signup with Biddy Pack $50 dollar and valid CC', async t => {

var flag = 'positive';
var skipBid = false;
await t
    .useRole(regularAccUser)
await mixins.optBidPack(t, skipBid);
await mixins.creditCardDetails(t);
await t
    .click(summaryPage.btnSubmit)
    .expect(summaryPage.confirmMsg.innerText).contains('Before signing in, please verify email by clicking on the link in the email sent to your email', 'account creation check');

});

test('Signup test 2', async t => {

var flag = 'positive';
var skipBid = false;
await t
    .useRole(regularAccUser)
    .wait(10000)

});

user role in second test is preserving the state I guess. I need to have preserveUrl: true because, I need to continue with the user state and perform the next steps. In the second test, I need it to have a fresh start. Sometimes, I need the ability to loop through the same test multiple times, So, I want the user role to have a fresh start in the second test.

@AlexKamaev
Copy link
Contributor

Thanks, I'll investigate the issue

@AlexKamaev
Copy link
Contributor

@Thejaswi05
Could you also provide me with credentials to some test account? We need them for debugging.

@Thejaswi05
Copy link

@AlexKamaev. SOrry for the late reply. I was on leave, so couldn't reply you immediately. I'm actually created roles to signup with different types, For example - Regular user Signup with just Email and Social user signup with facebook.

For example:
Inside Fixture:
test1 -> Regular user signup
test2 -> Regular user signup (this is not working as I mentioned earlier)

Test user: [email protected] and password: epic2016

@AlexKamaev
Copy link
Contributor

@Thejaswi05
I've tried to visit https://dev.bbidsdev.com/index.html#/joinnow and it seems the site does not work correctly. I see an empty page. Do you have the same problem with the site?

@Thejaswi05
Copy link

Thejaswi05 commented Jun 29, 2018

If you set { preserveUrl: false }); it might give you blank page when returned to the test. Please set preserveurl to true.
did you open it manually? I don't see blank page problem.. It works fine for me.

@AlexKamaev
Copy link
Contributor

@Thejaswi05
I apologize, it was my mistake about a blank page. However, I was not able to sign up manually. After I filled the form, the site redirects me to the #/SignIn page. If I try to type the same email and password, the 'User does not exist' alert message appears. I've also noticed that after the signing up, the 'Missing email' error appears in the browser console.
 
I wrote a test that checks signing in for the existing user and it works. Here is an example:

export const regularAccUser = Role('https://dev.bbidsdev.com/index.html#/SignIn', async t => {
    await t.typeText(Selector('input[type=email]'), '[email protected]');
    await t.typeText(Selector('input[type=password]'), 'epic2016');
    await t.click(Selector('button').withText('LOGIN'));
    await t.click(Selector('span').withText('WELCOME TO LIL BIDDY!'));
}, { preserveUrl: true });
 
test('1', async t => {
    await t.useRole(regularAccUser);
});
 
test('2', async t => {
    await t.useRole(regularAccUser);
    await t.click(Selector('span').withText('WELCOME TO LIL BIDDY!'));
});

 
Could you confirm that this test case works for you?
 

@Thejaswi05
Copy link

Thejaswi05 commented Jul 3, 2018

@AlexKamaev I'm using roles for signup with different types(signup via email, via facebook and via twitter) and not for sign in. Your example test might work because, there is no change in user states in the browser. In the first test, the user is signed in, second test is also signed in with same user. - I think browser will just refresh here with the saved cookies in second test and that's why you don't see any issue here.

Where as am using roles for signup. Image in first test, I have signed up via email and I'm logged in
In the second test, I'm trying to signup with same user - > but this doesn't happen

Do I have to use roles only for sign in? AM I not allowed to use it for signup's?

The reason you are seeing the sign in error after sign up might be because, you will receive an email confirmation and you need to confirm you account via email after signup and then only you can login.

@AlexKamaev
Copy link
Contributor

I cannot register manually and do not get a confirmation message on my email. Nonetheless, I consider your scenario correct. From your test code I can't understand if you are logged in already after registration. Let's see your test example:

await t
    .expect(registrationPage.btnLogin).ok()
    .typeText(registrationPage.emailId, emailId)
    .typeText(registrationPage.password, password.valid)
    .click(registrationPage.btnLogin)

I see that you do these steps:

  1. type email
  2. type password
  3. click login button

What should happen next? As I mentioned before, I was redirected to the #SignIn page. It means that you should sign in with your new login/password. After you logged in with your new login/password, testcafe saves cookies/localstorage and then you will be logged in with the second test.

@rafrsr
Copy link

rafrsr commented Jul 31, 2018

I have a similar issue... I have a fixture with 2 tests, each test runs fine separately, but when run the entire fixture the second test fails. I'm testing a react application, the login is a component displayed if does not exist a valid token saved in localstorage. When I run each test individually, the login process is ok, but I noticed that when I run the two tests together, the second test never executes the .useRole() step and fails to find an element that does not exist logically, because the app is showing the login.

const AdminUser = Role('http://localhost:9001', async (t) => {
    await t
        .typeText('input[name="username"]', 'admin')
        .typeText('input[name="password"]', '12345')
        .click('button[type="submit"]');
});

fixture('List & Edit')
    .page('http://localhost:9001');

test('List', async (t) => {
    await t
        .useRole(AdminUser)
        .navigateTo('#/list')
        .expect(Selector('.page-title').innerText)
        .contains('List');
});

test('Edit', async (t) => {
    await t
        .useRole(AdminUser)
        .navigateTo('#/list/1/edit')
        .expect(Selector('.page-title').innerText)
        .contains('Hello')
        .click(Selector('button[type="submit"]'))
        .expect(Selector('.ui-pnotify-text').innerText)
        .contains('Record saved successfully');
});

@rafrsr
Copy link

rafrsr commented Jul 31, 2018

My solution to this annoying problem; execute the login process for each test.

const LoginAsAdmin = async (t) => {
    await t
        .typeText('input[name="username"]', 'admin')
        .typeText('input[name="password"]', '12345')
        .click('button[type="submit"]');
};

fixture('List & Edit')
    .page('http://localhost:9001');

test('List', async (t) => {
    await LoginAsAdmin(t);
    await t
        .navigateTo('#/list')
        .expect(Selector('.page-title').innerText)
        .contains('List');
});

test('Edit', async (t) => {
    await LoginAsAdmin(t);
    await t
        .navigateTo('#/list/1/edit')
        .expect(Selector('.page-title').innerText)
        .contains('Hello')
        .click(Selector('button[type="submit"]'))
        .expect(Selector('.ui-pnotify-text').innerText)
        .contains('Record saved successfully');
});

Anyway, testcafe natively should save some snapshot of localstorage just after the login and restore it each time useRole () is used

@AlexKamaev
Copy link
Contributor

Hi @rafrsr
Your scenario is correct and the user should be logged in in the second test. As you mentioned, the role should save localStorage just after the role initializer and should restore it on each time useRole() is used. Would you please provide me with an example or link to your website to research the issue in detail?

@dsedmak
Copy link

dsedmak commented Nov 16, 2018

Hi
I just started using TestCafe and have run into this issue. So I'm using version 0.23.1 and this still happens. I hope this issue gets reopened because the issue is not fixed. I have figured out a workaround that causes the tests to behave properly which proves that the problem is with testcafe and not with the page. I'll give a working example:

import { Role } from "testcafe";
import * as conf from "../../configuration";
import { Page } from "../../page";

const page = new Page();

const regularUser = Role(
    conf.baseUrl,
    async t => {
        await t
            .typeText(page.login.credentials.usernameInput, conf.regularUserUsername)
            .typeText(page.login.credentials.passwordInput, conf.regularUserPassword)
            .click(page.login.credentials.submitButton);
    },
    { preserveUrl: false }
);

fixture("fixture")
    .page(conf.baseUrl)
    .beforeEach(async t => {
        await t.maximizeWindow().useRole(regularUser);
        await t.eval(() => location.reload(true));
    });

test("first", async t => {
    await t.click(page.shell.appMenu.mainMenuToggle);
});

test("second", async t => {
    await t.click(page.shell.appMenu.mainMenuToggle);
});

Removing .page from fixture and setting preserveUrl to true also works.

However the reload must be awaited separately. This will not work:

fixture("fixture")
    .page(conf.baseUrl)
    .beforeEach(async t => {
        await t
            .maximizeWindow()
            .useRole(regularUser)
            .eval(() => location.reload(true));
    });

Essentially it boils down to forcing a reload on the page.

@lock
Copy link

lock bot commented Mar 28, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or feature requests. For TestCafe API, usage and configuration inquiries, we recommend asking them on StackOverflow.

@lock lock bot added the STATE: Auto-locked An issue has been automatically locked by the Lock bot. label Mar 28, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Mar 28, 2019
kirovboris pushed a commit to kirovboris/testcafe-phoenix that referenced this issue Dec 18, 2019
… (DevExpress#2048)

* fix restore local storage correctly on UseRole with PreserveUrl (closes DevExpress#2015)

* fix local storage restore on useRole with preserveURL (DevExpress#2015)

* fix local storage restore on useRole with preserveURL (DevExpress#2015)

* fix 'test-server'

* Fix remarks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
STATE: Auto-locked An issue has been automatically locked by the Lock bot. TYPE: bug The described behavior is considered as wrong (bug).
Projects
None yet
Development

No branches or pull requests

8 participants