hensei-api/spec/services/processors/weapon_processor_spec.rb
Justin Edmund 3cdd925162
Fix filters and add processors (#181)
* Update test csvs

* Fix count filters and refactor apply_filters

* Update party_querying_concern.rb

* +tests/-debug logs

* Make party association optional in Job

* Updates for weapon series

- Change to new series numbers
- Add static method for querying whether the weapon's element is changeable
- Add a new method to return a text slug for the weapon's series

* Add and update test data

- Updates canonical.rb for loading multiple types of data with multiple types of associations
- Adds test data for Guidebooks, Job Accessories, Job Skills, and Jobs
- Updates test data for Weapons and Summons

* Migrations

- Adds series of migrations for changing the weapon's series to the values used by Cygames
- Shuffled around some foreign keys

* Implement BaseProcessor

Processors are in charge of processing deck data straight from Granblue.

* Implement CharacterProcessor

Process character data from deck

* Implement WeaponProcessor

Process weapon data from deck

* Implement JobProcessor

Process job, job skill, and job accessory data from deck

* Implement SummonProcessor

Process summon data from deck

* Update SummonProcessor to work like the others

* ImportController should use processors

* Process element for changeable weapons
2025-02-17 23:51:50 -08:00

137 lines
4.7 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Processors::WeaponProcessor, type: :model do
let(:party) { create(:party) }
# Minimal deck data for testing private methods.
let(:dummy_deck_data) { { 'deck' => { 'pc' => { 'weapons' => {} } } } }
let(:processor) { described_class.new(party, dummy_deck_data) }
describe '#level_to_transcendence' do
it 'returns 0 for levels less than 200' do
expect(processor.send(:level_to_transcendence, 150)).to eq(0)
end
it 'returns the correct transcendence step for levels >= 200' do
expect(processor.send(:level_to_transcendence, 200)).to eq(0)
expect(processor.send(:level_to_transcendence, 215)).to eq(1)
expect(processor.send(:level_to_transcendence, 250)).to eq(5)
end
end
describe '#matches_key?' do
it 'returns true if candidate key falls within a range' do
expect(processor.send(:matches_key?, '700', '697-706')).to be true
end
it 'returns false if candidate key is below the range' do
expect(processor.send(:matches_key?, '696', '697-706')).to be false
end
it 'returns false if candidate key is above the range' do
expect(processor.send(:matches_key?, '707', '697-706')).to be false
end
it 'returns true if candidate key exactly matches the mapping' do
expect(processor.send(:matches_key?, '700', '700')).to be true
end
end
describe '#process_weapon_ax' do
let(:grid_weapon) { build(:grid_weapon, party: party) }
it 'flattens nested augment_skill_info and assigns ax_modifier and ax_strength' do
ax_skill_info = [
[
{ 'skill_id' => '1588', 'effect_value' => '3', 'show_value' => '3%' },
{ 'skill_id' => '1591', 'effect_value' => '5', 'show_value' => '5%' }
]
]
processor.send(:process_weapon_ax, grid_weapon, ax_skill_info)
expect(grid_weapon.ax_modifier1).to eq(2) # from 1588 → 2
expect(grid_weapon.ax_strength1).to eq(3)
expect(grid_weapon.ax_modifier2).to eq(3) # from 1591 → 3
expect(grid_weapon.ax_strength2).to eq(5)
end
end
describe '#map_arousal_to_awakening' do
it 'returns nil if there is no form key' do
arousal_data = {}
expect(processor.send(:map_arousal_to_awakening, arousal_data)).to be_nil
end
it 'returns the awakening id if found' do
arousal_data = {
"is_arousal_weapon": true,
"level": 4,
"form": 2,
"form_name": 'Defense',
"remain_for_next_level": 0,
"width": 100,
"is_complete_condition": true,
"max_level": 4,
}
awakening = Awakening.find_by(slug: 'weapon-def')
expect(processor.send(:map_arousal_to_awakening, arousal_data)).to eq(awakening.id)
end
end
describe '#process_weapon_keys' do
let(:deck_data) do
file_path = Rails.root.join('spec', 'fixtures', 'deck_sample2.json')
JSON.parse(File.read(file_path))
end
let(:deck_weapon) do
deck_data['deck']['pc']['weapons']['7']
end
let(:canonical_weapon) do
Weapon.find_by(granblue_id: deck_weapon['master']['id'])
end
let(:grid_weapon) do
create(:grid_weapon, weapon: canonical_weapon, party: party)
end
context 'when the raw key is provided via KEY_MAPPING' do
it 'assigns the mapped WeaponKey' do
skill_ids = [deck_weapon['skill1'], deck_weapon['skill2'], deck_weapon['skill3']].compact.map { |s| s['id'] }
processor.send(:process_weapon_keys, grid_weapon, skill_ids)
expect(grid_weapon.weapon_key1_id).to be_nil
expect(grid_weapon.weapon_key2_id).to eq(WeaponKey.find_by(slug: 'pendulum-beta').id)
expect(grid_weapon.weapon_key3_id).to eq(WeaponKey.find_by(slug: 'pendulum-extremity').id)
end
end
context 'when no matching WeaponKey is found' do
it 'logs a warning and does not assign the key' do
processor.send(:process_weapon_keys, grid_weapon, ['unknown'])
expect(grid_weapon.weapon_key1_id).to be_nil
end
end
end
describe 'processing a complete canonical deck' do
let(:deck_data) do
file_path = Rails.root.join('spec', 'fixtures', 'deck_sample2.json')
JSON.parse(File.read(file_path))
end
subject { described_class.new(party, deck_data) }
it 'processes the deck and creates the expected number of GridWeapon records' do
# Assume the canonical records are already loaded (via canonical.rb).
expect { subject.process }.to change(GridWeapon, :count).by(13)
end
it 'creates the correct main weapon' do
# In this canonical deck, the main weapon (slot 1) should be Parazonium.
main_weapon = GridWeapon.find_by(position: -1)
expect(main_weapon).not_to be_nil
expect(main_weapon.weapon.granblue_id).to eq('1040108700')
end
end
end