Files
COMERCIAL-GTI/maquina-comercial-pessoal/tests/google-places.test.mjs
T
GustavoandClaude Sonnet 5 417da56bd6 chore: import maquina-comercial-pessoal history via subtree
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

git-subtree-dir: maquina-comercial-pessoal
git-subtree-mainline: f5af038e19
git-subtree-split: a9ef4d776d
2026-09-28 15:50:17 -03:00

89 lines
3.2 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { collect } from '../src/sources/google-places.mjs';
function fakeCtx() {
const logs = [];
return { emit: () => {}, log: (message) => logs.push(message), isCancelled: () => false, logs };
}
// Antes, uma falha na pagina 2/3 (comum: o next_page_token do Google ainda
// nao ativou apesar da espera de 2.5s entre paginas, ou uma falha transitoria
// de rede) fazia search() lancar e descartar TODOS os leads ja obtidos nas
// paginas anteriores bem-sucedidas, nao so a pagina que falhou.
test('falha na pagina 2 nao descarta os leads ja obtidos na pagina 1', async () => {
process.env.GOOGLE_PLACES_API_KEY = 'chave-teste';
const originalFetch = globalThis.fetch;
let textsearchCalls = 0;
globalThis.fetch = async (url) => {
const href = url.toString();
if (href.includes('textsearch')) {
textsearchCalls += 1;
if (textsearchCalls === 1) {
return new Response(JSON.stringify({
status: 'OK',
results: [{ place_id: 'p1', name: 'Pizzaria Um' }],
next_page_token: 'tok-pagina-2'
}));
}
// Pagina 2: falha transitoria (token ainda nao ativo, erro do provedor, etc.)
return new Response(JSON.stringify({ status: 'INVALID_REQUEST' }));
}
if (href.includes('details')) {
return new Response(JSON.stringify({ result: { place_id: 'p1', name: 'Pizzaria Um' } }));
}
throw new Error(`fetch inesperado: ${href}`);
};
try {
const ctx = fakeCtx();
const params = {
uf: 'BA',
cities: ['Salvador'],
segments: [{ name: 'restaurantes', queries: ['pizzaria'], interest: 'comida', pains: [] }],
limits: { maxPerQuery: 10, googlePages: 3 }
};
const batches = [];
for await (const batch of collect(params, ctx)) batches.push(batch);
assert.equal(batches.length, 1, JSON.stringify(batches));
assert.equal(batches[0].leads.length, 1);
assert.equal(batches[0].leads[0].company.name, 'Pizzaria Um');
assert.ok(ctx.logs.some((message) => /pagina 2/.test(message)), ctx.logs.join(' | '));
} finally {
globalThis.fetch = originalFetch;
delete process.env.GOOGLE_PLACES_API_KEY;
}
});
// Uma falha logo na primeira pagina (nada acumulado ainda) continua
// propagando e sendo tratada pelo chamador (loga e pula a query inteira) —
// esse caminho nao muda.
test('falha na primeira pagina ainda propaga e pula a query', async () => {
process.env.GOOGLE_PLACES_API_KEY = 'chave-teste';
const originalFetch = globalThis.fetch;
globalThis.fetch = async () => new Response(JSON.stringify({ status: 'INVALID_REQUEST' }));
try {
const ctx = fakeCtx();
const params = {
uf: 'BA',
cities: ['Salvador'],
segments: [{ name: 'restaurantes', queries: ['pizzaria'], interest: 'comida', pains: [] }],
limits: { maxPerQuery: 10, googlePages: 3 }
};
const batches = [];
for await (const batch of collect(params, ctx)) batches.push(batch);
assert.equal(batches.length, 0);
assert.ok(ctx.logs.some((message) => /falhou em/.test(message)), ctx.logs.join(' | '));
} finally {
globalThis.fetch = originalFetch;
delete process.env.GOOGLE_PLACES_API_KEY;
}
});