From b91b45a6831f3b3265743ec151f6a685070f573e Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Tue, 28 Aug 2018 23:55:02 +0200 Subject: [PATCH 01/16] refa: remove test folder, will get rspec instead --- test/application_system_test_case.rb | 5 ----- test/controllers/.keep | 0 test/fixtures/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/system/.keep | 0 test/test_helper.rb | 10 ---------- 10 files changed, 15 deletions(-) delete mode 100644 test/application_system_test_case.rb delete mode 100644 test/controllers/.keep delete mode 100644 test/fixtures/.keep delete mode 100644 test/fixtures/files/.keep delete mode 100644 test/helpers/.keep delete mode 100644 test/integration/.keep delete mode 100644 test/mailers/.keep delete mode 100644 test/models/.keep delete mode 100644 test/system/.keep delete mode 100644 test/test_helper.rb diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb deleted file mode 100644 index d19212a..0000000 --- a/test/application_system_test_case.rb +++ /dev/null @@ -1,5 +0,0 @@ -require "test_helper" - -class ApplicationSystemTestCase < ActionDispatch::SystemTestCase - driven_by :selenium, using: :chrome, screen_size: [1400, 1400] -end diff --git a/test/controllers/.keep b/test/controllers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/.keep b/test/fixtures/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/helpers/.keep b/test/helpers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/integration/.keep b/test/integration/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/mailers/.keep b/test/mailers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/models/.keep b/test/models/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/system/.keep b/test/system/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/test_helper.rb b/test/test_helper.rb deleted file mode 100644 index 3ab84e3..0000000 --- a/test/test_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -ENV['RAILS_ENV'] ||= 'test' -require_relative '../config/environment' -require 'rails/test_help' - -class ActiveSupport::TestCase - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. - fixtures :all - - # Add more helper methods to be used by all tests here... -end From 70b46cd152389f274af9a429a37bdded7558b6b3 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Tue, 28 Aug 2018 23:55:57 +0200 Subject: [PATCH 02/16] chore: add rspec gems to repo --- Gemfile | 1 + Gemfile.lock | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index bd6515a..1f1ab3f 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,7 @@ group :development, :test do end group :development do + gem 'rspec-rails', '~> 3.7' # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' diff --git a/Gemfile.lock b/Gemfile.lock index 8f8bcad..02ed1b7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,6 +79,7 @@ GEM coffee-script-source (1.12.2) concurrent-ruby (1.0.5) crass (1.0.3) + diff-lcs (1.3) erubi (1.7.1) execjs (2.7.0) ffi (1.9.23) @@ -155,6 +156,23 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.8.0) + rspec-rails (3.8.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) ruby_dep (1.5.0) rubyzip (1.2.1) sass (3.4.25) @@ -222,6 +240,7 @@ DEPENDENCIES pg puma (~> 3.11) rails (~> 5.2.0.rc1) + rspec-rails (~> 3.7) sass-rails (~> 5.0) selenium-webdriver spring @@ -235,4 +254,4 @@ RUBY VERSION ruby 2.5.0p0 BUNDLED WITH - 1.16.1 + 1.16.4 From 2ec75c61a23671e7df9b874c34a647068c6f4f4f Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Tue, 28 Aug 2018 23:57:40 +0200 Subject: [PATCH 03/16] chore: configure rspec --- .rspec | 1 + spec/rails_helper.rb | 61 ++++++++++++++++++++++++++++ spec/spec_helper.rb | 96 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 .rspec create mode 100644 spec/rails_helper.rb create mode 100644 spec/spec_helper.rb diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000..d73d80b --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,61 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +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 '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 and applies them before tests are run. +# If you are not using ActiveRecord, you can remove these lines. +begin + ActiveRecord::Migration.maintain_test_schema! +rescue ActiveRecord::PendingMigrationError => e + puts e.to_s.strip + exit 1 +end +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, :type => :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..ce33d66 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end From 0fac604e836e83d7fa055f4f3051f8ff9294281a Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Wed, 29 Aug 2018 13:57:23 +0200 Subject: [PATCH 04/16] refa: mimic the behavior of schema onto structure.sql, so we can create type within postgresql migrations --- config/application.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/application.rb b/config/application.rb index bf3d64a..b406d66 100644 --- a/config/application.rb +++ b/config/application.rb @@ -15,5 +15,7 @@ class Application < Rails::Application # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. + + config.active_record.schema_format = :sql end end From 6eb3f9d8bff780da618f1566db1b1ec0a52f72dd Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Wed, 29 Aug 2018 14:01:36 +0200 Subject: [PATCH 05/16] feat: basic tdd for Installation new fields --- app/models/installation.rb | 13 ++++- ...0180828221528_add_field_to_installation.rb | 51 +++++++++++++++++++ spec/models/installation_spec.rb | 21 ++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20180828221528_add_field_to_installation.rb create mode 100644 spec/models/installation_spec.rb diff --git a/app/models/installation.rb b/app/models/installation.rb index 4735a9b..931dd4b 100644 --- a/app/models/installation.rb +++ b/app/models/installation.rb @@ -1,8 +1,19 @@ class Installation < ActiveRecord::Base delegate :last_commit, :lines_diff, :files_changed, :diff_url, to: :github + enum organization_type: { + government: 'government', + ong: 'ong', + university: 'university', + school: 'school', + other: 'other', + } + enum installation_status: { + in_progress: 'in_progress', + in_production: 'in_production', + } def github Installation::Github.new(self) end -end \ No newline at end of file +end diff --git a/db/migrate/20180828221528_add_field_to_installation.rb b/db/migrate/20180828221528_add_field_to_installation.rb new file mode 100644 index 0000000..335140d --- /dev/null +++ b/db/migrate/20180828221528_add_field_to_installation.rb @@ -0,0 +1,51 @@ +class AddFieldToInstallation < ActiveRecord::Migration[5.2] + def up + ActiveRecord::Base.connection.execute <<-SQL + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'organization_type') THEN + CREATE TYPE organization_type AS ENUM ('government', 'ngo', 'university', 'school', 'other'); + END IF; + + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'installation_status') THEN + CREATE TYPE installation_status AS ENUM ('in_progress', 'in_production'); + END IF; + END + $$; + SQL + + if table_exists? :installations + add_column :installations, :website, :string + add_column :installations, :contact_name, :string + add_column :installations, :conact_email, :string + add_column :installations, :location, :string + add_column :installations, :organization_type, :organization_type + add_column :installations, :status, :installation_status + add_column :installations, :notes, :text + end + end + + def down + remove_column :installations, :website if column_exists? :installations, :website + remove_column :installations, :contact_name if column_exists? :installations, :contact_name + remove_column :installations, :conact_email if column_exists? :installations, :conact_email + remove_column :installations, :location if column_exists? :installations, :location + remove_column :installations, :organization_type if column_exists? :installations, :organization_type + remove_column :installations, :status if column_exists? :installations, :status + remove_column :installations, :notes if column_exists? :installations, :notes + + ActiveRecord::Base.connection.execute <<-SQL + DO $$ + BEGIN + IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'organization_type') THEN + DROP TYPE organization_type; + END IF; + + IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'installation_status') THEN + DROP TYPE installation_status; + END IF; + END + $$; + SQL + end +end diff --git a/spec/models/installation_spec.rb b/spec/models/installation_spec.rb new file mode 100644 index 0000000..352cb7b --- /dev/null +++ b/spec/models/installation_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe Installation, type: :model do + + it { is_expected.to respond_to(:name) } + it { is_expected.to respond_to(:repo) } + it { is_expected.to respond_to(:created_at) } + it { is_expected.to respond_to(:updated_at) } + it { is_expected.to respond_to(:website) } + it { is_expected.to respond_to(:contact_name) } + it { is_expected.to respond_to(:conact_email) } + it { is_expected.to respond_to(:location) } + it { is_expected.to respond_to(:organization_type) } + it { is_expected.to respond_to(:status) } + it { is_expected.to respond_to(:notes) } + + it "is valid with valid attributes" do + expect(Installation.new).to be_valid + end + +end From 41a47d12bfe391f14c0d6f30a47c02f047ed3dd5 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Thu, 30 Aug 2018 12:29:50 +0200 Subject: [PATCH 06/16] chore: factory bot and faker gems added to repo --- Gemfile | 2 ++ Gemfile.lock | 9 ++++++++ spec/spec_helper.rb | 52 +++------------------------------------------ 3 files changed, 14 insertions(+), 49 deletions(-) diff --git a/Gemfile b/Gemfile index 1f1ab3f..e72f7a8 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,8 @@ gem 'jquery-ui-rails' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + gem 'factory_bot_rails' + gem 'faker' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 02ed1b7..bf759fa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,6 +82,13 @@ GEM diff-lcs (1.3) erubi (1.7.1) execjs (2.7.0) + factory_bot (4.11.0) + activesupport (>= 3.0.0) + factory_bot_rails (4.11.0) + factory_bot (~> 4.11.0) + railties (>= 3.0.0) + faker (1.9.1) + i18n (>= 0.7) ffi (1.9.23) foundation-rails (6.4.3.0) railties (>= 3.1.0) @@ -232,6 +239,8 @@ DEPENDENCIES capybara (~> 2.15) chromedriver-helper coffee-rails (~> 4.2) + factory_bot_rails + faker foundation-rails jbuilder (~> 2.5) jquery-rails diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ce33d66..697c34c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +require 'factory_bot_rails' + # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -14,6 +16,7 @@ # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| + config.include FactoryBot::Syntax::Methods # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest # assertions if you prefer. @@ -44,53 +47,4 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end end From b5a90aac7575ff3108be7c7d1e275b1b6ef3c5b2 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Thu, 30 Aug 2018 12:32:09 +0200 Subject: [PATCH 07/16] feat: installation controller, new action with tdd --- app/controllers/installations_controller.rb | 6 +++- app/views/installations/new.html.erb | 5 ++++ config/routes.rb | 2 +- .../installations_controller_spec.rb | 29 +++++++++++++++++++ spec/factories/installations.rb | 13 +++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 app/views/installations/new.html.erb create mode 100644 spec/controllers/installations_controller_spec.rb create mode 100644 spec/factories/installations.rb diff --git a/app/controllers/installations_controller.rb b/app/controllers/installations_controller.rb index d03a5e2..2c3ccfa 100644 --- a/app/controllers/installations_controller.rb +++ b/app/controllers/installations_controller.rb @@ -8,4 +8,8 @@ def show @installation = Installation.find(params[:id]) end -end \ No newline at end of file + def new + @installation = Installation.new + end + +end diff --git a/app/views/installations/new.html.erb b/app/views/installations/new.html.erb new file mode 100644 index 0000000..ffa80bd --- /dev/null +++ b/app/views/installations/new.html.erb @@ -0,0 +1,5 @@ +

New Installation

+ +<%= render 'form', installation: @installation %> + +<%= link_to 'Back', installations_path %> diff --git a/config/routes.rb b/config/routes.rb index 82aad0e..347432c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - resources :installations, only: [:index, :show] + resources :installations, only: [:index, :show, :new] root 'installations#index' get '/dashboard' => 'installations#index' end diff --git a/spec/controllers/installations_controller_spec.rb b/spec/controllers/installations_controller_spec.rb new file mode 100644 index 0000000..755f84c --- /dev/null +++ b/spec/controllers/installations_controller_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +RSpec.describe InstallationsController, type: :controller do + + let(:valid_session) { {} } + let(:installation) { create(:installation) } + + describe "GET #index" do + it "returns a success response" do + get :index, params: {}, session: valid_session + expect(response).to be_successful + end + end + + describe "GET #show" do + it "returns a success response" do + get :show, params: {id: installation.id.to_param}, session: valid_session + expect(response).to be_successful + end + end + + describe "GET #new" do + it "returns a success response" do + get :new, params: {}, session: valid_session + expect(response).to be_successful + end + end + +end diff --git a/spec/factories/installations.rb b/spec/factories/installations.rb new file mode 100644 index 0000000..1d1e9f0 --- /dev/null +++ b/spec/factories/installations.rb @@ -0,0 +1,13 @@ +FactoryBot.define do + factory :installation do + name { Faker::Lorem.sentence } + repo { Faker::Internet.url('github.com') } + website { Faker::Internet.url } + contact_name { Faker::Name.name_with_middle } + conact_email { Faker::Internet.email } + location { Faker::Address.full_address } + organization_type { Installation.organization_types.keys.sample } + status { Installation.installation_statuses.keys.sample } + notes { Faker::Lorem.paragraph } + end +end From 9fa1859ac734059039f13665d5a620fb6efbb74b Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 02:40:11 +0200 Subject: [PATCH 08/16] feat: basic unit test for uniqueness and presence validations for some Installation new fields --- app/models/installation.rb | 3 +++ spec/models/installation_spec.rb | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/models/installation.rb b/app/models/installation.rb index 931dd4b..f68d588 100644 --- a/app/models/installation.rb +++ b/app/models/installation.rb @@ -12,6 +12,9 @@ class Installation < ActiveRecord::Base in_production: 'in_production', } + validates :name, presence: true + validates :repo, presence: true, uniqueness: true + def github Installation::Github.new(self) end diff --git a/spec/models/installation_spec.rb b/spec/models/installation_spec.rb index 352cb7b..721c5f1 100644 --- a/spec/models/installation_spec.rb +++ b/spec/models/installation_spec.rb @@ -15,7 +15,15 @@ it { is_expected.to respond_to(:notes) } it "is valid with valid attributes" do - expect(Installation.new).to be_valid + expect(Installation.new(name: 'foo', repo: 'bar')).to be_valid end + it "is not valid with empty attributes" do + expect(Installation.new).not_to be_valid + end + + it "is not valid with repeated 'repo' attribute" do + Installation.new(repo: 'foo') + expect(Installation.new(repo: 'foo')).not_to be_valid + end end From 05d72457c78fca2e3634d423d7936c737f051f59 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:45:40 +0200 Subject: [PATCH 09/16] feat: installations controller, create action with tdd --- app/controllers/installations_controller.rb | 19 ++++++++++ config/routes.rb | 2 +- .../installations_controller_spec.rb | 36 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/app/controllers/installations_controller.rb b/app/controllers/installations_controller.rb index 2c3ccfa..00bb9e6 100644 --- a/app/controllers/installations_controller.rb +++ b/app/controllers/installations_controller.rb @@ -12,4 +12,23 @@ def new @installation = Installation.new end + def create + @installation = Installation.new(installation_params) + + respond_to do |format| + if @installation.save + format.html { redirect_to @installation, notice: 'installation was successfully created.' } + format.json { render :show, status: :created, location: @installation } + else + format.html { render :new } + format.json { render json: @installation.errors, status: :unprocessable_entity } + end + end + end + + private + def installation_params + params.require(:installation).permit(:name, :repo, :website, :contact_name, :conact_email, :location, :organization_type, :status, :notes) + end + end diff --git a/config/routes.rb b/config/routes.rb index 347432c..9a433fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - resources :installations, only: [:index, :show, :new] + resources :installations, only: [:index, :show, :new, :create] root 'installations#index' get '/dashboard' => 'installations#index' end diff --git a/spec/controllers/installations_controller_spec.rb b/spec/controllers/installations_controller_spec.rb index 755f84c..7715b75 100644 --- a/spec/controllers/installations_controller_spec.rb +++ b/spec/controllers/installations_controller_spec.rb @@ -26,4 +26,40 @@ end end + describe "POST #create" do + let(:installation_params) { + { + name: Faker::Lorem.sentence, + repo: Faker::Internet.url('github.com'), + website: Faker::Internet.url, + contact_name: Faker::Name.name_with_middle, + conact_email: Faker::Internet.email, + location: Faker::Address.full_address, + organization_type: Installation.organization_types.keys.sample, + status: Installation.installation_statuses.keys.sample, + notes: Faker::Lorem.paragraph, + } + } + + context "with valid params" do + it "creates a new Installation" do + expect { + post :create, params: {installation: installation_params}, session: valid_session + }.to change(Installation, :count).by(1) + end + + it "redirects to the created installation" do + post :create, params: {installation: installation_params}, session: valid_session + expect(response).to redirect_to(Installation.last) + end + end + + context "with invalid params" do + it "returns a success response (i.e. to display the 'new' template)" do + post :create, params: {installation: {foo: 'foo', bar: 'bar'}}, session: valid_session + expect(response).to be_successful + end + end + end + end From f16cd03b65e9d4c5a9c7eb5513164d384186bd11 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:46:45 +0200 Subject: [PATCH 10/16] feat: form to insert field for new installation --- app/views/installations/_form.html.erb | 110 +++++++++++++++++++++++++ app/views/installations/new.html.erb | 18 +++- 2 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 app/views/installations/_form.html.erb diff --git a/app/views/installations/_form.html.erb b/app/views/installations/_form.html.erb new file mode 100644 index 0000000..9cbe081 --- /dev/null +++ b/app/views/installations/_form.html.erb @@ -0,0 +1,110 @@ +<%= form_with(model: installation, local: true) do |form| %> + <% if installation.errors.any? %> +
+

