diff --git a/db/seed/canonical.rb b/db/seed/canonical.rb index 86d5660..ddcd473 100644 --- a/db/seed/canonical.rb +++ b/db/seed/canonical.rb @@ -89,6 +89,8 @@ def load_csv_for(model_class, csv_filename, unique_key = :granblue_id, use_id: f end # Load canonical data for core models. +# Load weapon_series first since weapons depend on it +load_csv_for(WeaponSeries, 'weapon_series_test.csv', :id, use_id: true) load_csv_for(Awakening, 'awakenings_test.csv', :id, use_id: true) load_csv_for(Summon, 'summons_test.csv', :id, use_id: true) load_csv_for(Weapon, 'weapons_test.csv', :id, use_id: true) diff --git a/db/seed/test/weapon_series_test.csv b/db/seed/test/weapon_series_test.csv new file mode 100644 index 0000000..60f0ea4 --- /dev/null +++ b/db/seed/test/weapon_series_test.csv @@ -0,0 +1,12 @@ +id,slug,name_en,name_jp,order,extra,element_changeable,has_weapon_keys,has_awakening,has_ax_skills +00000000-0001-0000-0000-000000000001,gacha,Gacha Weapons,ガチャ武器,0,false,false,false,false,false +00000000-0001-0000-0000-000000000002,grand,Grand Weapons,リミテッドシリーズ,2,false,false,true,false,false +00000000-0001-0000-0000-000000000003,dark-opus,Dark Opus Weapons,終末の神器,3,false,false,true,true,false +00000000-0001-0000-0000-000000000004,revenant,Revenant Weapons,天星器,21,false,true,false,false,false +00000000-0001-0000-0000-000000000005,xeno,Xeno Weapons,六道武器,23,true,false,false,false,false +00000000-0001-0000-0000-000000000006,ultima,Ultima Weapons,オメガウェポン,9,false,true,true,false,false +00000000-0001-0000-0000-000000000007,superlative,Superlative Weapons,スペリオシリーズ,27,true,true,true,false,false +00000000-0001-0000-0000-000000000008,draconic,Draconic Weapons,ドラコニックウェポン・オリジン,5,false,false,true,true,false +00000000-0001-0000-0000-000000000009,draconic-providence,Draconic Weapons Providence,ドラコニックウェポン,6,false,false,true,true,false +00000000-0001-0000-0000-000000000010,primal,Primal Weapons,プライマルシリーズ,32,false,false,false,false,false +00000000-0001-0000-0000-000000000011,event,Event Weapons,イベント武器,99,false,false,false,false,false diff --git a/spec/factories/collection_weapons.rb b/spec/factories/collection_weapons.rb index ac75d63..6792b76 100644 --- a/spec/factories/collection_weapons.rb +++ b/spec/factories/collection_weapons.rb @@ -55,10 +55,12 @@ FactoryBot.define do # Trait for weapon with keys trait :with_keys do after(:build) do |collection_weapon| - # Create weapon keys that are compatible with any weapon - collection_weapon.weapon_key1 = FactoryBot.create(:weapon_key, :universal_key) - collection_weapon.weapon_key2 = FactoryBot.create(:weapon_key, :universal_key) - collection_weapon.weapon_key3 = FactoryBot.create(:weapon_key, :universal_key) + # Use an Opus weapon since it supports keys + collection_weapon.weapon = FactoryBot.create(:weapon, :opus) + # Create weapon keys that are compatible with Opus weapons + collection_weapon.weapon_key1 = FactoryBot.create(:weapon_key, :opus_key) + collection_weapon.weapon_key2 = FactoryBot.create(:weapon_key, :opus_key) + collection_weapon.weapon_key3 = FactoryBot.create(:weapon_key, :opus_key) end end @@ -66,8 +68,8 @@ FactoryBot.define do trait :with_four_keys do with_keys after(:build) do |collection_weapon| - collection_weapon.weapon = FactoryBot.create(:weapon, :opus) # Opus weapon supports 4 keys - collection_weapon.weapon_key4 = FactoryBot.create(:weapon_key, :universal_key) + # Opus weapon is already set by :with_keys trait + collection_weapon.weapon_key4 = FactoryBot.create(:weapon_key, :opus_key) end end @@ -88,12 +90,17 @@ FactoryBot.define do trait :maxed do uncap_level { 5 } transcendence_step { 10 } - with_keys after(:build) do |collection_weapon| - collection_weapon.weapon = FactoryBot.create(:weapon, :transcendable) + # Create a transcendable Opus weapon for full key support + opus_series = WeaponSeries.find_by(slug: 'dark-opus') || FactoryBot.create(:weapon_series, :opus) + collection_weapon.weapon = FactoryBot.create(:weapon, :transcendable, weapon_series: opus_series) collection_weapon.awakening = Awakening.where(object_type: 'Weapon').first || FactoryBot.create(:awakening, object_type: 'Weapon') collection_weapon.awakening_level = 10 + # Create keys compatible with Opus weapons + collection_weapon.weapon_key1 = FactoryBot.create(:weapon_key, :opus_key) + collection_weapon.weapon_key2 = FactoryBot.create(:weapon_key, :opus_key) + collection_weapon.weapon_key3 = FactoryBot.create(:weapon_key, :opus_key) end end end diff --git a/spec/factories/weapon_keys.rb b/spec/factories/weapon_keys.rb index 6fdc438..2d3b6c6 100644 --- a/spec/factories/weapon_keys.rb +++ b/spec/factories/weapon_keys.rb @@ -7,18 +7,35 @@ FactoryBot.define do order { rand(1..20) } sequence(:slug) { |n| "key-#{n}" } sequence(:granblue_id) { |n| n.to_s } - series { [3, 27] } # Opus and Draconic weapons + series { [3, 27] } # Opus and Draconic weapons (legacy) trait :opus_key do series { [3] } + after(:create) do |weapon_key| + opus_series = WeaponSeries.find_by(slug: 'dark-opus') || FactoryBot.create(:weapon_series, :opus) + weapon_key.weapon_series << opus_series unless weapon_key.weapon_series.include?(opus_series) + end end trait :draconic_key do series { [27] } + after(:create) do |weapon_key| + draconic_series = WeaponSeries.find_by(slug: 'draconic') || FactoryBot.create(:weapon_series, :draconic) + weapon_key.weapon_series << draconic_series unless weapon_key.weapon_series.include?(draconic_series) + end end trait :universal_key do - series { [3, 27, 99] } # Works with more weapon series + series { [3, 27, 99] } # Works with more weapon series (legacy) + after(:create) do |weapon_key| + opus_series = WeaponSeries.find_by(slug: 'dark-opus') || FactoryBot.create(:weapon_series, :opus) + draconic_series = WeaponSeries.find_by(slug: 'draconic') || FactoryBot.create(:weapon_series, :draconic) + gacha_series = WeaponSeries.find_by(slug: 'gacha') || FactoryBot.create(:weapon_series, :gacha) + + [opus_series, draconic_series, gacha_series].each do |ws| + weapon_key.weapon_series << ws unless weapon_key.weapon_series.include?(ws) + end + end end end end \ No newline at end of file diff --git a/spec/factories/weapon_series.rb b/spec/factories/weapon_series.rb new file mode 100644 index 0000000..21436bf --- /dev/null +++ b/spec/factories/weapon_series.rb @@ -0,0 +1,100 @@ +FactoryBot.define do + factory :weapon_series do + sequence(:name_en) { |n| "Test Series #{n}" } + sequence(:name_jp) { |n| "テストシリーズ#{n}" } + sequence(:slug) { |n| "test-series-#{n}" } + sequence(:order) { |n| n + 100 } + + extra { false } + element_changeable { false } + has_weapon_keys { false } + has_awakening { false } + has_ax_skills { false } + + trait :gacha do + slug { 'gacha' } + name_en { 'Gacha' } + name_jp { 'ガチャ' } + order { 99 } + end + + trait :opus do + slug { 'dark-opus' } + name_en { 'Dark Opus' } + name_jp { 'オプス' } + order { 3 } + has_weapon_keys { true } + has_awakening { true } + end + + trait :draconic do + slug { 'draconic' } + name_en { 'Draconic' } + name_jp { 'ドラゴニック' } + order { 27 } + has_awakening { true } + end + + trait :draconic_providence do + slug { 'draconic-providence' } + name_en { 'Draconic Providence' } + name_jp { 'ドラゴニック・プロビデンス' } + order { 40 } + has_awakening { true } + end + + trait :revenant do + slug { 'revenant' } + name_en { 'Revenant' } + name_jp { '天星器' } + order { 4 } + element_changeable { true } + end + + trait :ultima do + slug { 'ultima' } + name_en { 'Ultima' } + name_jp { 'オメガ' } + order { 13 } + element_changeable { true } + end + + trait :superlative do + slug { 'superlative' } + name_en { 'Superlative' } + name_jp { '超越' } + order { 17 } + element_changeable { true } + extra { true } + has_weapon_keys { true } + end + + trait :grand do + slug { 'grand' } + name_en { 'Grand' } + name_jp { 'リミテッド' } + order { 2 } + has_weapon_keys { true } + end + + trait :xeno do + slug { 'xeno' } + name_en { 'Xeno' } + name_jp { 'ゼノ' } + order { 11 } + extra { true } + end + + trait :extra_allowed do + extra { true } + end + + trait :element_changeable do + element_changeable { true } + end + + trait :with_weapon_keys do + has_weapon_keys { true } + end + end +end diff --git a/spec/factories/weapons.rb b/spec/factories/weapons.rb index 57fc132..5285ac4 100644 --- a/spec/factories/weapons.rb +++ b/spec/factories/weapons.rb @@ -6,7 +6,10 @@ FactoryBot.define do rarity { 4 } # SSR element { 1 } # Fire proficiency { 1 } # Sabre - series { 99 } # Gacha + series { 99 } # Gacha (legacy) + + # Use weapon_series association if available + weapon_series { nil } # Release info release_date { 1.year.ago } @@ -65,11 +68,18 @@ FactoryBot.define do end trait :opus do - series { 3 } # dark-opus + series { 3 } # dark-opus (legacy) + weapon_series { WeaponSeries.find_by(slug: 'dark-opus') || create(:weapon_series, :opus) } end trait :draconic do - series { 27 } # draconic + series { 27 } # draconic (legacy) + weapon_series { WeaponSeries.find_by(slug: 'draconic') || create(:weapon_series, :draconic) } + end + + trait :revenant do + series { 4 } # revenant (legacy) + weapon_series { WeaponSeries.find_by(slug: 'revenant') || create(:weapon_series, :revenant) } end trait :ax_weapon do diff --git a/spec/models/collection_weapon_spec.rb b/spec/models/collection_weapon_spec.rb index cdb1de4..24a5f8b 100644 --- a/spec/models/collection_weapon_spec.rb +++ b/spec/models/collection_weapon_spec.rb @@ -116,7 +116,7 @@ RSpec.describe CollectionWeapon, type: :model do context 'when weapon_key4 is set on Opus weapon' do it 'is valid' do - key = create(:weapon_key) + key = create(:weapon_key, :opus_key) collection_weapon = build(:collection_weapon, weapon: opus_weapon, weapon_key4: key) expect(collection_weapon).to be_valid end @@ -133,7 +133,7 @@ RSpec.describe CollectionWeapon, type: :model do end context 'when element is set on Revenant weapon' do - let(:revenant_weapon) { create(:weapon, series: 4) } # Revenant series (element-changeable) + let(:revenant_weapon) { create(:weapon, :revenant) } it 'is valid' do collection_weapon = build(:collection_weapon, weapon: revenant_weapon, element: 2) diff --git a/spec/models/grid_weapon_spec.rb b/spec/models/grid_weapon_spec.rb index 9f73265..9ccd74a 100644 --- a/spec/models/grid_weapon_spec.rb +++ b/spec/models/grid_weapon_spec.rb @@ -16,7 +16,8 @@ RSpec.describe GridWeapon, type: :model do # Setup common test objects using FactoryBot. let(:party) { create(:party) } - let(:weapon) { create(:weapon, limit: false, series: 5) } # a non-limited weapon with series 5 + let(:default_series) { create(:weapon_series, extra: false) } + let(:weapon) { create(:weapon, limit: false, weapon_series: default_series) } let(:grid_weapon) do build(:grid_weapon, party: party, @@ -42,7 +43,7 @@ RSpec.describe GridWeapon, type: :model do before { grid_weapon.position = 9 } context 'and weapon series is NOT in allowed extra series' do - before { weapon.series = 5 } # Allowed extra series are [11, 16, 17, 28, 29, 32, 34] + # default_series has extra: false, so this should fail it 'adds an error on :series' do grid_weapon.validate expect(grid_weapon.errors[:series]).to include('must be compatible with position') @@ -50,7 +51,11 @@ RSpec.describe GridWeapon, type: :model do end context 'and weapon series is in allowed extra series' do - before { weapon.series = 11 } + let(:extra_series) { create(:weapon_series, extra: true) } + let(:extra_weapon) { create(:weapon, limit: false, weapon_series: extra_series) } + + before { grid_weapon.weapon = extra_weapon } + it 'is valid with respect to position compatibility' do grid_weapon.validate expect(grid_weapon.errors[:series]).to be_empty @@ -69,9 +74,10 @@ RSpec.describe GridWeapon, type: :model do describe '#no_conflicts' do context 'when there is a conflicting grid weapon in the party' do + let(:limited_series) { create(:weapon_series) } + let(:limited_weapon) { create(:weapon, limit: true, weapon_series: limited_series) } + before do - # Create a limited weapon that will trigger conflict checking. - limited_weapon = create(:weapon, limit: true, series: 7) # Create an existing grid weapon in the party using that limited weapon. create(:grid_weapon, party: party, weapon: limited_weapon, position: 1) # Set up grid_weapon to use the same limited weapon in a different position.