require 'spec_helper'
describe Bourgeois::Presenter do
let(:user) { User.new first_name: 'Patrick', last_name: 'Bourgeois', birthdate: '1962-06-16' }
let(:presenter) { UserPresenter.new(user) }
describe :DelegatedMethods do
before do
class UserPresenter < Bourgeois::Presenter
def formatted_name
"#{first_name} #{last_name}".strip
end
def birthdate
super.presence || 'Unknown'
end
end
class User < OpenStruct
end
end
it { expect(presenter.formatted_name).to eql 'Patrick Bourgeois' }
it { expect(presenter.first_name).to eql 'Patrick' }
it { expect(presenter.last_name).to eql 'Bourgeois' }
it { expect(presenter.birthdate).to eql '1962-06-16' }
end
describe :InstanceMethods do
describe :initialize do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
end
it { expect { UserPresenter.new(user) }.to_not raise_error }
end
describe :view do
let(:view) { ActionView::Base.new }
let(:presenter) { UserPresenter.new(user, view) }
context 'with present view' do
before do
class UserPresenter < Bourgeois::Presenter
def local_name
view.t('users.attributes.local_name')
end
def first_name_in_bold
view.content_tag :strong, first_name
end
end
class ActionView::Base
def t(*args)
"Fancy translated string from #{args.join(', ')}"
end
end
class User < OpenStruct; end
end
it { expect(presenter.local_name).to eql 'Fancy translated string from users.attributes.local_name' }
it { expect(presenter.first_name_in_bold).to eql 'Patrick' }
end
context 'with blank view' do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
end
let(:presenter) { UserPresenter.new(user) }
it { expect(presenter.instance_variable_get(:@view)).to be_nil }
end
end
describe :object do
before do
class UserPresenter < Bourgeois::Presenter
def birthdate
object.birthdate.gsub(/-/, '/')
end
end
class User < OpenStruct; end
end
it { expect(presenter.birthdate).to eql '1962/06/16' }
end
describe :inspect do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
end
let(:user) { User.new foo: 'bar' }
it { expect(presenter.inspect).to eql '#>' }
end
end
describe :ClassMethods do
describe :helper do
before do
class UserPresenter < Bourgeois::Presenter
# We need a method to test that our block is executed
attr_reader :foo
end
end
let(:call_it!) do
presenter.send(helper) do
presenter.foo
end
end
context 'with helper using only a if condition' do
before do
class UserPresenter
helper :with_profile, if: -> { profile.present? }
end
end
context 'with matching if condition' do
let(:user) { User.new profile: 'Je suis Patrick.' }
let(:helper) { :with_profile }
specify do
presenter.should_receive(:foo).once
call_it!
end
end
context 'with non-matching if condition' do
let(:user) { User.new profile: nil }
let(:helper) { :with_profile }
specify do
presenter.should_receive(:foo).never
call_it!
end
end
end
context 'with helper using only an unless condition' do
let(:helper) { :without_name }
before do
class UserPresenter
helper :without_name, unless: -> { full_name.present? }
end
end
context 'with matching unless condition' do
let(:user) { User.new full_name: nil }
specify do
presenter.should_receive(:foo).once
call_it!
end
end
context 'with non-matching unless condition' do
let(:user) { User.new full_name: 'Patrick Bourgeois' }
specify do
presenter.should_receive(:foo).never
call_it!
end
end
end
context 'with helper without if nor unless' do
let(:user) { User.new }
let(:helper) { :with_something }
before do
class UserPresenter
helper :with_something
end
end
specify do
presenter.should_receive(:foo).once
call_it!
end
end
context 'with helper using both matching and unless conditions' do
let(:helper) { :sometimes }
before do
class UserPresenter
helper :sometimes, if: -> { profile.present? }, unless: -> { full_name.present? }
end
end
context 'with matching if and non-matching unless condition' do
let(:user) { User.new(profile: true, full_name: 'Patrick Bourgeois') }
specify do
presenter.should_receive(:foo).never
call_it!
end
end
context 'with non-matching if and non-matching unless condition' do
let(:user) { User.new(profile: false, full_name: 'Patrick Bourgeois') }
specify do
presenter.should_receive(:foo).never
call_it!
end
end
context 'with matching if and matching unless condition' do
let(:user) { User.new(profile: true, full_name: nil) }
specify do
presenter.should_receive(:foo).once
call_it!
end
end
context 'with non-matching if and matching unless condition' do
let(:user) { User.new(profile: false, full_name: 'Patrick Bourgeois') }
specify do
presenter.should_receive(:foo).never
call_it!
end
end
end
end
describe :kind_of? do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
end
it { expect(presenter).to be_kind_of(User) }
end
describe :model_name do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
User.should_receive(:model_name).and_return(:foo)
end
it { expect(UserPresenter.model_name).to eql :foo }
end
describe :human_attribute_name do
before do
class UserPresenter < Bourgeois::Presenter; end
class User < OpenStruct; end
User.should_receive(:human_attribute_name).and_return(:foo)
end
it { expect(UserPresenter.human_attribute_name).to eql :foo }
end
describe :present do
before do
class UserPresenter < Bourgeois::Presenter
def formatted_name
"#{first_name} #{last_name}".strip
end
end
class User < OpenStruct; end
end
context 'on a Nil object' do
context 'without a block' do
it { expect { Bourgeois::Presenter.present(nil) }.not_to raise_error }
end
context 'with a block' do
before { UserPresenter.any_instance.should_receive(:formatted_name).never }
specify do
expect do
Bourgeois::Presenter.present(nil) { |obj| obj.formatted_name }
end.not_to raise_error
end
end
end
context 'on a single resource' do
let(:user) { User.new first_name: 'Patrick', last_name: 'Bourgeois' }
context 'without a block' do
it { expect(Bourgeois::Presenter.present(user).formatted_name).to eql 'Patrick Bourgeois' }
end
context 'with a block' do
specify do
Bourgeois::Presenter.present(user) do |u|
expect(u.formatted_name).to eql 'Patrick Bourgeois'
end
end
end
end
context 'on a single already-presented resource' do
let(:user) { User.new first_name: 'Patrick', last_name: 'Bourgeois' }
let(:presenter) { UserPresenter.new(user) }
context 'without a block' do
it { expect(Bourgeois::Presenter.present(presenter).formatted_name).to eql 'Patrick Bourgeois' }
end
context 'with a block' do
specify do
Bourgeois::Presenter.present(presenter) do |u|
expect(u.formatted_name).to eql 'Patrick Bourgeois'
end
end
end
end
context 'on a collection of resources' do
let(:user1) { User.new first_name: 'Patrick', last_name: 'Bourgeois' }
let(:user2) { User.new first_name: 'Francois', last_name: 'Jean' }
let(:user3) { User.new first_name: 'Alain', last_name: 'Lapointe' }
let(:users) { [user1, user2, user3] }
specify do
output = []
Bourgeois::Presenter.present(users) { |u| output << u.formatted_name }
expect(output).to eql ['Patrick Bourgeois', 'Francois Jean', 'Alain Lapointe']
end
end
context 'on a collection of already-presented resources' do
let(:user1) { User.new first_name: 'Patrick', last_name: 'Bourgeois' }
let(:user2) { User.new first_name: 'Francois', last_name: 'Jean' }
let(:user3) { User.new first_name: 'Alain', last_name: 'Lapointe' }
let(:users) { [UserPresenter.new(user1), UserPresenter.new(user2), UserPresenter.new(user3)] }
specify do
output = []
Bourgeois::Presenter.present(users) { |u| output << u.formatted_name }
expect(output).to eql ['Patrick Bourgeois', 'Francois Jean', 'Alain Lapointe']
end
end
context 'on a resource without a defined presenter class' do
before do
class Project < OpenStruct; end
end
let(:project) { Project.new name: 'Les B.B.' }
it { expect { Bourgeois::Presenter.present(project) }.to raise_error(Bourgeois::UnknownPresenter, 'unknown presenter class ProjectPresenter') }
end
context 'on a resource with a custom presenter class' do
before do
class Article < OpenStruct; end
class CustomArticlePresenter < Bourgeois::Presenter
def name
super.upcase
end
end
end
let(:article) { Article.new name: 'Les B.B.' }
let(:presented_article) { Bourgeois::Presenter.present(article, CustomArticlePresenter) }
it { expect { presented_article }.not_to raise_error }
it { expect(presented_article.name).to eql 'LES B.B.' }
end
context 'on a Struct-based resource' do
before do
class Band < Struct.new(:name)
end
class BandPresenter < Bourgeois::Presenter
def name
super.upcase
end
end
end
let(:band) { Band.new('Les B.B.') }
let(:presented_band) { Bourgeois::Presenter.present(band) }
it { expect(presented_band.name).to eql 'LES B.B.' }
end
context 'on a collection of resources with a custom presenter class' do
before do
class Article < OpenStruct; end
class CustomArticlePresenter < Bourgeois::Presenter
def name
super.upcase
end
end
end
let(:articles) { [Article.new(name: 'Les B.B.'), Article.new(name: 'Rock et Belles Oreilles')] }
specify do
output = []
Bourgeois::Presenter.present(articles, CustomArticlePresenter) { |u| output << u.name }
expect(output).to eql ['LES B.B.', 'ROCK ET BELLES OREILLES']
end
end
end
end
end