Running and saving the response in repeat API gatling which is to be used in the next exec call - gatling

I want to call an API in the exec for n number of times. Each time, I want to save the response. All the responses would be collectively passed in an array in the body in my next exec call.
Example
Let's say, I want to call upload Attachment API 5 times. The response of the API is in the following format.
{
"attachmentId":"239092340ahds",
"path":"abc/def"
}
After calling the above API 5 times, I want to use the response in the next exec call in the chain. The request body would look like this.
{
"data":[
{
"attachmentId":"239092340ahds",
"path":"abc/def"
},
{
"attachmentId":"239092340ahds",
"path":"abc/def"
},
{
"attachmentId":"239092340ahds",
"path":"abc/def"
},
{
"attachmentId":"239092340ahds",
"path":"abc/def"
},
{
"attachmentId":"239092340ahds",
"path":"abc/def"
}
]
}
How to achieve this in gatling?

I ended up using the transform function. I got a variable from session. Appended the response to that variable and then saved it in the same variable.
.check(
bodyString
.transform((s, session) => {
val response: String = session("response").as[String]
if (!response.isBlank) {
s + "," + response
} else {
s
}
})
.saveAs("response")))

Related

how intercept and stub the response of a rpc call in react with cypress

I want to intercept a rpc call that I made to the api in my react app. I'm using a custom hook that receives the buffer and the rpc method that I want to call and returns the data(something like react-query useQuery hook).
The thing is because of being a rpc call, the request urls of my requests are all the same and the response is binary, I can't distinguish the requests and intercept the one to stub.
One example of making a rpc call:
const {response, loading, error} = useRpc({
Buffer: GetUser,
Request: GetUserRequest
});
Edit 1:
I'm using
cy.fixture('fixutre-file').then((data) => {
const response = new TextDecoder().decode(res.body);
cy.intercept('https://example.com/', { method: 'POST' },
(req) => {
req.continue((res) => {
if ("some condition for distinguishing the request I want to intercept, here") {
res.send({ fixture: 'fixutre-file' });
}
});
});
}):
to get the response and decide whether or not intercept this req and instead send back my fixture data. But the response constant is still some unreadable string. What's wrong with my approach?
Edit 2:
Another approach that I used, was to use the cypress-protobuf package and encode my fixture.json file with the related protobuffer file:
cy.fixture('fixutre-file').then((data) => {
cy.task('protobufEncode', {
fixtureBody: data,
message: 'the_message',
protoFilePath: './protobuf/protofile.proto'
}).then((encodedData) => {
cy.intercept('https://example.com/', { method: 'POST' },
(req) => {
/////// approach 1(didn't work): ///////
// can't use this approach(because there is no identifier on
// req object to distinguish the requests I want to
// intercept)
// if ("some condition based on `req` here") {
// req.reply(encodedData);
// } else {
// req.continue();
// }
/////// approach 2: ///////
// using encodedData to compare it with res.body
req.continue(res => {
// can't compare res.body with encodedData, because
// encodedData is an empty string!
});
}).as('needToWait');
cy.wait('#needToWait').get('some selector').should('exist')
});
}):
Now the problem is:
encodedData is just an empty string, meaning it didn't work, so I can't compare the response with my fixture data to intercept the related request
You can simply check for some value from the request that distinguishes it from the other requests. Request bodies and headers are often good places to start. Additionally, you can use req.alias to conditionally assign an alias if you need to wait for that specific call.
cy.intercept('/foo', (req) => {
if (req.body.bar === true) { // or whatever logic indicates the call you want to intercept
req.alias = 'baz'; // conditionally assign alias
req.reply({foo: 'bar'}); // mock response
} else {
req.continue(); // do not mock response
}
});
cy.get('something')
.click()
.wait('#baz'); // waits for your specific 'baz' call to happen.

How do i set time out in a HTTP request in react js?

I want to set time out for the following http request. I also want to catch 504 error, just in case and, also know normal error.
the HTTP request function:
const getClientData = (clientId) => {
const params = {
"id": [localStorage.dataId],
"clientId": "clientId",
};
return httpRequest('post','client','getClientDetails','params',params);
};

NextJS API routes how to handle multiple requests with MongoDB

I have an API route. Inside of this route I handle requests coming from my components with MongodDB. My problem is that I am sending a PUT request from one of my components to that route and it is working. But now I want to send another PUT request from another component. How will I achieve this?
if (req.method === "PUT") {
try {
const { _id, id, change } = req.body;
let set = `settings.$[el].${id}`;
const data = await db
.collection("Todos")
.updateOne(
{ _id: _id },
{ $set: { [set]: change } },
{ arrayFilters: [{ "el._id": id }] }
);
res.status(201).json(data);
} catch (err) {
res.status(500).json({ message: "Unable to instert the data." });
}
}
This is for my one request and now I want to send another one but also with another data. If I send it there will conflict so it fails. Some basic solutions I found but they are not sustainable.
One way is to create a new route /api/newRoute.
Another way is when you send the request add to its body a variable that differentiates between the two. For example:
body: {
// your original data
type: "newType" // this variable can be named anything you like
}
In the api route you can use the following code example:
if (req.method === "PUT" && req.body.type == "newType") {
try {
// your new code
} catch (err) {
// your new code
}
}

Passing through an array with axios

I am having an issue passing through an array through axios post call. The issue is that on the api endpoint the data received is null, when I try posting using postman it works fine so the endpoint is working. Example of the array
I need to pass the data in this format:
{
"UpdateItemList": [
{
"Text": 1,
"Value": "5"
},
{
"Text": 1,
"Value": "5"
}
]
}
Code:
export function createLogEntry(postData) {
let payload = {
UpdateItemList: postData
};
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', {
data: payload
});
return {
type: CREATE_LOG,
payload: request
}
}
Is there any issue with the way I am passing through the data with my current code?
Try with
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry',payload);
This worked for me!
The issue is that you are confusing two ways axios can be used. Currently you are actually posting your data nested in an object within and the key data:
{
data: {
UpdateItemList: postData
}
}
If you are using the axios.post function, you should just pass your object with the data to post as the second object like this:
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', payload);
If you are using the config object method, you should just pass one single object with url, method and data as keys.
// Send a POST request
axios({
method: 'post',
url: 'https://localhost:44312/api/Audit/AddLogEntry',
data: payload
});
This behaviour is explained in the axios Readme here: https://github.com/axios/axios#axios-api

Meteor call in a loop. How to prevent multiple call?

The method call "Insert All sms data" run more than once I tried to prevent using counter variable but on client side it run once and on the server side it runs x time as shown in the image, thus adding data to db multiple timres which I do not want, this should add to db only once. I want also add another call whith in method call "Insert All sms data" which should run x as the loop. I stuck here.
Meteor 1.8 react 16.8
imports/api/kuser.js
'Find all numbers' (smsText) {
if(!this.userId) {
throw new Meteor.Error('not-authorized');
}
let counter = 0;
return userKisandb.find({
userId: this.userId
}).fetch().map((Mob) => {
// return Mob.Mnumber
if(Mob.Mnumber) {
Meteor.call('Send to all',Mob.Mnumber,smsText,(err,resp) => {
//sms.js
if(err){
console.log("send all numbers error2", err);
} else {
console.log("send all numbers ", resp);
if(counter === 0) {
Meteor.call('Insert All sms data',smsText,counter,(err,resp1) => {
//get inserted data id
//allSmsdb
if(err){
console.log("Insert All sms data error", err);
} else {
console.log("this should run only once ",counter);
//Another call to be added which should run x times
}
})
counter++
}
}
});
} //Mob.Mnumber
});
},
and the method 1 is
'Send to all'(mob,text) {
return "sucess";
},
method 2 is
'Insert All sms data' (smstext,counter) {
if(!this.userId) {
throw new Meteor.Error('not-authorized');
}
console.log("Inserted same data x times",counter);
if(counter === 0) {
return allSms.insert({
smstext,
userId: this.userId,
updatedAt: moment().valueOf(),
});
}
},
And output is
Meteor methods can be called from the front end, asking the back end to do something. It doesn't make sense for a back end method to do a Meteor.call, because it's already on the back end. It will work, kind of, but then you get into trouble because your counter isn't passed around as you expect.
Make your method only work on the server, and just loop around the data, doing all of the work, rather than breaking it up into pieces like you have.

Resources