How to validate nested response using REST Assured? - web-services

Need help to validate particular JSON parameter from below response using REST Assured library.
I tried some of the options to validate other similar parameter as shown below but it didn't work.
.then().body("value.value.value.name", hasItems("balanceResultCode")).body("value.value.value.value", hasItems("0"));
If I want to validate "resultCode" & "subscriberIdType" from below response then how can I do it?
[
{
"name":"Id",
"value":"11"
},
{
"name":"version",
"value":null
},
{
"name":"header",
"value":[
{
"name":"mVersion",
"value":"1"
},
{
"name":"Name",
"value":"BalQ"
},
{
"name":"appID",
"value":"90091"
},
{
"name":"requestUid",
"value":"REST_REQUQEST_1"
},
{
"name":"sessionId",
"value":"REST_SESSION_1"
},
{
"name":"requestType",
"value":"SomeRequestType"
},
{
"name":"requestNumber",
"value":"REQ_111"
},
{
"name":"requestDuplicate",
"value":"1"
},
{
"name":"serviceProvider",
"value":1
},
{
"name":"username",
"value":"user"
},
{
"name":"password",
"value":"pass"
},
{
"name":"resultCode",
"value":100
}
]
},
{
"name":"content",
"value":[
{
"name":"subscriberAddressing",
"value":[
{
"name":"subscriber",
"value":[
{
"name":"subscriberIdType",
"value":200
},
{
"name":"subscriberIdValue",
"value":"1234567890"
}
]
}
]
}
]
}
]

This is one way:
then().
body("find { it.name == 'header' }.value.find { it.name == 'resultCode' }.value", is(100)).
body("find { it.name == 'content' }.value.find { it.name == 'subscriberAddressing' }.value.find { it.name == 'subscriber' }.value.find { it.name == 'subscriberIdType'}.value", is(200));
You can read up on Groovy collections and GPath to learn more.

First of all you need to import
import static org.hamcrest.CoreMatchers.equalTo;
after that you may use it as follows
RestAssured.given().auth().oauth2(token).when().accept("application/json").get("someurl").then().statusCode(200).body("name[0]", equalTo("Anwar"));

Related

BatchWriteItemCommand with AWS.DynamoDB class using AWS SDK V3 in Nodejs

I have been trying for hours to perform a DynamoDB DeleteRequest using BatchWriteItemCommand but I keep getting the following error:
Error ValidationException: 1 validation error detected: Value null at 'requestItems.td_notes_sdk.member.1.member.deleteRequest.key' failed to satisfy constraint: Member must not be null
This is what my table looks like:
Partition key: user_id (string)
Sort key: timestamp (number)
DynamoDB Screenshot
This is what my code looks like:
// Import required AWS SDK clients and commands for Node.js
import {
DynamoDBClient,
BatchWriteItemCommand,
} from "#aws-sdk/client-dynamodb";
// Set the parameters
export const params = {
RequestItems: {
"td_notes_sdk": [
{
DeleteRequest: {
Item: {
Key: {
user_id: { S : "bb" },
timestamp: { N : 2 },
},
},
},
},
],
},
};
export const run = async () => {
const ddbClient = new DynamoDBClient({ region: "us-east-2" });
try {
const data = await ddbClient.send(new BatchWriteItemCommand(params));
console.log("Success, items inserted", data);
return data;
} catch (err) {
console.log("Error", err);
}
};
run();
Here are some resources that I've been trying to follow along with:
Resource 1: Writing items in Batch Example
Resource 2: AWS Javascript SDK v3 Documentation
Update: BatchWrite PutRequest work with the code below, so I know that the structure of my keys/attributes is closer to being correct. Still does not work for DeleteRequest.
export const params = {
RequestItems: {
"td_notes_sdk": [
{
PutRequest: {
Item: {
user_id: { "S": "bb" },
timestamp: { "N": "5" },
},
},
},
],
},
};
You don't supply an Item when deleting an item. You supply a Key.
Here is a working example:
const params_delete = {
RequestItems: {
"td_notes_sdk": [
{
DeleteRequest: {
Key: {
user_id: { S: "bb" },
timestamp: { N: "2" },
},
},
},
],
},
};
const delete_batch = async () => {
const ddbClient = new DynamoDBClient({ region: "us-east-2" });
try {
const data = await ddbClient.send(new BatchWriteItemCommand(params_delete));
console.log("Success, item deleted");
return data;
} catch (err) {
console.log("Error", err);
}
};
delete_batch();

