# frozen_string_literal: true require 'rails_helper' RSpec.describe Points::RawData::ChunkCompressor do let(:user) { create(:user) } before do # Stub broadcasting to avoid ActionCable issues in tests allow(PointsChannel).to receive(:broadcast_to) end let(:points) do [ create(:point, user: user, raw_data: { lon: 13.4, lat: 52.5 }), create(:point, user: user, raw_data: { lon: 13.5, lat: 52.6 }), create(:point, user: user, raw_data: { lon: 13.6, lat: 52.7 }) ] end let(:compressor) { described_class.new(Point.where(id: points.map(&:id))) } describe '#compress' do it 'returns compressed gzip data' do result = compressor.compress expect(result).to be_a(String) expect(result.encoding.name).to eq('ASCII-8BIT') end it 'compresses points as JSONL format' do compressed = compressor.compress # Decompress and verify format io = StringIO.new(compressed) gz = Zlib::GzipReader.new(io) lines = gz.readlines gz.close expect(lines.count).to eq(3) # Each line should be valid JSON lines.each_with_index do |line, index| data = JSON.parse(line) expect(data).to have_key('id') expect(data).to have_key('raw_data') expect(data['id']).to eq(points[index].id) end end it 'includes point ID and raw_data in each line' do compressed = compressor.compress io = StringIO.new(compressed) gz = Zlib::GzipReader.new(io) first_line = gz.readline gz.close data = JSON.parse(first_line) expect(data['id']).to eq(points.first.id) expect(data['raw_data']).to eq({ 'lon' => 13.4, 'lat' => 52.5 }) end it 'processes points in batches' do # Create many points to test batch processing with unique timestamps many_points = [] base_time = Time.new(2024, 6, 15).to_i 2500.times do |i| many_points << create(:point, user: user, timestamp: base_time + i, raw_data: { lon: 13.4, lat: 52.5 }) end large_compressor = described_class.new(Point.where(id: many_points.map(&:id))) compressed = large_compressor.compress io = StringIO.new(compressed) gz = Zlib::GzipReader.new(io) line_count = 0 gz.each_line { line_count += 1 } gz.close expect(line_count).to eq(2500) end it 'produces smaller compressed output than uncompressed' do compressed = compressor.compress # Decompress to get original size io = StringIO.new(compressed) gz = Zlib::GzipReader.new(io) decompressed = gz.read gz.close # Compressed should be smaller expect(compressed.bytesize).to be < decompressed.bytesize end end end