Add model specs for collection sync functionality

Test sync_from_collection! and out_of_sync? methods for
GridCharacter, GridWeapon, GridSummon, and GridArtifact models.
This commit is contained in:
Justin Edmund 2025-12-03 23:08:01 -08:00
parent 8fca01d6c7
commit 4d30363187
4 changed files with 362 additions and 0 deletions

View file

@ -6,6 +6,7 @@ RSpec.describe GridArtifact, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:grid_character) }
it { is_expected.to belong_to(:artifact) }
it { is_expected.to belong_to(:collection_artifact).optional }
end
describe 'validations' do
@ -93,4 +94,99 @@ RSpec.describe GridArtifact, type: :model do
expect(GridArtifact).to respond_to(:amoeba_block)
end
end
describe 'Collection Sync' do
let(:user) { create(:user) }
let(:grid_character) { create(:grid_character) }
let(:artifact) { create(:artifact) }
let(:collection_artifact) do
create(:collection_artifact,
user: user,
artifact: artifact,
element: 2,
level: 4,
skill1: { 'modifier' => 1, 'strength' => 10 },
skill2: { 'modifier' => 2, 'strength' => 5 },
skill3: {},
skill4: {},
reroll_slot: 3)
end
describe '#sync_from_collection!' do
context 'when collection_artifact is linked' do
let(:linked_grid_artifact) do
create(:grid_artifact,
grid_character: grid_character,
artifact: artifact,
collection_artifact: collection_artifact,
element: 1,
level: 2,
skill1: {}, skill2: {}, skill3: {}, skill4: {})
end
it 'copies customizations from collection' do
expect(linked_grid_artifact.sync_from_collection!).to be true
linked_grid_artifact.reload
expect(linked_grid_artifact.element).to eq(2)
expect(linked_grid_artifact.level).to eq(4)
expect(linked_grid_artifact.skill1).to eq({ 'modifier' => 1, 'strength' => 10 })
expect(linked_grid_artifact.reroll_slot).to eq(3)
end
end
context 'when no collection_artifact is linked' do
let(:unlinked_grid_artifact) do
create(:grid_artifact,
grid_character: grid_character,
artifact: artifact,
element: 1,
level: 2,
skill1: {}, skill2: {}, skill3: {}, skill4: {})
end
it 'returns false' do
expect(unlinked_grid_artifact.sync_from_collection!).to be false
end
end
end
describe '#out_of_sync?' do
context 'when collection_artifact is linked' do
let(:linked_grid_artifact) do
create(:grid_artifact,
grid_character: grid_character,
artifact: artifact,
collection_artifact: collection_artifact,
element: 1,
level: 2,
skill1: {}, skill2: {}, skill3: {}, skill4: {})
end
it 'returns true when values differ' do
expect(linked_grid_artifact.out_of_sync?).to be true
end
it 'returns false after sync' do
linked_grid_artifact.sync_from_collection!
expect(linked_grid_artifact.out_of_sync?).to be false
end
end
context 'when no collection_artifact is linked' do
let(:unlinked_grid_artifact) do
create(:grid_artifact,
grid_character: grid_character,
artifact: artifact,
element: 1,
level: 2,
skill1: {}, skill2: {}, skill3: {}, skill4: {})
end
it 'returns false' do
expect(unlinked_grid_artifact.out_of_sync?).to be false
end
end
end
end
end

View file