checkSchema syntax documentation

I would like to use the checkSchema method instead of what I am currently doing with all the checks on the post route in an array. The problem I have is I can't find good documentation on the syntax used in the object for each key. The doc page for schema validation (https://express-validator.github.io/docs/schema-validation.html) gives one example but no links to all the syntax that defines all the attributes you can use (isInt, toInt, isUppercase, rtrim, etc.) I have searched high and low for the docs that tell you everything you can use there but no luck. Can someone point me in the right place?
express-validator is a set of express.js middlewares that wraps validator.js validator and sanitizer functions.
you can find all the rules available in the link above.
here is a good example how it's used with checkSchema:
import { checkSchema, validationResult } from 'express-validator'
const schema = {
id: {
isFloat: true,
// Sanitizers can go here as well
toFloat: true,
errorMessage: "must be a valid number"
},
first_name: {
exists: {
errorMessage: "first_name is required"
},
isLength: {
errorMessage: "first_name has invalid length",
options: {
min: 1
}
}
},
middle_name: {
optional: {
options: { nullable: true, checkFalsy: true }
}
},
last_name: {
exists: {
errorMessage: "last_name is required"
},
isLength: {
errorMessage: "last_name has invalid length",
options: {
min: 1
}
}
},
date_of_birth: {
isISO8601: {
errorMessage: `date of birth is not a valid iso date`
},
isBefore: {
date: "01-01-2000",
errorMessage: `should be less than 01-01-2000`
},
isAfter: {
date: "01-01-1970",
errorMessage: `should be greater than 01-01-1970`
}
},
email: {
exists: {
errorMessage: "email is required"
},
isEmail: {
errorMessage: "email is invalid"
}
},
current_country_of_residence: {
exists: {
errorMessage: "current_country_of_residence is required",
options: {
checkNull: true,
checkFalsy: true
}
}
},
current_city_of_residence: {
exists: {
bail: true,
errorMessage: "current_city_of_residence is required"
},
isMongoId: {
errorMessage: "current_city_of_residence is has invalid id for"
}
},
email: {
isEmail: { errorMessage: 'email is not a valid email' },
isLength: { errorMessage: 'email has invalid length', options: { min: 1 } }
},
skills: {
isArray: {
errorMessage: `invalid value for skills`,
options: {
min: 3,
max: 5
}
},
isIn: {
options: ["java", "C++", "javascript"],
errorMessage: `allowed values for skills are: ${["java", "C++", "javascript"]}`
},
custom: {
options: (values) => {
const unique_values = new Set(values)
if (unique_values.size !== values.length) {
return Promise.reject()
}
return Promise.resolve()
},
errorMessage: `you can't add duplicated`
},
customSanitizer: {
options: async (value, { req }) => {
return value
}
}
}
}
const validate = () => {
return [
checkSchema(schema),
(req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.mapped() })
}
next()
}
]
}
export default validate()

JSON Validate check based on response from arrayElement

