From 681a2c5e359db72e5669eaf334ff8eafbf695665 Mon Sep 17 00:00:00 2001 From: Nicolas Brousse Date: Wed, 30 Jan 2019 20:40:48 +0100 Subject: [PATCH] wip: test generators --- .rubocop.yml | 1 + spec/generators/decorator_generator_spec.rb | 17 +++ .../dekorator_install_generator_spec.rb | 9 ++ spec/lib/dekorator/decorators_helper.rb | 25 ++++ spec/lib/dekorator_base_spec.rb | 2 +- spec/spec_helper.rb | 4 + spec/support/generators.rb | 135 ++++++++++++++++++ spec/support/match_contents_matcher.rb | 8 ++ 8 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 spec/generators/decorator_generator_spec.rb create mode 100644 spec/generators/dekorator_install_generator_spec.rb create mode 100644 spec/lib/dekorator/decorators_helper.rb create mode 100644 spec/support/generators.rb create mode 100644 spec/support/match_contents_matcher.rb diff --git a/.rubocop.yml b/.rubocop.yml index aa7041b..2c22be2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,6 +3,7 @@ AllCops: DisabledByDefault: true Exclude: - lib/generators/**/templates/**/* + - tmp/**/* Gemspec/OrderedDependencies: Enabled: true diff --git a/spec/generators/decorator_generator_spec.rb b/spec/generators/decorator_generator_spec.rb new file mode 100644 index 0000000..5c07d14 --- /dev/null +++ b/spec/generators/decorator_generator_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +RSpec.describe "decorator", type: :generator do + before { with_app { generate("dekorator:install") } } + + it "generates a Decorator file for a simple Object" do + generate("decorator User") + + expect("app/decorators/user_decorator.rb").to match_contents(%r{UserDecorator}) + end + + it "generates a Decorator file for a namespaced Object" do + generate("decorator Product::Attribute") + + expect("app/decorators/product/attribute_decorator.rb").to match_contents(%r{Product::AttributeDecorator}) + end +end diff --git a/spec/generators/dekorator_install_generator_spec.rb b/spec/generators/dekorator_install_generator_spec.rb new file mode 100644 index 0000000..f3aedfb --- /dev/null +++ b/spec/generators/dekorator_install_generator_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +RSpec.describe "dekorator:install", type: :generator do + it "creates ApplicationDecorator file" do + with_app { generate("dekorator:install") } + + expect("app/decorators/application_decorator.rb").to match_contents(%r{ApplicationDecorator}) + end +end diff --git a/spec/lib/dekorator/decorators_helper.rb b/spec/lib/dekorator/decorators_helper.rb new file mode 100644 index 0000000..edaedd4 --- /dev/null +++ b/spec/lib/dekorator/decorators_helper.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require "active_support/core_ext/module/delegation" +require "dekorator/decorators_helper" + +require File.expand_path("../fixtures/models.rb", __dir__) +require File.expand_path("../fixtures/decorators.rb", __dir__) + +RSpec.describe DecoratorsHelper do + let(:comment) { Comment.new(author_name: "john.doe", body: "comment message") } + let(:post) { Post.new(name: "post title", body: "a" * 200, comments: [comment]) } + + describe "#decorate" do + context "with object" do + it { expect(described_class.decorate(post)).to be_a(PostDecorator) } + it { expect(described_class.decorate(post)).to be_a(PostDecorator) } + end + + context "with enumerable" do + it { expect(described_class.decorate([post, post, post])).to all(be_a(PostDecorator)) } + it { expect(described_class.decorate([post, post, post])).to all(be_a(PostDecorator)) } + it { expect(described_class.decorate([post, post, post])).to be_a(Enumerable) } + end + end +end diff --git a/spec/lib/dekorator_base_spec.rb b/spec/lib/dekorator_base_spec.rb index 6092e69..1e2f080 100644 --- a/spec/lib/dekorator_base_spec.rb +++ b/spec/lib/dekorator_base_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -# + require File.expand_path("../fixtures/models.rb", __dir__) require File.expand_path("../fixtures/decorators.rb", __dir__) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1d2ad84..8933645 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,8 +4,12 @@ SimpleCov.start require "bundler/setup" +Bundler.require(:default, :test) + require "dekorator" +Dir["./spec/support/**/*.rb"].each { |file| require file } + RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" diff --git a/spec/support/generators.rb b/spec/support/generators.rb new file mode 100644 index 0000000..8248448 --- /dev/null +++ b/spec/support/generators.rb @@ -0,0 +1,135 @@ +# frozen_string_literal: true + +module GeneratorTestHelpers + APP_NAME = "dummy_app" + + def remove_project_directory + FileUtils.rm_rf(project_path) + end + + def create_tmp_directory + FileUtils.mkdir_p(tmp_path) + end + + def remove_decorators_directory + FileUtils.rm_rf(decorators_path) + FileUtils.rm_rf(decorators_spec_path) + FileUtils.rm_rf(decorators_test_path) + end + + def with_app + remove_project_directory + rails_new + + yield + end + + def rails_new + run_in_tmp do + debug `#{system_rails_bin} new #{APP_NAME} --skip-webpack-install` + + Dir.chdir(APP_NAME) do + File.open("Gemfile", "a") do |file| + file.puts %{gem "dekorator", path: #{root_path.inspect}} + end + end + end + end + + def generate(generator) + run_in_project do + debug `bin/spring stop` + debug `#{project_rails_bin} generate #{generator}` + end + end + + def destroy(generator) + run_in_project do + `bin/spring stop` + `#{project_rails_bin} destroy #{generator}` + end + end + + def project_path + @project_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}") + end + + def decorators_path + @decorators_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}/app/decorators") + end + + def decorators_spec_path + @decorators_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}/spec/decorators") + end + + def decorators_test_path + @decorators_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}/test/decorators") + end + + private + + def tmp_path + @tmp_path ||= Pathname.new("#{root_path}/tmp") + end + + def system_rails_bin + "rails" + end + + def project_rails_bin + "bin/rails" + end + + def root_path + File.expand_path('../../../', __FILE__) + end + + def with_env(name, new_value) + had_key = ENV.has_key?(name) + prior = ENV[name] + ENV[name] = new_value.to_s + + yield + + ensure + ENV.delete(name) + + if had_key + ENV[name] = prior + end + end + + def run_in_tmp + create_tmp_directory + + Dir.chdir(tmp_path) do + Bundler.with_clean_env do + yield + end + end + end + + def run_in_project + Dir.chdir(project_path) do + Bundler.with_clean_env do + yield + end + end + end + + def debug(output) + if ENV["DEBUG"] + warn output + end + + output + end +end + +RSpec.configure do |config| + config.include GeneratorTestHelpers + + config.before(:each, type: :generator) do + remove_project_directory + end +end diff --git a/spec/support/match_contents_matcher.rb b/spec/support/match_contents_matcher.rb new file mode 100644 index 0000000..655fa0c --- /dev/null +++ b/spec/support/match_contents_matcher.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +RSpec::Matchers.define :match_contents do |regexp| + match do |filename| + contents = IO.read(File.join(project_path, filename)) + contents =~ regexp + end +end