@ -16,6 +16,7 @@ RSpec.describe GridCharacter, type: :model do
it { is_expected.to belong_to(:character) }
it { is_expected.to belong_to(:party) }
it { is_expected.to belong_to(:awakening).optional }
it { is_expected.to belong_to(:collection_character).optional }
# Use the canonical "Balanced" awakening already loaded from CSV.
before(:all) do
@ -163,4 +164,101 @@ RSpec.describe GridCharacter, type: :model do
end
end
end
describe 'Collection Sync' do
let(:user) { create(:user) }
let(:collection_character) do
create(:collection_character,
user: user,
character: character,
uncap_level: 5,
transcendence_step: 3,
perpetuity: true,
ring1: { 'modifier' => '1', 'strength' => 1500 },
ring2: { 'modifier' => '2', 'strength' => 750 },
ring3: { 'modifier' => nil, 'strength' => nil },
ring4: { 'modifier' => nil, 'strength' => nil },
earring: { 'modifier' => '3', 'strength' => 20 },
awakening: @balanced_awakening,
awakening_level: 7)
end
describe '#sync_from_collection!' do
context 'when collection_character is linked' do
before do
character.update!(ulb: true) # Enable transcendence
@grid_char = create(:grid_character,
valid_attributes.merge(
collection_character: collection_character,
uncap_level: 3,
transcendence_step: 0
))
end
it 'copies all customizations from collection' do
expect(@grid_char.sync_from_collection!).to be true
@grid_char.reload
expect(@grid_char.uncap_level).to eq(5)
expect(@grid_char.transcendence_step).to eq(3)
expect(@grid_char.perpetuity).to be true
expect(@grid_char.ring1).to eq({ 'modifier' => '1', 'strength' => 1500 })
expect(@grid_char.ring2).to eq({ 'modifier' => '2', 'strength' => 750 })
expect(@grid_char.awakening_level).to eq(7)
end
end
context 'when no collection_character is linked' do
before do
@grid_char = create(:grid_character, valid_attributes)
end
it 'returns false and does not change anything' do
original_uncap = @grid_char.uncap_level
expect(@grid_char.sync_from_collection!).to be false
expect(@grid_char.uncap_level).to eq(original_uncap)
end
end
end
describe '#out_of_sync?' do
context 'when collection_character is linked' do
before do
character.update!(ulb: true)
@grid_char = create(:grid_character,
valid_attributes.merge(collection_character: collection_character))
end
it 'returns true when uncap_level differs' do
@grid_char.update!(uncap_level: 4)
expect(@grid_char.out_of_sync?).to be true
end
it 'returns true when transcendence_step differs' do
@grid_char.update!(transcendence_step: 1)
expect(@grid_char.out_of_sync?).to be true
end
it 'returns true when perpetuity differs' do
@grid_char.update!(perpetuity: false)
expect(@grid_char.out_of_sync?).to be true
end
it 'returns false when all values match' do
@grid_char.sync_from_collection!
expect(@grid_char.out_of_sync?).to be false
end
end
context 'when no collection_character is linked' do
before do
@grid_char = create(:grid_character, valid_attributes)
end
it 'returns false' do
expect(@grid_char.out_of_sync?).to be false
end
end
end
end
end

View file