I wanted to check from the response format if status=AVAILABLE then arrayElement should return with roomTypeId else roomTypeId should not return for other status.
[
{
"status": "SOLDOUT",
"propertyId": "dc00e77f",
"Fee": 0,
"isComp": false
},
{
"roomTypeId": "c5730b9e",
"status": "AVAILABLE",
"propertyId": "dc00e77f",
"price": {
"baseAveragePrice": 104.71,
"discountedAveragePrice": 86.33
},
"Fee": 37,
"isComp": false
},
]
[
{
"status": "SOLDOUT",
"propertyId": "773000cc-468a-4d86-a38f-7ae78ecfa6aa",
"resortFee": 0,
"isComp": false
},
{
"roomTypeId": "c5730b9e-78d1-4c1c-a429-06ae279e6d4d",
"status": "AVAILABLE",
"propertyId": "dc00e77f-d6bb-4dd7-a8ea-dc33ee9675ad",
"price": {
"baseAveragePrice": 104.71,
"discountedAveragePrice": 86.33
},
"resortFee": 37,
"isComp": false
},
]
I tried to check this from below;
pm.test("Verify if Status is SOLDOUT, roomTypeId and price information is not returned ", () => {
var jsonData = pm.response.json();
jsonData.forEach(function(arrayElement) {
if (arrayElement.status == "SOLDOUT")
{
pm.expect(arrayElement).to.not.include("roomTypeId");
}
else if (arrayElement.status == "AVAILABLE")
{
pm.expect(arrayElement).to.include("roomTypeId");
}
});
});
You need to check if the property exists or not.
With the have.property syntax you can do that.
You can read the Postman API reference docs and also Postman uses a fork of chai internally, so ChaiJS docs should also help you.
Updated script:
pm.test("Verify if Status is SOLDOUT, roomTypeId and price information is not returned ", () => {
var jsonData = pm.response.json();
jsonData.forEach(function(arrayElement) {
if (arrayElement.status === "SOLDOUT") {
pm.expect(arrayElement).to.not.have.property("roomTypeId");
} else if (arrayElement.status === "AVAILABLE") {
pm.expect(arrayElement).to.have.property("roomTypeId");
}
});
});

How to intercept every not asset calls to constantly render the index.html file

I have built an SPA Application, i need to deploy it on a loopback server, and i never used it, so i am lost with all of these json files you can configure to intercept the calls.
I simply need to intercept every calls (expect static files) and to return my index.html file for every cases.
Technically, it is just a middleware that is invocked after the "serve-static" middleware and say "ok if you are here, you are not an asset, render the index.html file".
My / path already return the index.html, how am i supposed to implement that rule properly with loopback?
I guess it is going to happens on the middleware.json file, so mine currently looks like this:
{
"initial:before": {
"loopback#favicon": {}
},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": true,
"credentials": true,
"maxAge": 86400
}
}
},
"session": {
},
"auth": {
},
"parse": {
},
"routes": {
"loopback#rest": {
"paths": ["${restApiRoot}"]
}
},
"files": {
"serve-static": {
"params": "$!../client"
}
},
"final": {
"loopback#urlNotFound": {}
},
"final:after": {
"loopback#errorHandler": {}
}
}
You can a middleware which will check if nodejs has already served a request, if not redirect to /.
//in middleware.json
"final:before": {
"./middleware/redirect.js": {},
}
//in server/middleware/redirect.js
module.exports = function() {
return function redirect(request, response, next) {
if (!response.headersSent) {
response.redirect('/');
} else {
next();
}
}
};

StrongLoop modify data before each get on model

I have the following model in LoopBackJS:
{
"name": "member",
"base": "PersistedModel",
"properties": {
"firstName": {
"type": "string"
}
"public": {
"type": "boolean"
}
},
"relations": {
"spouse": {
"type": "hasOne",
"model": "spouse",
"foreignKey": "spouseId"
}
}
}
Now I need to modify the firstName field, so one can only see "public": true members first name and the others gets firstName: "*". The function for that I have already.
But how can I access the data on each data-access-request?
I tried it with the with the operation hook e.g. find, findOne,... but when I miss one of them some users could access the firstName.
With the remote hook it's the same.
Now I'm trying it with the connector hook:
connector.observe('after execute', function(ctx, next) {
if (ctx.model === 'familyMember') {
if (ctx.req.command === 'find') {
}
}
next();
});
For all find queries (mongodb) but there I can't access the data. Is there a way to access those data? Or is there a much better (build-in) solution for this problem?
You need to check result after each remote :
member.afterRemote('**', function(ctx, modelInstance, next) {
if (ctx.result) {
if (Array.isArray(modelInstance)) {
var answer = [];
ctx.result.forEach(function (result) {
if(result.public === false)
result.firstName = "*";
answer.push(result);
});
} else {
var answer =ctx.result;
if(answer.public === false)
answer.firstName = "*";
}
ctx.result = answer;
}
next();
});