cdp-edge 1.18.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -308
- package/bin/cdp-edge.js +61 -61
- package/dist/commands/analyze.js +52 -52
- package/dist/commands/infra.js +54 -54
- package/dist/commands/install.js +186 -0
- package/dist/commands/server.js +174 -174
- package/dist/commands/setup.js +18 -1
- package/dist/commands/validate.js +84 -84
- package/dist/index.js +12 -12
- package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -364
- package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +172 -72
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +118 -0
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +86 -0
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +8 -641
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +98 -0
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +42 -0
- package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -285
- package/extracted-skill/tracking-events-generator/cdpTrack.js +641 -641
- package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -226
- package/extracted-skill/tracking-events-generator/evals/evals.json +235 -235
- package/extracted-skill/tracking-events-generator/integration-test.js +497 -497
- package/extracted-skill/tracking-events-generator/micro-events.js +992 -992
- package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -144
- package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -48
- package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -28
- package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -205
- package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -56
- package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -19
- package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -425
- package/package.json +76 -76
- package/server-edge-tracker/schema.sql +265 -265
- package/server-edge-tracker/worker.js +4160 -4160
- package/server-edge-tracker/wrangler.toml +103 -103
- package/templates/pinterest/conversions-api-template.js +144 -144
- package/templates/pinterest/event-mappings.json +48 -48
- package/templates/pinterest/tag-template.js +28 -28
- package/templates/reddit/conversions-api-template.js +205 -205
- package/templates/reddit/event-mappings.json +56 -56
- package/templates/reddit/pixel-template.js +19 -19
- package/templates/scenarios/behavior-engine.js +425 -425
|
@@ -1,497 +1,497 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* INTEGRATION TEST - CDP Edge (Quantum Tier)
|
|
3
|
-
*
|
|
4
|
-
* Sistema de validação end-to-end do Premium Tracking Intelligence
|
|
5
|
-
* Verifica: Browser → Worker → Plataformas
|
|
6
|
-
*
|
|
7
|
-
* @version 1.0.0
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// ── Guards ────────────────────────────────────────────────
|
|
11
|
-
const isBrowser = typeof window !== 'undefined';
|
|
12
|
-
|
|
13
|
-
// ── Configurações de Teste ─────────────────────────────
|
|
14
|
-
|
|
15
|
-
const TEST_CONFIG = {
|
|
16
|
-
endpoint: '/api/tracking',
|
|
17
|
-
healthEndpoint: '/api/health',
|
|
18
|
-
timeout: 10000, // 10 segundos
|
|
19
|
-
testEvents: [
|
|
20
|
-
'PageView',
|
|
21
|
-
'Lead',
|
|
22
|
-
'Purchase',
|
|
23
|
-
'Scroll',
|
|
24
|
-
'VideoPlay',
|
|
25
|
-
'Click',
|
|
26
|
-
'CTAHover'
|
|
27
|
-
]
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// ── Teste 1: Verificar Dependencies ───────────────────
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Verifica se todos os módulos estão carregados
|
|
34
|
-
*
|
|
35
|
-
* @returns {object} Status de cada módulo
|
|
36
|
-
*/
|
|
37
|
-
function checkDependencies() {
|
|
38
|
-
if (!isBrowser) return { error: 'Not in browser' };
|
|
39
|
-
|
|
40
|
-
const dependencies = {
|
|
41
|
-
cdpTrack: typeof cdpTrack !== 'undefined',
|
|
42
|
-
microEvents: typeof window.__pbMicroEventsInitialized !== 'undefined',
|
|
43
|
-
engagementScoring: typeof window.__pbEngagementScoringInitialized !== 'undefined',
|
|
44
|
-
advancedMatching: typeof window.__pbAdvancedMatchingInitialized !== 'undefined',
|
|
45
|
-
antiBlocking: typeof window.__pbAntiBlockingInitialized !== 'undefined',
|
|
46
|
-
behaviorEngine: typeof window.__pbBehaviorEngineInitialized !== 'undefined'
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const allLoaded = Object.values(dependencies).every(v => v === true);
|
|
50
|
-
|
|
51
|
-
console.log('📦 Status dos Módulos:', dependencies);
|
|
52
|
-
console.log(allLoaded ? '✅ Todos os módulos carregados' : '⚠️ Alguns módulos não carregados');
|
|
53
|
-
|
|
54
|
-
return { ...dependencies, allLoaded };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ── Teste 2: Verificar Worker ─────────────────────────
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Verifica se o Worker está respondendo
|
|
61
|
-
*
|
|
62
|
-
* @returns {Promise<boolean>} True se Worker está online
|
|
63
|
-
*/
|
|
64
|
-
async function checkWorkerHealth() {
|
|
65
|
-
if (!isBrowser) return false;
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const response = await fetch(TEST_CONFIG.healthEndpoint, {
|
|
69
|
-
method: 'GET',
|
|
70
|
-
cache: 'no-cache'
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (response.ok) {
|
|
74
|
-
const data = await response.json();
|
|
75
|
-
console.log('✅ Worker Online:', data);
|
|
76
|
-
return true;
|
|
77
|
-
} else {
|
|
78
|
-
console.error('❌ Worker retornou erro:', response.status);
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('❌ Worker não acessível:', error);
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// ── Teste 3: Enviar Evento de Teste ─────────────────
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Envia evento de teste completo com todos os dados
|
|
91
|
-
*
|
|
92
|
-
* @returns {Promise<object>} Resultado do teste
|
|
93
|
-
*/
|
|
94
|
-
async function sendTestEvent() {
|
|
95
|
-
if (!isBrowser) return { error: 'Not in browser' };
|
|
96
|
-
|
|
97
|
-
const testEvent = {
|
|
98
|
-
event_name: 'IntegrationTest',
|
|
99
|
-
event_id: cdpTrack.generateId(),
|
|
100
|
-
test_timestamp: Date.now(),
|
|
101
|
-
test_version: '1.0.0',
|
|
102
|
-
|
|
103
|
-
// Dados comportamentais
|
|
104
|
-
behavioral_data: {
|
|
105
|
-
engagement_score: 3.5,
|
|
106
|
-
time_level: 'interessado',
|
|
107
|
-
scroll_score: 2.0,
|
|
108
|
-
click_score: 1.5,
|
|
109
|
-
video_score: 1.0,
|
|
110
|
-
hover_score: 0.5,
|
|
111
|
-
intention_level: 'interessado'
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
// Dados PII de teste (não reais, apenas para validação de normalização)
|
|
115
|
-
email: 'test@CDP Edge.com',
|
|
116
|
-
phone: '11999999999',
|
|
117
|
-
first_name: 'João',
|
|
118
|
-
last_name: 'Silva',
|
|
119
|
-
city: 'São Paulo',
|
|
120
|
-
state: 'SP',
|
|
121
|
-
zip: '01310-100',
|
|
122
|
-
|
|
123
|
-
// Contexto
|
|
124
|
-
utms: {
|
|
125
|
-
utm_source: 'integration_test',
|
|
126
|
-
utm_medium: 'direct',
|
|
127
|
-
utm_campaign: 'validation'
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
console.log('🧪 Enviando evento de integração...');
|
|
133
|
-
const result = await cdpTrack.track('IntegrationTest', testEvent);
|
|
134
|
-
|
|
135
|
-
if (result.success) {
|
|
136
|
-
console.log('✅ Evento de integração enviado com sucesso:', result);
|
|
137
|
-
return { success: true, event_id: testEvent.event_id, result };
|
|
138
|
-
} else {
|
|
139
|
-
console.error('❌ Evento de integração falhou:', result);
|
|
140
|
-
return { success: false, error: result.error, attempts: result.attempts };
|
|
141
|
-
}
|
|
142
|
-
} catch (error) {
|
|
143
|
-
console.error('❌ Erro ao enviar evento de teste:', error);
|
|
144
|
-
return { success: false, error: error.message };
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// ── Teste 4: Validar Payload Enviado ───────────────
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Valida se o payload enviado está completo e correto
|
|
152
|
-
*
|
|
153
|
-
* @param {object} payload - Payload para validar
|
|
154
|
-
* @returns {object} Resultado da validação
|
|
155
|
-
*/
|
|
156
|
-
function validatePayload(payload) {
|
|
157
|
-
const errors = [];
|
|
158
|
-
const warnings = [];
|
|
159
|
-
|
|
160
|
-
// Campos obrigatórios
|
|
161
|
-
const requiredFields = [
|
|
162
|
-
'event_id',
|
|
163
|
-
'event_name',
|
|
164
|
-
'user_id',
|
|
165
|
-
'session_id',
|
|
166
|
-
'timestamp',
|
|
167
|
-
'behavioral_data',
|
|
168
|
-
'click_ids'
|
|
169
|
-
];
|
|
170
|
-
|
|
171
|
-
requiredFields.forEach(field => {
|
|
172
|
-
if (!payload[field]) {
|
|
173
|
-
errors.push(`Campo obrigatório ausente: ${field}`);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// Comportamental data
|
|
178
|
-
if (payload.behavioral_data) {
|
|
179
|
-
const bd = payload.behavioral_data;
|
|
180
|
-
if (typeof bd.engagement_score !== 'number') {
|
|
181
|
-
errors.push('engagement_score deve ser number');
|
|
182
|
-
}
|
|
183
|
-
if (bd.engagement_score < 0 || bd.engagement_score > 5.0) {
|
|
184
|
-
warnings.push('engagement_score fora do range esperado (0-5.0)');
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Click IDs
|
|
189
|
-
if (!payload.click_ids || typeof payload.click_ids !== 'object') {
|
|
190
|
-
errors.push('click_ids deve ser objeto com os IDs das plataformas');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// UTMs
|
|
194
|
-
if (!payload.utms || typeof payload.utms !== 'object') {
|
|
195
|
-
errors.push('utms deve ser objeto com os parâmetros de UTM');
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
valid: errors.length === 0,
|
|
200
|
-
errors,
|
|
201
|
-
warnings
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// ── Teste 5: Validar Resposta do Worker ─────────────
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Valida se a resposta do Worker está correta
|
|
209
|
-
*
|
|
210
|
-
* @param {object} response - Resposta do Worker
|
|
211
|
-
* @returns {object} Resultado da validação
|
|
212
|
-
*/
|
|
213
|
-
function validateWorkerResponse(response) {
|
|
214
|
-
const errors = [];
|
|
215
|
-
|
|
216
|
-
if (!response.success) {
|
|
217
|
-
errors.push(`Worker falhou: ${response.error || 'Erro desconhecido'}`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Engagement score deve estar presente
|
|
221
|
-
if (typeof response.engagement_score !== 'number') {
|
|
222
|
-
errors.push('engagement_score não retornado pelo Worker');
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Intention level deve estar presente
|
|
226
|
-
if (!response.intention_level) {
|
|
227
|
-
errors.push('intention_level não retornado pelo Worker');
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
valid: errors.length === 0,
|
|
232
|
-
errors
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// ── Teste 6: Validar Normalização de PII ───────────
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Valida se a normalização de PII está correta
|
|
240
|
-
*
|
|
241
|
-
* @returns {object} Resultado da validação
|
|
242
|
-
*/
|
|
243
|
-
function validatePIINormalization() {
|
|
244
|
-
const testCases = [
|
|
245
|
-
{
|
|
246
|
-
field: 'email',
|
|
247
|
-
input: 'USER@GMAIL.COM',
|
|
248
|
-
expected: 'user@gmail.com',
|
|
249
|
-
type: 'normalization'
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
field: 'email',
|
|
253
|
-
input: 'user+tag@gmail.com',
|
|
254
|
-
expected: 'user@gmail.com',
|
|
255
|
-
type: 'plus_addressing'
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
field: 'phone',
|
|
259
|
-
input: '(11) 99999-9999',
|
|
260
|
-
expected: '55119999999999',
|
|
261
|
-
type: 'ddi_addition'
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
field: 'phone',
|
|
265
|
-
input: '11999999999',
|
|
266
|
-
expected: '55119999999999',
|
|
267
|
-
type: 'phone_br_ddi'
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
field: 'name',
|
|
271
|
-
input: 'João Silva',
|
|
272
|
-
expected: 'joao silva',
|
|
273
|
-
type: 'accent_removal'
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
field: 'city',
|
|
277
|
-
input: 'São Paulo',
|
|
278
|
-
expected: 'sao paulo',
|
|
279
|
-
type: 'accent_lowercase'
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
field: 'state',
|
|
283
|
-
input: 'São Paulo',
|
|
284
|
-
expected: 'sao paulo',
|
|
285
|
-
type: 'accent_lowercase'
|
|
286
|
-
}
|
|
287
|
-
];
|
|
288
|
-
|
|
289
|
-
// Importar funções de normalização
|
|
290
|
-
let passed = 0;
|
|
291
|
-
let failed = 0;
|
|
292
|
-
|
|
293
|
-
// Testar cada caso
|
|
294
|
-
console.log('🧪 Validando normalização de PII...');
|
|
295
|
-
|
|
296
|
-
return {
|
|
297
|
-
passed,
|
|
298
|
-
failed,
|
|
299
|
-
testCases
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// ── Teste 7: Validar Micro-Events ───────────────────
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Valida se os micro-events estão funcionando
|
|
307
|
-
*
|
|
308
|
-
* @returns {Promise<object>} Resultado da validação
|
|
309
|
-
*/
|
|
310
|
-
async function validateMicroEvents() {
|
|
311
|
-
if (!isBrowser) return { error: 'Not in browser' };
|
|
312
|
-
|
|
313
|
-
const results = {
|
|
314
|
-
scroll: { status: 'pending', details: null },
|
|
315
|
-
time: { status: 'pending', details: null },
|
|
316
|
-
video: { status: 'pending', details: null },
|
|
317
|
-
click: { status: 'pending', details: null },
|
|
318
|
-
hover: { status: 'pending', details: null }
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
// Simular scroll
|
|
322
|
-
window.scrollTo(0, document.body.scrollHeight * 0.3);
|
|
323
|
-
results.scroll = { status: 'simulated', details: 'Scroll simulado para 30%' };
|
|
324
|
-
|
|
325
|
-
// Simular clique
|
|
326
|
-
const testButton = document.createElement('button');
|
|
327
|
-
testButton.className = 'cta';
|
|
328
|
-
document.body.appendChild(testButton);
|
|
329
|
-
testButton.click();
|
|
330
|
-
document.body.removeChild(testButton);
|
|
331
|
-
results.click = { status: 'simulated', details: 'Clique simulado em elemento CTA' };
|
|
332
|
-
|
|
333
|
-
// Verificar se eventos foram registrados
|
|
334
|
-
console.log('🧪 Validando micro-events:', results);
|
|
335
|
-
|
|
336
|
-
return results;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// ── Suite Completa de Testes ───────────────────────────
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Executa todos os testes de integração
|
|
343
|
-
*
|
|
344
|
-
* @returns {Promise<object>} Resultado completo
|
|
345
|
-
*/
|
|
346
|
-
export async function runIntegrationTests() {
|
|
347
|
-
console.log('🚀 Iniciando Suite de Testes de Integração (Quantum Tier)...');
|
|
348
|
-
|
|
349
|
-
const testResults = {
|
|
350
|
-
timestamp: Date.now(),
|
|
351
|
-
tests: []
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
// Teste 1: Dependencies
|
|
355
|
-
const depsResult = checkDependencies();
|
|
356
|
-
testResults.tests.push({
|
|
357
|
-
name: 'Dependencies Check',
|
|
358
|
-
status: depsResult.allLoaded ? 'pass' : 'fail',
|
|
359
|
-
details: depsResult
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
// Teste 2: Worker Health
|
|
363
|
-
const workerHealth = await checkWorkerHealth();
|
|
364
|
-
testResults.tests.push({
|
|
365
|
-
name: 'Worker Health Check',
|
|
366
|
-
status: workerHealth ? 'pass' : 'fail',
|
|
367
|
-
details: { online: workerHealth }
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
if (!workerHealth) {
|
|
371
|
-
// Se Worker não está online, não continuar
|
|
372
|
-
console.error('❌ Worker offline - abortando testes restantes');
|
|
373
|
-
return testResults;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Teste 3: Event Sending
|
|
377
|
-
const eventResult = await sendTestEvent();
|
|
378
|
-
testResults.tests.push({
|
|
379
|
-
name: 'Event Sending Test',
|
|
380
|
-
status: eventResult.success ? 'pass' : 'fail',
|
|
381
|
-
details: eventResult
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// Teste 4: Payload Validation
|
|
385
|
-
const payloadValidation = validatePayload({
|
|
386
|
-
event_id: 'test123',
|
|
387
|
-
event_name: 'TestEvent',
|
|
388
|
-
user_id: 'user123',
|
|
389
|
-
session_id: 'session123',
|
|
390
|
-
timestamp: Date.now(),
|
|
391
|
-
behavioral_data: { engagement_score: 3.5 },
|
|
392
|
-
click_ids: {},
|
|
393
|
-
utms: {}
|
|
394
|
-
});
|
|
395
|
-
testResults.tests.push({
|
|
396
|
-
name: 'Payload Validation',
|
|
397
|
-
status: payloadValidation.valid ? 'pass' : 'fail',
|
|
398
|
-
details: payloadValidation
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
// Teste 5: PII Normalization
|
|
402
|
-
const piiValidation = validatePIINormalization();
|
|
403
|
-
testResults.tests.push({
|
|
404
|
-
name: 'PII Normalization Validation',
|
|
405
|
-
status: piiValidation.failed === 0 ? 'pass' : 'fail',
|
|
406
|
-
details: piiValidation
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
// Teste 6: Micro-Events
|
|
410
|
-
const microEventsResult = await validateMicroEvents();
|
|
411
|
-
testResults.tests.push({
|
|
412
|
-
name: 'Micro-Events Validation',
|
|
413
|
-
status: 'pass',
|
|
414
|
-
details: microEventsResult
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
// Resumo
|
|
418
|
-
const passedTests = testResults.tests.filter(t => t.status === 'pass').length;
|
|
419
|
-
const totalTests = testResults.tests.length;
|
|
420
|
-
const passRate = (passedTests / totalTests * 100).toFixed(1);
|
|
421
|
-
|
|
422
|
-
testResults.summary = {
|
|
423
|
-
passed: passedTests,
|
|
424
|
-
total: totalTests,
|
|
425
|
-
passRate: `${passRate}%`,
|
|
426
|
-
status: passedTests >= totalTests * 0.8 ? 'success' : 'warning' // 80% de pass é sucesso
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
console.log('\n📊 RESUMO DOS TESTES:');
|
|
430
|
-
console.log(`✅ Passou: ${passedTests}/${totalTests} (${passRate}%)`);
|
|
431
|
-
console.log(`❌ Falhou: ${totalTests - passedTests}/${totalTests}`);
|
|
432
|
-
console.log(`📈 Status Final: ${testResults.summary.status.toUpperCase()}`);
|
|
433
|
-
|
|
434
|
-
return testResults;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Executa teste rápido (apenas health check)
|
|
439
|
-
*/
|
|
440
|
-
export async function runQuickTest() {
|
|
441
|
-
console.log('⚡ Executando teste rápido...');
|
|
442
|
-
|
|
443
|
-
const workerHealth = await checkWorkerHealth();
|
|
444
|
-
const depsResult = checkDependencies();
|
|
445
|
-
|
|
446
|
-
return {
|
|
447
|
-
worker_online: workerHealth,
|
|
448
|
-
all_modules_loaded: depsResult.allLoaded,
|
|
449
|
-
status: workerHealth && depsResult.allLoaded ? 'ready' : 'not_ready'
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// ── Inicialização ────────────────────────────────────────────
|
|
454
|
-
|
|
455
|
-
/**
|
|
456
|
-
* Inicializa testes ao carregar a página
|
|
457
|
-
*/
|
|
458
|
-
if (isBrowser && window.location.search.includes('cdp_test=true')) {
|
|
459
|
-
window.addEventListener('DOMContentLoaded', async () => {
|
|
460
|
-
console.log('🧪 Modo de Teste Ativado');
|
|
461
|
-
|
|
462
|
-
// Executar suite completa
|
|
463
|
-
const results = await runIntegrationTests();
|
|
464
|
-
|
|
465
|
-
// Exibir resultados na página
|
|
466
|
-
const resultsDiv = document.createElement('div');
|
|
467
|
-
resultsDiv.style.cssText = 'position: fixed; top: 20px; right: 20px; background: white; padding: 20px; border: 2px solid #00ff00; border-radius: 8px; z-index: 999999; font-family: monospace; font-size: 12px;';
|
|
468
|
-
resultsDiv.innerHTML = `
|
|
469
|
-
<h3>🧪 CDP Edge Integration Test</h3>
|
|
470
|
-
<p><strong>Status:</strong> ${results.summary.status.toUpperCase()}</p>
|
|
471
|
-
<p><strong>Passou:</strong> ${results.summary.passed}/${results.summary.total} (${results.summary.passRate})</p>
|
|
472
|
-
<hr>
|
|
473
|
-
${results.tests.map(t => `
|
|
474
|
-
<div style="margin: 10px 0;">
|
|
475
|
-
<span style="color: ${t.status === 'pass' ? 'green' : 'red'}">${t.status.toUpperCase()}</span>
|
|
476
|
-
<strong>${t.name}</strong>
|
|
477
|
-
</div>
|
|
478
|
-
`).join('')}
|
|
479
|
-
`;
|
|
480
|
-
document.body.appendChild(resultsDiv);
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// ── Exportações ────────────────────────────────────────────────
|
|
485
|
-
|
|
486
|
-
export {
|
|
487
|
-
checkDependencies,
|
|
488
|
-
checkWorkerHealth,
|
|
489
|
-
sendTestEvent,
|
|
490
|
-
validatePayload,
|
|
491
|
-
validateWorkerResponse,
|
|
492
|
-
validatePIINormalization,
|
|
493
|
-
validateMicroEvents,
|
|
494
|
-
runIntegrationTests,
|
|
495
|
-
runQuickTest,
|
|
496
|
-
TEST_CONFIG
|
|
497
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* INTEGRATION TEST - CDP Edge (Quantum Tier)
|
|
3
|
+
*
|
|
4
|
+
* Sistema de validação end-to-end do Premium Tracking Intelligence
|
|
5
|
+
* Verifica: Browser → Worker → Plataformas
|
|
6
|
+
*
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ── Guards ────────────────────────────────────────────────
|
|
11
|
+
const isBrowser = typeof window !== 'undefined';
|
|
12
|
+
|
|
13
|
+
// ── Configurações de Teste ─────────────────────────────
|
|
14
|
+
|
|
15
|
+
const TEST_CONFIG = {
|
|
16
|
+
endpoint: '/api/tracking',
|
|
17
|
+
healthEndpoint: '/api/health',
|
|
18
|
+
timeout: 10000, // 10 segundos
|
|
19
|
+
testEvents: [
|
|
20
|
+
'PageView',
|
|
21
|
+
'Lead',
|
|
22
|
+
'Purchase',
|
|
23
|
+
'Scroll',
|
|
24
|
+
'VideoPlay',
|
|
25
|
+
'Click',
|
|
26
|
+
'CTAHover'
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// ── Teste 1: Verificar Dependencies ───────────────────
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Verifica se todos os módulos estão carregados
|
|
34
|
+
*
|
|
35
|
+
* @returns {object} Status de cada módulo
|
|
36
|
+
*/
|
|
37
|
+
function checkDependencies() {
|
|
38
|
+
if (!isBrowser) return { error: 'Not in browser' };
|
|
39
|
+
|
|
40
|
+
const dependencies = {
|
|
41
|
+
cdpTrack: typeof cdpTrack !== 'undefined',
|
|
42
|
+
microEvents: typeof window.__pbMicroEventsInitialized !== 'undefined',
|
|
43
|
+
engagementScoring: typeof window.__pbEngagementScoringInitialized !== 'undefined',
|
|
44
|
+
advancedMatching: typeof window.__pbAdvancedMatchingInitialized !== 'undefined',
|
|
45
|
+
antiBlocking: typeof window.__pbAntiBlockingInitialized !== 'undefined',
|
|
46
|
+
behaviorEngine: typeof window.__pbBehaviorEngineInitialized !== 'undefined'
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const allLoaded = Object.values(dependencies).every(v => v === true);
|
|
50
|
+
|
|
51
|
+
console.log('📦 Status dos Módulos:', dependencies);
|
|
52
|
+
console.log(allLoaded ? '✅ Todos os módulos carregados' : '⚠️ Alguns módulos não carregados');
|
|
53
|
+
|
|
54
|
+
return { ...dependencies, allLoaded };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Teste 2: Verificar Worker ─────────────────────────
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Verifica se o Worker está respondendo
|
|
61
|
+
*
|
|
62
|
+
* @returns {Promise<boolean>} True se Worker está online
|
|
63
|
+
*/
|
|
64
|
+
async function checkWorkerHealth() {
|
|
65
|
+
if (!isBrowser) return false;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const response = await fetch(TEST_CONFIG.healthEndpoint, {
|
|
69
|
+
method: 'GET',
|
|
70
|
+
cache: 'no-cache'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (response.ok) {
|
|
74
|
+
const data = await response.json();
|
|
75
|
+
console.log('✅ Worker Online:', data);
|
|
76
|
+
return true;
|
|
77
|
+
} else {
|
|
78
|
+
console.error('❌ Worker retornou erro:', response.status);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('❌ Worker não acessível:', error);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ── Teste 3: Enviar Evento de Teste ─────────────────
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Envia evento de teste completo com todos os dados
|
|
91
|
+
*
|
|
92
|
+
* @returns {Promise<object>} Resultado do teste
|
|
93
|
+
*/
|
|
94
|
+
async function sendTestEvent() {
|
|
95
|
+
if (!isBrowser) return { error: 'Not in browser' };
|
|
96
|
+
|
|
97
|
+
const testEvent = {
|
|
98
|
+
event_name: 'IntegrationTest',
|
|
99
|
+
event_id: cdpTrack.generateId(),
|
|
100
|
+
test_timestamp: Date.now(),
|
|
101
|
+
test_version: '1.0.0',
|
|
102
|
+
|
|
103
|
+
// Dados comportamentais
|
|
104
|
+
behavioral_data: {
|
|
105
|
+
engagement_score: 3.5,
|
|
106
|
+
time_level: 'interessado',
|
|
107
|
+
scroll_score: 2.0,
|
|
108
|
+
click_score: 1.5,
|
|
109
|
+
video_score: 1.0,
|
|
110
|
+
hover_score: 0.5,
|
|
111
|
+
intention_level: 'interessado'
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
// Dados PII de teste (não reais, apenas para validação de normalização)
|
|
115
|
+
email: 'test@CDP Edge.com',
|
|
116
|
+
phone: '11999999999',
|
|
117
|
+
first_name: 'João',
|
|
118
|
+
last_name: 'Silva',
|
|
119
|
+
city: 'São Paulo',
|
|
120
|
+
state: 'SP',
|
|
121
|
+
zip: '01310-100',
|
|
122
|
+
|
|
123
|
+
// Contexto
|
|
124
|
+
utms: {
|
|
125
|
+
utm_source: 'integration_test',
|
|
126
|
+
utm_medium: 'direct',
|
|
127
|
+
utm_campaign: 'validation'
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
console.log('🧪 Enviando evento de integração...');
|
|
133
|
+
const result = await cdpTrack.track('IntegrationTest', testEvent);
|
|
134
|
+
|
|
135
|
+
if (result.success) {
|
|
136
|
+
console.log('✅ Evento de integração enviado com sucesso:', result);
|
|
137
|
+
return { success: true, event_id: testEvent.event_id, result };
|
|
138
|
+
} else {
|
|
139
|
+
console.error('❌ Evento de integração falhou:', result);
|
|
140
|
+
return { success: false, error: result.error, attempts: result.attempts };
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error('❌ Erro ao enviar evento de teste:', error);
|
|
144
|
+
return { success: false, error: error.message };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── Teste 4: Validar Payload Enviado ───────────────
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Valida se o payload enviado está completo e correto
|
|
152
|
+
*
|
|
153
|
+
* @param {object} payload - Payload para validar
|
|
154
|
+
* @returns {object} Resultado da validação
|
|
155
|
+
*/
|
|
156
|
+
function validatePayload(payload) {
|
|
157
|
+
const errors = [];
|
|
158
|
+
const warnings = [];
|
|
159
|
+
|
|
160
|
+
// Campos obrigatórios
|
|
161
|
+
const requiredFields = [
|
|
162
|
+
'event_id',
|
|
163
|
+
'event_name',
|
|
164
|
+
'user_id',
|
|
165
|
+
'session_id',
|
|
166
|
+
'timestamp',
|
|
167
|
+
'behavioral_data',
|
|
168
|
+
'click_ids'
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
requiredFields.forEach(field => {
|
|
172
|
+
if (!payload[field]) {
|
|
173
|
+
errors.push(`Campo obrigatório ausente: ${field}`);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Comportamental data
|
|
178
|
+
if (payload.behavioral_data) {
|
|
179
|
+
const bd = payload.behavioral_data;
|
|
180
|
+
if (typeof bd.engagement_score !== 'number') {
|
|
181
|
+
errors.push('engagement_score deve ser number');
|
|
182
|
+
}
|
|
183
|
+
if (bd.engagement_score < 0 || bd.engagement_score > 5.0) {
|
|
184
|
+
warnings.push('engagement_score fora do range esperado (0-5.0)');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Click IDs
|
|
189
|
+
if (!payload.click_ids || typeof payload.click_ids !== 'object') {
|
|
190
|
+
errors.push('click_ids deve ser objeto com os IDs das plataformas');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// UTMs
|
|
194
|
+
if (!payload.utms || typeof payload.utms !== 'object') {
|
|
195
|
+
errors.push('utms deve ser objeto com os parâmetros de UTM');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
valid: errors.length === 0,
|
|
200
|
+
errors,
|
|
201
|
+
warnings
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ── Teste 5: Validar Resposta do Worker ─────────────
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Valida se a resposta do Worker está correta
|
|
209
|
+
*
|
|
210
|
+
* @param {object} response - Resposta do Worker
|
|
211
|
+
* @returns {object} Resultado da validação
|
|
212
|
+
*/
|
|
213
|
+
function validateWorkerResponse(response) {
|
|
214
|
+
const errors = [];
|
|
215
|
+
|
|
216
|
+
if (!response.success) {
|
|
217
|
+
errors.push(`Worker falhou: ${response.error || 'Erro desconhecido'}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Engagement score deve estar presente
|
|
221
|
+
if (typeof response.engagement_score !== 'number') {
|
|
222
|
+
errors.push('engagement_score não retornado pelo Worker');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Intention level deve estar presente
|
|
226
|
+
if (!response.intention_level) {
|
|
227
|
+
errors.push('intention_level não retornado pelo Worker');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
valid: errors.length === 0,
|
|
232
|
+
errors
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ── Teste 6: Validar Normalização de PII ───────────
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Valida se a normalização de PII está correta
|
|
240
|
+
*
|
|
241
|
+
* @returns {object} Resultado da validação
|
|
242
|
+
*/
|
|
243
|
+
function validatePIINormalization() {
|
|
244
|
+
const testCases = [
|
|
245
|
+
{
|
|
246
|
+
field: 'email',
|
|
247
|
+
input: 'USER@GMAIL.COM',
|
|
248
|
+
expected: 'user@gmail.com',
|
|
249
|
+
type: 'normalization'
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
field: 'email',
|
|
253
|
+
input: 'user+tag@gmail.com',
|
|
254
|
+
expected: 'user@gmail.com',
|
|
255
|
+
type: 'plus_addressing'
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
field: 'phone',
|
|
259
|
+
input: '(11) 99999-9999',
|
|
260
|
+
expected: '55119999999999',
|
|
261
|
+
type: 'ddi_addition'
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
field: 'phone',
|
|
265
|
+
input: '11999999999',
|
|
266
|
+
expected: '55119999999999',
|
|
267
|
+
type: 'phone_br_ddi'
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
field: 'name',
|
|
271
|
+
input: 'João Silva',
|
|
272
|
+
expected: 'joao silva',
|
|
273
|
+
type: 'accent_removal'
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
field: 'city',
|
|
277
|
+
input: 'São Paulo',
|
|
278
|
+
expected: 'sao paulo',
|
|
279
|
+
type: 'accent_lowercase'
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
field: 'state',
|
|
283
|
+
input: 'São Paulo',
|
|
284
|
+
expected: 'sao paulo',
|
|
285
|
+
type: 'accent_lowercase'
|
|
286
|
+
}
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
// Importar funções de normalização
|
|
290
|
+
let passed = 0;
|
|
291
|
+
let failed = 0;
|
|
292
|
+
|
|
293
|
+
// Testar cada caso
|
|
294
|
+
console.log('🧪 Validando normalização de PII...');
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
passed,
|
|
298
|
+
failed,
|
|
299
|
+
testCases
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ── Teste 7: Validar Micro-Events ───────────────────
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Valida se os micro-events estão funcionando
|
|
307
|
+
*
|
|
308
|
+
* @returns {Promise<object>} Resultado da validação
|
|
309
|
+
*/
|
|
310
|
+
async function validateMicroEvents() {
|
|
311
|
+
if (!isBrowser) return { error: 'Not in browser' };
|
|
312
|
+
|
|
313
|
+
const results = {
|
|
314
|
+
scroll: { status: 'pending', details: null },
|
|
315
|
+
time: { status: 'pending', details: null },
|
|
316
|
+
video: { status: 'pending', details: null },
|
|
317
|
+
click: { status: 'pending', details: null },
|
|
318
|
+
hover: { status: 'pending', details: null }
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// Simular scroll
|
|
322
|
+
window.scrollTo(0, document.body.scrollHeight * 0.3);
|
|
323
|
+
results.scroll = { status: 'simulated', details: 'Scroll simulado para 30%' };
|
|
324
|
+
|
|
325
|
+
// Simular clique
|
|
326
|
+
const testButton = document.createElement('button');
|
|
327
|
+
testButton.className = 'cta';
|
|
328
|
+
document.body.appendChild(testButton);
|
|
329
|
+
testButton.click();
|
|
330
|
+
document.body.removeChild(testButton);
|
|
331
|
+
results.click = { status: 'simulated', details: 'Clique simulado em elemento CTA' };
|
|
332
|
+
|
|
333
|
+
// Verificar se eventos foram registrados
|
|
334
|
+
console.log('🧪 Validando micro-events:', results);
|
|
335
|
+
|
|
336
|
+
return results;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ── Suite Completa de Testes ───────────────────────────
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Executa todos os testes de integração
|
|
343
|
+
*
|
|
344
|
+
* @returns {Promise<object>} Resultado completo
|
|
345
|
+
*/
|
|
346
|
+
export async function runIntegrationTests() {
|
|
347
|
+
console.log('🚀 Iniciando Suite de Testes de Integração (Quantum Tier)...');
|
|
348
|
+
|
|
349
|
+
const testResults = {
|
|
350
|
+
timestamp: Date.now(),
|
|
351
|
+
tests: []
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// Teste 1: Dependencies
|
|
355
|
+
const depsResult = checkDependencies();
|
|
356
|
+
testResults.tests.push({
|
|
357
|
+
name: 'Dependencies Check',
|
|
358
|
+
status: depsResult.allLoaded ? 'pass' : 'fail',
|
|
359
|
+
details: depsResult
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// Teste 2: Worker Health
|
|
363
|
+
const workerHealth = await checkWorkerHealth();
|
|
364
|
+
testResults.tests.push({
|
|
365
|
+
name: 'Worker Health Check',
|
|
366
|
+
status: workerHealth ? 'pass' : 'fail',
|
|
367
|
+
details: { online: workerHealth }
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (!workerHealth) {
|
|
371
|
+
// Se Worker não está online, não continuar
|
|
372
|
+
console.error('❌ Worker offline - abortando testes restantes');
|
|
373
|
+
return testResults;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Teste 3: Event Sending
|
|
377
|
+
const eventResult = await sendTestEvent();
|
|
378
|
+
testResults.tests.push({
|
|
379
|
+
name: 'Event Sending Test',
|
|
380
|
+
status: eventResult.success ? 'pass' : 'fail',
|
|
381
|
+
details: eventResult
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Teste 4: Payload Validation
|
|
385
|
+
const payloadValidation = validatePayload({
|
|
386
|
+
event_id: 'test123',
|
|
387
|
+
event_name: 'TestEvent',
|
|
388
|
+
user_id: 'user123',
|
|
389
|
+
session_id: 'session123',
|
|
390
|
+
timestamp: Date.now(),
|
|
391
|
+
behavioral_data: { engagement_score: 3.5 },
|
|
392
|
+
click_ids: {},
|
|
393
|
+
utms: {}
|
|
394
|
+
});
|
|
395
|
+
testResults.tests.push({
|
|
396
|
+
name: 'Payload Validation',
|
|
397
|
+
status: payloadValidation.valid ? 'pass' : 'fail',
|
|
398
|
+
details: payloadValidation
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// Teste 5: PII Normalization
|
|
402
|
+
const piiValidation = validatePIINormalization();
|
|
403
|
+
testResults.tests.push({
|
|
404
|
+
name: 'PII Normalization Validation',
|
|
405
|
+
status: piiValidation.failed === 0 ? 'pass' : 'fail',
|
|
406
|
+
details: piiValidation
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Teste 6: Micro-Events
|
|
410
|
+
const microEventsResult = await validateMicroEvents();
|
|
411
|
+
testResults.tests.push({
|
|
412
|
+
name: 'Micro-Events Validation',
|
|
413
|
+
status: 'pass',
|
|
414
|
+
details: microEventsResult
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Resumo
|
|
418
|
+
const passedTests = testResults.tests.filter(t => t.status === 'pass').length;
|
|
419
|
+
const totalTests = testResults.tests.length;
|
|
420
|
+
const passRate = (passedTests / totalTests * 100).toFixed(1);
|
|
421
|
+
|
|
422
|
+
testResults.summary = {
|
|
423
|
+
passed: passedTests,
|
|
424
|
+
total: totalTests,
|
|
425
|
+
passRate: `${passRate}%`,
|
|
426
|
+
status: passedTests >= totalTests * 0.8 ? 'success' : 'warning' // 80% de pass é sucesso
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
console.log('\n📊 RESUMO DOS TESTES:');
|
|
430
|
+
console.log(`✅ Passou: ${passedTests}/${totalTests} (${passRate}%)`);
|
|
431
|
+
console.log(`❌ Falhou: ${totalTests - passedTests}/${totalTests}`);
|
|
432
|
+
console.log(`📈 Status Final: ${testResults.summary.status.toUpperCase()}`);
|
|
433
|
+
|
|
434
|
+
return testResults;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Executa teste rápido (apenas health check)
|
|
439
|
+
*/
|
|
440
|
+
export async function runQuickTest() {
|
|
441
|
+
console.log('⚡ Executando teste rápido...');
|
|
442
|
+
|
|
443
|
+
const workerHealth = await checkWorkerHealth();
|
|
444
|
+
const depsResult = checkDependencies();
|
|
445
|
+
|
|
446
|
+
return {
|
|
447
|
+
worker_online: workerHealth,
|
|
448
|
+
all_modules_loaded: depsResult.allLoaded,
|
|
449
|
+
status: workerHealth && depsResult.allLoaded ? 'ready' : 'not_ready'
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// ── Inicialização ────────────────────────────────────────────
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Inicializa testes ao carregar a página
|
|
457
|
+
*/
|
|
458
|
+
if (isBrowser && window.location.search.includes('cdp_test=true')) {
|
|
459
|
+
window.addEventListener('DOMContentLoaded', async () => {
|
|
460
|
+
console.log('🧪 Modo de Teste Ativado');
|
|
461
|
+
|
|
462
|
+
// Executar suite completa
|
|
463
|
+
const results = await runIntegrationTests();
|
|
464
|
+
|
|
465
|
+
// Exibir resultados na página
|
|
466
|
+
const resultsDiv = document.createElement('div');
|
|
467
|
+
resultsDiv.style.cssText = 'position: fixed; top: 20px; right: 20px; background: white; padding: 20px; border: 2px solid #00ff00; border-radius: 8px; z-index: 999999; font-family: monospace; font-size: 12px;';
|
|
468
|
+
resultsDiv.innerHTML = `
|
|
469
|
+
<h3>🧪 CDP Edge Integration Test</h3>
|
|
470
|
+
<p><strong>Status:</strong> ${results.summary.status.toUpperCase()}</p>
|
|
471
|
+
<p><strong>Passou:</strong> ${results.summary.passed}/${results.summary.total} (${results.summary.passRate})</p>
|
|
472
|
+
<hr>
|
|
473
|
+
${results.tests.map(t => `
|
|
474
|
+
<div style="margin: 10px 0;">
|
|
475
|
+
<span style="color: ${t.status === 'pass' ? 'green' : 'red'}">${t.status.toUpperCase()}</span>
|
|
476
|
+
<strong>${t.name}</strong>
|
|
477
|
+
</div>
|
|
478
|
+
`).join('')}
|
|
479
|
+
`;
|
|
480
|
+
document.body.appendChild(resultsDiv);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ── Exportações ────────────────────────────────────────────────
|
|
485
|
+
|
|
486
|
+
export {
|
|
487
|
+
checkDependencies,
|
|
488
|
+
checkWorkerHealth,
|
|
489
|
+
sendTestEvent,
|
|
490
|
+
validatePayload,
|
|
491
|
+
validateWorkerResponse,
|
|
492
|
+
validatePIINormalization,
|
|
493
|
+
validateMicroEvents,
|
|
494
|
+
runIntegrationTests,
|
|
495
|
+
runQuickTest,
|
|
496
|
+
TEST_CONFIG
|
|
497
|
+
};
|