<%= pluralize(installation.errors.count, "error") %> prohibited this installation from being saved:

+ +
    + <% installation.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+ +
+ <% end %> + +
+
+ <%= form.label :name, class: "text-right middle" %> +
+ +
+ <%= form.text_field :name %> +
+
+ +
+
+ <%= form.label :repo, class: "text-right middle" %> +
+ +
+ <%= form.text_field :repo %> +
+
+ +
+
+ <%= form.label :website, class: "text-right middle" %> +
+ +
+ <%= form.text_field :website %> +
+
+ +
+
+ <%= form.label :contact_name, class: "text-right middle" %> +
+ +
+ <%= form.text_field :contact_name %> +
+
+ +
+
+ <%= form.label :conact_email, class: "text-right middle" %> +
+ +
+ <%= form.text_field :conact_email %> +
+
+ +
+
+ <%= form.label :location, class: "text-right middle" %> +
+ +
+ <%= form.text_field :location %> +
+
+ +
+
+ <%= form.label :organization_type, class: "text-right middle" %> +
+ +
+ <%= form.select :organization_type, organization_type_for_select %> +
+
+ +
+
+ <%= form.label :status, class: "text-right middle" %> +
+ +
+ <%= form.select :status, installation_status_for_select %> +
+
+ +
+
+ <%= form.label :notes, class: "text-right middle" %> +
+ +
+ <%= form.text_field :notes %> +
+
+ +
+ <%= form.submit class: 'button' %> +
+<% end %> diff --git a/app/views/installations/new.html.erb b/app/views/installations/new.html.erb index ffa80bd..7003747 100644 --- a/app/views/installations/new.html.erb +++ b/app/views/installations/new.html.erb @@ -1,5 +1,17 @@ -

