Merge pull request #1086 from Retrospring/view-specs
add some view specs for inbox
This commit is contained in:
commit
a6dc08ad9a
|
@ -2,7 +2,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__)
|
||||
# Prevent database truncation if the environment is production
|
||||
abort("The Rails environment is running in production mode!") if Rails.env.production?
|
||||
require "spec_helper"
|
||||
|
@ -26,6 +26,7 @@ require "rspec-sidekiq"
|
|||
# require only the support files necessary.
|
||||
#
|
||||
# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
|
||||
require "support/nokogiri_matchers"
|
||||
|
||||
# Checks for pending migration and applies them before tests are run.
|
||||
# If you are not using ActiveRecord, you can remove this line.
|
||||
|
@ -33,7 +34,7 @@ ActiveRecord::Migration.maintain_test_schema!
|
|||
|
||||
RSpec.configure do |config|
|
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
config.fixture_path = Rails.root.join("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
|
||||
|
@ -66,6 +67,7 @@ RSpec.configure do |config|
|
|||
|
||||
config.include Devise::Test::ControllerHelpers, type: :controller
|
||||
config.include Devise::Test::ControllerHelpers, type: :helper
|
||||
config.include Devise::Test::ControllerHelpers, type: :view
|
||||
end
|
||||
|
||||
Shoulda::Matchers.configure do |config|
|
||||
|
@ -75,4 +77,4 @@ Shoulda::Matchers.configure do |config|
|
|||
end
|
||||
end
|
||||
|
||||
Dir[Rails.root.join "spec", "shared_examples", "*.rb"].sort.each { |f| require f }
|
||||
Dir[Rails.root.join("spec/shared_examples/*.rb")].each { |f| require f }
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module NokogiriMatchers
|
||||
RSpec::Matchers.matcher :have_css do |css|
|
||||
description { %(have at least one element matching the CSS selector #{css.inspect}) }
|
||||
|
||||
match do |rendered|
|
||||
Nokogiri::HTML.parse(rendered).css(css).size.positive?
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.matcher :have_attribute do |expected_attribute|
|
||||
description do
|
||||
case expected_attribute
|
||||
when Hash
|
||||
raise ArgumentError.new("have_attribute only wants one key=>value pair") unless expected_attribute.size == 1
|
||||
|
||||
key = expected_attribute.keys.first
|
||||
value = expected_attribute.values.first
|
||||
%(have an attribute named #{key.inspect} with a value of #{value.inspect})
|
||||
else
|
||||
%(have an attribute named #{expected_attribute.inspect})
|
||||
end
|
||||
end
|
||||
|
||||
match do |element|
|
||||
case expected_attribute
|
||||
when Hash
|
||||
raise ArgumentError.new("have_attribute only wants one key=>value pair") unless expected_attribute.size == 1
|
||||
|
||||
key = expected_attribute.keys.first
|
||||
value = expected_attribute.values.first
|
||||
|
||||
element.attr(key.to_s).value == value
|
||||
else
|
||||
!element.attr(expected_attribute.to_s).nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |c|
|
||||
c.include NokogiriMatchers, view: true
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe "inbox/_actions.html.haml", type: :view do
|
||||
let(:delete_id) { "ib-delete-all" }
|
||||
let(:disabled) { false }
|
||||
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
end
|
||||
|
||||
subject(:rendered) do
|
||||
render partial: "inbox/actions", locals: {
|
||||
delete_id:,
|
||||
disabled:,
|
||||
inbox_count: 4020,
|
||||
}
|
||||
end
|
||||
|
||||
it "has a button for deleting all inbox entries" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
button = html.css("button#ib-delete-all")
|
||||
expect(button).not_to have_attribute(:disabled)
|
||||
end
|
||||
|
||||
context "with disabled = true" do
|
||||
let(:disabled) { true }
|
||||
|
||||
it "has a button for deleting all inbox entries" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
button = html.css("button#ib-delete-all")
|
||||
expect(button).to have_attribute(:disabled)
|
||||
end
|
||||
end
|
||||
|
||||
context "with delete_id = ib-delete-all-author" do
|
||||
let(:delete_id) { "ib-delete-all-author" }
|
||||
|
||||
it "has a button for deleting all inbox entries" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
button = html.css("button#ib-delete-all-author")
|
||||
|
||||
expect(button).to have_attribute("data-ib-count" => "4020")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,121 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe "inbox/_entry.html.haml", type: :view do
|
||||
let(:inbox_entry) { Inbox.create(user: inbox_user, question:, new:) }
|
||||
let(:inbox_user) { user }
|
||||
let(:user) { FactoryBot.create(:user, sharing_enabled:, sharing_custom_url:) }
|
||||
let(:sharing_enabled) { true }
|
||||
let(:sharing_custom_url) { nil }
|
||||
let(:question) { FactoryBot.create(:question, content: "owo what's this?", author_is_anonymous:, user: question_user, answer_count:) }
|
||||
let(:author_is_anonymous) { true }
|
||||
let(:question_user) { nil }
|
||||
let(:answer_count) { 0 }
|
||||
let(:new) { false }
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
end
|
||||
|
||||
subject(:rendered) do
|
||||
render partial: "inbox/entry", locals: {
|
||||
i: inbox_entry,
|
||||
}
|
||||
end
|
||||
|
||||
it "does not set the inbox-entry--new class on non-new inbox entries" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
classes = html.css("#inbox_#{inbox_entry.id}").attr("class").value
|
||||
expect(classes).not_to include "inbox-entry--new"
|
||||
end
|
||||
|
||||
context "when the inbox entry is new" do
|
||||
let(:new) { true }
|
||||
|
||||
it "sets the inbox-entry--new class" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
classes = html.css("#inbox_#{inbox_entry.id}").attr("class").value
|
||||
expect(classes).to include "inbox-entry--new"
|
||||
end
|
||||
end
|
||||
|
||||
context "when question author is not anonymous" do
|
||||
let(:question_user) { FactoryBot.create(:user) }
|
||||
let(:author_is_anonymous) { false }
|
||||
|
||||
it "has an avatar" do
|
||||
expect(rendered).to have_css(%(img.answerbox__question-user-avatar))
|
||||
end
|
||||
|
||||
it "does not have an icon indicating the author is anonymous" do
|
||||
expect(rendered).not_to have_css(%(i.fas.fa-user-secret))
|
||||
end
|
||||
|
||||
context "when the question already has some answers" do
|
||||
let(:answer_count) { 9001 }
|
||||
|
||||
it "has a link to the question view" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
selector = %(a[href="/@#{question_user.screen_name}/q/#{question.id}"])
|
||||
expect(rendered).to have_css(selector)
|
||||
expect(html.css(selector).text.strip).to eq "9001 answers"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "has an icon indicating the author is anonymous" do
|
||||
expect(rendered).to have_css(%(i.fas.fa-user-secret))
|
||||
end
|
||||
|
||||
it "contains the question text" do
|
||||
expect(rendered).to match "owo what's this?"
|
||||
end
|
||||
|
||||
it "has interactive elements" do
|
||||
expect(rendered).to have_css(%(textarea[name="ib-answer"][data-id="#{inbox_entry.id}"]))
|
||||
expect(rendered).to have_css(%(button[name="ib-answer"][data-ib-id="#{inbox_entry.id}"]))
|
||||
expect(rendered).to have_css(%(button[name="ib-destroy"][data-ib-id="#{inbox_entry.id}"]))
|
||||
end
|
||||
|
||||
it "has a hidden sharing bit" do
|
||||
expect(rendered).to have_css(%(.inbox-entry__sharing.d-none))
|
||||
end
|
||||
|
||||
it "has a link-button to share to tumblr" do
|
||||
expect(rendered).to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="tumblr"]))
|
||||
end
|
||||
|
||||
it "has a link-button to share to twitter" do
|
||||
expect(rendered).to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="twitter"]))
|
||||
end
|
||||
|
||||
it "does not have a link-button to share to a custom site" do
|
||||
expect(rendered).not_to have_css(%(.inbox-entry__sharing a.btn[data-inbox-sharing-target="custom"]))
|
||||
end
|
||||
|
||||
context "when the user has a custom share url set" do
|
||||
let(:sharing_custom_url) { "https://pounced-on.me/share?text=" }
|
||||
|
||||
it "has a link-button to share to a custom site" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
selector = %(.inbox-entry__sharing a.btn[data-inbox-sharing-target="custom"])
|
||||
expect(rendered).to have_css(selector)
|
||||
expect(html.css(selector).text.strip).to eq "pounced-on.me"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the inbox entry does not belong to the current user" do
|
||||
let(:inbox_user) { FactoryBot.create(:user) }
|
||||
|
||||
it "does not have any interactive elements" do
|
||||
expect(rendered).not_to have_css(%(textarea[name="ib-answer"][data-id="#{inbox_entry.id}"]))
|
||||
expect(rendered).not_to have_css(%(button[name="ib-answer"][data-ib-id="#{inbox_entry.id}"]))
|
||||
expect(rendered).not_to have_css(%(button[name="ib-destroy"][data-ib-id="#{inbox_entry.id}"]))
|
||||
end
|
||||
|
||||
it "does not have the sharing bit" do
|
||||
expect(rendered).not_to have_css(%(.inbox-entry__sharing.d-none))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe "inbox/_push_settings.haml", type: :view do
|
||||
subject(:rendered) { render }
|
||||
|
||||
it "has a button to enable push notifications" do
|
||||
expect(rendered).to have_css(%(button[data-action="push-enable"]))
|
||||
end
|
||||
|
||||
it "has a button to dismiss the view" do
|
||||
expect(rendered).to have_css(%(button[data-action="push-dismiss"]))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,75 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe "inbox/show.html.haml", type: :view do
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
end
|
||||
|
||||
subject(:rendered) { render }
|
||||
|
||||
context "with an empty inbox" do
|
||||
before do
|
||||
assign :inbox, []
|
||||
end
|
||||
|
||||
it "displays an 'inbox is empty' message" do
|
||||
html = Nokogiri::HTML.parse(rendered)
|
||||
selector = "p.empty"
|
||||
expect(rendered).to have_css(selector)
|
||||
expect(html.css(selector).text.strip).to eq "Nothing to see here."
|
||||
end
|
||||
end
|
||||
|
||||
context "with some inbox entries" do
|
||||
let(:inbox_entry1) { Inbox.create(user:, question: FactoryBot.create(:question)) }
|
||||
let(:inbox_entry2) { Inbox.create(user:, question: FactoryBot.create(:question)) }
|
||||
|
||||
before do
|
||||
assign :inbox, [inbox_entry2, inbox_entry1]
|
||||
end
|
||||
|
||||
it "renders inbox entries" do
|
||||
expect(rendered).to have_css("#inbox_#{inbox_entry1.id}")
|
||||
expect(rendered).to have_css("#inbox_#{inbox_entry2.id}")
|
||||
end
|
||||
|
||||
it "does not contain the empty inbox message" do
|
||||
expect(rendered).not_to have_css("p.empty")
|
||||
end
|
||||
|
||||
it "does not render the paginator" do
|
||||
expect(rendered).not_to have_css("#paginator")
|
||||
end
|
||||
|
||||
context "when more data is available" do
|
||||
before do
|
||||
assign :more_data_available, true
|
||||
assign :inbox_last_id, 1337
|
||||
end
|
||||
|
||||
it "renders the paginator" do
|
||||
expect(rendered).to have_css("#paginator")
|
||||
end
|
||||
|
||||
it "has the correct params on the button" do
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="last_id"][value="1337"]))
|
||||
expect(rendered).not_to have_css(%(input[type="hidden"][name="author"]))
|
||||
end
|
||||
|
||||
context "when passed an author" do
|
||||
before do
|
||||
assign :author, "jyrki"
|
||||
end
|
||||
|
||||
it "has the correct params on the button" do
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="last_id"][value="1337"]))
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="author"]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe "inbox/show.turbo_stream.haml", type: :view do
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
|
||||
before do
|
||||
sign_in user
|
||||
end
|
||||
|
||||
subject(:rendered) { render }
|
||||
|
||||
context "with some inbox entries" do
|
||||
let(:inbox_entry1) { Inbox.create(user:, question: FactoryBot.create(:question)) }
|
||||
let(:inbox_entry2) { Inbox.create(user:, question: FactoryBot.create(:question)) }
|
||||
|
||||
before do
|
||||
assign :inbox, [inbox_entry2, inbox_entry1]
|
||||
end
|
||||
|
||||
it "appends to entries" do
|
||||
expect(rendered).to have_css(%(turbo-stream[action="append"][target="entries"]))
|
||||
end
|
||||
|
||||
it "renders inbox entries" do
|
||||
expect(rendered).to have_css("#inbox_#{inbox_entry1.id}")
|
||||
expect(rendered).to have_css("#inbox_#{inbox_entry2.id}")
|
||||
end
|
||||
|
||||
it "updates the paginator" do
|
||||
expect(rendered).to have_css(%(turbo-stream[action="update"][target="paginator"]))
|
||||
end
|
||||
|
||||
context "when more data is available" do
|
||||
before do
|
||||
assign :more_data_available, true
|
||||
assign :inbox_last_id, 1337
|
||||
end
|
||||
|
||||
it "has the correct params on the button" do
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="last_id"][value="1337"]))
|
||||
expect(rendered).not_to have_css(%(input[type="hidden"][name="author"]))
|
||||
end
|
||||
|
||||
context "when passed an author" do
|
||||
before do
|
||||
assign :author, "jyrki"
|
||||
end
|
||||
|
||||
it "has the correct params on the button" do
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="last_id"][value="1337"]))
|
||||
expect(rendered).to have_css(%(input[type="hidden"][name="author"]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue