# frozen_string_literal: true require 'rails_helper' RSpec.describe ArtifactImportService, type: :service do let(:user) { create(:user) } # Create artifacts with specific granblue_ids matching the game data let(:standard_artifact) do Artifact.find_by(granblue_id: '301070101') || create(:artifact, granblue_id: '301070101', name_en: 'Ominous Bangle', proficiency: :melee) end let(:standard_artifact_2) do Artifact.find_by(granblue_id: '301090101') || create(:artifact, granblue_id: '301090101', name_en: 'Ominous Whistle', proficiency: :gun) end let(:quirk_artifact) do Artifact.find_by(granblue_id: '401110401') || create(:artifact, :quirk, granblue_id: '401110401', name_en: 'Fantosmik Fengtooth') end # Create artifact skills for the skill lookups before do # Create artifacts standard_artifact standard_artifact_2 quirk_artifact # Group I skills ArtifactSkill.find_by(skill_group: 1, modifier: 2) || create(:artifact_skill, :group_i, modifier: 2, name_en: 'HP', name_jp: 'HP', base_values: [660, 720, 780, 840, 900]) ArtifactSkill.find_by(skill_group: 1, modifier: 5) || create(:artifact_skill, :group_i, modifier: 5, name_en: 'Elemental ATK', name_jp: '自属性攻撃力', base_values: [8.8, 9.6, 10.4, 11.2, 12.0]) ArtifactSkill.find_by(skill_group: 1, modifier: 11) || create(:artifact_skill, :group_i, modifier: 11, name_en: 'Dodge Rate', name_jp: '回避率', base_values: [4.4, 4.8, 5.2, 5.6, 6.0]) # Group II skills ArtifactSkill.find_by(skill_group: 2, modifier: 2) || create(:artifact_skill, :group_ii, modifier: 2, name_en: 'Skill DMG Cap', name_jp: 'アビダメ上限', base_values: [8.8, 9.6, 10.4, 11.2, 12.0]) ArtifactSkill.find_by(skill_group: 2, modifier: 8) || create(:artifact_skill, :group_ii, modifier: 8, name_en: 'C.A. DMG cap boost tradeoff', name_jp: '奥義ダメ上限UP', base_values: [13.2, 14.4, 15.6, 16.8, 18.0]) # Group III skills ArtifactSkill.find_by(skill_group: 3, modifier: 5) || create(:artifact_skill, :group_iii, modifier: 5, name_en: 'Switch amplified', name_jp: 'バトル登場時', base_values: [3, 6, 9, 12, 15]) ArtifactSkill.find_by(skill_group: 3, modifier: 25) || create(:artifact_skill, :group_iii, modifier: 25, name_en: 'Armored', name_jp: 'ブロック効果', base_values: [5, 10, 15, 20, 25]) # Clear the cache so new skills are picked up ArtifactSkill.clear_cache! end after do ArtifactSkill.clear_cache! end describe '#import' do context 'with valid game data' do let(:game_data) do { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 8_138_020, 'level' => '1', 'kind' => '7', 'attribute' => '5', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => { 'name' => 'HP', 'skill_quality' => 5, 'level' => 1 }, 'skill3_info' => { 'name' => 'C.A. DMG cap boost tradeoff', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Switch amplified', 'skill_quality' => 1, 'level' => 1 } } ] } end it 'creates a collection artifact' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true expect(result.created.size).to eq(1) expect(result.errors).to be_empty end it 'sets the correct game_id' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.game_id).to eq('8138020') end it 'maps element correctly' do # attribute 5 = Light in game, which maps to our light (6) service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.element).to eq('light') end it 'parses skill1 correctly' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.skill1['modifier']).to eq(11) expect(artifact.skill1['quality']).to eq(1) expect(artifact.skill1['level']).to eq(1) end it 'parses skill2 with max quality correctly' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.skill2['modifier']).to eq(2) expect(artifact.skill2['quality']).to eq(5) end it 'parses skill3 (group II) correctly' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.skill3['modifier']).to eq(8) expect(artifact.skill3['quality']).to eq(1) end it 'parses skill4 (group III) correctly' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.skill4['modifier']).to eq(5) expect(artifact.skill4['quality']).to eq(1) end end context 'with duplicate game_id' do let(:game_data) do { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 8_138_020, 'level' => '1', 'kind' => '7', 'attribute' => '5', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => { 'name' => 'HP', 'skill_quality' => 5, 'level' => 1 }, 'skill3_info' => { 'name' => 'C.A. DMG cap boost tradeoff', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Switch amplified', 'skill_quality' => 1, 'level' => 1 } } ] } end before do create(:collection_artifact, user: user, artifact: standard_artifact, game_id: '8138020') end it 'skips the duplicate' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true expect(result.created.size).to eq(0) expect(result.skipped.size).to eq(1) expect(result.skipped.first[:reason]).to eq('Already exists') end context 'with update_existing: true' do it 'updates the existing artifact' do service = described_class.new(user, game_data, update_existing: true) result = service.import expect(result.success?).to be true expect(result.created.size).to eq(0) expect(result.updated.size).to eq(1) end end end context 'with quirk artifact' do let(:game_data) do { 'list' => [ { 'artifact_id' => 401_110_401, 'rarity' => '4', 'id' => 7_977_596, 'level' => '1', 'kind' => '8', 'attribute' => '6', 'skill1_info' => { 'name' => 'Unknown Skill 1', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => { 'name' => 'Unknown Skill 2', 'skill_quality' => 1, 'level' => 1 }, 'skill3_info' => { 'name' => 'Unknown Skill 3', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Unknown Skill 4', 'skill_quality' => 1, 'level' => 1 } } ] } end it 'creates the quirk artifact with proficiency' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true artifact = result.created.first expect(artifact.artifact.quirk?).to be true expect(artifact.proficiency).to eq('harp') # kind 8 = harp end it 'stores empty skills for unknown skill names' do service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.skill1).to eq({}) expect(artifact.skill2).to eq({}) expect(artifact.skill3).to eq({}) expect(artifact.skill4).to eq({}) end it 'maps element correctly for quirk artifacts' do # attribute 6 = Dark in game, which maps to our dark (5) service = described_class.new(user, game_data) result = service.import artifact = result.created.first expect(artifact.element).to eq('dark') end end context 'with unknown artifact_id' do let(:game_data) do { 'list' => [ { 'artifact_id' => 999_999_999, 'id' => 1234, 'level' => '1', 'kind' => '1', 'attribute' => '1', 'skill1_info' => {}, 'skill2_info' => {}, 'skill3_info' => {}, 'skill4_info' => {} } ] } end it 'records an error for the unknown artifact' do service = described_class.new(user, game_data) result = service.import expect(result.errors.size).to eq(1) expect(result.errors.first[:error]).to eq('Artifact not found') end end context 'with multiple artifacts' do let(:game_data) do { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 8_138_020, 'level' => '1', 'kind' => '7', 'attribute' => '5', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => { 'name' => 'HP', 'skill_quality' => 5, 'level' => 1 }, 'skill3_info' => { 'name' => 'C.A. DMG cap boost tradeoff', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Switch amplified', 'skill_quality' => 1, 'level' => 1 } }, { 'artifact_id' => 301_090_101, 'id' => 8_061_615, 'level' => '1', 'kind' => '9', 'attribute' => '6', 'skill1_info' => { 'name' => 'Elemental ATK', 'skill_quality' => 2, 'level' => 1 }, 'skill2_info' => { 'name' => 'HP', 'skill_quality' => 1, 'level' => 1 }, 'skill3_info' => { 'name' => 'Skill DMG Cap', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Armored', 'skill_quality' => 1, 'level' => 1 } } ] } end it 'imports all artifacts' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true expect(result.created.size).to eq(2) end it 'associates correct artifacts' do service = described_class.new(user, game_data) result = service.import artifacts = result.created.sort_by(&:game_id) expect(artifacts[0].artifact.name_en).to eq('Ominous Whistle') expect(artifacts[1].artifact.name_en).to eq('Ominous Bangle') end end context 'with empty data' do let(:game_data) { { 'list' => [] } } it 'returns an error' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be false expect(result.errors).to include('No artifact items found in data') end end context 'with array format data' do let(:game_data) do [ { 'artifact_id' => 301_070_101, 'id' => 8_138_020, 'level' => '1', 'kind' => '7', 'attribute' => '5', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => { 'name' => 'HP', 'skill_quality' => 5, 'level' => 1 }, 'skill3_info' => { 'name' => 'C.A. DMG cap boost tradeoff', 'skill_quality' => 1, 'level' => 1 }, 'skill4_info' => { 'name' => 'Switch amplified', 'skill_quality' => 1, 'level' => 1 } } ] end it 'handles array format correctly' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true expect(result.created.size).to eq(1) end end context 'with Japanese skill names' do let(:game_data) do { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 8_138_020, 'level' => '1', 'kind' => '7', 'attribute' => '5', 'skill1_info' => { 'name' => '回避率', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => {}, 'skill3_info' => {}, 'skill4_info' => {} } ] } end it 'matches skills by Japanese name' do service = described_class.new(user, game_data) result = service.import expect(result.success?).to be true artifact = result.created.first expect(artifact.skill1['modifier']).to eq(11) # Dodge Rate expect(artifact.skill1['quality']).to eq(1) end end end describe 'element mapping' do # Game: 1=Fire, 2=Water, 3=Earth, 4=Wind, 5=Light, 6=Dark # Ours: wind=1, fire=2, water=3, earth=4, dark=5, light=6 { '1' => 'fire', '2' => 'water', '3' => 'earth', '4' => 'wind', '5' => 'light', '6' => 'dark' }.each do |game_attr, expected_element| it "maps game attribute #{game_attr} to #{expected_element}" do game_data = { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 1234, 'level' => '1', 'kind' => '7', 'attribute' => game_attr, 'skill1_info' => {}, 'skill2_info' => {}, 'skill3_info' => {}, 'skill4_info' => {} } ] } service = described_class.new(user, game_data) result = service.import expect(result.created.first.element).to eq(expected_element) end end end describe 'skill quality storage' do it 'stores quality 1 correctly' do game_data = { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 1234, 'level' => '1', 'kind' => '7', 'attribute' => '1', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 1, 'level' => 1 }, 'skill2_info' => {}, 'skill3_info' => {}, 'skill4_info' => {} } ] } service = described_class.new(user, game_data) result = service.import expect(result.created.first.skill1['quality']).to eq(1) end it 'stores quality 5 correctly' do game_data = { 'list' => [ { 'artifact_id' => 301_070_101, 'id' => 1234, 'level' => '1', 'kind' => '7', 'attribute' => '1', 'skill1_info' => { 'name' => 'Dodge Rate', 'skill_quality' => 5, 'level' => 1 }, 'skill2_info' => {}, 'skill3_info' => {}, 'skill4_info' => {} } ] } service = described_class.new(user, game_data) result = service.import expect(result.created.first.skill1['quality']).to eq(5) end end end