How to login with HTTP basic authentication to ACCESS the website- Test Cafe with Gherkin and cucumber - testing

All links, project name and company name has been modified and are not original.
We have a basic HTTP authentication popup that appears when we are accessing out test/staging environments.
I am wondering, how can I enter the login information into the popup login window or send an api request in advance to save the cookie?
Because otherwise, I can't run the automation on our test environment. When the test access the page, I see a white website showing "unauthorized" in small letters.
This is what the login prompt looks like when accessing the Test/Staging env
We are using following plugin: https://www.npmjs.com/package/gherkin-testcafe
What I am asking is very similar to this question: Testing http basic authentication with Cucumber and RSpec in Rails 3.2.3
I have tried adding a role and using TestCafe http-authentication.html
Here is what I have tested so far:
TestCafe trying to use role:
const { Role } = require('testcafe');
const regularAccUser = Role('https://website/login', async t => {
await t
.typeText('#login', 'username')
.typeText('#password', 'password')
.click('#sign-in');
});
Given("I am open Dealer's login page", async t => {
await t
.useRole(regularAccUser)
.navigateTo(`${url}/login`);
});
That gives me:
ERROR CompositeParserException: Parser errors:
(7:3): expected: #EOF, #Comment, #BackgroundLine, #TagLine, #ScenarioLine, #ScenarioOutlineLine, #Empty, got 'Correct action happens when user provide either wrong or correct login information'
at Function.Errors.CompositeParserException.create (/Users/dennis/Projects/src/company/project/node_modules/gherkin/lib/gherkin/errors.js:27:13)
at Parser.parse (/Users/dennis/Projects/src/company/project/node_modules/gherkin/lib/gherkin/parser.js:72:45)
at specFiles.forEach.specFile (/Users/dennis/Projects/src/company/project/node_modules/gherkin-testcafe/src/compiler.js:43:33)
at Array.forEach (<anonymous>)
at GherkinTestcafeCompiler.getTests (/Users/dennis/Projects/src/company/project/node_modules/gherkin-testcafe/src/compiler.js:42:20)
at getTests (/Users/dennis/Projects/src/company/project/node_modules/testcafe/src/runner/bootstrapper.js:79:47)
at Generator.next (<anonymous>)
at step (/Users/dennis/Projects/src/company/project/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
at /Users/dennis/Projects/src/company/project/node_modules/babel-runtime/helpers/asyncToGenerator.js:28:13
If I try using:
import {Role} from 'testcafe'
I get:
tests/ui/stepDefinitions/login/login.js:1
(function (exports, require, module, __filename, __dirname) { import { Role } from 'testcafe';
^
SyntaxError: Unexpected token {
Using TestCafe's HTTP Authentication:
Feature: Login with correct and wrong info functionallity
.page('website/login')
.httpAuth({
username: 'username',
password: 'password',
})
Correct action happens when user provide either wrong or correct login information
#loginFunc
Scenario: Should NOT be able to login without filling in any credentials
Given I am open Dealer's login page
When I am login in with "empty" and "empty"
Then I should NOT be able to press the login button
I am getting following:
Feature: Login with correct and wrong info functionallity
✖ Scenario: Should NOT be able to login without filling in any credentials
1) Cannot obtain information about the node because the specified selector does not match any node in the DOM tree.
  | Selector('button[data-qa="qa-login-submit-button"]')
 > | Selector('button[data-qa="qa-login-submit-button"]')
Browser: Chrome 72.0.3626 / Mac OS X 10.14.3
32 | }
33 |});
34 |
35 |Then("I should NOT be able to press the login button", async t => {
36 | await t
> 37 | .expect(submitButton.hasAttribute('disabled')).ok()
38 | .expect(h1.exists).eql(true);
39 |});
```
It is basically showing me a white screen and saying: "**unauthorized**" in small letters.

You don't need any post/get requests with the Basic HTTP. Instead, you can log in using the Role mechanism:
When you switch to a role for the first time, TestCafe internally creates a branch of this role for this particular test run. All cookies set by your further actions will be appended to this branch. This branch will be used whenever you switch back to this role from the same test run.

Related

Cypress: Login Authentication redirects to another domain: Workaround?

I understand that Cypress does not allow flipping from one domain to another domain because it will error with:
chrome-error://chromewebdata/
However, I need a workaround. I am providing a test set for multiple environments: STAGE, DEMO, PROD.
With DEMO and PROD, during the authentication phase (username/password), stay within the same domain:
VISIT: https://[demo|www].foo.com
AUTH: https://account.foo.com/auth >> username >> password
CONSENT: https://[demo|www].foo.com/action...
With STAGE, the authentication phase flips to another domain:
VISIT: https://[stage].foo.com
AUTH: https://account.bar.com/auth >> username >> password
CONSENT: https://[stage].foo.com/action...
Thereby, Cypress fails to redirect from VISIT to AUTH because of domain flip. This is blocking testing of STAGE.
What recommended workaround approaches?
Puppeteer?
Native Cypress using cy.request()?
Referenced:
Handling Cypress url redirect
Error with authentication in e2e tests using cypress: chrome-error://chromewebdata
Thank you, much appreciate the assistance.
The approach I took is similar to the Cypress Recipe Login with CSRF token
As mentioned, each deployment has its own website URL followed by account login URL.
Needed first is the CSRF token from account login page, which its URL is referred here as $baseUrl:
Cypress.Commands.add('cmdGetCSRF', ($baseUrl) => {
cy.log('COMMAND cmdGetCSRF');
expect($baseUrl)
.to.be.a('string')
.not.empty
cy.request($baseUrl)
.its('body')
.then(($body) => {
const $html = Cypress.$($body)
cy.log('html', $html)
const csrf = $html.find('input[name="__RequestVerificationToken"]').val()
expect(csrf)
.to.be.a('string')
.not.empty
return cy.wrap(csrf)
})
})
Then within body of requestOptions provided to cy.request() which will performing the login, provide one-time CSRF token:
const body: { [key: string]: string } = {
email: $envCypress.account_username,
password: $envCypress.account_password,
__RequestVerificationToken: $csrfToken
};
Cypress has recently add a new experimental feature for running test on multiple origins here. There are examples for cross origin login too. More on experimentalSessionAndOrigin feature:
https://docs.cypress.io/api/commands/origin
https://docs.cypress.io/api/commands/session

Test automation of authorization prompt - chrome

I am trying to automate a simple login within this alert prompt authorization using cypress and javascript
I came across different solutions but I cant find the proper one.
What I actually do is I visit website with :
cy.visit('https://xxx/',{failOnStatusCode: false}) // Internal website with the fafailOnStatusCode: false
If I do not use failOnStatusCode: false I cant get to the prompt and I get an cypress message about using failOnStatusCode: false
But I am stuck after this step and neither cy.visit('https://username:password#xxx/',{failOnStatusCode: false})
is not working ...
Thanks for any comments and help. This is my first thread here :)
prompt
it('login prompt xxx', function () {
cy.setCookie("name", "value");
cy.visit("yourUrl.com", {
headers: {
authorization: 'Basic token'
},
failOnStatusCode: false
})
Test automated in cypress.
Open up the developer tools in chrome to find out these 2 things.
1.You have to know your cookie name and value from console. https://docs.cypress.io/api/commands/setcookie.html
2.Also you have to know your authorization which can be found in console.
https://docs.cypress.io/api/commands/visit.html

Handling Basic Authentication in Karate UI scenario

I have just started implementing karate UI (v0.9.5). Have already implemented api testing using karate and it works perfectly.
Following the HTTP basic auth strategy on this page - https://github.com/intuit/karate#http-basic-authentication-example the basic auth handling works for api tests. I set the HTTP headers once and run all api tests.
Now for the UI testing, the URL that I open brings up the basic auth pop-up as shown below:
So I thought that I could use the same strategy that I used for api tests to handle this. In the background section of my feature file, i call the feature file that does the authentication and sets headers as below:
The called feature file to set headers (admin-headers.feature). This feature file gets the token after admin user login is performed via karate-config.js. Then assigns the token along with the Base64 encoded basic auth to the headers calling headers.js. The Base64 user and password are being input as maven arguments and read via karate-config variables.
(/admin-headers.feature)
Feature: karate-config.js will perform one time login for admin and
set the session token for all subsequent requests
Background:
* def session = adminAuthInfo.authSession
* def basic_auth = call read('classpath:basic-auth.js') { username: '#(basicAuthUser)', password: '#(basicAuthPassword)' }
* configure headers = read('classpath:headers.js')
Scenario: One-time login for user and set the
session token in request header
The js code for returning Auth and Cookie to above feature file (/headers.js).
function() {
var session = karate.get('session');
var basic_auth = karate.get('basic_auth');
if(session){
return {
Authorization: basic_auth,
Cookie: "SESSION=" + session
};
} else {
return {};
}
}
My UI test feature file (/ui-test.feature):
Feature: Login test
Background:
# Authorise via api
* callonce read('classpath:common/headers/admin-headers.feature')
* configure driver = { type: 'chrome' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
Running the above feature file still shows the auth pop-up.
I then tried to set the cookies while I am initialising the driver (which I think is probably not the right way?) as below:
Feature: Login test
Background:
# Authorise via api
* def login = callonce read('classpath:common/headers/admin-headers.feature')
* def uiCookie = { name: 'SESSION', value: '#(login.userAuthInfo.authSession)', domain: 'test.internal.mysite.com' }
* configure driver = { type: 'chrome', cookie: '#(uiCookie)' }
Scenario: Test login
Given driver 'https://test.internal.mysite.com/names'
The above also does not work. What is it that I am doing wrong here? the pop-up keeps coming up because the cookie is not set when the driver is initialised and then opens the specified url?
Help is much appreciated.
I think you raised a very good feature request, that configure driver should take cookies also, so that you can navigate to the page and set cookies in one-shot, and I opened a feature request: https://github.com/intuit/karate/issues/1053
So try this sequence, refer docs for cookie(): https://github.com/intuit/karate/tree/master/karate-core#cookieset
* driver 'about:blank'
* cookie(uiCookie)
* driver 'https://test.internal.mysite.com/names'
And now it should work !
Feature: Windows Authentication feature
Background:
* configure driver = { type: 'chrome' }
Scenario: Windows Authentication Valid Login test case
Given driver 'http://the-internet.herokuapp.com/basic_auth'
And delay(3000)
And screenshot()
* robot {}
* robot.input('admin' + Key.TAB)
* robot.input('admin')
* robot.click('Sign in')
And delay(3000)
And screenshot()
works fine with chrome, edge

experiencing super slow tests with testcafe

I'm currently experimenting testcafe for the first time, I use the testdriven.io course as an example, and I'm facing really slow tests.
For instance testcafe e2e/login.test.js which is basically a register and a login takes sometimes 6min to pass, which I found insanely slow compared to the 15s the author has in his course.
import {Selector} from 'testcafe';
const randomstring = require('randomstring');
const username = randomstring.generate();
const email = `${username}#test.com`;
const TEST_URL = process.env.TEST_URL;
fixture('/login').page(`${TEST_URL}/login`);
test(`should display the sign-in form`, async (t) => {
await t
.navigateTo(`${TEST_URL}/login`)
.expect(Selector('H1').withText('Login').exists).ok()
.expect(Selector('form').exists).ok()
});
test(`should allow a user to sign in`, async (t) => {
// register user
await t
.navigateTo(`${TEST_URL}/register`)
.typeText('input[name="username"]', username)
.typeText('input[name="email"]', email)
.typeText('input[name="password"]', 'test')
.click(Selector('input[type="submit"]'))
// log a user out
await t
.click(Selector('a').withText('Log Out'))
// log a user in
await t
.navigateTo(`${TEST_URL}/login`)
.typeText('input[name="email"]', email)
.typeText('input[name="password"]', 'test')
.click(Selector('input[type="submit"]'))
// assert user is redirected to '/'
// assert '/' is displayed properly
const tableRow = Selector('td').withText(username).parent();
await t
.expect(Selector('H1').withText('All Users').exists).ok()
.expect(tableRow.child().withText(username).exists).ok()
.expect(tableRow.child().withText(email).exists).ok()
.expect(Selector('a').withText('User Status').exists).ok()
.expect(Selector('a').withText('Log Out').exists).ok()
.expect(Selector('a').withText('Register').exists).notOk()
.expect(Selector('a').withText('Log In').exists).notOk()
// log a user out
await t
.click(Selector('a').withText('Log Out'))
// assert '/logout' is displayed properly
await t
.expect(Selector('p').withText('You are now logged out').exists).ok()
.expect(Selector('a').withText('User Status').exists).notOk()
.expect(Selector('a').withText('Log Out').exists).notOk()
.expect(Selector('a').withText('Register').exists).ok()
.expect(Selector('a').withText('Log In').exists).ok()
});
I tried with Firefox, same deal, albeit much faster, 44s.
(project-tOIAx_A8) ➜ testdriven-app git:(master) ✗ testcafe 'chromium' e2e/login.test.js
Using locally installed version of TestCafe.
(node:16048) ExperimentalWarning: The fs.promises API is experimental
Running tests in:
- Chrome 67.0.3396 / Linux 0.0.0
/login
✓ should display the sign in form
✓ should allow a user to sign in
2 passed (6m 15s)
I wish I could provide more info, went to the dev tools, inspected the console without noticing any error message except this one sometimes:
hammerhead.js:7 WebSocket connection to 'ws://192.168.1.195:38039/4wxhbvTF7!w!http%3A%2F%2F172.18.0.5/http://172.18.0.5/sockjs-node/444/2kjm15kn/websocket' failed: Error during WebSocket handshake: Unexpected response code: 400
, the waterfall looks like slow, is there a way to give a log report of it to help understand what cases this slowness ?
edit: I put a .debug() at beginning and at the end of the tests and save a Performance profile inside Firefox if that helps
edit2: this is a performance profile in chromium if that helps

