FEATURE: Use async search for category dropdowns (#23774)

This commit introduces a new endpoint to search categories and uses it
instead of the categories map that is preloaded using SiteSerializer.

This feature is enabled only when the hidden site setting
lazy_load_categories is enabled and should be used only on sites with
many categories.
This commit is contained in:
Bianca Nenciu
2023-10-17 19:46:54 +03:00
committed by GitHub
parent 60ae69027c
commit 2e68ead45b
11 changed files with 257 additions and 64 deletions

View File

@ -1039,4 +1039,128 @@ RSpec.describe CategoriesController do
expect(response.parsed_body["groups"]).to eq([])
end
end
describe "#search" do
fab!(:category) { Fabricate(:category, name: "Foo") }
fab!(:subcategory) { Fabricate(:category, name: "Foobar", parent_category: category) }
fab!(:category2) { Fabricate(:category, name: "Notfoo") }
before do
SearchIndexer.enable
[category, category2, subcategory].each { |c| SearchIndexer.index(c, force: true) }
end
context "with term" do
it "returns categories" do
get "/categories/search.json", params: { term: "Foo" }
expect(response.parsed_body["categories"].size).to eq(2)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Foo",
"Foobar",
)
end
end
context "with parent_category_id" do
it "returns categories" do
get "/categories/search.json", params: { parent_category_id: category.id }
expect(response.parsed_body["categories"].size).to eq(2)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Foo",
"Foobar",
)
end
end
context "with include_uncategorized" do
it "returns Uncategorized" do
get "/categories/search.json", params: { include_uncategorized: true }
expect(response.parsed_body["categories"].size).to eq(4)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Uncategorized",
"Foo",
"Foobar",
"Notfoo",
)
end
it "does not return Uncategorized" do
get "/categories/search.json", params: { include_uncategorized: false }
expect(response.parsed_body["categories"].size).to eq(3)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Foo",
"Foobar",
"Notfoo",
)
end
end
context "with select_category_ids" do
it "returns categories" do
get "/categories/search.json", params: { select_category_ids: [category.id] }
expect(response.parsed_body["categories"].size).to eq(1)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly("Foo")
end
end
context "with reject_category_ids" do
it "returns categories" do
get "/categories/search.json", params: { reject_category_ids: [category2.id] }
expect(response.parsed_body["categories"].size).to eq(3)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Uncategorized",
"Foo",
"Foobar",
)
end
end
context "with include_subcategories" do
it "returns categories" do
get "/categories/search.json", params: { include_subcategories: false }
expect(response.parsed_body["categories"].size).to eq(3)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Uncategorized",
"Foo",
"Notfoo",
)
end
it "returns categories and subcategories" do
get "/categories/search.json", params: { include_subcategories: true }
expect(response.parsed_body["categories"].size).to eq(4)
expect(response.parsed_body["categories"].map { |c| c["name"] }).to contain_exactly(
"Uncategorized",
"Foo",
"Foobar",
"Notfoo",
)
end
end
context "with prioritized_category_id" do
it "returns categories" do
get "/categories/search.json", params: { prioritized_category_id: category2.id }
expect(response.parsed_body["categories"].size).to eq(4)
expect(response.parsed_body["categories"][0]["name"]).to eq("Notfoo")
end
end
context "with limit" do
it "returns categories" do
get "/categories/search.json", params: { limit: 2 }
expect(response.parsed_body["categories"].size).to eq(2)
end
end
end
end