Postman AssertionError when testing using a defined function - postman

I have a Postman request getting a json response like so:
{
"Rules": [
{
"Type": "Melee",
"Captain": "Falcon",
"Falco": "Lombardi",
"Fox": "McCloud",
"Princess": "Peach",
"Kirby": null
},
{
"Type": "Brawl",
"Captain": "Toad",
"Falco": "The bird",
"Fox": "Blip",
"Princess": "Daisy",
"Kirby": null
},
{
"Type": "64",
"Captain": "America",
"Falco": "Dair",
"Fox": "Shine",
"Princess": "Float",
"Kirby": null
}
]
}
I'd like to test all the values returned. The problem is that it won't always be in this order; for example, in the future, '64' might be sent first then 'Brawl' then 'Melee' or something along those lines. So I'm trying to make a loop that checks which type it is, then tests accordingly:
for(var i in jsonResponse.Rules)
{
if(jsonResponse.Rules[i] == "Melee")
{
pm.test("Melee Captain is Falcon", testFunction(jsonResponse.Rules[i].Captain, "Falcon");
pm.test("Melee Falco is Lombardi", testFunction(jsonResponse.Rules[i].Falco, "Lombardi");
//repeat for fox, princess and kirby
}
if(jsonResponse.Rules[i] == "Brawl")
{
pm.test("Brawl Captain is Toad", testFunction(jsonResponse.Rules[i].Captain, "Toad");
//repeat for the rest
}
if(jsonResponse.Rules[i] == "64")
{
pm.test("64 Captain is America", testFunction(jsonResponse.Rules[i].Captain, "America");
//repeat for the rest
}
}
And here is the testFunction method:
function testFunction(value, shouldEqualThis)
{
pm.expect(value).to.eql(shouldEqualThis);
}
This will work when the test passes, but if the test fails I get the following error:
There was an error in evaluating the test script:
AssertionError: expected 'FalconSpelledWrong' to deeply equal 'Falcon'
This is the case for anytime I do 'pm.test' that calls 'testFunction' with values that don't match.
I just want the test to fail rather than break the script.
Core Problem: I don't understand what the difference is between this: (working)
pm.test("Melee Captain is Falcon", function() {
pm.expect(jsonResponseData.Rules[0].Captain).to.eql("FalconSpelledWrong");
})
and this: (not working)
pm.test("Falcon equals FalconSpelledWrong", stringCompare("Falcon", "FalconSpelledWrong"));
function stringCompare(value, shouldEqualThis)
{
pm.expect(value).to.eql(shouldEqualThis);
}
The first one will just fail the test and move on. The second will throw an AssertionError.

The difference between the two is
With first you are passing a callback function (throws AssertionFailure)
while with second you are explicitly calling the function (throws AssertionError)

Related

How can I let `anything-but` support `not-exist` in event pattern

I am following this instruction https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-anything-but to setup a event pattern rule with anything-but like below code:
{
"detail": {
"payload": {
"type": [
{
"anything-but": "test"
}
]
}
}
}
In above example, I set the type field in payload of the event to be anything but test. It works fine if the event has payload->type field. But it doesn't accept the event if it payload doesn't have type field. It seems anything-but filter out none-exist field.
As an example, below event payload is accepted:
{
detail: {
payload: {
name: 'xxx',
type: 'production'
}
}
}
but below event which doesn't have type field is not accepted.
{
detail: {
payload: {
name: 'xxx'
}
}
}
How can I let it support none-exist? I'd like to make it accept event who doesn't have such field.
You have certainly moved on with your life since then... but figured I would drop an answer here for anyone else traversing the interwebs in frustration with EventBridge rules...
In the array you are assigning to type, you can include any number of matching options:
{
"detail": {
"payload":
"type": [
{"anything-but": "test"},
{"exists": false}
]
}
}
}
If you need more complex matching that includes multiple fields existing or not, look into $or
https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-complex-example-or

Postman = To assert that the array in the response body contains a string value in all its elements

I'm new to Postman. My Postman is failing to match test criteria. Could anyone please help! It is returning true even if there is no match
pm.test('Hourly metrics report generated to only 1 building', () => {
_.each(jsonData.attributes, (item) => {
pm.expect(item.building_ref_id).to.include('Mounting_View-EN-1-Internal_Alpha')
})
})
{
"id": "423317",
"type": "space",
"attributes": {
"name": "RM_05_030",
"space_ref_id": "RM_05_030",
"building_ref_id": "80_Fen",
"floor_ref_id": "5"
}
}
I assume that the code above is incomplete and that the response is actually and array of objects and that jsonData contains the parsed response body as a JavaScript array of objects.
The _.each() function takes an array as its first parameter, so you should not pass jsonData.attributes. This is the reason that your test passed; jsonData.attributes isn't an array, your callback will never get executed and no failing assertions means a succeeding test.
You can iterate over jsonData and assert that every item has a nested attribute item.attributes.building_ref_id containing your string:
jsonData = pm.response.json()
pm.test('Hourly metrics report generated to only 1 building', () => {
_.each(jsonData, (item) => {
pm.expect(item.attributes.building_ref_id).to.include('Mounting_View-EN-1-Internal_Alpha')
})
})

How to properly set an API call in QML using XMLHttpRequest

I am building a small weather API as exercise to use QML and properly operate an API call using OpenWeather and you can see there a typical API response.
The problem I am having is that I can't get the API call to work. After setting a minimal example with some cities that you can see below, right next to the city it should appear the symbol of the weather, but it does not happen. The list of the icon can be found here. Source code of the MVE can be found here for completeness.
The error from the compiler: qrc:/main.qml:282: SyntaxError: JSON.parse: Parse error
This is what is happening
This is what is expected
Typical API JSON response can be found both here and below:
{
"coord": {
"lon": -122.08,
"lat": 37.39
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 282.55,
"feels_like": 281.86,
"temp_min": 280.37,
"temp_max": 284.26,
"pressure": 1023,
"humidity": 100
},
"visibility": 16093,
"wind": {
"speed": 1.5,
"deg": 350
},
"clouds": {
"all": 1
},
"dt": 1560350645,
"sys": {
"type": 1,
"id": 5122,
"message": 0.0139,
"country": "US",
"sunrise": 1560343627,
"sunset": 1560396563
},
"timezone": -25200,
"id": 420006353,
"name": "Mountain View",
"cod": 200
}
Below a snippet of code related to the API call:
main.qml
// Create the API getcondition to get JSON data of weather
function getCondition(location, index) {
var res
var url = "api.openweathermap.org/data/2.5/weather?id={city id}&appid={your api key}"
var doc = new XMLHttpRequest()
// parse JSON data and put code result into codeList
doc.onreadystatechange = function() {
if(doc.readyState === XMLHttpRequest.DONE) {
res = doc.responseText
// parse data
var obj = JSON.parse(res) // <-- Error Here
if(typeof(obj) == 'object') {
if(obj.hasOwnProperty('query')) {
var ch = onj.query.results.channel
var item = ch.item
codeList[index] = item.condition["code"]
}
}
}
}
doc.open('GET', url, true)
doc.send()
}
In order to solve this problem I consulted several sources, first of all : official documentation and the related function. I believe it is correctly set, but I added the reference for completeness.
Also I came across this one which explained how to simply apply XMLHttpRequest.
Also I dug more into the problem to find a solution and also consulted this one which also explained how to apply the JSON parsing function. But still something is not correct.
Thanks for pointing in the right direction for solving this problem.
Below the answer to my question. I was not reading properly the JSON file and after console logging the problem the solution is below. code was correct from beginning, only the response needed to be reviewed properly and in great detail being the JSON response a bit confusing:
function getCondition() {
var request = new XMLHttpRequest()
request.open('GET', 'http://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=key', true);
request.onreadystatechange = function() {
if (request.readyState === XMLHttpRequest.DONE) {
if (request.status && request.status === 200) {
console.log("response", request.responseText)
var result = JSON.parse(request.responseText)
} else {
console.log("HTTP:", request.status, request.statusText)
}
}
}
request.send()
}
Hope that helps!
In your code, your url shows this: "api.openweathermap.org/data/2.5/weather?id={city id}&appid={your api key}". You need to replace {city id} and {your api key} with real values.
You can solve it by providing an actual city ID and API key in your request URL

Check for null values in request body using Wiremock

I am trying to setup a wiremock stub that will return a 400 error if any field has a null value in the json payload. Basically to simulate a Bad Request. I've been trying with a regex that matches any lowercase string for the json key but it doesn't seem to like it. I can't find any examples of what I want online so not sure if it's even possible.
My Bad Request body:
{
"cat": null,
"dog": {
"id": 1344
},
"horse": {
"id": 1
},
"fish": 1
}
My Stub:
wireMockServer.stubFor(post(urlEqualTo("/sample-api"))
.withRequestBody(matchingJsonPath("$.^[a-z]*", equalTo(null)))
.willReturn(aResponse()
.withStatus(400)
.withHeader("Content-Type", "application/json")))
In this example I would expect the stub to match "cat" as the value of it is null. This isn't the case. Can anyone tell me what I'm doing wrong?
In the WireMock documentation on Request Matching the section on JSON Path matching. In the source code there is a reference to com.jayway.jsonpath.JsonPath library used. The build.gradle refers to version 2.4.0. The documentation for the Jayway JSON Path library can be found on their Github project page. There is a good, but by no means perfect online evaluator here.
The WireMock documentation only shows support for Regular Expression for the node values in the form of the "matchesJsonPath". In the Jayway documenatation there is an online example: $..book[?(#.author =~ /.*REES/i)]. For this reason the only approach is to name all the nodes that are not allowed to be null.
In the below example mapping all the mentioned nodes will be tested, regardless of their depth (see #id). This mapping will not trigger if all the mentioned nodes are not null, but some unmentioned ones are.
{
"request": {
"urlPattern": "/sample-api",
"method": "GET",
"bodyPatterns" : [ {
"matchesJsonPath" : "$..[?(#.cat == null || #.dog == null || #.horse == null || #.fish == null || #.id == null)]"
} ]
},
"response": {
"status": "400",
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"jsonBody": {
"message": "some sapi message"
}
}
}
If you weren't aware of all possible keys, you could use a Custom Request Matcher to check if the request body contained any null values, and if so, return your 400 error. I'd recommend creating your own class, something that resembles...
public class BodyNullCheck extends RequestMatcherExtension {
#Override
public MatchResult match(Request request, Parameters parameters) {
JSONParser parser = new JSONParser();
try {
JSONObject body = (JSONObject) parser.parse(request.getBody().toString());
for(Iterator iterator = body.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (body.get(key) == null) {
return MatchResult.of(true);
}
}
} catch (ParseException ex) {
ex.printStackTrace();
}
return MatchResult.of(false);
}
}
The above takes the request body and converts it to a JSONObject, and then iterates over all keys in the JSONObject. If any of their values are null, then we will return true. If after iterating over all of them, a null value isn't found, we return false.

Control not being pushed or unshifted into form array Angular 6

I have a variable string in the format like this: id={ID}&sdv={sdvsdbsdb.:}
I need to get the contents between the two { } and push it into a form group array.
The pattern that I am using to match this is \{([a-zA-Z\:\.]*?)\}
Originally I was using a simpler regex \{(.*?)\} but the issue with this is that if you take id={ID}&sdv={sdvsdbsdb.:} and remove the first } it will match the entire string from the first { to the first }.
The function that I am using to do this is this:
while ((matched_parameter = pattern.exec(redirect_string)) != null) {
let redirect_found: boolean = false;
for (let index in parameters.controls) {
if (parameters.controls[index].value['key'] == matched_parameter[1]) {
redirect_found = true;
break;
}
}
if (!redirect_found && matched_parameter[1] != '') {
(<FormArray>this.form_group.get('parameters')).controls.unshift(this.form_builder.group({
"key": matched_parameter[1],
"internal": false,
"source": "record",
"field": "panelist_id",
"varies_by_status": false
}));
}
}
This does work and match any of the parameters that arent already in the list but when it says that it added to the array the new value doesnt appeare.