Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First attempt at a concept spec generator #82

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lib/generators/rspec/concept_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'rails/generators'
require 'generators/rspec'

# ensure that we can see the test-libraries like Capybara
Bundler.require :test if Bundler

module Rspec
module Generators
class ConceptGenerator < Base
source_root File.expand_path('../templates', __FILE__)
argument :actions, type: :array, default: []
class_option :e, type: :string, desc: 'The template engine'

def concept_name
class_path.empty? ? "'#{file_path}/cell'" : %{"#{file_path}/cell"}
end

def create_concept_spec_file
template "concept_spec.erb", File.join("spec/concepts/#{file_path}_concept_spec.rb")
end

def template_engine
(options[:e] || Rails.application.config.app_generators.rails[:template_engine] || 'erb').to_s
end
end
end
end
24 changes: 24 additions & 0 deletions lib/generators/rspec/templates/concept_spec.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'rails_helper'

RSpec.describe <%= class_name %>::Cell, type: :concept do

context 'concept rendering' do
<%- actions.each_with_index do |state, index| -%>
context 'rendering <%= state %>' do
subject { concept(<%= concept_name %>, <%= class_name %>.new).call(:<%= state %>) }

<%- if defined?(::Capybara) -%>
it { is_expected.to have_selector('h1', text: '<%= class_name %>#<%= state %>') }
it { is_expected.to have_selector('p', text: 'Find me in app/concepts/<%= file_path %>/views/<%= state %>.<%= template_engine %>') }
<%- else -%>
it { is_expected.to include '<%= class_name %>#<%= state %>' }
it { is_expected.to include 'Find me in app/concepts/<%= file_path %>/views/<%= state %>.<%= template_engine %>' }
<%- end -%>
end
<%- unless index == actions.length - 1 -%>

<%- end -%>
<%- end -%>
end

end
2 changes: 2 additions & 0 deletions lib/rspec/cells.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
require 'rspec/rails/example/rails_example_group'
require 'rspec/cells/example_group'
require 'rspec/cells/caching'
require 'rspec/concepts/example_group'
require 'rspec/concepts/caching'
28 changes: 28 additions & 0 deletions lib/rspec/concepts/caching.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module RSpec
module Concepts
module Caching
extend ActiveSupport::Concern

module ClassMethods
def enable_concepts_caching!
before :each do
ActionController::Base.perform_caching = true
end
after :each do
ActionController::Base.perform_caching = false
end
end

def disable_concepts_caching!
before :each do
ActionController::Base.perform_caching = false
end
end
end
end
end
end

RSpec.configure do |c|
c.include RSpec::Concepts::Caching, type: :concepts
end
60 changes: 60 additions & 0 deletions lib/rspec/concepts/example_group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module RSpec
module Concepts
module ExampleGroup
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is identical to https://github.com/apotonick/rspec-cells/blob/master/lib/rspec/cells/example_group.rb. We should rather reuse the existing (same with the other files that you copied). Can you do that? 🍺

extend ActiveSupport::Concern

include RSpec::Rails::RailsExampleGroup
include Cell::Testing
include ActionController::UrlFor

attr_reader :routes

def method_missing(method, *args, &block)
# Send the route helpers to the application router.
if route_defined?(method)
controller.send(method, *args, &block)
else
super
end
end

def route_defined?(method)
return false unless @routes

if @routes.named_routes.respond_to?(:route_defined?) # Rails > 4.2.
@routes.named_routes.route_defined?(method)
else
@routes.named_routes.helpers.include?(method)
end
end

included do
metadata[:type] = :cell

before do # called before every it.
@routes = ::Rails.application.routes
ActionController::Base.allow_forgery_protection = false
end

# add Example::controller and ::controller_class.
extend RSpec::Cells::ExampleGroup::Controller
let (:controller_class) { }
let (:controller) { controller_for(controller_class) }
end


module Controller
def controller(name) # DSL for test, e.g. `controller SongsController`.
let (:controller_class) { name }
end
end
end
end
end

RSpec.configure do |c|
c.include RSpec::Concepts::ExampleGroup, :file_path => /spec\/concepts/
c.include RSpec::Concepts::ExampleGroup, :type => :concept

Cell::Testing.capybara = true if Object.const_defined?(:"Capybara")
end
9 changes: 9 additions & 0 deletions lib/rspec/concepts/tasks.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'rspec/core/rake_task'

namespace :spec do
desc "Run the code examples in spec/concepts"
RSpec::Core::RakeTask.new("concepts") do |t|
t.pattern = "./spec/concepts/**/*_spec.rb"
t.rspec_opts = '--tag concept'
end
end
30 changes: 15 additions & 15 deletions spec/cells/cell_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

