hensei-api/spec/models/artifact_skill_spec.rb

181 lines
5.6 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ArtifactSkill, type: :model do
describe 'validations' do
subject { build(:artifact_skill) }
it { is_expected.to validate_presence_of(:skill_group) }
it { is_expected.to validate_presence_of(:modifier) }
it { is_expected.to validate_presence_of(:name_en) }
it { is_expected.to validate_presence_of(:name_jp) }
it { is_expected.to validate_presence_of(:base_values) }
it { is_expected.to validate_presence_of(:polarity) }
it 'validates uniqueness of modifier within skill_group' do
# Create with unique modifier, then try to create duplicate
existing = create(:artifact_skill, skill_group: :group_i, modifier: 5000)
duplicate = build(:artifact_skill, skill_group: :group_i, modifier: 5000)
expect(duplicate).not_to be_valid
expect(duplicate.errors[:modifier]).to include('has already been taken')
end
it 'allows same modifier in different skill groups' do
create(:artifact_skill, skill_group: :group_i, modifier: 5001)
different_group = build(:artifact_skill, skill_group: :group_ii, modifier: 5001)
expect(different_group).to be_valid
end
end
describe 'enums' do
it 'defines skill_group enum' do
expect(ArtifactSkill.skill_groups).to eq(
'group_i' => 1,
'group_ii' => 2,
'group_iii' => 3
)
end
it 'defines polarity enum' do
expect(ArtifactSkill.polarities).to eq(
'positive' => 'positive',
'negative' => 'negative'
)
end
end
describe '.for_slot' do
before do
# Use unique modifiers that won't conflict with seeded data
@group_i_skill = create(:artifact_skill, :group_i, modifier: 6000)
@group_ii_skill = create(:artifact_skill, :group_ii, modifier: 6001)
@group_iii_skill = create(:artifact_skill, :group_iii, modifier: 6002)
end
it 'returns Group I skills for slot 1' do
expect(ArtifactSkill.for_slot(1)).to include(@group_i_skill)
expect(ArtifactSkill.for_slot(1)).not_to include(@group_ii_skill)
end
it 'returns Group I skills for slot 2' do
expect(ArtifactSkill.for_slot(2)).to include(@group_i_skill)
expect(ArtifactSkill.for_slot(2)).not_to include(@group_ii_skill)
end
it 'returns Group II skills for slot 3' do
expect(ArtifactSkill.for_slot(3)).to include(@group_ii_skill)
expect(ArtifactSkill.for_slot(3)).not_to include(@group_i_skill)
end
it 'returns Group III skills for slot 4' do
expect(ArtifactSkill.for_slot(4)).to include(@group_iii_skill)
expect(ArtifactSkill.for_slot(4)).not_to include(@group_i_skill)
end
end
describe '.find_skill' do
before do
ArtifactSkill.clear_cache!
@test_skill = create(:artifact_skill, skill_group: :group_i, modifier: 7000)
end
after do
ArtifactSkill.clear_cache!
end
it 'finds skill by group number and modifier' do
ArtifactSkill.clear_cache!
found = ArtifactSkill.find_skill(1, 7000)
expect(found).to eq(@test_skill)
end
it 'returns nil for non-existent skill' do
ArtifactSkill.clear_cache!
expect(ArtifactSkill.find_skill(1, 99999)).to be_nil
end
it 'caches skills for performance' do
ArtifactSkill.clear_cache!
ArtifactSkill.find_skill(1, 7000)
expect(ArtifactSkill.instance_variable_get(:@cached_skills)).not_to be_nil
end
end
describe '#calculate_value' do
let(:skill) { build(:artifact_skill, growth: 300.0) }
it 'returns base strength at level 1' do
expect(skill.calculate_value(1800, 1)).to eq(1800)
end
it 'adds growth for each level above 1' do
expect(skill.calculate_value(1800, 3)).to eq(2400) # 1800 + (300 * 2)
end
it 'handles level 5' do
expect(skill.calculate_value(1800, 5)).to eq(3000) # 1800 + (300 * 4)
end
context 'with nil growth' do
let(:skill) { build(:artifact_skill, :no_growth) }
it 'returns base strength regardless of level' do
expect(skill.calculate_value(10, 1)).to eq(10)
expect(skill.calculate_value(10, 5)).to eq(10)
end
end
context 'with negative growth' do
let(:skill) { build(:artifact_skill, :negative, growth: -6.0) }
it 'subtracts growth for each level' do
expect(skill.calculate_value(30, 3)).to eq(18) # 30 + (-6 * 2)
end
end
end
describe '#format_value' do
context 'with percentage suffix' do
let(:skill) { build(:artifact_skill, suffix_en: '%', suffix_jp: '%') }
it 'formats with English suffix' do
expect(skill.format_value(18.0, :en)).to eq('18.0%')
end
it 'formats with Japanese suffix' do
expect(skill.format_value(18.0, :jp)).to eq('18.0%')
end
end
context 'with no suffix' do
let(:skill) { build(:artifact_skill, suffix_en: '', suffix_jp: '') }
it 'returns value without suffix' do
expect(skill.format_value(1800, :en)).to eq('1800')
end
end
end
describe '#valid_strength?' do
let(:skill) { build(:artifact_skill, base_values: [1320, 1440, 1560, 1680, 1800]) }
it 'returns true for valid base values' do
expect(skill.valid_strength?(1800)).to be true
expect(skill.valid_strength?(1320)).to be true
end
it 'returns false for invalid values' do
expect(skill.valid_strength?(1500)).to be false
expect(skill.valid_strength?(9999)).to be false
end
context 'with nil in base_values (unknown values)' do
let(:skill) { build(:artifact_skill, base_values: [nil]) }
it 'returns true for any value' do
expect(skill.valid_strength?(9999)).to be true
end
end
end
end