This repository has been archived by the owner on Jul 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor EquipmentModels controller spec
Resolves #1587 - Adds Mocker classes - Adds shared controller examples for successful and failed requests
- Loading branch information
Sydney Young
committed
Aug 8, 2016
1 parent
e8ffd13
commit 419cfa2
Showing
9 changed files
with
448 additions
and
359 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,21 @@ | ||
# some basic helpers to simulate devise controller methods in specs | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/user_mock.rb') | ||
|
||
module ControllerHelpers | ||
def current_user | ||
user_session_info = | ||
response.request.env['rack.session']['warden.user.user.key'] | ||
return unless user_session_info | ||
user_id = user_session_info[0][0] | ||
User.find(user_id) | ||
def mock_user_sign_in(user = UserMock.new(traits: [:findable])) | ||
pass_app_setup_check | ||
allow(request.env['warden']).to receive(:authenticate!).and_return(user) | ||
# necessary for permissions to work | ||
allow(ApplicationController).to receive(:current_user).and_return(user) | ||
allow(Ability).to receive(:new).and_return(Ability.new(user)) | ||
allow_any_instance_of(described_class).to \ | ||
receive(:current_user).and_return(user) | ||
end | ||
|
||
def user_signed_in? | ||
!current_user.nil? | ||
private | ||
|
||
def pass_app_setup_check | ||
allow(AppConfig).to receive(:first).and_return(true) unless AppConfig.first | ||
allow(User).to receive(:count).and_return(1) unless User.first | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/mocker.rb') | ||
require Rails.root.join('spec/support/mockers/equipment_model_mock.rb') | ||
|
||
class CategoryMock < Mocker | ||
def self.klass | ||
Category | ||
end | ||
|
||
def self.klass_name | ||
'Category' | ||
end | ||
|
||
private | ||
|
||
def with_equipment_models(models: nil, count: 1) | ||
models ||= Array.new(count) { EquipmentModelMock.new } | ||
parent_has_many(mocked_children: models, parent_sym: :category, | ||
child_sym: :equipment_models) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/mocker.rb') | ||
require Rails.root.join('spec/support/mockers/equipment_model_mock.rb') | ||
|
||
class EquipmentItemMock < Mocker | ||
def self.klass | ||
EquipmentItem | ||
end | ||
|
||
def self.klass_name | ||
'EquipmentItem' | ||
end | ||
|
||
private | ||
|
||
def with_model(model: nil) | ||
model ||= EquipmentModelMock.new | ||
child_of_has_many(mocked_parent: model, parent_sym: :equipment_model, | ||
child_sym: :equipment_items) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/mocker.rb') | ||
require Rails.root.join('spec/support/mockers/category_mock.rb') | ||
require Rails.root.join('spec/support/mockers/equipment_item_mock.rb') | ||
|
||
class EquipmentModelMock < Mocker | ||
def self.klass | ||
EquipmentModel | ||
end | ||
|
||
def self.klass_name | ||
'EquipmentModel' | ||
end | ||
|
||
private | ||
|
||
def with_item(item:) | ||
with_items(items: [item]) | ||
end | ||
|
||
def with_items(items: nil, count: 1) | ||
items ||= Array.new(count) { EquipmentItemMock.new } | ||
parent_has_many(mocked_children: items, parent_sym: :equipment_model, | ||
child_sym: :equipment_items) | ||
end | ||
|
||
def with_category(cat: nil) | ||
cat ||= CategoryMock.new | ||
child_of_has_many(mocked_parent: cat, parent_sym: :category, | ||
child_sym: :equipment_models) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# frozen_string_literal: true | ||
require 'rspec/mocks/standalone' | ||
|
||
# This class behaves as an extension of rspec-mocks' instance_spy. | ||
# It is intended to be extended and used to make mocking models much simpler! | ||
# | ||
# To create a new subclass, the following methods must be overridden: | ||
# - self.klass must return the class that the subclass is mocking | ||
# - self.klass_name must return a string that matches the class being mocked | ||
# | ||
# Some examples using the EquipmentModelMock subclass: | ||
# A mock that can be "found" with EquipmentModel#find: | ||
# EquipmentModelMock.new(traits: [:findable]) | ||
# A mock with a set of attributes: | ||
# EquipmentModelMock.new(name: 'Camera', late_fee: 3) | ||
# A mock with attributes and method stubs: | ||
# EquipmentModelMock.new(name: 'Camera', model_restriced: false) | ||
# A findable mock with attributes: | ||
# EquipmentModelMock.new(traits: [:findable], name: 'Camera') | ||
# | ||
# A trait can be any method that exists on the mocker superclass or child class. | ||
# To create an EquipmentModel that belongs to an existing category, camera: | ||
# EquipmentModelMock.new(traits: [[:with_category, cat: camera]]) | ||
# | ||
# Use caution before adding methods -- any method defined here should be usable | ||
# by all subclasses, with the exception of the association stub methods. | ||
|
||
class Mocker < RSpec::Mocks::InstanceVerifyingDouble | ||
include RSpec::Mocks | ||
|
||
FIND_METHODS = [:find, :find_by_id].freeze | ||
|
||
def initialize(traits: [], **attrs) | ||
# from RSpec::Mocks::ExampleMethods | ||
# combination of #declare_verifying_double and #declare_double | ||
ref = ObjectReference.for(self.class.klass_name) | ||
RSpec::Mocks.configuration.verifying_double_callbacks.each do |block| | ||
block.call(ref) | ||
end | ||
attrs ||= {} | ||
super(ref, attrs) | ||
as_null_object | ||
process_traits(traits) | ||
end | ||
|
||
def process_traits(traits) | ||
traits.each { |t| send(*t) } | ||
end | ||
|
||
private | ||
|
||
def klass | ||
Object | ||
end | ||
|
||
def klass_name | ||
'Object' | ||
end | ||
|
||
def spy | ||
self | ||
end | ||
|
||
# lets us use rspec-mock syntax in mockers | ||
def receive(method_name, &block) | ||
Matchers::Receive.new(method_name, block) | ||
end | ||
|
||
def allow(target) | ||
AllowanceTarget.new(target) | ||
end | ||
|
||
# Traits | ||
def findable | ||
id = FactoryGirl.generate(:unique_id) | ||
allow(spy).to receive(:id).and_return(id) | ||
FIND_METHODS.each do |method| | ||
allow(self.class.klass).to receive(method) | ||
allow(self.class.klass).to receive(method).with(id).and_return(spy) | ||
allow(self.class.klass).to receive(method).with(id.to_s).and_return(spy) | ||
end | ||
end | ||
|
||
# Generalized association stubs | ||
def child_of_has_many(mocked_parent:, parent_sym:, child_sym:) | ||
allow(spy).to receive(parent_sym).and_return(mocked_parent) | ||
children = if mocked_parent.send(child_sym).is_a? Array | ||
mocked_parent.send(child_sym) << spy | ||
else | ||
[spy] | ||
end | ||
allow(mocked_parent).to receive(child_sym).and_return(children) | ||
end | ||
|
||
def parent_has_many(mocked_children:, parent_sym:, child_sym:) | ||
if mocked_children.is_a? Array | ||
mocked_children.each do |child| | ||
allow(child).to receive(parent_sym).and_return(spy) | ||
end | ||
end | ||
allow(spy).to receive(child_sym).and_return(mocked_children) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/mocker.rb') | ||
|
||
class ReservationMock < Mocker | ||
def self.klass | ||
Reservation | ||
end | ||
|
||
def self.klass_name | ||
'Reservation' | ||
end | ||
|
||
private | ||
|
||
def for_user(user:) | ||
child_of_has_many(mocked_parent: user, parent_sym: :reserver, | ||
child_sym: :reservations) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
require Rails.root.join('spec/support/mockers/mocker.rb') | ||
|
||
class UserMock < Mocker | ||
def initialize(role = :user, traits: [], **attrs) | ||
attrs = FactoryGirl.attributes_for(role).merge attrs | ||
traits = [:findable] if traits.empty? | ||
super(traits: traits, **attrs) | ||
end | ||
|
||
def self.klass | ||
User | ||
end | ||
|
||
def self.klass_name | ||
'User' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
require 'spec_helper' | ||
|
||
shared_examples_for 'successful request' do |template| | ||
it { is_expected.to respond_with(:success) } | ||
it { is_expected.to render_template(template) } | ||
it { is_expected.not_to set_flash } | ||
end | ||
|
||
shared_examples_for 'redirected request' do | ||
it { expect(response).to be_redirect } | ||
it { is_expected.to set_flash } | ||
end |