iachat/spec/jobs/channels/whatsapp/zapi_qr_code_job_spec.rb
Gabriel Jablonski 63a2c70667
fix(zapi): first connection issues, and merge existing contact on received message (#138)
* fix(zapi): pairing issues on first connection

* fix(zapi): handle existing contact when receiving new message

* refactor: simplify logic
2025-11-06 23:41:58 -03:00

111 lines
4.6 KiB
Ruby

require 'rails_helper'
RSpec.describe Channels::Whatsapp::ZapiQrCodeJob do
let(:whatsapp_channel) do
create(:channel_whatsapp,
provider: 'zapi',
sync_templates: false,
validate_provider_config: false,
provider_config: {
'instance_id' => 'test-instance',
'token' => 'test-token',
'client_token' => 'test-client-token'
})
end
let(:zapi_service) { instance_double(Whatsapp::Providers::WhatsappZapiService) }
before do
allow(Whatsapp::Providers::WhatsappZapiService).to receive(:new)
.with(whatsapp_channel: whatsapp_channel)
.and_return(zapi_service)
end
describe '#perform' do
it 'returns early on first attempt when connection is not close' do
whatsapp_channel.update_provider_connection!(connection: 'open')
expect(zapi_service).not_to receive(:qr_code_image)
described_class.perform_now(whatsapp_channel, 1)
end
it 'returns early on subsequent attempts when connection is not connecting' do
whatsapp_channel.update_provider_connection!(connection: 'open')
expect(zapi_service).not_to receive(:qr_code_image)
described_class.perform_now(whatsapp_channel, 2)
end
it 'fetches QR code and schedules next attempt on first attempt with blank connection' do
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
expect(described_class).to receive(:set).with(wait: 30.seconds).and_call_original
expect do
described_class.perform_now(whatsapp_channel, 1)
end.to have_enqueued_job(described_class).with(whatsapp_channel, 2)
expect(whatsapp_channel.reload.provider_connection['connection']).to eq('connecting')
expect(whatsapp_channel.provider_connection['qr_data_url']).to eq('data:image/png;base64,test-qr-code')
end
it 'fetches QR code and schedules next attempt on first attempt with close connection' do
whatsapp_channel.update_provider_connection!(connection: 'close')
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
expect(described_class).to receive(:set).with(wait: 30.seconds).and_call_original
expect do
described_class.perform_now(whatsapp_channel, 1)
end.to have_enqueued_job(described_class).with(whatsapp_channel, 2)
expect(whatsapp_channel.reload.provider_connection['connection']).to eq('connecting')
expect(whatsapp_channel.provider_connection['qr_data_url']).to eq('data:image/png;base64,test-qr-code')
end
it 'fetches QR code and schedules next attempt on subsequent attempts with connecting connection' do
whatsapp_channel.update_provider_connection!(connection: 'connecting')
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,updated-qr-code')
expect(described_class).to receive(:set).with(wait: 30.seconds).and_call_original
expect do
described_class.perform_now(whatsapp_channel, 2)
end.to have_enqueued_job(described_class).with(whatsapp_channel, 3)
whatsapp_channel.reload
expect(whatsapp_channel.provider_connection['connection']).to eq('connecting')
expect(whatsapp_channel.provider_connection['qr_data_url']).to eq('data:image/png;base64,updated-qr-code')
end
it 'does not update provider connection when QR code is blank' do
whatsapp_channel.update_provider_connection!(connection: 'close')
allow(zapi_service).to receive(:qr_code_image).and_return(nil)
expect(whatsapp_channel).not_to receive(:update_provider_connection!)
described_class.perform_now(whatsapp_channel, 1)
end
it 'avoids race condition when connection becomes open during processing' do
whatsapp_channel.update_provider_connection!(connection: 'close')
allow(zapi_service).to receive(:qr_code_image).and_return('data:image/png;base64,test-qr-code')
allow(whatsapp_channel).to receive(:reload).and_return(whatsapp_channel)
allow(whatsapp_channel).to receive(:provider_connection).and_return({ 'connection' => 'open' })
expect(whatsapp_channel).not_to receive(:update_provider_connection!)
described_class.perform_now(whatsapp_channel, 1)
end
it 'sets connection to close when maximum attempts exceeded' do
whatsapp_channel.update_provider_connection!(connection: 'connecting')
expect(zapi_service).not_to receive(:qr_code_image)
expect(described_class).not_to receive(:set)
described_class.perform_now(whatsapp_channel, 4)
expect(whatsapp_channel.reload.provider_connection['connection']).to eq('close')
end
end
end