@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,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XPath Catalog (v2.7.44 - items 17, 18, 19 & 21)
|
|
3
|
+
*
|
|
4
|
+
* Mantém catálogo de XPaths por página, atualizado via `extract_page_structure`,
|
|
5
|
+
* e oferece resolução inteligente para métodos de ação (click, fill, select…).
|
|
6
|
+
*
|
|
7
|
+
* Item 17 — `extractPageStructure` como base para catálogo
|
|
8
|
+
* Item 18 — `getCurrentXPathCatalog` + resolver interno
|
|
9
|
+
* Item 19 — Geração de `.autocore/xpaths.generated.ts` para IntelliSense
|
|
10
|
+
* Item 21 — `pushToBackend` para execuções Azure sem agente de IA
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { Logger } from './Logger.js';
|
|
15
|
+
let _extractor = null;
|
|
16
|
+
const DEFAULT_TTL_MS = 60_000;
|
|
17
|
+
/** Normaliza URL para chave de cache (remove query/hash) */
|
|
18
|
+
function normalizePageKey(url) {
|
|
19
|
+
try {
|
|
20
|
+
const u = new URL(url);
|
|
21
|
+
return `${u.origin}${u.pathname}`.replace(/\/+$/, '').toLowerCase();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return url.toLowerCase().replace(/[?#].*$/, '').replace(/\/+$/, '');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Cache interno
|
|
28
|
+
const _cache = new Map();
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// XPathCatalog
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export class XPathCatalog {
|
|
33
|
+
/** Injeta extrator de estrutura de página (obrigatório antes de usar) */
|
|
34
|
+
static setExtractor(fn) {
|
|
35
|
+
_extractor = fn;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Obtém catálogo de XPaths para a página fornecida (ou a página atual).
|
|
39
|
+
*
|
|
40
|
+
* @param currentPageUrl URL da página atual (usada quando opts.page não informado)
|
|
41
|
+
* @param opts Opções de consulta
|
|
42
|
+
*/
|
|
43
|
+
static async getCatalog(currentPageUrl, opts) {
|
|
44
|
+
const pageUrl = opts?.page || currentPageUrl;
|
|
45
|
+
const pageKey = normalizePageKey(pageUrl);
|
|
46
|
+
const strictPage = opts?.strictPage ?? true;
|
|
47
|
+
const maxItems = opts?.maxItems ?? 200;
|
|
48
|
+
// Verificar cache (se não forçar refresh)
|
|
49
|
+
if (!opts?.refresh) {
|
|
50
|
+
const cached = _cache.get(pageKey);
|
|
51
|
+
if (cached && Date.now() - cached.updatedAt < DEFAULT_TTL_MS) {
|
|
52
|
+
return XPathCatalog.applyFilter(cached.items, opts?.filter, maxItems);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Extrair estrutura da página
|
|
56
|
+
const items = await XPathCatalog.refresh(pageUrl);
|
|
57
|
+
// Filtrar
|
|
58
|
+
let result = XPathCatalog.applyFilter(items, opts?.filter, maxItems);
|
|
59
|
+
// Cross-page fallback
|
|
60
|
+
if (result.length === 0 && !strictPage && opts?.filter) {
|
|
61
|
+
for (const [, entry] of _cache) {
|
|
62
|
+
const crossItems = XPathCatalog.applyFilter(entry.items, opts.filter, maxItems);
|
|
63
|
+
if (crossItems.length > 0) {
|
|
64
|
+
result = crossItems;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Recarrega a estrutura da página e atualiza o cache.
|
|
73
|
+
*/
|
|
74
|
+
static async refresh(pageUrl) {
|
|
75
|
+
if (!_extractor) {
|
|
76
|
+
Logger.warning('[XPathCatalog] Extrator de página não configurado. Use XPathCatalog.setExtractor().');
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const raw = await _extractor(pageUrl);
|
|
80
|
+
const items = XPathCatalog.flatten(raw);
|
|
81
|
+
const key = normalizePageKey(pageUrl);
|
|
82
|
+
_cache.set(key, { items, updatedAt: Date.now() });
|
|
83
|
+
return items;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve um alvo (texto/xpath/id/name/placeholder) para o melhor XPath do catálogo.
|
|
87
|
+
* Retorna undefined se não encontrar match aceitável.
|
|
88
|
+
*/
|
|
89
|
+
static resolveFromCatalog(target, pageUrl) {
|
|
90
|
+
const key = normalizePageKey(pageUrl);
|
|
91
|
+
const cached = _cache.get(key);
|
|
92
|
+
if (!cached)
|
|
93
|
+
return undefined;
|
|
94
|
+
// Se o alvo já é um XPath válido, verificar se existe no catálogo
|
|
95
|
+
if (target.startsWith('//') || target.startsWith('(//') || target.startsWith('xpath=')) {
|
|
96
|
+
return undefined; // Não resolver XPaths explícitos via catálogo
|
|
97
|
+
}
|
|
98
|
+
// Procurar match por texto/id/name/placeholder/ariaLabel
|
|
99
|
+
const scored = XPathCatalog.applyFilter(cached.items, target, 5);
|
|
100
|
+
if (scored.length > 0 && scored[0].score && scored[0].score >= 0.6) {
|
|
101
|
+
return scored[0].xpath;
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
/** Limpa cache de uma página específica ou todo o cache */
|
|
106
|
+
static clearCache(pageUrl) {
|
|
107
|
+
if (pageUrl) {
|
|
108
|
+
_cache.delete(normalizePageKey(pageUrl));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
_cache.clear();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// ---------- Item 21 — Azure DOM push ----------
|
|
115
|
+
/**
|
|
116
|
+
* Envia DOM/pageStructure capturado localmente para o backend processar.
|
|
117
|
+
*
|
|
118
|
+
* Usado em execuções Azure/CI onde o backend **não** tem acesso de rede
|
|
119
|
+
* à página alvo. O framework captura `pageHtml` e/ou `pageStructure`
|
|
120
|
+
* e envia para `POST /api/xpath-catalog/extract`.
|
|
121
|
+
*
|
|
122
|
+
* O backend enriquece com hints Redis e retorna catálogo + xpaths.
|
|
123
|
+
* O resultado alimenta o cache local por página.
|
|
124
|
+
*
|
|
125
|
+
* @param request Payload com URL, pageHtml/pageStructure e filtro opcional
|
|
126
|
+
* @param authToken JWT ou chave de automação (header Authorization)
|
|
127
|
+
* @returns Resposta do backend com catálogo enriquecido
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const html = await page.content()
|
|
132
|
+
* const result = await XPathCatalog.pushToBackend({
|
|
133
|
+
* url: page.url(),
|
|
134
|
+
* pageHtml: html,
|
|
135
|
+
* filter: 'cliente',
|
|
136
|
+
* })
|
|
137
|
+
* if (result?.catalog) {
|
|
138
|
+
* // catálogo já está no cache; usar via getCatalog()
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
static async pushToBackend(request, authToken) {
|
|
143
|
+
const backendUrl = (process.env.AUTOCORE_HUB_URL ||
|
|
144
|
+
process.env.AUTOCORE_HUB_IP ||
|
|
145
|
+
'').replace(/\/$/, '');
|
|
146
|
+
if (!backendUrl) {
|
|
147
|
+
Logger.warning('[XPathCatalog] AUTOCORE_HUB_URL não configurado; pushToBackend ignorado.');
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const headers = {
|
|
151
|
+
'Content-Type': 'application/json',
|
|
152
|
+
'x-automation-key': process.env.AUTOCORE_AUTOMATION_KEY || 'd8f3c4a9be7f29d1c6e04fa1a39c2e7bd91f57c8a3de45eb91c4f7a2d0e3b8fa',
|
|
153
|
+
};
|
|
154
|
+
if (authToken) {
|
|
155
|
+
headers['Authorization'] = authToken.startsWith('Bearer ') ? authToken : `Bearer ${authToken}`;
|
|
156
|
+
}
|
|
157
|
+
const controller = new AbortController();
|
|
158
|
+
const timeoutId = setTimeout(() => controller.abort(), 30_000);
|
|
159
|
+
try {
|
|
160
|
+
const res = await fetch(`${backendUrl}/api/xpath-catalog/extract`, {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers,
|
|
163
|
+
body: JSON.stringify(request),
|
|
164
|
+
signal: controller.signal,
|
|
165
|
+
});
|
|
166
|
+
if (!res.ok) {
|
|
167
|
+
const text = await res.text().catch(() => '');
|
|
168
|
+
Logger.warning(`[XPathCatalog] pushToBackend falhou: HTTP ${res.status} — ${text}`);
|
|
169
|
+
return { success: false, error: `HTTP ${res.status}` };
|
|
170
|
+
}
|
|
171
|
+
const data = (await res.json());
|
|
172
|
+
// Alimentar cache local com catálogo retornado
|
|
173
|
+
if (data.success && data.catalog?.length) {
|
|
174
|
+
const key = normalizePageKey(request.url);
|
|
175
|
+
_cache.set(key, { items: data.catalog, updatedAt: Date.now() });
|
|
176
|
+
Logger.info(`[XPathCatalog] pushToBackend: ${data.catalog.length} itens recebidos para ${request.url}`);
|
|
177
|
+
}
|
|
178
|
+
return data;
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
182
|
+
Logger.warning(`[XPathCatalog] pushToBackend erro: ${msg}`);
|
|
183
|
+
return { success: false, error: msg };
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// ---------- IntelliSense file generation (Item 19) ----------
|
|
190
|
+
/**
|
|
191
|
+
* Gera arquivo `.autocore/xpaths.generated.ts` com constantes tipadas por tela.
|
|
192
|
+
*
|
|
193
|
+
* @param outputDir Diretório de saída (default: `.autocore` na raiz do projeto)
|
|
194
|
+
*/
|
|
195
|
+
static generateIntelliSenseFile(outputDir) {
|
|
196
|
+
const dir = outputDir || path.resolve(process.cwd(), '.autocore');
|
|
197
|
+
const filePath = path.join(dir, 'xpaths.generated.ts');
|
|
198
|
+
if (_cache.size === 0) {
|
|
199
|
+
Logger.info('[XPathCatalog] Nenhum catálogo em cache; IntelliSense não gerado.');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const lines = [
|
|
203
|
+
'// Auto-generated by @silasfmartins/testhub XPathCatalog',
|
|
204
|
+
'// Do not edit manually — regenerated a cada extract_page_structure',
|
|
205
|
+
'',
|
|
206
|
+
];
|
|
207
|
+
for (const [pageKey, entry] of _cache) {
|
|
208
|
+
const blockName = XPathCatalog.pageKeyToConstName(pageKey);
|
|
209
|
+
lines.push(`export const ${blockName} = {`);
|
|
210
|
+
const seen = new Set();
|
|
211
|
+
for (const item of entry.items) {
|
|
212
|
+
if (!item.xpath)
|
|
213
|
+
continue;
|
|
214
|
+
const propName = XPathCatalog.itemToPropName(item);
|
|
215
|
+
if (seen.has(propName))
|
|
216
|
+
continue;
|
|
217
|
+
seen.add(propName);
|
|
218
|
+
const safeXPath = item.xpath.replace(/'/g, "\\'");
|
|
219
|
+
lines.push(` ${propName}: '${safeXPath}',`);
|
|
220
|
+
}
|
|
221
|
+
lines.push('} as const');
|
|
222
|
+
lines.push('');
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
if (!fs.existsSync(dir))
|
|
226
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
227
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
228
|
+
Logger.info(`[XPathCatalog] IntelliSense gerado: ${filePath}`);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
Logger.warning(`[XPathCatalog] Falha ao gerar IntelliSense: ${err}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// ---------- Utilitários internos ----------
|
|
235
|
+
/** Converte estrutura bruta em lista flat de XPathCatalogItem */
|
|
236
|
+
static flatten(raw) {
|
|
237
|
+
const items = [];
|
|
238
|
+
const push = (arr) => {
|
|
239
|
+
if (!arr)
|
|
240
|
+
return;
|
|
241
|
+
for (const el of arr) {
|
|
242
|
+
if (el.xpath)
|
|
243
|
+
items.push(el);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
push(raw.inputs);
|
|
247
|
+
push(raw.buttons);
|
|
248
|
+
push(raw.links);
|
|
249
|
+
push(raw.headings);
|
|
250
|
+
push(raw.elements);
|
|
251
|
+
return items;
|
|
252
|
+
}
|
|
253
|
+
/** Aplica filtro textual e ordena por relevância */
|
|
254
|
+
static applyFilter(items, filter, max) {
|
|
255
|
+
if (!filter || filter.trim() === '') {
|
|
256
|
+
return items.slice(0, max);
|
|
257
|
+
}
|
|
258
|
+
const tokens = filter.toLowerCase().split(/\s+/);
|
|
259
|
+
const scored = [];
|
|
260
|
+
for (const item of items) {
|
|
261
|
+
const haystack = [
|
|
262
|
+
item.text,
|
|
263
|
+
item.id,
|
|
264
|
+
item.name,
|
|
265
|
+
item.placeholder,
|
|
266
|
+
item.ariaLabel,
|
|
267
|
+
item.title,
|
|
268
|
+
item.role,
|
|
269
|
+
item.dataTestId,
|
|
270
|
+
item.className,
|
|
271
|
+
item.tag,
|
|
272
|
+
]
|
|
273
|
+
.filter(Boolean)
|
|
274
|
+
.join(' ')
|
|
275
|
+
.toLowerCase();
|
|
276
|
+
let matched = 0;
|
|
277
|
+
for (const t of tokens) {
|
|
278
|
+
if (haystack.includes(t))
|
|
279
|
+
matched++;
|
|
280
|
+
}
|
|
281
|
+
if (matched > 0) {
|
|
282
|
+
const score = matched / tokens.length;
|
|
283
|
+
scored.push({ ...item, score });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Ordenar: maior score primeiro; em empate, inputs > buttons > links
|
|
287
|
+
scored.sort((a, b) => {
|
|
288
|
+
const sa = a.score ?? 0;
|
|
289
|
+
const sb = b.score ?? 0;
|
|
290
|
+
if (sb !== sa)
|
|
291
|
+
return sb - sa;
|
|
292
|
+
return tagPriority(a.tag) - tagPriority(b.tag);
|
|
293
|
+
});
|
|
294
|
+
return scored.slice(0, max);
|
|
295
|
+
}
|
|
296
|
+
/** Converte pageKey em nome de constante TypeScript */
|
|
297
|
+
static pageKeyToConstName(pageKey) {
|
|
298
|
+
// Ex: "https://app.example.com/catalogo/ofertas" → "XPATH_CATALOGO_OFERTAS"
|
|
299
|
+
const segments = pageKey
|
|
300
|
+
.replace(/^https?:\/\/[^/]+/, '')
|
|
301
|
+
.replace(/^\//, '')
|
|
302
|
+
.split('/')
|
|
303
|
+
.filter(Boolean);
|
|
304
|
+
if (segments.length === 0)
|
|
305
|
+
return 'XPATH_HOME';
|
|
306
|
+
return ('XPATH_' +
|
|
307
|
+
segments
|
|
308
|
+
.map((s) => s
|
|
309
|
+
.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
310
|
+
.replace(/_+/g, '_')
|
|
311
|
+
.toUpperCase())
|
|
312
|
+
.join('_'));
|
|
313
|
+
}
|
|
314
|
+
/** Converte item em nome de propriedade para IntelliSense */
|
|
315
|
+
static itemToPropName(item) {
|
|
316
|
+
const tag = (item.tag || 'EL').toUpperCase();
|
|
317
|
+
const label = item.id ||
|
|
318
|
+
item.dataTestId ||
|
|
319
|
+
item.name ||
|
|
320
|
+
item.ariaLabel ||
|
|
321
|
+
item.placeholder ||
|
|
322
|
+
item.title ||
|
|
323
|
+
item.text ||
|
|
324
|
+
'';
|
|
325
|
+
const clean = label
|
|
326
|
+
.substring(0, 40)
|
|
327
|
+
.replace(/[^a-zA-Z0-9]/g, '_')
|
|
328
|
+
.replace(/_+/g, '_')
|
|
329
|
+
.replace(/^_|_$/g, '')
|
|
330
|
+
.toUpperCase();
|
|
331
|
+
return clean ? `${tag}_${clean}` : `${tag}_${Math.random().toString(36).slice(2, 6).toUpperCase()}`;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// ---------------------------------------------------------------------------
|
|
335
|
+
// Helpers
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
function tagPriority(tag) {
|
|
338
|
+
switch (tag?.toLowerCase()) {
|
|
339
|
+
case 'input':
|
|
340
|
+
case 'textarea':
|
|
341
|
+
case 'select':
|
|
342
|
+
return 0;
|
|
343
|
+
case 'button':
|
|
344
|
+
return 1;
|
|
345
|
+
case 'a':
|
|
346
|
+
return 2;
|
|
347
|
+
default:
|
|
348
|
+
return 3;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Geradores de dados para testes seguindo padrões DDD
|
|
3
|
+
* @module Utils/Generators
|
|
4
|
+
*
|
|
5
|
+
* 🎯 OBJETIVO: Generators de dados de teste padronizados
|
|
6
|
+
* - ✅ Geradores compatíveis com schemas de validação
|
|
7
|
+
* - ✅ Dados determinísticos para testes reproduzíveis
|
|
8
|
+
* - ✅ Integração com Domain Entities (TestExecution, TestReport)
|
|
9
|
+
* - ✅ Suporte a dados complexos para APIs e formulários
|
|
10
|
+
*
|
|
11
|
+
* 🏗️ ARQUITETURA DDD:
|
|
12
|
+
* - Domain Layer: Value Objects (CPF, CNPJ, Email)
|
|
13
|
+
* - Application Layer: Casos de uso específicos (generateApiTestData)
|
|
14
|
+
* - Infrastructure Layer: Implementações específicas de geradores
|
|
15
|
+
*
|
|
16
|
+
* EXEMPLO USO SIMPLES:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const id = generateRandomAlphanumeric(10)
|
|
19
|
+
* const email = generateEmail()
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* EXEMPLO USO AVANÇADO:
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const testData = generateCompleteFormData({
|
|
25
|
+
* includeOptional: true,
|
|
26
|
+
* locale: 'pt-BR'
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Gera UUID alfanumérico de tamanho específico
|
|
32
|
+
* @param length Comprimento desejado
|
|
33
|
+
* @returns String alfanumérica baseada em UUID
|
|
34
|
+
*/
|
|
35
|
+
export declare function generateRandomAlphanumericUUID(length: number): string;
|
|
36
|
+
/**
|
|
37
|
+
* Gera ID externo complexo para simulação de sistemas legados
|
|
38
|
+
* @returns ID no formato system1-system2-0xhexadecimal
|
|
39
|
+
*/
|
|
40
|
+
export declare function generateComplexExternalId(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Gera string alfanumérica aleatória
|
|
43
|
+
* @param length Comprimento desejado
|
|
44
|
+
* @returns String alfanumérica
|
|
45
|
+
*/
|
|
46
|
+
export declare function generateRandomAlphanumeric(length: number): string;
|
|
47
|
+
/**
|
|
48
|
+
* Gera string numérica aleatória
|
|
49
|
+
* @param length Comprimento desejado
|
|
50
|
+
* @returns String numérica
|
|
51
|
+
*/
|
|
52
|
+
export declare function generateRandomNumeric(length: number): string;
|
|
53
|
+
/**
|
|
54
|
+
* 🆕 DDD: Gera email válido para testes
|
|
55
|
+
* @param domain Domínio opcional (padrão: 'test.com')
|
|
56
|
+
* @returns Email válido para testes
|
|
57
|
+
*/
|
|
58
|
+
export declare function generateEmail(domain?: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* 🆕 DDD: Gera CPF válido para testes (apenas dígitos)
|
|
61
|
+
* @returns CPF válido no formato 11111111111
|
|
62
|
+
*/
|
|
63
|
+
export declare function generateCPF(): string;
|
|
64
|
+
/**
|
|
65
|
+
* 🆕 DDD: Gera telefone brasileiro válido
|
|
66
|
+
* @param withAreaCode Se deve incluir código de área
|
|
67
|
+
* @returns Telefone no formato 11999999999 ou 999999999
|
|
68
|
+
*/
|
|
69
|
+
export declare function generatePhoneBR(withAreaCode?: boolean): string;
|
|
70
|
+
/**
|
|
71
|
+
* 🆕 DDD: Gera dados completos para formulários
|
|
72
|
+
* @param options Opções de geração
|
|
73
|
+
* @returns Objeto com dados completos para teste
|
|
74
|
+
*/
|
|
75
|
+
export declare function generateCompleteFormData(options?: {
|
|
76
|
+
includeOptional?: boolean;
|
|
77
|
+
locale?: 'pt-BR' | 'en-US';
|
|
78
|
+
}): {
|
|
79
|
+
name: string;
|
|
80
|
+
email: string;
|
|
81
|
+
phone: string;
|
|
82
|
+
document: string;
|
|
83
|
+
address?: {
|
|
84
|
+
street: string;
|
|
85
|
+
number: string;
|
|
86
|
+
city: string;
|
|
87
|
+
zipCode: string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
export declare function generateServiceNowTaskId(): string;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Geradores de dados para testes seguindo padrões DDD
|
|
3
|
+
* @module Utils/Generators
|
|
4
|
+
*
|
|
5
|
+
* 🎯 OBJETIVO: Generators de dados de teste padronizados
|
|
6
|
+
* - ✅ Geradores compatíveis com schemas de validação
|
|
7
|
+
* - ✅ Dados determinísticos para testes reproduzíveis
|
|
8
|
+
* - ✅ Integração com Domain Entities (TestExecution, TestReport)
|
|
9
|
+
* - ✅ Suporte a dados complexos para APIs e formulários
|
|
10
|
+
*
|
|
11
|
+
* 🏗️ ARQUITETURA DDD:
|
|
12
|
+
* - Domain Layer: Value Objects (CPF, CNPJ, Email)
|
|
13
|
+
* - Application Layer: Casos de uso específicos (generateApiTestData)
|
|
14
|
+
* - Infrastructure Layer: Implementações específicas de geradores
|
|
15
|
+
*
|
|
16
|
+
* EXEMPLO USO SIMPLES:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const id = generateRandomAlphanumeric(10)
|
|
19
|
+
* const email = generateEmail()
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* EXEMPLO USO AVANÇADO:
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const testData = generateCompleteFormData({
|
|
25
|
+
* includeOptional: true,
|
|
26
|
+
* locale: 'pt-BR'
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { randomUUID } from 'node:crypto';
|
|
31
|
+
/**
|
|
32
|
+
* Gera UUID alfanumérico de tamanho específico
|
|
33
|
+
* @param length Comprimento desejado
|
|
34
|
+
* @returns String alfanumérica baseada em UUID
|
|
35
|
+
*/
|
|
36
|
+
export function generateRandomAlphanumericUUID(length) {
|
|
37
|
+
// Gera um UUID e remove os hífens para ter mais caracteres disponíveis
|
|
38
|
+
const uuid = randomUUID().replace(/-/g, '');
|
|
39
|
+
// Se o comprimento solicitado for maior que o UUID disponível,
|
|
40
|
+
// repete o processo até ter caracteres suficientes
|
|
41
|
+
let result = uuid;
|
|
42
|
+
while (result.length < length) {
|
|
43
|
+
result += randomUUID().replace(/-/g, '');
|
|
44
|
+
}
|
|
45
|
+
// Retorna apenas a quantidade de caracteres solicitada
|
|
46
|
+
return result.substring(0, length);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Gera ID externo complexo para simulação de sistemas legados
|
|
50
|
+
* @returns ID no formato system1-system2-0xhexadecimal
|
|
51
|
+
*/
|
|
52
|
+
export function generateComplexExternalId() {
|
|
53
|
+
const hex = 'abcdef0123456789';
|
|
54
|
+
const randomHex = (length) => Array.from({ length }, () => hex[Math.floor(Math.random() * hex.length)]).join('');
|
|
55
|
+
const part1 = randomHex(32);
|
|
56
|
+
const part2 = randomHex(32);
|
|
57
|
+
const part3 = '0x' +
|
|
58
|
+
randomHex(30) +
|
|
59
|
+
String.fromCharCode(97 + Math.floor(Math.random() * 26)); // adiciona uma letra no final
|
|
60
|
+
return `${part1}-${part2}${part3}`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gera string alfanumérica aleatória
|
|
64
|
+
* @param length Comprimento desejado
|
|
65
|
+
* @returns String alfanumérica
|
|
66
|
+
*/
|
|
67
|
+
export function generateRandomAlphanumeric(length) {
|
|
68
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
69
|
+
let result = '';
|
|
70
|
+
for (let i = 0; i < length; i++) {
|
|
71
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Gera string numérica aleatória
|
|
77
|
+
* @param length Comprimento desejado
|
|
78
|
+
* @returns String numérica
|
|
79
|
+
*/
|
|
80
|
+
export function generateRandomNumeric(length) {
|
|
81
|
+
const digits = '0123456789';
|
|
82
|
+
let result = '';
|
|
83
|
+
for (let i = 0; i < length; i++) {
|
|
84
|
+
result += digits.charAt(Math.floor(Math.random() * digits.length));
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 🆕 DDD: Gera email válido para testes
|
|
90
|
+
* @param domain Domínio opcional (padrão: 'test.com')
|
|
91
|
+
* @returns Email válido para testes
|
|
92
|
+
*/
|
|
93
|
+
export function generateEmail(domain = 'test.com') {
|
|
94
|
+
const username = generateRandomAlphanumeric(8).toLowerCase();
|
|
95
|
+
return `${username}@${domain}`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 🆕 DDD: Gera CPF válido para testes (apenas dígitos)
|
|
99
|
+
* @returns CPF válido no formato 11111111111
|
|
100
|
+
*/
|
|
101
|
+
export function generateCPF() {
|
|
102
|
+
// Gera os 9 primeiros dígitos
|
|
103
|
+
const nineDegits = Array.from({ length: 9 }, () => Math.floor(Math.random() * 10));
|
|
104
|
+
// Calcula o primeiro dígito verificador
|
|
105
|
+
let sum = 0;
|
|
106
|
+
for (let i = 0; i < 9; i++) {
|
|
107
|
+
sum += nineDegits[i] * (10 - i);
|
|
108
|
+
}
|
|
109
|
+
const firstDigit = (sum * 10) % 11;
|
|
110
|
+
const firstVerifier = firstDigit < 10 ? firstDigit : 0;
|
|
111
|
+
// Calcula o segundo dígito verificador
|
|
112
|
+
sum = 0;
|
|
113
|
+
for (let i = 0; i < 9; i++) {
|
|
114
|
+
sum += nineDegits[i] * (11 - i);
|
|
115
|
+
}
|
|
116
|
+
sum += firstVerifier * 2;
|
|
117
|
+
const secondDigit = (sum * 10) % 11;
|
|
118
|
+
const secondVerifier = secondDigit < 10 ? secondDigit : 0;
|
|
119
|
+
return [...nineDegits, firstVerifier, secondVerifier].join('');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 🆕 DDD: Gera telefone brasileiro válido
|
|
123
|
+
* @param withAreaCode Se deve incluir código de área
|
|
124
|
+
* @returns Telefone no formato 11999999999 ou 999999999
|
|
125
|
+
*/
|
|
126
|
+
export function generatePhoneBR(withAreaCode = true) {
|
|
127
|
+
const areaCode = withAreaCode ? generateRandomNumeric(2) : '';
|
|
128
|
+
const firstDigit = '9'; // Celular sempre inicia com 9
|
|
129
|
+
const restDigits = generateRandomNumeric(8);
|
|
130
|
+
return `${areaCode}${firstDigit}${restDigits}`;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 🆕 DDD: Gera dados completos para formulários
|
|
134
|
+
* @param options Opções de geração
|
|
135
|
+
* @returns Objeto com dados completos para teste
|
|
136
|
+
*/
|
|
137
|
+
export function generateCompleteFormData(options) {
|
|
138
|
+
const locale = options?.locale || 'pt-BR';
|
|
139
|
+
const includeOptional = options?.includeOptional;
|
|
140
|
+
const data = {
|
|
141
|
+
name: `Test User ${generateRandomAlphanumeric(4)}`,
|
|
142
|
+
email: generateEmail(),
|
|
143
|
+
phone: locale === 'pt-BR' ? generatePhoneBR() : generateRandomNumeric(10),
|
|
144
|
+
document: locale === 'pt-BR' ? generateCPF() : generateRandomNumeric(9),
|
|
145
|
+
};
|
|
146
|
+
if (includeOptional) {
|
|
147
|
+
return {
|
|
148
|
+
...data,
|
|
149
|
+
address: {
|
|
150
|
+
street: `Test Street ${generateRandomAlphanumeric(3)}`,
|
|
151
|
+
number: generateRandomNumeric(3),
|
|
152
|
+
city: 'Test City',
|
|
153
|
+
zipCode: locale === 'pt-BR'
|
|
154
|
+
? generateRandomNumeric(8)
|
|
155
|
+
: generateRandomNumeric(5),
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
export function generateServiceNowTaskId() {
|
|
162
|
+
const hex = 'abcdef0123456789';
|
|
163
|
+
const randomHex = (length) => Array.from({ length }, () => hex[Math.floor(Math.random() * hex.length)]).join('');
|
|
164
|
+
const part1 = randomHex(32);
|
|
165
|
+
const part2 = randomHex(31);
|
|
166
|
+
return `${part1}x${part2}`;
|
|
167
|
+
}
|