Pre-request script doesn't change the collection variable using Postman - javascript

Pre-Request Script:
let user_id = pm.collectionVariables.get("user_id");
pm.sendRequest(`http://security.postman-breakable.com/account/${user_id}/summary`, function (err, response) {
if(response.status == "FORBIDDEN"){
pm.collectionVariables.set("status_code", 403);
}else if(response.status == "OK"){
pm.collectionVariables.set("status_code",200);
}
});
Test:
let status_code = parseInt(pm.collectionVariables.get("status_code"));
pm.test(`Status code is ${status_code}`, function () {
pm.response.to.have.status(status_code);
});
The response code is 200 but it reads the previous response code which was 403.
Although I try to change my collection variable called "status_code" by writing pre-request script when the response code changes, it doesn't change.

I can replicate this 100% of the time. Searching for a solution brought me here.
I truly think it's a bug: it seems that Pre-request Scripts (in 10.8.7) get either a shallow copy of whatever state Collection Variables were in at time of Send, or the binding between pm.collectionVariables and Collection Variables has broken. I can't imagine that this behavior is intentional.
For now, I would suggest that you refactor this into a Request and have code in a Test do the pm.collectionVariables.set()
The following doesn't apply to your specific use case, but perhaps it will be relevant to whomever finds this question before the bug is fixed: for my own use I built a utility object with a function to manipulate a "cleanup" list in Collection Variables, but changes wouldn't persist. The workaround for my case is to pass the pm.collectionVariables reference from the Test sandbox at call-time, since that instance seems bound to Collection Variables in the UI.
My Collection's Pre-request Script:
utils = {
addCleanup: (collection, route, id) => {
const list = JSON.parse(collection.get('test_cleanup_list'));
list.push({ route, id, id_field: `${route}id`});
collection.set('test_cleanup_list', JSON.stringify(list));
return list;
}
};
and then from a Test in a Request later in the Run:
utils.addCleanup(pm.collectionVariables, 'account', account.id);

I was able to reproduce a similar behaviour, any chance you did something like this? Where the pre-request script calls a different endpoint than the actual request?
Also, don't know if it can help, in my postman the Forbidden was not uppercase

Related

Axios seemingly manipulates passed data

My current NuxtJS Application contains the following code:
// Create a new Canvas-Object on a Whiteboard
async createCanvasObject({ state }, canvasObject) {
if (!state.id) {
console.error(' Canvas ID is not defined!');
return;
}
console.log(canvasObject);
console.log(canvasObject.mtiID);
await this.$axios
.$post(`/whiteboard/${state.id}/canvas/object`, {
object: canvasObject,
})
.then((res) => console.log(res));
},
What should this code do?
It should send a passed object canvasObject via POST-Request to my backend, without modifying it.
The canvasObject itself is a JSON-Object, which describes an Object on a Canvas.
The logging directly before the Axios-Call yields something like this:
As you can see, there is a lot of stuff defined, and espacially the attribute mtiID.
Now the Problem:
If we look at the request, we can see, that a lot of stuff got stripped away from my JSON, including the mtiID. I have no idea why. The only 'Middleware', that is currently applied to Axios just logs every request to the console, without modifying it.

How to create a Shared Query Folder using the vso-node-api (VSTS)?

In the VSTS Rest API, there's a piece of documentation showing me how to create a folder. Specifically, I would like to create a folder within the Shared Queries folder. It seems like I can do this with the REST API.
I would like to do the same thing with the VSTS Node API (vso-node-api). The closest analogous function I can seem to find would be WorkItemTrackingApi.createQuery. Is this the correct function to use?
When I try to use this function, I'm getting an error:
Failed request: (405)
That seems strange, since a "Method Not Allowed" error doesn't seem like the right error here. In other words, I'm not the person deciding what method (GET/POST/...etc) to use, I'm just calling the VSTS Node API's function which should be using the correct HTTP Request Method.
I think the error code would/should be different if something about my request is wrong (like providing bad parameters/data).
But, I would not be surprised if VSTS didn't like the data I provided with the request. I wrote the following test function:
async function createQueryFolder (QueryHeirarchyItem, projectId, query) {
let result = await (WorkItemTrackingApi.createQuery(QueryHeirarchyItem, projectId, query))
return result
}
I set some variables and called the function:
let projectID = properties.project // A previously set project ID that works in other API calls
let QueryHeirarchyItem = {
isFolder: true,
name: 'Test Shared Query Folder 1'
}
try {
let result = await createQueryFolder(QueryHeirarchyFunction, projectID, '')
Notice that I provided a blank string for the query - I have no idea what to provide there when all I want to create is a folder.
So, I think a lot of things could be wrong with my approach here, but also if my request parameters are wrong maybe I should be getting a 400 error? 405 leads me to believe that the VSTS Node API is making a REST call that the underlying VSTS REST API doesn't understand.
For the third parameter of the createQueryFolder, you should specify the folder path where you want to create the new folder.
Such as if you want to create a folder Test Shared Query Folder 1 under Shared Queries, you should specify parameters for createQueryFolder as:
let result = await createQueryFolder(QueryHeirarchyFunction, projectID, 'Shared Queries')

JavaScript - Promise fulfilled too early?

I created a small sample application using VueJs and created a C# REST API to store and retrieve data in a SQL Server back end.
For testing, I created a simple web page with a form to create a "note". The note is stored by the following function, 'saveData()':
saveData()
{
let promiseStack = [];
var jsondata = JSON.stringify(this.note);
promiseStack.push(this.$http.post('REST_API/note', jsondata));
Promise.all(promiseStack).then(data =>
{
this.$http.get('REST_API/note');
this.$router.push({ name: 'viewnotes', params: { id: data[0].body.id }})
}, error =>
{
console.log(error);
});
}
I tried to use a promise to wait until the 'store' operation in the backend is complete, and issue a GET request to retrieve all notes once the promise is fulfilled.
However, the get request inside the promise doesn't return any data. If I issue the get request manually later one, I retrieve the data that was stored previously.
So I had look into the C# REST API. There are currently two functions: createNote(...), getAllNotes(...). I used a StreamWriter to log to the filesystem when these functions are called, using milisecond precision. What I see is that 'createNote' is called after 'getAllNotes'. So I suspect that the API is working correctly, but something with the way I'm using promises seems to be awfully wrong.
Maybe somebody has a hint?
UPDATE
I know that the GET request doesn't return any data by using the developer toolbar in Chromium. The response is empty
The developer toolbar in the network tab shows that the requests are submitted in the correct order, so the "POST" request is issued first
It seems I found the problem. I had a 'href' tag in my 'Save' link, which triggered an early routing. The intended 'POST' and 'GET' were fired correctly, but there was another 'GET' inbetween somewhere because of the 'href' tag in the link, even though it was empty.
I removed the tag, now it works as intended.

Understanding anonymous functions in Express js

I am new to express and am trying to wrap my head around callbacks in RESTful actions. In my PUT request below, I'm confused about the following line that I have bolded below. Why is response.pageInfo.book being set to the second parameter in the anonymous function (result)? that seems kind of arbitrary.
Also, what is the best way to inspect some of these parameters (req, res, result, etc)? When I console.log it, doesn't show up in my terminal or in my browser console.
exports.BookEdit = function(request, response) {
var id = request.params.id;
Model.BookModel.findOne({
_id: id
}, function(error, result) {
if (error) {
console.log("error");
response.redirect('/books?error=true&message=There was an error finding a book with this id');
} else {
response.pageInfo.title = "Edit Book";
**response.pageInfo.book = result;**
response.render('books/BookEdit', response.pageInfo)
}
})
}
The findOne function takes a query ({_id : id}) and a callback as arguments. The callback gets called after findOne has finished querying the database. This callback pattern is very common in nodejs. Typically the callback will have 2 arguments
the first one error is only set if there was an error.
the second one usually contains the value being returned. In this case you are finding one book in the database.
The line you have bolded is where the book object is assigned to a variable which will be sent back to be rendered in the browser. It is basically some javascript object.
Your second request, to debug this stuff, here is what you can do:
In you code type the word debugger;
e.g.
var id = request.params.id;
debugger;
Next, instead of running your program like this:
node myprogram.js
... run with debug flag, i.e.
node debug myprogram.js
It will pause at the beginning and you can continue by pressing c then Enter
Next it will stop at that debugger line above. Type repl and then Enter and you'll be able to inspect objects and variables by typing their names.
This works very well and requires no installation. However, you can also take a more visual approach and install a debugger such as node-inspector which does the same thing but in a web browser. If you use a good IDE (e.g. webstorm) you can also debug node.js pretty easily.
In the above, the document that is the result of the findOne() query is being added to the pageInfo key of the response and is then being rendered in a template. The first parameter is a potential error that must be checked and the remainder contain data. It's the standard node idiom that an asynchronous call returns to a callback where you do your work.
The writer of the code has also decided to decorate the response object with an extra attribute. This is often done when a request passes through a number of middleware functions and you might want to build up the response incrementally (for example having a middleware function that adds information about the current user to the pageInfo key).
Look and see what else is on response.pageInfo. Information was probably put there by previous middleware (especially since the function above expects the pageInfo key to exist). Just do a console.log(response.pageInfo) and look on your server log or standard out.

Saving Breeze entities manually and updating keyMappings

I want to manually save entities in Breeze. We just don't have the option (as much as I try to fight for my opinion) to use the SaveChanges(JObject saveBundle) and need to directly hit a 3rd party Web API with a specific URL for POST/PUT requests.
So I am basically looping through EntityManager.getChanges() and then handling Modified, Added, and Deleted entities.
I can handle the "Modified" without any problems. However, on "Added", I know I need to update keyMappings when I add a new entity after successful save but cannot find any documentation on how to do that manually in JavaScript.
I also wanted to see if there any examples in returning any errors. Basically I want to hook into this call:
$http(params).then(
function (response) { // success
console.log(response);
// update key mappings if its an "Added" somehow
// entityAspect.acceptChanges();
dfd.resolve("something eventually");
},
function () { // error
// added error object here and reject changes on this entity? or just show error message?
dfd.reject("error");
});
return dfd.promise;
In case anyone's wondering, I just check the entityAspect.entityState.isAdded() method. Get the new identity returned from my 3rd party and just update the id accordingly. Our system is a little bit nicer in that we have a set key for all of the entities.
Code wise it looks something like this (dfd is a $q defer):
$http(params).then(function (response) { // success
// on add update the instance id with the new instance id
if (entityState.isAdded()) {
var newId = response.data.changedInstance.newId;
entity.Id = newId ;
}
entityAspect.acceptChanges();
dfd.resolve(response.data);
},
function (response) { // error
dfd.reject(response.data);
});

Categories

Resources