HabitatMap/AirCasting

View on GitHub
spec/services/air_now/import_measurements_spec.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'rails_helper'

# locations aqsid|parameter|site_code|site_name|status|agency_id|agency_name|epa_region|latitude|longitude|elevation|timezone|country|msa_code|msa_name|state_code|state_name|county_code|county_name
# measurements date|time|aqsid|location|timezone|parameter|unit|value|attribution

describe AirNow::ImportMeasurements do
  let!(:user) do
    User.create!(
      email: 'airnow@example.com',
      username: 'US EPA AirNow',
      password: 'abcdefgh'
    )
  end

  let!(:mock_import_data) { instance_double(AirNow::ImportData) }
  let!(:locations_data) { "000020104|location-name|site-code|site-name|status|agency-id|agency-name|epa-region|44.941101|-105.837799|27.9|timezone|country|msa-code|msa-name|state-code|state-name|county-code|county-name" }
  let!(:threshold_set_pm25) { create_threshold_set!(sensor_name: 'Government-PM2.5', unit_symbol: 'µg/m³', threshold_very_low: 0, threshold_low: 12, threshold_medium: 35, threshold_high: 55, threshold_very_high: 150) }
  let!(:threshold_set_no2) { create_threshold_set!(sensor_name: 'Government-NO2', unit_symbol: 'ppb', threshold_very_low: 0, threshold_low: 53, threshold_medium: 100, threshold_high: 360, threshold_very_high: 649) }
  let!(:threshold_set_o3) { create_threshold_set!(sensor_name: 'Government-Ozone', unit_symbol: 'ppb', threshold_very_low: 0, threshold_low: 59, threshold_medium: 75, threshold_high: 95, threshold_very_high: 115) }

  context 'with correct data' do
    before do
      allow(AirNow::ImportData).to receive(:new).and_return(mock_import_data)
      allow(mock_import_data).to receive(:call).and_return([locations_data, measurements_data])
    end

    let!(:measurements_data) { ["03/25/24|07:00|000020104|measurement-location|-4|PM2.5|PPB|0.3|attribution"] }

    it 'creates measurement, stream, session correctly for correct data' do
      described_class.new.call

      locations_array = locations_data.split('|')
      measurements_array = measurements_data.first.split('|')

      [
        [:value, measurements_array[7].to_f],
        [:latitude, locations_array[8].to_f],
        [:longitude, locations_array[9].to_f]
      ].each do |attribute, expected|
        expect(Measurement.first.public_send(attribute)).to eq(expected)
      end

      [
        [:sensor_name, "Government-PM2.5"],
        [:unit_name, "microgram per cubic meter"],
        [:measurement_type, "Particulate Matter"],
        [:measurement_short_type, "PM"],
        [:unit_symbol, "µg/m³"],
        [:sensor_package_name, "Government-PM2.5"],
      ].each do |attribute, expected|
        expect(Stream.first.public_send(attribute)).to eq(expected)
      end

      [
        [:latitude, locations_array[8].to_f],
        [:longitude, locations_array[9].to_f],
        [:title, locations_array[3]]
      ].each do |attribute, expected|
        expect(Session.first.public_send(attribute)).to eq(expected)
      end
    end
  end

  context 'with unwanted parameters' do
    let!(:measurements_data) do
      ["03/25/24|07:00|000020104|measurement-location|-4|SO2|PPB|0.3|attribution\n" +
      "03/25/24|07:00|000020104|measurement-location|-4|NO2|PPB|0.3|attribution"]
    end

    before do
      allow(AirNow::ImportData).to receive(:new).and_return(mock_import_data)
      allow(mock_import_data).to receive(:call).and_return([locations_data, measurements_data])
    end

    it 'does not create measurement, stream, session for unwanted parameter' do
      described_class.new.call
      expect(Measurement.count).to eq(1)
      expect(Stream.count).to eq(1)
      expect(Session.count).to eq(1)
    end
  end

  context 'with multiple correct measurements in the same location' do
    let!(:measurements_data) do
      ["03/25/24|07:00|000020104|measurement-location|-4|PM2.5|PPB|0.3|attribution\n" +
      "03/25/24|07:00|000020104|measurement-location|-4|NO2|PPB|0.3|attribution"]
    end

    before do
      allow(AirNow::ImportData).to receive(:new).and_return(mock_import_data)
      allow(mock_import_data).to receive(:call).and_return([locations_data, measurements_data])
    end

    it 'creates sessions for multiple correct measurements and streams in the same location' do
      described_class.new.call
      expect(Measurement.count).to eq(2)
      expect(Stream.count).to eq(2)
      expect(Session.count).to eq(2)
    end
  end
end