How to use only matchers at the stubs without applying body? - spring-cloud-contract

I am confused about behavior of body and bodyMatchers sections.
For example for a contract response.
I want my consumer (stub) to have a body from file (exact response from the stub) and producer only to have some matchers for the response (to validate reponse).
1 case I tried:
...
body (
file('__files/someFile.json')
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Expected - result:
Test has matchers for the reponse - false
Test doesn't have body matching - false
Stub has response body from the file - true
Stub doesn't have matchers - true
My workaround for a json body and response section:to add something for the producer body or i won't get matchers at the test response:
body (
$(
consumer(
file('__files/someFile.json')
),
producer(
cards: [
cardType: anyNonEmptyString()
]
)
)
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Shortly the problem I see - bodyMatchers requires body, but it is not intuitive. Response could have only matchers for the producer (tests) and request could have only matchers for the consumer (stubs).
I think it should work like this:
body (
$(
consumer(
file('__files/someFile.json')
)
)
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Updated:
request {
body(
file('__files/offer13-request.xml').asString()
)
bodyMatchers {
xPath('/a/b/c/text()', byRegex('123'))
}
}
And i see at the stubs:
{
"matchesXPath" : {
"expression" : "/soap:Envelope/#xmlns:soap",
"equalTo" : "http://schemas.xmlsoap.org/soap/envelope/"
}
}, {
"matchesXPath" : {
"expression" : "/a/b/c/text()",
"matches" : "123"
}
}
But i need only my matcher "expression" : "/a/b/c/text()"

I want my consumer (stub) to have a body from file (exact response from the stub) and producer only to have some matchers for the response (to validate reponse).
That's not how it works.
body (
file('__files/someFile.json')
)
bodyMathers {
jsonPath('$.[cards[0]].cardType', byRegex('[A-Z]{2}')
}
Means that
1) you have a body in a file someFile.json
2) it will be parsed and each part of the body will be analyzed like described in the json file
3) for th concrete json path there will be a regex verification (only for that json path)
Shortly the problem I see - bodyMatchers requires body, but it is not intuitive.
Since it's a bodyMatcher it requires a body. It kind of makes sense since it's a body matcher. If it was a matcher for headers it would require headers.

Related

AWS AppSync - DeleteItem doesn't execute response mapping template

When attempting to delete an item using the following request mapping:
{
"version" : "2017-02-28",
"operation" : "DeleteItem",
"key" : {
"id": { "S" : "$ctx.args.id"},
"sortKey" : { "S" : "$ctx.args.sortKey"}
}
}
If the item exists it will process the result through the response template, however when the item does not exist the response template is never run.
Response template:
#set($ctx.result.status = "SUCCESS")
#set($ctx.result.message = "This was a success!")
$utils.toJson($ctx.result)
I am aware that when an item does not exist in Dynamo it will perform no action but I would expect that it would still process through the template.
Is there anything I am missing or is it impossible for AppSync to processed a DeleteItem request through the response mapping when the document does not exist?
This the expected execution behavior for the version of the template you are using (2017-02-28).
You can switch your request mapping template version to 2018-05-29 and your response mapping template will be executed, with the following characteristics:
If the datasource invocation result is null, the response mapping template is executed.
If the datasource invocation yields an error, it is now up to you to handle the error. The invocation error is accessible using $ctx.error.
The response mapping template evaluated result will always be placed inside the GraphQL response data block. You can also raise or append an error using $util.error() and $util.appendError() respectively.
More info https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-changelog.html#aws-appsync-resolver-mapping-template-version-2018-05-29
So for your example:
{
"version" : "2018-05-29", ## Note the new version
"operation" : "DeleteItem",
"key" : {
"id": { "S" : "$ctx.args.id"},
"sortKey" : { "S" : "$ctx.args.sortKey"}
}
}
and response template
#if ( $ctx.error )
$util.error($ctx.error.message, $ctx.error.type)
#end
#set($ctx.result.status = "SUCCESS")
#set($ctx.result.message = "This was a success!")
$utils.toJson($ctx.result)

Firestore Update a document field Using Rest API

Im trying to perform PATCH Opeartion in cloud firestore using REST API.
This is my Request body
`{
"fields": {
"name": {
"stringValue":"Dinesh"
}
}
}`
When i fire the request , All the existing fields inside the document are getting deleted and only the name field is getting updated. In the Documentation they have given the Document Mask. but i dont understand how it works , neither im able to find any samples for that. Somebody know how to update only one field inside the document without affecting other fields ?
Without a DocumentMask object, the patch method defaults to replacing the Firestore Document with the request body rather than updating the submitted fields and retaining omitted fields.
The DocumentMask is submitted as an updateMask parameter containing the fieldPaths to be patched. It took a while but thanks to this answer and a lot of attempts I figured out that each fieldPath property of the updateMask object needs to be individually included in the query string of the request url:
https://firestore.googleapis.com/v1beta1/projects/{projectId}/databases/{databaseId}/documents/{document_path}?updateMask.fieldPaths=status&updateMask.fieldPaths=title
Where status and title are two fields in the request body. Note that fields included in the request body are disregarded if they are omitted from the query string, remaining unchanged.
Here is another example giving this json structure from firestore
"fields": {
"eth0": {
"mapValue": {
"fields": {
"address": {
"stringValue": "172.0.0.1"
},
"port": {
"stringValue": "8080"
},
"endpoint": {
"stringValue": "10.0.5.24"
}
}
}
}
}
Then to update the endpoint field only
curl -sSLX PATCH \
-H "Authorization: Bearer {TOKEN}" \
-H "Content-type: application/json" \
-d "{
\"fields\": {
\"eth0\": {
\"mapValue\": {
\"fields\": {
\"endpoint\": {
\"stringValue\": \"10.10.2.24\"
}
}
}
}
}
}" \
"https://firestore.googleapis.com/v1/projects/{project-id}/databases/(default)/documents/{collection}/{document}?updateMask.fieldPaths=eth0.endpoint")
Your request body is ok. But you need to use the update mask.
From reading the documents I found that the DocumentMask is used to restrict a get or update operation on a document to a subset of its fields. So by adding 'name' to your field paths on the mask, it will only allow you to update that specific field and the others won't get deleted.
You can read more about it here.

