@silasfmartins/testhub 1.0.1 → 1.0.3

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.
@@ -242,7 +242,6 @@ async function installMcpPackageGlobally() {
242
242
  console.log("🆕 MCP não encontrado globalmente");
243
243
  }
244
244
  // 2️⃣ Verificar acesso ao registry e obter última versão
245
- console.log("🔍 Verificando registry Azure Artifacts...");
246
245
  const latestVersion = await checkRegistryAccess();
247
246
  if (!latestVersion) {
248
247
  console.log("🔒 Sem acesso ao registry Azure Artifacts (modo offline)");
@@ -159,7 +159,7 @@ function checkGlobalMcpPackage() {
159
159
  // ✅ Instalar ou atualizar pacote MCP globalmente
160
160
  // 🎯 COMPORTAMENTO:
161
161
  // - Se já está na última versão: NÃO reinstala
162
- // - Se versão antiga: atualiza automaticamente
162
+ // - Se versão antiga: atualiza automaticamente
163
163
  // - Se não instalado: instala globalmente
164
164
  // - Se offline: usa versão local existente
165
165
  function installOrUpdateMcpPackage() {
@@ -174,7 +174,6 @@ function installOrUpdateMcpPackage() {
174
174
  console.log('AutoCore: MCP não encontrado globalmente');
175
175
  }
176
176
  // Verificar acesso ao registry e obter última versão
177
- console.log('AutoCore: Verificando registry Azure Artifacts...');
178
177
  const latestVersion = checkRegistryAndGetLatestVersion();
179
178
  if (!latestVersion) {
180
179
  console.log('AutoCore: Sem acesso ao registry Azure Artifacts (modo offline)');
@@ -986,7 +986,10 @@ export class WebActions {
986
986
  return await fn(initialCandidate);
987
987
  }
988
988
  // 🔄 Refresh DOM antes da primeira tentativa — garantir DOM fresco para SPAs/Shadow DOM
989
- await WebActions.refreshDOM(150).catch(() => { });
989
+ // 🛡️ Pular refreshDOM se já estiver em contexto de recovery (evitar overhead desnecessário)
990
+ if (WebActions._recoveryDepth <= 0) {
991
+ await WebActions.refreshDOM(150).catch(() => { });
992
+ }
990
993
  // 🎯 Catalog pre-resolve + lazy auto-refresh (Item 18/20 v2.7.44)
991
994
  // Se o target for texto/label (não XPath explícito), tentar resolver via catálogo local.
992
995
  // Na primeira ação de cada URL, popular o catálogo automaticamente.
@@ -1008,11 +1011,16 @@ export class WebActions {
1008
1011
  }
1009
1012
  catch { }
1010
1013
  }
1014
+ // 🛡️ Flag para rastrear se entramos no bloco de recovery (catch).
1015
+ // Sem essa flag, o finally decrementa _recoveryDepth mesmo em chamadas bem-sucedidas,
1016
+ // fazendo depth ficar negativo e desabilitando o guard de recursão em falhas futuras.
1017
+ let enteredRecovery = false;
1011
1018
  try {
1012
1019
  const initialCandidate = await WebActions.resolveCandidateForRecovery(originalElement);
1013
1020
  return await fn(initialCandidate);
1014
1021
  }
1015
1022
  catch (error) {
1023
+ enteredRecovery = true;
1016
1024
  // 🔄 Refresh DOM imediato após falha — capturar estado mais recente do Shadow DOM
1017
1025
  await WebActions.refreshDOM(200).catch(() => { });
1018
1026
  // 🛡️ Incrementar profundidade de recovery para evitar recursão infinita
@@ -1345,8 +1353,12 @@ export class WebActions {
1345
1353
  throw error;
1346
1354
  }
1347
1355
  finally {
1348
- // 🛡️ Decrementar profundidade de recovery independente de sucesso/falha
1349
- WebActions._recoveryDepth--;
1356
+ // 🛡️ Decrementar profundidade de recovery SOMENTE se entramos no bloco de recovery.
1357
+ // Sem essa condição, chamadas bem-sucedidas decrementam sem ter incrementado,
1358
+ // fazendo _recoveryDepth ficar negativo e desabilitando o guard de recursão.
1359
+ if (enteredRecovery) {
1360
+ WebActions._recoveryDepth--;
1361
+ }
1350
1362
  }
1351
1363
  }
1352
1364
  // Helper genérico para tentar heurísticas de preenchimento/atribuição de valor
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silasfmartins/testhub",
3
3
  "description": "Biblioteca de utilitários para automação de testes",
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "author": "Silas Martins Feliciano da Silva <silas.martins2041@gmail.com>",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -106,7 +106,7 @@
106
106
  "cross-env": "^10.1.0",
107
107
  "esbuild": "^0.27.4",
108
108
  "typescript": "^5.9.3",
109
- "ultracite": "7.3.1",
109
+ "ultracite": "7.3.2",
110
110
  "undici": "^7.24.4",
111
111
  "vitest": "4.1.0"
112
112
  },
@@ -289,7 +289,6 @@ async function installMcpPackageGlobally(): Promise<boolean> {
289
289
  }
290
290
 
291
291
  // 2️⃣ Verificar acesso ao registry e obter última versão
292
- console.log("🔍 Verificando registry Azure Artifacts...");
293
292
  const latestVersion = await checkRegistryAccess();
294
293
 
295
294
  if (!latestVersion) {
@@ -183,14 +183,14 @@ function checkGlobalMcpPackage(): boolean {
183
183
  // ✅ Instalar ou atualizar pacote MCP globalmente
184
184
  // 🎯 COMPORTAMENTO:
185
185
  // - Se já está na última versão: NÃO reinstala
186
- // - Se versão antiga: atualiza automaticamente
186
+ // - Se versão antiga: atualiza automaticamente
187
187
  // - Se não instalado: instala globalmente
188
188
  // - Se offline: usa versão local existente
189
189
  function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; version: string | null } {
190
190
  console.log('AutoCore: ======================================================')
191
191
  console.log('AutoCore: MCP - Verificando instalação global')
192
192
  console.log('AutoCore: ======================================================')
193
-
193
+
194
194
  const installedVersion = getInstalledMcpVersion()
195
195
 
196
196
  if (installedVersion) {
@@ -198,11 +198,10 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
198
198
  } else {
199
199
  console.log('AutoCore: MCP não encontrado globalmente')
200
200
  }
201
-
201
+
202
202
  // Verificar acesso ao registry e obter última versão
203
- console.log('AutoCore: Verificando registry Azure Artifacts...')
204
203
  const latestVersion = checkRegistryAndGetLatestVersion()
205
-
204
+
206
205
  if (!latestVersion) {
207
206
  console.log('AutoCore: Sem acesso ao registry Azure Artifacts (modo offline)')
208
207
  if (installedVersion) {
@@ -212,28 +211,28 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
212
211
  console.log('AutoCore: MCP será executado via npx quando necessário')
213
212
  return { installed: false, updated: false, version: null }
214
213
  }
215
-
214
+
216
215
  console.log(`AutoCore: Última versão disponível: ${latestVersion}`)
217
-
216
+
218
217
  // Comparar versões se já instalado
219
218
  if (installedVersion) {
220
219
  if (installedVersion === latestVersion) {
221
220
  console.log('AutoCore: MCP já está na última versão global - nada a fazer! ✓')
222
221
  return { installed: true, updated: false, version: installedVersion }
223
222
  }
224
-
223
+
225
224
  // Versão desatualizada - atualizar
226
225
  console.log(`AutoCore: Atualizando MCP: ${installedVersion} → ${latestVersion}`)
227
226
  } else {
228
227
  console.log('AutoCore: Instalando MCP globalmente...')
229
228
  }
230
-
229
+
231
230
  // Executar instalação/atualização
232
231
  const installResult = execNpmSync(
233
232
  ['install', '-g', `@silasfmartins/autocore-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`],
234
233
  60000
235
234
  )
236
-
235
+
237
236
  if (installResult.status === 0) {
238
237
  const newVersion = getInstalledMcpVersion()
239
238
  if (installedVersion) {
@@ -244,13 +243,13 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
244
243
  console.log('AutoCore: Disponível para todos os projetos da máquina')
245
244
  return { installed: true, updated: !!installedVersion, version: newVersion || latestVersion }
246
245
  }
247
-
246
+
248
247
  console.warn('AutoCore: Falha ao instalar/atualizar MCP')
249
248
  if (installedVersion) {
250
249
  console.log(`AutoCore: Usando versão global existente: ${installedVersion}`)
251
250
  return { installed: true, updated: false, version: installedVersion }
252
251
  }
253
-
252
+
254
253
  console.log('AutoCore: MCP será executado via npx')
255
254
  return { installed: false, updated: false, version: null }
256
255
  }
@@ -265,12 +264,12 @@ function extractUserHash(url: string): string {
265
264
  async function copyCopilotInstructions(): Promise<void> {
266
265
  try {
267
266
  const cwd = process.cwd()
268
-
267
+
269
268
  // Se estiver em dist/scripts, subir dois níveis; senão, um nível
270
269
  const isDist = __dirname.includes('dist')
271
270
  const levelsUp = isDist ? '../..' : '..'
272
271
  const sourceFile = path.join(__dirname, levelsUp, '.github', 'copilot-instructions.md')
273
-
272
+
274
273
  const targetDir = path.join(cwd, '.github')
275
274
  const targetFile = path.join(targetDir, 'copilot-instructions.md')
276
275
 
@@ -357,7 +356,7 @@ async function ensureMcpConfig(): Promise<void> {
357
356
  if (existsSync(mcpFile)) {
358
357
  // Arquivo existe - preservar hashes do usuário
359
358
  const currentContent = JSON.parse(readFileSync(mcpFile, 'utf8'))
360
-
359
+
361
360
  // Preservar hash do mcp-estimative
362
361
  let existingEstimativeHash = ''
363
362
  if (currentContent.servers?.['mcp-estimative']?.url) {
@@ -384,7 +383,7 @@ async function ensureMcpConfig(): Promise<void> {
384
383
  }
385
384
 
386
385
  writeFileSync(mcpFile, JSON.stringify(updatedConfig, null, 2))
387
-
386
+
388
387
  if (existingEstimativeHash) {
389
388
  console.log('AutoCore: Arquivo mcp.json atualizado (hash mcp-estimative preservado) ✓')
390
389
  } else {
@@ -413,19 +412,19 @@ async function ensurePlaywrightInstalled(): Promise<void> {
413
412
  try {
414
413
  const cwd = process.cwd()
415
414
  const pkgFile = path.join(cwd, 'package.json')
416
-
415
+
417
416
  if (!existsSync(pkgFile)) return
418
-
417
+
419
418
  const content = readFileSync(pkgFile, 'utf8')
420
419
  const pkg = JSON.parse(content)
421
-
420
+
422
421
  // Verificar se é projeto Frontend ou Scenarios (tem @playwright/test nas dependências)
423
- const hasPlaywright =
424
- pkg.dependencies?.['@playwright/test'] ||
422
+ const hasPlaywright =
423
+ pkg.dependencies?.['@playwright/test'] ||
425
424
  pkg.devDependencies?.['@playwright/test'] ||
426
425
  pkg.dependencies?.['@silasfmartins/testhub'] ||
427
426
  pkg.devDependencies?.['@silasfmartins/testhub']
428
-
427
+
429
428
  // Determinar se devemos instalar browsers Playwright
430
429
  // Prioridade 1: variável de ambiente PROJECT_TYPE (WEB/FRONTEND or SCENARIOS)
431
430
  const projectTypeEnv = (process.env.PROJECT_TYPE || process.env.PROJECTTYPE || '').toUpperCase()
@@ -439,7 +438,7 @@ async function ensurePlaywrightInstalled(): Promise<void> {
439
438
 
440
439
  // Só instalar se o projeto for Web/Frontend ou Scenarios (por env ou por scripts indicativos)
441
440
  if (!hasPlaywright || !(isProjectTypeWebOrScenarios || hasFrontendScripts)) return
442
-
441
+
443
442
  // Verificar se os browsers já estão instalados em vários locais comuns
444
443
  function browsersPresent(dir: string): boolean {
445
444
  try {