high-value end-to-end happy path specs

Viewing homepage, ubmitting a story, viewing a story as a logged-in or
logged-out user, and submitting a comment. Also allows posting comments
without JavaScript.

I wanted smoke tests for the highest-traffic endpoints that tend to throw me a
few hundred emails if they hit exceptions in production.
This commit is contained in:
Peter Bhat Harkins 2018-04-18 10:06:09 -05:00
parent bf6bc8c2c5
commit ff1dc75523
14 changed files with 127 additions and 92 deletions

View File

@ -37,6 +37,7 @@ gem "mail"
group :test, :development do
gem 'bullet'
gem 'capybara'
gem "rspec-rails"
gem "machinist"
gem "rubocop", require: false

View File

@ -40,6 +40,8 @@ GEM
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
arel (8.0.0)
ast (2.4.0)
bcrypt (3.1.11)
@ -47,6 +49,13 @@ GEM
bullet (5.7.5)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11.0)
capybara (2.15.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
chunky_png (1.3.10)
commonmarker (0.17.9)
ruby-enum (~> 0.5)
@ -91,6 +100,7 @@ GEM
parser (2.5.0.5)
ast (~> 2.4.0)
powerpack (0.1.1)
public_suffix (3.0.0)
rack (2.0.4)
rack-test (0.8.3)
rack (>= 1.0, < 3)
@ -177,6 +187,8 @@ GEM
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
xpath (2.1.0)
nokogiri (~> 1.3)
PLATFORMS
ruby
@ -185,6 +197,7 @@ DEPENDENCIES
activerecord-typedstore
bcrypt (~> 3.1.2)
bullet
capybara
commonmarker (~> 0.14)
dynamic_form
exception_notification

View File

@ -503,7 +503,8 @@ $(document).ready(function() {
children(".markdown_help").toggle();
});
$(document).on("click", "button.comment-post", function() {
$(document).on("click", ".comment-post", function(event) {
event.preventDefault();
Lobsters.postComment($(this).parents("form").first());
});
@ -556,7 +557,7 @@ $(document).ready(function() {
$('textarea#comment').keydown(function (e) {
if ((e.metaKey || e.ctrlKey) && e.keyCode == 13) {
$("button.comment-post").click();
$(".comment-post").click();
}
});
});

View File

@ -16,7 +16,7 @@ class ApplicationController < ActionController::Base
end
if session[:u] &&
(user = User.where(:session_token => session[:u].to_s).first) &&
(user = User.find_by(:session_token => session[:u].to_s)) &&
user.is_active?
@user = user
Rails.logger.info " Logged in as user #{@user.id} (#{@user.username})"

View File

@ -49,8 +49,12 @@ class CommentsController < ApplicationController
if comment.valid? && params[:preview].blank? && comment.save
comment.current_vote = { :vote => 1 }
render :partial => "comments/postedreply", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
if request.xhr?
render :partial => "comments/postedreply", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
else
redirect_to comment.path
end
else
comment.upvotes = 1
comment.current_vote = { :vote => 1 }
@ -83,7 +87,7 @@ class CommentsController < ApplicationController
def redirect_from_short_id
if (comment = find_comment)
return redirect_to comment.url
return redirect_to comment.path
else
return render :plain => "can't find comment", :status => 400
end

View File

@ -387,7 +387,7 @@ class Comment < ApplicationRecord
end
def path
self.story.comments_path + "/comments/#{self.short_id}#c_#{self.short_id}"
self.story.comments_path + "#c_#{self.short_id}"
end
def plaintext_comment

View File

@ -32,9 +32,8 @@ data-shortid="<%= comment.short_id if comment.persisted? %>">
</div>
<% end %>
<%= button_tag "#{comment.new_record?? "Post" : "Update"}",
:class => "comment-post", :type => "button",
:disabled => !@user %>
<%= submit_tag "#{comment.new_record?? "Post" : "Update"}",
:class => "comment-post", :disabled => !@user %>
&nbsp;
<%= button_tag "Preview", :class => "comment-preview",
:type => "button", :disabled => !@user %>

View File

@ -1,36 +0,0 @@
# 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 'rspec/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f }
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# 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
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
config.infer_spec_type_from_file_location!
config.raise_errors_for_deprecations!
end
RSpec::Expectations.configuration.on_potential_false_positives = :nothing

View File

@ -3,10 +3,8 @@ require "rails_helper"
describe TagsController do
let(:user_id) { 5 }
before do
stub_login_as double('admin', id: user_id, is_active?: true, username: 'admin')
allow(controller).to receive(:require_logged_in_admin)
allow(controller).to receive(:session).and_return(u: 'asdf')
allow(User).to receive(:where).and_return(
double(first: double(id: user_id, is_active?: true, username: 'name')))
end
context 'create' do

View File

@ -0,0 +1,22 @@
require 'rails_helper'
RSpec.feature "Reading Homepage", type: feature do
let!(:story) { Story.make! title: "Example Story" }
feature "when logged out" do
scenario "reading a story" do
visit "/"
expect(page).to have_content(story.title)
end
end
feature "when logged in" do
let(:user) { User.make! }
before(:each) { stub_login_as user }
scenario "reading a story" do
visit "/"
expect(page).to have_content(story.title)
end
end
end

View File

@ -0,0 +1,30 @@
require 'rails_helper'
RSpec.feature "Reading Stories", type: :feature do
let!(:story) { Story.make! title: "Example Story" }
let!(:comment) { Comment.make! story_id: story.id, comment: "Example comment" }
feature "when logged out" do
scenario "reading a story" do
visit "/s/#{story.short_id}"
expect(page).to have_content(story.title)
expect(page).to have_content(comment.comment)
end
end
feature "when logged in" do
let(:user) { User.make! }
before(:each) { stub_login_as user }
scenario "reading a story" do
visit "/s/#{story.short_id}"
expect(page).to have_content(story.title)
expect(page).to have_content(comment.comment)
fill_in "comment", with: "New reply"
click_button "Post"
expect(page).to have_content("New reply")
end
end
end

View File

@ -0,0 +1,16 @@
require 'rails_helper'
RSpec.feature "Submitting Stories", type: :feature do
let(:user) { User.make! }
before(:each) { stub_login_as user }
scenario "submitting a link" do
visit "/stories/new"
fill_in "URL", with: "https://example.com/page"
fill_in "Title", with: "Example Story"
select :tag1, from: 'Tags'
click_button "Submit"
expect(page).not_to have_content "prohibited this story from being saved"
end
end

View File

@ -1,57 +1,38 @@
# 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?
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
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 this line.
ActiveRecord::Migration.maintain_test_schema!
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f }
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/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!
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# 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")
config.infer_spec_type_from_file_location!
config.raise_errors_for_deprecations!
config.include AuthenticationHelper
end
RSpec::Expectations.configuration.on_potential_false_positives = :nothing

View File

@ -0,0 +1,6 @@
module AuthenticationHelper
def stub_login_as user
allow(User).to receive(:find_by).and_return(user)
allow_any_instance_of(ApplicationController).to receive(:session).and_return(u: 'asdf')
end
end