2025-09-16 14:41:53 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
|
|
require 'rails_helper'
|
|
|
|
|
|
|
|
|
|
RSpec.describe Maps::HexagonRequestHandler do
|
|
|
|
|
describe '.call' do
|
|
|
|
|
subject(:handle_request) do
|
2025-09-18 14:02:18 -04:00
|
|
|
described_class.new(
|
2025-09-16 14:41:53 -04:00
|
|
|
params: params,
|
2025-09-18 16:23:47 -04:00
|
|
|
user: user,
|
|
|
|
|
stat: nil,
|
|
|
|
|
start_date: params[:start_date],
|
|
|
|
|
end_date: params[:end_date]
|
2025-09-18 14:02:18 -04:00
|
|
|
).call
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
|
2025-09-18 12:29:46 -04:00
|
|
|
context 'with authenticated user but no pre-calculated data' do
|
2025-09-16 14:41:53 -04:00
|
|
|
let(:params) do
|
2025-09-18 12:29:46 -04:00
|
|
|
ActionController::Parameters.new(
|
|
|
|
|
{
|
|
|
|
|
min_lon: -74.1,
|
|
|
|
|
min_lat: 40.6,
|
|
|
|
|
max_lon: -73.9,
|
|
|
|
|
max_lat: 40.8,
|
|
|
|
|
start_date: '2024-06-01T00:00:00Z',
|
|
|
|
|
end_date: '2024-06-30T23:59:59Z'
|
|
|
|
|
}
|
|
|
|
|
)
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
|
2025-09-18 12:29:46 -04:00
|
|
|
it 'returns empty feature collection when no pre-calculated data' do
|
2025-09-16 14:41:53 -04:00
|
|
|
result = handle_request
|
|
|
|
|
|
|
|
|
|
expect(result).to be_a(Hash)
|
|
|
|
|
expect(result['type']).to eq('FeatureCollection')
|
2025-09-18 12:29:46 -04:00
|
|
|
expect(result['features']).to eq([])
|
|
|
|
|
expect(result['metadata']['hexagon_count']).to eq(0)
|
|
|
|
|
expect(result['metadata']['source']).to eq('pre_calculated')
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with public sharing UUID and pre-calculated centers' do
|
|
|
|
|
let(:pre_calculated_centers) do
|
2025-09-19 13:55:27 -04:00
|
|
|
{
|
|
|
|
|
'8a1fb46622dffff' => [5, 1_717_200_000, 1_717_203_600],
|
|
|
|
|
'8a1fb46622e7fff' => [3, 1_717_210_000, 1_717_213_600]
|
|
|
|
|
}
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
let(:stat) do
|
|
|
|
|
create(:stat, :with_sharing_enabled, user:, year: 2024, month: 6,
|
2025-09-19 13:55:27 -04:00
|
|
|
h3_hex_ids: pre_calculated_centers)
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
let(:params) do
|
2025-09-18 12:29:46 -04:00
|
|
|
ActionController::Parameters.new(
|
|
|
|
|
{
|
|
|
|
|
uuid: stat.sharing_uuid,
|
|
|
|
|
min_lon: -74.1,
|
|
|
|
|
min_lat: 40.6,
|
|
|
|
|
max_lon: -73.9,
|
2025-09-18 14:02:18 -04:00
|
|
|
max_lat: 40.8
|
2025-09-18 12:29:46 -04:00
|
|
|
}
|
|
|
|
|
)
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'returns pre-calculated hexagon data' do
|
|
|
|
|
result = handle_request
|
|
|
|
|
|
|
|
|
|
expect(result['type']).to eq('FeatureCollection')
|
|
|
|
|
expect(result['features'].length).to eq(2)
|
|
|
|
|
expect(result['metadata']['pre_calculated']).to be true
|
|
|
|
|
expect(result['metadata']['user_id']).to eq(user.id)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with public sharing UUID but no pre-calculated centers' do
|
|
|
|
|
let(:stat) { create(:stat, :with_sharing_enabled, user:, year: 2024, month: 6) }
|
|
|
|
|
let(:params) do
|
2025-09-18 12:29:46 -04:00
|
|
|
ActionController::Parameters.new(
|
|
|
|
|
{
|
|
|
|
|
uuid: stat.sharing_uuid,
|
|
|
|
|
min_lon: -74.1,
|
|
|
|
|
min_lat: 40.6,
|
|
|
|
|
max_lon: -73.9,
|
2025-09-18 14:02:18 -04:00
|
|
|
max_lat: 40.8
|
2025-09-18 12:29:46 -04:00
|
|
|
}
|
|
|
|
|
)
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
|
2025-09-18 12:29:46 -04:00
|
|
|
it 'returns empty feature collection when no pre-calculated centers' do
|
2025-09-16 14:41:53 -04:00
|
|
|
result = handle_request
|
|
|
|
|
|
|
|
|
|
expect(result['type']).to eq('FeatureCollection')
|
2025-09-18 12:29:46 -04:00
|
|
|
expect(result['features']).to eq([])
|
|
|
|
|
expect(result['metadata']['hexagon_count']).to eq(0)
|
|
|
|
|
expect(result['metadata']['source']).to eq('pre_calculated')
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with legacy area_too_large that can be recalculated' do
|
|
|
|
|
let(:stat) do
|
|
|
|
|
create(:stat, :with_sharing_enabled, user:, year: 2024, month: 6,
|
2025-09-19 13:55:27 -04:00
|
|
|
h3_hex_ids: { 'area_too_large' => true })
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
let(:params) do
|
2025-09-18 12:29:46 -04:00
|
|
|
ActionController::Parameters.new(
|
|
|
|
|
{
|
|
|
|
|
uuid: stat.sharing_uuid,
|
|
|
|
|
min_lon: -74.1,
|
|
|
|
|
min_lat: 40.6,
|
|
|
|
|
max_lon: -73.9,
|
2025-09-18 14:02:18 -04:00
|
|
|
max_lat: 40.8
|
2025-09-18 12:29:46 -04:00
|
|
|
}
|
|
|
|
|
)
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
# Mock successful recalculation
|
|
|
|
|
allow_any_instance_of(Stats::CalculateMonth).to receive(:calculate_hexagon_centers)
|
|
|
|
|
.and_return([[-74.0, 40.7, 1_717_200_000, 1_717_203_600]])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'recalculates and returns pre-calculated data' do
|
|
|
|
|
result = handle_request
|
|
|
|
|
|
|
|
|
|
expect(result['type']).to eq('FeatureCollection')
|
|
|
|
|
expect(result['features'].length).to eq(1)
|
|
|
|
|
expect(result['metadata']['pre_calculated']).to be true
|
2025-09-16 19:55:42 -04:00
|
|
|
|
|
|
|
|
# Verify that the stat was updated with new centers (reload to check persistence)
|
2025-09-19 13:55:27 -04:00
|
|
|
expect(stat.reload.h3_hex_ids).to eq([[-74.0, 40.7, 1_717_200_000, 1_717_203_600]])
|
2025-09-16 19:55:42 -04:00
|
|
|
end
|
|
|
|
|
end
|
2025-09-16 14:41:53 -04:00
|
|
|
end
|
2025-09-18 12:29:46 -04:00
|
|
|
end
|