Add api/nonprofits#create
This commit is contained in:
parent
f6f92788dd
commit
c20d01c4e8
10 changed files with 114 additions and 602 deletions
13
app/controllers/api/api_controller.rb
Normal file
13
app/controllers/api/api_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
class Api::ApiController < ApplicationController
|
||||
rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue
|
||||
|
||||
protected
|
||||
|
||||
def record_invalid_rescue(error)
|
||||
render json:{errors: error.record.errors.messages}, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
end
|
|
@ -1,5 +1,7 @@
|
|||
class Api::NonprofitsController < ApplicationController
|
||||
rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue
|
||||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
class Api::NonprofitsController < Api::ApiController
|
||||
# requires :nonprofit, type: Hash do
|
||||
# requires :name, type: String, desc: 'Organization Name', allow_blank: false, documentation: { param_type: 'body' }
|
||||
# requires :zip_code, type: String, allow_blank: false, desc: 'Organization Address ZIP Code', documentation: { param_type: 'body' }
|
||||
|
@ -12,94 +14,15 @@ class Api::NonprofitsController < ApplicationController
|
|||
# requires :email, type: String, desc: 'Username', allow_blank: false, documentation: { param_type: 'body' }
|
||||
# requires :password, type: String, desc: 'Password', allow_blank: false, is_equal_to: :password_confirmation, documentation: { param_type: 'body' }
|
||||
def create
|
||||
#model = CreateModel.new(clean_params)
|
||||
Qx.transaction do
|
||||
# raise Errors::MessageInvalid.new(model) unless model.valid?
|
||||
nonprofit = Nonprofit.new(clean_params)
|
||||
nonprofit.save!
|
||||
end
|
||||
# Qx.transaction do
|
||||
# byebug
|
||||
# np = ::Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(clean_params[:nonprofit]))
|
||||
|
||||
# begin
|
||||
# np.save!
|
||||
# rescue ActiveRecord::RecordInvalid => e
|
||||
# if e.record.errors[:slug]
|
||||
# begin
|
||||
# slug = SlugNonprofitNamingAlgorithm.new(np.state_code_slug, np.city_slug).create_copy_name(np.slug)
|
||||
# np.slug = slug
|
||||
# np.save!
|
||||
# rescue UnableToCreateNameCopyError
|
||||
# raise Grape::Exceptions::ValidationErrors.new(errors: [Grape::Exceptions::Validation.new(
|
||||
# params: ['nonprofit[name]'],
|
||||
# message: 'has an invalid slug. Contact support for help.'
|
||||
# )])
|
||||
# end
|
||||
# else
|
||||
# raise e
|
||||
# end
|
||||
# end
|
||||
|
||||
# u = User.new(clean_params[:user])
|
||||
# u.save!
|
||||
|
||||
# role = u.roles.build(host: np, name: 'nonprofit_admin')
|
||||
# role.save!
|
||||
|
||||
# billing_plan = BillingPlan.find(Settings.default_bp.id)
|
||||
# b_sub = np.build_billing_subscription(billing_plan: billing_plan, status: 'active')
|
||||
# b_sub.save!
|
||||
# rescue ActiveRecord::RecordInvalid => e
|
||||
# class_to_name = { Nonprofit => 'nonprofit', User => 'user' }
|
||||
# if class_to_name[e.record.class]
|
||||
# errors = e.record.errors.keys.map do |k|
|
||||
# errors = e.record.errors[k].uniq
|
||||
# errors.map do |error|
|
||||
# Grape::Exceptions::Validation.new(
|
||||
# params: ["#{class_to_name[e.record.class]}[#{k}]"],
|
||||
# message: error
|
||||
# )
|
||||
# end
|
||||
# end
|
||||
|
||||
# raise Grape::Exceptions::ValidationErrors.new(errors: errors.flatten)
|
||||
# else
|
||||
# raise e
|
||||
# end
|
||||
# end
|
||||
@nonprofit = Nonprofit.new(clean_params.merge({user_id: current_user_id}))
|
||||
@nonprofit.save!
|
||||
render status: :created
|
||||
end
|
||||
|
||||
private
|
||||
def record_invalid_rescue(error)
|
||||
render json:{errors: error.record.errors.messages}, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def change_to_errors(message)
|
||||
message.model.errors.keys.map do |k|
|
||||
errors = e.record.errors[k].uniq
|
||||
errors.map do |error|
|
||||
Grape::Exceptions::Validation.new(
|
||||
params: ["#{class_to_name[e.record.class]}[#{k}]"],
|
||||
message: error
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def flatten_errors(hash_or_array, parent=nil)
|
||||
if hash_or_array.keys
|
||||
result = hash_or_array.keys.map{|i|
|
||||
param = !parent ? i : "#{parent}[#{i}]"
|
||||
|
||||
}
|
||||
else
|
||||
return hash_or_array;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def clean_params
|
||||
params.permit(:name, :zip_code, :state_code, :city, :user)
|
||||
params.permit(:name, :zip_code, :state_code, :city, :phone, :email, :website)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
12
app/helpers/api/nonprofits_helper.rb
Normal file
12
app/helpers/api/nonprofits_helper.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
module Api::NonprofitsHelper
|
||||
def nonprofit_slug_url(nonprofit)
|
||||
nonprofit_location_url city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug
|
||||
end
|
||||
|
||||
def nonprofit_slug_path(nonprofit)
|
||||
nonprofit_location_path city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug
|
||||
end
|
||||
end
|
|
@ -83,10 +83,11 @@ class Nonprofit < ApplicationRecord
|
|||
validates :name, presence: true
|
||||
validates :city, presence: true
|
||||
validates :state_code, presence: true
|
||||
validates :email, format: { with: Email::Regex }, allow_blank: true
|
||||
validates_uniqueness_of :slug, scope: %i[city_slug state_code_slug]
|
||||
validates_format_of :email, with: Email::Regex, allow_nil: true
|
||||
validates_format_of :website, with: URI.regexp(['https', 'http']), allow_nil: true
|
||||
validates_presence_of :slug
|
||||
|
||||
validates_uniqueness_of :slug, scope: %i[city_slug state_code_slug]
|
||||
|
||||
validates_presence_of :user_id, on: :create, unless: -> {register_np_only}
|
||||
validate :user_is_valid, on: :create, unless: -> {register_np_only}
|
||||
validate :user_registerable_as_admin, on: :create, unless: -> {register_np_only}
|
||||
|
@ -165,7 +166,7 @@ class Nonprofit < ApplicationRecord
|
|||
slug = SlugNonprofitNamingAlgorithm.new(self.state_code_slug, self.city_slug).create_copy_name(self.slug)
|
||||
self.slug = slug
|
||||
rescue UnableToCreateNameCopyError
|
||||
errors.add(:slug, "another nonprofit admin")
|
||||
errors.add(:slug, "could not be created.")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -176,10 +177,6 @@ class Nonprofit < ApplicationRecord
|
|||
self
|
||||
end
|
||||
|
||||
def user_is_valid
|
||||
(user && user.is_a?(User)) || errors.add(:user_id, "is not a valid user")
|
||||
end
|
||||
|
||||
def full_address
|
||||
Format::Address.full_address(address, city, state_code)
|
||||
end
|
||||
|
@ -228,11 +225,6 @@ class Nonprofit < ApplicationRecord
|
|||
Settings.intntl.all_currencies.find { |i| i.abbv.casecmp(currency).zero? }&.symbol
|
||||
end
|
||||
|
||||
def user_registerable_as_admin
|
||||
if user && user.roles.nonprofit_admins.any?
|
||||
errors.add(:user_id, "cannot already be an admin for a nonprofit.")
|
||||
end
|
||||
end
|
||||
private
|
||||
def build_admin_role
|
||||
role = user.roles.build(host: self, name: 'nonprofit_admin')
|
||||
|
@ -244,4 +236,15 @@ private
|
|||
b_sub = build_billing_subscription(billing_plan: billing_plan, status: 'active')
|
||||
b_sub.save!
|
||||
end
|
||||
|
||||
def user_registerable_as_admin
|
||||
if user && user.roles.nonprofit_admins.any?
|
||||
errors.add(:user_id, "cannot already be an admin for a nonprofit.")
|
||||
end
|
||||
end
|
||||
|
||||
def user_is_valid
|
||||
(user && user.is_a?(User)) || errors.add(:user_id, "is not a valid user")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
19
app/views/api/nonprofits/create.json.jbuilder
Normal file
19
app/views/api/nonprofits/create.json.jbuilder
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
json.id @nonprofit.id
|
||||
json.name @nonprofit.name
|
||||
json.city @nonprofit.city
|
||||
json.state_code @nonprofit.state_code
|
||||
json.zip_code @nonprofit.zip_code
|
||||
json.state_code_slug @nonprofit.state_code_slug
|
||||
json.city_slug @nonprofit.city_slug
|
||||
json.slug @nonprofit.slug
|
||||
json.email @nonprofit.email
|
||||
json.website @nonprofit.website
|
||||
json.phone @nonprofit.phone
|
||||
|
||||
json.urls do
|
||||
json.plain_url nonprofit_url(@nonprofit)
|
||||
json.slug_url nonprofit_slug_url(@nonprofit)
|
||||
end
|
|
@ -1,204 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'HOUDINI NOnprofit_spec', type: :request do
|
||||
describe 'get' do
|
||||
end
|
||||
|
||||
describe 'post' do
|
||||
around(:each) do |example|
|
||||
@old_bp = Settings.default_bp
|
||||
example.run
|
||||
Settings.default_bp = @old_bp
|
||||
end
|
||||
def expect_validation_errors(actual, input)
|
||||
expected_errors = input.with_indifferent_access[:errors]
|
||||
expect(actual['errors']).to match_array expected_errors
|
||||
end
|
||||
|
||||
def create_errors(*wrapper_params)
|
||||
output = totally_empty_errors
|
||||
wrapper_params.each { |i| output[:errors].push(h(params: [i], messages: gr_e('presence'))) }
|
||||
output
|
||||
end
|
||||
|
||||
def h(h = {})
|
||||
h.with_indifferent_access
|
||||
end
|
||||
|
||||
let(:totally_empty_errors) do
|
||||
{
|
||||
errors:
|
||||
[
|
||||
h(params: ['nonprofit[name]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['nonprofit[zip_code]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['nonprofit[state_code]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['nonprofit[city]'], messages: gr_e('presence', 'blank')),
|
||||
|
||||
h(params: ['user[name]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['user[email]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['user[password]'], messages: gr_e('presence', 'blank')),
|
||||
h(params: ['user[password_confirmation]'], messages: gr_e('presence', 'blank'))
|
||||
]
|
||||
|
||||
}.with_indifferent_access
|
||||
end
|
||||
describe 'authorization' do
|
||||
around(:each) do |e|
|
||||
Rails.configuration.action_controller.allow_forgery_protection = true
|
||||
e.run
|
||||
Rails.configuration.action_controller.allow_forgery_protection = false
|
||||
end
|
||||
|
||||
it 'rejects csrf' do
|
||||
post '/api/nonprofits', params: {}, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
end
|
||||
end
|
||||
|
||||
it 'validates nothing' do
|
||||
input = {}
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
expect_validation_errors(JSON.parse(response.body), create_errors('nonprofit', 'user'))
|
||||
end
|
||||
|
||||
it 'validates url, email, phone ' do
|
||||
input = {
|
||||
nonprofit: {
|
||||
email: 'noemeila',
|
||||
phone: 'notphone',
|
||||
url: ''
|
||||
}
|
||||
}
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
expected = create_errors('user')
|
||||
expected[:errors].push(h(params: ['nonprofit[email]'], messages: gr_e('regexp')))
|
||||
# expected[:errors].push(h(params:["nonprofit[phone]"], messages: gr_e("regexp")))
|
||||
# expected[:errors].push(h(params:["nonprofit[url]"], messages: gr_e("regexp")))
|
||||
|
||||
expect_validation_errors(JSON.parse(response.body), expected)
|
||||
end
|
||||
|
||||
it 'should reject unmatching passwords ' do
|
||||
input = {
|
||||
|
||||
user: {
|
||||
email: 'wmeil@email.com',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
password_confirmation: 'doesn\'t match'
|
||||
}
|
||||
}
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
expect(JSON.parse(response.body)['errors']).to include(h(params: ['user[password]', 'user[password_confirmation]'], messages: gr_e('is_equal_to')))
|
||||
end
|
||||
|
||||
it 'attempts to make a slug copy and returns the proper errors' do
|
||||
force_create(:nm_justice, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton')
|
||||
input = {
|
||||
nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915 },
|
||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||
}
|
||||
|
||||
expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new)
|
||||
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
|
||||
expect_validation_errors(JSON.parse(response.body),
|
||||
errors: [
|
||||
h(
|
||||
params: ['nonprofit[name]'],
|
||||
messages: ['has an invalid slug. Contact support for help.']
|
||||
)
|
||||
])
|
||||
end
|
||||
|
||||
it 'errors on attempt to add user with email that already exists' do
|
||||
force_create(:user, email: 'em@em.com')
|
||||
|
||||
input = {
|
||||
nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915 },
|
||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||
}
|
||||
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
|
||||
expect_validation_errors(JSON.parse(response.body),
|
||||
errors: [
|
||||
h(
|
||||
params: ['user[email]'],
|
||||
messages: ['has already been taken']
|
||||
)
|
||||
])
|
||||
end
|
||||
|
||||
it 'succeeds' do
|
||||
force_create(:nm_justice, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton')
|
||||
input = {
|
||||
nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, url: 'www.cs.c', website: 'www.cs.c' },
|
||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||
}
|
||||
|
||||
bp = force_create(:billing_plan)
|
||||
Settings.default_bp.id = bp.id
|
||||
|
||||
# expect(Houdini::V1::Nonprofit).to receive(:sign_in)
|
||||
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response.code).to eq '201'
|
||||
|
||||
our_np = Nonprofit.all[1]
|
||||
expected_np = {
|
||||
name: 'n',
|
||||
state_code: 'WI',
|
||||
city: 'appleton',
|
||||
zip_code: '54915',
|
||||
state_code_slug: 'wi',
|
||||
city_slug: 'appleton',
|
||||
slug: 'n-00',
|
||||
website: 'http://www.cs.c'
|
||||
}.with_indifferent_access
|
||||
|
||||
expected_np = our_np.attributes.with_indifferent_access.merge(expected_np)
|
||||
expect(our_np.attributes).to eq expected_np
|
||||
|
||||
expect(our_np.billing_subscription.billing_plan).to eq bp
|
||||
|
||||
response_body = {
|
||||
id: our_np.id
|
||||
}.with_indifferent_access
|
||||
|
||||
expect(JSON.parse(response.body)).to eq response_body
|
||||
|
||||
user = User.first
|
||||
expected_user = {
|
||||
email: 'em@em.com',
|
||||
name: 'Name'
|
||||
}
|
||||
|
||||
expected_user = user.attributes.with_indifferent_access.merge(expected_user)
|
||||
expect(our_np.roles.nonprofit_admins.count).to eq 1
|
||||
expect(our_np.roles.nonprofit_admins.first.user.attributes).to eq expected_user
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_error_message(json, field_name)
|
||||
errors = json['errors']
|
||||
|
||||
error = errors.select { |i| i['params'].any? { |j| j == field_name } }.first
|
||||
return error unless error
|
||||
|
||||
error['messages']
|
||||
end
|
||||
|
||||
def gr_e(*keys)
|
||||
keys.map { |i| I18n.translate('grape.errors.messages.' + i, locale: 'en') }
|
||||
end
|
|
@ -1,172 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||
require 'controllers/support/general_shared_user_context'
|
||||
RSpec.shared_context :api_shared_user_verification do
|
||||
include_context :general_shared_user_context
|
||||
let(:user_as_np_admin) do
|
||||
__create_admin(nonprofit)
|
||||
end
|
||||
|
||||
let(:user_as_other_np_admin) do
|
||||
__create_admin(other_nonprofit)
|
||||
end
|
||||
|
||||
let(:user_as_np_associate) do
|
||||
__create_associate(nonprofit)
|
||||
end
|
||||
|
||||
let(:user_as_other_np_associate) do
|
||||
__create_associate(other_nonprofit)
|
||||
end
|
||||
|
||||
let(:unauth_user) do
|
||||
force_create(:user)
|
||||
end
|
||||
|
||||
let(:campaign_editor) do
|
||||
__create(:campaign_editor, campaign)
|
||||
end
|
||||
|
||||
let(:confirmed_user) do
|
||||
force_create(:user, confirmed_at: Time.current)
|
||||
end
|
||||
|
||||
let(:event_editor) do
|
||||
__create(:event_editor, event)
|
||||
end
|
||||
|
||||
let(:super_admin) do
|
||||
__create(:super_admin, other_nonprofit)
|
||||
end
|
||||
|
||||
let(:user_with_profile) do
|
||||
u = force_create(:user)
|
||||
force_create(:profile, user: u)
|
||||
u
|
||||
end
|
||||
|
||||
let(:all_users) do
|
||||
{ user_as_np_admin: user_as_np_admin,
|
||||
user_as_other_np_admin: user_as_other_np_admin,
|
||||
user_as_np_associate: user_as_np_associate,
|
||||
user_as_other_np_associate: user_as_other_np_associate,
|
||||
unauth_user: unauth_user,
|
||||
campaign_editor: campaign_editor,
|
||||
event_editor: event_editor,
|
||||
super_admin: super_admin,
|
||||
user_with_profile: user_with_profile }
|
||||
end
|
||||
|
||||
let(:roles__open_to_all) do
|
||||
[nil, :user_as_np_admin,
|
||||
:user_as_other_np_admin,
|
||||
:user_as_np_associate,
|
||||
:user_as_other_np_associate,
|
||||
:unauth_user,
|
||||
:campaign_editor,
|
||||
:event_editor,
|
||||
:super_admin,
|
||||
:user_with_profile]
|
||||
end
|
||||
|
||||
let(:roles__open_to_np_associate) do
|
||||
%i[user_as_np_admin
|
||||
|
||||
user_as_np_associate
|
||||
|
||||
super_admin]
|
||||
end
|
||||
|
||||
def __create(name, host)
|
||||
u = force_create(:user)
|
||||
force_create(:role, user: u, name: name, host: host)
|
||||
u
|
||||
end
|
||||
|
||||
def __create_admin(host)
|
||||
u = force_create(:user)
|
||||
force_create(:role, user: u, name: :nonprofit_admin, host: host)
|
||||
u
|
||||
end
|
||||
|
||||
def __create_associate(host)
|
||||
u = force_create(:user)
|
||||
force_create(:role, user: u, name: :nonprofit_associate, host: host)
|
||||
u
|
||||
end
|
||||
|
||||
def sign_in(user_to_signin)
|
||||
post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: 'json'
|
||||
end
|
||||
|
||||
def sign_out
|
||||
send(:get, 'users/sign_out')
|
||||
end
|
||||
|
||||
def send(method, *args)
|
||||
case method
|
||||
when :get
|
||||
xhr(:get, *args)
|
||||
when :post
|
||||
xhr(:post, *args)
|
||||
when :delete
|
||||
xhr(:delete, *args)
|
||||
when :put
|
||||
xhr(:put, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def accept(user_to_signin:, method:, action:, args:)
|
||||
new_user = user_to_signin
|
||||
if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct)
|
||||
new_user = user_to_signin.value
|
||||
end
|
||||
sign_in new_user if new_user
|
||||
# allows us to run the helpers but ignore what the controller action does
|
||||
#
|
||||
send(method, action, args)
|
||||
expect(response.status).to eq(200), "expcted success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}"
|
||||
sign_out
|
||||
end
|
||||
|
||||
def reject(user_to_signin:, method:, action:, args:)
|
||||
new_user = user_to_signin
|
||||
if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct)
|
||||
new_user = user_to_signin.value
|
||||
end
|
||||
sign_in new_user if new_user
|
||||
send(method, action, args)
|
||||
expect(response.status).to eq(401), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}"
|
||||
sign_out
|
||||
end
|
||||
|
||||
alias_method :redirects_to, :reject
|
||||
|
||||
def run_authorization_tests(details, &block)
|
||||
@method = details[:method]
|
||||
@successful_users = details[:successful_users]
|
||||
@action = details[:action]
|
||||
@block_to_get_arguments_to_run = block || ->(_) {} # no-op
|
||||
accept_test_for_nil = false
|
||||
all_users.each do |k, v|
|
||||
os = OpenStruct.new
|
||||
os.key = k
|
||||
os.value = v
|
||||
|
||||
if k.nil?
|
||||
accept(user_to_signin: nil, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v))
|
||||
accept_test_for_nil = true
|
||||
end
|
||||
if @successful_users.include? k
|
||||
accept(user_to_signin: os, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v))
|
||||
else
|
||||
reject(user_to_signin: os, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v))
|
||||
end
|
||||
end
|
||||
|
||||
unless accept_test_for_nil
|
||||
reject(user_to_signin: nil, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(nil))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,115 +9,35 @@ describe Api::NonprofitsController, type: :request do
|
|||
role
|
||||
end
|
||||
let(:nonprofit) {create(:nm_justice)}
|
||||
|
||||
describe 'get' do
|
||||
end
|
||||
|
||||
describe 'post' do
|
||||
describe 'create' do
|
||||
around(:each) do |example|
|
||||
@old_bp = Settings.default_bp
|
||||
example.run
|
||||
Settings.default_bp = @old_bp
|
||||
end
|
||||
def expect_validation_errors(actual, input)
|
||||
expected_errors = input.with_indifferent_access[:errors]
|
||||
expect(actual['errors']).to match_array expected_errors
|
||||
end
|
||||
|
||||
def create_errors(*wrapper_params)
|
||||
output = totally_empty_errors
|
||||
wrapper_params.each { |i| output[:errors].push(h(params: [i], messages: gr_e('presence'))) }
|
||||
output
|
||||
end
|
||||
|
||||
def h(h = {})
|
||||
h.with_indifferent_access
|
||||
end
|
||||
|
||||
describe 'authorization' do
|
||||
around(:each) do |e|
|
||||
Rails.configuration.action_controller.allow_forgery_protection = true
|
||||
e.run
|
||||
Rails.configuration.action_controller.allow_forgery_protection = false
|
||||
end
|
||||
|
||||
it 'rejects csrf' do
|
||||
post :create, params: {}, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
end
|
||||
end
|
||||
|
||||
it 'validates nothing' do
|
||||
it 'validates and returns correct errors' do
|
||||
input = {}
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response.parsed_body['errors'].keys).to match_array ['name', 'city', 'state_code', 'slug', 'user']
|
||||
end
|
||||
|
||||
it 'validates url, email, phone ' do
|
||||
input = {
|
||||
nonprofit: {
|
||||
email: 'noemeila',
|
||||
phone: 'notphone',
|
||||
url: ''
|
||||
}
|
||||
}
|
||||
post :create, params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
expected = create_errors('user')
|
||||
expected[:errors].push(h(params: ['nonprofit[email]'], messages: gr_e('regexp')))
|
||||
# expected[:errors].push(h(params:["nonprofit[phone]"], messages: gr_e("regexp")))
|
||||
# expected[:errors].push(h(params:["nonprofit[url]"], messages: gr_e("regexp")))
|
||||
|
||||
expect_validation_errors(JSON.parse(response.body), expected)
|
||||
end
|
||||
|
||||
it 'attempts to make a slug copy and returns the proper errors' do
|
||||
force_create(:nonprofit, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton')
|
||||
input = {
|
||||
nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915 },
|
||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||
}
|
||||
|
||||
expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new)
|
||||
|
||||
post :create, params: input, xhr: true
|
||||
expect(response.code).to eq '400'
|
||||
|
||||
expect_validation_errors(JSON.parse(response.body),
|
||||
errors: [
|
||||
h(
|
||||
params: ['nonprofit[name]'],
|
||||
messages: ['has an invalid slug. Contact support for help.']
|
||||
)
|
||||
])
|
||||
end
|
||||
|
||||
it 'errors on attempt to add the user to a second nonprofit' do
|
||||
nonprofit_admin_role
|
||||
input = { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, user_id: user.id }
|
||||
post '/api/nonprofits', params: input, xhr:true
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response.parsed_body['errors'].keys).to match_array 'user'
|
||||
byebug
|
||||
expect(response.parsed_body['errors']['user'].first).to has_include? 'nonprofit admin'
|
||||
expect(response.parsed_body['errors'].keys).to match_array ['name', 'city', 'state_code', 'slug', 'user_id']
|
||||
end
|
||||
|
||||
it 'succeeds' do
|
||||
force_create(:nonprofit, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton')
|
||||
input = {
|
||||
nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, url: 'www.cs.c', website: 'www.cs.c' },
|
||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||
}
|
||||
|
||||
input = { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, user_id: user.id, phone: '920-555-5555' }
|
||||
sign_in user
|
||||
bp = force_create(:billing_plan)
|
||||
Settings.default_bp.id = bp.id
|
||||
|
||||
# expect(Houdini::V1::Nonprofit).to receive(:sign_in)
|
||||
sign_in user
|
||||
|
||||
post :create, params: input, xhr: true
|
||||
expect(response.code).to eq '201'
|
||||
post '/api/nonprofits', params: input, xhr: true
|
||||
expect(response).to have_http_status :created
|
||||
|
||||
our_np = Nonprofit.all[1]
|
||||
expected_np = {
|
||||
name: 'n',
|
||||
state_code: 'WI',
|
||||
|
@ -125,45 +45,17 @@ describe Api::NonprofitsController, type: :request do
|
|||
zip_code: '54915',
|
||||
state_code_slug: 'wi',
|
||||
city_slug: 'appleton',
|
||||
slug: 'n-00',
|
||||
website: 'http://www.cs.c'
|
||||
slug: 'n',
|
||||
phone: '920-555-5555',
|
||||
email: nil,
|
||||
website: nil,
|
||||
urls: {plain_url: "http://www.example.com/nonprofits/1", slug_url: "http://www.example.com/wi/appleton/n"}
|
||||
}.with_indifferent_access
|
||||
|
||||
expected_np = our_np.attributes.with_indifferent_access.merge(expected_np)
|
||||
expect(our_np.attributes).to eq expected_np
|
||||
|
||||
expect(our_np.billing_subscription.billing_plan).to eq bp
|
||||
|
||||
response_body = {
|
||||
id: our_np.id
|
||||
}.with_indifferent_access
|
||||
|
||||
expect(JSON.parse(response.body)).to eq response_body
|
||||
|
||||
user = User.first
|
||||
expected_user = {
|
||||
email: 'em@em.com',
|
||||
name: 'Name'
|
||||
}
|
||||
|
||||
expected_user = user.attributes.with_indifferent_access.merge(expected_user)
|
||||
expect(our_np.roles.nonprofit_admins.count).to eq 1
|
||||
expect(our_np.roles.nonprofit_admins.first.user.attributes).to eq expected_user
|
||||
|
||||
expect(response.parsed_body['id']).to be > 0
|
||||
expect(response.parsed_body.except('id')).to eq expected_np
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_error_message(json, field_name)
|
||||
errors = json['errors']
|
||||
|
||||
error = errors.select { |i| i['params'].any? { |j| j == field_name } }.first
|
||||
return error unless error
|
||||
|
||||
error['messages']
|
||||
end
|
||||
|
||||
def gr_e(*keys)
|
||||
keys.map { |i| I18n.translate('grape.errors.messages.' + i, locale: 'en') }
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ RSpec.describe Nonprofit, type: :model do
|
|||
let(:nonprofit_with_same_name) { Nonprofit.new({name: "New Mexico Equality", state_code: nm_justice.state_code, city: nm_justice.city, user_id: user.id})}
|
||||
let(:nonprofit_with_same_name_but_different_state) { Nonprofit.new({name: "New Mexico Equality", state_code: 'mn', city: nm_justice.city, user_id: user.id })}
|
||||
|
||||
let(:nonprofit_with_bad_email_and_website) { Nonprofit.new({email: 'not_email', website: 'not_website'})}
|
||||
|
||||
let(:user) { create(:user)}
|
||||
let(:nonprofit_admin_role) do
|
||||
role = user.roles.build(host: nonprofit, name: 'nonprofit_admin')
|
||||
|
@ -61,7 +63,15 @@ RSpec.describe Nonprofit, type: :model do
|
|||
end
|
||||
let(:nm_justice) {create(:nm_justice)}
|
||||
|
||||
before(:each) { nonprofit.valid?; nonprofit_with_invalid_user.valid?; nonprofit_with_user_who_already_admin.valid?; nonprofit_with_same_name.valid?; nonprofit_with_same_name_but_different_state.valid?}
|
||||
before(:each) do
|
||||
nonprofit.valid?
|
||||
nonprofit_with_invalid_user.valid?
|
||||
nonprofit_with_user_who_already_admin.valid?
|
||||
nonprofit_with_same_name.valid?
|
||||
nonprofit_with_same_name_but_different_state.valid?
|
||||
nonprofit_with_bad_email_and_website.valid?
|
||||
end
|
||||
|
||||
it 'has an error for no name' do
|
||||
expect(nonprofit.errors['name'].first).to match /.*blank.*/
|
||||
end
|
||||
|
@ -91,10 +101,25 @@ RSpec.describe Nonprofit, type: :model do
|
|||
expect(nonprofit_with_same_name.slug).to eq "#{nm_justice.slug}-00"
|
||||
end
|
||||
|
||||
it 'does nothing to a slug when it tries to save' do
|
||||
it 'does nothing to a slug when a slug was provided' do
|
||||
expect(nonprofit_with_same_name_but_different_state.errors['slug']).to be_empty
|
||||
expect(nonprofit_with_same_name_but_different_state.slug).to eq "#{nm_justice.slug}"
|
||||
end
|
||||
|
||||
it 'marks email as having errors if they do' do
|
||||
expect(nonprofit_with_bad_email_and_website.errors['email'].first).to match /.*invalid.*/
|
||||
end
|
||||
|
||||
it 'marks website as having errors if they do' do
|
||||
expect(nonprofit_with_bad_email_and_website.errors['website'].first).to match /.*invalid.*/
|
||||
end
|
||||
|
||||
it 'marks an nonprofit as invalid when no slug could be created ' do
|
||||
nonprofit = Nonprofit.new({name: nm_justice.name, city: nm_justice.city, state_code: nm_justice.state_code, slug: nm_justice.slug})
|
||||
expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new)
|
||||
nonprofit.valid?
|
||||
expect(nonprofit.errors['slug'].first).to match /.*could not be created.*/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -70,5 +70,6 @@ RSpec.configure do |config|
|
|||
# arbitrary gems may also be filtered via:
|
||||
# config.filter_gems_from_backtrace("gem name")
|
||||
config.include Devise::Test::ControllerHelpers, type: :controller
|
||||
config.include Devise::Test::IntegrationHelpers, type: :request
|
||||
config.include RSpec::Rails::RequestExampleGroup, type: :request, file_path: %r{spec/api}
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue