diff --git a/lib/generators/rspec/templates/decorator_spec.rb b/lib/generators/rspec/templates/decorator_spec.rb index 0e0a4ee..98b907e 100644 --- a/lib/generators/rspec/templates/decorator_spec.rb +++ b/lib/generators/rspec/templates/decorator_spec.rb @@ -5,5 +5,4 @@ <% end %> RSpec.describe <%= class_name %>Decorator, type: :decorator do - end diff --git a/spec/decorators/active_model_serializers_spec.rb b/spec/decorators/active_model_serializers_spec.rb new file mode 100644 index 0000000..e4d00a8 --- /dev/null +++ b/spec/decorators/active_model_serializers_spec.rb @@ -0,0 +1,16 @@ +require_relative '../rails_helper' + +RSpec.describe Draper::CollectionDecorator do + describe "#active_model_serializer" do + it "returns ActiveModel::ArraySerializer" do + collection_decorator = Draper::CollectionDecorator.new([]) + if defined?(ActiveModel::ArraySerializerSupport) + collection_serializer = collection_decorator.active_model_serializer + else + collection_serializer = ActiveModel::Serializer.serializer_for(collection_decorator) + end + + expect(collection_serializer).to be ActiveModel::ArraySerializer + end + end +end diff --git a/spec/decorators/devise_spec.rb b/spec/decorators/devise_spec.rb new file mode 100644 index 0000000..540a04d --- /dev/null +++ b/spec/decorators/devise_spec.rb @@ -0,0 +1,64 @@ +require_relative '../rails_helper' + +if defined?(Devise) + RSpec.describe "A decorator spec" do + it "can sign in a real user" do + user = User.new + sign_in user + + expect(helper.current_user).to be user + end + + it "can sign in a mock user" do + user = double("User") + sign_in :user, user + + expect(helper.current_user).to be user + end + + it "can sign in a real admin" do + admin = Admin.new + sign_in admin + + expect(helper.current_admin).to be admin + end + + it "can sign in a mock admin" do + admin = double("Admin") + sign_in :admin, admin + + expect(helper.current_admin).to be admin + end + + it "can sign out a real user" do + user = User.new + sign_in user + sign_out user + + expect(helper.current_user).to be_nil + end + + it "can sign out a mock user" do + user = double("User") + sign_in :user, user + sign_out :user + + expect(helper.current_user).to be_nil + end + + it "can sign out without a user" do + sign_out :user + + expect(helper.current_user).to be_nil + end + + it "is backwards-compatible" do + user = double("User") + ActiveSupport::Deprecation.silence do + sign_in user + end + + expect(helper.current_user).to be user + end + end +end diff --git a/spec/decorators/helpers_spec.rb b/spec/decorators/helpers_spec.rb new file mode 100644 index 0000000..8d32a54 --- /dev/null +++ b/spec/decorators/helpers_spec.rb @@ -0,0 +1,21 @@ +require_relative '../rails_helper' + +RSpec.describe "A decorator spec" do + it "can access helpers through `helper`" do + expect(helper.content_tag(:p, "Help!")).to eq "

Help!

" + end + + it "can access helpers through `helpers`" do + expect(helpers.content_tag(:p, "Help!")).to eq "

Help!

" + end + + it "can access helpers through `h`" do + expect(h.content_tag(:p, "Help!")).to eq "

Help!

