mirror of
https://github.com/discourse/discourse.git
synced 2026-08-04 10:23:17 -05:00
DEV: Introduce core features system specs for plugins
This patch adds a new shared example to be used as a smoke test in plugins and themes. A `skip_examples` argument is available to easily opt-out from a category of tests. Example: ```rb RSpec.describe "Testing core features", type: :system do it_behaves_like "having working core features", skip_examples: %i[search login] end ```
This commit is contained in:
committed by
Loïc Guitaut
parent
7b9976795e
commit
4f82ceaf39
@@ -10,66 +10,4 @@ module OneboxHelpers
|
||||
preview = Nokogiri::HTML::DocumentFragment.parse(raw_fragment)
|
||||
preview.css(tag_name).first[attribute]
|
||||
end
|
||||
|
||||
RSpec.shared_context "with engines" do
|
||||
let(:onebox) { described_class.new(link) }
|
||||
let(:html) { onebox.to_html }
|
||||
let(:data) { onebox.send(:data).deep_symbolize_keys }
|
||||
let(:link) { @link }
|
||||
let(:uri) { defined?(@uri) ? @uri : link }
|
||||
|
||||
before do
|
||||
fixture = defined?(@onebox_fixture) ? @onebox_fixture : described_class.onebox_name
|
||||
stub_request(:get, uri).to_return(status: 200, body: onebox_response(fixture))
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples_for "an engine" do
|
||||
it "responds to data" do
|
||||
expect(described_class.private_instance_methods).to include(:data)
|
||||
end
|
||||
|
||||
it "correctly matches the url" do
|
||||
onebox = Onebox::Matcher.new(link, { allowed_iframe_regexes: [/.*/] }).oneboxed
|
||||
expect(onebox).to be(described_class)
|
||||
end
|
||||
|
||||
describe "#data" do
|
||||
it "includes title" do
|
||||
expect(data[:title]).not_to be_nil
|
||||
end
|
||||
|
||||
it "includes link" do
|
||||
expect(data[:link]).not_to be_nil
|
||||
end
|
||||
|
||||
it "is serializable" do
|
||||
expect { Marshal.dump(data) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples_for "a layout engine" do
|
||||
describe "#to_html" do
|
||||
it "includes subname" do
|
||||
expect(html).to include(%|<aside class="onebox #{described_class.onebox_name}">|)
|
||||
end
|
||||
|
||||
it "includes title" do
|
||||
expect(html).to include(data[:title])
|
||||
end
|
||||
|
||||
it "includes link" do
|
||||
expect(html).to include(%|class="link" href="#{data[:link]}|)
|
||||
end
|
||||
|
||||
it "includes badge" do
|
||||
expect(html).to include(%|<strong class="name">#{data[:badge]}</strong>|)
|
||||
end
|
||||
|
||||
it "includes domain" do
|
||||
expect(html).to include(%|class="domain" href="#{data[:domain]}|)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
shared_examples "basic reviewable attributes" do
|
||||
RSpec.shared_examples "basic reviewable attributes" do
|
||||
describe "#id" do
|
||||
it "equals the reviewable's id" do
|
||||
expect(subject[:id]).to eq(reviewable.id)
|
||||
@@ -0,0 +1,201 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples_for "having working core features" do |skip_examples: []|
|
||||
fab!(:category) { Fabricate(:category, name: "General") }
|
||||
fab!(:topics) { Fabricate.times(3, :topic_with_op, category:) }
|
||||
fab!(:topic)
|
||||
fab!(:active_user) { Fabricate(:active_user, password: "secure_password") }
|
||||
|
||||
let(:composer) { PageObjects::Components::Composer.new }
|
||||
|
||||
if skip_examples.exclude?(:login)
|
||||
describe "Login" do
|
||||
let(:login_form) { PageObjects::Modals::Login.new }
|
||||
|
||||
before { EmailToken.confirm(Fabricate(:email_token, user: active_user).token) }
|
||||
|
||||
it "logs in" do
|
||||
visit("/")
|
||||
login_form
|
||||
.open
|
||||
.fill(username: active_user.username, password: "secure_password")
|
||||
.click_login
|
||||
expect(page).to have_css(".current-user", visible: true)
|
||||
end
|
||||
|
||||
it "displays a login button in the header" do
|
||||
visit("/")
|
||||
expect(page).to have_css("header .login-button", visible: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if skip_examples.exclude?(:topics)
|
||||
describe "Topics" do
|
||||
context "with an anonymous user" do
|
||||
before { visit "/" }
|
||||
|
||||
it "lists latest topics" do
|
||||
expect(page).to have_css(".topic-list-item", count: 4)
|
||||
end
|
||||
|
||||
it "lists topics for a category" do
|
||||
within("#sidebar-section-content-categories") { click_on("General") }
|
||||
expect(page).to have_css(".topic-list-item", count: 3)
|
||||
end
|
||||
|
||||
it "displays a specific topic" do
|
||||
click_on(topics.first.title)
|
||||
expect(page).to have_content(topics.first.title)
|
||||
expect(page).to have_content(topics.first.first_post.raw)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a logged in user" do
|
||||
before do
|
||||
sign_in(active_user)
|
||||
visit "/"
|
||||
end
|
||||
|
||||
it "lists latest topics" do
|
||||
expect(page).to have_css(".topic-list-item", count: 4)
|
||||
end
|
||||
|
||||
it "lists topics for a category" do
|
||||
within("#sidebar-section-content-categories") { click_on("General") }
|
||||
expect(page).to have_css(".topic-list-item", count: 3)
|
||||
end
|
||||
|
||||
it "displays a specific topic" do
|
||||
click_on(topics.first.title)
|
||||
expect(page).to have_content(topics.first.title)
|
||||
expect(page).to have_content(topics.first.first_post.raw)
|
||||
end
|
||||
|
||||
it "replies in a topic" do
|
||||
click_on(topics.first.title)
|
||||
expect(page).to have_content(topics.first.first_post.raw)
|
||||
within(".actions") { click_button("Reply") }
|
||||
composer.focus
|
||||
send_keys("This is a long enough reply.")
|
||||
expect(page).to have_css(".d-editor-preview p", visible: true)
|
||||
within(".save-or-cancel") { click_button("Reply") }
|
||||
expect(page).to have_content("This is a long enough reply.")
|
||||
end
|
||||
|
||||
it "creates a new topic" do
|
||||
find("#create-topic", visible: true).click
|
||||
composer.fill_title("This is a new topic")
|
||||
composer.fill_content("This is a long enough sentence.")
|
||||
expect(page).to have_css(".d-editor-preview p", visible: true)
|
||||
within(".save-or-cancel") { click_button("Create Topic") }
|
||||
expect(page).to have_content("This is a new topic")
|
||||
expect(page).to have_content("This is a long enough sentence.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if skip_examples.exclude?(:likes)
|
||||
describe "Likes" do
|
||||
before do
|
||||
sign_in(active_user)
|
||||
visit "/"
|
||||
end
|
||||
|
||||
it "likes a post" do
|
||||
click_on(topics.first.title)
|
||||
within(".double-button") do
|
||||
find(".toggle-like").click
|
||||
expect(page).to have_content("1")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if skip_examples.exclude?(:profile)
|
||||
describe "User profile" do
|
||||
fab!(:user)
|
||||
|
||||
before { UserStat.update_all(post_count: 1) }
|
||||
|
||||
context "with an anonymous user" do
|
||||
it "displays a user’s profile" do
|
||||
visit("/u/#{user.username}/summary")
|
||||
expect(page).to have_content(user.name)
|
||||
expect(page).to have_content("Activity")
|
||||
end
|
||||
end
|
||||
|
||||
context "with a logged in user" do
|
||||
before { sign_in(active_user) }
|
||||
|
||||
it "displays a user’s profile" do
|
||||
visit("/u/#{user.username}/summary")
|
||||
expect(page).to have_content(user.name)
|
||||
expect(page).to have_content("Message")
|
||||
end
|
||||
|
||||
it "displays the user’s own profile" do
|
||||
visit("/u/#{active_user.username}/summary")
|
||||
expect(page).to have_content(active_user.name)
|
||||
expect(page).to have_content("Preferences")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if skip_examples.exclude?(:search)
|
||||
describe "Search" do
|
||||
let(:search_page) { PageObjects::Pages::Search.new }
|
||||
|
||||
before do
|
||||
SearchIndexer.enable
|
||||
topics.each { SearchIndexer.index(_1, force: true) }
|
||||
SiteSetting.enable_welcome_banner = false
|
||||
end
|
||||
|
||||
after { SearchIndexer.disable }
|
||||
|
||||
context "with an anonymous user" do
|
||||
it "searches using the quick search" do
|
||||
visit("/")
|
||||
search_page.click_search_icon
|
||||
search_page.type_in_search_menu(topics.first.title)
|
||||
search_page.click_search_menu_link
|
||||
expect(search_page).to have_topic_title_for_first_search_result(topics.first.title)
|
||||
end
|
||||
|
||||
it "searches using the full page search" do
|
||||
visit("/search")
|
||||
|
||||
search_page.type_in_search(topics.first.title)
|
||||
search_page.click_search_button
|
||||
|
||||
expect(search_page).to have_search_result
|
||||
end
|
||||
end
|
||||
|
||||
context "with a logged in user" do
|
||||
before { sign_in(active_user) }
|
||||
|
||||
it "searches using the quick search" do
|
||||
visit("/")
|
||||
search_page.click_search_icon
|
||||
search_page.type_in_search_menu(topics.first.title)
|
||||
search_page.click_search_menu_link
|
||||
expect(search_page).to have_topic_title_for_first_search_result(topics.first.title)
|
||||
end
|
||||
|
||||
it "searches using the full page search" do
|
||||
visit("/search")
|
||||
|
||||
search_page.type_in_search(topics.first.title)
|
||||
search_page.click_search_button
|
||||
|
||||
expect(search_page).to have_search_result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_context "with engines" do
|
||||
let(:onebox) { described_class.new(link) }
|
||||
let(:html) { onebox.to_html }
|
||||
let(:data) { onebox.send(:data).deep_symbolize_keys }
|
||||
let(:link) { @link }
|
||||
let(:uri) { defined?(@uri) ? @uri : link }
|
||||
|
||||
before do
|
||||
fixture = defined?(@onebox_fixture) ? @onebox_fixture : described_class.onebox_name
|
||||
stub_request(:get, uri).to_return(status: 200, body: onebox_response(fixture))
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples_for "an engine" do
|
||||
it "responds to data" do
|
||||
expect(described_class.private_instance_methods).to include(:data)
|
||||
end
|
||||
|
||||
it "correctly matches the url" do
|
||||
onebox = Onebox::Matcher.new(link, { allowed_iframe_regexes: [/.*/] }).oneboxed
|
||||
expect(onebox).to be(described_class)
|
||||
end
|
||||
|
||||
describe "#data" do
|
||||
it "includes title" do
|
||||
expect(data[:title]).not_to be_nil
|
||||
end
|
||||
|
||||
it "includes link" do
|
||||
expect(data[:link]).not_to be_nil
|
||||
end
|
||||
|
||||
it "is serializable" do
|
||||
expect { Marshal.dump(data) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples_for "a layout engine" do
|
||||
describe "#to_html" do
|
||||
it "includes subname" do
|
||||
expect(html).to include(%|<aside class="onebox #{described_class.onebox_name}">|)
|
||||
end
|
||||
|
||||
it "includes title" do
|
||||
expect(html).to include(data[:title])
|
||||
end
|
||||
|
||||
it "includes link" do
|
||||
expect(html).to include(%|class="link" href="#{data[:link]}|)
|
||||
end
|
||||
|
||||
it "includes badge" do
|
||||
expect(html).to include(%|<strong class="name">#{data[:badge]}</strong>|)
|
||||
end
|
||||
|
||||
it "includes domain" do
|
||||
expect(html).to include(%|class="domain" href="#{data[:domain]}|)
|
||||
end
|
||||
end
|
||||
end
|
||||
+3
-3
@@ -100,13 +100,13 @@ RSpec.shared_examples "User Sidebar Serializer Attributes" do |serializer_klass|
|
||||
describe "#display_sidebar_tags" do
|
||||
fab!(:tag)
|
||||
|
||||
it "should not be included in serialised object when tagging has been disabled" do
|
||||
it "is not included in serialised object when tagging has been disabled" do
|
||||
SiteSetting.tagging_enabled = false
|
||||
|
||||
expect(serializer.as_json[:display_sidebar_tags]).to eq(nil)
|
||||
end
|
||||
|
||||
it "should be true when user has visible tags" do
|
||||
it "returns true when user has visible tags" do
|
||||
SiteSetting.tagging_enabled = true
|
||||
|
||||
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [tag.name])
|
||||
@@ -115,7 +115,7 @@ RSpec.shared_examples "User Sidebar Serializer Attributes" do |serializer_klass|
|
||||
expect(serializer.as_json[:display_sidebar_tags]).to eq(true)
|
||||
end
|
||||
|
||||
it "should be false when user has no visible tags" do
|
||||
it "returns false when user has no visible tags" do
|
||||
SiteSetting.tagging_enabled = true
|
||||
|
||||
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [tag.name])
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
RSpec.shared_examples_for "a versioned model" do
|
||||
let(:model) { Fabricate(described_class.to_s.downcase) }
|
||||
|
||||
it "should be versioned" do
|
||||
it "is versioned" do
|
||||
expect(model).to respond_to(:version)
|
||||
expect(model.version).to eq(1)
|
||||
end
|
||||
Reference in New Issue
Block a user