diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..9fa6b7d4 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,54 @@ +# The behavior of RuboCop can be controlled via the .rubocop.yml +# configuration file. It makes it possible to enable/disable +# certain cops (checks) and to alter their behavior if they accept +# any parameters. The file can be placed either in your home +# directory or in some project directory. +# +# RuboCop will start looking for the configuration file in the directory +# where the inspected file is and continue its way up to the root directory. +# +# See https://docs.rubocop.org/rubocop/configuration + +require: + - rubocop-rails + - rubocop-rspec + +AllCops: + NewCops: enable + Exclude: + - 'Gemfile' + - '**/*.rake' + - 'bin/**/*' + - 'config/**/*' + - 'db/**/*' + - 'node_modules/**/*' + - 'vendor/**/*' + - 'tmp/**/*' + - 'Rakefile' + - 'config.rb' + - 'config.ru' + +Style/Documentation: + Enabled: false + +Style/FrozenStringLiteralComment: + Enabled: false + +Style/StringLiterals: + Enabled: false + +Metrics/BlockLength: + ExcludedMethods: + - describe + - context + - factory + - define + +RSpec/ExampleLength: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false + +Style/RegexpLiteral: + AllowInnerSlashes: true diff --git a/.travis.yml b/.travis.yml index a5a875fc..7105733e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ before_script: - chmod +x ./cc-test-reporter - ./cc-test-reporter before-build script: + - docker-compose run web rubocop - docker-compose run -e "RAILS_ENV=test" web rake db:test:prepare spec after_script: - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT --prefix /refugerestrooms diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 333cc628..4a1e553e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,14 +81,27 @@ This is equivalent, but slower during a code-test-code-test development cycle: docker-compose run web rspec spec/models/restroom_spec.rb ``` -### 7 Shut down the Docker Container: +### 7 Linting Code +Ruby code is linted with [rubocop](https://docs.rubocop.org/). + +If you want to lint your code before pushing it, you can run: +``` +docker-compose run web rubocop +``` + +Some lint issues can be resolved automatically by running: +``` +docker-compose run web rubocop --auto-correct +``` + +### 8 Shut down the Docker Container: In another terminal window, run: ``` docker-compose down ``` _(Shutting down the container in this way is safer than exiting with `Ctrl + C`, and prevents issues with breaking the `db` container.)_ -### 8 Optional tasks: +### 9 Optional tasks: To clean up encoding problems in the safe2pee data, run (Use `rake db:fix_accents[dry_run]` to preview the changes.): ``` docker-compose run rake db:fixaccents diff --git a/Gemfile b/Gemfile index f93024e2..5a337314 100644 --- a/Gemfile +++ b/Gemfile @@ -42,6 +42,9 @@ group :development, :test do gem 'listen', '>= 3.0.5', '< 3.2' gem 'pry' gem 'rspec-rails' + gem 'rubocop', require: false + gem 'rubocop-rails', require: false + gem 'rubocop-rspec', require: false end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 2a72d0c6..7d1045bd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,6 +58,7 @@ GEM arbre (1.2.1) activesupport (>= 3.0.0) arel (9.0.0) + ast (2.4.1) autoprefixer-rails (9.7.5) execjs bcrypt (3.1.13) @@ -234,6 +235,9 @@ GEM nokogiri (1.10.10) mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) + parallel (1.19.2) + parser (2.7.2.0) + ast (~> 2.4.1) pg (1.2.3) pg_search (2.3.2) activerecord (>= 5.2) @@ -285,6 +289,7 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) + rainbow (3.0.0) rake (13.0.1) rakismet (1.5.4) ransack (2.3.2) @@ -300,6 +305,7 @@ GEM responders (3.0.0) actionpack (>= 5.0) railties (>= 5.0) + rexml (3.2.4) rspec-core (3.9.1) rspec-support (~> 3.9.1) rspec-expectations (3.9.1) @@ -317,6 +323,24 @@ GEM rspec-mocks (~> 3.9) rspec-support (~> 3.9) rspec-support (3.9.2) + rubocop (0.92.0) + parallel (~> 1.10) + parser (>= 2.7.1.5) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.7) + rexml + rubocop-ast (>= 0.5.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.7.1) + parser (>= 2.7.1.5) + rubocop-rails (2.8.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 0.87.0) + rubocop-rspec (1.43.2) + rubocop (~> 0.87) + ruby-progressbar (1.10.1) ruby2_keywords (0.0.2) ruby_dep (1.5.0) safe_yaml (1.0.5) @@ -360,6 +384,7 @@ GEM thread_safe (~> 0.1) uglifier (4.2.0) execjs (>= 0.3.0, < 3) + unicode-display_width (1.7.0) unicode_utils (1.4.0) warden (1.2.8) rack (>= 2.0.6) @@ -418,6 +443,9 @@ DEPENDENCIES rails (= 5.2.4.4) rakismet rspec-rails + rubocop + rubocop-rails + rubocop-rspec sassc-rails sdoc simple_form (~> 5.0) diff --git a/app/admin/admin_user.rb b/app/admin/admin_user.rb index a9fb2471..51833526 100644 --- a/app/admin/admin_user.rb +++ b/app/admin/admin_user.rb @@ -12,12 +12,11 @@ filter :email form do |f| - f.inputs "Admin Details" do + f.inputs 'Admin Details' do f.input :email f.input :password f.input :password_confirmation end f.actions end - end diff --git a/app/admin/dashboard.rb b/app/admin/dashboard.rb index 60837575..4a71bfcd 100644 --- a/app/admin/dashboard.rb +++ b/app/admin/dashboard.rb @@ -1,12 +1,11 @@ ActiveAdmin.register_page "Dashboard" do + menu priority: 1, label: proc { I18n.t('active_admin.dashboard') } - menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") } - - content :title => proc{ I18n.t("active_admin.dashboard") } do - div :class => "blank_slate_container", :id => "dashboard_default_message" do - span :class => "blank_slate" do - span I18n.t("active_admin.dashboard_welcome.welcome") - small I18n.t("active_admin.dashboard_welcome.call_to_action") + content title: proc { I18n.t('active_admin.dashboard') } do + div class: 'blank_slate_container', id: 'dashboard_default_message' do + span class: 'blank_slate' do + span I18n.t('active_admin.dashboard_welcome.welcome') + small I18n.t('active_admin.dashboard_welcome.call_to_action') end end @@ -29,5 +28,5 @@ # end # end # end - end # content + end end diff --git a/app/admin/restroom.rb b/app/admin/restroom.rb index 150bd599..97933525 100644 --- a/app/admin/restroom.rb +++ b/app/admin/restroom.rb @@ -1,5 +1,4 @@ ActiveAdmin.register Restroom do - -permit_params :name, :street, :city, :state, :accessible, :changing_table, :unisex, :directions, - :comment, :latitude, :longitude, :country, :edit_id, :approved + permit_params :name, :street, :city, :state, :accessible, :changing_table, :unisex, :directions, + :comment, :latitude, :longitude, :country, :edit_id, :approved end diff --git a/app/controllers/api/docs_controller.rb b/app/controllers/api/docs_controller.rb index f2638dc8..f222a264 100644 --- a/app/controllers/api/docs_controller.rb +++ b/app/controllers/api/docs_controller.rb @@ -1,4 +1,5 @@ -class Api::DocsController < ApplicationController - def index +module Api + class DocsController < ApplicationController + def index; end end end diff --git a/app/controllers/api/v1/restrooms.rb b/app/controllers/api/v1/restrooms.rb index 3cfa0c08..1b050e3e 100644 --- a/app/controllers/api/v1/restrooms.rb +++ b/app/controllers/api/v1/restrooms.rb @@ -7,6 +7,7 @@ class Restrooms < Grape::API version 'v1' format :json + # rubocop:disable Metrics/BlockLength resource :restrooms do desc "Get all restroom records ordered by date descending." params do @@ -49,14 +50,18 @@ class Restrooms < Grape::API r = r.current r = r.accessible if params[:ada].present? r = r.unisex if params[:unisex] - paginate(r.near([params[:lat], params[:lng]], 20, :order => 'distance')) + paginate(r.near([params[:lat], params[:lng]], 20, order: 'distance')) end desc "Search for restroom records updated or created on or after a given date" params do optional :ada, type: Boolean, desc: "Only return restrooms that are ADA accessible." optional :unisex, type: Boolean, desc: "Only return restrooms that are unisex." - optional :updated, type: Boolean, desc: "Return restroom records updated (rather than created) since given date" + optional( + :updated, + type: Boolean, + desc: "Return restroom records updated (rather than created) since given date" + ) requires :day, type: Integer, desc: "Day" requires :month, type: Integer, desc: "Month" requires :year, type: Integer, desc: "Year" @@ -65,16 +70,17 @@ class Restrooms < Grape::API r = Restroom r = r.current date = Date.new(params[:year], params[:month], params[:day]) - if params[:updated] - r = r.updated_since(date) - else - r = r.created_since(date) - end + r = if params[:updated] + r.updated_since(date) + else + r.created_since(date) + end r = r.accessible if params[:ada].present? r = r.unisex if params[:unisex].present? paginate(r.order(created_at: :desc)) end end + # rubocop:enable Metrics/BlockLength end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 103cf92c..08fd6fd9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,8 +9,7 @@ def mobile_filter_header @mobile = true end - def set_locale - I18n.locale = http_accept_language.language_region_compatible_from(I18n.available_locales) - end - + def set_locale + I18n.locale = http_accept_language.language_region_compatible_from(I18n.available_locales) + end end diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index 36719daf..3af59a29 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -5,6 +5,8 @@ def new @contact = Contact.new(restroom_id: params['restroom_id'], restroom_name: params['restroom_name']) end + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength def create @contact = Contact.new(params[:contact]) unless @contact.valid? @@ -26,4 +28,6 @@ def create flash.now[:error] = nil flash.now[:notice] = I18n.t('contacts.submitted.thank-you-exclamation') end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength end diff --git a/app/controllers/restrooms_controller.rb b/app/controllers/restrooms_controller.rb index e183c1bb..8ac83d2d 100644 --- a/app/controllers/restrooms_controller.rb +++ b/app/controllers/restrooms_controller.rb @@ -1,11 +1,12 @@ require_relative '../helpers/recaptcha_helper' +# rubocop:disable Metrics/ClassLength class RestroomsController < ApplicationController respond_to :html, :json before_action :restrooms_filters, only: [:index] before_action :list_restrooms, only: [:index] - before_action :find_restroom, only: [:show, :update, :edit, :destroy] + before_action :find_restroom, only: %i[show update edit] def index if params[:nearby] @@ -15,6 +16,7 @@ def index end end + # rubocop:disable Metrics/MethodLength def new if params[:edit_id] @restroom = find_restroom @@ -28,7 +30,12 @@ def new @restroom = Restroom.new end end + # rubocop:enable Metrics/MethodLength + def show; end + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength def create @restroom = Restroom.new(permitted_params) @@ -58,12 +65,18 @@ def create render 'new' end end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + def edit; end + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength def update if params[:restroom][:downvote] - Restroom.increment_counter(:downvote, @restroom.id) + Restroom.increment_counter(:downvote, @restroom.id) # rubocop:disable Rails/SkipsModelValidations elsif params[:restroom][:upvote] - Restroom.increment_counter(:upvote, @restroom.id) + Restroom.increment_counter(:upvote, @restroom.id) # rubocop:disable Rails/SkipsModelValidations elsif @restroom.update(permitted_params) flash[:notice] = I18n.t('restroom.flash.updated') else @@ -73,35 +86,38 @@ def update redirect_to @restroom end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + private -private def restrooms_filters @filters = params - .fetch(:filters, '') - .split(',') - .reduce({}) do |filters, filter| - filters[filter] = true if ['accessible', 'changing_table', 'unisex'].include?(filter) - - filters - end + .fetch(:filters, '') + .split(',') + .each_with_object({}) do |filter, filters| + filters[filter] = true if %w[accessible changing_table unisex].include?(filter) + end end + # rubocop:disable Metrics/AbcSize def list_restrooms @restrooms = Restroom.current.where(@filters).page(params[:page]) @restrooms = if params[:search].present? || params[:map] == "1" - @restrooms.near([params[:lat], params[:long]], 20, :order => 'distance') + @restrooms.near([params[:lat], params[:long]], 20, order: 'distance') else @restrooms.reverse_order end @restrooms = @restrooms.out_of_range? ? @restrooms.page(1) : @restrooms end + # rubocop:enable Metrics/AbcSize def display_errors if @restroom.errors.any? - errors = @restroom.errors.each do |attribute, message| + @restroom.errors.each do flash[:alert] = I18n.t('restroom.flash.field') end else @@ -113,6 +129,7 @@ def find_restroom @restroom = Restroom.find(params[:id]) end + # rubocop:disable Metrics/MethodLength def permitted_params params.require(:restroom).permit( :name, @@ -131,4 +148,6 @@ def permitted_params :approved ) end + # rubocop:enable Metrics/MethodLength end +# rubocop:enable Metrics/ClassLength diff --git a/app/helpers/recaptcha_helper.rb b/app/helpers/recaptcha_helper.rb index fb026f2d..de995d60 100644 --- a/app/helpers/recaptcha_helper.rb +++ b/app/helpers/recaptcha_helper.rb @@ -4,6 +4,16 @@ module RecaptchaHelper def self.valid_token?(token) + json_body = verify(token) + + if json_body['success'] + true + else + false + end + end + + def self.verify(token) # Get secret from env secret = ENV['RECAPTCHA_SECRET_KEY'] @@ -14,12 +24,6 @@ def self.valid_token?(token) https.request(request) end - # Check response - json_body = JSON.parse(response.body) - if json_body['success'] - true - else - false - end + JSON.parse(response.body) end end diff --git a/app/models/contact.rb b/app/models/contact.rb index 6f1f12d3..b6c4835c 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -1,27 +1,27 @@ class Contact < MailForm::Base - attribute :name, :validate => true - attribute :email, :validate => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i - attribute :restroom_id, :allow_blank => true - attribute :restroom_name, :allow_blank => true + attribute :name, validate: true + attribute :email, validate: /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i # rubocop:disable Style/RedundantRegexpEscape, Style/RedundantRegexpCharacterClass + attribute :restroom_id, allow_blank: true + attribute :restroom_name, allow_blank: true validate :restroom_must_exist attribute :message - attribute :nickname, :captcha => true + attribute :nickname, captcha: true def restroom_must_exist - if restroom_id.present? - if Restroom.where(:id => restroom_id, :name => restroom_name).blank? - errors.add(:base, "Must be valid restroom ID and Name") - end - end + return if restroom_id.blank? + return if Restroom.exists?(id: restroom_id, name: restroom_name) + + errors.add(:base, "Must be valid restroom ID and Name") end + # Declare the e-mail headers. It accepts anything the mail method # in ActionMailer accepts. def headers { - :subject => "My Contact Form #{restroom_id}", - :to => "refugerestrooms@gmail.com", - :from => %("#{name}" <#{email}>), # :from overriden by google smtp config - :reply_to => %("#{name}" <#{email}>) + subject: "My Contact Form #{restroom_id}", + to: "refugerestrooms@gmail.com", + from: %("#{name}" <#{email}>), # :from overriden by google smtp config + reply_to: %("#{name}" <#{email}>) } end end diff --git a/app/models/rating_level.rb b/app/models/rating_level.rb index 906f3f44..a04bee46 100644 --- a/app/models/rating_level.rb +++ b/app/models/rating_level.rb @@ -3,11 +3,11 @@ def self.for_restroom(restroom) percentage = restroom.rating_percentage if percentage > 70 - self.green + green elsif percentage > 50 - self.yellow + yellow else - self.red + red end end diff --git a/app/models/restroom.rb b/app/models/restroom.rb index 85643d35..6406d52a 100644 --- a/app/models/restroom.rb +++ b/app/models/restroom.rb @@ -3,19 +3,21 @@ # (accessible) is coded by 1 class Restroom < ApplicationRecord - include PgSearch::Model - pg_search_scope :search, against: { - :name => 'A', - :street => 'B', - :city => 'C', - :state => 'D', - :comment => 'B', - :directions => 'B', - :country => 'D', - }, - using: {tsearch: {dictionary: "english"}}, - ignoring: :accents + pg_search_scope( + :search, + against: { + name: 'A', + street: 'B', + city: 'C', + state: 'D', + comment: 'B', + directions: 'B', + country: 'D' + }, + using: { tsearch: { dictionary: "english" } }, + ignoring: :accents + ) validates :name, :street, :city, :state, presence: true @@ -23,7 +25,8 @@ class Restroom < ApplicationRecord after_validation :perform_geocoding reverse_geocoded_by :latitude, :longitude do |obj, results| - if geo = results.first + geo = results.first + if geo obj.name = geo.address obj.street = geo.address.split(',').first obj.city = geo.city @@ -39,7 +42,7 @@ class Restroom < ApplicationRecord after_find :strip_slashes - scope :current, -> { + scope :current, lambda { Restroom.where('id IN (SELECT MAX(id) FROM restrooms WHERE approved = true GROUP BY edit_id)') } @@ -55,13 +58,13 @@ def full_address end def rated? - upvote > 0 || downvote > 0 + upvote.positive? || downvote.positive? end def rating_percentage return 0 unless rated? - upvote.to_f / (upvote + downvote).to_f * 100 + upvote.to_f / (upvote + downvote) * 100 end # PostgreSQL Full-Text Search for the API. @@ -75,15 +78,16 @@ def self.text_search(query) private - def strip_slashes - ['name', 'street', 'city', 'state', 'comment', 'directions'].each do |field| - attributes[field].try(:gsub!, "\\'", "'") - end + def strip_slashes + %w[name street city state comment directions].each do |field| + attributes[field].try(:gsub!, "\\'", "'") end + end - def perform_geocoding - return true if Rails.env == "test" - return true if ENV["SEEDING_DONT_GEOCODE"] - geocode - end + def perform_geocoding + return true if Rails.env.test? + return true if ENV["SEEDING_DONT_GEOCODE"] + + geocode + end end diff --git a/app/services/save_restroom.rb b/app/services/save_restroom.rb index 97a5edac..e7f7a293 100644 --- a/app/services/save_restroom.rb +++ b/app/services/save_restroom.rb @@ -9,9 +9,7 @@ def call else Restroom.transaction do @restroom.save - if @restroom.approved? - @restroom.update(edit_id: @restroom.id) - end + @restroom.update(edit_id: @restroom.id) if @restroom.approved? end end @restroom diff --git a/features/step_definitions/edit_steps.rb b/features/step_definitions/edit_steps.rb index 6aee7dc3..0fa4fb75 100644 --- a/features/step_definitions/edit_steps.rb +++ b/features/step_definitions/edit_steps.rb @@ -1,5 +1,13 @@ -Given(/^I am on the restroom page for id 1$/) do - FactoryBot.create(:restroom, {id: 1, name: 'Winnipeg restroom', street: '91 Albert St.', city: 'Winnipeg', state: 'MB', country: 'Canada'}.merge(locations[:Winnipeg])) +Given(/^I am on the restroom page for id 1$/) do + FactoryBot.create( + :restroom, + id: 1, + name: 'Winnipeg restroom', + street: '91 Albert St.', + city: 'Winnipeg', + state: 'MB', + country: 'Canada'.merge(locations[:Winnipeg]) + ) visit '/restrooms/1' end @@ -8,7 +16,15 @@ end Given(/^I visit the edit page for 'Winnepeg restroom'$/) do - FactoryBot.create(:restroom, {id: 1, name: 'Winnipeg restroom', street: '91 Albert St.', city: 'Winnipeg', state: 'MB', country: 'Canada'}.merge(locations[:Winnipeg])) + FactoryBot.create( + :restroom, + id: 1, + name: 'Winnipeg restroom', + street: '91 Albert St.', + city: 'Winnipeg', + state: 'MB', + country: 'Canada'.merge(locations[:Winnipeg]) + ) visit '/restrooms/new?edit_id=1&restroom_id=1' end @@ -16,15 +32,21 @@ expect(page).to have_content("684 East hastings") end -Given(/^I submit an edit to 'Winnepeg Restroom'$/) do - FactoryBot.create(:restroom, {id: 1, name: 'Winnipeg restroom', street: '91 Albert St.', city: 'Winnipeg', state: 'MB', country: 'Canada'}.merge(locations[:Winnipeg])) +Given(/^I submit an edit to 'Winnepeg Restroom'$/) do + FactoryBot.create( + :restroom, + id: 1, + name: 'Winnipeg restroom', + street: '91 Albert St.', + city: 'Winnipeg', + state: 'MB', + country: 'Canada'.merge(locations[:Winnipeg]) + ) visit '/restrooms/new?edit_id=1&restroom_id=1' - fill_in'restroom[name]', with: 'Not Winnepeg restroom' + fill_in 'restroom[name]', with: 'Not Winnepeg restroom' click_button "Save Restroom" end Then(/^I should see that the edit has been submitted$/) do expect(page).to have_content("Your edit has been submitted. We will review it and update the listing") end - - diff --git a/spec/api/v1/restrooms_spec.rb b/spec/api/v1/restrooms_spec.rb index 8dd2ea53..98e305e2 100644 --- a/spec/api/v1/restrooms_spec.rb +++ b/spec/api/v1/restrooms_spec.rb @@ -12,9 +12,8 @@ json.each do |rest_json| restroom = Restroom.find(rest_json['id']) expect(restroom.valid?).to be true - if previous_record.present? - expect(restroom.created_at).to be >= previous_record.created_at - end + # TODO: this assertion doesn't seem to ever run + expect(restroom.created_at).to be >= previous_record.created_at if previous_record.present? end end @@ -45,8 +44,8 @@ expect(response.header['X-Total']).to eq('15') end - context 'filters' do - before :each do + describe 'filters' do + before do create_list(:restroom, 5) create_list(:unisex_restroom, 5) create_list(:ada_restroom, 5) @@ -55,8 +54,8 @@ let(:json) { JSON.parse(response.body) } - context 'a list of unisex restrooms' do - before :each do + context 'when requesting a list of unisex restrooms' do + before do get '/api/v1/restrooms', params: { unisex: true } end @@ -73,8 +72,8 @@ end end - context 'a list of restrooms by ADA availability' do - before :each do + context 'when requesting a list of restrooms by ADA availability' do + before do get '/api/v1/restrooms', params: { ada: true } end @@ -101,7 +100,7 @@ get '/api/v1/restrooms/search', params: { query: 'Coffee Shop' } json = JSON.parse(response.body) expect(json.length).to eq(2) - json.each do |restroom| + json.each do expect(json[0]['name']).to match(/Coffee Shop/) end @@ -133,8 +132,8 @@ expect(response.header['X-Total']).to eq('15') end - context "queries" do - before :each do + describe "queries" do + before do create(:restroom) create(:unisex_restroom, name: 'Frankie\'s Coffee Shop') create(:ada_restroom, name: 'Hipster Coffee Shop') @@ -143,8 +142,8 @@ let(:json) { JSON.parse(response.body) } - context 'filters a full-text searched list of restrooms by unisex type' do - before :each do + context 'when looking for unisex restrooms and given a search query' do + before do get '/api/v1/restrooms/search', params: { query: 'Coffee', unisex: true } end @@ -165,8 +164,8 @@ end end - context 'filters a full-text searched list of restrooms by ADA availability' do - before :each do + context 'when searching for ADA accessible restrooms and given a search query' do + before do get '/api/v1/restrooms/search', params: { query: 'Coffee', ada: true } end @@ -187,10 +186,16 @@ end end - context "filters a list of restrooms by updated date" do - before :each do + context "when looking for restrooms by updated date" do + before do create(:restroom, created_at: 1.day.ago) - get "/api/v1/restrooms/by_date", params: { updated: true, day: Date.today.day, month: Date.today.month, year: Date.today.year } + params = { + updated: true, + day: Time.current.day, + month: Time.current.month, + year: Time.current.year + } + get "/api/v1/restrooms/by_date", params: params end it "is successful" do @@ -202,10 +207,15 @@ end end - context "filters a list of restrooms by created date" do - before :each do + context "when filtering by created date" do + before do create(:restroom, created_at: 1.week.ago) - get "/api/v1/restrooms/by_date", params: { day: Date.today.day, month: Date.today.month, year: Date.today.year } + params = { + day: Time.current.day, + month: Time.current.month, + year: Time.current.year + } + get "/api/v1/restrooms/by_date", params: params end it "is successful" do diff --git a/spec/controllers/pages_controller_spec.rb b/spec/controllers/pages_controller_spec.rb index d1f56b1f..e4c850d5 100644 --- a/spec/controllers/pages_controller_spec.rb +++ b/spec/controllers/pages_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe PagesController, type: :controller do - it "should get index" do +describe PagesController, type: :controller do + it "#index" do get :index assert_response :success end diff --git a/spec/controllers/restrooms_controller_spec.rb b/spec/controllers/restrooms_controller_spec.rb index 686a5b98..7d7f4a59 100644 --- a/spec/controllers/restrooms_controller_spec.rb +++ b/spec/controllers/restrooms_controller_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper' describe RestroomsController, type: :controller do - it "should get index" do + it "#index" do get :index assert_response :success end - context "voting" do + describe "voting" do let(:restroom) { FactoryBot.create(:restroom) } - it "should downvote" do + it "can downvote" do post_params = { id: restroom.id, restroom: { @@ -17,12 +17,12 @@ } } - expect { + expect do post :update, params: post_params - }.to change { restroom.reload.downvote }.by 1 + end.to change { restroom.reload.downvote }.by 1 end - it "should upvote" do + it "can upvote" do post_params = { id: restroom.id, restroom: { @@ -30,9 +30,9 @@ } } - expect { + expect do post :update, params: post_params - }.to change { restroom.reload.upvote }.by 1 + end.to change { restroom.reload.upvote }.by 1 end end end diff --git a/spec/factories/restrooms.rb b/spec/factories/restrooms.rb index 93f654ca..d6bdebe8 100644 --- a/spec/factories/restrooms.rb +++ b/spec/factories/restrooms.rb @@ -1,60 +1,59 @@ FactoryBot.define do factory :restroom do - name 'The SF LGBT Center' - street '1800 Market St' - city 'San Francisco' - state 'CA' - country 'US' - upvote 22 - downvote 11 - comment 'Comment' - directions 'Direction' - approved true + name { 'The SF LGBT Center' } + street { '1800 Market St' } + city { 'San Francisco' } + state { 'CA' } + country { 'US' } + upvote { 22 } + downvote { 11 } + comment { 'Comment' } + directions { 'Direction' } + approved { true } after(:create) do |restroom| restroom.update(edit_id: restroom.id) end trait :geocoded do - latitude 37.7749 - longitude -122.4194 + latitude { 37.7749 } + longitude { -122.4194 } end trait :unisex do - unisex true + unisex { true } end trait :ada do - accessible true + accessible { true } end trait :comment do - comment 'Spacious, single-stall with auto-flushing toilet and ADA railings.' + comment { 'Spacious, single-stall with auto-flushing toilet and ADA railings.' } end trait :directions do - directions 'Near the back, past the counter on the left.' + directions { 'Near the back, past the counter on the left.' } end factory :unisex_restroom, traits: [:unisex] factory :ada_restroom, traits: [:ada] - factory :unisex_and_ada_restroom, traits: [:unisex, :ada] + factory :unisex_and_ada_restroom, traits: %i[unisex ada] factory :oakland_restroom do - name 'Some Cafe' - street '1400 Broadway' - city 'Oakland' - state 'CA' - country 'US' + name { 'Some Cafe' } + street { '1400 Broadway' } + city { 'Oakland' } + state { 'CA' } + country { 'US' } end factory :spam_restroom do - name 'Spam Cafe' - street 'Spam Street' - city 'Spam City' - state 'Spam State' - country 'Spam Country' + name { 'Spam Cafe' } + street { 'Spam Street' } + city { 'Spam City' } + state { 'Spam State' } + country { 'Spam Country' } end end end - diff --git a/spec/features/contacts_spec.rb b/spec/features/contacts_spec.rb index 3752214c..b3a6b89f 100644 --- a/spec/features/contacts_spec.rb +++ b/spec/features/contacts_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' describe 'the contact process', type: :feature do - it 'should show a generic contact when contact is not from restroom form' do + it 'shows a generic contact when contact is not from restroom form' do restroom = create(:restroom, name: "Mission Creek Cafe") visit restroom_path restroom click_link 'Contact' - expect(page).to_not have_content('Mission Creek Cafe') + expect(page).not_to have_content('Mission Creek Cafe') end end diff --git a/spec/features/restrooms_spec.rb b/spec/features/restrooms_spec.rb index ea448610..6298be5c 100644 --- a/spec/features/restrooms_spec.rb +++ b/spec/features/restrooms_spec.rb @@ -1,142 +1,143 @@ require 'spec_helper' -describe 'the restroom submission process', type: :feature, js: true do - it 'should add a restroom when submitted' do - visit root_path - click_link "Submit a New Restroom" - fill_in "restroom[name]", with: "Vancouver restroom" - fill_in "restroom[street]", with: "684 East Hastings" - fill_in "restroom[city]", with: "Vancouver" - fill_in "restroom[state]", with: "British Columbia" - find(:select, "Country").first(:option, "Canada").select_option - click_button "Save Restroom" - - expect(page).to have_content("A new restroom entry has been created for") +describe 'restrooms', type: :feature, js: true do + describe 'submission' do + it 'adds a restroom when submitted' do + visit root_path + click_link "Submit a New Restroom" + fill_in "restroom[name]", with: "Vancouver restroom" + fill_in "restroom[street]", with: "684 East Hastings" + fill_in "restroom[city]", with: "Vancouver" + fill_in "restroom[state]", with: "British Columbia" + find(:select, "Country").first(:option, "Canada").select_option + click_button "Save Restroom" + + expect(page).to have_content("A new restroom entry has been created for") + end + + it 'blocks a spam submission' do + visit root_path + click_link 'Submit a New Restroom' + fill_in 'restroom[name]', with: 'Spam restroom' + fill_in 'restroom[street]', with: 'Spamstreet' + fill_in 'restroom[city]', with: 'Spamland' + fill_in 'restroom[state]', with: 'Spamstate' + find('#restroom_country').find(:xpath, "option[contains(., 'Canada')][1]").select_option + click_button 'Save Restroom' + + expect(page).to have_content("Your submission was rejected as spam.") + end + + # it "should guess my location" do + # visit "/" + # click_link "Submit a New Restroom" + # mock_location("Oakland") + + # find(".guess-btn").click + + # expect(page).to have_field('restroom[street]', with: "1400 Broadway") + # expect(page).to have_field('restroom[city]', with: "Oakland") + # expect(page).to have_field('restroom[state]', with: "CA") + # end end - it 'should block a spam submission' do - visit root_path - click_link 'Submit a New Restroom' - fill_in 'restroom[name]', with: 'Spam restroom' - fill_in 'restroom[street]', with: 'Spamstreet' - fill_in 'restroom[city]', with: 'Spamland' - fill_in 'restroom[state]', with: 'Spamstate' - find('#restroom_country').find(:xpath, "option[contains(., 'Canada')][1]").select_option - click_button 'Save Restroom' - - expect(page).to have_content("Your submission was rejected as spam.") - end - - #it "should guess my location" do - # visit "/" - # click_link "Submit a New Restroom" - # mock_location("Oakland") - - # find(".guess-btn").click + describe 'search' do + it 'searches for text from the splash page' do + create(:restroom, :geocoded, name: 'Mission Creek Cafe') - # expect(page).to have_field('restroom[street]', with: "1400 Broadway") - # expect(page).to have_field('restroom[city]', with: "Oakland") - # expect(page).to have_field('restroom[state]', with: "CA") - #end -end + visit root_path + fill_in 'search', with: 'San Francisco' + click_on 'Search' -describe 'the restroom search process', type: :feature, js: true do - it 'should search for text from the splash page' do - create(:restroom, :geocoded, name: 'Mission Creek Cafe') + expect(page).to have_content 'Mission Creek Cafe' + end - visit root_path - fill_in 'search', with: 'San Francisco' - click_on 'Search' + it 'can search for location from the splash page' do + create(:oakland_restroom, name: "Some Cafe") - expect(page).to have_content 'Mission Creek Cafe' - end + visit root_path + mock_location "Oakland" + click_on 'Search by Current Location' - it 'should search for location from the splash page' do - create(:oakland_restroom, name: "Some Cafe") + expect(page).not_to have_content 'Some Cafe' + end - visit root_path - mock_location "Oakland" - click_on 'Search by Current Location' + it 'can search from the splash page with a screen reader' do + visit root_path - expect(page).to_not have_content 'Some Cafe' - end + expect(find('button.submit-search-button')['aria-label']).to be_truthy + expect(find('button.current-location-button')['aria-label']).to be_truthy + end - it 'should search from the splash page with a screen reader' do - visit root_path + it 'displays a map' do + create(:oakland_restroom) - expect(find('button.submit-search-button')['aria-label']).to be_truthy - expect(find('button.current-location-button')['aria-label']).to be_truthy - end + visit root_path + mock_location "Oakland" + find('.current-location-button').click + # TODO: Figure out why this isn't working. + # print page.html + page.has_css?(".mapToggle", visible: true) + # find('.mapToggle').click + # print page.html - it 'should display a map' do - create(:oakland_restroom) - - visit root_path - mock_location "Oakland" - find('.current-location-button').click - # TODO: Figure out why this isn't working. - # print page.html - page.has_css?(".mapToggle", :visible => true) - # find('.mapToggle').click - # print page.html - - # TODO: Figure Out why This isn't working either - # page.has_css?(#) - # expect(page).to have_css('#mapArea.loaded') - # expect(page).to have_css('#mapArea .numberCircleText') + # TODO: Figure Out why This isn't working either + # page.has_css?(#) + # expect(page).to have_css('#mapArea.loaded') + # expect(page).to have_css('#mapArea .numberCircleText') + end end -end - -describe 'the preview process', type: :feature, js: true do - it 'should preview a restroom before submitting' do - visit "/" - click_link "Submit a New Restroom" - fill_in "restroom[name]", with: "Vancouver restroom" - fill_in "restroom[street]", with: "684 East Hastings" - fill_in "restroom[city]", with: "Vancouver" - fill_in "restroom[state]", with: "British Columbia" - find(:select, "Country").first(:option, "Canada").select_option + describe 'preview' do + it 'can preview a restroom before submitting' do + visit "/" + click_link "Submit a New Restroom" + fill_in "restroom[name]", with: "Vancouver restroom" + fill_in "restroom[street]", with: "684 East Hastings" + fill_in "restroom[city]", with: "Vancouver" + fill_in "restroom[state]", with: "British Columbia" + find(:select, "Country").first(:option, "Canada").select_option - click_on "Preview" + click_on "Preview" - expect(page).to have_css("div#mapArea", :visible => true) + expect(page).to have_css("div#mapArea", visible: :visible) + end end -end -describe 'the nearby restroom display process', type: :feature, js: true do - it 'should show nearby restrooms when they exist' do - create(:oakland_restroom) - visit "/" - click_link "Submit a New Restroom" - mock_location "Oakland" + describe 'nearby restroom' do + it 'shows nearby restrooms when they exist' do + create(:oakland_restroom) + visit "/" + click_link "Submit a New Restroom" + mock_location "Oakland" - find(".guess-btn").click + find(".guess-btn").click - page.has_css?(".nearby-container .listItem", :visible => true) - end + page.has_css?(".nearby-container .listItem", visible: :visible) + end - it "should not show nearby restrooms when they don't exist" do - visit "/" - click_link "Submit a New Restroom" - mock_location "Oakland" + it "does not show nearby restrooms when they don't exist" do + visit "/" + click_link "Submit a New Restroom" + mock_location "Oakland" - find(".guess-btn").click + find(".guess-btn").click - page.has_css?(".nearby-container .none", :visible => true) + page.has_css?(".nearby-container .none", visible: :visible) + end end -end -describe "the edit process", type: :feature do - it "should create an edit listing" do - restroom = create(:restroom) - visit "/restrooms/#{restroom.id}" - click_link "Propose an edit to this listing." + describe "edit" do + it "creates an edit listing" do + restroom = create(:restroom) + visit "/restrooms/#{restroom.id}" + click_link "Propose an edit to this listing." - fill_in "restroom[directions]", with: "This is an edit" - click_on "Save Restroom" + fill_in "restroom[directions]", with: "This is an edit" + click_on "Save Restroom" - expect(page).to have_content("Your edit has been submitted.") - expect(Restroom.where(edit_id: restroom.id).size).to eq(2) + expect(page).to have_content("Your edit has been submitted.") + expect(Restroom.where(edit_id: restroom.id).size).to eq(2) + end end end diff --git a/spec/models/rating_level_spec.rb b/spec/models/rating_level_spec.rb index 21f9b4e6..fe381a91 100644 --- a/spec/models/rating_level_spec.rb +++ b/spec/models/rating_level_spec.rb @@ -4,22 +4,22 @@ describe '.for_restroom' do it 'returns green level for restrooms with a rating higher than 70%' do restroom = Restroom.new upvote: 71, downvote: 29 - expect(RatingLevel.for_restroom(restroom)).to eq RatingLevel.green + expect(described_class.for_restroom(restroom)).to eq described_class.green end it 'returns red level for restrooms with a rating up to 50%' do restroom = Restroom.new upvote: 50, downvote: 50 - expect(RatingLevel.for_restroom(restroom)).to eq RatingLevel.red + expect(described_class.for_restroom(restroom)).to eq described_class.red end it 'returns yellow level for restrooms with a rating of 51%' do restroom = Restroom.new upvote: 51, downvote: 49 - expect(RatingLevel.for_restroom(restroom)).to eq RatingLevel.yellow + expect(described_class.for_restroom(restroom)).to eq described_class.yellow end it 'returns yellow level for restrooms with a rating of 70%' do restroom = Restroom.new upvote: 70, downvote: 30 - expect(RatingLevel.for_restroom(restroom)).to eq RatingLevel.yellow + expect(described_class.for_restroom(restroom)).to eq described_class.yellow end end end diff --git a/spec/models/restroom_spec.rb b/spec/models/restroom_spec.rb index b2e05bb4..de23c024 100644 --- a/spec/models/restroom_spec.rb +++ b/spec/models/restroom_spec.rb @@ -1,71 +1,69 @@ require 'spec_helper' describe Restroom do - let (:restroom) { Restroom.new } + let(:restroom) { described_class.new } describe '#rated?' do - let (:unrated_restroom) { Restroom.new } - let (:rated_restroom) { Restroom.new(upvote: 1) } + let(:unrated_restroom) { described_class.new } + let(:rated_restroom) { described_class.new(upvote: 1) } - specify { expect(rated_restroom.rated?).to be_truthy } - specify { expect(unrated_restroom.rated?).to be_falsey } + specify { expect(rated_restroom).to be_rated } + specify { expect(unrated_restroom).not_to be_rated } end describe '#rating_percentage' do - context 'it returns the rating percentage' do - it 'should return 0 when there are no votes' do - expect(restroom.rating_percentage).to eq 0 - end - - it "should return zero if there are no upvotes" do - expect(Restroom.new(upvote: 0, downvote: 1).rating_percentage).to eq 0 - end - - it "should return 50% if upvotes equal downvotes" do - expect(Restroom.new(upvote: 1, downvote: 1).rating_percentage).to eq 50 - end - - it "should return 100% if there are upvotes and no downvotes" do - expect(Restroom.new(upvote: 1, downvote: 0).rating_percentage).to eq 100 - end + it 'returns 0 when there are no votes' do + expect(restroom.rating_percentage).to eq 0 + end + + it "returns zero if there are no upvotes" do + expect(described_class.new(upvote: 0, downvote: 1).rating_percentage).to eq 0 + end + + it "returns 50% if upvotes equal downvotes" do + expect(described_class.new(upvote: 1, downvote: 1).rating_percentage).to eq 50 + end + + it "returns 100% if there are upvotes and no downvotes" do + expect(described_class.new(upvote: 1, downvote: 0).rating_percentage).to eq 100 end end describe '#unisex?' do - it { expect(Restroom.new.unisex?).to be false } - it { expect(Restroom.new(unisex: true).unisex?).to be true } + it { expect(described_class.new.unisex?).to be false } + it { expect(described_class.new(unisex: true).unisex?).to be true } end describe '#accessible?' do - it { expect(Restroom.new.accessible?).to be false } - it { expect(Restroom.new(accessible: true).accessible?).to be true } + it { expect(described_class.new.accessible?).to be false } + it { expect(described_class.new(accessible: true).accessible?).to be true } end describe '#changing_table?' do - it { expect(Restroom.new.changing_table?).to be false } - it { expect(Restroom.new(changing_table: true).changing_table?).to be true } + it { expect(described_class.new.changing_table?).to be false } + it { expect(described_class.new(changing_table: true).changing_table?).to be true } end describe '.current' do - it 'should return active listings' do + it 'returns active listings' do create(:restroom, directions: "Most Recent") edit = create(:restroom) edit.update(approved: false, edit_id: 2) - restrooms = Restroom.current + restrooms = described_class.current expect(restrooms.size).to eq(1) expect(restrooms.first.directions).to eq("Most Recent") end - it 'should return most recent edit approved' do + it 'returns most recent edit approved' do restroom = create(:restroom, id: 1, edit_id: 1) edit1 = create(:restroom, id: 2, approved: true, directions: "Most Recent") edit1.update(edit_id: restroom.id) edit2 = create(:restroom, id: 3, directions: "Not approved", approved: false) edit2.update(edit_id: restroom.id) - restrooms = Restroom.current + restrooms = described_class.current expect(restrooms.size).to eq(1) expect(restrooms.first.directions).to eq("Most Recent") diff --git a/spec/services/save_restroom_spec.rb b/spec/services/save_restroom_spec.rb index 0383f0b7..933eaeb8 100644 --- a/spec/services/save_restroom_spec.rb +++ b/spec/services/save_restroom_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'the save process' do +describe SaveRestroom do it 'saves a restroom' do restroom = build(:restroom, id: 1) - actual_restroom = SaveRestroom.new(restroom).call + actual_restroom = described_class.new(restroom).call expect(Restroom.all.size).to eq(1) expect(actual_restroom.id).to eq(1) @@ -15,7 +15,7 @@ it 'creates an error for spam' do restroom = build(:spam_restroom) - actual_restroom = SaveRestroom.new(restroom).call + actual_restroom = described_class.new(restroom).call expect(Restroom.all.size).to eq(0) expect(actual_restroom.errors.key?(:spam)).to be true @@ -26,11 +26,10 @@ restroom.edit_id = 1 restroom.approved = false - actual_restroom = SaveRestroom.new(restroom).call + actual_restroom = described_class.new(restroom).call expect(Restroom.all.size).to eq(1) expect(actual_restroom.edit_id).to eq(1) expect(actual_restroom.approved?).to eq(false) end end - diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index da3496f8..aa96df63 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,7 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= "test" -require File.expand_path("../../config/environment", __FILE__) +require File.expand_path('../config/environment', __dir__) require "rspec/rails" require "webmock/rspec" @@ -14,7 +14,7 @@ # 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 with the --pattern # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. -Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } +Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } # rubocop:disable Lint/NonDeterministicRequireOrder # Checks for pending migrations before tests are run. # If you are not using ActiveRecord, you can remove this line. @@ -44,17 +44,18 @@ config.order = "random" end -Geocoder.configure(:lookup => :test) +Geocoder.configure(lookup: :test) Geocoder::Lookup::Test.add_stub( - "123 Example St., San Francisco, CA, US", [ + "123 Example St., San Francisco, CA, US", + [ { - "latitude" => 37.7749295, - "longitude" => -122.41941550000001, - "address" => "123 Example St., San Francisco, CA, USA", - "state" => "California", - "state_code" => "CA", - "country" => "United States", + "latitude" => 37.7749295, + "longitude" => -122.41941550000001, + "address" => "123 Example St., San Francisco, CA, USA", + "state" => "California", + "state_code" => "CA", + "country" => "United States", "country_code" => "US" } ] diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb index a33d2590..c7890e49 100644 --- a/spec/support/factory_bot.rb +++ b/spec/support/factory_bot.rb @@ -1,4 +1,3 @@ RSpec.configure do |config| config.include FactoryBot::Syntax::Methods end - diff --git a/spec/support/locations.rb b/spec/support/locations.rb index 02c7a898..8beedcbb 100644 --- a/spec/support/locations.rb +++ b/spec/support/locations.rb @@ -1,12 +1,13 @@ module Locations def locations { - Winnipeg: {latitude: 49.8975494, longitude: -97.140118}, - Vancouver: {latitude: 49.281006, longitude: -123.089959}, - Oakland: {latitude: 37.8044, longitude: -122.2708} + Winnipeg: { latitude: 49.8975494, longitude: -97.140118 }, + Vancouver: { latitude: 49.281006, longitude: -123.089959 }, + Oakland: { latitude: 37.8044, longitude: -122.2708 } } end + # rubocop:disable Metrics/MethodLength def mock_location(location_name) location = locations[location_name.to_sym] page.execute_script " @@ -31,4 +32,5 @@ def mock_location(location_name) })(); " end + # rubocop:enable Metrics/MethodLength end diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb index 2fdbfad3..2ce2f539 100644 --- a/spec/support/rspec.rb +++ b/spec/support/rspec.rb @@ -5,11 +5,12 @@ # spec/spec_helper.rb # -require_relative './locations.rb' +require_relative './locations' Capybara.register_driver :poltergeist_debug do |app| - Capybara::Poltergeist::Driver.new(app, - :js_errors => false + Capybara::Poltergeist::Driver.new( + app, + js_errors: false ) end @@ -17,29 +18,33 @@ WebMock.disable_net_connect!(allow_localhost: true) - RSpec.configure do |config| config.include Locations - config.before(:each) do + config.before do stub_request(:get, "http://maps.googleapis.com/maps/api/geocode/json?language=en&latlng=37.8044,-122.2708") - .with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}) - .to_return(:status => 200, :body => File.new("#{Rails.root}/spec/fixtures/guess_in_oakland.json"), :headers => {}) - - recaptcha_response = {'success' => true} + .with( + headers: { + 'Accept' => '*/*', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'User-Agent' => 'Ruby' + } + ) + .to_return(status: 200, body: File.new(Rails.root.join('spec/fixtures/guess_in_oakland.json')), headers: {}) + + recaptcha_response = { 'success' => true } stub_request(:post, 'https://www.google.com/recaptcha/api/siteverify') .to_return(status: 200, body: recaptcha_response.to_json, - headers: {'Content-Type' => 'application/json'}) + headers: { 'Content-Type' => 'application/json' }) # Akismet response for spam - stub_request(:post, /.*.rest.akismet.com\/1.1\/comment-check/). - with(body: /^.*Spam.*$/). - to_return(status: 200, body: 'true', headers: {}) + stub_request(:post, /.*.rest.akismet.com\/1.1\/comment-check/) + .with(body: /^.*Spam.*$/) + .to_return(status: 200, body: 'true', headers: {}) # Akismet response for non-spam - stub_request(:post, /.*.rest.akismet.com\/1.1\/comment-check/). - with{|request| !request.body.include? "Spam"}. - to_return(status: 200, body: 'false', headers: {}) + stub_request(:post, /.*.rest.akismet.com\/1.1\/comment-check/) + .with { |request| request.body.exclude? "Spam" } + .to_return(status: 200, body: 'false', headers: {}) end end -