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:
parent
bf6bc8c2c5
commit
ff1dc75523
1
Gemfile
1
Gemfile
|
@ -37,6 +37,7 @@ gem "mail"
|
|||
|
||||
group :test, :development do
|
||||
gem 'bullet'
|
||||
gem 'capybara'
|
||||
gem "rspec-rails"
|
||||
gem "machinist"
|
||||
gem "rubocop", require: false
|
||||
|
|
13
Gemfile.lock
13
Gemfile.lock
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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})"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %>
|
||||
|
||||
<%= button_tag "Preview", :class => "comment-preview",
|
||||
:type => "button", :disabled => !@user %>
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue