Automatically call API from Postman and generate a JSON response in a file - postman

I am using Postman to call API. I have a couple to call, so I made a collection and I am able to run it.
I am trying to get the results of the API saved in a file (JSON is fine) and then everytime I call the API, to get the file updated. It is possible to automatically save a response for each API call?
Could you please how can I do it? I have tried with newman, but I`m not being succesful. Thank you.

Managed to get results in JSON files, although I have to update it manually. Followed this video on Youtube and this is the code in .js (if helps anyone in the future)
const newman = require('newman'); // require newman in your project
const fs = require('fs');
// call newman.run to pass `options` object and wait for callback
newman.run({
collection: require('./name_of_postman_collection.json'),
reporters: 'cli'
}).on('beforeRequest', (error, data) => {
if (error) {
console.log(error);
return;
}
console.log(data);
})
.on('request', (error, data) =>{
if (error) {
console.log(error);
return;
}
const fileName = `response ${data.item.name}.json`;
const content = data.response.stream.toString();
fs.writeFile(fileName, content, function (error) {
if (error) {
console.error(error);
}
});
});
I am still trying to find out how to automate the process, to get refreshed files every 2-3 hours for example.

Related

Postman test script - how to call an api twice to simulate 409 error

I am trying to run a few automated testing using the Postman tool. For regular scenarios, I understand how to write pre-test and test scripts. What I do not know (and trying to understand) is, how to write scripts for checking 409 error (let us call it duplicate resource check).
I want to run a create resource api like below, then run it again and ensure that the 2nd invocation really returns 409 error.
POST /myservice/books
Is there a way to run the same api twice and check the return value for 2nd invocation. If yes, how do I do that. One crude way of achieving this could be to create a dependency between two tests, where the first one creates a resource, and the second one uses the same payload once again to create the same resource. I am looking for a single test to do an end-to-end testing.
Postman doesn't really provide a standard way, but is still flexible. I realized that we have to write javascript code in the pre-request tab, to do our own http request (using sendRequest method) and store the resulting data into env vars for use by the main api call.
Here is a sample:
var phone = pm.variables.replaceIn("{{$randomPhoneNumber}}");
console.log("phone:", phone)
var baseURL = pm.variables.replaceIn("{{ROG_SERVER}}:{{ROG_PORT}}{{ROG_BASE_URL}}")
var usersURL = pm.variables.replaceIn("{{ROG_SERVICE}}/users")
var otpURL = `${baseURL}/${phone}/_otp_x`
// Payload for partner creation
const payload = {
"name": pm.variables.replaceIn("{{username}}"),
"phone":phone,
"password": pm.variables.replaceIn("{{$randomPassword}}"),
}
console.log("user payload:", payload)
function getOTP (a, callback) {
// Get an OTP
pm.sendRequest(otpURL, function(err, response) {
if (err) throw err
var jsonDaata = response.json()
pm.expect(jsonDaata).to.haveOwnProperty('otp')
pm.environment.set("otp", jsonDaata.otp)
pm.environment.set("phone", phone);
pm.environment.set("username", "{{$randomUserName}}")
if (callback) callback(jsonDaata.otp)
})
}
// Get an OTP
getOTP("a", otp => {
console.log("OTP received:", otp)
payload.partnerRef = pm.variables.replaceIn("{{$randomPassword}}")
payload.otp = otp
//create a partner user with the otp.
let reqOpts = {
url: usersURL,
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify(payload)
}
pm.sendRequest(reqOpts, (err, response) => {
console.log("response?", response)
pm.expect(response).to.have.property('code', 201)
})
// Get a new OTP for the main request to be executed.
getOTP()
})
I did it in my test block. Create your normal request as you would send it, then in your tests, validate the original works, and then you can send the second command and validate the response.
You can also use the pre and post scripting to do something similar, or have one test after the other in the file (they run sequentially) to do the same testing.
For instance, I sent an API call here to create records. As I need the Key_ to delete them, I can make a call to GET /foo at my API
pm.test("Response should be 200", function () {
pm.response.to.be.ok;
pm.response.to.have.status(200);
});
pm.test("Parse Key_ values and send DELETE from original request response", function () {
var jsonData = JSON.parse(responseBody);
jsonData.forEach(function (TimeEntryRecord) {
console.log(TimeEntryRecord.Key_);
const DeleteURL = pm.variables.get('APIHost') + '/bar/' + TimeEntryRecord.Key_;
pm.sendRequest({
url: DeleteURL,
method: 'DELETE',
header: { 'Content-Type': 'application/json' },
body: { TimeEntryRecord }
}, function (err, res) {
console.log("Sent Delete: " + DeleteURL );
});
});
});

Next JS How can i set cookies in an api without errors?

Next JS. I am trying to set some cookies in my /api/tokencheck endpoint. Here is a very simplified version of the code:
import { serialize } from 'cookie';
export default (req, res) => {
/* I change this manually to simulate if a cookie is already set */
let cookieexists = 'no';
async function getToken() {
const response = await fetch('https://getthetokenurl');
const data = await response.json();
return data.token;
}
if (cookieexists === 'no') {
getToken().then((token) => {
res.setHeader('Set-Cookie', serialize('token', token, { path: '/' }));
});
return res.status(200).end();
} else {
return res.status(200).end();
}
};
I have tried a ton of variations as to where to put my return.res.status... code, and tried many different ways to return a success code, but depending on where I put the code I variously end up with either of the following errors:
"API resolved without sending a response for /api/checkguestytoken, this may result in stalled requests."
or
"unhandledRejection: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
I seem to have some gap in my knowledge about how the API works in Next JS because I cannot figure out how to just run the async function, get a result, set a couple of cookies and then exit with a 200. Could someone please tell me what I'm doing wrong?

AsyncStorage.setItem is not working with Expo BackgroundFetch

using "expo" (~43.0.2) and "expo-background-fetch" (~10.0.3), my app need to download update from server then save it into storage (AsyncStorage is simply used), but failed. here is my code snippet
TaskManager.defineTask("test", async () => {
const token = await AsyncStorage.getItem("token");
const res = await fetch("...", { headers: { "authorization": token } }) // download data from server
const data = await res.json();
await AsyncStorage.setItem("unread", `${data?.count ?? 0}`);
return BackgroundFetch.BackgroundFetchResult[+data?.count ? "NewData" : "NoData"]
})
I find that the AsyncStorage.getItem is working because there is a valid server log. However, i cannot retrieve the unread from AsyncStorage in the app.
can someone help? any suggestion to me?
moreover, i need to call expo.pedometer.getStepCountSync and scheduleNotificationAsync during the background task, is it possible?

PayloadTooLargeError for Expo in React Native

What is causing the PayloadTooLargeError error? I get it sometimes and also when the payload is a few KB (as far as I can figure out).
PayloadTooLargeError: request entity too large
at readStream (/usr/local/lib/node_modules/expo-cli/node_modules/#expo/dev-server/node_modules/raw-body/index.js:155:17)
at getRawBody (/usr/local/lib/node_modules/expo-cli/node_modules/#expo/dev-server/node_modules/raw-body/index.js:108:12)
at read (/usr/local/lib/node_modules/expo-cli/node_modules/#expo/dev-server/node_modules/body-parser/lib/read.js:77:3)
at jsonParser (/usr/local/lib/node_modules/expo-cli/node_modules/#expo/dev-server/node_modules/body-parser/lib/types/json.js:135:5)
at call (/usr/local/lib/node_modules/expo-cli/node_modules/connect/index.js:239:7)
at next (/usr/local/lib/node_modules/expo-cli/node_modules/connect/index.js:183:5)
at serveStatic (/usr/local/lib/node_modules/expo-cli/node_modules/serve-static/index.js:75:16)
at call (/usr/local/lib/node_modules/expo-cli/node_modules/connect/index.js:239:7)
at next (/usr/local/lib/node_modules/expo-cli/node_modules/connect/index.js:183:5)
I found some solutions that you can set the limit to a higher value, but that's not specifically for Expo.io
There is no console.log used in the app
The error you are seeing could be caused by one of the packages you are using which uses body parser.
In body parser there is an option to limit to request body size:
limit
Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the bytes library for parsing. Defaults to '100kb'.
Taken from here.
You can see a related SO questions here and here.
I also saw this GitHub issue for Expo-Cli
I had the same problem, after a lot of trials, I figure it out. The issue is related to the way you fetch the data, you are continuously fetching the data from database, which cause this error.
The solution is to fetch the data only once,
useEffect(() => {
}, []);
Here is code example to
useEffect(() => {
const fetchUser = async () => {
try {
let user = await AsyncStorage.getItem('user_id');
let parsed = JSON.parse(user);
setUserId(parsed);
//Service to get the data from the server to render
fetch('http://myIpAddress/insaf/mobileConnection/ClientDashboard/PrivateReplyConsulationTab.php?ID=' + parsed)
//Sending the currect offset with get request
.then((response) => response.json())
.then((responseJson) => {
//Successful response from the API Call
setOffset(offset + 1);
const pri = Object.values(responseJson[0].reply_list);
setPrivateReplies(pri);
setLoading(false);
})
.catch((error) => {
console.error(error);
});
}
catch (error) {
alert(error + "Unkbown user name")
}
}
fetchUser();
}, []);
I think the storage is merging the old requests, so can you reset the async storage
AsyncStorage.clear()

Postman & Newman - cookieJar.getAll() requires a callback function

I am trying to call a graphql and get the data from cookies, it runs well in postman app. However when I trying to run this postman collection on the command line with Newman
In terminal:
newman run postman_collection.json -e environment.json
then it gave me the error
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block,
or by rejecting a promise which was not handled with .catch().
The promise rejected with the reason "TypeError: CookieJar.getAll() requires a callback function".]
{
code: 'ERR_UNHANDLED_REJECTION'
}
And the Test script code is like this
pm.test("Get a test data", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.data.createTest.success).to.eql(true);
});
pm.test("Test data cookies set", async function () {
const cookieJar = pm.cookies.jar();
const url = pm.environment.get("service-url");
const cookies = await cookieJar.getAll(url);
const cookieNames = cookies.map(cookie => cookie.name);
pm.expect(cookieNames).to.include("test-token");
pm.expect(cookieNames).to.include("legacy-test-token");
});
So I assume the error is because getAll() requires a callback function, Do you know what I'm doing wrong? How can I improve it, Can you help me solve this? Many thanks
'it runs well in postman app' --> I doubt it. I tried and it always passed.
I added a callback, also changed a setting Whitelist Domain in Postman GUI.
pm.test("Test data cookies set", function () {
const cookieJar = pm.cookies.jar();
const url = pm.environment.get("service-url");
cookieJar.getAll(url, (error, cookies)=> {
if(error) console.log(error);
const cookieNames = cookies.map(cookie => cookie.name);
pm.expect(cookieNames).to.include("test-token");
pm.expect(cookieNames).to.include("legacy-test-token");
});
});