Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> git-subtree-dir: maquina-comercial-pessoal git-subtree-mainline:f5af038e19git-subtree-split:a9ef4d776d
89 lines
3.2 KiB
JavaScript
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;
|
|
}
|
|
});
|