HI there I am making post call using karate And for that I am passing json Payload but before i pass it i want to validate is there any null or empty string present and if yes then Abort the post call and print message empty string or null values cant be accepted.
Thanks in advance!
peter thomas Thank you in advance
This doesn't make sense to me, because if you are preparing this payload yourself, you never need to validate it.
That said, you can run a match anytime.
* def body = { myKey: 'myValue' }
* match body == { myKey: '#string' }
* url 'https://httpbin.org/anything'
* request body
* method post
* status 200
* match response contains deep { json: { myKey: 'myValue' } }
See how the second line does a validation.
Also refer this answer to see how you can programmatically run karate.match() for advanced use-cases: https://stackoverflow.com/a/50350442/143475
Related
I want to assert responseTime of all scenarios. But i do not want to repeat the assertion code in every scenario. Below is my feature file:
Feature: Reqres api test cases
Background: base url
Given url base_url
Scenario: list single user get request
Given path single_user_path
When method get
Then status 200
And assert responseTime < 4000
Scenario: create user using post and inline json payload
* def path = '/users'
Given path path
And request {"name": "morpheus","job": "leader"}
When method post
Then status 201
And assert responseTime < 4000
In the above code block, I want to avoid responseTime assertion duplication. How to achieve this in karate?. Please help.
No this is not supported and not planned either. It is unlikely every API call will have the exact same SLA. Also this is what the Gatling integration is for: https://stackoverflow.com/a/55146463/143475
EDIT as an example of how you can do "reuse" of response assertions:
Feature:
Background:
* def validateResponse =
"""
function() {
var contentType = karate.get("responseHeaders['Content-Type'][0]");
if (contentType !== 'application/json') {
karate.fail('content type is not json');
}
var responseType = karate.get('responseType');
if (responseType !== 'json') {
karate.fail('response type is not json');
}
}
"""
Scenario:
* url 'https://httpbin.org/post'
* request { foo: 'bar' }
* method post
* validateResponse()
Please note that I absolutely don't recommend the above approach because of reasons best explained here: https://stackoverflow.com/a/54126724/143475
I have a Reactive Rest Controller that makes a POST call along with Flux<> Request Body.
I want to do sequential steps in this Post call
Validate Request Body input
Delete all rows based on one field inside Request Body.
Save all data from this Flux Request Body
Return all updated saved data from Flux to Controller
Sample Code
public Mono<Boolean> update(Flux<RequestBody> body, Long id) {.
return body.
.flatMap(d -> this.repo.deleteCriteria(id, d.getValue);
.thenMany(body)
.flatMap(m-> {mapper to convert from DTO to Entity});
.flatMap(s -> this.repo.save(s.name, s.data)
.then(c -> this.repo.findById(id).count)
.then(n-> n.intValue() > 0 ? Mono.just(true) : Mono.just(false));
}.
Controller code -
#ResponseStatus(HttpStatus.CREATED).
#PostMapping("/abc").
public Mono<ResponseEntity<Void> update(Long id, Flux<Body> body) {
Mono<Boolean> onSuccess = this.service.update(id, body);
onSuccess
.log()
.flatMap(b -> b ? Mono.just(new ResponseEntity<>(HttpStatus.CREATED) :
Mono.just(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
I see in Logs that Delete statement getting executed n times. Ideally I wanted it only one time to run but I only know flatMap().
But after delete statement I see below error in logs.
"Error - 400 Bad Request - Request body is missing ....."
FYI - Before when I only had a delete statement and I was not fetching value from Flux Request Body everything was working fine.
Please let me know if there is a way to
read values from Request Body and do validations.
perform multiple operations on this Request body like Delete, save and find by reading some values from the RequestBody.
Any help appreciated :)
I'm trying to send a POST request to the server, this post requires parameters "email" and "password".
but I don't know how to specify parameters, I read the documentation but I didn't understand.
this is my code:
val request=client.post<String> {
url(BASE_URL+"login.php")
body="email=$email,password=$password"
}
fwiw I use something like following here....though I would have thought specifying url like you do should also work. What issue do you see? The body might also be some json for example, or maybe a data class etc if you have serialization setup.
response = client.post(url) {
body = "some params/data etc"
}
It should work if you use serialization, but I solved my problem by using 'Uploading multipart/form-data'
val request=client.post(url) {
body=MultiPartFormDataContent(formData {
append("email","data")
append("password","data")
})
}
see Documentation
In the Readme for nock it explains how one can ignore the request body.
I am using the fixtures feature of nock and I need to ignore the request body (at least partially). How can I do this? Can I write a regex in the body field of the json entries in the fixtures files?
I solved it myself after some painful digging. Here is the solution:
I am trying to nock requests to the Kraken API. The request for the endpoint /0/private/TradesHistory is of method POST and sends a body containing a "query string like" string. For example the body will look like ofs=50&nonce=xxx. The nonce value changes with each request, so I want to ignore it to when looking for a matching nock. (The nonce can only be used once, it would make no sense for the client library to send the same value again).
So I have to add a "preprocessing" function as a config object to the call to nockBack like so:
import * as queryString from 'query-string'
import { back } from 'nock'
import * as path from 'path'
const before = (scope: any) => {
scope.filteringRequestBody = (body: string, aRecordedBody: string) => {
const { of: currentOffset, } = queryString.parse(`?${body}`) //Prepend a `?` so it is actually a query string.
const { of: recordedOffset, } = queryString.parse(`?${body}`)
if (!(currentOffset || recordedOffset)) {//This is the case where no offset is set. There is only possible recorded body in my case that matches this: The other body which has no offset. I replace the body with the recorded body to produce a match.
return aRecordedBody
}
if (currentOffset === recordedOffset) {//This is the case where the sent body has the same offset as the recorded body. I replace the body with the recorded body in order to produce a match.
return aRecordedBody
}
return body
}
}
back.fixtures = `${__dirname}/nockFixtures/`
const { nockDone } = back('nocks.json',{before})
...//Run my queris
nockDone()
Now it works like a charm.
In feature file i am writing assertion as
match response contains {token_type: '#string' }
Is there a way to get the output status of the above assertion value like true or false,
so that i can extend that into java for further processing?
The whole point of Karate is to avoid Java, and I don't recommend doing anything else.
But since you insist, if you want to get the equivalent of the above, just do something like this. Yes, you have to use "normal" JS fundas.
* def response = { token_type: 'foo' }
* def isString = typeof(response.token_type) === "string"
* match isString == true