"""The Tiny adapter against a fake HTTP transport: payload and idempotency. This proves the documented contract only; the client's account must still confirm endpoints, product codes and tags. Runs where httpx is installed. """ import json import unittest from urllib.parse import parse_qs import httpx from app.tiny import TinyError, TinyOrders, order_payload PAID = {'order_id': 'b6f1c0de-0000-4000-8000-000000000001', 'number': 42, 'event': 'payment_approved', 'order': {'customer': {'cnpj': '11222333000181', 'zap': '16999999999', 'mail': 'loja@example.test'}, 'items': [{'mode': 'avulsa', 'grade': 90, 'billed_metres': '2.8', 'unit_cents': 2490}], 'freight': {'service': 'mock-standard', 'total_cents': 1500}, 'destination': {'recipient': 'Loja Teste', 'street': 'Rua A', 'number': '10', 'complement': '', 'district': 'Centro', 'city': 'Franca', 'state': 'SP', 'postal_code': '14400000'}, 'total_cents': 8472}} class TinyTests(unittest.TestCase): def setUp(self): self.orders = {} self.calls = [] def handler(request): form = {k: v[0] for k, v in parse_qs(request.content.decode()).items()} method = request.url.path.rsplit('/', 1)[-1].removesuffix('.php') self.calls.append((method, form)) if method == 'pedidos.pesquisa': found = self.orders.get(form['numeroEcommerce']) if not found: return httpx.Response(200, json={'retorno': {'status': 'Erro', 'codigo_erro': 20}}) return httpx.Response(200, json={'retorno': {'status': 'OK', 'pedidos': [{'pedido': found}]}}) pedido = json.loads(form['pedido'])['pedido'] record = {'id': 9000 + len(self.orders), 'numero': 100 + len(self.orders), 'status': 'OK'} self.orders[pedido['numero_pedido_ecommerce']] = {**record, 'numero_ecommerce': pedido['numero_pedido_ecommerce']} return httpx.Response(200, json={'retorno': {'status': 'OK', 'registros': [{'registro': {'sequencia': 1, **record}}]}}) self.tiny = TinyOrders('test-token', transport=httpx.MockTransport(handler)) def test_payload_carries_customer_address_items_and_freight(self): pedido = order_payload(PAID)['pedido'] self.assertEqual(pedido['numero_pedido_ecommerce'], 'DTF-42') self.assertEqual((pedido['cliente']['cpf_cnpj'], pedido['cliente']['cep'], pedido['cliente']['uf']), ('11222333000181', '14400000', 'SP')) item = pedido['itens'][0]['item'] self.assertEqual((item['quantidade'], item['valor_unitario'], item['unidade']), ('2.8', '24.90', 'M')) self.assertEqual(pedido['valor_frete'], '15.00') pickup = order_payload({**PAID, 'order': {**PAID['order'], 'destination': None, 'freight': {'service': 'pickup', 'total_cents': 0}}})['pedido'] self.assertEqual((pickup['forma_envio'], pickup['frete_por_conta']), ('X', 'R')) self.assertNotIn('endereco', pickup['cliente']) def test_second_delivery_finds_the_first_order(self): first = self.tiny.deliver('k1', PAID) second = self.tiny.deliver('k1', PAID) self.assertEqual(first['status'], 'created') self.assertEqual(second['status'], 'already-created') self.assertEqual(first['tiny_id'], second['tiny_id']) self.assertEqual([m for m, _ in self.calls].count('pedido.incluir'), 1) self.assertEqual(self.calls[0][1]['token'], 'test-token') def test_production_events_are_not_sent(self): self.assertEqual(self.tiny.deliver('k2', {**PAID, 'event': 'ready'})['status'], 'not-applicable') self.assertEqual(self.calls, []) def test_errors_reported_in_the_body_are_failures(self): tiny = TinyOrders('t', transport=httpx.MockTransport(lambda r: httpx.Response( 200, json={'retorno': {'status': 'Erro', 'codigo_erro': 6, 'erros': [{'erro': 'API Bloqueada'}]}}))) with self.assertRaises(TinyError): tiny.deliver('k3', PAID) if __name__ == '__main__': unittest.main()