From 9b4a98695ed7422289e37b4e0dd6b68d74894106 Mon Sep 17 00:00:00 2001 From: OsamaSayegh Date: Mon, 4 Jun 2018 06:09:59 +0300 Subject: [PATCH] REFACTOR: list controller specs to requests (#5902) --- spec/controllers/list_controller_spec.rb | 410 ----------------------- spec/requests/list_controller_spec.rb | 368 +++++++++++++++++++- 2 files changed, 367 insertions(+), 411 deletions(-) delete mode 100644 spec/controllers/list_controller_spec.rb diff --git a/spec/controllers/list_controller_spec.rb b/spec/controllers/list_controller_spec.rb deleted file mode 100644 index 1f1374c5c92..00000000000 --- a/spec/controllers/list_controller_spec.rb +++ /dev/null @@ -1,410 +0,0 @@ -require 'rails_helper' - -describe ListController do - - # we need some data - before do - @user = Fabricate(:coding_horror) - @post = Fabricate(:post, user: @user) - - SiteSetting.top_menu = 'latest|new|unread|categories' - end - - describe 'indexes' do - - (Discourse.anonymous_filters - [:categories]).each do |filter| - context "#{filter}" do - before { get filter } - it { is_expected.to respond_with(:success) } - end - end - - it 'allows users to filter on a set of topic ids' do - p = create_post - - get :latest, format: :json, params: { topic_ids: "#{p.topic_id}" } - expect(response).to be_success - parsed = JSON.parse(response.body) - expect(parsed["topic_list"]["topics"].length).to eq(1) - end - end - - describe 'RSS feeds' do - it 'renders latest RSS' do - get "latest_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders top RSS' do - get "top_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders all time top RSS' do - get "top_all_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders yearly top RSS' do - get "top_yearly_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders quarterly top RSS' do - get "top_quarterly_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders monthly top RSS' do - get "top_monthly_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders weekly top RSS' do - get "top_weekly_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - - it 'renders daily top RSS' do - get "top_daily_feed", format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - end - - context 'category' do - - context 'in a category' do - let(:category) { Fabricate(:category) } - - context 'without access to see the category' do - before do - Guardian.any_instance.expects(:can_see?).with(category).returns(false) - get :category_latest, params: { category: category.slug } - end - - it { is_expected.not_to respond_with(:success) } - end - - context 'with access to see the category' do - before do - get :category_latest, params: { category: category.slug } - end - - it { is_expected.to respond_with(:success) } - end - - context 'with a link that includes an id' do - before do - get :category_latest, params: { - category: "#{category.id}-#{category.slug}" - } - end - - it { is_expected.to respond_with(:success) } - end - - context 'with a link that has a parent slug, slug and id in its path' do - let(:child_category) { Fabricate(:category, parent_category: category) } - - context "with valid slug" do - before do - get :category_latest, params: { - parent_category: category.slug, - category: child_category.slug, - id: child_category.id - } - end - - it { is_expected.to redirect_to(child_category.url) } - end - - context "with invalid slug" do - before do - get :category_latest, params: { - parent_category: 'random slug', - category: 'random slug', - id: child_category.id - } - end - - it { is_expected.to redirect_to(child_category.url) } - end - end - - context 'another category exists with a number at the beginning of its name' do - # One category has another category's id at the beginning of its name - let!(:other_category) { Fabricate(:category, name: "#{category.id} name") } - - it 'uses the correct category' do - get :category_latest, - params: { category: other_category.slug }, - format: :json - - expect(response).to be_success - - body = JSON.parse(response.body) - - expect(body["topic_list"]["topics"].first["category_id"]) - .to eq(other_category.id) - end - end - - context 'a child category' do - let(:sub_category) { Fabricate(:category, parent_category_id: category.id) } - - context 'when parent and child are requested' do - before do - get :category_latest, params: { - parent_category: category.slug, category: sub_category.slug - } - end - - it { is_expected.to respond_with(:success) } - end - - context 'when child is requested with the wrong parent' do - before do - get :category_latest, params: { - parent_category: 'not_the_right_slug', category: sub_category.slug - } - end - - it { is_expected.not_to respond_with(:success) } - end - end - - describe 'feed' do - it 'renders RSS' do - get :category_feed, params: { category: category.slug }, format: :rss - expect(response).to be_success - expect(response.content_type).to eq('application/rss+xml') - end - end - - describe "category default views" do - it "has a top default view" do - category.update_attributes!(default_view: 'top', default_top_period: 'monthly') - described_class.expects(:best_period_with_topics_for).with(anything, category.id, :monthly).returns(:monthly) - get :category_default, params: { category: category.slug } - expect(response).to be_success - end - - it "has a default view of nil" do - category.update_attributes!(default_view: nil) - described_class.expects(:best_period_for).never - get :category_default, params: { category: category.slug } - expect(response).to be_success - end - - it "has a default view of ''" do - category.update_attributes!(default_view: '') - described_class.expects(:best_period_for).never - get :category_default, params: { category: category.slug } - expect(response).to be_success - end - - it "has a default view of latest" do - category.update_attributes!(default_view: 'latest') - described_class.expects(:best_period_for).never - get :category_default, params: { category: category.slug } - expect(response).to be_success - end - end - - describe "renders canonical tag" do - render_views - - it 'for category default view' do - get :category_default, params: { category: category.slug } - expect(response).to be_success - expect(css_select("link[rel=canonical]").length).to eq(1) - end - - it 'for category latest view' do - get :category_latest, params: { category: category.slug } - expect(response).to be_success - expect(css_select("link[rel=canonical]").length).to eq(1) - end - end - end - end - - describe "topics_by" do - let!(:user) { log_in } - - it "should respond with a list" do - get :topics_by, params: { username: @user.username } - expect(response).to be_success - end - end - - context "private_messages" do - let!(:user) { log_in } - - it "raises an error when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(false) - get :private_messages, params: { username: @user.username } - expect(response).to be_forbidden - end - - it "succeeds when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(true) - get :private_messages, params: { username: @user.username } - expect(response).to be_success - end - end - - context "private_messages_sent" do - let!(:user) { log_in } - - it "raises an error when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(false) - get :private_messages_sent, params: { username: @user.username } - expect(response).to be_forbidden - end - - it "succeeds when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(true) - get :private_messages_sent, params: { username: @user.username } - expect(response).to be_success - end - end - - context "private_messages_unread" do - let!(:user) { log_in } - - it "raises an error when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(false) - get :private_messages_unread, params: { username: @user.username } - expect(response).to be_forbidden - end - - it "succeeds when can_see_private_messages? is false " do - Guardian.any_instance.expects(:can_see_private_messages?).returns(true) - get :private_messages_unread, params: { username: @user.username } - expect(response).to be_success - end - end - - context 'read' do - it 'raises an error when not logged in' do - get :read - expect(response.status).to eq(404) - end - - context 'when logged in' do - before do - log_in_user(@user) - get :read - end - - it { is_expected.to respond_with(:success) } - end - end - - describe "best_periods_for" do - - it "returns yearly for more than 180 days" do - expect(ListController.best_periods_for(nil, :all)).to eq([:yearly]) - expect(ListController.best_periods_for(180.days.ago, :all)).to eq([:yearly]) - end - - it "includes monthly when less than 180 days and more than 35 days" do - (35...180).each do |date| - expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:monthly, :yearly]) - end - end - - it "includes weekly when less than 35 days and more than 8 days" do - (8...35).each do |date| - expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:weekly, :monthly, :yearly]) - end - end - - it "includes daily when less than 8 days" do - (0...8).each do |date| - expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:daily, :weekly, :monthly, :yearly]) - end - end - - it "returns default even for more than 180 days" do - expect(ListController.best_periods_for(nil, :monthly)).to eq([:monthly, :yearly]) - expect(ListController.best_periods_for(180.days.ago, :monthly)).to eq([:monthly, :yearly]) - end - - it "returns default even when less than 180 days and more than 35 days" do - (35...180).each do |date| - expect(ListController.best_periods_for(date.days.ago, :weekly)).to eq([:weekly, :monthly, :yearly]) - end - end - - it "returns default even when less than 35 days and more than 8 days" do - (8...35).each do |date| - expect(ListController.best_periods_for(date.days.ago, :daily)).to eq([:daily, :weekly, :monthly, :yearly]) - end - end - - it "doesn't return default when set to all" do - expect(ListController.best_periods_for(nil, :all)).to eq([:yearly]) - end - - it "doesn't return value twice when matches default" do - expect(ListController.best_periods_for(nil, :yearly)).to eq([:yearly]) - end - end - - describe "categories suppression" do - let(:category_one) { Fabricate(:category) } - let(:sub_category) { Fabricate(:category, parent_category: category_one, suppress_from_latest: true) } - let!(:topic_in_sub_category) { Fabricate(:topic, category: sub_category) } - - let(:category_two) { Fabricate(:category, suppress_from_latest: true) } - let!(:topic_in_category_two) { Fabricate(:topic, category: category_two) } - - it "suppresses categories from the latest list" do - get SiteSetting.homepage, format: :json - expect(response).to be_success - - topic_titles = JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["title"] } - expect(topic_titles).not_to include(topic_in_sub_category.title, topic_in_category_two.title) - end - - it "does not suppress" do - get SiteSetting.homepage, params: { category: category_one.id }, format: :json - expect(response).to be_success - - topic_titles = JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["title"] } - expect(topic_titles).to include(topic_in_sub_category.title) - end - - end - - describe "safe mode" do - render_views - - it "handles safe mode" do - get :latest - expect(response.body).to match(/plugin\.js/) - expect(response.body).to match(/plugin-third-party\.js/) - - get :latest, params: { safe_mode: "no_plugins" } - expect(response.body).not_to match(/plugin\.js/) - expect(response.body).not_to match(/plugin-third-party\.js/) - - get :latest, params: { safe_mode: "only_official" } - expect(response.body).to match(/plugin\.js/) - expect(response.body).not_to match(/plugin-third-party\.js/) - - end - - end - -end diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb index 288d49cd293..5910aa3c57a 100644 --- a/spec/requests/list_controller_spec.rb +++ b/spec/requests/list_controller_spec.rb @@ -1,8 +1,14 @@ require 'rails_helper' RSpec.describe ListController do - let(:topic) { Fabricate(:topic) } + let(:topic) { Fabricate(:topic, user: user) } let(:group) { Fabricate(:group) } + let(:user) { Fabricate(:user) } + let(:post) { Fabricate(:post, user: user) } + + before do + SiteSetting.top_menu = 'latest|new|unread|categories' + end describe '#index' do it "doesn't throw an error with a negative page" do @@ -14,6 +20,24 @@ RSpec.describe ListController do get "/#{Discourse.anonymous_filters[1]}", params: { page: ['7'] } expect(response).to be_success end + + (Discourse.anonymous_filters - [:categories]).each do |filter| + context "#{filter}" do + it "succeeds" do + get "/#{filter}" + expect(response).to be_success + end + end + end + + it 'allows users to filter on a set of topic ids' do + p = create_post + + get "/latest.json", params: { topic_ids: "#{p.topic_id}" } + expect(response).to be_success + parsed = JSON.parse(response.body) + expect(parsed["topic_list"]["topics"].length).to eq(1) + end end describe "categories and X" do @@ -210,4 +234,346 @@ RSpec.describe ListController do end end end + + describe 'RSS feeds' do + it 'renders latest RSS' do + get "/latest.rss" + expect(response).to be_success + expect(response.content_type).to eq('application/rss+xml') + end + + it 'renders top RSS' do + get "/top.rss" + expect(response).to be_success + expect(response.content_type).to eq('application/rss+xml') + end + + TopTopic.periods.each do |period| + it "renders #{period} top RSS" do + get "/top/#{period}.rss" + expect(response).to be_success + expect(response.content_type).to eq('application/rss+xml') + end + end + end + + describe 'category' do + context 'in a category' do + let(:category) { Fabricate(:category) } + let(:group) { Fabricate(:group) } + let(:private_category) { Fabricate(:private_category, group: group) } + + context 'without access to see the category' do + it "responds with a 404 error" do + get "/c/#{private_category.slug}/l/latest" + expect(response.status).to eq(404) + end + end + + context 'with access to see the category' do + it "succeeds" do + get "/c/#{category.slug}/l/latest" + expect(response.status).to eq(200) + end + end + + context 'with a link that includes an id' do + it "succeeds" do + get "/c/#{category.id}-#{category.slug}/l/latest" + expect(response.status).to eq(200) + end + end + + context 'with a link that has a parent slug, slug and id in its path' do + let(:child_category) { Fabricate(:category, parent_category: category) } + + context "with valid slug" do + it "redirects to the child category" do + get "/c/#{category.slug}/#{child_category.slug}/l/latest", params: { + id: child_category.id + } + expect(response).to redirect_to(child_category.url) + end + end + + context "with invalid slug" do + it "redirects to child category" do + get "/c/random_slug/another_random_slug/l/latest", params: { + id: child_category.id + } + expect(response).to redirect_to(child_category.url) + end + end + end + + context 'another category exists with a number at the beginning of its name' do + # One category has another category's id at the beginning of its name + let!(:other_category) { Fabricate(:category, name: "#{category.id} name") } + + it 'uses the correct category' do + get "/c/#{other_category.slug}/l/latest.json" + expect(response).to be_success + body = JSON.parse(response.body) + expect(body["topic_list"]["topics"].first["category_id"]) + .to eq(other_category.id) + end + end + + context 'a child category' do + let(:sub_category) { Fabricate(:category, parent_category_id: category.id) } + + context 'when parent and child are requested' do + it "succeeds" do + get "/c/#{category.slug}/#{sub_category.slug}/l/latest" + expect(response.status).to eq(200) + end + end + + context 'when child is requested with the wrong parent' do + it "responds with a 404 error" do + get "/c/not-the-right-slug/#{sub_category.slug}/l/latest" + expect(response.status).to eq(404) + end + end + end + + describe 'feed' do + it 'renders RSS' do + get "/c/#{category.slug}.rss" + expect(response).to be_success + expect(response.content_type).to eq('application/rss+xml') + end + end + + describe "category default views" do + it "has a top default view" do + category.update_attributes!(default_view: 'top', default_top_period: 'monthly') + get "/c/#{category.slug}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["for_period"]).to eq("monthly") + end + + it "has a default view of nil" do + category.update_attributes!(default_view: nil) + get "/c/#{category.slug}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["for_period"]).to be_blank + end + + it "has a default view of ''" do + category.update_attributes!(default_view: '') + get "/c/#{category.slug}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["for_period"]).to be_blank + end + + it "has a default view of latest" do + category.update_attributes!(default_view: 'latest') + get "/c/#{category.slug}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["for_period"]).to be_blank + end + end + + describe "renders canonical tag" do + it 'for category default view' do + get "/c/#{category.slug}" + expect(response).to be_success + expect(css_select("link[rel=canonical]").length).to eq(1) + end + + it 'for category latest view' do + get "/c/#{category.slug}/l/latest" + expect(response).to be_success + expect(css_select("link[rel=canonical]").length).to eq(1) + end + end + end + end + + describe "topics_by" do + before do + sign_in(Fabricate(:user)) + Fabricate(:topic, user: user) + end + + it "should respond with a list" do + get "/topics/created-by/#{user.username}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["topics"].size).to eq(1) + end + end + + describe "private_messages" do + it "returns 403 error when the user can't see private message" do + sign_in(Fabricate(:user)) + get "/topics/private-messages/#{user.username}.json" + expect(response).to be_forbidden + end + + it "succeeds when the user can see private messages" do + pm = Fabricate(:private_message_topic, user: Fabricate(:user)) + pm.topic_allowed_users.create!(user: user) + sign_in(user) + get "/topics/private-messages/#{user.username}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["topics"].size).to eq(1) + end + end + + describe "private_messages_sent" do + before do + pm = Fabricate(:private_message_topic, user: user) + Fabricate(:post, user: user, topic: pm, post_number: 1) + end + + it "returns 403 error when the user can't see private message" do + sign_in(Fabricate(:user)) + get "/topics/private-messages-sent/#{user.username}.json" + expect(response).to be_forbidden + end + + it "succeeds when the user can see private messages" do + sign_in(user) + get "/topics/private-messages-sent/#{user.username}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["topics"].size).to eq(1) + end + end + + describe "private_messages_unread" do + before do + u = Fabricate(:user) + pm = Fabricate(:private_message_topic, user: u) + Fabricate(:post, user: u, topic: pm, post_number: 1) + pm.topic_allowed_users.create!(user: user) + end + + it "returns 403 error when the user can't see private message" do + sign_in(Fabricate(:user)) + get "/topics/private-messages-unread/#{user.username}.json" + expect(response).to be_forbidden + end + + it "succeeds when the user can see private messages" do + sign_in(user) + get "/topics/private-messages-unread/#{user.username}.json" + expect(response).to be_success + json = JSON.parse(response.body) + expect(json["topic_list"]["topics"].size).to eq(1) + end + end + + describe 'read' do + it 'raises an error when not logged in' do + get "/read" + expect(response.status).to eq(404) + end + + context 'when logged in' do + it "succeeds" do + sign_in(user) + get "/read" + expect(response).to be_success + end + end + end + + describe "best_periods_for" do + it "returns yearly for more than 180 days" do + expect(ListController.best_periods_for(nil, :all)).to eq([:yearly]) + expect(ListController.best_periods_for(180.days.ago, :all)).to eq([:yearly]) + end + + it "includes monthly when less than 180 days and more than 35 days" do + (35...180).each do |date| + expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:monthly, :yearly]) + end + end + + it "includes weekly when less than 35 days and more than 8 days" do + (8...35).each do |date| + expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:weekly, :monthly, :yearly]) + end + end + + it "includes daily when less than 8 days" do + (0...8).each do |date| + expect(ListController.best_periods_for(date.days.ago, :all)).to eq([:daily, :weekly, :monthly, :yearly]) + end + end + + it "returns default even for more than 180 days" do + expect(ListController.best_periods_for(nil, :monthly)).to eq([:monthly, :yearly]) + expect(ListController.best_periods_for(180.days.ago, :monthly)).to eq([:monthly, :yearly]) + end + + it "returns default even when less than 180 days and more than 35 days" do + (35...180).each do |date| + expect(ListController.best_periods_for(date.days.ago, :weekly)).to eq([:weekly, :monthly, :yearly]) + end + end + + it "returns default even when less than 35 days and more than 8 days" do + (8...35).each do |date| + expect(ListController.best_periods_for(date.days.ago, :daily)).to eq([:daily, :weekly, :monthly, :yearly]) + end + end + + it "doesn't return default when set to all" do + expect(ListController.best_periods_for(nil, :all)).to eq([:yearly]) + end + + it "doesn't return value twice when matches default" do + expect(ListController.best_periods_for(nil, :yearly)).to eq([:yearly]) + end + end + + describe "categories suppression" do + let(:category_one) { Fabricate(:category) } + let(:sub_category) { Fabricate(:category, parent_category: category_one, suppress_from_latest: true) } + let!(:topic_in_sub_category) { Fabricate(:topic, category: sub_category) } + + let(:category_two) { Fabricate(:category, suppress_from_latest: true) } + let!(:topic_in_category_two) { Fabricate(:topic, category: category_two) } + + it "suppresses categories from the latest list" do + get "/#{SiteSetting.homepage}.json" + expect(response).to be_success + + topic_titles = JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["title"] } + expect(topic_titles).not_to include(topic_in_sub_category.title, topic_in_category_two.title) + end + + it "does not suppress" do + get "/#{SiteSetting.homepage}.json", params: { category: category_one.id } + expect(response).to be_success + + topic_titles = JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["title"] } + expect(topic_titles).to include(topic_in_sub_category.title) + end + end + + describe "safe mode" do + it "handles safe mode" do + get "/latest" + expect(response.body).to match(/plugin\.js/) + expect(response.body).to match(/plugin-third-party\.js/) + + get "/latest", params: { safe_mode: "no_plugins" } + expect(response.body).not_to match(/plugin\.js/) + expect(response.body).not_to match(/plugin-third-party\.js/) + + get "/latest", params: { safe_mode: "only_official" } + expect(response.body).to match(/plugin\.js/) + expect(response.body).not_to match(/plugin-third-party\.js/) + end + end end