NightwatchJS capture network traffic / network response - nightwatch.js

I have a ReactJS SPA that I'm testing, specifically I'm testing user signup.
This is a response value from the GET request that my SPA makes when a user has signs up.
{"data":{"id":1387,"token":"3f38cfd0-a392-11e7-8d24-130a2af7f20a"}}
How can I access the data returned from network requests made from my SPA within NightwatchJS?

I'm using a workaround, by adding code into my React SPA that console.warn's out the token when it's received.
Then I'm using NightwatchJS getLog method to access the data. This isn't clean by any means.

Jonathan is right.
And here is full demo to capture the XHR traffic:
https://github.com/Bugazelle/nightwatch-capture-network-traffic
How it is working
Take advantage of the ajaxListener.js
The js is forked from https://gist.github.com/icodejs/3183154
This hack will make all the XHR requests as a warn log to console
{
"type": "response",
"syncMode": this.syncMode,
"method": this.method,
"url": this.url,
"requestData": this.requestData,
"readyState": this.readyState,
"responseText": this.responseText,
"responseCode": this.status,
"responseHeader": this.getAllResponseHeaders()
}
Then take advantage of Nightwatch API .getLog
The .getLog could capture the console warn logs for us

Related

intercepting third party calls in Cypress

I am able to use cy.intercept() to intercept a backend API. But this backend API internally makes a call to a third party server. I want to intercept this internal call and stub it, but it's not happening. This internal call cannot be 'seen' in the Network requests of a browser, but it's definitely happening since it's coded in the backend API.
So to summarize, I can intercept a request but not the second request that the first request makes internally. How do I intercept this second internal request?
Many thanks in advance!
You cannot with Cypress commands, they will only work with requests sent from the browser.
Cypress sets up a network proxy in the browser and catch requests made from the app and response back to the browser.
You can add a mock reply to the frontend intercept in order to cut out the backend API altogether.
This makes sense if you are testing the browser app, since you do not care what happens outside browser.
If you also wish to test then backend API, then call it directly (in a different test) and check it's response. See Example API Test
context("GET /users", () => {
it("gets a list of users", () => {
cy.request("GET", "/users").then((response) => {
expect(response.status).to.eq(200)
expect(response.body.results).length.to.be.greaterThan(1)
})
})
})
See the discussion here which asks the same question.

Keycloak - Getting 401 in Ajax calls after token expired

I'm using keycloak 3.4.3 Server and 3.4.3 springboot adapter. The login is done with the Java Adapter using the following json configurations:
{
"realm": "real name",
"auth-server-url": "http://172.21.34.65/auth",
"ssl-required": "external",
"resource": "appName",
"public-client": true,
"use-resource-role-mappings": true
}
The token is refreshed with non ajax calls but when the request contains the header X-Requested-With: XMLHttpRequest the token is not refreshed. Is there a problem with my config or is this the normal behavior and I need to use the JS adapter to refresh the token before the ajax calls?
For me an ugly solution was to embed an invisible self-reloading iframe that causes the token refresh. But that is the source of another problem: sometimes the redirect after logging into keycloak leads to the iframe url rather than the desired one.
I haven't found a satisfying solution yet.

How to make a cross domain request and send cookies with the request

