JWS Error during API testing python flask - api

I am trying to test a function, which basically calls the API by passing a some values, which is then loaded to the schema to be validated and then accepted or rejected based on validation.
The below is my test function.
params = {
'first': [10,20],
'second': 400,
'third ': 'Testing'
}
headers = {
'Authorization': 'Bearer{}'.format(token),
'Data-type' : "json"
}
response = self.client.post(url_for('MyView:post', id=current_id.id),
json=params,
headers=headers)
This renders me the error below:
{
"msg": "Invalid header string: must be a json object"
}
I was able to check the issue and found out its due to the mapping of invalid types. But as headers is still a dictionary, I am not able to comprehend why this error is being rendered.
I have also added the structure of my schema and API below:
class MySchema(marshmallow.Schema):
id = fields.Integer(required=True)
second = fields.Integer(fields.Integer(), required=True)
first = fields.List(fields.String(), required=False)
third = fields.Str(validate=validate.Length(min=0, max=255), required=False)
class Meta:
fields = ('id',
'second',
'first',
'third')
#validates_schema(pass_original=True)
def validate_numbers(self, _, data):
//function code
The below is the structure of my API
class MyView(V1FlaskView):
#jwt_requried
def post(id):
//code

Maybe a space character is missing after Bearer:
'Authorization': 'Bearer {}'.format(token),

Related

django rest pagination on api view decorator

im trying to do pagination on my django rest code, but i get the same code when i change the number of the page, this is what im doing to get that page: http://localhost:8000/movies?page=3
When i change the page number i get the same response, idk if i have to send the number of the page or something but i do the same of this stackoverflow thread
I put the entire view code:
#api_view(['GET', 'POST', 'DELETE', 'PUT'])
def movies(request):
if request.method == 'GET':
if request.query_params.get('id'):
try:
id = request.query_params.get('id')
movie = Movie.objects.get(id=id)
serializer = MovieSerializer(movie, many=False)
return Response(serializer.data)
except Movie.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
movies = Movie.objects.all().order_by('release_date')
serializer = MovieSerializer(movies , many=True, context={'request':request})
if request.query_params.get('page'):
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request)
serializer = MovieSerializer(result_page, many=True, context={'request':request})
return Response(serializer.data)
if request.query_params.get('Genre'):
genreparam = request.query_params.get('Genre')
genre = Genre.objects.get(name=genreparam)
queryset = Movie.objects.filter(genre_relation=genre.id).values().order_by('release_date')
return Response(queryset)
return Response(serializer.data)
this is my settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 2,
}
this is what i get whatever number i send via request params
[
{
"id": 1,
"title": "Guardians of the galaxy",
"tagline": "this is a tagline",
"overview": "this is an overview, starlord in the begins...",
"release_date": "1971-07-13T03:00:00Z",
"poster_url": "http\"//posterurl",
"backdrop_url": "http\"//backdropurl",
"imdb_id": "idk what is a imdb",
"genre_relation": []
},
{
"id": 2,
"title": "Avengers endgame",
"tagline": "this is a tagline",
"overview": "tony stark dies, theres no more happy days, only days",
"release_date": "2019-07-13T03:00:00Z",
"poster_url": "http//posterurl",
"backdrop_url": "http//backdropurl",
"imdb_id": "idk what is a imdb",
"genre_relation": [
1
]
}
]
You are not using the pagination properly. You need to instantiate the paginator with the request, and then call paginate_queryset. You are merely instantiating a paginator, and then completely ignoring it.
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request)
You thus should rewrite this to:
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request, view=self)
Note that we here pass view=self, since the LimitOffsetPagination uses self.request, self.response, etc.
Furthermore you should not construct a new serializer, but reuse the existing one, and pass result_page as the queryset:
serializer = MovieSerializer(result_page, many=True, context={'request': request})
Finally you should return the paginated results with:
return paginator.get_paginated_response(serializer.data)
This will add pagination metadata to the response.
So a full example:
#api_view(['GET', 'POST', 'DELETE', 'PUT'])
def movies(request):
# ...
if request.query_params.get('page'):
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request, view=self)
serializer = MovieSerializer(result_page, many=True, context={'request':request})
return paginator.get_paginated_response(serializer.data)
# ...
Note that using the #api_view decorator is often discouraged. You might want to consider using the #api_view decorator.

Karate - how to use param from response to test child endpoints

I have a parent URL that returns an array of objects with id and slug, this is dynamically generated because it depends of the user (test env). After getting this data, how can I dynamically call each element object from an array and make another request ?
Example :
Scenario: parent
Given url 'posts'
Then Status 200
* assert response.status == true
Example url/posts returns a data of array of objects :
[
{id: 6, slug: 'my-post-6'},
{id: 23, slug: 'example-test-23'},
{id: 133, slug: 'another-test-133'},
]
Then I want to make a get request to every object like so : url 'posts/' data.slug
How can I do this ?
GET url 'posts/my-post-6'
// Validate schema
GET url 'posts/example-test-23'
// Validate schema
GET url 'posts/another-test-133'
// Validate schema
Karate's call keyword auto-loops over a JSON array of objects. Refer the docs: https://github.com/karatelabs/karate#data-driven-features
You can try this simple example:
Feature:
Scenario:
* def data = [{ slug: 'one'}, { slug: 'two'}]
* call read('#called') data
#called #ignore
Scenario:
* url 'https://httpbin.org/anything'
* path slug
* method get
This is getting improved in future versions, refer: https://github.com/karatelabs/karate/issues/1905 (available now in 1.3.0.RC2)

