"""The Jadlog quote client against a fake HTTP transport: payload and errors. This proves the manual's contract only; app.jadlog_probe must still confirm it on the client's account. Runs where httpx is installed. """ import json import unittest import httpx from app.jadlog import QUOTE_URL, JadlogError, JadlogQuotes from app.jadlog_probe import run CNPJ = '11.222.333/0001-81' def client(handler, **settings): return JadlogQuotes(token=settings.pop('token', 'tok-1'), cnpj=CNPJ, conta='123456', transport=httpx.MockTransport(handler), **settings) class JadlogQuoteTest(unittest.TestCase): def test_payload_follows_the_manual_and_price_becomes_centavos(self): seen = [] def handler(request): seen.append(request) item = json.loads(request.content)['frete'][0] return httpx.Response(200, json={'frete': [{**item, 'vltotal': 23.455, 'prazo': 4}]}) result = client(handler).quote('01310-100', 1.5, 12990) request = seen[0] self.assertEqual(str(request.url), QUOTE_URL) self.assertEqual(request.headers['authorization'], 'tok-1') item = json.loads(request.content)['frete'][0] self.assertEqual(item, {'cepori': '14402310', 'cepdes': '01310100', 'frap': 'N', 'peso': 1.5, 'cnpj': '11222333000181', 'conta': '123456', 'contrato': None, 'modalidade': 3, 'tpentrega': 'D', 'tpseguro': 'N', 'vldeclarado': 129.9, 'vlcoleta': 0}) self.assertEqual((result['total_cents'], result['days']), (2346, 4)) def test_contract_is_sent_only_when_configured(self): def handler(request): item = json.loads(request.content)['frete'][0] self.assertEqual(item['contrato'], '042') return httpx.Response(200, json={'frete': [{'vltotal': 10, 'prazo': 2}]}) client(handler, contrato='042').quote('01310100', 1, 100) def test_account_and_item_errors_are_raised_with_jadlog_text(self): replies = [ httpx.Response(200, json={'frete': [{}], 'error': {'id': -1, 'descricao': 'frete[0].contrato Numero de contrato invalido'}}), httpx.Response(200, json={'frete': [{'erro': {'id': 2, 'descricao': 'CEP destino invalido'}}]}), httpx.Response(200, json={'frete': [{'prazo': 3}]}), httpx.Response(502, text='bad gateway'), ] messages = ['contrato invalido', 'CEP destino invalido', 'no freight value', 'not JSON'] for reply, message in zip(replies, messages): with self.subTest(message=message), self.assertRaisesRegex(JadlogError, message): client(lambda request, reply=reply: reply).quote('01310100', 1, 100) def test_missing_credentials_refuse_to_start(self): with self.assertRaises(RuntimeError): JadlogQuotes(token='', cnpj=CNPJ) with self.assertRaises(RuntimeError): JadlogQuotes(token='tok', cnpj='123') class JadlogProbeTest(unittest.TestCase): def test_bearer_is_tried_once_after_a_401_and_kept(self): headers = [] def handler(request): headers.append(request.headers['authorization']) if not request.headers['authorization'].startswith('Bearer '): return httpx.Response(401, json={'descricao': 'TOKEN INVALIDO', 'id': 1}) return httpx.Response(200, json={'frete': [{'vltotal': 12.5, 'prazo': 3}]}) lines = [] status = run(client(handler), ['01310100', '20040002'], ['1'], 10000, lines.append) self.assertEqual(status, 0) self.assertEqual(headers, ['tok-1', 'Bearer tok-1', 'Bearer tok-1']) self.assertIn('Bearer', lines[0]) self.assertIn('R$ 12,50', lines[1]) def test_first_failure_stops_the_run(self): calls = [] def handler(request): calls.append(request) return httpx.Response(200, json={'frete': [{}], 'error': {'id': -1, 'descricao': 'CNPJ invalido'}}) lines = [] self.assertEqual(run(client(handler), ['01310100', '20040002'], ['1', '2'], 10000, lines.append), 1) self.assertEqual(len(calls), 1) self.assertIn('CNPJ invalido', lines[0]) if __name__ == '__main__': unittest.main()