attr_accessor :test_case, :test

DESTINATION_ROOT = File.expand_path("../../tmp", __FILE__)
CELL_DESTINATION_ROOT = File.expand_path("../../tmp", __FILE__)

before(:all) do
test_case = Class.new(Rails::Generators::TestCase)
test_case.destination_root = DESTINATION_ROOT
test_case.destination_root = CELL_DESTINATION_ROOT
test_case.generator_class = Rspec::Generators::CellGenerator
self.test = test_case.new :wow
end
Expand All @@ -25,7 +25,7 @@ def t(line_code)
end

after(:all) do
FileUtils.rm_rf(DESTINATION_ROOT) # Cleanup after we are done testing
FileUtils.rm_rf(CELL_DESTINATION_ROOT) # Cleanup after we are done testing
# Object.send(:remove_const, :"Capybara")
end

Expand Down Expand Up @@ -95,32 +95,32 @@ def t(line_code)
end

after(:all) do
FileUtils.rm_rf(DESTINATION_ROOT) # Cleanup after we are done testing
FileUtils.rm_rf(CELL_DESTINATION_ROOT) # Cleanup after we are done testing
end

GENERATED_FILE = "spec/cells/forum/comment_cell_spec.rb"
CELL_GENERATED_FILE = "spec/cells/forum/comment_cell_spec.rb"

it "creates widget spec" do
test.assert_file GENERATED_FILE, t("require 'rails_helper'")
test.assert_file GENERATED_FILE, t('describe Forum::CommentCell, type: :cell do')
test.assert_file GENERATED_FILE, t('context \'cell rendering\' do')
test.assert_file GENERATED_FILE, t('end')
test.assert_file CELL_GENERATED_FILE, t("require 'rails_helper'")
test.assert_file CELL_GENERATED_FILE, t('describe Forum::CommentCell, type: :cell do')
test.assert_file CELL_GENERATED_FILE, t('context \'cell rendering\' do')
test.assert_file CELL_GENERATED_FILE, t('end')
end

it 'creates display state' do
test.assert_file GENERATED_FILE, t('context \'rendering display\' do')
test.assert_file GENERATED_FILE, t('subject { cell("forum/comment", Forum::Comment.new).call(:display) }')
test.assert_file CELL_GENERATED_FILE, t('context \'rendering display\' do')
test.assert_file CELL_GENERATED_FILE, t('subject { cell("forum/comment", Forum::Comment.new).call(:display) }')
# test.assert_file GENERATED_FILE, t('it { is_expected.to include \'Forum::Comment#display\' }')
# test.assert_file GENERATED_FILE, t('it { is_expected.to include \'Find me in app/cells/forum/comment/display.erb\' }')
test.assert_file GENERATED_FILE, t('end')
test.assert_file CELL_GENERATED_FILE, t('end')
end

it 'creates form state' do
test.assert_file GENERATED_FILE, t('context \'rendering form\' do')
test.assert_file GENERATED_FILE, t('subject { cell("forum/comment", Forum::Comment.new).call(:form) }')
test.assert_file CELL_GENERATED_FILE, t('context \'rendering form\' do')
test.assert_file CELL_GENERATED_FILE, t('subject { cell("forum/comment", Forum::Comment.new).call(:form) }')
# test.assert_file GENERATED_FILE, t('it { is_expected.to include \'Forum::Comment#form\' }')
# test.assert_file GENERATED_FILE, t('it { is_expected.to include \'Find me in app/cells/forum/comment/form.erb\' }')
test.assert_file GENERATED_FILE, t('end')
test.assert_file CELL_GENERATED_FILE, t('end')
end
end
end
126 changes: 126 additions & 0 deletions spec/cells/concept_generator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
require "spec_helper"
require "generators/rspec/concept_generator"

describe Rspec::Generators::ConceptGenerator do
include RSpec::Rails::RailsExampleGroup

attr_accessor :test_case, :test

CONCEPT_DESTINATION_ROOT = File.expand_path("../../tmp", __FILE__)

before(:all) do
test_case = Class.new(Rails::Generators::TestCase)
test_case.destination_root = CONCEPT_DESTINATION_ROOT
test_case.generator_class = Rspec::Generators::ConceptGenerator
self.test = test_case.new :wow
end

def t(line_code)
Regexp.new(Regexp.escape(line_code))
end

context "When defined Capybara" do
before(:all) do
test.run_generator %w(Twitter display form)
end

