From e3e9efe68462853c1570b5059f2e79d54301e383 Mon Sep 17 00:00:00 2001 From: Codex Night Worker Date: Fri, 13 Nov 2026 12:40:14 +0900 Subject: [PATCH] AI: address review on PR #458 --- backend/spec/requests/tags_spec.rb | 44 +++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/backend/spec/requests/tags_spec.rb b/backend/spec/requests/tags_spec.rb index 7a66889..39bc0d5 100644 --- a/backend/spec/requests/tags_spec.rb +++ b/backend/spec/requests/tags_spec.rb @@ -482,6 +482,7 @@ RSpec.describe 'Tags API', type: :request do create(:tag, category: :general, primary_name: name, post_count: 1) create(:external_tag, name:, post_count: 1) end + create(:external_tag, name: 'suffix_combined', post_count: 100) get '/tags/autocomplete', params: { q: 'combined' } @@ -490,6 +491,39 @@ RSpec.describe 'Tags API', type: :request do expect(json.map { |row| row.fetch('name') }).to eq(expected.first(20)) end + it 'appends primary, alias, and external suffix matches without duplicate resources' do + prefix = create(:tag, primary_name: 'tail', post_count: 1) + create(:tag_name, :alias, name: 'tail_alias', tag: prefix) + create(:tag_name, :alias, name: 'alias_tail', tag: prefix) + create(:tag, primary_name: 'primary_tail', post_count: 4) + alias_target = create(:tag, primary_name: 'alias_target', post_count: 3) + create(:tag_name, :alias, name: 'suffix_tail', tag: alias_target) + external = create(:external_tag, id: prefix.id, name: 'external_tail', post_count: 5) + create(:tag, primary_name: 'middle_tail_only', post_count: 100) + create(:external_tag, name: 'middle_tail_only', post_count: 100) + + get '/tags/autocomplete', params: { q: 'tail' } + + expect(response).to have_http_status(:ok) + expect(json.map { |row| row.fetch('name') }).to eq( + ['tail', 'nico:external_tail', 'primary_tail', 'alias_target']) + expect(json.first.fetch('matched_alias')).to eq('tail_alias') + expect(json.last.fetch('matched_alias')).to eq('suffix_tail') + expect(json[1]).to include('id' => external.id, 'category' => 'nico') + end + + it 'fills only the remaining places with suffix matches' do + names = 19.times.map { |number| "capacity_#{ number.to_s.rjust(2, '0') }" } + names.each { create(:tag, primary_name: _1, post_count: 1) } + create(:tag, primary_name: 'first_capacity', post_count: 3) + create(:external_tag, name: 'second_capacity', post_count: 2) + + get '/tags/autocomplete', params: { q: 'capacity' } + + expect(response).to have_http_status(:ok) + expect(json.map { |row| row.fetch('name') }).to eq(names + ['first_capacity']) + end + it 'excludes external tags but preserves internal alias matches when nico is false' do internal = create(:tag, category: :general, primary_name: 'switch_internal', post_count: 1) alias_target = create(:tag, category: :general, primary_name: 'alias_target', post_count: 1) @@ -518,12 +552,20 @@ RSpec.describe 'Tags API', type: :request do create(:external_tag, name: literal, post_count: 1) create(:tag, category: :general, primary_name: 'literalXmatch', post_count: 2) create(:external_tag, name: 'literalXmatch', post_count: 2) + suffix = "suffix_literal#{ wildcard }" + create(:tag, primary_name: suffix, post_count: 1) + suffix_alias = create(:tag, primary_name: 'suffix_alias_target', post_count: 1) + create(:tag_name, :alias, name: "alias_#{ suffix }", tag: suffix_alias) + create(:external_tag, name: suffix, post_count: 1) + create(:tag, primary_name: 'suffix_literalX', post_count: 2) + create(:external_tag, name: 'suffix_literalX', post_count: 2) get '/tags/autocomplete', params: { q: "literal#{ wildcard }" } expect(json.map { |row| row.fetch('name') }) .to contain_exactly( - literal, primary_tag_name_for(alias_target, 'ja').name, "nico:#{ literal }") + literal, primary_tag_name_for(alias_target, 'ja').name, "nico:#{ literal }", + suffix, 'suffix_alias_target', "nico:#{ suffix }") end end