Karate API, How do I match 2 different responses

I get 2 different responses from an endpoint depending on it's state and either one of them is fine.
first response:
{"available":'#boolean',"collection":'#boolean'}
second response:
{"code": "#string","message": "#string"}
I'm trying the following but it's not working:
def firstSchema = {"available":'#boolean',"collection":'#boolean'}
def secondSchema = {"code": "#string","message": "#string"}
match response contains any (firstSchema, secondSchema)
Any ideas how to best get this working so either response is fine?
Thanks
Try this:
* def first = { available: true, collection: true }
* def second = { code: 'foo', message: 'bar' }
* def response = second
* def expected = response.code ? { code: '#string', 'message': '#string' } : { available: '#boolean', collection: '#boolean' }
* match response == expected
Also refer to the documentation on "Conditional Logic". You can use JsonPath to "check" what shape the response is and then define expected results.
I get 2 different responses from an endpoint and either one of them is fine.
first response:
response1.xml
second response:
response2.xml
I tried below assertion but it's not working:
And match response == read('response1.xml') || response == read('response2.xml')

API_Defining an array

How can I define array below in Intellij? I am sending this API request and getting error:
sharedAccountDetails [
Account details.
SharedAccountItem{
accountNumber string
Account number of the user.
accountName string
Account name of the user.
accountType string
Account type saving/current etc.
branchCode string
Branch Code.
}]
This is my request below:
And request { 'channel': 'email'}
And request { 'accountNumber': '000000000'}
And request { 'accountName': 'Mr Bytes C'}
And request { 'accountType': 'Current Account'}
And request { 'branchCode': '000'}
It is requesting for the arrays. how do I define them?
Thanks in advance.
Regards,
Tshilidzi
Not sure I understand but can you look at the demo examples of Karate carefully. Looks like you have to understand how to use JSON. See this example below:
And request
"""
{
sharedAccountDetails: [
{ accountNumber: '000000000', 'accountName': 'Mr Bytes C', 'accountType': 'Current Account' }
]
}
"""

Backbone.js and ActiveRecord

This is a Noob question regarding Backbone.JS and ActiveRecord.
I'd be grateful for a pointer on how to debug this.
I'm trying to use Backbone.Js code to create a "Trainer" object, which has a single attribute, "name" (a string).
The front end of the application is Ruby on Rails. There is a data migration for the Trainer table.
In trainers controller:
def create
document = Trainer.create! params[:trainer]
render :json => document
end
Now, in app/assets/javascripts/backbone/views/trainers/new_view.js:
Gym.Views.Trainers.NewView = Backbone.View.extend({
el : 'div.trainer_form',
template: JST['backbone/templates/trainers/new_template'],
model : new window.Gym.Models.Trainer({}),
initialize: function() {
this.document = this.options.user;
Backbone.Validation.bind(this, {
invalid: function(view, attr, error) {
$("form#new-trainer .errors ul").append("<li>" + error + "</li>")
}
});
this.render();
},
render : function() {
$(this.el).html(this.template({trainer:this.model.toJSON()}));
return this
},
events : {
"click input#submit_button" : 'create_trainer'
},
create_trainer : function(event) {
event.preventDefault()
params = $("form#new-trainer").formParams()
params['user_id'] = Gym.currentUser.userId
this.model.save(params, {success : function(model, response) {
Gym.trainers.add(model)
Objects.views.selectTrainer.render()
Gym.current_trainer = model
$("select#trainer_selector").val(Gym.current_trainer.get('id'))
Objects.views.new_trainer.model = new Gym.Models.Trainer()
Objects.views.new_trainer.render()
}
});
Now, I can see in the Rails log that I'm getting to the controller:
Started POST "/trainers" ...
Processing by TrainersController#create as JSON
Parameters: {"name"=>"Lori Stevens", "user_id"=>1, "trainer"=>{}}
However, when it gets to the SQL, I see this:
[1m^[[36mSQL (0.4ms)^[[0m ^[[1mINSERT INTO `trainers` (`created_at`, `name`, `updated_at`, `user_id`) VALUES ('2012-11-07 20:33:09', NULL, '2012-11-07 20:33:09', NULL)^[[0m
The parameter 'name' - which comes from the template, and is the attribute of the Trainer object- is not getting to the database, even though the parameter "name" is set in the JSON.
I'd appreciate a pointer on how to debug this - clearly I am not understanding how Backbone.js and ActiveRecord are connected.
The Controller takes the request from your browser and puts the data into ActiveRecord:
def create
document = Trainer.create! params[:trainer]
...
end
But then you see request in the log, params[:trainer] equals the empty hash {}
You can either change the javascript that it creates json with a hash like
{ 'trainer': {'name' : 'Lori stevens', ... }}
I don't know how easy this in backbone.
Or you can change your controller that it gets the values out of the hash and constructs an new hash for your trainer model, like it is:
gotten_name_from_json = params['name']
...
document = Trainer.create!(
{:name => gotten_name_from_json, :town => gotten_twon_from_json})
I made this verbose to show that using this you can translate what ever json comes in, even when it comes from third parties where you can not control the format.