after(:all) do
FileUtils.rm_rf(CONCEPT_DESTINATION_ROOT) # Cleanup after we are done testing
# Object.send(:remove_const, :"Capybara")
end

it "creates widget spec" do
test.assert_file "spec/concepts/twitter_concept_spec.rb", t("require 'rails_helper'")
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('RSpec.describe Twitter::Cell, type: :concept do')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('context \'concept rendering\' do')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('end')
end

it 'creates display state' do
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('context \'rendering display\' do')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('subject { concept(\'twitter/cell\', Twitter.new).call(:display) }')
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('it { is_expected.to have_selector(\'h1\', text: \'Twitter#display\') }')
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('it { is_expected.to have_selector(\'p\', text: \'Find me in app/concepts/twitter/views/display.erb\') }')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('end')
end

it 'creates form state' do
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('context \'rendering form\' do')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('subject { concept(\'twitter/cell\', Twitter.new).call(:form) }')
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('it { is_expected.to have_selector(\'h1\', text: \'Twitter#form\') }')
test.assert_file 'spec/concepts/twitter_concept_spec.rb', t('it { is_expected.to have_selector(\'p\', text: \'Find me in app/concepts/twitter/views/form.erb\') }')
test.assert_file "spec/concepts/twitter_concept_spec.rb", t('end')
end
end

# context "When not defined Capybara" do
# before(:all) do
# test.run_generator %w(Twitter display form)
# end

# after(:all) do
# FileUtils.rm_rf(CONCEPT_DESTINATION_ROOT) # Cleanup after we are done testing
# end

# it "creates widget spec" do
# test.assert_file "spec/cells/twitter_cell_spec.rb", t("require 'rails_helper'")
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('RSpec.describe TwitterCell, type: :cell do')
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('context \'cell rendering\' do')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('end')
# end

# it 'creates display state' do
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('context \'rendering display\' do')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('subject { cell(:twitter, Twitter.new).call(:display) }')
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('it { is_expected.to include \'Twitter#display\' }')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('it { is_expected.to include \'Find me in app/cells/twitter/display.erb\' }')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('end')
# end

# it 'creates form state' do
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('context \'rendering form\' do')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('subject { cell(:twitter, Twitter.new).call(:form) }')
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('it { is_expected.to include \'Twitter#form\' }')
# test.assert_file 'spec/cells/twitter_cell_spec.rb', t('it { is_expected.to include \'Find me in app/cells/twitter/form.erb\' }')
# test.assert_file "spec/cells/twitter_cell_spec.rb", t('end')
# end
# end

# TODO: does rspec even work without capybara?

context "When uses namespace" do

before(:all) do
test.run_generator %w(Forum::Comment display form)
end

after(:all) do
FileUtils.rm_rf(CONCEPT_DESTINATION_ROOT) # Cleanup after we are done testing
end

CONCEPT_GENERATED_FILE = "spec/concepts/forum/comment_concept_spec.rb"

it "creates widget spec" do
test.assert_file CONCEPT_GENERATED_FILE, t("require 'rails_helper'")
test.assert_file CONCEPT_GENERATED_FILE, t('describe Forum::Comment::Cell, type: :concept do')
test.assert_file CONCEPT_GENERATED_FILE, t('context \'concept rendering\' do')
test.assert_file CONCEPT_GENERATED_FILE, t('end')
end

it 'creates display state' do
test.assert_file CONCEPT_GENERATED_FILE, t('context \'rendering display\' do')
test.assert_file CONCEPT_GENERATED_FILE, t('subject { concept("forum/comment/cell", Forum::Comment.new).call(:display) }')
# test.assert_file CONCEPT_GENERATED_FILE, t('it { is_expected.to include \'Forum::Comment#display\' }')
# test.assert_file CONCEPT_GENERATED_FILE, t('it { is_expected.to include \'Find me in app/cells/forum/comment/display.erb\' }')
test.assert_file CONCEPT_GENERATED_FILE, t('end')
end

it 'creates form state' do
test.assert_file CONCEPT_GENERATED_FILE, t('context \'rendering form\' do')
test.assert_file CONCEPT_GENERATED_FILE, t('subject { concept("forum/comment/cell", Forum::Comment.new).call(:form) }')
# test.assert_file CONCEPT_GENERATED_FILE, t('it { is_expected.to include \'Forum::Comment#form\' }')
# test.assert_file CONCEPT_GENERATED_FILE, t('it { is_expected.to include \'Find me in app/cells/forum/comment/form.erb\' }')
test.assert_file CONCEPT_GENERATED_FILE, t('end')
end
end
end