Error: Unrecognized operator: $nearSphere in meteor js

i have simple code in meteor js for find near by garages within 10 Kilometres the query works fine in my mongodb database if run it manually in robomongo it works fine but when i run it in my routes it throws an error. like this.
Error: Unrecognized operator: $nearSphere in meteor jsi
i see some blogs they said you need to call a server side method for this. so i use below code to call a server side route.
Router.route('/search/:name',
{name:'searchlist',
data:function(){
var searchedParams = this.params.name.split('-');
var lat = searchedParams.pop();
var lng = searchedParams.pop(1);
return {searchValue: Centers.find({ coordinates: { $nearSphere: { $geometry: { type: "Point", coordinates: [lng,lat] }, $maxDistance: 10000 } } })}
}
}, { where: "server" }
);
if anyone have idea please help.
You're mixing definitions for client and server side routes.
Server-side route should look like this:
Router.route('/search/:name', function(...){...}, { where: 'server' });
Client-side route could look like this:
Router.route('/search/:name, { ... });
Thus, your route is actually client-side route and minimongo doesn't have support for $nearSphere operator as noted here: https://github.com/meteor/meteor/blob/devel/packages/minimongo/NOTES
First, look at Styx answer and make the route a client route by eliminating this part:
', { where: "server" }'
Now that the router is available to the client, let's fix the $nearSphere issue, by changing the operator to $near. Use the following code:
Centers.find(
{
geoloc: {
$near: {
$geometry: {
type: "Point",
coordinates: [lng, lat]
}
}
}
}
);
Give it a try and let me know if it works.

Get POST body data in Silex RESTful API

I am creating a RESTful API using Silex. To test I am using Chrome's "Simple REST Client" addon.
In the addon I set the URL to: http://localhost/api-test/web/v1/clients
I set the "method" to: POST
I leave the "headers" blank
I set the "data" to: name=whatever
In my "clients.php" page I have:
require_once __DIR__.'/../../vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$app = new Silex\Application();
$app->post('/clients', function (Request $request) use ($app) {
return new Response('Created client with name: ' . $request->request->get('name'), 201);
}
In the addon, the output shows: "Status: 201" (correct), a bunch of headers, and "Data: Created client with name: " (it should say "Data: Created client with name: whatever"
What am I doing wrong? I also tried: $request->get('name')
Thank you.
Three steps were needed to resolve:
1) In "Simple Rest Client" set the "Headers" to:
Content-Type: application/json
2) Change the "Data" to:
{ "name": "whatever" }
3) In Silex add the code to convert input to JSON, as described at http://silex.sensiolabs.org/doc/cookbook/json_request_body.html:
$app->before(function (Request $request) {
if (strpos($request->headers->get('Content-Type'), 'application/json') === 0) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
});
Then I was able to access the data in my PHP code with:
$request->request->get('name')
Thank you #xabbuh for your help, which led me towards the answer.

angular 2 - asynchrone issue

I have a very simple Typescript script (ionic2 and angular2) that add an authentication header before an HTTP call. Here is the idea (simplified code):
function CreateAuthorization(){
this.header.append('tests' : 'test')
Storage.retrieve('Auth').then(data){
this.header.append('authorization' : data.token)
}
}
function customHttp(url){
CreateAuthorization();
Http.get(url, this.header);
}
In my Request header, I have 'test' = 'test' but I do NOT have 'authorization' = 'MyToken'.
How can I make in sort to "wait" for the header to be set in Storage.retrieve('Auth') ?
I know that I can use a setTimeout() but I don't like this dirty workaround.
The solution could be an observable/promise but I don't really master those things.
Any help would be very appreciated :)
Geoffrey
It's because your CreateAuthorization method is asynchronous. I would try something like that leveraging promise chaining to be notified when the Authorization header is actually added:
createAuthorization() {
this.header.append('tests' : 'test');
return Storage.retrieve('Auth').then(data){
this.header.append('authorization', data.token);
return true;
}
}
customHttp(url) {
this.createAuthorization().then(() => {
this.http.get(url, { headers: this.header });
});
}

Resources