diff --git a/app/services/article_api_index_service.rb b/app/services/article_api_index_service.rb index a39e8b0d2..66f9c1a03 100644 --- a/app/services/article_api_index_service.rb +++ b/app/services/article_api_index_service.rb @@ -1,5 +1,8 @@ class ArticleApiIndexService - attr_accessor :tag, :username, :page, :state, :top, :collection_id + attr_accessor :tag, :username, :page, :state, :top, :collection_id, :per_page + + DEFAULT_PER_PAGE = 30 + MAX_PER_PAGE = 1000 def initialize(params) @page = params[:page] @@ -8,6 +11,7 @@ class ArticleApiIndexService @state = params[:state] @top = params[:top] @collection_id = params[:collection_id] + @per_page = params[:per_page] end def get @@ -32,9 +36,9 @@ class ArticleApiIndexService def username_articles num = if @state == "all" - 1000 + MAX_PER_PAGE else - 30 + DEFAULT_PER_PAGE end if (user = User.find_by(username: username)) @@ -42,13 +46,13 @@ class ArticleApiIndexService includes(:organization). order("published_at DESC"). page(page). - per(num) + per(per_page || num) elsif (organization = Organization.find_by(slug: username)) organization.articles.published. includes(:user). order("published_at DESC"). page(page). - per(num) + per(per_page || num) else Article.none end @@ -66,12 +70,12 @@ class ArticleApiIndexService articles.order("hotness_score DESC") end - articles.page(page).per(30) + articles.page(page).per(per_page || DEFAULT_PER_PAGE) end def top_articles Article.published.order("positive_reactions_count DESC").where("published_at > ?", top.to_i.days.ago). - page(page).per(30) + page(page).per(per_page || DEFAULT_PER_PAGE) end def state_articles(state) @@ -90,7 +94,7 @@ class ArticleApiIndexService includes(:user, :organization). order("published_at"). page(page). - per(30) + per(per_page || DEFAULT_PER_PAGE) end def base_articles @@ -99,6 +103,6 @@ class ArticleApiIndexService includes(:user, :organization). order("hotness_score DESC"). page(page). - per(30) + per(per_page || DEFAULT_PER_PAGE) end end diff --git a/spec/requests/api/v0/articles_spec.rb b/spec/requests/api/v0/articles_spec.rb index f6d1eddb4..8edb825f8 100644 --- a/spec/requests/api/v0/articles_spec.rb +++ b/spec/requests/api/v0/articles_spec.rb @@ -9,74 +9,132 @@ RSpec.describe "Api::V0::Articles", type: :request do end describe "GET /api/articles" do - it "returns json response" do - get api_articles_path - expect(response.content_type).to eq("application/json") + context "without params" do + it "returns json response" do + get api_articles_path + expect(response.content_type).to eq("application/json") + end + + it "returns featured articles if no param is given" do + article.update_column(:featured, true) + get api_articles_path + expect(json_response.size).to eq(1) + end + + it "supports pagination" do + create_list(:article, 2, featured: true) + get api_articles_path, params: { page: 1, per_page: 2 } + expect(json_response.length).to eq(2) + get api_articles_path, params: { page: 2, per_page: 2 } + expect(json_response.length).to eq(1) + end + + it "returns flare tag in the response" do + get api_articles_path + response_article = JSON.parse(response.body)[0] + expect(response_article["flare_tag"]).to be_present + expect(response_article["flare_tag"].keys).to eq(%w[name bg_color_hex text_color_hex]) + expect(response_article["flare_tag"]["name"]).to eq("discuss") + end end - it "returns featured articles if no param is given" do - article.update_column(:featured, true) - get api_articles_path - expect(json_response.size).to eq(1) + context "with username param" do + it "returns user's articles for the given username" do + create(:article, user: article.user) + get api_articles_path(username: article.user.username) + expect(json_response.size).to eq(2) + end + + it "returns nothing if given user is not found" do + get api_articles_path(username: "foobar") + expect(json_response.size).to eq(0) + end + + it "returns org's articles if org's slug is given" do + create(:article, user: article.user, organization: organization) + get api_articles_path(username: organization.slug) + expect(json_response.size).to eq(1) + end + + it "supports pagination" do + create_list(:article, 2, user: article.user) + get api_articles_path(username: article.user.username), params: { page: 1, per_page: 2 } + expect(json_response.length).to eq(2) + get api_articles_path(username: article.user.username), params: { page: 2, per_page: 2 } + expect(json_response.length).to eq(1) + end end - it "returns user's articles for the given username" do - create(:article, user: article.user) - get api_articles_path(username: article.user.username) - expect(json_response.size).to eq(2) + context "with tag param" do + it "returns tag's articles" do + get api_articles_path(tag: article.tag_list.first) + expect(json_response.size).to eq(1) + end + + it "returns top tag articles if tag and top param is present" do + get api_articles_path(tag: article.tag_list.first, top: "7") + expect(json_response.size).to eq(1) + end + + it "returns not tag articles if article and tag are not approved" do + article.update_column(:approved, false) + tag = Tag.find_by(name: article.tag_list.first) + tag.update(requires_approval: true) + + get api_articles_path(tag: tag.name) + expect(JSON.parse(response.body).size).to eq(0) + end + + it "supports pagination" do + create_list(:article, 2, tags: "discuss") + get api_articles_path(tag: article.tag_list.first), params: { page: 1, per_page: 2 } + expect(json_response.length).to eq(2) + get api_articles_path(tag: article.tag_list.first), params: { page: 2, per_page: 2 } + expect(json_response.length).to eq(1) + end end - it "returns nothing if given user is not found" do - get api_articles_path(username: "foobar") - expect(json_response.size).to eq(0) + context "with top param" do + it "only returns fresh top articles if top param is present" do + # TODO: slight duplication, test should be removed + old_article = create(:article) + old_article.update_column(:published_at, 10.days.ago) + get api_articles_path(top: "7") + expect(json_response.size).to eq(1) + end + + it "supports pagination" do + old_articles = create_list(:article, 2, featured: true) + old_articles.each do |old_article| + old_article.update_column(:published_at, 10.days.ago) + end + get api_articles_path(top: "11"), params: { page: 1, per_page: 2 } + expect(json_response.length).to eq(2) + get api_articles_path(top: "11"), params: { page: 2, per_page: 2 } + expect(json_response.length).to eq(1) + end end - it "returns org's articles if org's slug is given" do - create(:article, user: article.user, organization: organization) - get api_articles_path(username: organization.slug) - expect(json_response.size).to eq(1) - end + context "with collection_id param" do + it "returns a collection id" do + collection = create(:collection, user: article.user) + article.update_columns(collection_id: collection.id) + get api_articles_path(collection_id: collection.id) + expect(json_response[0]["collection_id"]).to eq collection.id + end - it "returns tag's articles" do - get api_articles_path(tag: article.tag_list.first) - expect(json_response.size).to eq(1) - end - - it "returns top tag articles if tag and top param is present" do - get api_articles_path(tag: article.tag_list.first, top: "7") - expect(json_response.size).to eq(1) - end - - it "only returns fresh top articles if top param is present" do - # TODO: slight duplication, test should be removed - old_article = create(:article) - old_article.update_column(:published_at, 10.days.ago) - get api_articles_path(top: "7") - expect(json_response.size).to eq(1) - end - - it "returns not tag articles if article and tag are not approved" do - article.update_column(:approved, false) - tag = Tag.find_by(name: article.tag_list.first) - tag.update(requires_approval: true) - - get api_articles_path(tag: tag.name) - expect(JSON.parse(response.body).size).to eq(0) - end - - it "returns flare tag in the response" do - get api_articles_path - response_article = JSON.parse(response.body)[0] - expect(response_article["flare_tag"]).to be_present - expect(response_article["flare_tag"].keys).to eq(%w[name bg_color_hex text_color_hex]) - expect(response_article["flare_tag"]["name"]).to eq("discuss") - end - - it "returns a collection id" do - collection = create(:collection, user: article.user) - article.update_columns(collection_id: collection.id) - get api_articles_path(collection_id: collection.id) - expect(json_response[0]["collection_id"]).to eq collection.id + it "supports pagination" do + collection = create(:collection, user: article.user) + article.update_columns(collection_id: collection.id) + collection_articles = create_list(:article, 2, featured: true) + collection_articles.each do |collection_article| + collection_article.update_columns(collection_id: collection.id) + end + get api_articles_path(collection_id: collection.id), params: { page: 1, per_page: 2 } + expect(json_response.length).to eq(2) + get api_articles_path(collection_id: collection.id), params: { page: 2, per_page: 2 } + expect(json_response.length).to eq(1) + end end end