@ -18,6 +18,13 @@ RSpec.describe GridSummon, type: :model do
expect(association).not_to be_nil
expect(association.macro).to eq(:belongs_to)
end
it 'belongs to a collection_summon (optional)' do
association = described_class.reflect_on_association(:collection_summon)
expect(association).not_to be_nil
expect(association.macro).to eq(:belongs_to)
expect(association.options[:optional]).to be true
end
end
describe 'validations' do
@ -232,4 +239,97 @@ RSpec.describe GridSummon, type: :model do
expect(grid_summon.blueprint).to eq(GridSummonBlueprint)
end
end
describe 'Collection Sync' do
let(:party) { create(:party) }
let(:user) { create(:user) }
let(:summon) { Summon.find_by!(granblue_id: '2040433000') }
let(:collection_summon) do
create(:collection_summon,
user: user,
summon: summon,
uncap_level: 5,
transcendence_step: 2)
end
describe '#sync_from_collection!' do
context 'when collection_summon is linked' do
let(:linked_grid_summon) do
# Ensure summon has transcendence for valid transcendence_step
summon.update!(transcendence: true, ulb: true, flb: true)
create(:grid_summon,
party: party,
summon: summon,
position: 1,
collection_summon: collection_summon,
uncap_level: 3,
transcendence_step: 0)
end
it 'copies customizations from collection' do
expect(linked_grid_summon.sync_from_collection!).to be true
linked_grid_summon.reload
expect(linked_grid_summon.uncap_level).to eq(5)
expect(linked_grid_summon.transcendence_step).to eq(2)
end
end
context 'when no collection_summon is linked' do
let(:unlinked_grid_summon) do
build(:grid_summon,
party: party,
summon: summon,
position: 1,
uncap_level: 3,
transcendence_step: 0)
end
it 'returns false' do
unlinked_grid_summon.save!
expect(unlinked_grid_summon.sync_from_collection!).to be false
end
end
end
describe '#out_of_sync?' do
context 'when collection_summon is linked' do
let(:linked_grid_summon) do
summon.update!(transcendence: true, ulb: true, flb: true)
create(:grid_summon,
party: party,
summon: summon,
position: 1,
collection_summon: collection_summon,
uncap_level: 3,
transcendence_step: 0)
end
it 'returns true when values differ' do
expect(linked_grid_summon.out_of_sync?).to be true
end
it 'returns false after sync' do
linked_grid_summon.sync_from_collection!
expect(linked_grid_summon.out_of_sync?).to be false
end
end
context 'when no collection_summon is linked' do
let(:unlinked_grid_summon) do
build(:grid_summon,
party: party,
summon: summon,
position: 1,
uncap_level: 3,
transcendence_step: 0)
end
it 'returns false' do
unlinked_grid_summon.save!
expect(unlinked_grid_summon.out_of_sync?).to be false
end
end
end
end
end

View file

@ -13,6 +13,7 @@ RSpec.describe GridWeapon, type: :model do
it { is_expected.to belong_to(:weapon_key3).optional }
it { is_expected.to belong_to(:weapon_key4).optional }
it { is_expected.to belong_to(:awakening).optional }
it { is_expected.to belong_to(:collection_weapon).optional }
# Setup common test objects using FactoryBot.
let(:party) { create(:party) }
@ -134,4 +135,71 @@ RSpec.describe GridWeapon, type: :model do
expect(grid_weapon.blueprint).to eq(GridWeaponBlueprint)
end
end
describe 'Collection Sync' do
let(:user) { create(:user) }
let(:collection_weapon) do
create(:collection_weapon,
user: user,
weapon: weapon,
uncap_level: 5,
transcendence_step: 0,
element: 2)
end
describe '#sync_from_collection!' do
context 'when collection_weapon is linked' do
let(:linked_grid_weapon) do
create(:grid_weapon,
party: party,
weapon: weapon,
position: 0,
collection_weapon: collection_weapon,
uncap_level: 3)
end
it 'copies customizations from collection' do
expect(linked_grid_weapon.sync_from_collection!).to be true
linked_grid_weapon.reload
expect(linked_grid_weapon.uncap_level).to eq(5)
expect(linked_grid_weapon.element).to eq(2)
end
end
context 'when no collection_weapon is linked' do
it 'returns false' do
expect(grid_weapon.sync_from_collection!).to be false
end
end
end
describe '#out_of_sync?' do
context 'when collection_weapon is linked' do
let(:linked_grid_weapon) do
create(:grid_weapon,
party: party,
weapon: weapon,
position: 0,
collection_weapon: collection_weapon,
uncap_level: 3)
end
it 'returns true when values differ' do
expect(linked_grid_weapon.out_of_sync?).to be true
end
it 'returns false after sync' do
linked_grid_weapon.sync_from_collection!
expect(linked_grid_weapon.out_of_sync?).to be false
end
end
context 'when no collection_weapon is linked' do
it 'returns false' do
expect(grid_weapon.out_of_sync?).to be false
end
end
end
end
end