FIX: Category hashtags weren't always found for sub-sub-categories (#20156)

The algorithm failed to find the correct category by slug when there are multiple sub-sub-categories with the same child-category name and the first child doesn't  have the correct grandchild.

So, searching for "child / grandchild" worked in the following case, it found (3):

- (1) parent 1
  - (2) child
    - (3) grandchild
- (4) parent 2
  - (5) child
    - (6) grandchild

But it failed to find the grandchild in the following case:

- (1) parent 1
  - (2) child
- (4) parent 2
  - (5) child
    - (6) grandchild

And this also fixes a flaky spec by forcing categories to always order by by `parent_category_id` and `id`.
This makes it possible to partly revert 60990aab55
This commit is contained in:
Gerhard Schlager
2023-02-03 12:17:52 +01:00
committed by GitHub
parent 6c80e17b92
commit e17c145e8d
4 changed files with 58 additions and 9 deletions

View File

@@ -275,6 +275,8 @@ RSpec.describe HashtagsController do
qux = Fabricate(:category_with_definition, slug: "qux")
quxbar = Fabricate(:category_with_definition, slug: "bar", parent_category_id: qux.id)
quxbarbaz =
Fabricate(:category_with_definition, slug: "baz", parent_category_id: quxbar.id)
invalid_slugs = [":"]
child_slugs = %w[bar baz]

View File

@@ -40,6 +40,47 @@ RSpec.describe CategoryHashtagDataSource do
group.add(user)
expect(described_class.lookup(Guardian.new(user), ["secret"]).first).not_to eq(nil)
end
context "with sub-sub-categories" do
before { SiteSetting.max_category_nesting = 3 }
it "returns the first matching grandchild category (ordered by IDs) when there are multiple categories with the same slug" do
parent1 = Fabricate(:category, slug: "parent1")
parent2 = Fabricate(:category, slug: "parent2")
parent1_child = Fabricate(:category, slug: "child", parent_category_id: parent1.id)
parent1_child_grandchild =
Fabricate(:category, slug: "grandchild", parent_category_id: parent1_child.id)
parent2_child = Fabricate(:category, slug: "child", parent_category_id: parent2.id)
parent2_child_grandchild =
Fabricate(:category, slug: "grandchild", parent_category_id: parent2_child.id)
result = described_class.lookup(guardian, ["child:grandchild"])
expect(result.map(&:relative_url)).to eq([parent1_child_grandchild.url])
parent1_child.destroy
parent1_child = Fabricate(:category, slug: "child", parent_category_id: parent1.id)
result = described_class.lookup(guardian, ["child:grandchild"])
expect(result.map(&:relative_url)).to eq([parent2_child_grandchild.url])
end
it "returns the correct grandchild category when there are multiple children with the same slug and only one of them has the correct grandchild" do
parent1 = Fabricate(:category, slug: "parent1")
parent1_child = Fabricate(:category, slug: "child", parent_category_id: parent1.id)
parent1_child_grandchild =
Fabricate(:category, slug: "another-grandchild", parent_category_id: parent1_child.id)
parent2 = Fabricate(:category, slug: "parent2")
parent2_child = Fabricate(:category, slug: "child", parent_category_id: parent2.id)
parent2_child_grandchild =
Fabricate(:category, slug: "grandchild", parent_category_id: parent2_child.id)
result = described_class.lookup(guardian, ["child:grandchild"])
expect(result.map(&:relative_url)).to eq([parent2_child_grandchild.url])
end
end
end
describe "#search" do