Params is being nested in params in an Rspec post request - rails-activerecord

I am currently testing a post request for a nested route with Rspec request.
It is set up like this:
describe 'POST /url_contents' do
let!(:role) { create(:role, name: "admin") }
let(:valid_attributes) {
{
jwt: "SAMPLE",
role: role
}
}
context 'when the url is valid' do
before { post "/#{role.name}/1", params: valid_attributes }
it 'returns a status code of 201' do
expect(response).to have_http_status(201)
end
end
end
I am hitting my controller, but when I check params, I am getting a nested params:
:params => { :params => { :jwt => "SAMPLE", :role => #<Role:0x0055959d32a888>" }, "controller"=> "auth"... }
How can I get the params to point to :jwt for my controller?

I've found a solution but would be happy to hear other ideas.
context 'when the jwt is valid' do
before { post "/#{role.name}/1", {
jwt: "SAMPLE",
role: role
}
}
Now params is not nested.

Related

Spring Boot Swagger annotations for supporting API KEYs on AWS API Gateway

I am trying to setup an AWS API Gateway that requires an API KEY in the header of any request. I setup swagger to generate the json definition and AWS imports it perfectly fine. However when I try to add the API KEY Security definition, Amazon rejects my swagger api doc with this error:
Your API was not imported due to errors in the Swagger file.
API Key security definition 'api_key' has unexpected name or location. Ignoring.
I assume i'm doing it wrong...so i've tried several variations along these lines.
given a spring boot config created using springfox thusly:
#Bean
public Docket swaggerSpringMvcPlugin() {
List<ApiKey> securitySchemes = new ArrayList<>();
ApiKey apiKey = new ApiKey("apiKey", "api_key", "header");
list.add(apiKey);
//the above is probably where i'm missing something
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.securitySchemes(securitySchemes)
.select()
.paths(PathSelectors.regex("/api/swaggertest"))
.build();
}
and the above api defined like so:
#RestController
public class SwaggerTestController {
#ApiOperation(notes = "my notes", value = "test", nickname = "testNickname",
tags = {"tests"}, authorizations = {#Authorization(value="api_key")} )
#ApiResponses({
#ApiResponse(code = 200, message = "Nice!", response = Swag.class)
})
#RequestMapping(value = "/api/swaggertest", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<Swag> getSwag() throws Exception {
return ResponseEntity.ok().body(new Swag());
}
}
When i run my app the api-docs produce (i remove some sections to keep it smaller):
{
swagger: "2.0",
host: "localhost:4014",
basePath: "/",
tags: [
{
name: "swagger-test-controller",
description: "Swagger Test Controller"
}
],
paths: {
/api/swaggertest: {
get: {
tags: [
"tests"
],
summary: "test",
description: "my notes",
operationId: "testNickname",
consumes: [
"application/json"
],
produces: [
"application/json"
],
responses: {
200: {
description: "Nice!",
schema: {
$ref: "#/definitions/Swag"
}
}
},
security: [
{
api_key: [ ]
}
]
}
}
},
securityDefinitions: {
api_key: {
type: "apiKey",
name: "api_key",
in: "header"
}
},
definitions: {
Swag: {
type: "object",
properties: {
foo: {
type: "string"
}
}
}
}
if anyone can help point me to how to add api key support to this, i'd appreciate it.
Security definition should look like this, referencing <any_name> in your method security.
"<any_name>" : {
"type" : "apiKey",
"name" : "x-api-key",
"in" : "header"
},

Why is an Array in my payload being flattened in Sinatra / Rack::Test?

I'm trying to test a small Sinatra app using rspec. I want to pass a rather complex payload and am running into issues i do not understand: my payload contains an array of hashes. When I run the actual application this will work as expected, yet when I use the post helper to run my tests, the array will contain a merged hash:
post(
"/#{bot}/webhook",
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
)
In the sinatra handler I use params to access this payload:
post '/:bot/webhook' do |bot|
do_something_with(params)
end
When I now look at the structure of params when running the test suite, I will see the following structure:
[{"some" => "fixture", "name" => "generic", "parameters" => {"facebook_sender_id" => "zuck-so-cool"}}]
which I do not really understand. Is this a syntax issue (me being a ruby noob), am I using params wrong, or is this a bug?
EDIT: So i found out this is an "issue" with the way that Rack::Test will serialize the given payload when not specifying how to (i.e. as form data). If I pass JSON and pass the correct headers it will do what I expect it to do:
post(
"/#{bot}/webhook",
{
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
}.to_json,
{ 'HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
)
Still I am unsure of this is an issue with the passed data structure not being possible to be serialized into form data or if this is a bug in the way that Rack::Test serializes data.
Looking at the relevant portion of the specs it looks like this is is expected behavior.

FactoryGirl Sequence not instantiating when creating an object with association

I have to write a few tests for a controller I have. I have 3 models : User, UserInfo and UserPaymentPreference. I am using FactoryGirl to make a UserPaymentPreference object like this:
factory :advertiser_payment_preference_sequence do
association :advertiser_user, factory: [:advertiser_user_sequence]
end
factory :advertiser_user_sequence, class: 'AdvertiserUser' do
deposit { rand(100..1000).round(2) }
sequence(:login) { |n| "#{Faker::Internet.domain_name}#{n}" }
user_type 'advertiser'
association :user_info, factory: :advertiser_user_info_sequence
trait :no_deposit do
deposit 0
end
end
factory :advertiser_user_info_sequence, class: 'AdvertiserUserInfo' do
sequence(:firstname) { |n| "#{Faker::Name.first_name}#{n}" }
sequence(:organization) { |n| "#{Faker::Company.name}#{n}" }
sequence(:phone) { |n| "#{Faker::PhoneNumber.cell_phone}#{n}" }
sequence(:fiscal_code) { |n| "#{Faker::Company.duns_number}#{n}" }
sequence(:address) { |n| "#{Faker::Address.street_address}#{n}" }
sequence(:city) { |n| "#{Faker::Address.city}#{n}" }
end
This works fine if I do something like FactoryGirl.build(:advertiser_user_info_sequence) it will create an object of type UserInfo with all the fields populated as they should be.
However when I try to make an AdvertiserPaymentPreference object by doing FactoryGirl.build(:advertiser_payment_preference_sequence) all the user_info fields will be "" instead of the value that it should have been created by the association.
describe 'Advertiser::Billing::SettingsController', type: :request do
let!(:campaign) { create :campaign }
let!(:user) { campaign.user }
let!(:user_info) { user.user_info }
let!(:advertiser_payment_preference) { create(:advertiser_payment_preference, advertiser_user_id: user.id)}
before :each do
login(user)
end
describe "PUT/PATCH /advertiser/billing/settings" do
context "it is a valid request" do
it "updates the resource" do
binding.pry
new_advertiser_payment_preference = build(:advertiser_payment_preference_sequence)
binding.pry
params = {}
params['user_info'] = to_api_advertiser_info(new_advertiser_user_info)
api_put '/advertiser/billing/profile', params
expect(response.status).to eq(200)
user_info.reload
expect(user_info.organization).to eq(new_advertiser_user_info.organization)
expect(user_info.phone).to eq(new_advertiser_user_info.phone)
expect(user_info.fiscal_code).to eq(new_advertiser_user_info.fiscal_code)
expect(user_info.country).to eq(new_advertiser_user_info.country)
expect(user_info.address).to eq(new_advertiser_user_info.address)
end
end
end
end
This is how the test for the controller looks like . When I call new_advertiser_payment_preference = build(:advertiser_payment_preference_sequence) I get an object user_info with "" on all fields that are made using advertser_user_info_sequence.

How to populate the response model for http_code 400/401 in swagger ui using ruby?

How to populate the response model for http_code 400/401 in swagger ui using ruby? I want to add the response model for 401 error.My code looks something like this:
user_entity.rb:
module something
module V1
class UserEntity < Grape::Entity
expose :id, documentation: { type: "String", desc: "User id" }
expose :phone, documentation: { type: "String", desc: "Registered phone number" }
expose :email, documentation: { type: "String", desc: "Email" }
expose :created_at, documentation: { type: "String", desc: "format:yyyy-mm-ddThh:mm:ss.364+(gmt) for eg:\"2015-10-04T15:33:39.364+04:00\"" }
expose :updated_at, documentation: { type: "String", desc: "format:yyyy-mm-ddThh:mm:ss.364+(gmt) for eg:\"2015-10-04T15:33:39.364+04:00\"" }
expose :access_token, if: lambda { |object, options| options[:show_access_token] == true }
expose :access_token_expires, if: lambda { |object, options| options[:show_access_token] == true }
private
def id
object.id.to_s
end
end
end
end
user_resource.rb:
module something
module V1
class UsersResource < Grape::API
include something::V1::Defaults
resource :users, desc: 'Operations about users' do
desc "Returns all users", {
headers: {
"Authorization" => {description: "pass the access token as Bearer",
required: true
}
},
http_codes: [
[401, 'Not authorized: The access token does not exist or is invalid'],
[200, 'Success',UserEntity]
],
detail: 'This endpoint returns all the users that have successfully registered with a valid phone number.'
}
get do
User.all.to_a
end
.....
I figured it out myself. I just added all the error codes i needed in my defaults.rb and added it to my http_codes

How to refactor RSpec tests for API

I've got a series of RSpec tests for a Sinatra based API, and would like to refactor them to make them a little simpler and reduce repetition.
Here's an example a test for a route:
describe 'post /sections with empty data' do
before do
params = {
:site_id => site.id,
:page_id => page.id,
}
post '/sections', params, #session
end
specify { last_response.status.should == 200 }
specify { json_response['id'].should_not be_nil }
specify { json_response['type'].should == default_section_type }
end
Each test will be using the same base URL, with the same session data, the only difference is the parameters, and what the responses should be. There's at least 4 tests (GET, POST, PUT, DELETE) per route, and usually more.
Is there a way of making these tests more manageable?
Without resorting to metaprogramimng, you can use nested describe blocks to override only the parameters you want:
describe "/sessions" do
before do
send(http_method, "/sessions", params, #session)
end
describe "with POST" do
let(:http_method) { :post }
describe "and empty data" do
let(:params) do
{ :site_id => site.id, :page_id => page.id }
end
specify { last_response.status.should == 200 }
specify { json_response['id'].should_not be_nil }
specify { json_response['type'].should == default_section_type }
end
describe "with non-empty data" do
let(:params) do
# relevant params
end
end
end
describe "with GET" do
let(:http_method) { :get }
# ...
end
end
Have no idea if this works but it can give you an idea of what you can do
describe ' /sections with empty data' do
before(:all) do
#params = {
:site_id => site.id,
:page_id => page.id,
}
end
after(:each) do
specify { last_response.status.should == 200 }
specify { json_response['id'].should_not be_nil }
specify { json_response['type'].should == default_section_type }
end
[:get, :post, :put, :delete].each do |http_method|
it "works with #{http_method}" do
send(http_method) '/sections', #params, #session
end
end
end
Update
Reading your question again made me realize that this is not what you actually asked for. If it doesn't help at all tell me so I delete it.

Resources