Ember-auth signin test fails with json

I am having some issues with testing my signin/signout and related features of my app. The app works, but the test fail.
For testing, I use a QUnit with testem (I also tried teaspoon)
test "after signin, should redirect user back to previous page", ->
visit '/library'
fillIn '.signin-email', 'example#example.com'
fillIn '.signin-password', 'examplepass'
click '.signin-btn'
andThen ->
equal(testing().path(), 'library', "Should redirect back to library (was #{testing().path()})")
After running the test, I get a failure:
(screenshot here )
Authentication: visiting restricted page as non authenticated user: after signin, should redirect user back to previous page (2, 0, 2)Rerun544 ms
{user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
Source:
at Test.QUnitAdapter.Test.Adapter.extend.exception (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50149:5)
at superWrapper [as exception] (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:13374:16)
at Object.onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50009:22)
at onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20453:16)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20439:14)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20588:17
Should redirect back to library (was signin)
Expected:
"library"
Result:
"signin"
Diff:
"library" "signin"
Source:
at http://localhost:7357/public/assets/spec/javascripts/integration/authentication_pages_spec.js.js:22:14
at andThen (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50258:20)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49817:21
at isolate (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49989:14)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49972:12
at invokeCallback (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20463:19)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20513:11)
Also, auth.coffee:
App.Auth = Em.Auth.extend
request: 'jquery'
response: 'json'
strategy: 'token'
session: 'cookie'
modules: [
'emberData',
'authRedirectable',
'actionRedirectable'
]
signInEndPoint: '/signin'
signOutEndPoint: '/signout'
tokenKey: 'auth_token'
tokenIdKey: 'user_id'
tokenLocation: 'param'
emberData:
userModel: 'user' # create user model on login
authRedirectable:
route: 'signin'
actionRedirectable:
signInRoute: 'library'
# signInSmart: true
# signInBlacklist: ['signin']
signOutRoute: 'index'
I am unable to find the source of the error, so maybe it is something to do with ember-auth. Any ideas would be very appreciated.
Update 1 [Jan 4th]:
I've written an additional test, which passes only halfway. The test is simpler than the previous in that it does not check a redirect, but only checks that the user name appears in the UI after signin.
test "after signin, TEST", ->
visit '/library'
fillIn '.signin-email', 'user#example.com'
fillIn '.signin-password', 'foobargaz'
click '.signin-btn'
andThen ->
ok exists('.menu-signout'), "signout button exists"
The assertions passes, but I get an additional error reporting the returned JSON as seen in this screenshot. The screenshot basically shows:
[Fail] {user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
[Pass] signout button exists
Additionally, I've also run the tests by mocking the ajax requests with mockjax, but with the same failure.
Third, I should note that I had to patch "ember-auth-request-jquery.js" to make it work with ember testing as suggested here
I'm pretty sure you're failing to wait on the first visit to happen, so here's how I read it (I'm no CS person)
You're telling Ember to go to library
Before being sure it's finished navigating you're trying to fill in 2 fields and click a button (all of which probably doesn't exist)
then you check to see if it's library, but while waiting after you thought you clicked, really the page finishes rendering the login page from the visit
Here's what js2coffe says it'd kind of look like (my main point is the then after the visit).
test "after signin, should redirect user back to previous page", ->
visit("/library").then ->
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click(".signin-btn").then ->
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
Update 1/4: Documentation changed on me
Now we move to educated guess time. Looking through the Ember-auth code it might not be creating any timers/promises that Ember is aware of, in affect Ember thinks it's finished the signin process immediately. So the click promise is resolved immediately and you run your test immediately (andThen waits on the global testing promise to resolve). To test the theory you can do some terrible timeout and see if it does indeed redirect after some time
test "after signin, should redirect user back to previous page", ->
visit "/library"
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click ".signin-btn"
stop()
Ember.run.later this, (->
start()
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
), 5000
It turns out my coffeescript was not the best in the world.
The module function in QUnit should NOT compile to:
module('Authentication: visiting restricted page as non authenticated user', function() {
return setup(function() {
return Em.run(App, App.advanceReadiness);
});
});
but to:
module('Authentication: visiting restricted page as non authenticated user', {
setup: function() {
Ember.run(App, App.advanceReadiness);
},
// This is also new
teardown: function() {
App.reset();
}
});
Additionally, in my spec_helper.coffee file I had something like this:
QUnit.testStart(function() {
// FIXME: this below made it fail every time
// Ember.run(function() {
// return App.reset();
// });
Ember.testing = true;
});
QUnit.testDone(function() {
Ember.testing = false;
});
QUnit.done(function() {
return Ember.run(function() {
return App.reset();
});
});
which seems to have caused some issues, so I just deleted it and the tests now pass.