@silasfmartins/testhub 1.0.0 → 1.0.2
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 +1 -1
- package/dist/scripts/consumer-postinstall.js +13 -14
- package/dist/scripts/init-api.js +10 -12
- package/dist/scripts/init-banco.js +19 -21
- package/dist/scripts/init-frontend.js +1 -3
- package/dist/scripts/init-mobile.js +0 -2
- package/dist/scripts/init-scenarios.js +15 -17
- package/dist/scripts/init-ssh.js +0 -2
- package/dist/scripts/postinstall.js +10 -11
- package/dist/src/playwright/WebActions.js +15 -3
- package/dist/src/utils/McpLocalClient.js +2 -2
- package/package.json +2 -2
- package/scripts/consumer-postinstall.ts +13 -14
- package/scripts/init-api.ts +10 -16
- package/scripts/init-banco.ts +19 -25
- package/scripts/init-frontend.ts +1 -7
- package/scripts/init-mobile.ts +0 -6
- package/scripts/init-scenarios.ts +15 -21
- package/scripts/init-ssh.ts +0 -6
- package/scripts/postinstall.ts +31 -32
|
@@ -80,7 +80,7 @@ Nao documenta detalhes do **Portal/UI** nem changelog por versao. Para isso, use
|
|
|
80
80
|
- `McpLocalClient` deve tentar iniciar STDIO automaticamente em ordem:
|
|
81
81
|
1. `HUB_MCP_STDIO_BIN` (quando definido),
|
|
82
82
|
2. `autocore-hub-mcp` global,
|
|
83
|
-
3. `npx -y @silasfmartins/
|
|
83
|
+
3. `npx -y @silasfmartins/autocore-orchestrator-mcp --stdio`.
|
|
84
84
|
- Em `tools/list`, expor somente `codegen`; manter `playwright_execute` apenas como alias de compatibilidade em `tools/call` (sem aparecer na listagem).
|
|
85
85
|
- No `consumer-postinstall` do framework (Windows local), configurar AutoStart do MCP automaticamente apos a instalacao:
|
|
86
86
|
- usar Startup do usuario (`%APPDATA%\\...\\Startup`) sem depender de Task Scheduler,
|
|
@@ -118,7 +118,7 @@ function isExtensionInstalled(extensionId) {
|
|
|
118
118
|
}
|
|
119
119
|
// 🌐 Registry privado do Azure Artifacts (único registry para pacotes @rbqa)
|
|
120
120
|
const AZURE_REGISTRY = "https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/";
|
|
121
|
-
const WINDOWS_MCP_AUTOSTART_START_COMMAND = "npx -y @silasfmartins/
|
|
121
|
+
const WINDOWS_MCP_AUTOSTART_START_COMMAND = "npx -y @silasfmartins/autocore-orchestrator-mcp";
|
|
122
122
|
const WINDOWS_MCP_STARTUP_SCRIPT_FILE = "autocore-orchestrator-mcp.cmd";
|
|
123
123
|
const WINDOWS_MCP_STARTUP_VBS_FILE = "autocore-orchestrator-mcp.vbs";
|
|
124
124
|
/**
|
|
@@ -157,11 +157,11 @@ async function execNpmCommand(command, timeoutMs = 30000) {
|
|
|
157
157
|
*/
|
|
158
158
|
async function getInstalledMcpVersion() {
|
|
159
159
|
try {
|
|
160
|
-
const result = await execNpmCommand("npm list -g @silasfmartins/
|
|
160
|
+
const result = await execNpmCommand("npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0 --json");
|
|
161
161
|
if (!result)
|
|
162
162
|
return null;
|
|
163
163
|
const data = JSON.parse(result.stdout);
|
|
164
|
-
return (data.dependencies?.["@silasfmartins/
|
|
164
|
+
return (data.dependencies?.["@silasfmartins/autocore-orchestrator-mcp"]?.version || null);
|
|
165
165
|
}
|
|
166
166
|
catch {
|
|
167
167
|
return null;
|
|
@@ -173,7 +173,7 @@ async function getInstalledMcpVersion() {
|
|
|
173
173
|
*/
|
|
174
174
|
async function getLatestMcpVersion() {
|
|
175
175
|
try {
|
|
176
|
-
const result = await execNpmCommand(`npm view @silasfmartins/
|
|
176
|
+
const result = await execNpmCommand(`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
|
|
177
177
|
if (!result)
|
|
178
178
|
return null;
|
|
179
179
|
return result.stdout.trim() || null;
|
|
@@ -183,13 +183,13 @@ async function getLatestMcpVersion() {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
/**
|
|
186
|
-
* 🔍 Verifica se o pacote @silasfmartins/
|
|
186
|
+
* 🔍 Verifica se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
|
|
187
187
|
*/
|
|
188
188
|
async function isMcpPackageInstalled() {
|
|
189
189
|
try {
|
|
190
|
-
const result = await execNpmCommand("npm list -g @silasfmartins/
|
|
190
|
+
const result = await execNpmCommand("npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0");
|
|
191
191
|
return result
|
|
192
|
-
? result.stdout.includes("@silasfmartins/
|
|
192
|
+
? result.stdout.includes("@silasfmartins/autocore-orchestrator-mcp")
|
|
193
193
|
: false;
|
|
194
194
|
}
|
|
195
195
|
catch {
|
|
@@ -203,7 +203,7 @@ async function isMcpPackageInstalled() {
|
|
|
203
203
|
async function checkRegistryAccess() {
|
|
204
204
|
try {
|
|
205
205
|
// Tenta obter a versão do pacote no Azure Artifacts
|
|
206
|
-
const result = await execNpmCommand(`npm view @silasfmartins/
|
|
206
|
+
const result = await execNpmCommand(`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
|
|
207
207
|
if (result && result.stdout.trim()) {
|
|
208
208
|
return result.stdout.trim();
|
|
209
209
|
}
|
|
@@ -214,7 +214,7 @@ async function checkRegistryAccess() {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
|
-
* 📦 Instala ou atualiza o pacote @silasfmartins/
|
|
217
|
+
* 📦 Instala ou atualiza o pacote @silasfmartins/autocore-orchestrator-mcp globalmente
|
|
218
218
|
*
|
|
219
219
|
* 🎯 COMPORTAMENTO:
|
|
220
220
|
* - Se já está na última versão: NÃO reinstala (economia de tempo)
|
|
@@ -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)");
|
|
@@ -252,7 +251,7 @@ async function installMcpPackageGlobally() {
|
|
|
252
251
|
}
|
|
253
252
|
console.log("⚠️ O MCP será executado via npx quando necessário");
|
|
254
253
|
console.log(" 💡 Conecte-se à VPN e execute:");
|
|
255
|
-
console.log(` npm install -g @silasfmartins/
|
|
254
|
+
console.log(` npm install -g @silasfmartins/autocore-orchestrator-mcp --registry=${AZURE_REGISTRY}`);
|
|
256
255
|
return false;
|
|
257
256
|
}
|
|
258
257
|
console.log(`🌐 Última versão disponível: ${latestVersion}`);
|
|
@@ -270,7 +269,7 @@ async function installMcpPackageGlobally() {
|
|
|
270
269
|
console.log("🔄 Instalando MCP globalmente...");
|
|
271
270
|
}
|
|
272
271
|
// 5️⃣ Executar instalação/atualização
|
|
273
|
-
const installResult = await execNpmCommand(`npm install -g @silasfmartins/
|
|
272
|
+
const installResult = await execNpmCommand(`npm install -g @silasfmartins/autocore-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`, 60000);
|
|
274
273
|
if (!installResult) {
|
|
275
274
|
console.log("⚠️ Falha ao instalar/atualizar MCP");
|
|
276
275
|
if (installedVersion) {
|
|
@@ -400,7 +399,7 @@ async function ensureMcpConfig() {
|
|
|
400
399
|
},
|
|
401
400
|
"autocore-orchestrator": {
|
|
402
401
|
command: "npx",
|
|
403
|
-
args: ["-y", "@silasfmartins/
|
|
402
|
+
args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
|
|
404
403
|
env: {
|
|
405
404
|
HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
|
|
406
405
|
},
|
|
@@ -426,7 +425,7 @@ async function ensureMcpConfig() {
|
|
|
426
425
|
},
|
|
427
426
|
"autocore-orchestrator": {
|
|
428
427
|
command: "npx",
|
|
429
|
-
args: ["-y", "@silasfmartins/
|
|
428
|
+
args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
|
|
430
429
|
env: {
|
|
431
430
|
HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
|
|
432
431
|
},
|
package/dist/scripts/init-api.js
CHANGED
|
@@ -61,8 +61,6 @@ export default defineConfig({
|
|
|
61
61
|
trace: 'on',
|
|
62
62
|
},
|
|
63
63
|
})`);
|
|
64
|
-
// .npmrc
|
|
65
|
-
write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
|
|
66
64
|
// .gitignore
|
|
67
65
|
write('.gitignore', `# Playwright
|
|
68
66
|
node_modules/
|
|
@@ -131,10 +129,10 @@ test.describe('API Tests - ${projectName}', () => {
|
|
|
131
129
|
test('CT001 - Exemplo de requisição API', async ({ }, testInfo: TestInfo) => {
|
|
132
130
|
TestAnnotations.Api.testInfo = testInfo
|
|
133
131
|
await TestAnnotations.setSystem('MEU_SISTEMA')
|
|
134
|
-
|
|
132
|
+
|
|
135
133
|
// Exemplo de requisição - substitua pelo seu statement
|
|
136
134
|
// await new StatementsToken().getToken()
|
|
137
|
-
|
|
135
|
+
|
|
138
136
|
// Exemplo de chamada API direta
|
|
139
137
|
await ApiActions.executeGet(
|
|
140
138
|
'Buscar dados do endpoint',
|
|
@@ -180,20 +178,20 @@ export class StatementsToken {
|
|
|
180
178
|
const VALIDATE_TOKEN = 200
|
|
181
179
|
|
|
182
180
|
const tokenResponse = await ApiActions.post(
|
|
183
|
-
new RequestToken().requestToken(),
|
|
184
|
-
"Requisição Token Sistêmico",
|
|
181
|
+
new RequestToken().requestToken(),
|
|
182
|
+
"Requisição Token Sistêmico",
|
|
185
183
|
true
|
|
186
184
|
);
|
|
187
185
|
|
|
188
186
|
ApiActions.validateEquals(
|
|
189
187
|
tokenResponse.status(),
|
|
190
|
-
VALIDATE_TOKEN,
|
|
188
|
+
VALIDATE_TOKEN,
|
|
191
189
|
"Validação do status code da requisição de token"
|
|
192
190
|
);
|
|
193
191
|
|
|
194
192
|
// Armazenar token para uso posterior
|
|
195
193
|
DataStore.set("ACCESS_TOKEN", tokenResponse.get("token"))
|
|
196
|
-
|
|
194
|
+
|
|
197
195
|
Logger.info("Token obtido e armazenado com sucesso");
|
|
198
196
|
}
|
|
199
197
|
}
|
|
@@ -205,7 +203,7 @@ import { StatementsToken } from '../src/statements/token/StatementsToken.js';
|
|
|
205
203
|
test.describe('Exemplo API Tests', () => {
|
|
206
204
|
TestAnnotations.Api.testInfo = testInfo;
|
|
207
205
|
await TestAnnotations.setSystem('MEU_SISTEMA');
|
|
208
|
-
test('Deve obter token com sucesso', async () => {
|
|
206
|
+
test('Deve obter token com sucesso', async () => {
|
|
209
207
|
// Obter token
|
|
210
208
|
await new StatementsToken().getToken()
|
|
211
209
|
});
|
|
@@ -364,12 +362,12 @@ import { type TestInfo, test, TestAnnotations } from '@silasfmartins/testhub'
|
|
|
364
362
|
|
|
365
363
|
test('Meu teste de API', async ({ }, testInfo) => {
|
|
366
364
|
TestAnnotations.Api.testInfo = testInfo;
|
|
367
|
-
|
|
365
|
+
|
|
368
366
|
const response = await ApiActions.get({
|
|
369
367
|
url: 'https://api.example.com/endpoint',
|
|
370
368
|
options: {}
|
|
371
369
|
}, 'Descrição da requisição');
|
|
372
|
-
|
|
370
|
+
|
|
373
371
|
ApiActions.validateEquals(response.status, 200, 'Status deve ser 200');
|
|
374
372
|
});
|
|
375
373
|
\`\`\`
|
|
@@ -383,7 +381,7 @@ test('Fluxo autenticado', async () => {
|
|
|
383
381
|
// Obter token
|
|
384
382
|
const statements = new StatementsToken();
|
|
385
383
|
await statements.getToken();
|
|
386
|
-
|
|
384
|
+
|
|
387
385
|
// Usar token
|
|
388
386
|
const token = DataStore.get('ACCESS_TOKEN');
|
|
389
387
|
// ... usar token em requisições subsequentes
|
|
@@ -60,8 +60,6 @@ export default defineConfig({
|
|
|
60
60
|
trace: 'on',
|
|
61
61
|
},
|
|
62
62
|
})`);
|
|
63
|
-
// .npmrc
|
|
64
|
-
write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
|
|
65
63
|
// .gitignore
|
|
66
64
|
write('.gitignore', `# Playwright
|
|
67
65
|
node_modules/
|
|
@@ -143,32 +141,32 @@ DB_PASSWORD=
|
|
|
143
141
|
write('src/models/ModelDBA.ts', `export class ModelDBA {
|
|
144
142
|
getCep(cidade: string): string {
|
|
145
143
|
return /*sql*/ \`
|
|
146
|
-
SELECT
|
|
147
|
-
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
148
|
-
FROM
|
|
149
|
-
siebel.s_addr_per
|
|
150
|
-
WHERE
|
|
151
|
-
x_network_owner = 'VIVO2'
|
|
152
|
-
AND x_access_technology = 'GPON'
|
|
153
|
-
AND city = '\${cidade}'
|
|
154
|
-
AND comments LIKE '%Endereço com cobertura%'
|
|
155
|
-
ORDER BY
|
|
144
|
+
SELECT
|
|
145
|
+
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
146
|
+
FROM
|
|
147
|
+
siebel.s_addr_per
|
|
148
|
+
WHERE
|
|
149
|
+
x_network_owner = 'VIVO2'
|
|
150
|
+
AND x_access_technology = 'GPON'
|
|
151
|
+
AND city = '\${cidade}'
|
|
152
|
+
AND comments LIKE '%Endereço com cobertura%'
|
|
153
|
+
ORDER BY
|
|
156
154
|
last_upd DESC
|
|
157
155
|
\`;
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
getCep2(cidade: string, tecnology: string): string {
|
|
161
159
|
return /*sql*/ \`
|
|
162
|
-
SELECT
|
|
163
|
-
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
164
|
-
FROM
|
|
165
|
-
siebel.s_addr_per
|
|
166
|
-
WHERE
|
|
167
|
-
x_network_owner = 'VIVO2'
|
|
160
|
+
SELECT
|
|
161
|
+
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
162
|
+
FROM
|
|
163
|
+
siebel.s_addr_per
|
|
164
|
+
WHERE
|
|
165
|
+
x_network_owner = 'VIVO2'
|
|
168
166
|
AND x_access_technology = '\${tecnology}'
|
|
169
|
-
AND city = '\${cidade}'
|
|
170
|
-
AND comments LIKE '%Endereço com cobertura%'
|
|
171
|
-
ORDER BY
|
|
167
|
+
AND city = '\${cidade}'
|
|
168
|
+
AND comments LIKE '%Endereço com cobertura%'
|
|
169
|
+
ORDER BY
|
|
172
170
|
last_upd DESC
|
|
173
171
|
\`;
|
|
174
172
|
}
|
|
@@ -121,8 +121,6 @@ export default defineConfig({
|
|
|
121
121
|
],
|
|
122
122
|
});
|
|
123
123
|
`);
|
|
124
|
-
// .npmrc
|
|
125
|
-
write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
|
|
126
124
|
// .gitignore
|
|
127
125
|
write('.gitignore', `# Playwright
|
|
128
126
|
node_modules/
|
|
@@ -414,7 +412,7 @@ test.describe('Login', () => {
|
|
|
414
412
|
test('Login test', async ({}, testInfo: TestInfo) => {
|
|
415
413
|
TestAnnotations.Frontend.testInfo = testInfo;
|
|
416
414
|
await TestAnnotations.setSystem('MEU_SISTEMA');
|
|
417
|
-
|
|
415
|
+
|
|
418
416
|
await new PageLogin().navigateToLogin();
|
|
419
417
|
});
|
|
420
418
|
});
|
|
@@ -60,8 +60,6 @@ export default defineConfig({
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
`);
|
|
63
|
-
// .npmrc
|
|
64
|
-
write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
|
|
65
63
|
// .gitignore otimizado para mobile
|
|
66
64
|
write('.gitignore', `# Mobile específicos
|
|
67
65
|
node_modules/
|
|
@@ -72,7 +72,7 @@ export default defineConfig({
|
|
|
72
72
|
// ✅ Projetos "headless" (sem browser) — para SSH, API, Banco, Mobile
|
|
73
73
|
{
|
|
74
74
|
name: 'ssh',
|
|
75
|
-
use: {
|
|
75
|
+
use: {
|
|
76
76
|
browserName: undefined,
|
|
77
77
|
screenshot: 'off',
|
|
78
78
|
trace: 'off',
|
|
@@ -81,8 +81,8 @@ export default defineConfig({
|
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
name: 'api',
|
|
84
|
-
use: {
|
|
85
|
-
browserName: undefined,
|
|
84
|
+
use: {
|
|
85
|
+
browserName: undefined,
|
|
86
86
|
screenshot: 'off',
|
|
87
87
|
trace: 'off',
|
|
88
88
|
video: 'off'
|
|
@@ -90,8 +90,8 @@ export default defineConfig({
|
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
name: 'banco',
|
|
93
|
-
use: {
|
|
94
|
-
browserName: undefined,
|
|
93
|
+
use: {
|
|
94
|
+
browserName: undefined,
|
|
95
95
|
screenshot: 'off',
|
|
96
96
|
trace: 'off',
|
|
97
97
|
video: 'off'
|
|
@@ -99,7 +99,7 @@ export default defineConfig({
|
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
name: 'mobile',
|
|
102
|
-
use: { browserName: undefined,
|
|
102
|
+
use: { browserName: undefined,
|
|
103
103
|
screenshot: 'off',
|
|
104
104
|
trace: 'off',
|
|
105
105
|
video: 'off'
|
|
@@ -143,8 +143,6 @@ export default defineConfig({
|
|
|
143
143
|
],
|
|
144
144
|
});
|
|
145
145
|
`);
|
|
146
|
-
// .npmrc
|
|
147
|
-
write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
|
|
148
146
|
// .gitignore otimizado para cenários
|
|
149
147
|
write('.gitignore', `# Playwright
|
|
150
148
|
node_modules/
|
|
@@ -388,7 +386,7 @@ parameters:
|
|
|
388
386
|
- esteira1
|
|
389
387
|
- esteira2
|
|
390
388
|
- prodlike
|
|
391
|
-
|
|
389
|
+
|
|
392
390
|
- name: browser
|
|
393
391
|
displayName: Escolha o navegador para os testes
|
|
394
392
|
type: string
|
|
@@ -551,15 +549,15 @@ ${projectName}/
|
|
|
551
549
|
\`\`\`typescript
|
|
552
550
|
test('CT001 - Cenário misto', async ({ page }, testInfo) => {
|
|
553
551
|
TestAnnotations.Mixed.testInfo = testInfo;
|
|
554
|
-
|
|
552
|
+
|
|
555
553
|
// 1. Obter token via API
|
|
556
554
|
const tokenResponse = await ApiActions.post(tokenRequest, 'Obtenção de token');
|
|
557
555
|
DataStore.set('TOKEN', tokenResponse.body.access_token);
|
|
558
|
-
|
|
556
|
+
|
|
559
557
|
// 2. Usar interface
|
|
560
558
|
await WebActions.navegarPara('/app', 'Navegação');
|
|
561
559
|
await WebActions.preencherCampo(searchInput, 'busca', 'Preenchimento');
|
|
562
|
-
|
|
560
|
+
|
|
563
561
|
// 3. Validar via banco (se disponível)
|
|
564
562
|
const dbResults = await BancoHelper.executarQuery(query);
|
|
565
563
|
expect(dbResults.length).toBeGreaterThan(0);
|
|
@@ -571,13 +569,13 @@ test('CT001 - Cenário misto', async ({ page }, testInfo) => {
|
|
|
571
569
|
test('Fluxo E2E completo', async () => {
|
|
572
570
|
// Fase 1: Autenticação
|
|
573
571
|
await authenticateViaAPI();
|
|
574
|
-
|
|
572
|
+
|
|
575
573
|
// Fase 2: Navegação e interação
|
|
576
574
|
await performUIInteractions();
|
|
577
|
-
|
|
575
|
+
|
|
578
576
|
// Fase 3: Validação de dados
|
|
579
577
|
await validateDataConsistency();
|
|
580
|
-
|
|
578
|
+
|
|
581
579
|
// Fase 4: Cleanup e relatório
|
|
582
580
|
await generateEvidences();
|
|
583
581
|
});
|
|
@@ -588,10 +586,10 @@ test('Fluxo E2E completo', async () => {
|
|
|
588
586
|
test('Validação de infraestrutura', async () => {
|
|
589
587
|
// Verificar serviços via SSH
|
|
590
588
|
await SSHActions.write('systemctl status myapp');
|
|
591
|
-
|
|
589
|
+
|
|
592
590
|
// Validar dados no banco
|
|
593
591
|
await BancoActions.executarQuery('SELECT 1 FROM dual');
|
|
594
|
-
|
|
592
|
+
|
|
595
593
|
// Validar interface está acessível
|
|
596
594
|
await WebActions.navegarPara('/health', 'Health check');
|
|
597
595
|
});
|
package/dist/scripts/init-ssh.js
CHANGED
|
@@ -127,10 +127,10 @@ function execNpmSync(args, timeoutMs = 30000) {
|
|
|
127
127
|
// ✅ Obter versão instalada globalmente do pacote MCP
|
|
128
128
|
function getInstalledMcpVersion() {
|
|
129
129
|
try {
|
|
130
|
-
const result = execNpmSync(['list', '-g', '@silasfmartins/
|
|
130
|
+
const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0', '--json']);
|
|
131
131
|
if (result.status === 0) {
|
|
132
132
|
const data = JSON.parse(result.stdout);
|
|
133
|
-
return data.dependencies?.['@silasfmartins/
|
|
133
|
+
return data.dependencies?.['@silasfmartins/autocore-orchestrator-mcp']?.version || null;
|
|
134
134
|
}
|
|
135
135
|
return null;
|
|
136
136
|
}
|
|
@@ -141,7 +141,7 @@ function getInstalledMcpVersion() {
|
|
|
141
141
|
// ✅ Verificar acesso ao registry e obter última versão do MCP
|
|
142
142
|
function checkRegistryAndGetLatestVersion() {
|
|
143
143
|
try {
|
|
144
|
-
const result = execNpmSync(['view', '@silasfmartins/
|
|
144
|
+
const result = execNpmSync(['view', '@silasfmartins/autocore-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`], 30000);
|
|
145
145
|
if (result.status === 0 && result.stdout.trim()) {
|
|
146
146
|
return result.stdout.trim();
|
|
147
147
|
}
|
|
@@ -151,15 +151,15 @@ function checkRegistryAndGetLatestVersion() {
|
|
|
151
151
|
return null;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
// ✅ Verificar se o pacote @silasfmartins/
|
|
154
|
+
// ✅ Verificar se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
|
|
155
155
|
function checkGlobalMcpPackage() {
|
|
156
|
-
const result = execNpmSync(['list', '-g', '@silasfmartins/
|
|
157
|
-
return result.status === 0 && result.stdout.includes('@silasfmartins/
|
|
156
|
+
const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0']);
|
|
157
|
+
return result.status === 0 && result.stdout.includes('@silasfmartins/autocore-orchestrator-mcp');
|
|
158
158
|
}
|
|
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)');
|
|
@@ -199,7 +198,7 @@ function installOrUpdateMcpPackage() {
|
|
|
199
198
|
console.log('AutoCore: Instalando MCP globalmente...');
|
|
200
199
|
}
|
|
201
200
|
// Executar instalação/atualização
|
|
202
|
-
const installResult = execNpmSync(['install', '-g', `@silasfmartins/
|
|
201
|
+
const installResult = execNpmSync(['install', '-g', `@silasfmartins/autocore-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`], 60000);
|
|
203
202
|
if (installResult.status === 0) {
|
|
204
203
|
const newVersion = getInstalledMcpVersion();
|
|
205
204
|
if (installedVersion) {
|
|
@@ -299,7 +298,7 @@ async function ensureMcpConfig() {
|
|
|
299
298
|
},
|
|
300
299
|
'autocore-orchestrator': {
|
|
301
300
|
command: 'npx',
|
|
302
|
-
args: ['-y', '@silasfmartins/
|
|
301
|
+
args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
|
|
303
302
|
env: {
|
|
304
303
|
HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
|
|
305
304
|
},
|
|
@@ -325,7 +324,7 @@ async function ensureMcpConfig() {
|
|
|
325
324
|
},
|
|
326
325
|
'autocore-orchestrator': {
|
|
327
326
|
command: 'npx',
|
|
328
|
-
args: ['-y', '@silasfmartins/
|
|
327
|
+
args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
|
|
329
328
|
env: {
|
|
330
329
|
HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
|
|
331
330
|
},
|
|
@@ -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
|
-
|
|
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
|
|
1349
|
-
|
|
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
|
|
@@ -91,8 +91,8 @@ function getMcpStdioCandidates() {
|
|
|
91
91
|
});
|
|
92
92
|
candidates.push({
|
|
93
93
|
command: "npx",
|
|
94
|
-
args: ["-y", "@silasfmartins/
|
|
95
|
-
label: "npx:@silasfmartins/
|
|
94
|
+
args: ["-y", "@silasfmartins/autocore-orchestrator-mcp", "--stdio"],
|
|
95
|
+
label: "npx:@silasfmartins/autocore-orchestrator-mcp",
|
|
96
96
|
});
|
|
97
97
|
// remover duplicados mantendo ordem
|
|
98
98
|
const dedupe = new Set();
|
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.
|
|
4
|
+
"version": "1.0.2",
|
|
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.
|
|
109
|
+
"ultracite": "7.3.2",
|
|
110
110
|
"undici": "^7.24.4",
|
|
111
111
|
"vitest": "4.1.0"
|
|
112
112
|
},
|
|
@@ -141,7 +141,7 @@ function isExtensionInstalled(extensionId: string): boolean {
|
|
|
141
141
|
const AZURE_REGISTRY =
|
|
142
142
|
"https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/";
|
|
143
143
|
const WINDOWS_MCP_AUTOSTART_START_COMMAND =
|
|
144
|
-
"npx -y @silasfmartins/
|
|
144
|
+
"npx -y @silasfmartins/autocore-orchestrator-mcp";
|
|
145
145
|
const WINDOWS_MCP_STARTUP_SCRIPT_FILE = "autocore-orchestrator-mcp.cmd";
|
|
146
146
|
const WINDOWS_MCP_STARTUP_VBS_FILE = "autocore-orchestrator-mcp.vbs";
|
|
147
147
|
|
|
@@ -193,12 +193,12 @@ async function execNpmCommand(
|
|
|
193
193
|
async function getInstalledMcpVersion(): Promise<string | null> {
|
|
194
194
|
try {
|
|
195
195
|
const result = await execNpmCommand(
|
|
196
|
-
"npm list -g @silasfmartins/
|
|
196
|
+
"npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0 --json",
|
|
197
197
|
);
|
|
198
198
|
if (!result) return null;
|
|
199
199
|
const data = JSON.parse(result.stdout);
|
|
200
200
|
return (
|
|
201
|
-
data.dependencies?.["@silasfmartins/
|
|
201
|
+
data.dependencies?.["@silasfmartins/autocore-orchestrator-mcp"]?.version || null
|
|
202
202
|
);
|
|
203
203
|
} catch {
|
|
204
204
|
return null;
|
|
@@ -212,7 +212,7 @@ async function getInstalledMcpVersion(): Promise<string | null> {
|
|
|
212
212
|
async function getLatestMcpVersion(): Promise<string | null> {
|
|
213
213
|
try {
|
|
214
214
|
const result = await execNpmCommand(
|
|
215
|
-
`npm view @silasfmartins/
|
|
215
|
+
`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
|
|
216
216
|
30000,
|
|
217
217
|
);
|
|
218
218
|
if (!result) return null;
|
|
@@ -223,15 +223,15 @@ async function getLatestMcpVersion(): Promise<string | null> {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/**
|
|
226
|
-
* 🔍 Verifica se o pacote @silasfmartins/
|
|
226
|
+
* 🔍 Verifica se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
|
|
227
227
|
*/
|
|
228
228
|
async function isMcpPackageInstalled(): Promise<boolean> {
|
|
229
229
|
try {
|
|
230
230
|
const result = await execNpmCommand(
|
|
231
|
-
"npm list -g @silasfmartins/
|
|
231
|
+
"npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0",
|
|
232
232
|
);
|
|
233
233
|
return result
|
|
234
|
-
? result.stdout.includes("@silasfmartins/
|
|
234
|
+
? result.stdout.includes("@silasfmartins/autocore-orchestrator-mcp")
|
|
235
235
|
: false;
|
|
236
236
|
} catch {
|
|
237
237
|
return false;
|
|
@@ -246,7 +246,7 @@ async function checkRegistryAccess(): Promise<string | null> {
|
|
|
246
246
|
try {
|
|
247
247
|
// Tenta obter a versão do pacote no Azure Artifacts
|
|
248
248
|
const result = await execNpmCommand(
|
|
249
|
-
`npm view @silasfmartins/
|
|
249
|
+
`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
|
|
250
250
|
30000,
|
|
251
251
|
);
|
|
252
252
|
if (result && result.stdout.trim()) {
|
|
@@ -259,7 +259,7 @@ async function checkRegistryAccess(): Promise<string | null> {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
/**
|
|
262
|
-
* 📦 Instala ou atualiza o pacote @silasfmartins/
|
|
262
|
+
* 📦 Instala ou atualiza o pacote @silasfmartins/autocore-orchestrator-mcp globalmente
|
|
263
263
|
*
|
|
264
264
|
* 🎯 COMPORTAMENTO:
|
|
265
265
|
* - Se já está na última versão: NÃO reinstala (economia de tempo)
|
|
@@ -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) {
|
|
@@ -301,7 +300,7 @@ async function installMcpPackageGlobally(): Promise<boolean> {
|
|
|
301
300
|
console.log("⚠️ O MCP será executado via npx quando necessário");
|
|
302
301
|
console.log(" 💡 Conecte-se à VPN e execute:");
|
|
303
302
|
console.log(
|
|
304
|
-
` npm install -g @silasfmartins/
|
|
303
|
+
` npm install -g @silasfmartins/autocore-orchestrator-mcp --registry=${AZURE_REGISTRY}`,
|
|
305
304
|
);
|
|
306
305
|
return false;
|
|
307
306
|
}
|
|
@@ -326,7 +325,7 @@ async function installMcpPackageGlobally(): Promise<boolean> {
|
|
|
326
325
|
|
|
327
326
|
// 5️⃣ Executar instalação/atualização
|
|
328
327
|
const installResult = await execNpmCommand(
|
|
329
|
-
`npm install -g @silasfmartins/
|
|
328
|
+
`npm install -g @silasfmartins/autocore-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`,
|
|
330
329
|
60000,
|
|
331
330
|
);
|
|
332
331
|
|
|
@@ -492,7 +491,7 @@ async function ensureMcpConfig(): Promise<void> {
|
|
|
492
491
|
},
|
|
493
492
|
"autocore-orchestrator": {
|
|
494
493
|
command: "npx",
|
|
495
|
-
args: ["-y", "@silasfmartins/
|
|
494
|
+
args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
|
|
496
495
|
env: {
|
|
497
496
|
HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
|
|
498
497
|
},
|
|
@@ -523,7 +522,7 @@ async function ensureMcpConfig(): Promise<void> {
|
|
|
523
522
|
},
|
|
524
523
|
"autocore-orchestrator": {
|
|
525
524
|
command: "npx",
|
|
526
|
-
args: ["-y", "@silasfmartins/
|
|
525
|
+
args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
|
|
527
526
|
env: {
|
|
528
527
|
HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
|
|
529
528
|
},
|
package/scripts/init-api.ts
CHANGED
|
@@ -87,12 +87,6 @@ export default defineConfig({
|
|
|
87
87
|
})`,
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
// .npmrc
|
|
91
|
-
write(
|
|
92
|
-
'.npmrc',
|
|
93
|
-
`registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
90
|
// .gitignore
|
|
97
91
|
write(
|
|
98
92
|
'.gitignore',
|
|
@@ -184,10 +178,10 @@ test.describe('API Tests - ${projectName}', () => {
|
|
|
184
178
|
test('CT001 - Exemplo de requisição API', async ({ }, testInfo: TestInfo) => {
|
|
185
179
|
TestAnnotations.Api.testInfo = testInfo
|
|
186
180
|
await TestAnnotations.setSystem('MEU_SISTEMA')
|
|
187
|
-
|
|
181
|
+
|
|
188
182
|
// Exemplo de requisição - substitua pelo seu statement
|
|
189
183
|
// await new StatementsToken().getToken()
|
|
190
|
-
|
|
184
|
+
|
|
191
185
|
// Exemplo de chamada API direta
|
|
192
186
|
await ApiActions.executeGet(
|
|
193
187
|
'Buscar dados do endpoint',
|
|
@@ -245,20 +239,20 @@ export class StatementsToken {
|
|
|
245
239
|
const VALIDATE_TOKEN = 200
|
|
246
240
|
|
|
247
241
|
const tokenResponse = await ApiActions.post(
|
|
248
|
-
new RequestToken().requestToken(),
|
|
249
|
-
"Requisição Token Sistêmico",
|
|
242
|
+
new RequestToken().requestToken(),
|
|
243
|
+
"Requisição Token Sistêmico",
|
|
250
244
|
true
|
|
251
245
|
);
|
|
252
246
|
|
|
253
247
|
ApiActions.validateEquals(
|
|
254
248
|
tokenResponse.status(),
|
|
255
|
-
VALIDATE_TOKEN,
|
|
249
|
+
VALIDATE_TOKEN,
|
|
256
250
|
"Validação do status code da requisição de token"
|
|
257
251
|
);
|
|
258
252
|
|
|
259
253
|
// Armazenar token para uso posterior
|
|
260
254
|
DataStore.set("ACCESS_TOKEN", tokenResponse.get("token"))
|
|
261
|
-
|
|
255
|
+
|
|
262
256
|
Logger.info("Token obtido e armazenado com sucesso");
|
|
263
257
|
}
|
|
264
258
|
}
|
|
@@ -274,7 +268,7 @@ import { StatementsToken } from '../src/statements/token/StatementsToken.js';
|
|
|
274
268
|
test.describe('Exemplo API Tests', () => {
|
|
275
269
|
TestAnnotations.Api.testInfo = testInfo;
|
|
276
270
|
await TestAnnotations.setSystem('MEU_SISTEMA');
|
|
277
|
-
test('Deve obter token com sucesso', async () => {
|
|
271
|
+
test('Deve obter token com sucesso', async () => {
|
|
278
272
|
// Obter token
|
|
279
273
|
await new StatementsToken().getToken()
|
|
280
274
|
});
|
|
@@ -446,12 +440,12 @@ import { type TestInfo, test, TestAnnotations } from '@silasfmartins/testhub'
|
|
|
446
440
|
|
|
447
441
|
test('Meu teste de API', async ({ }, testInfo) => {
|
|
448
442
|
TestAnnotations.Api.testInfo = testInfo;
|
|
449
|
-
|
|
443
|
+
|
|
450
444
|
const response = await ApiActions.get({
|
|
451
445
|
url: 'https://api.example.com/endpoint',
|
|
452
446
|
options: {}
|
|
453
447
|
}, 'Descrição da requisição');
|
|
454
|
-
|
|
448
|
+
|
|
455
449
|
ApiActions.validateEquals(response.status, 200, 'Status deve ser 200');
|
|
456
450
|
});
|
|
457
451
|
\`\`\`
|
|
@@ -465,7 +459,7 @@ test('Fluxo autenticado', async () => {
|
|
|
465
459
|
// Obter token
|
|
466
460
|
const statements = new StatementsToken();
|
|
467
461
|
await statements.getToken();
|
|
468
|
-
|
|
462
|
+
|
|
469
463
|
// Usar token
|
|
470
464
|
const token = DataStore.get('ACCESS_TOKEN');
|
|
471
465
|
// ... usar token em requisições subsequentes
|
package/scripts/init-banco.ts
CHANGED
|
@@ -94,12 +94,6 @@ export default defineConfig({
|
|
|
94
94
|
})`,
|
|
95
95
|
)
|
|
96
96
|
|
|
97
|
-
// .npmrc
|
|
98
|
-
write(
|
|
99
|
-
'.npmrc',
|
|
100
|
-
`registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
97
|
// .gitignore
|
|
104
98
|
write(
|
|
105
99
|
'.gitignore',
|
|
@@ -208,32 +202,32 @@ DB_PASSWORD=
|
|
|
208
202
|
`export class ModelDBA {
|
|
209
203
|
getCep(cidade: string): string {
|
|
210
204
|
return /*sql*/ \`
|
|
211
|
-
SELECT
|
|
212
|
-
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
213
|
-
FROM
|
|
214
|
-
siebel.s_addr_per
|
|
215
|
-
WHERE
|
|
216
|
-
x_network_owner = 'VIVO2'
|
|
217
|
-
AND x_access_technology = 'GPON'
|
|
218
|
-
AND city = '\${cidade}'
|
|
219
|
-
AND comments LIKE '%Endereço com cobertura%'
|
|
220
|
-
ORDER BY
|
|
205
|
+
SELECT
|
|
206
|
+
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
207
|
+
FROM
|
|
208
|
+
siebel.s_addr_per
|
|
209
|
+
WHERE
|
|
210
|
+
x_network_owner = 'VIVO2'
|
|
211
|
+
AND x_access_technology = 'GPON'
|
|
212
|
+
AND city = '\${cidade}'
|
|
213
|
+
AND comments LIKE '%Endereço com cobertura%'
|
|
214
|
+
ORDER BY
|
|
221
215
|
last_upd DESC
|
|
222
216
|
\`;
|
|
223
217
|
}
|
|
224
218
|
|
|
225
219
|
getCep2(cidade: string, tecnology: string): string {
|
|
226
220
|
return /*sql*/ \`
|
|
227
|
-
SELECT
|
|
228
|
-
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
229
|
-
FROM
|
|
230
|
-
siebel.s_addr_per
|
|
231
|
-
WHERE
|
|
232
|
-
x_network_owner = 'VIVO2'
|
|
221
|
+
SELECT
|
|
222
|
+
ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
|
|
223
|
+
FROM
|
|
224
|
+
siebel.s_addr_per
|
|
225
|
+
WHERE
|
|
226
|
+
x_network_owner = 'VIVO2'
|
|
233
227
|
AND x_access_technology = '\${tecnology}'
|
|
234
|
-
AND city = '\${cidade}'
|
|
235
|
-
AND comments LIKE '%Endereço com cobertura%'
|
|
236
|
-
ORDER BY
|
|
228
|
+
AND city = '\${cidade}'
|
|
229
|
+
AND comments LIKE '%Endereço com cobertura%'
|
|
230
|
+
ORDER BY
|
|
237
231
|
last_upd DESC
|
|
238
232
|
\`;
|
|
239
233
|
}
|
package/scripts/init-frontend.ts
CHANGED
|
@@ -153,12 +153,6 @@ export default defineConfig({
|
|
|
153
153
|
`,
|
|
154
154
|
)
|
|
155
155
|
|
|
156
|
-
// .npmrc
|
|
157
|
-
write(
|
|
158
|
-
'.npmrc',
|
|
159
|
-
`registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
|
|
160
|
-
)
|
|
161
|
-
|
|
162
156
|
// .gitignore
|
|
163
157
|
write(
|
|
164
158
|
'.gitignore',
|
|
@@ -506,7 +500,7 @@ test.describe('Login', () => {
|
|
|
506
500
|
test('Login test', async ({}, testInfo: TestInfo) => {
|
|
507
501
|
TestAnnotations.Frontend.testInfo = testInfo;
|
|
508
502
|
await TestAnnotations.setSystem('MEU_SISTEMA');
|
|
509
|
-
|
|
503
|
+
|
|
510
504
|
await new PageLogin().navigateToLogin();
|
|
511
505
|
});
|
|
512
506
|
});
|
package/scripts/init-mobile.ts
CHANGED
|
@@ -91,12 +91,6 @@ export default defineConfig({
|
|
|
91
91
|
`,
|
|
92
92
|
)
|
|
93
93
|
|
|
94
|
-
// .npmrc
|
|
95
|
-
write(
|
|
96
|
-
'.npmrc',
|
|
97
|
-
`registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
|
|
98
|
-
)
|
|
99
|
-
|
|
100
94
|
// .gitignore otimizado para mobile
|
|
101
95
|
write(
|
|
102
96
|
'.gitignore',
|
|
@@ -99,7 +99,7 @@ export default defineConfig({
|
|
|
99
99
|
// ✅ Projetos "headless" (sem browser) — para SSH, API, Banco, Mobile
|
|
100
100
|
{
|
|
101
101
|
name: 'ssh',
|
|
102
|
-
use: {
|
|
102
|
+
use: {
|
|
103
103
|
browserName: undefined,
|
|
104
104
|
screenshot: 'off',
|
|
105
105
|
trace: 'off',
|
|
@@ -108,8 +108,8 @@ export default defineConfig({
|
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
110
|
name: 'api',
|
|
111
|
-
use: {
|
|
112
|
-
browserName: undefined,
|
|
111
|
+
use: {
|
|
112
|
+
browserName: undefined,
|
|
113
113
|
screenshot: 'off',
|
|
114
114
|
trace: 'off',
|
|
115
115
|
video: 'off'
|
|
@@ -117,8 +117,8 @@ export default defineConfig({
|
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
name: 'banco',
|
|
120
|
-
use: {
|
|
121
|
-
browserName: undefined,
|
|
120
|
+
use: {
|
|
121
|
+
browserName: undefined,
|
|
122
122
|
screenshot: 'off',
|
|
123
123
|
trace: 'off',
|
|
124
124
|
video: 'off'
|
|
@@ -126,7 +126,7 @@ export default defineConfig({
|
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
name: 'mobile',
|
|
129
|
-
use: { browserName: undefined,
|
|
129
|
+
use: { browserName: undefined,
|
|
130
130
|
screenshot: 'off',
|
|
131
131
|
trace: 'off',
|
|
132
132
|
video: 'off'
|
|
@@ -172,12 +172,6 @@ export default defineConfig({
|
|
|
172
172
|
`,
|
|
173
173
|
)
|
|
174
174
|
|
|
175
|
-
// .npmrc
|
|
176
|
-
write(
|
|
177
|
-
'.npmrc',
|
|
178
|
-
`registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
175
|
// .gitignore otimizado para cenários
|
|
182
176
|
write(
|
|
183
177
|
'.gitignore',
|
|
@@ -451,7 +445,7 @@ parameters:
|
|
|
451
445
|
- esteira1
|
|
452
446
|
- esteira2
|
|
453
447
|
- prodlike
|
|
454
|
-
|
|
448
|
+
|
|
455
449
|
- name: browser
|
|
456
450
|
displayName: Escolha o navegador para os testes
|
|
457
451
|
type: string
|
|
@@ -618,15 +612,15 @@ ${projectName}/
|
|
|
618
612
|
\`\`\`typescript
|
|
619
613
|
test('CT001 - Cenário misto', async ({ page }, testInfo) => {
|
|
620
614
|
TestAnnotations.Mixed.testInfo = testInfo;
|
|
621
|
-
|
|
615
|
+
|
|
622
616
|
// 1. Obter token via API
|
|
623
617
|
const tokenResponse = await ApiActions.post(tokenRequest, 'Obtenção de token');
|
|
624
618
|
DataStore.set('TOKEN', tokenResponse.body.access_token);
|
|
625
|
-
|
|
619
|
+
|
|
626
620
|
// 2. Usar interface
|
|
627
621
|
await WebActions.navegarPara('/app', 'Navegação');
|
|
628
622
|
await WebActions.preencherCampo(searchInput, 'busca', 'Preenchimento');
|
|
629
|
-
|
|
623
|
+
|
|
630
624
|
// 3. Validar via banco (se disponível)
|
|
631
625
|
const dbResults = await BancoHelper.executarQuery(query);
|
|
632
626
|
expect(dbResults.length).toBeGreaterThan(0);
|
|
@@ -638,13 +632,13 @@ test('CT001 - Cenário misto', async ({ page }, testInfo) => {
|
|
|
638
632
|
test('Fluxo E2E completo', async () => {
|
|
639
633
|
// Fase 1: Autenticação
|
|
640
634
|
await authenticateViaAPI();
|
|
641
|
-
|
|
635
|
+
|
|
642
636
|
// Fase 2: Navegação e interação
|
|
643
637
|
await performUIInteractions();
|
|
644
|
-
|
|
638
|
+
|
|
645
639
|
// Fase 3: Validação de dados
|
|
646
640
|
await validateDataConsistency();
|
|
647
|
-
|
|
641
|
+
|
|
648
642
|
// Fase 4: Cleanup e relatório
|
|
649
643
|
await generateEvidences();
|
|
650
644
|
});
|
|
@@ -655,10 +649,10 @@ test('Fluxo E2E completo', async () => {
|
|
|
655
649
|
test('Validação de infraestrutura', async () => {
|
|
656
650
|
// Verificar serviços via SSH
|
|
657
651
|
await SSHActions.write('systemctl status myapp');
|
|
658
|
-
|
|
652
|
+
|
|
659
653
|
// Validar dados no banco
|
|
660
654
|
await BancoActions.executarQuery('SELECT 1 FROM dual');
|
|
661
|
-
|
|
655
|
+
|
|
662
656
|
// Validar interface está acessível
|
|
663
657
|
await WebActions.navegarPara('/health', 'Health check');
|
|
664
658
|
});
|
package/scripts/init-ssh.ts
CHANGED
package/scripts/postinstall.ts
CHANGED
|
@@ -147,10 +147,10 @@ function execNpmSync(args: string[], timeoutMs = 30000): { stdout: string; statu
|
|
|
147
147
|
// ✅ Obter versão instalada globalmente do pacote MCP
|
|
148
148
|
function getInstalledMcpVersion(): string | null {
|
|
149
149
|
try {
|
|
150
|
-
const result = execNpmSync(['list', '-g', '@silasfmartins/
|
|
150
|
+
const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0', '--json'])
|
|
151
151
|
if (result.status === 0) {
|
|
152
152
|
const data = JSON.parse(result.stdout)
|
|
153
|
-
return data.dependencies?.['@silasfmartins/
|
|
153
|
+
return data.dependencies?.['@silasfmartins/autocore-orchestrator-mcp']?.version || null
|
|
154
154
|
}
|
|
155
155
|
return null
|
|
156
156
|
} catch {
|
|
@@ -162,7 +162,7 @@ function getInstalledMcpVersion(): string | null {
|
|
|
162
162
|
function checkRegistryAndGetLatestVersion(): string | null {
|
|
163
163
|
try {
|
|
164
164
|
const result = execNpmSync(
|
|
165
|
-
['view', '@silasfmartins/
|
|
165
|
+
['view', '@silasfmartins/autocore-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`],
|
|
166
166
|
30000
|
|
167
167
|
)
|
|
168
168
|
if (result.status === 0 && result.stdout.trim()) {
|
|
@@ -174,23 +174,23 @@ function checkRegistryAndGetLatestVersion(): string | null {
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
// ✅ Verificar se o pacote @silasfmartins/
|
|
177
|
+
// ✅ Verificar se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
|
|
178
178
|
function checkGlobalMcpPackage(): boolean {
|
|
179
|
-
const result = execNpmSync(['list', '-g', '@silasfmartins/
|
|
180
|
-
return result.status === 0 && result.stdout.includes('@silasfmartins/
|
|
179
|
+
const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0'])
|
|
180
|
+
return result.status === 0 && result.stdout.includes('@silasfmartins/autocore-orchestrator-mcp')
|
|
181
181
|
}
|
|
182
182
|
|
|
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
|
-
['install', '-g', `@silasfmartins/
|
|
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
|
|
|
@@ -344,7 +343,7 @@ async function ensureMcpConfig(): Promise<void> {
|
|
|
344
343
|
},
|
|
345
344
|
'autocore-orchestrator': {
|
|
346
345
|
command: 'npx',
|
|
347
|
-
args: ['-y', '@silasfmartins/
|
|
346
|
+
args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
|
|
348
347
|
env: {
|
|
349
348
|
HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
|
|
350
349
|
},
|
|
@@ -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) {
|
|
@@ -373,7 +372,7 @@ async function ensureMcpConfig(): Promise<void> {
|
|
|
373
372
|
},
|
|
374
373
|
'autocore-orchestrator': {
|
|
375
374
|
command: 'npx',
|
|
376
|
-
args: ['-y', '@silasfmartins/
|
|
375
|
+
args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
|
|
377
376
|
env: {
|
|
378
377
|
HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
|
|
379
378
|
},
|
|
@@ -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 {
|