@silasfmartins/testhub 1.0.0
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/.github/copilot-instructions.md +520 -0
- package/biome.json +37 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +169 -0
- package/dist/scripts/consumer-postinstall.d.ts +15 -0
- package/dist/scripts/consumer-postinstall.js +785 -0
- package/dist/scripts/generate-docs.d.ts +16 -0
- package/dist/scripts/generate-docs.js +1363 -0
- package/dist/scripts/generate-index.d.ts +2 -0
- package/dist/scripts/generate-index.js +314 -0
- package/dist/scripts/init-api.d.ts +2 -0
- package/dist/scripts/init-api.js +525 -0
- package/dist/scripts/init-banco.d.ts +2 -0
- package/dist/scripts/init-banco.js +347 -0
- package/dist/scripts/init-frontend.d.ts +2 -0
- package/dist/scripts/init-frontend.js +627 -0
- package/dist/scripts/init-mobile.d.ts +2 -0
- package/dist/scripts/init-mobile.js +481 -0
- package/dist/scripts/init-scenarios.d.ts +2 -0
- package/dist/scripts/init-scenarios.js +846 -0
- package/dist/scripts/init-ssh.d.ts +2 -0
- package/dist/scripts/init-ssh.js +639 -0
- package/dist/scripts/package-versions.d.ts +57 -0
- package/dist/scripts/package-versions.js +768 -0
- package/dist/scripts/postinstall.d.ts +1 -0
- package/dist/scripts/postinstall.js +527 -0
- package/dist/scripts/robust-build.d.ts +7 -0
- package/dist/scripts/robust-build.js +88 -0
- package/dist/scripts/setup-local-packages.d.ts +31 -0
- package/dist/scripts/setup-local-packages.js +237 -0
- package/dist/scripts/smart-override.d.ts +2 -0
- package/dist/scripts/smart-override.js +1360 -0
- package/dist/scripts/sync-configs.d.ts +27 -0
- package/dist/scripts/sync-configs.js +248 -0
- package/dist/scripts/test-biome-parse.d.ts +5 -0
- package/dist/scripts/test-biome-parse.js +84 -0
- package/dist/scripts/ultracite-setup.d.ts +4 -0
- package/dist/scripts/ultracite-setup.js +310 -0
- package/dist/scripts/update-all-init-scripts.d.ts +2 -0
- package/dist/scripts/update-all-init-scripts.js +52 -0
- package/dist/scripts/update-biome-schema.d.ts +15 -0
- package/dist/scripts/update-biome-schema.js +124 -0
- package/dist/src/AutoCoreFacade.d.ts +145 -0
- package/dist/src/AutoCoreFacade.js +217 -0
- package/dist/src/api/ApiActions.d.ts +297 -0
- package/dist/src/api/ApiActions.js +1905 -0
- package/dist/src/api/Certificate.d.ts +60 -0
- package/dist/src/api/Certificate.js +79 -0
- package/dist/src/api/JsonResponse.d.ts +116 -0
- package/dist/src/api/JsonResponse.js +206 -0
- package/dist/src/appium/DeviceFarmViewer.d.ts +79 -0
- package/dist/src/appium/DeviceFarmViewer.js +1083 -0
- package/dist/src/appium/MobileActions.d.ts +347 -0
- package/dist/src/appium/MobileActions.js +1632 -0
- package/dist/src/appium/MobileConnection.d.ts +160 -0
- package/dist/src/appium/MobileConnection.js +772 -0
- package/dist/src/config/envLoader.d.ts +123 -0
- package/dist/src/config/envLoader.js +361 -0
- package/dist/src/config/jest-safe-setup.d.ts +19 -0
- package/dist/src/config/jest-safe-setup.js +369 -0
- package/dist/src/config/timeouts.d.ts +32 -0
- package/dist/src/config/timeouts.js +38 -0
- package/dist/src/desktop/DesktopActions.d.ts +46 -0
- package/dist/src/desktop/DesktopActions.js +398 -0
- package/dist/src/desktop/DesktopConnection.d.ts +32 -0
- package/dist/src/desktop/DesktopConnection.js +84 -0
- package/dist/src/domain/entities/TestExecution.d.ts +117 -0
- package/dist/src/domain/entities/TestExecution.js +150 -0
- package/dist/src/domain/entities/TestReport.d.ts +114 -0
- package/dist/src/domain/entities/TestReport.js +179 -0
- package/dist/src/domain/repositories/ITestRepository.d.ts +196 -0
- package/dist/src/domain/repositories/ITestRepository.js +14 -0
- package/dist/src/domain/schemas/ValidationSchemas.d.ts +159 -0
- package/dist/src/domain/schemas/ValidationSchemas.js +181 -0
- package/dist/src/functions/errors/BaseError.d.ts +78 -0
- package/dist/src/functions/errors/BaseError.js +245 -0
- package/dist/src/functions/errors/ConfigurationError.d.ts +16 -0
- package/dist/src/functions/errors/ConfigurationError.js +48 -0
- package/dist/src/functions/errors/ErrorCatalog.d.ts +148 -0
- package/dist/src/functions/errors/ErrorCatalog.js +157 -0
- package/dist/src/functions/errors/GlobalErrorHandler.d.ts +101 -0
- package/dist/src/functions/errors/GlobalErrorHandler.js +281 -0
- package/dist/src/functions/errors/IntegrationError.d.ts +17 -0
- package/dist/src/functions/errors/IntegrationError.js +51 -0
- package/dist/src/functions/errors/SecurityError.d.ts +14 -0
- package/dist/src/functions/errors/SecurityError.js +42 -0
- package/dist/src/functions/errors/SystemError.d.ts +12 -0
- package/dist/src/functions/errors/SystemError.js +36 -0
- package/dist/src/functions/errors/ValidationError.d.ts +14 -0
- package/dist/src/functions/errors/ValidationError.js +61 -0
- package/dist/src/functions/errors/index.d.ts +12 -0
- package/dist/src/functions/errors/index.js +13 -0
- package/dist/src/global-setup.d.ts +1 -0
- package/dist/src/global-setup.js +1037 -0
- package/dist/src/helpers/BancoActions.d.ts +188 -0
- package/dist/src/helpers/BancoActions.js +581 -0
- package/dist/src/helpers/EnviromentHelper.d.ts +17 -0
- package/dist/src/helpers/EnviromentHelper.js +66 -0
- package/dist/src/helpers/ParallelExecutionHelper.d.ts +183 -0
- package/dist/src/helpers/ParallelExecutionHelper.js +375 -0
- package/dist/src/helpers/SyncSignal.d.ts +15 -0
- package/dist/src/helpers/SyncSignal.js +44 -0
- package/dist/src/hubdocs/CategoryDetector.d.ts +83 -0
- package/dist/src/hubdocs/CategoryDetector.js +401 -0
- package/dist/src/hubdocs/DirectStatementInterceptor.d.ts +54 -0
- package/dist/src/hubdocs/DirectStatementInterceptor.js +243 -0
- package/dist/src/hubdocs/ExecutionTracker.d.ts +107 -0
- package/dist/src/hubdocs/ExecutionTracker.js +702 -0
- package/dist/src/hubdocs/HubDocs.d.ts +395 -0
- package/dist/src/hubdocs/HubDocs.js +3586 -0
- package/dist/src/hubdocs/StatementMethodFilter.d.ts +71 -0
- package/dist/src/hubdocs/StatementMethodFilter.js +618 -0
- package/dist/src/hubdocs/StatementTracker.d.ts +417 -0
- package/dist/src/hubdocs/StatementTracker.js +2419 -0
- package/dist/src/hubdocs/SwaggerGenerator.d.ts +59 -0
- package/dist/src/hubdocs/SwaggerGenerator.js +405 -0
- package/dist/src/hubdocs/index.d.ts +9 -0
- package/dist/src/hubdocs/index.js +9 -0
- package/dist/src/hubdocs/types.d.ts +114 -0
- package/dist/src/hubdocs/types.js +5 -0
- package/dist/src/infrastructure/DependencyContainer.d.ts +142 -0
- package/dist/src/infrastructure/DependencyContainer.js +250 -0
- package/dist/src/infrastructure/adapters/AppiumAdapter.d.ts +168 -0
- package/dist/src/infrastructure/adapters/AppiumAdapter.js +468 -0
- package/dist/src/infrastructure/adapters/OracleAdapter.d.ts +150 -0
- package/dist/src/infrastructure/adapters/OracleAdapter.js +388 -0
- package/dist/src/infrastructure/adapters/PlaywrightAdapter.d.ts +192 -0
- package/dist/src/infrastructure/adapters/PlaywrightAdapter.js +382 -0
- package/dist/src/infrastructure/adapters/SSHAdapter.d.ts +141 -0
- package/dist/src/infrastructure/adapters/SSHAdapter.js +428 -0
- package/dist/src/interfaces.d.ts +501 -0
- package/dist/src/interfaces.js +25 -0
- package/dist/src/internal/fakes/__fake-actions__.d.ts +17 -0
- package/dist/src/internal/fakes/__fake-actions__.js +21 -0
- package/dist/src/internal/fakes/__forbidden__.d.ts +10 -0
- package/dist/src/internal/fakes/__forbidden__.js +18 -0
- package/dist/src/internal/fakes/__honeypot__.d.ts +15 -0
- package/dist/src/internal/fakes/__honeypot__.js +24 -0
- package/dist/src/octane/OctaneReporter.d.ts +13 -0
- package/dist/src/octane/OctaneReporter.js +61 -0
- package/dist/src/playwright/CryptoActions.d.ts +20 -0
- package/dist/src/playwright/CryptoActions.js +75 -0
- package/dist/src/playwright/EnhancedWebActions.d.ts +7 -0
- package/dist/src/playwright/EnhancedWebActions.js +65 -0
- package/dist/src/playwright/WebActions.d.ts +1599 -0
- package/dist/src/playwright/WebActions.js +11788 -0
- package/dist/src/playwright/actions/ActionTimeline.d.ts +36 -0
- package/dist/src/playwright/actions/ActionTimeline.js +101 -0
- package/dist/src/playwright/actions/RecoveryQueue.d.ts +82 -0
- package/dist/src/playwright/actions/RecoveryQueue.js +130 -0
- package/dist/src/playwright/actions/SelectorCache.d.ts +53 -0
- package/dist/src/playwright/actions/SelectorCache.js +96 -0
- package/dist/src/playwright/actions/index.d.ts +13 -0
- package/dist/src/playwright/actions/index.js +14 -0
- package/dist/src/playwright/actions/types.d.ts +147 -0
- package/dist/src/playwright/actions/types.js +5 -0
- package/dist/src/playwright/fixtures.d.ts +112 -0
- package/dist/src/playwright/fixtures.js +718 -0
- package/dist/src/playwright/network-logs-reporter.d.ts +7 -0
- package/dist/src/playwright/network-logs-reporter.js +66 -0
- package/dist/src/playwright/registerRecoveryWrappers.d.ts +1 -0
- package/dist/src/playwright/registerRecoveryWrappers.js +54 -0
- package/dist/src/security/BuildSecurity.d.ts +12 -0
- package/dist/src/security/BuildSecurity.js +138 -0
- package/dist/src/security/EulaProtection.d.ts +70 -0
- package/dist/src/security/EulaProtection.js +155 -0
- package/dist/src/security/HoneypotManager.d.ts +46 -0
- package/dist/src/security/HoneypotManager.js +234 -0
- package/dist/src/security/KeysManager.d.ts +36 -0
- package/dist/src/security/KeysManager.js +158 -0
- package/dist/src/security/ProofOfWorkIntegration.d.ts +64 -0
- package/dist/src/security/ProofOfWorkIntegration.js +206 -0
- package/dist/src/security/SecurityValidation.d.ts +21 -0
- package/dist/src/security/SecurityValidation.js +163 -0
- package/dist/src/security/SourceMapProtection.d.ts +55 -0
- package/dist/src/security/SourceMapProtection.js +220 -0
- package/dist/src/security/protector.d.ts +1 -0
- package/dist/src/security/protector.js +97 -0
- package/dist/src/ssh/SSHActions.d.ts +262 -0
- package/dist/src/ssh/SSHActions.js +790 -0
- package/dist/src/ssh/SSHClient.d.ts +99 -0
- package/dist/src/ssh/SSHClient.js +409 -0
- package/dist/src/statements/BaseStatement.d.ts +38 -0
- package/dist/src/statements/BaseStatement.js +78 -0
- package/dist/src/testContext/AuthStateManager.d.ts +93 -0
- package/dist/src/testContext/AuthStateManager.js +256 -0
- package/dist/src/testContext/CoverageManager.d.ts +198 -0
- package/dist/src/testContext/CoverageManager.js +917 -0
- package/dist/src/testContext/TestAnnotations.d.ts +476 -0
- package/dist/src/testContext/TestAnnotations.js +2647 -0
- package/dist/src/testContext/TestContext.d.ts +138 -0
- package/dist/src/testContext/TestContext.js +369 -0
- package/dist/src/testContext/UnifiedHtmlGenerator.d.ts +7 -0
- package/dist/src/testContext/UnifiedHtmlGenerator.js +264 -0
- package/dist/src/testContext/UnifiedReportManager.d.ts +211 -0
- package/dist/src/testContext/UnifiedReportManager.js +1206 -0
- package/dist/src/testhub/DynamicConfigManager.d.ts +121 -0
- package/dist/src/testhub/DynamicConfigManager.js +320 -0
- package/dist/src/testhub/SystemsManager.d.ts +119 -0
- package/dist/src/testhub/SystemsManager.js +365 -0
- package/dist/src/testhub/TestHubClient.d.ts +335 -0
- package/dist/src/testhub/TestHubClient.js +1215 -0
- package/dist/src/testhub/TestHubReporter.d.ts +62 -0
- package/dist/src/testhub/TestHubReporter.js +576 -0
- package/dist/src/testhub/TestHubVars.d.ts +116 -0
- package/dist/src/testhub/TestHubVars.js +273 -0
- package/dist/src/utils/ActionInterceptor.d.ts +59 -0
- package/dist/src/utils/ActionInterceptor.js +741 -0
- package/dist/src/utils/ArtifactsCompressor.d.ts +43 -0
- package/dist/src/utils/ArtifactsCompressor.js +181 -0
- package/dist/src/utils/AutoLogsFinal.d.ts +47 -0
- package/dist/src/utils/AutoLogsFinal.js +148 -0
- package/dist/src/utils/CodeGenSession.d.ts +114 -0
- package/dist/src/utils/CodeGenSession.js +264 -0
- package/dist/src/utils/ConfigLogger.d.ts +133 -0
- package/dist/src/utils/ConfigLogger.js +611 -0
- package/dist/src/utils/CustomReporter.d.ts +22 -0
- package/dist/src/utils/CustomReporter.js +352 -0
- package/dist/src/utils/DataStore.d.ts +171 -0
- package/dist/src/utils/DataStore.js +484 -0
- package/dist/src/utils/DatabaseInterceptor.d.ts +19 -0
- package/dist/src/utils/DatabaseInterceptor.js +295 -0
- package/dist/src/utils/DateHelper.d.ts +16 -0
- package/dist/src/utils/DateHelper.js +120 -0
- package/dist/src/utils/DateValidator.d.ts +4 -0
- package/dist/src/utils/DateValidator.js +51 -0
- package/dist/src/utils/DocumentGenerator.d.ts +35 -0
- package/dist/src/utils/DocumentGenerator.js +129 -0
- package/dist/src/utils/EvidenceCapture.d.ts +90 -0
- package/dist/src/utils/EvidenceCapture.js +600 -0
- package/dist/src/utils/EvidenceReportGenerator.d.ts +70 -0
- package/dist/src/utils/EvidenceReportGenerator.js +799 -0
- package/dist/src/utils/FrameManagementUtil.d.ts +42 -0
- package/dist/src/utils/FrameManagementUtil.js +75 -0
- package/dist/src/utils/GlobalStatementsInterceptor.d.ts +1 -0
- package/dist/src/utils/GlobalStatementsInterceptor.js +1 -0
- package/dist/src/utils/HTMLTemplate.d.ts +1 -0
- package/dist/src/utils/HTMLTemplate.js +1034 -0
- package/dist/src/utils/InterceptacaoMagica.d.ts +23 -0
- package/dist/src/utils/InterceptacaoMagica.js +365 -0
- package/dist/src/utils/LogSanitizer.d.ts +35 -0
- package/dist/src/utils/LogSanitizer.js +110 -0
- package/dist/src/utils/Logger.d.ts +65 -0
- package/dist/src/utils/Logger.js +284 -0
- package/dist/src/utils/McpLocalClient.d.ts +141 -0
- package/dist/src/utils/McpLocalClient.js +871 -0
- package/dist/src/utils/PDFEvidenceGenerator.d.ts +20 -0
- package/dist/src/utils/PDFEvidenceGenerator.js +156 -0
- package/dist/src/utils/SpecFileAnalyzer.d.ts +35 -0
- package/dist/src/utils/SpecFileAnalyzer.js +209 -0
- package/dist/src/utils/StatementInterceptor.d.ts +18 -0
- package/dist/src/utils/StatementInterceptor.js +87 -0
- package/dist/src/utils/StatementLogger.d.ts +33 -0
- package/dist/src/utils/StatementLogger.js +113 -0
- package/dist/src/utils/StatementsInterceptor.d.ts +1 -0
- package/dist/src/utils/StatementsInterceptor.js +1 -0
- package/dist/src/utils/TeamsFlushHook.d.ts +17 -0
- package/dist/src/utils/TeamsFlushHook.js +168 -0
- package/dist/src/utils/TerminalLogCapture.d.ts +158 -0
- package/dist/src/utils/TerminalLogCapture.js +531 -0
- package/dist/src/utils/TestMethodLogger.d.ts +70 -0
- package/dist/src/utils/TestMethodLogger.js +95 -0
- package/dist/src/utils/UnifiedTeardown.d.ts +4 -0
- package/dist/src/utils/UnifiedTeardown.js +400 -0
- package/dist/src/utils/XPathCatalog.d.ts +152 -0
- package/dist/src/utils/XPathCatalog.js +350 -0
- package/dist/src/utils/generators.d.ts +90 -0
- package/dist/src/utils/generators.js +167 -0
- package/dist/src/utils/testRecovery/ResilientPlaywright.d.ts +152 -0
- package/dist/src/utils/testRecovery/ResilientPlaywright.js +715 -0
- package/dist/src/utils/testRecovery/TestRecoveryClient.d.ts +801 -0
- package/dist/src/utils/testRecovery/TestRecoveryClient.js +1415 -0
- package/dist/src/utils/testRecovery/autoFixCode.d.ts +65 -0
- package/dist/src/utils/testRecovery/autoFixCode.js +32 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +59 -0
- package/dist/wdio.conf.d.ts +1 -0
- package/dist/wdio.conf.js +420 -0
- package/package.json +137 -0
- package/protect-loader.mjs +643 -0
- package/scripts/consumer-postinstall.ts +975 -0
- package/scripts/generate-index.ts +343 -0
- package/scripts/init-api.ts +613 -0
- package/scripts/init-banco.ts +437 -0
- package/scripts/init-frontend.ts +727 -0
- package/scripts/init-mobile.ts +558 -0
- package/scripts/init-scenarios.ts +925 -0
- package/scripts/init-ssh.ts +734 -0
- package/scripts/package-versions.ts +978 -0
- package/scripts/postinstall.ts +605 -0
- package/scripts/smart-override.ts +1675 -0
- package/scripts/sync-configs.ts +302 -0
- package/scripts/ultracite-setup.ts +370 -0
- package/src/types/globals.d.ts +48 -0
- package/tsconfig.json +29 -0
- package/types/autocore-sync-signal.d.ts +10 -0
|
@@ -0,0 +1,1206 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { StatementTracker } from '../hubdocs/StatementTracker.js';
|
|
4
|
+
import { Logger } from '../utils/Logger.js';
|
|
5
|
+
import { TestAnnotations } from './TestAnnotations.js';
|
|
6
|
+
import { TestContext } from './TestContext.js';
|
|
7
|
+
import { UnifiedHtmlGenerator } from './UnifiedHtmlGenerator.js';
|
|
8
|
+
import { HTMLTemplate } from '../utils/HTMLTemplate.js';
|
|
9
|
+
// 🔗 Import dinâmico do StatementTracker para evitar dependência circular
|
|
10
|
+
const getStatementTrackerData = async () => {
|
|
11
|
+
try {
|
|
12
|
+
return StatementTracker.getReportData();
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Gerenciador unificado de relatórios para todos os tipos de teste
|
|
20
|
+
*/
|
|
21
|
+
export class UnifiedReportManager {
|
|
22
|
+
static inicioExecucao;
|
|
23
|
+
static fimExecucao;
|
|
24
|
+
static testes = [];
|
|
25
|
+
static contextoPorTeste = new Map();
|
|
26
|
+
static logsPorTeste = new Map();
|
|
27
|
+
static metadataPorTeste = new Map();
|
|
28
|
+
static duracoesPorTeste = new Map();
|
|
29
|
+
static ctToCnMap = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* ✅ Dados globais estruturados
|
|
32
|
+
*/
|
|
33
|
+
static dadosGlobais = {
|
|
34
|
+
totalTestes: 0,
|
|
35
|
+
testesPassados: 0,
|
|
36
|
+
testesFalharam: 0,
|
|
37
|
+
testes: {},
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* ✅ NOVO: Sistema de detecção automática
|
|
41
|
+
*/
|
|
42
|
+
static autoDetectionActive = false;
|
|
43
|
+
static currentTestName = null;
|
|
44
|
+
static testStartTime = null;
|
|
45
|
+
static monitoringInterval = null;
|
|
46
|
+
/**
|
|
47
|
+
* Registra relacionamento entre CT (test.title) e CN (test.describe)
|
|
48
|
+
*/
|
|
49
|
+
static registrarCtParaCn(ctName, cnName) {
|
|
50
|
+
if (!ctName || !cnName)
|
|
51
|
+
return;
|
|
52
|
+
UnifiedReportManager.ctToCnMap.set(ctName, cnName);
|
|
53
|
+
}
|
|
54
|
+
static obterCnRegistrado(ctName) {
|
|
55
|
+
if (!ctName)
|
|
56
|
+
return undefined;
|
|
57
|
+
return UnifiedReportManager.ctToCnMap.get(ctName);
|
|
58
|
+
}
|
|
59
|
+
static limparRegistroCt(ctName) {
|
|
60
|
+
if (!ctName)
|
|
61
|
+
return;
|
|
62
|
+
UnifiedReportManager.ctToCnMap.delete(ctName);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* ❌ DESABILITADO: Auto-inicialização que causava registro duplicado
|
|
66
|
+
* O registro correto já é feito via TestAnnotations.Api/SSH/Banco/etc
|
|
67
|
+
*/
|
|
68
|
+
static autoInit() {
|
|
69
|
+
if (!UnifiedReportManager.autoDetectionActive) {
|
|
70
|
+
UnifiedReportManager.autoDetectionActive = true;
|
|
71
|
+
// 🤖 FORÇA INICIALIZAÇÃO DO STATEMENT TRACKER
|
|
72
|
+
try {
|
|
73
|
+
import('../hubdocs/StatementTracker.js')
|
|
74
|
+
.then(() => {
|
|
75
|
+
// StatementTracker carregado e auto-inicializado
|
|
76
|
+
})
|
|
77
|
+
.catch(() => {
|
|
78
|
+
// Ignorar erro se não conseguir carregar
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// Ignorar erro de importação
|
|
83
|
+
}
|
|
84
|
+
// Configurar interceptação de erros automaticamente
|
|
85
|
+
UnifiedReportManager.configurarInterceptacaoErros();
|
|
86
|
+
// ❌ REMOVIDO: Monitoramento automático que registrava CT como teste
|
|
87
|
+
// this.iniciarMonitoramentoAutomatico()
|
|
88
|
+
// this.interceptarTestContext()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* ✅ NOVO: Monitoramento automático de mudanças de teste
|
|
93
|
+
*/
|
|
94
|
+
static iniciarMonitoramentoAutomatico() {
|
|
95
|
+
UnifiedReportManager.monitoringInterval = setInterval(() => {
|
|
96
|
+
try {
|
|
97
|
+
const testInfo = TestContext.getSafeTestInfo();
|
|
98
|
+
const currentTest = testInfo?.title || null;
|
|
99
|
+
// Detectar mudança de teste
|
|
100
|
+
if (currentTest &&
|
|
101
|
+
currentTest !== UnifiedReportManager.currentTestName) {
|
|
102
|
+
// Finalizar teste anterior se existir
|
|
103
|
+
if (UnifiedReportManager.currentTestName) {
|
|
104
|
+
UnifiedReportManager.finalizarTesteAutomatico(UnifiedReportManager.currentTestName);
|
|
105
|
+
}
|
|
106
|
+
// Iniciar novo teste
|
|
107
|
+
UnifiedReportManager.iniciarTesteAutomatico(currentTest);
|
|
108
|
+
}
|
|
109
|
+
// Detectar fim de teste (quando não há mais TestInfo)
|
|
110
|
+
if (!currentTest && UnifiedReportManager.currentTestName) {
|
|
111
|
+
UnifiedReportManager.finalizarTesteAutomatico(UnifiedReportManager.currentTestName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
// Ignorar erros do monitoramento
|
|
116
|
+
}
|
|
117
|
+
}, 100); // Verificar a cada 100ms
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* ✅ NOVO: Interceptar TestContext para detectar mudanças automaticamente
|
|
121
|
+
*/
|
|
122
|
+
static interceptarTestContext() {
|
|
123
|
+
try {
|
|
124
|
+
// ✅ CORRIGIDO: Verificar se TestContext está disponível antes de interceptar
|
|
125
|
+
if (typeof TestContext === 'undefined' || !TestContext) {
|
|
126
|
+
console.debug('TestContext ainda não está disponível para interceptação');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Interceptar o método setTestInfo do TestContext
|
|
130
|
+
const originalSetTestInfo = TestContext.setTestInfo;
|
|
131
|
+
if (originalSetTestInfo && typeof originalSetTestInfo === 'function') {
|
|
132
|
+
TestContext.setTestInfo = (testInfo) => {
|
|
133
|
+
// Chamar método original
|
|
134
|
+
originalSetTestInfo.call(TestContext, testInfo);
|
|
135
|
+
// Detectar novo teste automaticamente
|
|
136
|
+
if (testInfo?.title) {
|
|
137
|
+
UnifiedReportManager.detectarNovoTeste(testInfo.title);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.debug('Erro ao interceptar TestContext:', error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* ✅ NOVO: Detectar novo teste automaticamente
|
|
148
|
+
*/
|
|
149
|
+
static detectarNovoTeste(testName) {
|
|
150
|
+
if (testName !== UnifiedReportManager.currentTestName) {
|
|
151
|
+
// Finalizar teste anterior se existir
|
|
152
|
+
if (UnifiedReportManager.currentTestName) {
|
|
153
|
+
UnifiedReportManager.finalizarTesteAutomatico(UnifiedReportManager.currentTestName);
|
|
154
|
+
}
|
|
155
|
+
// Iniciar novo teste
|
|
156
|
+
UnifiedReportManager.iniciarTesteAutomatico(testName);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* ✅ NOVO: Iniciar teste automaticamente
|
|
161
|
+
*/
|
|
162
|
+
static iniciarTesteAutomatico(testName) {
|
|
163
|
+
UnifiedReportManager.currentTestName = testName;
|
|
164
|
+
UnifiedReportManager.testStartTime = Date.now();
|
|
165
|
+
// Registrar teste automaticamente
|
|
166
|
+
UnifiedReportManager.registrarTeste(testName, 'Mixed'); // Detectar tipo depois
|
|
167
|
+
// ❌ REMOVIDO: NÃO chamar StatementTracker.setTestName() aqui!
|
|
168
|
+
// O nome correto (CN do test.describe) já foi setado em TestAnnotations.Api/SSH/Banco/etc
|
|
169
|
+
// Este testName aqui é o CT (test.title), não o CN!
|
|
170
|
+
// Iniciar execução se não iniciada
|
|
171
|
+
if (!UnifiedReportManager.inicioExecucao) {
|
|
172
|
+
UnifiedReportManager.registrarInicioExecucao();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* ✅ NOVO: Finalizar teste automaticamente
|
|
177
|
+
*/
|
|
178
|
+
static async finalizarTesteAutomatico(testName) {
|
|
179
|
+
// Detectar status baseado em logs
|
|
180
|
+
const logs = UnifiedReportManager.logsPorTeste.get(testName) || [];
|
|
181
|
+
const hasError = logs.some((log) => log.includes('❌') ||
|
|
182
|
+
log.includes('ERRO') ||
|
|
183
|
+
log.includes('Error') ||
|
|
184
|
+
log.includes('failed'));
|
|
185
|
+
const status = hasError ? 'failed' : 'passed';
|
|
186
|
+
// Marcar fim do teste
|
|
187
|
+
await UnifiedReportManager.marcarFimTeste(testName, status);
|
|
188
|
+
// Calcular duração
|
|
189
|
+
if (UnifiedReportManager.testStartTime) {
|
|
190
|
+
const duracao = Date.now() - UnifiedReportManager.testStartTime;
|
|
191
|
+
UnifiedReportManager.setTestDuration(testName, duracao);
|
|
192
|
+
}
|
|
193
|
+
// Reset
|
|
194
|
+
UnifiedReportManager.currentTestName = null;
|
|
195
|
+
UnifiedReportManager.testStartTime = null;
|
|
196
|
+
}
|
|
197
|
+
static setTestContext(testeName, contexto) {
|
|
198
|
+
UnifiedReportManager.contextoPorTeste.set(testeName, contexto);
|
|
199
|
+
}
|
|
200
|
+
static iniciarTeste(testeName, contexto) {
|
|
201
|
+
Logger.info(`🎯 Iniciando teste: ${testeName}`);
|
|
202
|
+
// ✅ IMPORTANTE: Registrar o teste no sistema
|
|
203
|
+
UnifiedReportManager.registrarTeste(testeName, contexto || 'Mixed');
|
|
204
|
+
// Definir teste atual
|
|
205
|
+
UnifiedReportManager.currentTestName = testeName;
|
|
206
|
+
// ✅ CRÍTICO: Informar StatementTracker sobre o nome do teste
|
|
207
|
+
try {
|
|
208
|
+
StatementTracker.setTestName(testeName);
|
|
209
|
+
Logger.success(`✅ Nome do teste "${testeName}" registrado no StatementTracker`);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
Logger.warning(`⚠️ Erro ao registrar nome no StatementTracker: ${error}`);
|
|
213
|
+
}
|
|
214
|
+
// Definir contexto se fornecido
|
|
215
|
+
if (contexto) {
|
|
216
|
+
UnifiedReportManager.contextoPorTeste.set(testeName, contexto);
|
|
217
|
+
}
|
|
218
|
+
// Inicializar estruturas de dados para o teste
|
|
219
|
+
if (!UnifiedReportManager.logsPorTeste.has(testeName)) {
|
|
220
|
+
UnifiedReportManager.logsPorTeste.set(testeName, []);
|
|
221
|
+
}
|
|
222
|
+
// Adicionar log inicial
|
|
223
|
+
UnifiedReportManager.adicionarLog(testeName, `🎯 INICIANDO: ${testeName}`);
|
|
224
|
+
// Marcar início do tempo
|
|
225
|
+
UnifiedReportManager.duracoesPorTeste.set(testeName, Date.now());
|
|
226
|
+
Logger.success(`✅ Teste ${testeName} inicializado no contexto ${contexto || 'Mixed'}`);
|
|
227
|
+
}
|
|
228
|
+
static registrarInicioExecucao() {
|
|
229
|
+
if (!UnifiedReportManager.inicioExecucao) {
|
|
230
|
+
UnifiedReportManager.inicioExecucao = new Date();
|
|
231
|
+
Logger.info(`⏱️ Início da execução unificada: ${UnifiedReportManager.inicioExecucao.toLocaleTimeString()}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Registra informações do ambiente CI (Azure Pipelines, GitHub Actions, etc)
|
|
236
|
+
* e as anexa como metadados globais para o relatório.
|
|
237
|
+
*/
|
|
238
|
+
static registrarCIInfo() {
|
|
239
|
+
try {
|
|
240
|
+
const metadata = {};
|
|
241
|
+
// Azure Pipelines
|
|
242
|
+
if (process.env.AGENT_NAME || process.env.BUILD_REASON) {
|
|
243
|
+
metadata.ciProvider = 'azure-pipelines';
|
|
244
|
+
metadata.agentName = process.env.AGENT_NAME || null;
|
|
245
|
+
metadata.buildReason = process.env.BUILD_REASON || null; // Ex: 'Schedule', 'Manual'
|
|
246
|
+
metadata.requestedFor = process.env.BUILD_REQUESTEDFOR || process.env.BUILD_REQUESTEDFORID || null;
|
|
247
|
+
metadata.buildId = process.env.BUILD_BUILDID || null;
|
|
248
|
+
metadata.project = process.env.SYSTEM_TEAMPROJECT || null;
|
|
249
|
+
metadata.collectionUri = process.env.SYSTEM_COLLECTIONURI || null;
|
|
250
|
+
// Tentativa de descobrir email do usuário que requisitou
|
|
251
|
+
metadata.requestedForEmail = process.env.BUILD_REQUESTEDFOR || process.env.BUILD_REQUESTEDFOREMAIL || null;
|
|
252
|
+
metadata.isScheduled = (process.env.BUILD_REASON || '').toLowerCase() === 'schedule';
|
|
253
|
+
}
|
|
254
|
+
// GitHub Actions
|
|
255
|
+
if (process.env.GITHUB_ACTIONS) {
|
|
256
|
+
metadata.ciProvider = 'github-actions';
|
|
257
|
+
metadata.actor = process.env.GITHUB_ACTOR || null;
|
|
258
|
+
metadata.workflow = process.env.GITHUB_WORKFLOW || null;
|
|
259
|
+
metadata.runId = process.env.GITHUB_RUN_ID || null;
|
|
260
|
+
metadata.eventName = process.env.GITHUB_EVENT_NAME || null;
|
|
261
|
+
// GitHub schedule detection: eventName == 'schedule'
|
|
262
|
+
metadata.isScheduled = (process.env.GITHUB_EVENT_NAME || '').toLowerCase() === 'schedule';
|
|
263
|
+
}
|
|
264
|
+
// Fallbacks: tentar detectar e-mail do usuário a partir de variáveis comuns
|
|
265
|
+
if (!metadata.requestedForEmail) {
|
|
266
|
+
metadata.requestedForEmail = process.env.BUILD_REQUESTEDFOREMAIL || process.env.BUILD_REQUESTEDFOR || process.env.USER_EMAIL || null;
|
|
267
|
+
}
|
|
268
|
+
// Armazenar em dadosGlobais para anexar ao relatório final
|
|
269
|
+
;
|
|
270
|
+
UnifiedReportManager.dadosGlobais.ciMetadata = metadata;
|
|
271
|
+
Logger.info(`🔗 CI metadata registrada: ${JSON.stringify(metadata)}`);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
Logger.warning(`⚠️ Não foi possível registrar CI info: ${error}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
static registrarFimExecucao() {
|
|
278
|
+
UnifiedReportManager.fimExecucao = new Date();
|
|
279
|
+
if (UnifiedReportManager.inicioExecucao) {
|
|
280
|
+
const duration = (UnifiedReportManager.fimExecucao.getTime() -
|
|
281
|
+
UnifiedReportManager.inicioExecucao.getTime()) /
|
|
282
|
+
1000;
|
|
283
|
+
Logger.info(`⏱️ Execução unificada concluída em ${duration.toFixed(2)}s`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* ✅ NOVO: Registra explicitamente um teste no sistema
|
|
288
|
+
*/
|
|
289
|
+
static registrarTeste(testName, contextType) {
|
|
290
|
+
if (!testName) {
|
|
291
|
+
Logger.warning('⚠️ Nome do teste vazio, ignorando registrarTeste');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// ✅ CRÍTICO: Sempre criar entrada para o teste
|
|
295
|
+
UnifiedReportManager.dadosGlobais.testes[testName] = {
|
|
296
|
+
nome: testName,
|
|
297
|
+
tipo: contextType,
|
|
298
|
+
inicio: new Date(),
|
|
299
|
+
fim: null,
|
|
300
|
+
duracao: 0,
|
|
301
|
+
status: 'running',
|
|
302
|
+
logs: [],
|
|
303
|
+
screenshots: [],
|
|
304
|
+
dados: {},
|
|
305
|
+
};
|
|
306
|
+
// ✅ IMPORTANTE: Incrementar contador
|
|
307
|
+
UnifiedReportManager.dadosGlobais.totalTestes++;
|
|
308
|
+
// ✅ NOVO: Também criar entrada básica no array de testes para relatórios
|
|
309
|
+
const testeExistente = UnifiedReportManager.testes.find((t) => t.nome === testName);
|
|
310
|
+
if (!testeExistente) {
|
|
311
|
+
const novoTeste = {
|
|
312
|
+
nome: testName,
|
|
313
|
+
resultado: 'FAIL', // Assumir FAIL inicialmente, será atualizado
|
|
314
|
+
tipo: contextType,
|
|
315
|
+
duracao: 0,
|
|
316
|
+
logs: [],
|
|
317
|
+
timestamp: new Date(),
|
|
318
|
+
metadata: {},
|
|
319
|
+
};
|
|
320
|
+
UnifiedReportManager.testes.push(novoTeste);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 🆕 HELPER: Obter o nome correto do CN (test.describe) do TestInfo
|
|
325
|
+
*/
|
|
326
|
+
static getCNNameFromTestInfo() {
|
|
327
|
+
const testInfo = TestContext.getSafeTestInfo();
|
|
328
|
+
// titlePath[0] = filename, titlePath[1] = CN (test.describe), titlePath[2] = CT (test)
|
|
329
|
+
return testInfo?.titlePath?.[1] || null;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* ✅ NOVO: Marca explicitamente o fim de um teste
|
|
333
|
+
*/
|
|
334
|
+
static async marcarFimTeste(testName, status, options = {}) {
|
|
335
|
+
const mappedCtName = options.ctName || testName;
|
|
336
|
+
const cnName = options.cnName ||
|
|
337
|
+
UnifiedReportManager.obterCnRegistrado(mappedCtName) ||
|
|
338
|
+
UnifiedReportManager.getCNNameFromTestInfo() ||
|
|
339
|
+
testName;
|
|
340
|
+
if (status === 'passed') {
|
|
341
|
+
await UnifiedReportManager.corrigirStatusCTsQuandoTestePassou(cnName, mappedCtName);
|
|
342
|
+
}
|
|
343
|
+
else if (status === 'failed') {
|
|
344
|
+
await UnifiedReportManager.corrigirStatusCTsQuandoTesteFalha(cnName, mappedCtName, options.errorMessage);
|
|
345
|
+
}
|
|
346
|
+
// Atualizar dadosGlobais
|
|
347
|
+
const testeGlobal = UnifiedReportManager.dadosGlobais.testes[testName];
|
|
348
|
+
if (testeGlobal) {
|
|
349
|
+
testeGlobal.fim = new Date();
|
|
350
|
+
testeGlobal.status = status;
|
|
351
|
+
// Calcular duração
|
|
352
|
+
if (testeGlobal.inicio) {
|
|
353
|
+
testeGlobal.duracao =
|
|
354
|
+
(testeGlobal.fim.getTime() - testeGlobal.inicio.getTime()) / 1000;
|
|
355
|
+
// Atualizar também no Map de durações
|
|
356
|
+
UnifiedReportManager.duracoesPorTeste.set(testName, testeGlobal.duracao * 1000);
|
|
357
|
+
}
|
|
358
|
+
if (status === 'passed') {
|
|
359
|
+
UnifiedReportManager.dadosGlobais.testesPassados++;
|
|
360
|
+
}
|
|
361
|
+
else if (status === 'failed') {
|
|
362
|
+
UnifiedReportManager.dadosGlobais.testesFalharam++;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Atualizar também o array de testes
|
|
366
|
+
const testeIndex = UnifiedReportManager.testes.findIndex((t) => t.nome === testName);
|
|
367
|
+
if (testeIndex >= 0) {
|
|
368
|
+
UnifiedReportManager.testes[testeIndex].resultado =
|
|
369
|
+
status === 'passed' ? 'PASS' : 'FAIL';
|
|
370
|
+
// Atualizar logs se existirem
|
|
371
|
+
const logs = UnifiedReportManager.logsPorTeste.get(testName) || [];
|
|
372
|
+
UnifiedReportManager.testes[testeIndex].logs = logs;
|
|
373
|
+
// Atualizar duração corretamente
|
|
374
|
+
UnifiedReportManager.testes[testeIndex].duracao =
|
|
375
|
+
testeGlobal?.duracao ?? 0;
|
|
376
|
+
}
|
|
377
|
+
UnifiedReportManager.limparRegistroCt(mappedCtName);
|
|
378
|
+
// Log de finalização
|
|
379
|
+
Logger.info(`🏁 Finalizado: ${testName} [${status.toUpperCase()}]`);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* ✅ NOVO: Corrige status dos CTs quando teste PASSA
|
|
383
|
+
* Marca todos os CTs "running" do teste como "passed"
|
|
384
|
+
*/
|
|
385
|
+
static async corrigirStatusCTsQuandoTestePassou(testName, ctName) {
|
|
386
|
+
try {
|
|
387
|
+
StatementTracker.finalizeRunningCTsAsPassed(testName, ctName);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
Logger.warning(`⚠️ Erro ao corrigir status dos CTs para teste ${testName}: ${error}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* ✅ NOVO: Corrige status dos CTs quando teste FALHA
|
|
395
|
+
* Marca todos os CTs "running" do teste como "failed"
|
|
396
|
+
*/
|
|
397
|
+
static async corrigirStatusCTsQuandoTesteFalha(testName, ctName, reason) {
|
|
398
|
+
try {
|
|
399
|
+
Logger.info(`🔧 Finalizando CTs "running" como "failed" para teste: ${testName}${ctName ? ` (CT: ${ctName})` : ''}`);
|
|
400
|
+
// Importar StatementTracker dinamicamente (ESModules)
|
|
401
|
+
StatementTracker.finalizeRunningCTsAsFailed(testName, reason || 'Teste falhou - finalizando CTs pendentes', ctName);
|
|
402
|
+
Logger.success(`✅ Status dos CTs corrigido para teste ${testName}`);
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
Logger.warning(`⚠️ Erro ao corrigir status dos CTs para teste ${testName}: ${error}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
static async coletarDadosDoTeste(testeName) {
|
|
409
|
+
const testInfo = TestContext.getSafeTestInfo();
|
|
410
|
+
// ✅ CORREÇÃO CRÍTICA: Buscar pelo CN (test.describe = titlePath[1]), não pelo CT (test.title)
|
|
411
|
+
// titlePath[0] = filename, titlePath[1] = CN (test.describe), titlePath[2] = CT (test)
|
|
412
|
+
const nomeDoCN = testeName || testInfo?.titlePath?.[1] || testInfo?.title;
|
|
413
|
+
if (!nomeDoCN)
|
|
414
|
+
return { cts: [], logs: [], screenshots: [] };
|
|
415
|
+
if (testInfo?.titlePath) {
|
|
416
|
+
Logger.info(` 📋 titlePath completo: ${testInfo.titlePath.join(' > ')}`);
|
|
417
|
+
}
|
|
418
|
+
const contexto = UnifiedReportManager.contextoPorTeste.get(nomeDoCN) || 'Mixed';
|
|
419
|
+
// 🔧 CORREÇÃO COMPLETA: Captura de logs de TODAS as fontes
|
|
420
|
+
let logs = [];
|
|
421
|
+
// ✅ FONTE 1: Logs do Map logsPorTeste
|
|
422
|
+
const logsDoMap = UnifiedReportManager.logsPorTeste.get(nomeDoCN) ?? [];
|
|
423
|
+
if (logsDoMap.length > 0) {
|
|
424
|
+
Logger.info(`📋 Encontrados ${logsDoMap.length} logs no Map`);
|
|
425
|
+
logs.push(...logsDoMap);
|
|
426
|
+
}
|
|
427
|
+
// ✅ FONTE 2: Logs dos dadosGlobais
|
|
428
|
+
const testeGlobal = UnifiedReportManager.dadosGlobais.testes[nomeDoCN];
|
|
429
|
+
if (testeGlobal?.logs && testeGlobal.logs.length > 0) {
|
|
430
|
+
Logger.info(`📋 Encontrados ${testeGlobal.logs.length} logs nos dadosGlobais`);
|
|
431
|
+
logs.push(...testeGlobal.logs);
|
|
432
|
+
}
|
|
433
|
+
// ✅ FONTE 3: Logs do buffer global do console
|
|
434
|
+
if (globalThis.consoleBuffer) {
|
|
435
|
+
const bufferLogs = globalThis.consoleBuffer
|
|
436
|
+
.filter((log) => log.testName === nomeDoCN ||
|
|
437
|
+
log.testName?.includes(nomeDoCN) ||
|
|
438
|
+
nomeDoCN.includes(log.testName || ''))
|
|
439
|
+
.map((log) => log.message);
|
|
440
|
+
if (bufferLogs.length > 0) {
|
|
441
|
+
Logger.info(`📋 Encontrados ${bufferLogs.length} logs no buffer do console`);
|
|
442
|
+
logs.push(...bufferLogs);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// ✅ FONTE 4: Logs do TestAnnotations (NOVO)
|
|
446
|
+
try {
|
|
447
|
+
const logsCapturados = TestAnnotations.getLogsCapturados();
|
|
448
|
+
if (logsCapturados && logsCapturados.length > 0) {
|
|
449
|
+
Logger.info(`📋 Encontrados ${logsCapturados.length} logs do TestAnnotations`);
|
|
450
|
+
logs.push(...logsCapturados);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
Logger.warning(`⚠️ Erro ao capturar logs do TestAnnotations: ${error}`);
|
|
455
|
+
}
|
|
456
|
+
// ✅ FONTE 5: Buscar logs por padrões similares de nome de teste
|
|
457
|
+
const nomeString = String(nomeDoCN || 'Unknown Test');
|
|
458
|
+
const nomesVariacoes = [
|
|
459
|
+
nomeString,
|
|
460
|
+
nomeString.replace(/[^\w\d]/g, ''),
|
|
461
|
+
nomeString.replace(/[^\w\d]/g, '_'),
|
|
462
|
+
nomeString.replace(/\s+/g, '_'),
|
|
463
|
+
nomeString.replace(/\s+/g, ''),
|
|
464
|
+
];
|
|
465
|
+
for (const nomeVariacao of nomesVariacoes) {
|
|
466
|
+
const logsVariacao = UnifiedReportManager.logsPorTeste.get(nomeVariacao);
|
|
467
|
+
if (logsVariacao && logsVariacao.length > 0) {
|
|
468
|
+
Logger.info(`📋 Encontrados ${logsVariacao.length} logs para variação: ${nomeVariacao}`);
|
|
469
|
+
logs.push(...logsVariacao);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// 🔧 Remover duplicatas preservando ordem
|
|
473
|
+
logs = [...new Set(logs)];
|
|
474
|
+
// 🆕 Se ainda não temos logs, criar logs informativos básicos
|
|
475
|
+
if (logs.length === 0) {
|
|
476
|
+
logs = [
|
|
477
|
+
`🎯 Iniciando execução do teste: ${nomeDoCN}`,
|
|
478
|
+
`📋 Contexto detectado: ${contexto}`,
|
|
479
|
+
`🕐 Timestamp: ${new Date().toLocaleString('pt-BR')}`,
|
|
480
|
+
'ℹ️ ATENÇÃO: Logs reais não foram capturados automaticamente',
|
|
481
|
+
'💡 Para capturar logs, use: Logger.info(), console.log(), ou UnifiedReportManager.adicionarLog()',
|
|
482
|
+
`🔧 Debug: Total de variações testadas: ${nomesVariacoes.length}`,
|
|
483
|
+
`📊 Debug: Buffer do console disponível: ${globalThis.consoleBuffer ? 'SIM' : 'NÃO'}`,
|
|
484
|
+
`🎯 Debug: Nome do teste atual: ${UnifiedReportManager.currentTestName || 'NENHUM'}`,
|
|
485
|
+
];
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
Logger.success(`✅ Total de ${logs.length} logs coletados de todas as fontes`);
|
|
489
|
+
// 🆕 Adicionar logs informativos no início se não existirem
|
|
490
|
+
const logsComInfo = [
|
|
491
|
+
`🎯 Teste: ${nomeDoCN} (${contexto})`,
|
|
492
|
+
`🕐 Início: ${testeGlobal?.inicio ? new Date(testeGlobal.inicio).toLocaleString('pt-BR') : 'N/A'}`,
|
|
493
|
+
`📊 Total de logs capturados: ${logs.length}`,
|
|
494
|
+
'------- LOGS DE EXECUÇÃO -------',
|
|
495
|
+
...logs,
|
|
496
|
+
];
|
|
497
|
+
logs = logsComInfo;
|
|
498
|
+
}
|
|
499
|
+
const metadata = UnifiedReportManager.metadataPorTeste.get(nomeDoCN) || {};
|
|
500
|
+
// Buscar duração preferencialmente dos dadosGlobais
|
|
501
|
+
const duracao = testeGlobal?.duracao
|
|
502
|
+
? testeGlobal.duracao
|
|
503
|
+
: (UnifiedReportManager.duracoesPorTeste.get(nomeDoCN) || 0) / 1000;
|
|
504
|
+
// Determina se há erros nos logs
|
|
505
|
+
const temErroLogs = logs.some((log) => log.includes('❌') ||
|
|
506
|
+
log.includes('FAILED') ||
|
|
507
|
+
log.includes('erro') ||
|
|
508
|
+
log.includes('falhou'));
|
|
509
|
+
// ✅ NOVO: Se o teste tem erro, corrigir CTs "running" antes de coletar
|
|
510
|
+
if (temErroLogs) {
|
|
511
|
+
Logger.info(`🔧 Teste com erro detectado nos logs, corrigindo CTs em execução: ${nomeDoCN}`);
|
|
512
|
+
await UnifiedReportManager.corrigirStatusCTsQuandoTesteFalha(nomeDoCN);
|
|
513
|
+
// Aguardar um pouco para permitir que as correções sejam aplicadas
|
|
514
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
515
|
+
}
|
|
516
|
+
// 🆕 CRÍTICO: Aguardar que StatementTracker tenha dados prontos
|
|
517
|
+
try {
|
|
518
|
+
await StatementTracker.waitForDataReady();
|
|
519
|
+
Logger.success('✅ StatementTracker pronto para coleta de dados');
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
Logger.warning(`⚠️ Erro ao aguardar dados do StatementTracker: ${error}`);
|
|
523
|
+
}
|
|
524
|
+
// 🔧 CORREÇÃO CRÍTICA: Busca direta e simples
|
|
525
|
+
const allExecutions = StatementTracker.getExecutions();
|
|
526
|
+
// 🆕 BUSCA SIMPLIFICADA: Pegar CTs do teste específico
|
|
527
|
+
let cts = [];
|
|
528
|
+
let totalCTs = 0;
|
|
529
|
+
let passedCTs = 0;
|
|
530
|
+
let failedCTs = 0;
|
|
531
|
+
let skippedCTs = 0;
|
|
532
|
+
// ✅ CORREÇÃO: Buscar pelo nome do CN (test.describe)
|
|
533
|
+
let testExecution = allExecutions.get(nomeDoCN);
|
|
534
|
+
// 🔍 DEBUG CRÍTICO: Ver todos os nomes registrados
|
|
535
|
+
for (const [key, value] of allExecutions.entries()) {
|
|
536
|
+
Logger.info(` 📋 "${key}" - ${value.totalCTs} CTs`);
|
|
537
|
+
}
|
|
538
|
+
// 🆘 FALLBACK: Se não encontrou exato, tentar busca parcial
|
|
539
|
+
if (!testExecution) {
|
|
540
|
+
// Tentar encontrar por semelhança
|
|
541
|
+
for (const [key, value] of allExecutions.entries()) {
|
|
542
|
+
if (key.includes(nomeDoCN) || nomeDoCN.includes(key)) {
|
|
543
|
+
Logger.info(`🎯 [UnifiedReport] Encontrado por semelhança: "${key}" para "${nomeDoCN}"`);
|
|
544
|
+
testExecution = value;
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
// Se ainda não encontrou, pegar qualquer um que tenha CTs
|
|
549
|
+
if (!testExecution) {
|
|
550
|
+
for (const [key, value] of allExecutions.entries()) {
|
|
551
|
+
if (value.totalCTs > 0) {
|
|
552
|
+
Logger.info(`🆘 [UnifiedReport] Usando primeiro teste com CTs: "${key}"`);
|
|
553
|
+
testExecution = value;
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (testExecution && testExecution.cts && testExecution.cts.length > 0) {
|
|
560
|
+
Logger.info(`🎯 Encontrado dados com ${testExecution.cts.length} CTs`); // ✅ CORREÇÃO: Iterar sobre os CTs do teste específico
|
|
561
|
+
cts = testExecution.cts.map((ct, index) => {
|
|
562
|
+
const rawName = ct.ctName || ct.name || '';
|
|
563
|
+
const derivedClass = ct.className ||
|
|
564
|
+
rawName.split('.')[0] ||
|
|
565
|
+
rawName.split('→')[0]?.trim() ||
|
|
566
|
+
'Unknown';
|
|
567
|
+
const derivedMethod = ct.methodName ||
|
|
568
|
+
rawName.split('.')[1] ||
|
|
569
|
+
rawName.split('→')[1]?.trim() ||
|
|
570
|
+
rawName ||
|
|
571
|
+
'method';
|
|
572
|
+
const durationMs = typeof ct.duration === 'number'
|
|
573
|
+
? ct.duration
|
|
574
|
+
: ct.endTime && ct.startTime
|
|
575
|
+
? ct.endTime - ct.startTime
|
|
576
|
+
: 0;
|
|
577
|
+
return {
|
|
578
|
+
ctId: ct.ctId ||
|
|
579
|
+
ct.ctIdentifier ||
|
|
580
|
+
`CT${(index + 1).toString().padStart(3, '0')}`,
|
|
581
|
+
ctName: rawName || `CT ${index + 1}`,
|
|
582
|
+
ctOrder: ct.ctOrder ?? index + 1,
|
|
583
|
+
status: (ct.status || 'running'),
|
|
584
|
+
duration: durationMs,
|
|
585
|
+
timestamp: ct.startTime ? new Date(ct.startTime) : new Date(),
|
|
586
|
+
startTime: ct.startTime ?? null,
|
|
587
|
+
endTime: ct.endTime ?? (ct.startTime ? ct.startTime + durationMs : null),
|
|
588
|
+
error: ct.error,
|
|
589
|
+
className: derivedClass,
|
|
590
|
+
methodName: derivedMethod,
|
|
591
|
+
systemName: ct.systemName || testExecution.systemName || 'Unknown',
|
|
592
|
+
statements: Array.isArray(ct.statements)
|
|
593
|
+
? ct.statements.map((stmt) => ({ ...stmt }))
|
|
594
|
+
: [],
|
|
595
|
+
executedActions: Array.isArray(ct.executedActions)
|
|
596
|
+
? ct.executedActions.map((action) => ({ ...action }))
|
|
597
|
+
: [],
|
|
598
|
+
logs: Array.isArray(ct.logs) ? [...ct.logs] : [],
|
|
599
|
+
};
|
|
600
|
+
});
|
|
601
|
+
// ✅ CORREÇÃO CRÍTICA: Sempre contar TODOS os CTs do array mapeado
|
|
602
|
+
// Não confiar apenas em testExecution.totalCTs pois pode estar desatualizado
|
|
603
|
+
// 🛡️ CRÍTICO: CTs "running" devem ser contados como "failed"
|
|
604
|
+
totalCTs = cts.length;
|
|
605
|
+
passedCTs = cts.filter((ct) => ct.status === 'passed').length;
|
|
606
|
+
failedCTs = cts.filter((ct) => ct.status === 'failed' || ct.status === 'running').length;
|
|
607
|
+
skippedCTs = cts.filter((ct) => ct.status === 'skipped').length;
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
Logger.info(`⚠️ Nenhum CT encontrado para CN "${nomeDoCN}"`);
|
|
611
|
+
Logger.info(`📋 CNs disponíveis no StatementTracker: ${Array.from(allExecutions.keys()).join(', ')}`);
|
|
612
|
+
// 🔍 DEBUG: Verificar total de CNs e detalhes
|
|
613
|
+
for (const [testName, testData] of allExecutions.entries()) {
|
|
614
|
+
Logger.info(` 📋 Teste ${testName}: ${testData.totalCTs} CTs`);
|
|
615
|
+
Logger.info(` ⚠️ Nenhum CT encontrado para ${testName}`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// 🆕 CORREÇÃO CRÍTICA: Determinar resultado considerando tanto logs quanto CTs falhados
|
|
619
|
+
// 🛡️ IMPORTANTE: Se tem CT "failed" OU "running", o CN inteiro falhou
|
|
620
|
+
const temCTsFalhados = failedCTs > 0; // Já inclui running porque failedCTs conta running
|
|
621
|
+
const testeFalhou = temErroLogs || temCTsFalhados;
|
|
622
|
+
const resultado = {
|
|
623
|
+
nome: nomeDoCN,
|
|
624
|
+
resultado: testeFalhou ? 'FAIL' : 'PASS',
|
|
625
|
+
tipo: contexto,
|
|
626
|
+
duracao,
|
|
627
|
+
logs, // sempre array
|
|
628
|
+
timestamp: new Date(),
|
|
629
|
+
metadata,
|
|
630
|
+
// 🆕 Dados dos CTs
|
|
631
|
+
cts,
|
|
632
|
+
totalCTs,
|
|
633
|
+
passedCTs,
|
|
634
|
+
failedCTs,
|
|
635
|
+
skippedCTs,
|
|
636
|
+
};
|
|
637
|
+
// Remove teste existente e adiciona o atualizado
|
|
638
|
+
UnifiedReportManager.testes = UnifiedReportManager.testes.filter((t) => t.nome !== nomeDoCN);
|
|
639
|
+
UnifiedReportManager.testes.push(resultado);
|
|
640
|
+
// 🆕 Retornar os dados coletados
|
|
641
|
+
return {
|
|
642
|
+
cts,
|
|
643
|
+
logs,
|
|
644
|
+
screenshots: [], // TODO: implementar screenshots
|
|
645
|
+
totalCTs,
|
|
646
|
+
passedCTs,
|
|
647
|
+
failedCTs,
|
|
648
|
+
skippedCTs,
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
static adicionarLog(testeName, message) {
|
|
652
|
+
// 🔧 PROTEÇÃO CRÍTICA ANTI-LOOP: Evitar qualquer recursão
|
|
653
|
+
if (message.includes('[UNIFIED]') ||
|
|
654
|
+
message.includes('[LOG]') ||
|
|
655
|
+
message.includes('📝 Adicionando log para') ||
|
|
656
|
+
message.includes('AutoCore: Sistema') ||
|
|
657
|
+
message.includes('interceptação') ||
|
|
658
|
+
message.includes('interceptar') ||
|
|
659
|
+
UnifiedReportManager._addingLog) {
|
|
660
|
+
return; // Evitar re-processar logs já processados
|
|
661
|
+
}
|
|
662
|
+
// 🔧 MARCAR que estamos adicionando log para evitar recursão
|
|
663
|
+
;
|
|
664
|
+
UnifiedReportManager._addingLog = true;
|
|
665
|
+
try {
|
|
666
|
+
// 🔧 CRÍTICO: NÃO usar console.log aqui - usar apenas estruturas internas
|
|
667
|
+
if (!UnifiedReportManager.logsPorTeste.has(testeName)) {
|
|
668
|
+
UnifiedReportManager.logsPorTeste.set(testeName, []);
|
|
669
|
+
}
|
|
670
|
+
UnifiedReportManager.logsPorTeste.get(testeName).push(message);
|
|
671
|
+
// ✅ NOVO: Adicionar log aos dadosGlobais também
|
|
672
|
+
if (UnifiedReportManager.dadosGlobais.testes[testeName]) {
|
|
673
|
+
UnifiedReportManager.dadosGlobais.testes[testeName].logs.push(message);
|
|
674
|
+
}
|
|
675
|
+
// ✅ NOVO: Adicionar também ao buffer global se não existir
|
|
676
|
+
if (globalThis.consoleBuffer) {
|
|
677
|
+
;
|
|
678
|
+
globalThis.consoleBuffer.push({
|
|
679
|
+
testName: testeName,
|
|
680
|
+
message,
|
|
681
|
+
timestamp: new Date().toISOString(),
|
|
682
|
+
type: 'auto-added',
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
catch (error) {
|
|
687
|
+
// Evitar qualquer erro que possa causar loop
|
|
688
|
+
}
|
|
689
|
+
finally {
|
|
690
|
+
// 🔧 SEMPRE limpar flag
|
|
691
|
+
;
|
|
692
|
+
UnifiedReportManager._addingLog = false;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
static setTestMetadata(testeName, metadata) {
|
|
696
|
+
UnifiedReportManager.metadataPorTeste.set(testeName, metadata);
|
|
697
|
+
}
|
|
698
|
+
static setTestDuration(testeName, duracao) {
|
|
699
|
+
UnifiedReportManager.duracoesPorTeste.set(testeName, duracao);
|
|
700
|
+
// ✅ NOVO: Atualizar também nos dadosGlobais
|
|
701
|
+
if (UnifiedReportManager.dadosGlobais.testes[testeName]) {
|
|
702
|
+
UnifiedReportManager.dadosGlobais.testes[testeName].duracao =
|
|
703
|
+
duracao / 1000; // Converter para segundos
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* ✅ NOVO: Obter logs de um teste específico
|
|
708
|
+
*/
|
|
709
|
+
static getTestLogs(testName) {
|
|
710
|
+
return UnifiedReportManager.logsPorTeste.get(testName) || [];
|
|
711
|
+
}
|
|
712
|
+
static async anexarRelatorioIndividual() {
|
|
713
|
+
const testInfo = TestContext.getSafeTestInfo();
|
|
714
|
+
if (!testInfo)
|
|
715
|
+
return;
|
|
716
|
+
const testeName = testInfo.title;
|
|
717
|
+
const testeAtual = UnifiedReportManager.testes.find((t) => t.nome === testeName);
|
|
718
|
+
if (!testeAtual) {
|
|
719
|
+
Logger.warning(`Teste ${testeName} não encontrado para relatório individual`);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
try {
|
|
723
|
+
const htmlBuffer = await UnifiedHtmlGenerator.generate([testeAtual], UnifiedReportManager.inicioExecucao || new Date(), UnifiedReportManager.fimExecucao || new Date(), true, testeName);
|
|
724
|
+
// Gerar nome de arquivo baseado no nome do teste
|
|
725
|
+
// Exemplo: CT003_Consultar_Cobertura.html
|
|
726
|
+
const safeTestName = testeName
|
|
727
|
+
.replace(/[^\w\d]+/g, '_')
|
|
728
|
+
.replace(/^_+|_+$/g, '');
|
|
729
|
+
const reportDir = path.join(process.cwd(), 'playwright-report');
|
|
730
|
+
if (!fs.existsSync(reportDir)) {
|
|
731
|
+
fs.mkdirSync(reportDir, { recursive: true });
|
|
732
|
+
}
|
|
733
|
+
const reportPath = path.join(reportDir, `${safeTestName}.html`);
|
|
734
|
+
fs.writeFileSync(reportPath, htmlBuffer);
|
|
735
|
+
// Anexar ao contexto do Playwright (útil para CI e UI)
|
|
736
|
+
await testInfo.attach(`${safeTestName}.html`, {
|
|
737
|
+
body: htmlBuffer,
|
|
738
|
+
contentType: 'text/html',
|
|
739
|
+
});
|
|
740
|
+
Logger.success(`📄 Relatório individual salvo e anexado: ${reportPath}`);
|
|
741
|
+
}
|
|
742
|
+
catch (error) {
|
|
743
|
+
Logger.error(`Erro ao gerar relatório individual para ${testeName}`, error);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* ✅ CORRIGIDO: Anexa relatório geral unificado
|
|
748
|
+
*/
|
|
749
|
+
static async anexarRelatorioGeral() {
|
|
750
|
+
try {
|
|
751
|
+
const testesRegistrados = Object.keys(UnifiedReportManager.dadosGlobais.testes);
|
|
752
|
+
Logger.info(`📊 Verificando testes registrados: ${testesRegistrados.length}`);
|
|
753
|
+
if (testesRegistrados.length === 0) {
|
|
754
|
+
Logger.info('⚠️ Nenhum teste registrado para relatório geral');
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
// ✅ Gerar relatório mesmo com testes que falharam
|
|
758
|
+
Logger.info(`📋 Gerando relatório para ${testesRegistrados.length} teste(s)...`);
|
|
759
|
+
// 🆕 CRÍTICO: Buscar CNs reais do StatementTracker ao invés dos nomes dos testes
|
|
760
|
+
Logger.info('📊 Coletando dados dos CTs para todos os CNs...');
|
|
761
|
+
const allExecutions = StatementTracker.getExecutions();
|
|
762
|
+
const nomesDosCNs = Array.from(allExecutions.keys());
|
|
763
|
+
Logger.info(`📊 CNs detectados no StatementTracker: ${nomesDosCNs.join(', ')}`);
|
|
764
|
+
Logger.info(`📊 Testes registrados no UnifiedReportManager: ${testesRegistrados.join(', ')}`);
|
|
765
|
+
// 🔧 CORREÇÃO: Iterar sobre os CNs do StatementTracker, não sobre testesRegistrados
|
|
766
|
+
for (const nomeDoCN of nomesDosCNs) {
|
|
767
|
+
try {
|
|
768
|
+
await UnifiedReportManager.coletarDadosDoTeste(nomeDoCN);
|
|
769
|
+
}
|
|
770
|
+
catch (error) {
|
|
771
|
+
Logger.warning(`⚠️ Erro ao coletar dados do CN ${nomeDoCN}: ${error}`);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
UnifiedReportManager.testes.forEach((teste, index) => {
|
|
775
|
+
if (teste.cts && teste.cts.length > 0) {
|
|
776
|
+
teste.cts.forEach((ct, ctIndex) => {
|
|
777
|
+
Logger.info(` CT${ctIndex + 1}: ${ct.ctName} (${ct.status})`);
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
Logger.info(` ⚠️ Nenhum CT encontrado para ${teste.nome}`);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
// ✅ NOVO: Gerar HTML do relatório geral
|
|
785
|
+
try {
|
|
786
|
+
const htmlBuffer = await UnifiedHtmlGenerator.generate(UnifiedReportManager.testes, UnifiedReportManager.inicioExecucao || new Date(), UnifiedReportManager.fimExecucao || new Date(), false, 'Relatório Geral');
|
|
787
|
+
// ✅ Salvar arquivo HTML
|
|
788
|
+
const reportDir = path.join(process.cwd(), 'playwright-report');
|
|
789
|
+
if (!fs.existsSync(reportDir)) {
|
|
790
|
+
fs.mkdirSync(reportDir, { recursive: true });
|
|
791
|
+
}
|
|
792
|
+
const reportPath = path.join(reportDir, 'relatorio-geral-unificado.html');
|
|
793
|
+
fs.writeFileSync(reportPath, htmlBuffer);
|
|
794
|
+
Logger.info(`📁 Relatório geral salvo em: ${reportPath}`);
|
|
795
|
+
}
|
|
796
|
+
catch (error) {
|
|
797
|
+
Logger.error('❌ Erro ao gerar arquivo HTML do relatório', error);
|
|
798
|
+
}
|
|
799
|
+
// Logar os dados dos testes
|
|
800
|
+
testesRegistrados.forEach((testName) => {
|
|
801
|
+
const teste = UnifiedReportManager.dadosGlobais.testes[testName];
|
|
802
|
+
Logger.info(` 📄 ${testName}: ${teste.status} (${teste.tipo})`);
|
|
803
|
+
});
|
|
804
|
+
Logger.success('✅ Relatório geral gerado com sucesso!');
|
|
805
|
+
}
|
|
806
|
+
catch (error) {
|
|
807
|
+
Logger.error('❌ Erro ao gerar relatório geral', error);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* 🔍 DEBUG: Método para acessar dados globais
|
|
812
|
+
*/
|
|
813
|
+
static getDadosGlobais() {
|
|
814
|
+
return UnifiedReportManager.dadosGlobais;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* ✅ ÚNICO: Método getMetrics unificado
|
|
818
|
+
*/
|
|
819
|
+
static getMetrics() {
|
|
820
|
+
const testesPorTipo = {
|
|
821
|
+
API: 0,
|
|
822
|
+
Frontend: 0,
|
|
823
|
+
Mobile: 0,
|
|
824
|
+
SSH: 0,
|
|
825
|
+
Banco: 0,
|
|
826
|
+
Mixed: 0,
|
|
827
|
+
Scenarios: 0,
|
|
828
|
+
};
|
|
829
|
+
const resultadosPorTipo = {
|
|
830
|
+
API: { passou: 0, falhou: 0 },
|
|
831
|
+
Frontend: { passou: 0, falhou: 0 },
|
|
832
|
+
Mobile: { passou: 0, falhou: 0 },
|
|
833
|
+
SSH: { passou: 0, falhou: 0 },
|
|
834
|
+
Banco: { passou: 0, falhou: 0 },
|
|
835
|
+
Mixed: { passou: 0, falhou: 0 },
|
|
836
|
+
Scenarios: { passou: 0, falhou: 0 }, // Adicione esta linha
|
|
837
|
+
};
|
|
838
|
+
// ✅ USAR dadosGlobais como fonte única da verdade
|
|
839
|
+
Object.values(UnifiedReportManager.dadosGlobais.testes).forEach((teste) => {
|
|
840
|
+
testesPorTipo[teste.tipo]++;
|
|
841
|
+
if (teste.status === 'passed') {
|
|
842
|
+
resultadosPorTipo[teste.tipo].passou++;
|
|
843
|
+
}
|
|
844
|
+
else if (teste.status === 'failed') {
|
|
845
|
+
resultadosPorTipo[teste.tipo].falhou++;
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
const duracao = UnifiedReportManager.inicioExecucao && UnifiedReportManager.fimExecucao
|
|
849
|
+
? (UnifiedReportManager.fimExecucao.getTime() -
|
|
850
|
+
UnifiedReportManager.inicioExecucao.getTime()) /
|
|
851
|
+
1000
|
|
852
|
+
: 0;
|
|
853
|
+
return {
|
|
854
|
+
totalTestes: UnifiedReportManager.dadosGlobais.totalTestes,
|
|
855
|
+
testesPorTipo,
|
|
856
|
+
resultadosPorTipo,
|
|
857
|
+
inicio: UnifiedReportManager.inicioExecucao,
|
|
858
|
+
fim: UnifiedReportManager.fimExecucao,
|
|
859
|
+
duracao,
|
|
860
|
+
testes: UnifiedReportManager.testes,
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
static reset() {
|
|
864
|
+
UnifiedReportManager.testes = [];
|
|
865
|
+
UnifiedReportManager.contextoPorTeste.clear();
|
|
866
|
+
UnifiedReportManager.logsPorTeste.clear();
|
|
867
|
+
UnifiedReportManager.metadataPorTeste.clear();
|
|
868
|
+
UnifiedReportManager.duracoesPorTeste.clear();
|
|
869
|
+
UnifiedReportManager.inicioExecucao = undefined;
|
|
870
|
+
UnifiedReportManager.fimExecucao = undefined;
|
|
871
|
+
// ✅ NOVO: Reset dadosGlobais
|
|
872
|
+
UnifiedReportManager.dadosGlobais = {
|
|
873
|
+
totalTestes: 0,
|
|
874
|
+
testesPassados: 0,
|
|
875
|
+
testesFalharam: 0,
|
|
876
|
+
testes: {},
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
static async finalizarTeste(testName, status) {
|
|
880
|
+
try {
|
|
881
|
+
// Se foi chamado com parâmetros, usar a versão específica
|
|
882
|
+
if (testName && status) {
|
|
883
|
+
await UnifiedReportManager.marcarFimTeste(testName, status);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
// 🆕 Finalizar todos os CTs pendentes antes de coletar dados
|
|
887
|
+
TestAnnotations.finalizarCTAtivo();
|
|
888
|
+
await UnifiedReportManager.coletarDadosDoTeste();
|
|
889
|
+
await UnifiedReportManager.anexarRelatorioIndividual();
|
|
890
|
+
}
|
|
891
|
+
catch (error) {
|
|
892
|
+
Logger.error('❌ Erro ao finalizar teste unificado', error);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* ✅ NOVO: Interceptar e registrar erros de teste automaticamente
|
|
897
|
+
* @param testName Nome do teste
|
|
898
|
+
* @param error Erro capturado
|
|
899
|
+
*/
|
|
900
|
+
static async registrarErroTeste(testName, error) {
|
|
901
|
+
const errorMessage = typeof error === 'string' ? error : error.message || error.toString();
|
|
902
|
+
Logger.info(`🔴 Erro registrado para ${testName}: ${errorMessage}`);
|
|
903
|
+
// Adicionar log do erro
|
|
904
|
+
UnifiedReportManager.adicionarLog(testName, `❌ ERRO: ${errorMessage}`);
|
|
905
|
+
// ✅ IMPORTANTE: Chamar corrigirStatusCTsQuandoTesteFalha imediatamente
|
|
906
|
+
await UnifiedReportManager.corrigirStatusCTsQuandoTesteFalha(testName);
|
|
907
|
+
// Marcar teste como falhado nos dados globais
|
|
908
|
+
if (UnifiedReportManager.dadosGlobais.testes[testName]) {
|
|
909
|
+
UnifiedReportManager.dadosGlobais.testes[testName].status = 'failed';
|
|
910
|
+
Logger.success(`✅ Status do teste ${testName} atualizado para 'failed'`);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* ✅ NOVO: Configurar interceptação global de erros para testes AutoCore
|
|
915
|
+
*/
|
|
916
|
+
static configurarInterceptacaoErros() {
|
|
917
|
+
const errorHandler = (error) => {
|
|
918
|
+
const errorMessage = error.message || error.toString();
|
|
919
|
+
// Usar teste atual do monitoramento automático
|
|
920
|
+
const testName = UnifiedReportManager.currentTestName;
|
|
921
|
+
if (testName &&
|
|
922
|
+
(errorMessage.includes('expect') ||
|
|
923
|
+
errorMessage.includes('AssertionError') ||
|
|
924
|
+
errorMessage.includes('Error:'))) {
|
|
925
|
+
Logger.info(`🤖 AutoCore: Erro detectado automaticamente no teste ${testName}`);
|
|
926
|
+
UnifiedReportManager.registrarErroTeste(testName, error).catch((err) => Logger.error('Erro ao registrar erro:', err));
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
// Adicionar handlers se ainda não existem
|
|
930
|
+
if (!process.listenerCount('uncaughtException')) {
|
|
931
|
+
process.on('uncaughtException', errorHandler);
|
|
932
|
+
}
|
|
933
|
+
if (!process.listenerCount('unhandledRejection')) {
|
|
934
|
+
process.on('unhandledRejection', (reason) => {
|
|
935
|
+
errorHandler(new Error(`Unhandled Rejection: ${reason}`));
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* ✅ NOVO: Interceptar logs do console para detectar ações automaticamente
|
|
941
|
+
*/
|
|
942
|
+
static interceptarConsole() {
|
|
943
|
+
// 🆕 Criar buffer global para logs se não existir
|
|
944
|
+
if (!globalThis.consoleBuffer) {
|
|
945
|
+
;
|
|
946
|
+
globalThis.consoleBuffer = [];
|
|
947
|
+
}
|
|
948
|
+
const originalLog = console.log;
|
|
949
|
+
const originalError = console.error;
|
|
950
|
+
const originalInfo = console.info;
|
|
951
|
+
const originalWarn = console.warn;
|
|
952
|
+
console.log = (...args) => {
|
|
953
|
+
const message = args.join(' ');
|
|
954
|
+
// 🔧 CRÍTICO: Evitar recursão infinita com proteções múltiplas
|
|
955
|
+
if (!(message.includes('📝 Adicionando log para') ||
|
|
956
|
+
message.includes('[UNIFIED]') ||
|
|
957
|
+
message.includes('interceptação') ||
|
|
958
|
+
message.includes('AutoCore: Sistema')) &&
|
|
959
|
+
UnifiedReportManager.currentTestName &&
|
|
960
|
+
!UnifiedReportManager._intercepting) {
|
|
961
|
+
;
|
|
962
|
+
UnifiedReportManager._intercepting = true;
|
|
963
|
+
try {
|
|
964
|
+
;
|
|
965
|
+
globalThis.consoleBuffer.push({
|
|
966
|
+
testName: UnifiedReportManager.currentTestName,
|
|
967
|
+
message,
|
|
968
|
+
timestamp: new Date().toISOString(),
|
|
969
|
+
type: 'log',
|
|
970
|
+
});
|
|
971
|
+
// 🔧 ADIÇÃO DIRETA SEM chamar adicionarLog para evitar loop
|
|
972
|
+
if (!UnifiedReportManager.logsPorTeste.has(UnifiedReportManager.currentTestName)) {
|
|
973
|
+
UnifiedReportManager.logsPorTeste.set(UnifiedReportManager.currentTestName, []);
|
|
974
|
+
}
|
|
975
|
+
UnifiedReportManager.logsPorTeste
|
|
976
|
+
.get(UnifiedReportManager.currentTestName)
|
|
977
|
+
.push(message);
|
|
978
|
+
}
|
|
979
|
+
finally {
|
|
980
|
+
;
|
|
981
|
+
UnifiedReportManager._intercepting = false;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
// Chamar console original
|
|
985
|
+
originalLog.apply(console, args);
|
|
986
|
+
};
|
|
987
|
+
console.info = (...args) => {
|
|
988
|
+
const message = args.join(' ');
|
|
989
|
+
if (UnifiedReportManager.currentTestName) {
|
|
990
|
+
;
|
|
991
|
+
globalThis.consoleBuffer.push({
|
|
992
|
+
testName: UnifiedReportManager.currentTestName,
|
|
993
|
+
message: `ℹ️ ${message}`,
|
|
994
|
+
timestamp: new Date().toISOString(),
|
|
995
|
+
type: 'info',
|
|
996
|
+
});
|
|
997
|
+
// 🔧 EVITAR RECURSÃO: Não chamar adicionarLog que faz console.log
|
|
998
|
+
// this.adicionarLog(this.currentTestName, `ℹ️ ${message}`)
|
|
999
|
+
}
|
|
1000
|
+
originalInfo.apply(console, args);
|
|
1001
|
+
};
|
|
1002
|
+
console.warn = (...args) => {
|
|
1003
|
+
const message = args.join(' ');
|
|
1004
|
+
if (UnifiedReportManager.currentTestName) {
|
|
1005
|
+
;
|
|
1006
|
+
globalThis.consoleBuffer.push({
|
|
1007
|
+
testName: UnifiedReportManager.currentTestName,
|
|
1008
|
+
message: `⚠️ ${message}`,
|
|
1009
|
+
timestamp: new Date().toISOString(),
|
|
1010
|
+
type: 'warn',
|
|
1011
|
+
});
|
|
1012
|
+
// 🔧 EVITAR RECURSÃO: Não chamar adicionarLog que faz console.log
|
|
1013
|
+
// this.adicionarLog(this.currentTestName, `⚠️ ${message}`)
|
|
1014
|
+
}
|
|
1015
|
+
originalWarn.apply(console, args);
|
|
1016
|
+
};
|
|
1017
|
+
console.error = (...args) => {
|
|
1018
|
+
const message = args.join(' ');
|
|
1019
|
+
// 🆕 Adicionar ao buffer global
|
|
1020
|
+
if (UnifiedReportManager.currentTestName) {
|
|
1021
|
+
;
|
|
1022
|
+
globalThis.consoleBuffer.push({
|
|
1023
|
+
testName: UnifiedReportManager.currentTestName,
|
|
1024
|
+
message: `❌ ERRO: ${message}`,
|
|
1025
|
+
timestamp: new Date().toISOString(),
|
|
1026
|
+
type: 'error',
|
|
1027
|
+
});
|
|
1028
|
+
// 🔧 EVITAR RECURSÃO: Não chamar adicionarLog que faz console.log
|
|
1029
|
+
// this.adicionarLog(this.currentTestName, `❌ ERRO: ${message}`)
|
|
1030
|
+
// Considerar como falha
|
|
1031
|
+
setTimeout(() => {
|
|
1032
|
+
if (UnifiedReportManager.currentTestName) {
|
|
1033
|
+
UnifiedReportManager.registrarErroTeste(UnifiedReportManager.currentTestName, message).catch((err) => console.error('Erro ao registrar erro:', err));
|
|
1034
|
+
}
|
|
1035
|
+
}, 10);
|
|
1036
|
+
}
|
|
1037
|
+
// Chamar console original
|
|
1038
|
+
originalError.apply(console, args);
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* ✅ NOVO: Adiciona um CT ao teste
|
|
1043
|
+
*/
|
|
1044
|
+
static adicionarCT(testName, ct) {
|
|
1045
|
+
if (!(testName && ct)) {
|
|
1046
|
+
Logger.warning('⚠️ Nome do teste ou CT vazio, ignorando adicionarCT');
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
// Buscar o teste nos dados globais
|
|
1050
|
+
const testeGlobal = UnifiedReportManager.dadosGlobais.testes[testName];
|
|
1051
|
+
if (testeGlobal) {
|
|
1052
|
+
if (!testeGlobal.cts) {
|
|
1053
|
+
testeGlobal.cts = [];
|
|
1054
|
+
}
|
|
1055
|
+
testeGlobal.cts.push(ct);
|
|
1056
|
+
Logger.info(`📋 CT adicionado ao teste ${testName}: ${ct.id || ct.descricao}`);
|
|
1057
|
+
}
|
|
1058
|
+
// Também adicionar ao array principal de testes
|
|
1059
|
+
const testeArray = UnifiedReportManager.testes.find((t) => t.nome === testName);
|
|
1060
|
+
if (testeArray) {
|
|
1061
|
+
if (!testeArray.cts) {
|
|
1062
|
+
testeArray.cts = [];
|
|
1063
|
+
}
|
|
1064
|
+
testeArray.cts.push(ct);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* ✅ NOVO: Gera o relatório unificado final
|
|
1069
|
+
*/
|
|
1070
|
+
static async gerarRelatorioUnificado() {
|
|
1071
|
+
Logger.info('📊 Gerando relatório unificado...');
|
|
1072
|
+
try {
|
|
1073
|
+
// Coletar dados de todos os testes
|
|
1074
|
+
const testesComDados = await Promise.all(UnifiedReportManager.testes.map(async (teste) => {
|
|
1075
|
+
const dadosColetados = await UnifiedReportManager.coletarDadosDoTeste(teste.nome);
|
|
1076
|
+
return {
|
|
1077
|
+
...teste,
|
|
1078
|
+
cts: dadosColetados.cts || [],
|
|
1079
|
+
logs: dadosColetados.logs || [],
|
|
1080
|
+
screenshots: dadosColetados.screenshots || [],
|
|
1081
|
+
};
|
|
1082
|
+
}));
|
|
1083
|
+
// 🆕 Buscar dados do StatementTracker
|
|
1084
|
+
let ctData = null;
|
|
1085
|
+
let allCNsData = {};
|
|
1086
|
+
try {
|
|
1087
|
+
ctData = await getStatementTrackerData();
|
|
1088
|
+
const allExecutions = StatementTracker.getExecutions();
|
|
1089
|
+
// 🔧 Converter Map para objeto plano (JSON serializable)
|
|
1090
|
+
allCNsData = Object.fromEntries(allExecutions);
|
|
1091
|
+
Logger.info(`📊 gerarRelatorioUnificado: ${Object.keys(allCNsData).length} CNs exportados para template`);
|
|
1092
|
+
}
|
|
1093
|
+
catch (error) {
|
|
1094
|
+
Logger.warning(`⚠️ Erro ao buscar dados do StatementTracker: ${error}`);
|
|
1095
|
+
}
|
|
1096
|
+
// Preparar dados para o template
|
|
1097
|
+
const dadosRelatorio = {
|
|
1098
|
+
testes: testesComDados,
|
|
1099
|
+
titulo: 'Relatório Unificado de Testes',
|
|
1100
|
+
subtitulo: 'Resultados da execução de testes automatizados',
|
|
1101
|
+
totalTestes: UnifiedReportManager.dadosGlobais.totalTestes,
|
|
1102
|
+
testesPassaram: UnifiedReportManager.dadosGlobais.testesPassados,
|
|
1103
|
+
testesFalharam: UnifiedReportManager.dadosGlobais.testesFalharam,
|
|
1104
|
+
projectName: 'TestHUB',
|
|
1105
|
+
environment: 'N/A',
|
|
1106
|
+
executionDate: new Date().toLocaleString('pt-BR'),
|
|
1107
|
+
autocoreVersion: 'v1.1.x',
|
|
1108
|
+
// 🔗 INTEGRAÇÃO: Dados dos CTs detectados automaticamente
|
|
1109
|
+
ctData,
|
|
1110
|
+
allCNsData, // 🆕 Mapa completo de CNs → CTs → Statements → Actions
|
|
1111
|
+
estatisticasPorTipo: {},
|
|
1112
|
+
coresDosTipos: {
|
|
1113
|
+
API: '#3b82f6',
|
|
1114
|
+
Frontend: '#10b981',
|
|
1115
|
+
Mobile: '#f59e0b',
|
|
1116
|
+
SSH: '#ef4444',
|
|
1117
|
+
Banco: '#8b5cf6',
|
|
1118
|
+
Mixed: '#6b7280',
|
|
1119
|
+
},
|
|
1120
|
+
chartLabels: ['Passou', 'Falhou'],
|
|
1121
|
+
chartData: [
|
|
1122
|
+
UnifiedReportManager.dadosGlobais.testesPassados,
|
|
1123
|
+
UnifiedReportManager.dadosGlobais.testesFalharam,
|
|
1124
|
+
],
|
|
1125
|
+
chartColors: ['#22c55e', '#ef4444'],
|
|
1126
|
+
barLabels: ['Testes'],
|
|
1127
|
+
barData: [UnifiedReportManager.dadosGlobais.totalTestes],
|
|
1128
|
+
pieLabels: ['Passou', 'Falhou'],
|
|
1129
|
+
pieData: [
|
|
1130
|
+
UnifiedReportManager.dadosGlobais.testesPassados,
|
|
1131
|
+
UnifiedReportManager.dadosGlobais.testesFalharam,
|
|
1132
|
+
],
|
|
1133
|
+
getIconePorTipo: (tipo) => {
|
|
1134
|
+
const icones = {
|
|
1135
|
+
API: '🌐',
|
|
1136
|
+
Frontend: '💻',
|
|
1137
|
+
Mobile: '📱',
|
|
1138
|
+
SSH: '🔐',
|
|
1139
|
+
Banco: '🗃️',
|
|
1140
|
+
Mixed: '🔄',
|
|
1141
|
+
};
|
|
1142
|
+
return icones[tipo] || '📋';
|
|
1143
|
+
},
|
|
1144
|
+
resumo: {
|
|
1145
|
+
totalTestes: UnifiedReportManager.dadosGlobais.totalTestes,
|
|
1146
|
+
testesPassados: UnifiedReportManager.dadosGlobais.testesPassados,
|
|
1147
|
+
testesFalharam: UnifiedReportManager.dadosGlobais.testesFalharam,
|
|
1148
|
+
duracaoTotal: UnifiedReportManager.calcularDuracaoTotal(),
|
|
1149
|
+
timestamp: new Date().toISOString(),
|
|
1150
|
+
},
|
|
1151
|
+
metadata: {
|
|
1152
|
+
inicio: UnifiedReportManager.inicioExecucao?.toISOString(),
|
|
1153
|
+
fim: UnifiedReportManager.fimExecucao?.toISOString(),
|
|
1154
|
+
contextos: UnifiedReportManager.getContextosUnicos(),
|
|
1155
|
+
},
|
|
1156
|
+
};
|
|
1157
|
+
// Gerar HTML usando o template
|
|
1158
|
+
const htmlTemplatePath = path.join(process.cwd(), 'src', 'utils', 'HTMLTemplate.js');
|
|
1159
|
+
const htmlContent = HTMLTemplate(dadosRelatorio);
|
|
1160
|
+
// Salvar arquivo
|
|
1161
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
1162
|
+
const nomeArquivo = `relatorio-unificado-${timestamp}.html`;
|
|
1163
|
+
const caminhoCompleto = path.join(process.cwd(), 'docs', nomeArquivo);
|
|
1164
|
+
// Garantir que o diretório existe
|
|
1165
|
+
const dirDocs = path.dirname(caminhoCompleto);
|
|
1166
|
+
if (!fs.existsSync(dirDocs)) {
|
|
1167
|
+
fs.mkdirSync(dirDocs, { recursive: true });
|
|
1168
|
+
}
|
|
1169
|
+
fs.writeFileSync(caminhoCompleto, htmlContent, 'utf8');
|
|
1170
|
+
Logger.info(`✅ Relatório unificado gerado: ${caminhoCompleto}`);
|
|
1171
|
+
Logger.info(`📊 Resumo: ${dadosRelatorio.resumo.totalTestes} testes, ${dadosRelatorio.resumo.testesPassados} passaram, ${dadosRelatorio.resumo.testesFalharam} falharam`);
|
|
1172
|
+
return caminhoCompleto;
|
|
1173
|
+
}
|
|
1174
|
+
catch (error) {
|
|
1175
|
+
Logger.error('❌ Erro ao gerar relatório unificado:', error);
|
|
1176
|
+
return '';
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* ✅ HELPER: Calcula duração total
|
|
1181
|
+
*/
|
|
1182
|
+
static calcularDuracaoTotal() {
|
|
1183
|
+
if (UnifiedReportManager.inicioExecucao &&
|
|
1184
|
+
UnifiedReportManager.fimExecucao) {
|
|
1185
|
+
const duracao = (UnifiedReportManager.fimExecucao.getTime() -
|
|
1186
|
+
UnifiedReportManager.inicioExecucao.getTime()) /
|
|
1187
|
+
1000;
|
|
1188
|
+
return `${duracao.toFixed(2)}s`;
|
|
1189
|
+
}
|
|
1190
|
+
return '0s';
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* ✅ HELPER: Pega contextos únicos
|
|
1194
|
+
*/
|
|
1195
|
+
static getContextosUnicos() {
|
|
1196
|
+
const contextos = new Set();
|
|
1197
|
+
UnifiedReportManager.testes.forEach((teste) => {
|
|
1198
|
+
contextos.add(teste.tipo);
|
|
1199
|
+
});
|
|
1200
|
+
return Array.from(contextos);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
// ✅ CRITICAL: Auto-inicialização quando módulo é carregado
|
|
1204
|
+
UnifiedReportManager['autoInit']();
|
|
1205
|
+
// ✅ IMPORTANTE: Interceptar console automaticamente
|
|
1206
|
+
UnifiedReportManager['interceptarConsole']();
|