Bug.
Create role({preserveUrl : true})
Test1 : useRole(role) //performs login
Test2 : useRole(role) // doesn't perform login neither restore Test 1 loggedin state
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)
Create role({preserveUrl : true})
Test1 : useRole(role)
Test2 : useRole(role)
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")
})
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);
});
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.
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.
@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 ?
Yep, you are right. Thanks for the note. I'll double check the behavior.
@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?
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.
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");
});
Hi @AlexanderMoskovkin ,
thank you for the feedback !
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.
Hi @AlexanderMoskovkin ,
thanks for the update and the workaround. Actually, I was already using another workaround :
This way, local storage is properly reloaded.
@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)
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 :/
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
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");
});
Hi, @Thejaswi05
Your scenario looks valid, so it should work. Would you please provide me with your page to investigate the issue in detail?
@AlexKamaev do you need the page url ?
@Thejaswi05 yes, a page URL or a very simple example which I could examine on my machine
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.
Thanks, I'll investigate the issue
@Thejaswi05
Could you also provide me with credentials to some test account? We need them for debugging.
@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
@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?
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.
@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?
聽
@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.
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.
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.
````javascript
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');
});
````
My solution to this annoying problem; execute the login process for each test.
````javascript
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
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?
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.
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.