sessionStorage.getItem is coming as null in cypress - cypress

I tried to set the session as in a custom command and called it in beforeall block
Cypress.Commands.add('cLogin', (win: any) => {
cy.request({
method: 'POST',
url: `loginAPIURL`,
body: {
UserName: userName,
Password: password,
},
})
.then((response) => {
sessionStorage.setItem('TestApp', response.body);
const token = sessionStorage.getItem('ChartsApp');
headers.token = response.body;
headers.ChartsApp = response.body;
})
});
I called it in
describe('testing', () => {
before('login is called', function () {
cy.cLogin();
// this is setting session and able to print here
});
});
Then I tried to get the session from the Test case via custom command as
Cypress.Commands.add('cLogOut', () => {
const token = win.sessionStorage.getItem('TestApp');
console.log(token);
}
this log is printing as null but not the value from above stored in the session
it('testing session get', ()=> {
cy.cLogOut(); // when this is called inside this custom command session data is null
});
please help me solve this problem if anyone knows about it

Related

after hook doesn't work for the first time in cypress

after hook doesnt work for the first time in cypress but when i retry, it works. in the after hook i call a cy.request and i get a token from another request . i run the token request in before all the tests to make sure i got the token here is the code in the main tests
describe('test', () => {
before(() => {
Login.userLg();
});
it('first test', () => {
cy.visit('`url`);
// some code to test
});
// delete user
afterEach(() => {
user.delete();
});
});
here is the code of the user function in another file (tokenFile)
delete() {
failOnStatusCode: false
cy.request({
method: 'PATCH',
url: `url`,
headers: {
Authorization: 'Bearer ' + Cypress.env('token'),
},
body: {
name: user,
},
});
}
here is the code to get the token in a third file
describe('token', () => {
it('get operator token', () => {
cy.request({
method: 'POST',
url: 'url',
form: true,
body: {
grant_type: 'password',
username: 'user',
password: 'pass',
},
}).then((response) => {
Cypress.env('token', response.body.token);
});
});
});
i call the token request in support/e2e.ts
import './tokenFile';
i tried to put the fucntion in after hook ,put in before hook before login , also i tried afterEach and it didn'T work , i tried to put the token request in command file . nothing works
You should really clear state before tests run rather than after. This is in the official Cypress docs:
https://docs.cypress.io/guides/references/best-practices#Using-after-or-afterEach-hooks
One other benefit of doing this is that if you have a test failure you preserve all the data that the test failed with meaning you can debug the issue.

how to store access token generated using cypress (request) so I can use this as Auth header to call other API's

How can I access the token parsed from JSON response
const getToken = () =>
cy.request({
method: 'GET',
url: '/generateToken'
});
.its('body')
.then((response) => {
JSON.parse(response)
token = token['accessToken'] //How can I access this token value to use in other It tests?
})
You could use this approach:
const getToken = () => {
cy.request({
method: 'GET',
url: '/generateToken'
}).its('body').then(function(response) {
json = JSON.parse(response)
this.token = json['accessToken']
})
}
// Afterwards...
it('should xxxxxxxx xxx xxx', () => {
console.log(this.token)
});
Please note that accessing aliases as properties with this.* will not work if you use arrow functions =>, this is the reason why I used function.

How get information from laravel controller in typescript

I have a problems sending information from a Laravel controller to TypeScript (TS)
I have tried using Ajax but I have not been able to get the information sent from controller
Laravel controller
public function getUrl()
{
$Id = request('id');
$urlAdjunto = Adjunto::where('articulo_id', $Id)->plunk('url');
return response()->json(['url' => $urlAdjunto]);
}
Ajax function in typescript
function getUrl(id) {
var a= $.ajax({
type : 'GET',
dataType: 'json',
url : '/adjunto',
data : {id}
});
return a;
}
A few small modifications to make this type safe and return a promise as expected:
async function getUrl(id: number): Promise<any> {
return await $.ajax({
type: 'get',
dataType: 'json',
url: '/adjunto',
data: {id}
})
}
And now you have a promise to work with that you can observe and react to in your code:
getUrl(15)
.then((response: any) => {
//response.data has everything you need
}).catch((error: any) => {
// do something with failures
})
Or call it from another async function and leverage await for cleaner syntax:
async myFunc(){
try {
const { data } = await getUrl(15)
// do something with your data
} catch(error) {
// we all make mistakes
}
}

How to set to redux store following ajax call?

Not sure what I'm missing here. The console.log prints the correct data, but the return statement is not setting the values to my redux store.
// reducer.js
function getPreviousMonthData(state) {
$.ajax({
url: uri,
method: "GET",
dataType: "json",
success: (data) => {
const newObj = {
previousMonthTotal: data.totals[0],
previousMonth: data.app_reports
};
console.log(newObj);
return Object.assign({}, state, newObj);
}
});
}
In every other context of my app, return Object.assign({}, state, newObj); successfully sets data to my redux store, e.g.:
// reducer.js
function setState(state, newState) {
return Object.assign({}, state, newState);
}
function setToStore(state, data, label) {
let newObj = {};
newObj[label] = data;
return Object.assign({}, state, newObj);
}
EDIT: this is the reducer side of the action... my action-creator is a little bit wacky. The fuller story is that this ajax call comes at the end of a chain of dispatched actions that began with a different ajax call. The overall goal is to (1) receive one set of data based upon a range given by two unix time stamps; (2) calculate the prior month's range; and (3) take that new date range to create a new get request for the prior month's data. Everything works except for the final assignment of the prior month's data to the redux store.
// action_creators.js
export function getDataPointQuery(queryObj) {
const app = queryObj.app_id ? queryObj.app_id : CONFIG.test_app;
const token = queryObj.token ? queryObj.token : CONFIG.token;
const start_date = queryObj.start_date ? queryObj.start_date : CONFIG.start_date;
const end_date = queryObj.end_date ? queryObj.end_date : CONFIG.end_date;
const uri = CONFIG.host2+"/v3/apps/"+app+"/app_reports?token="+token+"&start="+queryObj.start_date+"&end="+queryObj.end_date;
return(dispatch) => {
$.ajax({
url: uri,
method: "GET",
dataType: "json",
}).then((data) => {
dispatch(setToStore(app, "appId"));
dispatch(setToStore(token, "token"));
dispatch(setToStore(data.app_reports, "dataQueryPeriod"));
dispatch(setToStore(data.totals[0], "dataQueryPeriodTotal"));
dispatch(setToStore(data.app_reports[0].created_at, "startDate"));
dispatch(setToStore(data.app_reports[data.app_reports.length-1].created_at, "endDate"));
}).then(() => {
dispatch(getPreviousMonthDates());
dispatch(createChartJsData());
}).then(() => {
dispatch(getPreviousMonthData());
});
};
}
Essentially, the final dispatch is failing to work as anticipated. I'm also cognizant of the fact that it is extraordinarily inelegant to make one ajax call from action_creators and another ajax call from reducer. I was hoping to get it working once and then refactor.
Following the advice from guruPitka, I ditched the reducer ajax call and implemented it into the action_creator, which created the following behemoth:
export function getDataPointQuery(queryObj) {
// variables and stuff
return(dispatch) => {
$.ajax({
url: uri,
method: "GET",
dataType: "json"
}).then((data) => {
dispatch(setToStore(app, "appId"));
dispatch(setToStore(token, "token"));
dispatch(setToStore(data.app_reports, "dataQueryPeriod"));
dispatch(setToStore(data.totals[0], "dataQueryPeriodTotal"));
dispatch(getMonthDates());
}).then(() => {
dispatch(getPreviousMonthDates());
dispatch(createChartJsData());
}).then(() => {
$.ajax({
url: previousUri,
method: "GET",
dataType: "json"
}).then((result) => {
console.log(result);
dispatch(setToStore(result.app_reports, "previousMonth"));
dispatch(setToStore(result.totals[0], "previousMonthTotal"));
});
});
};
}

Session info lost using React-Router navigating two ajax calls in react components

I am new here. Would like to seek your help for the problem that blocks me several days.
The design is simple. I have a server.js running localhost. It provides a POST (Login to acquire authentication) and a GET method (retrieving json after authentication). The login uses basic authentication to verify email/password of a user. if matches, return status 200 and put the user in the session & response. The following are the server side codes:
//Log user in Server.js
app.post('/session/login', function(req, res) {
var email = req.body.email;
var password = req.body.password;
if ( null == email || email.length < 1
|| null == password || password.length < 1 ) {
res.status(401).send("Wrong username or password");
return;
}
if (email == "xxxxx" && password == "xxxxx") {
var user = new User(email, password);
req.session.user = user;
return res.status(200).send({
auth : true,
user : user
});
}else{
return res.status(401).send("Wrong username or password");
}
});
The Get Method is having a basic auth before server can pass the json back. The following are the codes:
function Auth (req, res, next) {
if(req.session.user){
next();
}else{
console.log("Auth");
res.status(401).send({
flash : 'Please log in first'
});
}
}
app.get('/form/FormFields', Auth, function(req, res) {
fs.readFile(FORMFIELDS_FILE, function(err, data) {
if (err) {
console.error(err);
process.exit(1);
}
res.json(JSON.parse(data));
});
});
Now client side, I have two js files, one is a form to email/password to call Login above, and the other is simply get the form info using ajax in react. The navigation uses React-Router. The following are some codes:
// login.js
var LoginBox = React.createClass({
getInitialState: function () {
return {text: '', data: []};
},
handleLoginSubmit: function (data) {
$.ajax({
url: "https://localhost:3000/session/login",
dataType: 'json',
type: 'POST',
data: data,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function () {
return(
<div className="container">
<LoginForm data={this.state.data} onLoginSubmit={this.handleLoginSubmit} />
<p className="tips">{this.state.text}</p>
</div>
);
}
});
var LoginForm = React.createClass({
contextTypes: {
router: React.PropTypes.object
},
getInitialState: function () {
return {data:0,tittle: 'Login Test',text:''};
},
handleSubmit: function (e) {
e.preventDefault();
var email = this.refs.email.value.trim();
var password = this.refs.password.value.trim();
if (!email || !password) {
this.setState({text:"please input both username and password!"});
return;
}
this.props.onLoginSubmit({email:email,password:password});
this.setState({text:""});
this.refs.email.value = '';
this.refs.password.value = '';
//Routing defined in React-Router
const path = '/form';
this.context.router.push(path);
},
render: function () {
return (
<form className="loginForm" onSubmit={this.handleSubmit}>
<p>{this.state.tittle}</p>
<input type="email" placeholder="Your username" ref="email"/>
<input type="password" placeholder="Your password" ref="password"/>
<input type="submit" value="Login"/>
<p className="tips">{this.state.text}</p>
</form>
)
}
});
//code piece in form.js to call server and get form info
loadFieldsFromServer: function() {
$.ajax({
url: "https://localhost:3000/form/FormFields",
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
Eventually, here is my problem. the login is ok, which I can see from network monitoring. I printed the log in server and found user is saved in the session. However when it navigates to form.js, I always retrieve 401 from server code below. from the log, i found user info in the session disappears and hence the following 401 returns.
else{
console.log("Auth");
res.status(401).send({
flash : 'Please log in first'
});
}
Please anybody help take a look at where i am wrong. Many thanks. BTW, just share more info, when I use Postman to simulate two calls to the server. Once I call login first, I can also retrieve form json successfully unless i call logout to clean the user in the session. Just dont know why it does not work in the program.

Resources