New Installation

+
+
+
+

New Installation

+
+
-<%= render 'form', installation: @installation %> +
+
+ <%= render 'form', installation: @installation %> +
-<%= link_to 'Back', installations_path %> +
+ <%= link_to 'Back', installations_path %> +
+
+
From fb861b8ac4aad7d01fc910400a30ca26d954df4b Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:47:07 +0200 Subject: [PATCH 11/16] fix: fix typo in installation model --- app/models/installation.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/installation.rb b/app/models/installation.rb index f68d588..898cc17 100644 --- a/app/models/installation.rb +++ b/app/models/installation.rb @@ -1,8 +1,9 @@ class Installation < ActiveRecord::Base delegate :last_commit, :lines_diff, :files_changed, :diff_url, to: :github + enum organization_type: { government: 'government', - ong: 'ong', + ngo: 'ngo', university: 'university', school: 'school', other: 'other', From 533adc0452e29e0c97e6b538cdf564b4a8383128 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:47:32 +0200 Subject: [PATCH 12/16] feat: add link to new installation in index page --- app/views/installations/index.html.erb | 39 +++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/app/views/installations/index.html.erb b/app/views/installations/index.html.erb index 01c2b1a..79355ef 100644 --- a/app/views/installations/index.html.erb +++ b/app/views/installations/index.html.erb @@ -1,19 +1,30 @@ -
+
-
- +
+
+
+ -

- <%= image_tag('icons/terminal.svg', alt: "") %> - <%= t("installations.index.title") %> -

+

+ <%= image_tag('icons/terminal.svg', alt: "") %> + <%= t("installations.index.title") %> +

+
+
+ +
+
From e7cb1762534f45fe982b79eec1198d40f2fd7718 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:48:07 +0200 Subject: [PATCH 13/16] feat: helper methods for selects on installation form --- app/helpers/installations_helper.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 app/helpers/installations_helper.rb diff --git a/app/helpers/installations_helper.rb b/app/helpers/installations_helper.rb new file mode 100644 index 0000000..9903190 --- /dev/null +++ b/app/helpers/installations_helper.rb @@ -0,0 +1,15 @@ +module InstallationsHelper + + def organization_type_for_select + Installation.organization_types.map do |organization_type, _| + [I18n.t("activerecord.attributes.installation.organization_types.#{organization_type}"), organization_type] + end + end + + def installation_status_for_select + Installation.installation_statuses.map do |installation_status, _| + [I18n.t("activerecord.attributes.installation.installation_statuses.#{installation_status}"), installation_status] + end + end + +end From 5828e7b13346ff07be7027b953f42ed5f2faa687 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:48:33 +0200 Subject: [PATCH 14/16] chore: configure capybara for feature tests --- spec/rails_helper.rb | 66 +++++++++++++++----------------------------- spec/spec_helper.rb | 36 +----------------------- 2 files changed, 23 insertions(+), 79 deletions(-) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index d73d80b..55a6fb6 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,61 +1,39 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' + +require 'spec_helper' 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 '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 } +require 'rspec/rails' +require 'capybara/rails' +require 'capybara/rspec' -# Checks for pending migrations and applies them before tests are run. -# If you are not using ActiveRecord, you can remove these lines. begin ActiveRecord::Migration.maintain_test_schema! rescue ActiveRecord::PendingMigrationError => e puts e.to_s.strip exit 1 end + RSpec.configure do |config| - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. config.use_transactional_fixtures = true - - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, :type => :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://relishapp.com/rspec/rspec-rails/docs config.infer_spec_type_from_file_location! - - # Filter lines from Rails gems in backtraces. config.filter_rails_from_backtrace! - # arbitrary gems may also be filtered via: - # config.filter_gems_from_backtrace("gem name") +end + +Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome) +end + +Capybara.register_driver :headless_chrome do |app| + capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( + chromeOptions: { args: %w(headless no-sandbox window-size=1200,600) } + ) + + Capybara::Selenium::Driver.new( + app, + browser: :chrome, + desired_capabilities: capabilities + ) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 697c34c..94bf118 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,50 +1,16 @@ require 'factory_bot_rails' -# This file was generated by the `rails generate rspec:install` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| config.include FactoryBot::Syntax::Methods - # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minitest - # assertions if you prefer. config.expect_with :rspec do |expectations| - # This option will default to `true` in RSpec 4. It makes the `description` - # and `failure_message` of custom matchers include text for helper methods - # defined using `chain`, e.g.: - # be_bigger_than(2).and_smaller_than(4).description - # # => "be bigger than 2 and smaller than 4" - # ...rather than: - # # => "be bigger than 2" expectations.include_chain_clauses_in_custom_matcher_descriptions = true end - # rspec-mocks config goes here. You can use an alternate test double - # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| - # Prevents you from mocking or stubbing a method that does not exist on - # a real object. This is generally recommended, and will default to - # `true` in RSpec 4. mocks.verify_partial_doubles = true + mocks.syntax = :should end - # This option will default to `:apply_to_host_groups` in RSpec 4 (and will - # have no way to turn it off -- the option exists only for backwards - # compatibility in RSpec 3). It causes shared context metadata to be - # inherited by the metadata hash of host groups and examples, rather than - # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups end From 8e6f148bda5091d4b0ab1b469c8ac827c26deec3 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:49:15 +0200 Subject: [PATCH 15/16] feat: basic styling for installations scaffold --- app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/installations.scss | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 app/assets/stylesheets/installations.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 2fc78bf..d5307d9 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,2 +1,3 @@ +@import 'installations'; @import 'foundation_and_overrides'; @import 'consulproject' diff --git a/app/assets/stylesheets/installations.scss b/app/assets/stylesheets/installations.scss new file mode 100644 index 0000000..d586bee --- /dev/null +++ b/app/assets/stylesheets/installations.scss @@ -0,0 +1,13 @@ +.installations { + .top-bar { + height: auto; + + ul { + background-color: unset; + + .button { + color: white; + } + } + } +} From a54fdd866af2afa715d0980c81959f78ed98e615 Mon Sep 17 00:00:00 2001 From: Emba Moussa Date: Fri, 31 Aug 2018 14:52:02 +0200 Subject: [PATCH 16/16] feat: feature tests for installation scaffold management --- .../installations/installations_spec.rb | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 spec/features/installations/installations_spec.rb diff --git a/spec/features/installations/installations_spec.rb b/spec/features/installations/installations_spec.rb new file mode 100644 index 0000000..4e946a2 --- /dev/null +++ b/spec/features/installations/installations_spec.rb @@ -0,0 +1,41 @@ +require 'rails_helper' + +feature 'Installations management' do + before(:each) { + create_list(:installation, 3) + + Installation.any_instance.stub(:last_commit).and_return(Faker::Date.between(2.days.ago, Date.today)) + Installation.any_instance.stub(:github).and_return(self) + Installation.any_instance.stub(:lines_diff).and_return(Faker::Number.number(2)) + Installation.any_instance.stub(:diff_url).and_return(Faker::Internet.url('github.com')) + Installation.any_instance.stub(:files_changed).and_return([Faker::File.file_name]) + } + + scenario 'Index', :js do + + visit installations_path + + expect(page).to have_link(I18n.t('helpers.link.new', model: 'Installation'), href: new_installation_path) + expect(page).to have_css "h2.installation__header--title", count: 3 + + end + + scenario 'New', :js do + visit new_installation_path + + fill_in :name.to_s.humanize, with: Faker::Lorem.sentence + fill_in :repo.to_s.humanize, with: Faker::Internet.url('github.com') + fill_in :website.to_s.humanize, with: Faker::Internet.url + fill_in :contact_name.to_s.humanize, with: Faker::Name.name_with_middle + fill_in :conact_email.to_s.humanize, with: Faker::Internet.email + fill_in :location.to_s.humanize, with: Faker::Address.full_address + find_field(:organization_type.to_s.humanize).select(I18n.t('activerecord.attributes.installation.organization_types.government')) + find_field(:status.to_s.humanize).select(I18n.t('activerecord.attributes.installation.installation_statuses.in_progress')) + fill_in :notes.to_s.humanize, with: Faker::Lorem.paragraph + + click_button I18n.t('helpers.submit.create', model: 'Installation') + + expect(page).to have_content I18n.t('installations.show.files_changed') + expect(page).to have_link I18n.t('installations.show.changes_in_github') + end +end