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 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 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.
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
}
}
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"));
});
});
};
}
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.