| @@ -15,7 +15,7 @@ RSpec.describe 'Posts API', type: :request do | |||
| end | |||
| let!(:tag_name) { TagName.create!(name: 'spec_tag') } | |||
| let!(:tag) { Tag.create!(tag_name: tag_name, category: 'general') } | |||
| let!(:tag) { Tag.create!(tag_name: tag_name, category: :general) } | |||
| let!(:post_record) do | |||
| Post.create!(title: 'spec post', url: 'https://example.com/spec').tap do |p| | |||
| @@ -27,9 +27,9 @@ RSpec.describe 'Posts API', type: :request do | |||
| let!(:user) { create_member_user! } | |||
| let!(:tag_name) { TagName.create!(name: "spec_tag") } | |||
| let!(:tag) { Tag.create!(tag_name:, category: "general") } | |||
| let!(:tag) { Tag.create!(tag_name:, category: :general) } | |||
| let!(:tag_name2) { TagName.create!(name: 'unko') } | |||
| let!(:tag2) { Tag.create!(tag_name: tag_name2, category: 'deerjikist') } | |||
| let!(:tag2) { Tag.create!(tag_name: tag_name2, category: :deerjikist) } | |||
| let!(:alias_tag_name) { TagName.create!(name: 'manko', canonical: tag_name) } | |||
| let!(:hit_post) do | |||
| @@ -114,6 +114,123 @@ RSpec.describe 'Posts API', type: :request do | |||
| expect(json.fetch('count')).to eq(0) | |||
| end | |||
| end | |||
| context 'when tags contain not:' do | |||
| let!(:foo_tag_name) { TagName.create!(name: 'not_spec_foo') } | |||
| let!(:foo_tag) { Tag.create!(tag_name: foo_tag_name, category: :general) } | |||
| let!(:bar_tag_name) { TagName.create!(name: 'not_spec_bar') } | |||
| let!(:bar_tag) { Tag.create!(tag_name: bar_tag_name, category: :general) } | |||
| let!(:baz_tag_name) { TagName.create!(name: 'not_spec_baz') } | |||
| let!(:baz_tag) { Tag.create!(tag_name: baz_tag_name, category: :general) } | |||
| let!(:foo_alias_tag_name) do | |||
| TagName.create!(name: 'not_spec_foo_alias', canonical: foo_tag_name) | |||
| end | |||
| let!(:foo_only_post) do | |||
| Post.create!(uploaded_user: user, title: 'foo only', | |||
| url: 'https://example.com/not-spec-foo').tap do |p| | |||
| PostTag.create!(post: p, tag: foo_tag) | |||
| end | |||
| end | |||
| let!(:bar_only_post) do | |||
| Post.create!(uploaded_user: user, title: 'bar only', | |||
| url: 'https://example.com/not-spec-bar').tap do |p| | |||
| PostTag.create!(post: p, tag: bar_tag) | |||
| end | |||
| end | |||
| let!(:baz_only_post) do | |||
| Post.create!(uploaded_user: user, title: 'baz only', | |||
| url: 'https://example.com/not-spec-baz').tap do |p| | |||
| PostTag.create!(post: p, tag: baz_tag) | |||
| end | |||
| end | |||
| let!(:foo_bar_post) do | |||
| Post.create!(uploaded_user: user, title: 'foo bar', | |||
| url: 'https://example.com/not-spec-foo-bar').tap do |p| | |||
| PostTag.create!(post: p, tag: foo_tag) | |||
| PostTag.create!(post: p, tag: bar_tag) | |||
| end | |||
| end | |||
| let!(:foo_baz_post) do | |||
| Post.create!(uploaded_user: user, title: 'foo baz', | |||
| url: 'https://example.com/not-spec-foo-baz').tap do |p| | |||
| PostTag.create!(post: p, tag: foo_tag) | |||
| PostTag.create!(post: p, tag: baz_tag) | |||
| end | |||
| end | |||
| let(:controlled_ids) do | |||
| [foo_only_post.id, bar_only_post.id, baz_only_post.id, | |||
| foo_bar_post.id, foo_baz_post.id] | |||
| end | |||
| it 'supports not search' do | |||
| get '/posts', params: { tags: 'not:not_spec_foo' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [bar_only_post.id, baz_only_post.id] | |||
| ) | |||
| end | |||
| it 'supports alias in not search' do | |||
| get '/posts', params: { tags: 'not:not_spec_foo_alias' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [bar_only_post.id, baz_only_post.id] | |||
| ) | |||
| end | |||
| it 'treats multiple not terms as AND when match is omitted' do | |||
| get '/posts', params: { tags: 'not:not_spec_foo not:not_spec_bar' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [baz_only_post.id] | |||
| ) | |||
| end | |||
| it 'treats multiple not terms as OR when match=any' do | |||
| get '/posts', params: { tags: 'not:not_spec_foo not:not_spec_bar', match: 'any' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [foo_only_post.id, bar_only_post.id, baz_only_post.id, foo_baz_post.id] | |||
| ) | |||
| end | |||
| it 'supports mixed positive and negative search with AND' do | |||
| get '/posts', params: { tags: 'not_spec_foo not:not_spec_bar' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [foo_only_post.id, foo_baz_post.id] | |||
| ) | |||
| end | |||
| it 'supports mixed positive and negative search with OR when match=any' do | |||
| get '/posts', params: { tags: 'not_spec_foo not:not_spec_bar', match: 'any' } | |||
| expect(response).to have_http_status(:ok) | |||
| expect(json.fetch('posts').map { |p| p['id'] } & controlled_ids).to match_array( | |||
| [foo_only_post.id, baz_only_post.id, foo_bar_post.id, foo_baz_post.id] | |||
| ) | |||
| end | |||
| end | |||
| end | |||
| describe 'GET /posts/:id' do | |||
| @@ -210,7 +327,7 @@ RSpec.describe 'Posts API', type: :request do | |||
| context "when nico tag already exists in tags" do | |||
| before do | |||
| Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), | |||
| category: 'nico') | |||
| category: :nico) | |||
| end | |||
| it 'return 400' do | |||
| @@ -276,7 +393,7 @@ RSpec.describe 'Posts API', type: :request do | |||
| # 追加で別タグも作って、更新時に入れ替わることを見る | |||
| tn2 = TagName.create!(name: 'spec_tag_2') | |||
| Tag.create!(tag_name: tn2, category: 'general') | |||
| Tag.create!(tag_name: tn2, category: :general) | |||
| put "/posts/#{post_record.id}", params: { | |||
| title: 'updated title', | |||
| @@ -295,7 +412,7 @@ RSpec.describe 'Posts API', type: :request do | |||
| context "when nico tag already exists in tags" do | |||
| before do | |||
| Tag.find_or_create_by!(tag_name: TagName.find_or_create_by!(name: 'nico:nico_tag'), | |||
| category: 'nico') | |||
| category: :nico) | |||
| end | |||
| it 'return 400' do | |||
| @@ -332,7 +449,7 @@ RSpec.describe 'Posts API', type: :request do | |||
| it 'returns add/remove events (history) for a post' do | |||
| # add | |||
| tn2 = TagName.create!(name: 'spec_tag2') | |||
| tag2 = Tag.create!(tag_name: tn2, category: 'general') | |||
| tag2 = Tag.create!(tag_name: tn2, category: :general) | |||
| pt = PostTag.create!(post: post_record, tag: tag2, created_user: member) | |||
| # remove (discard) | |||