From a3914fb22a86f3795744fd8a4324f4d96f99d6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BF=E3=81=A6=E3=82=8B=E3=81=9E?= Date: Sat, 11 Apr 2026 22:13:19 +0900 Subject: [PATCH] =?UTF-8?q?posts=20=E5=B1=A5=E6=AD=B4=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=88RSpec=20=E4=BF=AE=E6=AD=A3=EF=BC=89=EF=BC=88#264?= =?UTF-8?q?=EF=BC=89=20(#310)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge remote-tracking branch 'origin/main' into feature/264 Merge branch 'feature/264' of https://git.miteruzo.com/miteruzo/btrc-hub into feature/264 #264 Merge branch 'main' into feature/264 #264 #264 #264 #264 Co-authored-by: miteruzo Reviewed-on: https://git.miteruzo.com/miteruzo/btrc-hub/pulls/310 --- backend/spec/models/tag_spec.rb | 65 ++++++++++++++ backend/spec/tasks/nico_sync_spec.rb | 124 +++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/backend/spec/models/tag_spec.rb b/backend/spec/models/tag_spec.rb index a9fc35e..1dee732 100644 --- a/backend/spec/models/tag_spec.rb +++ b/backend/spec/models/tag_spec.rb @@ -145,5 +145,70 @@ RSpec.describe Tag, type: :model do expect(target_tag.reload.post_count).to eq(0) end end + + def snapshot_tags(post) + post.snapshot_tag_names.join(' ') + end + + def create_post_version_for!(post, version_no: 1, event_type: 'create', created_by_user: nil) + PostVersion.create!( + post: post, + version_no: version_no, + event_type: event_type, + title: post.title, + url: post.url, + thumbnail_base: post.thumbnail_base, + tags: snapshot_tags(post), + parent: post.parent, + original_created_from: post.original_created_from, + original_created_before: post.original_created_before, + created_at: Time.current, + created_by_user: created_by_user + ) + end + + context 'when post versions are enabled' do + let!(:source_post_tag) { PostTag.create!(post: post_record, tag: source_tag) } + let!(:unaffected_post) do + Post.create!(url: 'https://example.com/posts/2', title: 'unaffected post') + end + + before do + create_post_version_for!(post_record) + create_post_version_for!(unaffected_post) + end + + it 'creates an update post_version only for affected posts' do + expect { + described_class.merge_tags!(target_tag, [source_tag]) + }.to change(PostVersion, :count).by(1) + + affected_versions = post_record.reload.post_versions.order(:version_no) + expect(affected_versions.pluck(:version_no)).to eq([1, 2]) + + latest = affected_versions.last + expect(latest.event_type).to eq('update') + expect(latest.created_by_user).to be_nil + expect(latest.tags).to eq(snapshot_tags(post_record.reload)) + + expect(unaffected_post.reload.post_versions.count).to eq(1) + end + end + + context 'when the source tag has no active post_tags' do + let!(:another_post) do + Post.create!(url: 'https://example.com/posts/3', title: 'another post') + end + + before do + create_post_version_for!(another_post) + end + + it 'does not create any post_version' do + expect { + described_class.merge_tags!(target_tag, [source_tag]) + }.not_to change(PostVersion, :count) + end + end end end diff --git a/backend/spec/tasks/nico_sync_spec.rb b/backend/spec/tasks/nico_sync_spec.rb index d4f0e09..ff64490 100644 --- a/backend/spec/tasks/nico_sync_spec.rb +++ b/backend/spec/tasks/nico_sync_spec.rb @@ -90,4 +90,128 @@ RSpec.describe "nico:sync" do expect(active_names).to include("nico:NEW") expect(active_names).not_to include("nico:OLD") end + + def snapshot_tags(post) + post.snapshot_tag_names.join(' ') + end + + def create_post_version_for!(post, version_no: 1, event_type: 'create', created_by_user: nil) + PostVersion.create!( + post: post, + version_no: version_no, + event_type: event_type, + title: post.title, + url: post.url, + thumbnail_base: post.thumbnail_base, + tags: snapshot_tags(post), + parent: post.parent, + original_created_from: post.original_created_from, + original_created_before: post.original_created_before, + created_at: Time.current, + created_by_user: created_by_user + ) + end + + it '新規 post 作成時に version 1 を作る' do + Tag.bot + Tag.tagme + Tag.niconico + Tag.video + Tag.no_deerjikist + + stub_python([{ + 'code' => 'sm9', + 'title' => 't', + 'tags' => ['AAA'], + 'uploaded_at' => '2026-01-01 12:34:56' + }]) + + allow(URI).to receive(:open).and_return(StringIO.new('')) + + expect { + run_rake_task('nico:sync') + }.to change(PostVersion, :count).by(1) + + post = Post.find_by!(url: 'https://www.nicovideo.jp/watch/sm9') + version = post.post_versions.order(:version_no).last + + expect(version.version_no).to eq(1) + expect(version.event_type).to eq('create') + expect(version.created_by_user).to be_nil + expect(version.tags).to eq(snapshot_tags(post.reload)) + end + + it '既存 post の内容または tags が変わったとき update version を作る' do + post = Post.create!( + title: 'old', + url: 'https://www.nicovideo.jp/watch/sm9', + uploaded_user: nil + ) + + kept_general = create_tag!('spec_kept', category: 'general') + PostTag.create!(post: post, tag: kept_general) + create_post_version_for!(post) + + linked = create_tag!('spec_linked', category: 'general') + nico = create_tag!('nico:AAA', category: 'nico') + link_nico_to_tag!(nico, linked) + + Tag.bot + Tag.tagme + Tag.no_deerjikist + + stub_python([{ + 'code' => 'sm9', + 'title' => 't', + 'tags' => ['AAA'], + 'uploaded_at' => '2026-01-01 12:34:56' + }]) + + allow(URI).to receive(:open).and_return(StringIO.new('')) + + expect { + run_rake_task('nico:sync') + }.to change(PostVersion, :count).by(1) + + version = post.reload.post_versions.order(:version_no).last + expect(version.version_no).to eq(2) + expect(version.event_type).to eq('update') + expect(version.created_by_user).to be_nil + expect(version.tags).to eq(snapshot_tags(post.reload)) + end + + it '既存 post に差分が無いときは新しい version を作らない' do + nico = create_tag!('nico:AAA', category: 'nico') + no_deerjikist = create_tag!('ニジラー情報不詳', category: 'meta') + + post = Post.create!( + title: 't', + url: 'https://www.nicovideo.jp/watch/sm9', + uploaded_user: nil, + original_created_from: Time.iso8601('2026-01-01T03:34:00Z'), + original_created_before: Time.iso8601('2026-01-01T03:35:00Z') + ) + + PostTag.create!(post: post, tag: nico) + PostTag.create!(post: post, tag: no_deerjikist) + create_post_version_for!(post) + + stub_python([{ + 'code' => 'sm9', + 'title' => 't', + 'tags' => ['AAA'], + 'uploaded_at' => '2026-01-01 12:34:56' + }]) + + allow(URI).to receive(:open).and_return(StringIO.new('')) + + expect { + run_rake_task('nico:sync') + }.not_to change(PostVersion, :count) + + version = post.reload.post_versions.order(:version_no).last + expect(version.version_no).to eq(1) + expect(version.event_type).to eq('create') + expect(version.tags).to eq(snapshot_tags(post.reload)) + end end