" + end + + it "gets the same helper object as a decorator" do + decorator = Draper::Decorator.new(Object.new) + + expect(helpers).to be decorator.helpers + end +end diff --git a/spec/decorators/post_decorator_spec.rb b/spec/decorators/post_decorator_spec.rb new file mode 100755 index 0000000..a763599 --- /dev/null +++ b/spec/decorators/post_decorator_spec.rb @@ -0,0 +1,66 @@ +require_relative '../rails_helper' + +RSpec.describe PostDecorator do + let(:decorator) { PostDecorator.new(object) } + let(:object) { Post.create } + + it "can use built-in helpers" do + expect(decorator.truncated).to eq "Once upon a..." + end + + it "can use built-in private helpers" do + expect(decorator.html_escaped).to eq "<script>danger</script>" + end + + it "can use user-defined helpers from app/helpers" do + expect(decorator.hello_world).to eq "Hello, world!" + end + + it "can be passed to path helpers" do + expect(helpers.post_path(decorator)).to eq "/en/posts/#{object.id}" + end + + it "can use path helpers with its model" do + expect(decorator.path_with_model).to eq "/en/posts/#{object.id}" + end + + it "can use path helpers with its id" do + expect(decorator.path_with_id).to eq "/en/posts/#{object.id}" + end + + it "can be passed to url helpers" do + expect(helpers.post_url(decorator)).to eq "http://www.example.com:12345/en/posts/#{object.id}" + end + + it "can use url helpers with its model" do + expect(decorator.url_with_model).to eq "http://www.example.com:12345/en/posts/#{object.id}" + end + + it "can use url helpers with its id" do + expect(decorator.url_with_id).to eq "http://www.example.com:12345/en/posts/#{object.id}" + end + + it "can be passed implicitly to url_for" do + expect(decorator.link).to eq "#{object.id}" + end + + it "serializes overriden attributes" do + expect(decorator.serializable_hash["updated_at"]).to be :overridden + end + + it "serializes to JSON" do + json = decorator.to_json + expect(json).to match /"updated_at":"overridden"/ + end + + it "serializes to XML" do + pending("Rails < 3.2 does not use `serializable_hash` in `to_xml`") if Rails.version.to_f < 3.2 + + xml = Capybara.string(decorator.to_xml) + expect(xml).to have_css "post > updated-at", text: "overridden" + end + + it "uses a test view context from ApplicationController" do + expect(Draper::ViewContext.current.controller).to be_an ApplicationController + end +end diff --git a/spec/decorators/spec_type_spec.rb b/spec/decorators/spec_type_spec.rb new file mode 100644 index 0000000..d0ac746 --- /dev/null +++ b/spec/decorators/spec_type_spec.rb @@ -0,0 +1,7 @@ +require_relative '../rails_helper' + +RSpec.describe "A spec in this folder" do + it "is a decorator spec" do + expect(RSpec.current_example.metadata[:type]).to be :decorator + end +end diff --git a/spec/decorators/view_context_spec.rb b/spec/decorators/view_context_spec.rb new file mode 100644 index 0000000..13498cf --- /dev/null +++ b/spec/decorators/view_context_spec.rb @@ -0,0 +1,22 @@ +require_relative '../rails_helper' + +def it_does_not_leak_view_context + 2.times do + it "has an independent view context" do + expect(Draper::ViewContext.current).not_to be :leaked + Draper::ViewContext.current = :leaked + end + end +end + +RSpec.describe "A decorator spec", type: :decorator do + it_does_not_leak_view_context +end + +RSpec.describe "A controller spec", type: :controller do + it_does_not_leak_view_context +end + +RSpec.describe "A mailer spec", type: :mailer do + it_does_not_leak_view_context +end diff --git a/spec/draper/decoratable_spec.rb b/spec/draper/decoratable_spec.rb index 899e6b8..63f9992 100644 --- a/spec/draper/decoratable_spec.rb +++ b/spec/draper/decoratable_spec.rb @@ -132,7 +132,6 @@ module Draper it "calls #decorate_collection on .decorator_class" do scoped = [Product.new] allow(Product).to receive(scoping_method).and_return(scoped) - expect(Product.decorator_class).to receive(:decorate_collection).with(scoped, with: nil).and_return(:decorated_collection) expect(Product.decorate).to be :decorated_collection end diff --git a/spec/draper/decorator_spec.rb b/spec/draper/decorator_spec.rb index da4a582..42cc5a9 100755 --- a/spec/draper/decorator_spec.rb +++ b/spec/draper/decorator_spec.rb @@ -228,13 +228,11 @@ module Draper it "returns false when .object_class is not inferrable" do allow(Decorator).to receive(:object_class).and_raise(UninferrableSourceError.new(Decorator)) - expect(Decorator.object_class?).to be_falsey end it "is aliased to .source_class?" do allow(Decorator).to receive(:object_class).and_return(Model) - expect(Decorator.source_class?).to be_truthy end end @@ -488,7 +486,6 @@ module Draper describe ".model_name" do it "delegates to the source class" do allow(Decorator).to receive(:object_class) { double(model_name: :delegated) } - expect(Decorator.model_name).to be :delegated end end diff --git a/spec/draper/factory_spec.rb b/spec/draper/factory_spec.rb index a249568..6831a54 100644 --- a/spec/draper/factory_spec.rb +++ b/spec/draper/factory_spec.rb @@ -246,6 +246,5 @@ module Draper end end end - end end diff --git a/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers new file mode 120000 index 0000000..b870225 --- /dev/null +++ b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers @@ -0,0 +1 @@ +../ \ No newline at end of file diff --git a/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_0 b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_0 new file mode 120000 index 0000000..b870225 --- /dev/null +++ b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_0 @@ -0,0 +1 @@ +../ \ No newline at end of file diff --git a/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_1 b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_1 new file mode 120000 index 0000000..b870225 --- /dev/null +++ b/spec/dummy/spec~ed5c3c6... Refactored spec setup and helpers_1 @@ -0,0 +1 @@ +../ \ No newline at end of file diff --git a/spec/mailers/post_mailer_spec.rb b/spec/mailers/post_mailer_spec.rb new file mode 100644 index 0000000..1838fef --- /dev/null +++ b/spec/mailers/post_mailer_spec.rb @@ -0,0 +1,33 @@ +require_relative '../rails_helper' + +RSpec.describe PostMailer do + describe "#decorated_email" do + let(:email_body) { Capybara.string(email.body.to_s) } + let(:email) { PostMailer.decorated_email(post).deliver } + let(:post) { Post.create } + + it "decorates" do + expect(email_body).to have_content "Today" + end + + it "can use path helpers with a model" do + expect(email_body).to have_css "#path_with_model", text: "/en/posts/#{post.id}" + end + + it "can use path helpers with an id" do + expect(email_body).to have_css "#path_with_id", text: "/en/posts/#{post.id}" + end + + it "can use url helpers with a model" do + expect(email_body).to have_css "#url_with_model", text: "http://www.example.com:12345/en/posts/#{post.id}" + end + + it "can use url helpers with an id" do + expect(email_body).to have_css "#url_with_id", text: "http://www.example.com:12345/en/posts/#{post.id}" + end + + it "uses the correct view context controller" do + expect(email_body).to have_css "#controller", text: "PostMailer" + end + end +end diff --git a/spec/models/mongoid_post_spec.rb b/spec/models/mongoid_post_spec.rb new file mode 100644 index 0000000..ea13958 --- /dev/null +++ b/spec/models/mongoid_post_spec.rb @@ -0,0 +1,8 @@ +require_relative '../spec_helper' +require_relative '../shared_examples/decoratable' + +if defined?(Mongoid) + RSpec.describe MongoidPost do + it_behaves_like "a decoratable model" + end +end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb new file mode 100644 index 0000000..4c453fe --- /dev/null +++ b/spec/models/post_spec.rb @@ -0,0 +1,6 @@ +require_relative '../spec_helper' +require_relative '../shared_examples/decoratable' + +RSpec.describe Post do + it_behaves_like "a decoratable model" +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000..34e083f --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,32 @@ +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +# Prevent database truncation if the environment is production +abort('Rails is running in production mode!') if Rails.env.production? +require 'spec_helper' +require 'rspec/rails' +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } + +# Checks for pending migrations before tests are run. +# If you are not using ActiveRecord, you can remove this line. +ActiveRecord::Migration.maintain_test_schema! + +RSpec.configure do |config| + config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! +end diff --git a/spec/shared_examples/decoratable.rb b/spec/shared_examples/decoratable.rb new file mode 100644 index 0000000..331b4ad --- /dev/null +++ b/spec/shared_examples/decoratable.rb @@ -0,0 +1,24 @@ +RSpec.shared_examples_for "a decoratable model" do + describe ".decorate" do + it "applies a collection decorator to a scope" do + described_class.create + decorated = described_class.limit(1).decorate + + expect(decorated.size).to eq(1) + expect(decorated).to be_decorated + end + end + + describe "#==" do + it "is true for other instances' decorators" do + pending "Mongoid < 3.1 overrides `#==`" if defined?(Mongoid) && Mongoid::VERSION.to_f < 3.1 && described_class < Mongoid::Document + + described_class.create + one = described_class.first + other = described_class.first + + expect(one).not_to be other + expect(one == other.decorate).to be_truthy + end + end +end