diff --git a/.gitignore b/.gitignore index 880a43e..97a78fb 100644 --- a/.gitignore +++ b/.gitignore @@ -26,11 +26,16 @@ config/application.yml # Ignore master key for decrypting credentials and more. /config/master.key +# ignore precompiled assets +/public/test-assets /public/assets + /public/packs /public/packs-test + /node_modules /yarn-error.log yarn-debug.log* .yarn-integrity + diff --git a/Gemfile b/Gemfile index c87c2ca..36f2c3a 100644 --- a/Gemfile +++ b/Gemfile @@ -118,6 +118,12 @@ group :test do gem 'selenium-webdriver' # Easy installation and use of chromedriver to run system tests with Chrome gem 'chromedriver-helper' + gem 'rspec-html-matchers' + + gem 'vcr' + gem 'webmock' + gem 'timecop' + end diff --git a/Gemfile.lock b/Gemfile.lock index d1d4402..a85aecd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -85,6 +85,8 @@ GEM nokogiri (~> 1.8) coderay (1.1.2) concurrent-ruby (1.1.5) + crack (0.4.3) + safe_yaml (~> 1.0.0) crass (1.0.4) debug_inspector (0.0.3) derailed_benchmarks (1.3.5) @@ -120,6 +122,7 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) + hashdiff (0.4.0) heapy (0.1.4) high_voltage (3.1.2) hpricot (0.8.6) @@ -229,6 +232,9 @@ GEM rspec-expectations (3.8.4) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) + rspec-html-matchers (0.9.1) + nokogiri (~> 1) + rspec (>= 3.0.0.a, < 4) rspec-mocks (3.8.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) @@ -253,6 +259,7 @@ GEM ruby-progressbar (1.10.1) ruby_dep (1.5.0) rubyzip (1.2.3) + safe_yaml (1.0.5) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -295,17 +302,23 @@ GEM thor (0.19.4) thread_safe (0.3.6) tilt (2.0.9) + timecop (0.9.1) turbolinks (5.2.0) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) tzinfo (1.2.5) thread_safe (~> 0.1) unicode-display_width (1.6.0) + vcr (5.0.0) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) + webmock (3.6.0) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) webpacker (4.0.7) activesupport (>= 4.2) rack-proxy (>= 0.6.1) @@ -345,6 +358,7 @@ DEPENDENCIES rails-erd redcarpet redis + rspec-html-matchers rspec-rails (~> 3) rubocop ruby-prof (>= 0.17.0) @@ -357,9 +371,12 @@ DEPENDENCIES stackprof test-prof therubyracer + timecop turbolinks (~> 5) tzinfo-data + vcr web-console (>= 3.3) + webmock webpacker RUBY VERSION diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..23074cd --- /dev/null +++ b/Guardfile @@ -0,0 +1,70 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# Note: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: "bundle exec rspec" do + require "guard/rspec/dsl" + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w(erb haml slim)) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance" + end +end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0a38fd3..205da4d 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -5,21 +5,28 @@ # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + + config.cache_classes = ENV["CI"].present? # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. config.eager_load = false + # we use precompiled assets to speed up multiple test runs + config.assets.enabled = false + + # we need to use a different prefix so that we don't interfere with development environment + config.assets.prefix = "test-assets" + # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + "Cache-Control" => "public, max-age=#{1.hour.to_i}", } # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates. diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 6f1ab14..6ac6cbe 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,10 +1,10 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) +ENV["RAILS_ENV"] ||= "test" +require File.expand_path("../../config/environment", __FILE__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? -require 'spec_helper' -require 'rspec/rails' +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 @@ -20,12 +20,14 @@ # 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 } +Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } # Checks for pending migration and applies them before tests are run. # If you are not using ActiveRecord, you can remove this line. ActiveRecord::Migration.maintain_test_schema! +RSpec::Matchers.define_negated_matcher :not_have_any, :include + RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" diff --git a/spec/requests/pages/hello_spec.rb b/spec/requests/pages/hello_spec.rb new file mode 100644 index 0000000..e61b33d --- /dev/null +++ b/spec/requests/pages/hello_spec.rb @@ -0,0 +1,21 @@ +require "rails_helper" + +RSpec.describe "hello (static page)", type: :request do + include RSpecHtmlMatchers + + describe "GET /pages/hello" do + it "loads and has a link to hello page" do + get page_path("hello") + + expect(response).to have_http_status(200) + + show_in_browser(response.body) + sleep 50 + expect(response.body).to( + have_tag(:h1) do + with_text "Hello World" + end + ) + end + end +end diff --git a/spec/requests/pages/home_spec.rb b/spec/requests/pages/home_spec.rb new file mode 100644 index 0000000..679e93e --- /dev/null +++ b/spec/requests/pages/home_spec.rb @@ -0,0 +1,19 @@ +require "rails_helper" + +RSpec.describe "home (static page)", type: :request do + include RSpecHtmlMatchers + + describe "GET /pages/home" do + it "loads and has a link to hello page" do + get '/' + + expect(response).to have_http_status(200) + + expect(response.body).to( + have_tag(:a, with: { href: "/pages/hello" }) do + with_text "Hello" + end + ) + end + end +end diff --git a/spec/support/precompile_assets.rb b/spec/support/precompile_assets.rb new file mode 100644 index 0000000..45e55ab --- /dev/null +++ b/spec/support/precompile_assets.rb @@ -0,0 +1,14 @@ +RSpec.configure do |config| + config.before :all do + unless File.exist?(Rails.root.join("public/test-assets")) + case self.class.metadata[:type] + when :feature, :view, :request + STDOUT.write "Precompiling assets..." + + system "bundle exec rake assets:precompile > /dev/null 2>&1" + + STDOUT.puts "\n Done." + end + end + end +end diff --git a/spec/support/show_in_browser.rb b/spec/support/show_in_browser.rb new file mode 100644 index 0000000..2d6986c --- /dev/null +++ b/spec/support/show_in_browser.rb @@ -0,0 +1,12 @@ +def show_in_browser(s) + s = s.gsub(%r{\btest-assets/}, "file://#{Rails.public_path.to_s}/test-assets/") + file = Tempfile.new(["rspec-results", ".html"]) + begin + puts "writing contents to tempfile #{file.path}" + + file.write(s) + `open #{file.path}` + ensure + file.close + end +end diff --git a/todos/main.todo b/todos/main.todo index b21fad6..a8b46e0 100644 --- a/todos/main.todo +++ b/todos/main.todo @@ -29,8 +29,13 @@ Base: Specs: ✔ add high voltage and a home page @done(2019-06-18 10:57) ✔ add high voltage hello page @done(2019-06-18 10:57) - ☐ spec high voltage home page @next - ☐ spec link to hv hello page + ✔ setup guard @done(2019-06-20 18:30) + ✔ setup show in browser from past projects @done(2019-06-20 19:04) + ✔ setup rspec html matchers from past projects @done(2019-06-20 19:04) + ✔ setup precompile assets in request specs @done(2019-06-20 19:04) + ✔ spec high voltage home page @done(2019-06-20 19:04) + ✔ spec link to hv hello page @done(2019-06-20 19:04) + ☐ CI with request spec ☐ add devise ☐ devise request specs, with CI @@ -42,7 +47,7 @@ Base: ☐ cypress CI Static Pages: - ☐ add high-voltage + ✔ add high-voltage @done(2019-06-20 19:04) Users: ☐ devise setup @@ -52,6 +57,8 @@ Base: ☐ login with facebook GUI/CSS: + ☐ add tailwind @next + ☐ tailwind helloworld on home & hello pages ☐ choose a powerful widget platform ☐ must be themeable ☐ must be built on a standard