@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,600 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 📸 Sistema de Captura de Evidências
|
|
3
|
+
* @description Captura e organiza screenshots e logs para gerar relatórios com evidências
|
|
4
|
+
* @author TestHUB Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { TestContext } from '../testContext/TestContext.js';
|
|
10
|
+
import { Logger } from './Logger.js';
|
|
11
|
+
export class EvidenceCapture {
|
|
12
|
+
static evidenceByTest = new Map();
|
|
13
|
+
static currentEvidenceId = 0;
|
|
14
|
+
static playwrightReportDir = '';
|
|
15
|
+
static evidenceFile = '';
|
|
16
|
+
/**
|
|
17
|
+
* ✅ Inicializa o sistema de captura de evidências
|
|
18
|
+
*/
|
|
19
|
+
static initialize() {
|
|
20
|
+
// Detectar diretório playwright-report
|
|
21
|
+
const possibleDirs = [
|
|
22
|
+
path.join(process.cwd(), 'playwright-report'),
|
|
23
|
+
path.join(process.cwd(), 'test-results'),
|
|
24
|
+
path.join(process.cwd(), 'reports'),
|
|
25
|
+
];
|
|
26
|
+
for (const dir of possibleDirs) {
|
|
27
|
+
if (fs.existsSync(dir)) {
|
|
28
|
+
EvidenceCapture.playwrightReportDir = dir;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Se não encontrar, criar playwright-report
|
|
33
|
+
if (!EvidenceCapture.playwrightReportDir) {
|
|
34
|
+
EvidenceCapture.playwrightReportDir = path.join(process.cwd(), 'playwright-report');
|
|
35
|
+
if (!fs.existsSync(EvidenceCapture.playwrightReportDir)) {
|
|
36
|
+
fs.mkdirSync(EvidenceCapture.playwrightReportDir, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Criar subpasta para evidências
|
|
40
|
+
const evidenceDir = path.join(EvidenceCapture.playwrightReportDir, 'evidence');
|
|
41
|
+
if (!fs.existsSync(evidenceDir)) {
|
|
42
|
+
fs.mkdirSync(evidenceDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
// Definir arquivo de persistência
|
|
45
|
+
EvidenceCapture.evidenceFile = path.join(EvidenceCapture.playwrightReportDir, 'evidence-data.json');
|
|
46
|
+
// Carregar evidências existentes
|
|
47
|
+
EvidenceCapture.loadEvidence();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 🆕 Carregar evidências do arquivo de persistência
|
|
51
|
+
*/
|
|
52
|
+
static loadEvidence() {
|
|
53
|
+
try {
|
|
54
|
+
if (fs.existsSync(EvidenceCapture.evidenceFile)) {
|
|
55
|
+
const data = fs.readFileSync(EvidenceCapture.evidenceFile, 'utf-8');
|
|
56
|
+
const parsed = JSON.parse(data);
|
|
57
|
+
// Restaurar Map
|
|
58
|
+
if (parsed.evidenceByTest) {
|
|
59
|
+
for (const [testName, testEvidence] of Object.entries(parsed.evidenceByTest)) {
|
|
60
|
+
// Converter datas de volta para objetos Date
|
|
61
|
+
const evidence = testEvidence;
|
|
62
|
+
evidence.startTime = new Date(evidence.startTime);
|
|
63
|
+
if (evidence.endTime) {
|
|
64
|
+
evidence.endTime = new Date(evidence.endTime);
|
|
65
|
+
}
|
|
66
|
+
if (evidence.items) {
|
|
67
|
+
evidence.items.forEach((item) => {
|
|
68
|
+
item.timestamp = new Date(item.timestamp);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
EvidenceCapture.evidenceByTest.set(testName, evidence);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
Logger.info('⚠️ [EvidenceCapture] loadEvidence - No evidenceByTest in parsed data');
|
|
76
|
+
}
|
|
77
|
+
// Restaurar contador
|
|
78
|
+
if (parsed.currentEvidenceId) {
|
|
79
|
+
EvidenceCapture.currentEvidenceId = parsed.currentEvidenceId;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
Logger.warning(`⚠️ [EvidenceCapture] Erro ao carregar evidências: ${error}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 🆕 Salvar evidências no arquivo de persistência
|
|
91
|
+
*/
|
|
92
|
+
static saveEvidence() {
|
|
93
|
+
try {
|
|
94
|
+
const data = {
|
|
95
|
+
evidenceByTest: Object.fromEntries(EvidenceCapture.evidenceByTest),
|
|
96
|
+
currentEvidenceId: EvidenceCapture.currentEvidenceId,
|
|
97
|
+
lastSaved: new Date().toISOString(),
|
|
98
|
+
};
|
|
99
|
+
fs.writeFileSync(EvidenceCapture.evidenceFile, JSON.stringify(data, null, 2), 'utf-8');
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
Logger.warning(`⚠️ [EvidenceCapture] Erro ao salvar evidências: ${error}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* ✅ Inicia captura para um teste
|
|
107
|
+
*/
|
|
108
|
+
static startTest(testName) {
|
|
109
|
+
if (!EvidenceCapture.evidenceByTest.has(testName)) {
|
|
110
|
+
EvidenceCapture.evidenceByTest.set(testName, {
|
|
111
|
+
testName,
|
|
112
|
+
startTime: new Date(),
|
|
113
|
+
items: [],
|
|
114
|
+
totalActions: 0,
|
|
115
|
+
successActions: 0,
|
|
116
|
+
failedActions: 0,
|
|
117
|
+
});
|
|
118
|
+
// Salvar imediatamente
|
|
119
|
+
EvidenceCapture.saveEvidence();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* ✅ Finaliza captura para um teste
|
|
124
|
+
*/
|
|
125
|
+
static endTest(testName) {
|
|
126
|
+
const evidence = EvidenceCapture.evidenceByTest.get(testName);
|
|
127
|
+
if (evidence) {
|
|
128
|
+
evidence.endTime = new Date();
|
|
129
|
+
// Salvar imediatamente
|
|
130
|
+
EvidenceCapture.saveEvidence();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* ✅ Captura uma ação com screenshot
|
|
135
|
+
* @param testName Nome do teste
|
|
136
|
+
* @param action Ação executada
|
|
137
|
+
* @param description Descrição da ação
|
|
138
|
+
* @param metadata Metadados opcionais
|
|
139
|
+
* @param providedScreenshot Screenshot fornecido externamente (Buffer ou caminho)
|
|
140
|
+
*/
|
|
141
|
+
static async captureAction(testName, action, description, metadata, providedScreenshot) {
|
|
142
|
+
try {
|
|
143
|
+
// Garantir que o teste está iniciado
|
|
144
|
+
EvidenceCapture.startTest(testName);
|
|
145
|
+
const evidenceId = `evidence-${++EvidenceCapture.currentEvidenceId}`;
|
|
146
|
+
const timestamp = new Date();
|
|
147
|
+
// Capturar screenshot se possível
|
|
148
|
+
let screenshot;
|
|
149
|
+
let screenshotPath;
|
|
150
|
+
try {
|
|
151
|
+
// 🆕 PRIORIZAR SCREENSHOT FORNECIDO (Mobile/Web)
|
|
152
|
+
if (providedScreenshot) {
|
|
153
|
+
if (Buffer.isBuffer(providedScreenshot)) {
|
|
154
|
+
screenshot = providedScreenshot;
|
|
155
|
+
}
|
|
156
|
+
else if (typeof providedScreenshot === 'string') {
|
|
157
|
+
// Se for caminho, usar o caminho diretamente
|
|
158
|
+
screenshotPath = providedScreenshot;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Se não tiver screenshot fornecido, tentar capturar via TestContext
|
|
162
|
+
if (!(screenshot || screenshotPath)) {
|
|
163
|
+
const capturedScreenshot = await TestContext.captureScreenshot();
|
|
164
|
+
if (capturedScreenshot) {
|
|
165
|
+
screenshot = capturedScreenshot;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Se tiver screenshot buffer, salvar arquivo
|
|
169
|
+
if (screenshot) {
|
|
170
|
+
const evidenceDir = path.join(EvidenceCapture.playwrightReportDir, 'evidence', testName.replace(/[^a-zA-Z0-9]/g, '_'));
|
|
171
|
+
if (!fs.existsSync(evidenceDir)) {
|
|
172
|
+
fs.mkdirSync(evidenceDir, { recursive: true });
|
|
173
|
+
}
|
|
174
|
+
const screenshotFile = path.join(evidenceDir, `${evidenceId}.png`);
|
|
175
|
+
fs.writeFileSync(screenshotFile, screenshot);
|
|
176
|
+
// Path relativo para o HTML
|
|
177
|
+
screenshotPath = `evidence/${testName.replace(/[^a-zA-Z0-9]/g, '_')}/${evidenceId}.png`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
Logger.warning(`⚠️ Não foi possível capturar screenshot para ${action}: ${error}`);
|
|
182
|
+
}
|
|
183
|
+
const evidenceItem = {
|
|
184
|
+
id: evidenceId,
|
|
185
|
+
timestamp,
|
|
186
|
+
testName,
|
|
187
|
+
action,
|
|
188
|
+
description,
|
|
189
|
+
screenshot,
|
|
190
|
+
screenshotPath,
|
|
191
|
+
metadata,
|
|
192
|
+
};
|
|
193
|
+
const evidence = EvidenceCapture.evidenceByTest.get(testName);
|
|
194
|
+
evidence.items.push(evidenceItem);
|
|
195
|
+
evidence.totalActions++;
|
|
196
|
+
// Determinar se ação foi bem-sucedida baseado na descrição
|
|
197
|
+
if (description.includes('❌') ||
|
|
198
|
+
description.includes('erro') ||
|
|
199
|
+
description.includes('falhou')) {
|
|
200
|
+
evidence.failedActions++;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
evidence.successActions++;
|
|
204
|
+
}
|
|
205
|
+
// 🆕 SALVAR IMEDIATAMENTE APÓS ADICIONAR EVIDÊNCIA
|
|
206
|
+
EvidenceCapture.saveEvidence();
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
Logger.error('❌ Erro ao capturar evidência:', error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Compatibilidade: capturar página (wrapper para captureAction)
|
|
214
|
+
* @param description descrição da captura
|
|
215
|
+
* @param providedScreenshot buffer ou path opcional
|
|
216
|
+
*/
|
|
217
|
+
static async capturePage(description, providedScreenshot) {
|
|
218
|
+
try {
|
|
219
|
+
const testInfo = TestContext.getSafeTestInfo();
|
|
220
|
+
const testName = (testInfo && testInfo.title) || 'unknown';
|
|
221
|
+
await EvidenceCapture.captureAction(testName, 'page', description, undefined, providedScreenshot);
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
Logger.warning(`⚠️ EvidenceCapture.capturePage falhou: ${e}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* ✅ Obtém evidências de um teste
|
|
229
|
+
*/
|
|
230
|
+
static getTestEvidence(testName) {
|
|
231
|
+
return EvidenceCapture.evidenceByTest.get(testName);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* ✅ Obtém todas as evidências (sempre carrega dados atualizados quando Map está vazio)
|
|
235
|
+
*/
|
|
236
|
+
static getAllEvidence() {
|
|
237
|
+
// 🆕 RECARREGAR dados do arquivo APENAS se o Map estiver vazio
|
|
238
|
+
if (EvidenceCapture.evidenceByTest.size === 0) {
|
|
239
|
+
EvidenceCapture.loadEvidence();
|
|
240
|
+
}
|
|
241
|
+
return EvidenceCapture.evidenceByTest;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* ✅ Gera relatório HTML com evidências
|
|
245
|
+
*/
|
|
246
|
+
static async generateEvidenceReport() {
|
|
247
|
+
try {
|
|
248
|
+
const reportPath = path.join(EvidenceCapture.playwrightReportDir, 'evidence-report.html');
|
|
249
|
+
const html = EvidenceCapture.generateEvidenceHTML();
|
|
250
|
+
fs.writeFileSync(reportPath, html, 'utf-8');
|
|
251
|
+
Logger.success(`📄 Relatório de evidências gerado: ${reportPath}`);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
Logger.error('❌ Erro ao gerar relatório de evidências:', error);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* ✅ Gera HTML do relatório de evidências
|
|
259
|
+
*/
|
|
260
|
+
static generateEvidenceHTML() {
|
|
261
|
+
const allEvidence = Array.from(EvidenceCapture.evidenceByTest.values());
|
|
262
|
+
// Agrupar por tipo de teste e status
|
|
263
|
+
const groupedEvidence = allEvidence.reduce((groups, evidence) => {
|
|
264
|
+
// Detectar tipo de teste baseado no nome
|
|
265
|
+
let testType = 'Geral';
|
|
266
|
+
if (evidence.testName.toLowerCase().includes('api'))
|
|
267
|
+
testType = 'API';
|
|
268
|
+
else if (evidence.testName.toLowerCase().includes('frontend'))
|
|
269
|
+
testType = 'Frontend';
|
|
270
|
+
else if (evidence.testName.toLowerCase().includes('mobile'))
|
|
271
|
+
testType = 'Mobile';
|
|
272
|
+
else if (evidence.testName.toLowerCase().includes('ssh'))
|
|
273
|
+
testType = 'SSH';
|
|
274
|
+
else if (evidence.testName.toLowerCase().includes('banco'))
|
|
275
|
+
testType = 'Banco';
|
|
276
|
+
if (!groups[testType])
|
|
277
|
+
groups[testType] = [];
|
|
278
|
+
groups[testType].push(evidence);
|
|
279
|
+
return groups;
|
|
280
|
+
}, {});
|
|
281
|
+
const totalTests = allEvidence.length;
|
|
282
|
+
const totalActions = allEvidence.reduce((sum, e) => sum + e.totalActions, 0);
|
|
283
|
+
const successActions = allEvidence.reduce((sum, e) => sum + e.successActions, 0);
|
|
284
|
+
const failedActions = allEvidence.reduce((sum, e) => sum + e.failedActions, 0);
|
|
285
|
+
const successRate = totalActions > 0
|
|
286
|
+
? ((successActions / totalActions) * 100).toFixed(1)
|
|
287
|
+
: '0.0';
|
|
288
|
+
return `<!DOCTYPE html>
|
|
289
|
+
<html lang="pt-BR">
|
|
290
|
+
<head>
|
|
291
|
+
<meta charset="UTF-8">
|
|
292
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
293
|
+
<title>📸 Relatório de Evidências - TestHUB</title>
|
|
294
|
+
<style>
|
|
295
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
296
|
+
body { font-family: 'Segoe UI', system-ui, sans-serif; background: #0f172a; color: #f1f5f9; line-height: 1.6; }
|
|
297
|
+
.light-mode { background-color: #f9fafb !important; color: #111827 !important; }
|
|
298
|
+
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
|
|
299
|
+
.header { text-align: center; margin-bottom: 3rem; padding: 2rem; background: linear-gradient(135deg, #1e293b, #334155); border-radius: 1rem; }
|
|
300
|
+
.header h1 { color: #22d3ee; font-size: 2.5rem; margin-bottom: 0.5rem; }
|
|
301
|
+
.header p { color: #94a3b8; font-size: 1.1rem; margin-bottom: 1rem; }
|
|
302
|
+
.header-buttons { margin-top: 1rem; display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
|
|
303
|
+
.btn { background: #10b981; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 0.5rem; cursor: pointer; font-size: 1rem; font-weight: 600; transition: all 0.3s ease; }
|
|
304
|
+
.btn:hover { background: #059669; transform: translateY(-2px); }
|
|
305
|
+
.btn-theme { background: #3b82f6; }
|
|
306
|
+
.btn-theme:hover { background: #2563eb; }
|
|
307
|
+
|
|
308
|
+
/* Agrupamento por tipo */
|
|
309
|
+
.type-group { margin-bottom: 3rem; background: #1e293b; border-radius: 1rem; padding: 1.5rem; }
|
|
310
|
+
.type-header { display: flex; items-center justify-between; margin-bottom: 2rem; padding-bottom: 1rem; border-bottom: 2px solid #374151; }
|
|
311
|
+
.type-title { font-size: 1.8rem; font-weight: 700; display: flex; items-center gap: 0.5rem; }
|
|
312
|
+
.type-stats { display: flex; gap: 1rem; font-size: 0.9rem; }
|
|
313
|
+
.stat-item { background: #374151; padding: 0.5rem 1rem; border-radius: 0.5rem; }
|
|
314
|
+
.stat-success { color: #10b981; }
|
|
315
|
+
.stat-failed { color: #ef4444; }
|
|
316
|
+
.stat-total { color: #06b6d4; }
|
|
317
|
+
|
|
318
|
+
.tests-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 2rem; }
|
|
319
|
+
.test-card { background: #111827; border-radius: 0.75rem; overflow: hidden; border: 1px solid #374151; }
|
|
320
|
+
.test-card-header { background: #1f2937; padding: 1rem; }
|
|
321
|
+
.test-title { color: #22d3ee; font-size: 1.2rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
322
|
+
.test-meta { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; font-size: 0.85rem; color: #9ca3af; }
|
|
323
|
+
.test-meta-item { background: #374151; padding: 0.5rem; border-radius: 0.25rem; text-align: center; }
|
|
324
|
+
|
|
325
|
+
.actions-container { padding: 1rem; }
|
|
326
|
+
.action-item { background: #1f2937; border-radius: 0.5rem; margin-bottom: 1rem; overflow: hidden; }
|
|
327
|
+
.action-header { display: flex; justify-content: between; align-items: center; padding: 0.75rem; background: #374151; }
|
|
328
|
+
.action-title { color: #22c55e; font-weight: 600; flex-1; }
|
|
329
|
+
.action-time { color: #94a3b8; font-size: 0.8rem; }
|
|
330
|
+
.action-status { font-size: 0.7rem; padding: 0.25rem 0.5rem; border-radius: 0.25rem; margin-left: 0.5rem; }
|
|
331
|
+
.status-success { background: #059669; color: white; }
|
|
332
|
+
.status-failed { background: #dc2626; color: white; }
|
|
333
|
+
.action-description { color: #e2e8f0; padding: 0.75rem; font-size: 0.9rem; }
|
|
334
|
+
.screenshot-container { padding: 0.75rem; text-align: center; }
|
|
335
|
+
.screenshot { max-width: 100%; max-height: 200px; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0,0,0,0.3); cursor: pointer; transition: transform 0.2s; }
|
|
336
|
+
.screenshot:hover { transform: scale(1.05); }
|
|
337
|
+
.no-screenshot { color: #64748b; font-style: italic; padding: 1rem; text-align: center; background: #374151; border-radius: 0.25rem; }
|
|
338
|
+
|
|
339
|
+
.summary-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.5rem; margin: 3rem 0; }
|
|
340
|
+
.summary-card { background: linear-gradient(135deg, #1e293b, #334155); padding: 2rem; border-radius: 1rem; text-align: center; }
|
|
341
|
+
.summary-number { font-size: 2.5rem; font-weight: bold; margin-bottom: 0.5rem; }
|
|
342
|
+
.summary-label { color: #94a3b8; font-weight: 500; }
|
|
343
|
+
.summary-tests { color: #06b6d4; }
|
|
344
|
+
.summary-actions { color: #22d3ee; }
|
|
345
|
+
.summary-success { color: #10b981; }
|
|
346
|
+
.summary-failed { color: #ef4444; }
|
|
347
|
+
|
|
348
|
+
.collapsible { cursor: pointer; user-select: none; }
|
|
349
|
+
.collapsible:hover { background: #1f2937; }
|
|
350
|
+
.content { max-height: 300px; overflow-y: auto; }
|
|
351
|
+
|
|
352
|
+
@media (max-width: 768px) {
|
|
353
|
+
.header-buttons { flex-direction: column; align-items: center; }
|
|
354
|
+
.tests-grid { grid-template-columns: 1fr; }
|
|
355
|
+
.type-header { flex-direction: column; gap: 1rem; }
|
|
356
|
+
.type-stats { flex-wrap: wrap; justify-content: center; }
|
|
357
|
+
}
|
|
358
|
+
</style>
|
|
359
|
+
</head>
|
|
360
|
+
<body id="body-root">
|
|
361
|
+
<div class="container">
|
|
362
|
+
<div class="header">
|
|
363
|
+
<h1>📸 Relatório de Evidências TestHUB</h1>
|
|
364
|
+
<p>Documentação visual completa dos testes executados</p>
|
|
365
|
+
<div class="header-buttons">
|
|
366
|
+
<button onclick="toggleTheme()" class="btn btn-theme">🌙 Alternar Tema</button>
|
|
367
|
+
<button onclick="generatePDF()" class="btn">📄 Gerar PDF</button>
|
|
368
|
+
<button onclick="printPage()" class="btn">🖨️ Imprimir</button>
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<!-- Estatísticas Resumidas -->
|
|
373
|
+
<div class="summary-stats">
|
|
374
|
+
<div class="summary-card">
|
|
375
|
+
<div class="summary-number summary-tests">${totalTests}</div>
|
|
376
|
+
<div class="summary-label">Testes com Evidências</div>
|
|
377
|
+
</div>
|
|
378
|
+
<div class="summary-card">
|
|
379
|
+
<div class="summary-number summary-actions">${totalActions}</div>
|
|
380
|
+
<div class="summary-label">Total de Ações</div>
|
|
381
|
+
</div>
|
|
382
|
+
<div class="summary-card">
|
|
383
|
+
<div class="summary-number summary-success">${successActions}</div>
|
|
384
|
+
<div class="summary-label">Ações Bem-sucedidas</div>
|
|
385
|
+
</div>
|
|
386
|
+
<div class="summary-card">
|
|
387
|
+
<div class="summary-number summary-failed">${failedActions}</div>
|
|
388
|
+
<div class="summary-label">Ações com Falha</div>
|
|
389
|
+
</div>
|
|
390
|
+
<div class="summary-card">
|
|
391
|
+
<div class="summary-number" style="color: ${Number.parseFloat(successRate) >= 80 ? '#10b981' : Number.parseFloat(successRate) >= 60 ? '#f59e0b' : '#ef4444'}">${successRate}%</div>
|
|
392
|
+
<div class="summary-label">Taxa de Sucesso</div>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<!-- Agrupamento por Tipo de Teste -->
|
|
397
|
+
${Object.entries(groupedEvidence)
|
|
398
|
+
.map(([testType, evidences]) => `
|
|
399
|
+
<div class="type-group">
|
|
400
|
+
<div class="type-header">
|
|
401
|
+
<div class="type-title">
|
|
402
|
+
${EvidenceCapture.getTypeIcon(testType)} ${testType}
|
|
403
|
+
<span style="font-size: 0.8rem; color: #9ca3af;">(${evidences.length} teste${evidences.length > 1 ? 's' : ''})</span>
|
|
404
|
+
</div>
|
|
405
|
+
<div class="type-stats">
|
|
406
|
+
<div class="stat-item stat-total">
|
|
407
|
+
📊 ${evidences.reduce((sum, e) => sum + e.totalActions, 0)} ações
|
|
408
|
+
</div>
|
|
409
|
+
<div class="stat-item stat-success">
|
|
410
|
+
✅ ${evidences.reduce((sum, e) => sum + e.successActions, 0)} sucessos
|
|
411
|
+
</div>
|
|
412
|
+
<div class="stat-item stat-failed">
|
|
413
|
+
❌ ${evidences.reduce((sum, e) => sum + e.failedActions, 0)} falhas
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
<div class="tests-grid">
|
|
419
|
+
${evidences
|
|
420
|
+
.map((evidence) => `
|
|
421
|
+
<div class="test-card">
|
|
422
|
+
<div class="test-card-header collapsible" onclick="toggleTestContent('${evidence.testName.replace(/[^a-zA-Z0-9]/g, '_')}')">
|
|
423
|
+
<div class="test-title">
|
|
424
|
+
🧪 ${evidence.testName}
|
|
425
|
+
<span id="toggle-${evidence.testName.replace(/[^a-zA-Z0-9]/g, '_')}" style="float: right;">📋</span>
|
|
426
|
+
</div>
|
|
427
|
+
<div class="test-meta">
|
|
428
|
+
<div class="test-meta-item">
|
|
429
|
+
<strong>Início:</strong><br>${evidence.startTime.toLocaleString('pt-BR')}
|
|
430
|
+
</div>
|
|
431
|
+
<div class="test-meta-item">
|
|
432
|
+
<strong>Fim:</strong><br>${evidence.endTime?.toLocaleString('pt-BR') || 'Em execução'}
|
|
433
|
+
</div>
|
|
434
|
+
<div class="test-meta-item">
|
|
435
|
+
<strong>Total de Ações:</strong><br><span class="stat-total">${evidence.totalActions}</span>
|
|
436
|
+
</div>
|
|
437
|
+
<div class="test-meta-item">
|
|
438
|
+
<strong>Taxa de Sucesso:</strong><br>
|
|
439
|
+
<span style="color: ${((evidence.successActions / evidence.totalActions) * 100) >= 80 ? '#10b981' : '#f59e0b'}">
|
|
440
|
+
${((evidence.successActions / evidence.totalActions) * 100).toFixed(1)}%
|
|
441
|
+
</span>
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
|
|
446
|
+
<div id="content-${evidence.testName.replace(/[^a-zA-Z0-9]/g, '_')}" class="actions-container content" style="display: none;">
|
|
447
|
+
${evidence.items
|
|
448
|
+
.map((item, index) => `
|
|
449
|
+
<div class="action-item">
|
|
450
|
+
<div class="action-header">
|
|
451
|
+
<div class="action-title">
|
|
452
|
+
<span style="color: #9ca3af; font-size: 0.8rem; margin-right: 0.5rem;">#${index + 1}</span>
|
|
453
|
+
🎯 ${item.action}
|
|
454
|
+
</div>
|
|
455
|
+
<div class="action-time">${item.timestamp.toLocaleTimeString('pt-BR')}</div>
|
|
456
|
+
<div class="action-status ${item.success ? 'status-success' : 'status-failed'}">
|
|
457
|
+
${item.success ? '✅' : '❌'}
|
|
458
|
+
</div>
|
|
459
|
+
</div>
|
|
460
|
+
<div class="action-description">${item.description}</div>
|
|
461
|
+
<div class="screenshot-container">
|
|
462
|
+
${item.screenshotPath
|
|
463
|
+
? `<img src="${item.screenshotPath}" alt="Screenshot da ação ${item.action}" class="screenshot" onclick="openImageModal('${item.screenshotPath}')">`
|
|
464
|
+
: `<div class="no-screenshot">📷 Screenshot não disponível para esta ação</div>`}
|
|
465
|
+
</div>
|
|
466
|
+
</div>
|
|
467
|
+
`)
|
|
468
|
+
.join('')}
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
`)
|
|
472
|
+
.join('')}
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
`)
|
|
476
|
+
.join('')}
|
|
477
|
+
</div>
|
|
478
|
+
|
|
479
|
+
<!-- Modal para visualização de imagem -->
|
|
480
|
+
<div id="imageModal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9);" onclick="closeImageModal()">
|
|
481
|
+
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 90%; max-height: 90%;">
|
|
482
|
+
<img id="modalImage" style="max-width: 100%; max-height: 100%; border-radius: 0.5rem;">
|
|
483
|
+
</div>
|
|
484
|
+
<span style="position: absolute; top: 15px; right: 35px; color: #f1f5f9; font-size: 40px; font-weight: bold; cursor: pointer;" onclick="closeImageModal()">×</span>
|
|
485
|
+
</div>
|
|
486
|
+
|
|
487
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
|
488
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
|
489
|
+
<script>
|
|
490
|
+
function toggleTheme() {
|
|
491
|
+
document.getElementById('body-root').classList.toggle('light-mode')
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function toggleTestContent(testId) {
|
|
495
|
+
const content = document.getElementById('content-' + testId)
|
|
496
|
+
const toggle = document.getElementById('toggle-' + testId)
|
|
497
|
+
|
|
498
|
+
if (content.style.display === 'none') {
|
|
499
|
+
content.style.display = 'block'
|
|
500
|
+
toggle.innerHTML = '📋 ▲'
|
|
501
|
+
} else {
|
|
502
|
+
content.style.display = 'none'
|
|
503
|
+
toggle.innerHTML = '📋'
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function openImageModal(imageSrc) {
|
|
508
|
+
document.getElementById('modalImage').src = imageSrc
|
|
509
|
+
document.getElementById('imageModal').style.display = 'block'
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function closeImageModal() {
|
|
513
|
+
document.getElementById('imageModal').style.display = 'none'
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
async function generatePDF() {
|
|
517
|
+
const element = document.body;
|
|
518
|
+
|
|
519
|
+
// Aplicar estilos para PDF
|
|
520
|
+
const originalBg = element.style.background;
|
|
521
|
+
const originalColor = element.style.color;
|
|
522
|
+
element.style.background = 'white';
|
|
523
|
+
element.style.color = 'black';
|
|
524
|
+
|
|
525
|
+
try {
|
|
526
|
+
// Usar html2canvas para capturar o conteúdo
|
|
527
|
+
const canvas = await html2canvas(element, {
|
|
528
|
+
scale: 1.5,
|
|
529
|
+
useCORS: false,
|
|
530
|
+
allowTaint: true,
|
|
531
|
+
backgroundColor: '#fff'
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// Criar PDF com jsPDF
|
|
535
|
+
const { jsPDF } = jspdf;
|
|
536
|
+
const pdf = new jsPDF({
|
|
537
|
+
orientation: 'portrait',
|
|
538
|
+
unit: 'mm',
|
|
539
|
+
format: 'a4'
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
const imgData = canvas.toDataURL('image/jpeg', 0.98);
|
|
543
|
+
const imgWidth = 210;
|
|
544
|
+
const pageHeight = 297;
|
|
545
|
+
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
|
546
|
+
let heightLeft = imgHeight;
|
|
547
|
+
let position = 0;
|
|
548
|
+
|
|
549
|
+
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
|
550
|
+
heightLeft -= pageHeight;
|
|
551
|
+
|
|
552
|
+
while (heightLeft > 0) {
|
|
553
|
+
position = heightLeft - imgHeight;
|
|
554
|
+
pdf.addPage();
|
|
555
|
+
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
|
556
|
+
heightLeft -= pageHeight;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
pdf.save('evidencias-testhub-' + new Date().toISOString().split('T')[0] + '.pdf');
|
|
560
|
+
} catch (error) {
|
|
561
|
+
console.error('Erro ao gerar PDF:', error);
|
|
562
|
+
alert('Erro ao gerar PDF: ' + error.message);
|
|
563
|
+
} finally {
|
|
564
|
+
// Restaurar estilos originais
|
|
565
|
+
element.style.background = originalBg;
|
|
566
|
+
element.style.color = originalColor;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function printPage() {
|
|
571
|
+
window.print();
|
|
572
|
+
}
|
|
573
|
+
</script>
|
|
574
|
+
</body>
|
|
575
|
+
</html>`;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* ✅ Obter ícone do tipo de teste
|
|
579
|
+
*/
|
|
580
|
+
static getTypeIcon(testType) {
|
|
581
|
+
const icons = {
|
|
582
|
+
API: '🌐',
|
|
583
|
+
Frontend: '💻',
|
|
584
|
+
Mobile: '📱',
|
|
585
|
+
SSH: '🔧',
|
|
586
|
+
Banco: '🗃️',
|
|
587
|
+
Geral: '📋',
|
|
588
|
+
};
|
|
589
|
+
return icons[testType] || '📋';
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* ✅ Limpa evidências antigas
|
|
593
|
+
*/
|
|
594
|
+
static cleanup() {
|
|
595
|
+
EvidenceCapture.evidenceByTest.clear();
|
|
596
|
+
EvidenceCapture.currentEvidenceId = 0;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
// ✅ Auto-inicialização
|
|
600
|
+
EvidenceCapture.initialize();
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 📸 Organizador de Evidências do AutoCore
|
|
3
|
+
* @description Coleta e organiza screenshots já gerados pelos projetos consumidores (Web/Mobile)
|
|
4
|
+
* @author TestHUB Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ IMPORTANTE: Este projeto AutoCore NÃO gera evidências
|
|
8
|
+
* Ele apenas coleta e organiza evidências dos projetos consumidores:
|
|
9
|
+
* - Web: C:\Users\{user}\PlayWright\test-simplifique-e2e\test-results\web-screenshots\
|
|
10
|
+
* - Mobile: C:\Users\{user}\PlayWright\mobile\test-results\mobile-screenshots\
|
|
11
|
+
*/
|
|
12
|
+
export interface EvidenceScreenshot {
|
|
13
|
+
fileName: string;
|
|
14
|
+
fullPath: string;
|
|
15
|
+
relativePath: string;
|
|
16
|
+
testName: string;
|
|
17
|
+
timestamp: Date;
|
|
18
|
+
size: number;
|
|
19
|
+
base64?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare class EvidenceReportGenerator {
|
|
22
|
+
/**
|
|
23
|
+
* 🎯 Detectar o tipo do projeto atual baseado nas pastas de evidências
|
|
24
|
+
*
|
|
25
|
+
* ℹ️ AutoCore trabalha no projeto atual e verifica se há:
|
|
26
|
+
* - Web: test-results/web-screenshots/
|
|
27
|
+
* - Mobile: test-results/mobile-screenshots/
|
|
28
|
+
*/
|
|
29
|
+
private static detectCurrentProjectType;
|
|
30
|
+
/**
|
|
31
|
+
* 🔍 Coleta screenshots em uma pasta específica do projeto consumidor
|
|
32
|
+
*/
|
|
33
|
+
private static findScreenshotsInDirectory;
|
|
34
|
+
/**
|
|
35
|
+
* ✅ Gera relatório de evidências procurando screenshots nas pastas padrão
|
|
36
|
+
*/
|
|
37
|
+
static generateEvidenceReport(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* ✅ Procura screenshots em diretórios específicos
|
|
40
|
+
*/
|
|
41
|
+
private static findScreenshots;
|
|
42
|
+
/**
|
|
43
|
+
* 🆕 Converte imagem para base64
|
|
44
|
+
*/
|
|
45
|
+
private static convertImageToBase64;
|
|
46
|
+
/**
|
|
47
|
+
* ✅ Encontra arquivos recursivamente
|
|
48
|
+
*/
|
|
49
|
+
private static findFilesRecursively;
|
|
50
|
+
/**
|
|
51
|
+
* ✅ Extrai nome do teste do caminho ou nome do arquivo
|
|
52
|
+
*/
|
|
53
|
+
private static extractTestName;
|
|
54
|
+
/**
|
|
55
|
+
* ✅ Gera HTML do relatório com recursos avançados (igual HTMLTemplate)
|
|
56
|
+
*/
|
|
57
|
+
private static generateHTML;
|
|
58
|
+
/**
|
|
59
|
+
* ✅ Agrupa screenshots por teste
|
|
60
|
+
*/
|
|
61
|
+
private static groupScreenshotsByTest;
|
|
62
|
+
/**
|
|
63
|
+
* ✅ Formata tamanho de arquivo
|
|
64
|
+
*/
|
|
65
|
+
private static formatFileSize;
|
|
66
|
+
/**
|
|
67
|
+
* ✅ Gera relatório vazio quando não há evidências nos projetos consumidores
|
|
68
|
+
*/
|
|
69
|
+
private static generateEmptyReport;
|
|
70
|
+
}
|