181 lines
5.6 KiB
Ruby
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
|