I am in the middle of upgrading dredd from 1.08 to the latest version, while at it, I am trying to validate our api documentation, written in blueprint with the realtime test api and it is failing.
Since the tests are running against a real time api, the response returned from the api contains different values than specified in the blurprint document. I receive the following error from dredd.
Could someone help me figure it out ? :)
body: At '/data/email' No enum match for: "dredd_testzz#keyflow.se"
body: At '/data/firstName' No enum match for: "Sniper"
body: At '/data/lastName' No enum match for: "Wolf"
body: At '/data/verified' No enum match for: false
## `ResponseSchema` (object)
+ email: `john.doe#example.com` (string, required) - Email address
+ firstName: John (string, required) - First name
+ lastName: Doe (string, required) - Last name
+ verified: true (boolean, required) - True
# Group Account
## Login [/login/?]
Login user
### Login [POST]
Authentication required.
+ Request (application/json)
+ Attribute (LoginInputSchema)
+ Response 200 (application/json; charset=UTF-8)
+ Attribute
+ status: 200 (number, required, fixed)
+ data (ResponseSchema, required, fixed)
The JSON Schema generated by dredd is below
bodySchema: {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"status": {
"type": "number",
"enum": [
200
]
},
"data": {
"type": "object",
"properties": {
"email": {
"type": "string",
"enum": [
"john.doe#example.com"
],
"description": "Email address of the guest."
},
"firstName": {
"type": "string",
"enum": [
"John"
],
"description": "First name of the guest."
},
"lastName": {
"type": "string",
"enum": [
"Doe"
],
"description": "Last name of the guest."
},
"verified": {
"type": "boolean",
"enum": [
true
],
"description": "The user is verified or not"
},
},
"required": [
"email",
"firstName",
"lastName",
"verified",
],
"additionalProperties": false
}
},
"required": [
"status",
"data"
]
}
TL;DR: Try to use fixed-type instead of fixed in your API Blueprint document. fixed requires the sample values to be the actual values.
More elaborate explanation:
body: At '/data/email' No enum match for: "dredd_testzz#keyflow.se"
This means the response returned by the server under test contains a correctly parseable JSON body, but the body isn't valid according to the schema provided by the API description.
The error points to /data/email, which means the {"data": {"email": ... property is problematic. Further, it mentions that enum of values is expected, and that the actual response contains dredd_testzz#keyflow.se, which isn't allowed by the enum. The other errors are similar.
Looking at the API description, the specification of what is expected in the response goes as follows:
+ Attribute
+ status: 200 (number, required, fixed)
+ data (ResponseSchema, required, fixed)
The fixed attribute, as explained in the 4.3 Nested Member Types section of the MSON spec, fixes not only the structure, but also all values, and propagates further down the data structure:
...MAY specify fixed to indicate a "value object" where all the properties MUST be present and the values of the properties MUST be the values specified, if any, in its Nested Member Types. Further, such an object type structure MUST NOT contain any other properties.
I think you want to use fixed-type instead, which fixes just the structure. This is further explained also in the Making Dredd Validation Stricter section of the Dredd docs.
Related
I'm trying to validate JSON response messages according to schema.
But as soon as an attribute has the type "array" or "object", AJV seems to ignore them and does not see the nested attribute within that object or array.
I started trying to break up the schema into multiple smaller ones so all objects/arrays are covered, but this is a tedious task and I'm hoping I'm just using AJV incorrectly.
Example schema (simplified):
{
"type": "object",
"required": [
"MainThing"
],
"properties": {
"MainThing": {
"type": "string",
"description": "Some kind of string.",
"example": "This is some kind of string."
},
"NestedThing": {
"type": "object",
"required": [
"NestedAttribute"
],
"properties": {
"NestedAttribute": {
"type": "String",
"description": "A nested string.",
"example": "This is a nested string"
}
}
}
}
}
If I change the NestedAttribute to an Integer instead of a String, the schema validation in Postman will tell me the response is valid against the schema. While it's not, because the response will contain a NestedAttribute which is a String value.
The following response would be deemed valid, while it's not:
{
"MainThing": "The main thing",
"NestedThing": {
"NestedAttribute": 12345
}
}
My Postman testcode:
var Ajv = require('ajv'),
ajv = new Ajv({logger: console}),
schema = JSON.parse(pm.variables.get("THIS_IS_MY_AWESOME_SCHEMA"));
pm.test('My schema is valid', function() {
var data = pm.response.json();
pm.expect(ajv.validate(schema, data)).to.be.true;
});
If anyone can point me in the right direction, that would be greatly appreciated!
Trying to get rid of the 'empty' value from the enum list on Swagger UI.
My field options is a list of enums which null is not a part of it. My OpenApi3 specification is as below:
"description": "number of options",
"explode": true,
"in": "query",
"name": "options",
"required": false,
"schema": {
"items": {
"enum": [
1,
2,
3
],
"type": "string"
},
"type": "array"
},
"style": "form"
I seem to make it disappear if I make the field required:
But I don't want this. The field should be either nullable or be part of one of the enum values. The reason is that, if the 'empty' value is selected, the request goes like
http://localhost?options=&...
This brings up a HTTP 400 result with the message
"The value '' is invalid."
I don't want this '--' entry to be listed at all. The field should be nullable (nothing selected) or be part of the enum values.
When I search with only birthData in fhir I am getting results.
For example: http://localhost:8080/hapi-fhir-jpaserver/fhir/Patient?_pretty=true&birthdate=2020-03-16 will return patient who has birthdate as 2020-03-16.
When I am searching with _content I am not getting any results. Something like this:
http://localhost:8080/hapi-fhir-jpaserver/fhir/Patient?_content=2019-09-05
_content is for searching text content.
If you want to search for dates you need to use a date search parameter. E.g.:
http://localhost:8080/hapi-fhir-jpaserver/fhir/Patient?birthDate=2019-09-05
This can be achieved using Search Parameters.
Search parameters are essentially named paths within resources that are indexed by the system so that they can be used to find resources that match a given criteria.
Using Search parameter
we can add additional search parameters that will index fields that do not have a standard search parameter defined.
we can add additional search parameters that will index extensions used by your clients.
we can disable search parameters
Example:
Lets say I have a PractitionerRole
"resourceType": "PractitionerRole",
"id": "6639",
"meta": {
"versionId": "1",
"lastUpdated": "2020-03-19T13:26:34.748+05:30",
"source": "#aYyeIlv9Yutudiwy"
},
"text": {
"status": "generated",
"div": "<div xmlns=\"<http://www.w3.org/1999/xhtml\">foo</div>">
},
"active": true,
"practitioner": {
"reference": "Practitioner/6607"
},
"organization": {
"reference": "Organization/6528"
},
"specialty": [
{
"coding": [
{
"system": "<http://snomed.info/sct",>
"code": "42343242",
"display": "Clinical immunology"
}
]
}
]
}
PractitionerRole has thier own search parameters. Apart from those search parameters we wanted to have a search parameter which will filter all practitioner roles based on practitioner.reference. We can achieve this using Search parameters. All we need to do is creating a new search parameter just like below.
{
"resourceType": "SearchParameter",
"title": "Practitioner Referecene",
"base": [ "PractitionerRole" ],
"status": "active",
"code": "practitioner_reference",
"type": "token",
"expression": "PractitionerRole.practitioner.reference",
"xpathUsage": "normal"
}
Here what fhir tells is when user wanted to filter with practitioner_reference then look for PractitionerRole.practitioner.reference.
This looks something like this:
http://localhost:8080/hapi-fhir-jpaserver/fhir/PractitionerRole?practitioner_reference=Practitioner/6607
We can also extend this to search with multiple parameters. We can create a search parameter with or condition so that it can search with multi parameters.
"resourceType": "SearchParameter",
"title": "Patient Multi Search",
"base": [ "Patient" ],
"status": "active",
"code": "pcontent",
"type": "token",
"expression": "Patient.managingOrganization.reference|Patient.birthDate|Patient.address[0].city",
"xpathUsage": "normal"
}
Above SearchParameter will search withPatient.managingOrganization.reference or Patient.birthDate or Patient.address[0].city.
The query looks like this:
Search With City → http://localhost:8080/hapi-fhir-jpaserver/fhir/Patient?pcontent=Bruenmouth
Search With Birth Date → http://localhost:8080/hapi-fhir-jpaserver/fhir/Patient?pcontent=2019-04-06
Hi there REST HATEOAS experts !
Here is a typical JSON response from an HATEOAS service
{
links: {
'add': 'http://myhost/API/students',
'csv-export': 'http://myhost/API/students/export'
},
list: [
{id: '1', name: 'John Doe', links: {'see': 'http://myhost/API/students/1'},
{id: '2', name: 'Jane Doe', links: {'see': 'http://myhost/API/students/2'},
...
]
}
From this we can see that sending full HTTP(s) links along with the response is
very space consuming (yes, I know about gzip)
hard to read (imagine when there are 1000 elements in list)
not sufficient since you still don't know which method to use (nor which content you need to send)
So what I am doing is the following :
{
resType: 'studentsCollection',
rels: ['add','csv-export'],
list: [
{id: '1', name: 'John Doe', resType: 'studentCollectionItem', rels: ['see'],
{id: '2', name: 'Jane Doe', resType: 'studentCollectionItem', rels: ['see'],
...
]
}
And I provide additional endpoints :
/resTypes/studentsColelction/rels
{
resType: 'studentsCollection',
links: {
'add': {method: 'POST', url: '/students', contentType: 'studentForm', resultType: 'studentId'},
'csv-export': {method: 'GET', url: '/students/export', contentType: 'studentCriteria', resultType: 'binary'}
}
}
/resTypes/studentCollectionItem/rels
{
resType: 'studentCollectionItem',
links: {
'see': {method: 'GET', url: '/students/{id}', resultType: 'studentEntity'}
}
}
There also exists /resTypes which return all the resTypes at once to avoid multiple roundtrips
It sounds like JSON Hyper-Schema is a good fit for you. JSON Hyper-Schema is a hypermedia media type that you can use to apply links to your raw data without needing to modify your data.
Let's say you have this JSON response data
{
"list": [
{
"id": "1",
"name": "foo"
},
{
"id": "2",
"name": "bar"
}
]
}
That data can then be describedby the following Hyper-Schema.
{
"title": "Students",
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
},
"links": [
{ "rel": "student", "href": "/students/{id}" }
]
}
}
}
"links": [
{
"rel": "create", "href": "/students",
"method": "POST",
"schema": { "$ref": "/schemas/createStudent" }
}
]
}
The Hyper-Schema is like a hypermedia template that can be applied to a plain JSON document to transform a plain JSON response into a hypermedia enabled JSON response. Notice the URL template in the example /students/{id}. The {id} variable is filled in from the instance data. Therefore, the first item in the list has a link /students/1 and the second item has a link /students/2. This allows you to not have to duplicate all of that link boilerplate in every response.
You use a header Link to associate a JSON response with a Hyper-Schema
Link: </schema/students>; rel="describedby"
At this point you might be thinking, "that's nice but the extra request to get the Hyper-Schema for each response takes even more resources than sending bloated responses". That's why you should design your system so that Hyper-Schemas are cacheable forever. Then when the client sees a describedby link for a resource it already has, it just uses it's cached version. No additional request needed. If you ever need to change the Hyper-Schema, just change the describedby link to a different URI /schema/v2/student and the client will do a one time download of the new Hyper-Schema. Despite the occasional extra request to retrieve a Hyper-Schema, your overall bandwidth usage should be less than if you send all of your links in every request.
This example uses the draft-04 version JSON Hyper-Schema. Since draft-04, JSON Schema has been "under new management" so to speak. Although draft-04 is far from perfect, I'm personally not happy with the direction they have taken the spec since draft-04. However, I encourage you to checkout the latest draft (currently draft-07) as well and make your own decision.
I'm trying to set up some automation using Jenkins and Jira Trigger plugin for Jenkins. I've set up a web hook at Jira side which is able to invoke build on Jenkins as desired.
I've a trouble with obtaining value for a custom field from incoming Jira request.
I'm trying to use "Issue Attribute Path" feature and I've also referred to post (How to use the 'Issue attribute path' in the parameter mapping of jenkins-trigger-plugin)
Howevevr I'm still unable to get value for custom fields customfield_10010, customfield_10011. I've tried with mapping like fields.customfield_10010, fields.customfield_10010.value, fields.customfield_10010.0.value,customfield_10010.0.value and similar combinations. I'm able to get value for other standard fields as suggested in plugin help. ex: status.name, description etc.
I could not get any clue from Jira documentation site either.
Parts of incoming json data is below for easy reference.
"issue": {
"id": "1000x",
"self": "http://localhost:3080/rest/api/2/issue/10007",
"key": "ABC-2",
"fields": {
"issuetype": {
..
},
"parent": {
..
},
"components": [
],
"timespent": null,
"timeoriginalestimate": 28800,
"description": ".....",
"project": {
..
},
"customfield_10010": [
{
"self": "http://localhost:3080/rest/api/2/customFieldOption/10019",
"value": "ABC-Custom 1",
"id": "10019"
}
],
"fixVersions": [
],
"customfield_10011": [
{
"self": "http://localhost:3080/rest/api/2/customFieldOption/10021",
"value": "ABC-Custom 2",
"id": "10021"
}
],
.....
....
....
}
}
You can get the value of a custom field with the following syntax:
fields.find { it.id == "customfield_10010" }.value
I had the same problem and found this solution here:
https://issues.jenkins-ci.org/browse/JENKINS-13216