I'm developing 2 applications for backend and frontend (spring mvc and angular4), i host the spring app on tomcat server using the http port (8080) and my frontend using the http port (4200) , the communication between both of the apps is made using json.
To identify the user i'm using a session cookie.
The problem is that i came to a cross domain issue because i use different ports for both of the apps, the cookie is not send when i make a http post request.
the only solution i found until now :
When i put the angular app inside the /src/main/webapp of my spring project, following this documentation , i dont have the issue and the cookie are automatically set but it's painful to do the previous steps everytime when i want to test something.
I thought also about some workaround like jsonp during the development process but i don't think this would be productive plus later on i need to execute some e2e testing.
Did anyone have an idea/example about how to make this cross domain...
Communication can be established via proxy.
Add in package.json "start": "ng serve --proxy-config proxy.config.json" in "scripts".
In proxy.config.json add:
{
"/api/*": {
"target": "http://server.com:8080",
"secure": false,
"logLevel": "debug"
}
}
So after some researches i came out with this solution :
in term of security and scalability of my backend service the best way is to use CROS, any other solutions like JSONP, Proxy is just a workaround and this will bring nothing because of the same-origin-policy followed by browsers
Following this documentation the scenario that will happens :
1) the browser will send an OPTIONAL request
2) the server will response with the allowed origin
3) if the our domain(the frontend domain/ angular app in my case) is verified the cookies will be automatically send in another request
the implementation that i made :
in the spring app :
//Some logic before this
if ("OPTIONS".equals(request.getMethod())) {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Methods","POST");
response.setHeader("Access-Control-Allow-Headers","Content-Type");
response.setStatus(HttpServletResponse.SC_OK);
((HttpServletResponse) servletResponse).setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
return ;
}
// some logic after this
in the front app we can send the request using xhr like it's described in the attached link.

NodeJS|SailsJS|PassportJS AJAX Authentication: Making Successive Requests for Data

Making Successive Requests for Data
TL;DR
After authentication, I cannot request data from my app's Front-End -- but only through server-side views and Postman can I make subsequent requests for data after logging in, or by authenticating my user in Postman and then making the data request in my app.
First off, I'm a newbie on the server-side.
I've a SailsJS backend which I'm using for REST. Creating and authenticating a user, using LocalStrategy, works fine -- and really, even making subsequent requests for data works fine -- but not via AJAX from my app.
I can use Postman or server-side views to access data, such as /list; making requests after authentication in my app doesn't work -- UNLESS I jump back into Postman and login, then jump back to my app and remake the request.
I do notice that my set-cookie's in my app are different between the first authentication request and the request for /list.
If necessary, I can show some code, but this seems I'm missing a very high-level, basic concept in making authenticated AJAX requests.
EDIT:
My front-end is on a different domain -- Sails runs on localhost:1337 while my UI runs on localhost:8100.
Here's what my /api/config/cors.js looks like:
module.exports.cors = {
allRoutes: true,
origin: '*',
credentials: true,
// methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
// headers: 'content-type'
};
I'm using angular on the front-end, and the subsequent requests are using withCredentials: true -- do I need to add this to the login request too? Must I send the username/email along in the request also?
How do I allow all my subsequent requests for data authenticated after login?
If your frontend application has as a different origin than your backend application the AJAX requests will not include the session cookie by default.
If you are using jQuery:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
This option has to be used for all AJAX requests, so the server can treat them as belonging to the same session.
You also have to configure the server side to allow CORS requests.

AWS S3 static website ajax callback fails

Recently I got to the point to host a static webpage with a subscription option on aws s3 while website development is undergoing. My static web page makes an ajax call to another RESTful service with an email of a subscriber as a parameter. When subscription is done I need to notify a subscriber. Here it seams an issue with the callback.
$.ajax({
type: 'GET',
url: 'http://www.my-domain.com/api/Subscribe?email=' + email
}).success(function (data) {
if (data) {
alert('Thank you for registering!');
}
});
After subscription is done ".success(" doesn't fire up. Response on the request is:
Reload the page to get source for: http://www.my-domain.com/api/Subscribe?email=john.smith#simplyemail.com
Does anyone know if it's an s3 feature or something else?
As per your description this seems to be related with CORS policy.
Look to "why CORS" as Amazon defines it:
In order to keep your content safe, your web browser implements something called the same origin policy.
The default policy ensures that scripts and other active content
loaded from one site or domain cannot interfere or interact with
content from another location without an explicit indication that this
is the desired behavior.
In certain cases, the developer of the original page might have
legitimate reasons to write code that interacts with content or
services at other locations. CORS provides the mechanism to allow the
developer to tell the browser to allow this interaction.
I understood that:
[...] ajax call to another RESTful service[...]
Means call to another server, and this may be blocked by Browser because of CORS.
References:
Mozilla
W3C

Resources