# frozen_string_literal: true require 'rails_helper' RSpec.describe Maps::HexagonCenterManager do describe '.call' do subject(:manage_centers) do described_class.call( stat: stat, target_user: target_user ) end let(:user) { create(:user) } let(:target_user) { user } context 'with pre-calculated hexagon centers' do let(:pre_calculated_centers) do [ [-74.0, 40.7, 1_717_200_000, 1_717_203_600], # lng, lat, earliest, latest timestamps [-74.01, 40.71, 1_717_210_000, 1_717_213_600], [-74.02, 40.72, 1_717_220_000, 1_717_223_600] ] end let(:stat) { create(:stat, user:, year: 2024, month: 6, hexagon_centers: pre_calculated_centers) } it 'returns success with pre-calculated data' do result = manage_centers expect(result[:success]).to be true expect(result[:pre_calculated]).to be true expect(result[:data]['type']).to eq('FeatureCollection') expect(result[:data]['features'].length).to eq(3) expect(result[:data]['metadata']['pre_calculated']).to be true expect(result[:data]['metadata']['count']).to eq(3) expect(result[:data]['metadata']['user_id']).to eq(target_user.id) end it 'generates proper hexagon features from centers' do result = manage_centers features = result[:data]['features'] features.each_with_index do |feature, index| expect(feature['type']).to eq('Feature') expect(feature['id']).to eq(index + 1) expect(feature['geometry']['type']).to eq('Polygon') expect(feature['geometry']['coordinates'].first.length).to eq(7) # 6 vertices + closing properties = feature['properties'] expect(properties['hex_id']).to eq(index + 1) expect(properties['hex_size']).to eq(1000) expect(properties['earliest_point']).to be_present expect(properties['latest_point']).to be_present end end end context 'with legacy area_too_large flag' do let(:stat) do create(:stat, user:, year: 2024, month: 6, hexagon_centers: { 'area_too_large' => true }) end before do # Mock the Stats::CalculateMonth service allow_any_instance_of(Stats::CalculateMonth).to receive(:calculate_hexagon_centers) .and_return(new_centers) end context 'when recalculation succeeds' do let(:new_centers) do [ [-74.0, 40.7, 1_717_200_000, 1_717_203_600], [-74.01, 40.71, 1_717_210_000, 1_717_213_600] ] end it 'recalculates and updates the stat' do expect(stat).to receive(:update).with(hexagon_centers: new_centers) result = manage_centers expect(result[:success]).to be true expect(result[:pre_calculated]).to be true expect(result[:data]['features'].length).to eq(2) end end context 'when recalculation fails' do let(:new_centers) { nil } it 'returns nil' do expect(manage_centers).to be_nil end end context 'when recalculation returns area_too_large again' do let(:new_centers) { { area_too_large: true } } it 'returns nil' do expect(manage_centers).to be_nil end end end context 'with no stat' do let(:stat) { nil } it 'returns nil' do expect(manage_centers).to be_nil end end context 'with stat but no hexagon_centers' do let(:stat) { create(:stat, user:, year: 2024, month: 6, hexagon_centers: nil) } it 'returns nil' do expect(manage_centers).to be_nil end end context 'with empty hexagon_centers' do let(:stat) { create(:stat, user:, year: 2024, month: 6, hexagon_centers: []) } it 'returns nil' do expect(manage_centers).to be_nil end end end end