@diegosouzacdv/jev-browser-mcp 0.6.2 → 0.7.1
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/README.md +356 -117
- package/config/ui-testing.json +2 -2
- package/docs/jev-browser-mcp.md +356 -117
- package/mcp_servers/jev-browser-npm/src/config.mjs +27 -12
- package/mcp_servers/jev-browser-npm/src/flow.mjs +2181 -914
- package/mcp_servers/jev-browser-npm/src/server.mjs +270 -69
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ versão em produção, use o número explícito no argumento do pacote:
|
|
|
17
17
|
"mcpServers": {
|
|
18
18
|
"jev-browser": {
|
|
19
19
|
"command": "npx",
|
|
20
|
-
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.
|
|
20
|
+
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.7.1"],
|
|
21
21
|
"env": {
|
|
22
22
|
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
|
23
23
|
"JEV_BROWSER_MODE": "computer"
|
|
@@ -32,7 +32,7 @@ um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
|
|
|
32
32
|
de configuração. Para instalar no projeto Node do próprio harness:
|
|
33
33
|
|
|
34
34
|
```sh
|
|
35
|
-
npm install @diegosouzacdv/jev-browser-mcp@0.
|
|
35
|
+
npm install @diegosouzacdv/jev-browser-mcp@0.7.1
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Se o harness executa o MCP repetidamente nesta máquina, instale uma versão
|
|
@@ -40,7 +40,7 @@ fixa globalmente para evitar a resolução e o download feitos pelo `npx` em cad
|
|
|
40
40
|
inicialização:
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
|
-
npm install --global @diegosouzacdv/jev-browser-mcp@0.
|
|
43
|
+
npm install --global @diegosouzacdv/jev-browser-mcp@0.7.1
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Depois configure o servidor MCP com `command: "jev-browser-mcp"` e `args: []`.
|
|
@@ -49,14 +49,23 @@ Para atualizar, rode `npm install --global
|
|
|
49
49
|
|
|
50
50
|
O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
|
|
51
51
|
configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
|
|
52
|
-
pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.
|
|
53
|
-
|
|
54
|
-
O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
|
|
55
|
-
persistente exclusivo em `browser.computer_user_data_dir`.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.7.1 --install-browser`.
|
|
53
|
+
|
|
54
|
+
O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
|
|
55
|
+
persistente exclusivo por processo MCP em `browser.computer_user_data_dir`. O
|
|
56
|
+
template aceita `{browser}` e `{session}`; por padrão, `{session}` é `pid-<PID>`.
|
|
57
|
+
Use um `JEV_BROWSER_SESSION_ID` único por instância para manter um nome estável
|
|
58
|
+
entre reinicializações. Um
|
|
59
|
+
`JEV_BROWSER_PROFILE` explícito também recebe o sufixo da sessão, a menos que o
|
|
60
|
+
caminho contenha `{session}`. Assim, processos MCP independentes não disputam o
|
|
61
|
+
mesmo perfil. Clientes conectados ao mesmo processo MCP compartilham a sessão;
|
|
62
|
+
para isolamento entre harnesses, execute uma instância por sessão. No modo
|
|
63
|
+
`harness`, a instalação baixa uma vez o Chrome/Edge que o Playwright controlará.
|
|
64
|
+
Personalize as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
|
|
65
|
+
`JEV_BROWSER_PROFILE`. Sem um ID estável, o perfil é específico do processo e
|
|
66
|
+
uma reinicialização começa outra sessão. O browser permanece aquecido enquanto
|
|
67
|
+
o processo MCP estiver ativo e fecha quando o harness encerra o processo.
|
|
68
|
+
`JEV_PROVIDER_URL`
|
|
60
69
|
e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
|
|
61
70
|
nome de variável declarado em `jev.credential_env`.
|
|
62
71
|
|
|
@@ -76,8 +85,14 @@ publicada.
|
|
|
76
85
|
|
|
77
86
|
### Contrato do pacote
|
|
78
87
|
|
|
79
|
-
O executável oferece `browser_health`, `choose_next_action`
|
|
80
|
-
sessão do browser por processo e reutiliza
|
|
88
|
+
O executável oferece `browser_health`, `describe_actions`, `choose_next_action`
|
|
89
|
+
e `run_browser_flow`, mantém uma sessão do browser por processo e reutiliza
|
|
90
|
+
essa sessão entre chamadas. `browser_health` informa versão, sessão e
|
|
91
|
+
capacidades; `describe_actions` publica o schema atual das ações, opções,
|
|
92
|
+
aliases, placeholders, campos obrigatórios de `flow`/plano e requisitos
|
|
93
|
+
condicionais por ação. `run_browser_flow` agrega campos obrigatórios ausentes
|
|
94
|
+
em todos os planos e etapas antes de abrir o navegador. Consulte essas ferramentas
|
|
95
|
+
antes de construir um plano para evitar nomes de campos desatualizados. O plano
|
|
81
96
|
passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
|
|
82
97
|
hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
|
|
83
98
|
raiz local configurada e reações idempotentes a um comentário único. Também
|
|
@@ -112,9 +127,14 @@ Cada plano pode usar:
|
|
|
112
127
|
- `navigate` para mudar de página no meio do fluxo. Com a continuidade ligada,
|
|
113
128
|
um `initial_url` de mesma origem diferente da URL ativa produz erro claro; use
|
|
114
129
|
`navigate` ou `continue_from_current_page: false` para escolher o destino;
|
|
115
|
-
- `click`, `
|
|
116
|
-
papel/nome acessível ou
|
|
117
|
-
`text`, `test_id`
|
|
130
|
+
- `click`, `check`, `uncheck`, `type`, `clear`, `hover`, `select_option`,
|
|
131
|
+
`press` e `assert_*` aceitam papel/nome acessível ou localizadores como
|
|
132
|
+
`label`, `placeholder`, `title`, `text`, `test_id` e `selector`;
|
|
133
|
+
- `screenshot` e `clear_storage` atuam na página/contexto atual; `upload_file`
|
|
134
|
+
recebe o arquivo e o alvo de upload. Os limites e formatos estão descritos nas
|
|
135
|
+
seções de evidências e upload;
|
|
136
|
+
- `navigate_menu` para percorrer uma sequência de rótulos de menu; veja a seção
|
|
137
|
+
de navegação de menus para o formato e as opções;
|
|
118
138
|
- `name_match: "exact" | "contains" | "regex"` para controlar a comparação do
|
|
119
139
|
nome acessível; regex rejeita construções com backtracking excessivo. O papel
|
|
120
140
|
`switch` funciona em cliques, verificações e asserções;
|
|
@@ -131,8 +151,11 @@ Cada plano pode usar:
|
|
|
131
151
|
espaços/glyphs de uso privado, como ícones Font Awesome; controles
|
|
132
152
|
desabilitados não aparecem no diagnóstico, mas continuam contando para que o
|
|
133
153
|
índice aponte ao controle correto;
|
|
134
|
-
- `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
|
|
135
|
-
em `warnings`; não é permitido enviar JavaScript nem coordenadas;
|
|
154
|
+
- `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
|
|
155
|
+
em `warnings`; não é permitido enviar JavaScript nem coordenadas;
|
|
156
|
+
- quando `click` falha porque o alvo está fora da viewport ou não está visível,
|
|
157
|
+
o MCP tenta rolar o alvo até a tela; se isso não bastar, tenta focar o controle
|
|
158
|
+
e enviar `Enter`, sem repetir cegamente o clique;
|
|
136
159
|
- `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
|
|
137
160
|
- `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
|
|
138
161
|
`blur: true` para desfocar o campo e `sensitive: false` para permitir que o
|
|
@@ -140,7 +163,7 @@ Cada plano pode usar:
|
|
|
140
163
|
de ambiente do processo MCP, sem colocá-lo no plano. Nesse modo, `\n` envia
|
|
141
164
|
Enter e `\t` envia Tab;
|
|
142
165
|
- `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
|
|
143
|
-
(`url`, `network_idle`, `hidden
|
|
166
|
+
(`url`, `network_idle`, `hidden` ou `angular_idle`). `wait` recebe
|
|
144
167
|
`ms` para uma pausa curta e limitada. `angular_idle` aguarda requisições
|
|
145
168
|
`$http` e digest do AngularJS. `wait_for_text` aceita `fail_on: {"role":"alert"}` para
|
|
146
169
|
interromper a espera assim que um alerta visível aparecer e incluir seu texto
|
|
@@ -150,10 +173,48 @@ Cada plano pode usar:
|
|
|
150
173
|
`ready_stable_ms`; WebSocket, EventSource e polling não relacionado não
|
|
151
174
|
bloqueiam a espera. Se não surgir requisição correspondente, o passo conclui
|
|
152
175
|
após a janela de silêncio;
|
|
176
|
+
- `assert_network` valida resposta HTTP observada (inclusive sucesso 2xx ou erro
|
|
177
|
+
esperado); `wait_for_request` aguarda uma resposta usando `*` como curinga na
|
|
178
|
+
URL e filtros opcionais de método/status; `assert_ws` confere texto, pares
|
|
179
|
+
JSON esperados ou código de fechamento de WebSocket. `wait_for_request`
|
|
180
|
+
consulta o histórico desde o começo da chamada, inclusive requisições feitas
|
|
181
|
+
durante a navegação inicial e dentro de iframes; URLs cobertas por uma
|
|
182
|
+
asserção ficam retidas mesmo quando a SPA excede o buffer circular;
|
|
183
|
+
- `evaluate` lê somente caminhos de propriedades como `navigator.mediaDevices`,
|
|
184
|
+
`document.readyState` ou `location.pathname`. Não aceita código, chamadas de
|
|
185
|
+
função, armazenamento local ou propriedades de credenciais. Strings e números
|
|
186
|
+
voltam diretamente; objetos e arrays retornam somente tipo, chaves e tamanho,
|
|
187
|
+
sem despejar seus valores;
|
|
188
|
+
- `http_request` executa somente GET com a sessão da página; `inspect_cookies`
|
|
189
|
+
retorna apenas metadados e valores redigidos; `read_angular_state` devolve o
|
|
190
|
+
nome do estado e nomes dos parâmetros, sem valores. As três ações exigem
|
|
191
|
+
`local_only: true` e página em loopback. `http_request` fica restrito à mesma
|
|
192
|
+
origem, não segue redirecionamentos e limita/redige o corpo opcional;
|
|
193
|
+
- `frame: "first"` seleciona o primeiro iframe; `frame: {"url_contains":"..."}`
|
|
194
|
+
localiza um iframe pela URL. Uma string diferente continua buscando o nome ou
|
|
195
|
+
título exato do frame;
|
|
196
|
+
- `navigate_menu` aceita `path` para menus acessíveis ou `screen` para procurar
|
|
197
|
+
código/nome pela tela Acesso Rápido do SAFI. O segundo caminho usa a interface
|
|
198
|
+
do SAFI e preserva as verificações de acesso do próprio aplicativo;
|
|
199
|
+
- `new_tab`, `switch_tab` e `new_context` abrem/selecionam abas e criam contexto
|
|
200
|
+
separado dentro do fluxo; `target_page: "popup"` mantém popups abertos para
|
|
201
|
+
passos posteriores;
|
|
202
|
+
- `if_visible` em um clique torna a ação condicional e
|
|
203
|
+
`when: {"visible":"..."}` em cada plano limita as opções do Jev às que
|
|
204
|
+
correspondem à tela atual;
|
|
205
|
+
- `fill` é alias de `type`, `press_key` de `press`, `duration_ms` de `wait.ms` e
|
|
206
|
+
`value` de campos de texto. `timeout_ms` funciona por etapa. Placeholders usam
|
|
207
|
+
`{nome}`; referências desconhecidas e `{{nome}}` são recusadas antes da
|
|
208
|
+
navegação;
|
|
153
209
|
- `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
|
|
154
210
|
`Home`, `End`, setas, `Enter`, `Escape`, `Tab`, `Shift+Tab`, `Space`,
|
|
155
211
|
`Backspace` ou `Delete`. `clear` limpa um campo sem exigir texto. Sem alvo,
|
|
156
212
|
`press` envia a tecla ao elemento focado; com alvo, usa o localizador informado;
|
|
213
|
+
- `screenshot` grava uma imagem local; `full_page: true` inclui a página inteira.
|
|
214
|
+
Também é possível pedir uma captura após qualquer etapa com `screenshot: true`;
|
|
215
|
+
- `clear_storage` limpa cookies, local/session storage, IndexedDB, Cache Storage
|
|
216
|
+
e service workers do contexto atual. Como opção de fluxo,
|
|
217
|
+
`options.clear_storage: true` também recarrega a página antes do snapshot inicial;
|
|
157
218
|
- `assert_text`, `assert_value`, `assert_visible`, `assert_hidden` e
|
|
158
219
|
`assert_enabled`; `assert_text`
|
|
159
220
|
pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
|
|
@@ -169,19 +230,25 @@ Cada plano pode usar:
|
|
|
169
230
|
|
|
170
231
|
As proteções e evidências por etapa usam estes campos:
|
|
171
232
|
|
|
172
|
-
- `confirm_dialog` recebe `expected_text` e `button`. Em diálogos HTML, o MCP
|
|
173
|
-
confere o texto antes de localizar e clicar no botão. Também trata diálogos
|
|
174
|
-
nativos `alert`/`confirm`: precisa haver uma etapa `confirm_dialog` logo após
|
|
175
|
-
o clique que os abre, o texto deve corresponder e um diálogo inesperado é
|
|
176
|
-
fechado sem aceitar;
|
|
177
|
-
- `
|
|
233
|
+
- `confirm_dialog` recebe `expected_text` e `button`. Em diálogos HTML, o MCP
|
|
234
|
+
confere o texto antes de localizar e clicar no botão. Também trata diálogos
|
|
235
|
+
nativos `alert`/`confirm`: precisa haver uma etapa `confirm_dialog` logo após
|
|
236
|
+
o clique que os abre, o texto deve corresponder e um diálogo inesperado é
|
|
237
|
+
fechado sem aceitar;
|
|
238
|
+
- `confirm_modal` combina o clique no gatilho, a conferência do texto e o clique
|
|
239
|
+
afirmativo em uma única etapa protegida. Também aceita os aliases
|
|
240
|
+
`trigger`/`confirm`, por exemplo
|
|
241
|
+
`{"action":"confirm_modal","trigger":"Salvar","expected_text":"Confirma a alteração?","confirm":"OK"}`;
|
|
242
|
+
- `mutating: true` marca etapas que gravam dados ou disparam efeitos externos.
|
|
178
243
|
O MCP também classifica botões conhecidos como `Salvar`, `Emitir`, `Cancelar`
|
|
179
244
|
ou `Sim` pelo nome e pelo controle resolvido, inclusive quando o plano usa um
|
|
180
245
|
seletor CSS. `options.dry_run: true` executa até a primeira etapa mutável e
|
|
181
246
|
para antes dela; retorna `dry_run_stopped_before_step` e um
|
|
182
|
-
`confirmation_token` temporário, de uso único e vinculado ao fluxo e à página.
|
|
183
|
-
Reenvie a mesma chamada com `options.confirmation_token` para
|
|
184
|
-
|
|
247
|
+
`confirmation_token` temporário, de uso único e vinculado ao fluxo e à página.
|
|
248
|
+
Reenvie a mesma chamada com `options.confirmation_token` para retomar no passo
|
|
249
|
+
pausado sem repetir os passos anteriores; o MCP confere a rota e o alvo da
|
|
250
|
+
mutação antes de executá-la. Ele pausa novamente antes de cada outra etapa
|
|
251
|
+
mutável. Sem `dry_run`,
|
|
185
252
|
o primeiro pedido de ação mutável também retorna `status: "confirmation_required"`
|
|
186
253
|
e token; nenhuma etapa mutável roda sem essa autorização. O token expira após
|
|
187
254
|
dez minutos por padrão;
|
|
@@ -217,9 +284,34 @@ incluindo respostas 2xx ou erros esperados como 404. Exemplo:
|
|
|
217
284
|
}
|
|
218
285
|
```
|
|
219
286
|
|
|
220
|
-
Essa asserção aparece na evidência como `response_status`, separado do campo
|
|
221
|
-
`status` da etapa (`passed` ou `failed`). `message_contains` lê somente resposta
|
|
222
|
-
da mesma origem e respeita o limite configurado para captura de corpos.
|
|
287
|
+
Essa asserção aparece na evidência como `response_status`, separado do campo
|
|
288
|
+
`status` da etapa (`passed` ou `failed`). `message_contains` lê somente resposta
|
|
289
|
+
da mesma origem e respeita o limite configurado para captura de corpos.
|
|
290
|
+
`assert_network` consulta respostas desde o marcador da etapa e usa a resposta
|
|
291
|
+
da navegação inicial como fallback quando nenhuma resposta posterior corresponde.
|
|
292
|
+
`wait_for_request` e `expected_outcome.request` consultam desde o início do fluxo.
|
|
293
|
+
URLs cobertas por uma asserção são retidas em um buffer separado limitado por
|
|
294
|
+
`jev_browser_mcp.browser.max_network_history_events` (4096 eventos nesta
|
|
295
|
+
configuração). A captura de página também observa requisições de iframes.
|
|
296
|
+
Um único plano `fast_path` composto apenas por `assert_network` e
|
|
297
|
+
`wait_for_request` não espera um snapshot visual, então endpoints que respondem
|
|
298
|
+
sem HTML também podem ser verificados. `navigation_http_status` registra um
|
|
299
|
+
status HTTP de erro recebido pela navegação inicial; ele não é uma falha de rede.
|
|
300
|
+
|
|
301
|
+
`options.capture_network: "all"` inclui até o limite de diagnóstico eventos
|
|
302
|
+
com URL sem query string, método, status, tipo de recurso, duração e cabeçalhos
|
|
303
|
+
de resposta de uma allowlist. `capture_network_url_contains` filtra as URLs.
|
|
304
|
+
Quando o Chromium informa cookies bloqueados, `blocked_cookies` mostra nome,
|
|
305
|
+
domínio, caminho, flags e motivo, sem revelar valores.
|
|
306
|
+
|
|
307
|
+
Para aguardar a API antes de abrir a interface, passe
|
|
308
|
+
`options.wait_for_http: {"url":"http://localhost:8000/health","timeout_ms":30000}`.
|
|
309
|
+
Também aceita apenas a URL como string ou `{ "url": "...", "timeout_seconds": 30 }`.
|
|
310
|
+
O probe faz GET e tenta novamente até o limite; qualquer resposta abaixo de 500
|
|
311
|
+
indica que o servidor respondeu (inclusive 4xx), enquanto 5xx e erros de conexão
|
|
312
|
+
são repetidos. Ao expirar, `reason` inclui a última causa. Por segurança, a URL
|
|
313
|
+
precisa ser loopback ou usar o mesmo host de `initial_url`; isso permite, por
|
|
314
|
+
exemplo, Vite em `localhost:5173` e API em `localhost:8000`.
|
|
223
315
|
|
|
224
316
|
Exemplo de parâmetro e extração: passe `params: {"pedido":"1528721"}`, filtre
|
|
225
317
|
com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
|
|
@@ -227,8 +319,10 @@ com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
|
|
|
227
319
|
A etapa seguinte pode localizar o mesmo documento com `name: "{documento}"`.
|
|
228
320
|
|
|
229
321
|
Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
|
|
230
|
-
localizadores, `near` ou `within`;
|
|
231
|
-
|
|
322
|
+
localizadores, `near` ou `within`; para esperar texto desaparecer, use
|
|
323
|
+
`{"condition":"hidden","text":"Carregando..."}`. Para esperar que texto suma
|
|
324
|
+
antes do primeiro passo, use `options.ready: {"hidden_text":"Carregando..."}`.
|
|
325
|
+
Para aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
|
|
232
326
|
`url_contains`. O filtro considera somente a atividade correspondente e termina
|
|
233
327
|
após a janela configurada sem atividade; também termina caso nenhuma requisição
|
|
234
328
|
correspondente apareça. Para validar status e corpo, prefira `assert_network`.
|
|
@@ -239,16 +333,44 @@ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
|
|
|
239
333
|
um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
|
|
240
334
|
controle próximo ao texto visível do rótulo.
|
|
241
335
|
|
|
242
|
-
`within` pode combinar um container e uma linha. Use, por exemplo,
|
|
336
|
+
`within` pode combinar um container e uma linha. Use, por exemplo,
|
|
243
337
|
`{"role":"cell","name":"Documento A","within":{"role":"table","row_containing_word":"1528721"}}`.
|
|
244
338
|
`row_containing_word` usa limites de palavra para não confundir `1528721` com
|
|
245
339
|
`15287210`; `row_containing_exact` continua disponível para texto de célula
|
|
246
340
|
exato. `check` e `uncheck` alteram checkboxes, e `select_option` aceita rótulo
|
|
247
341
|
exato (`option`), valor (`value`) ou rótulo parcial único (`label_contains`).
|
|
248
|
-
`navigate_menu` percorre uma lista de rótulos exatos e abre `#open_btn` quando o
|
|
249
|
-
primeiro item ainda está oculto. Se vários itens visíveis tiverem o mesmo
|
|
250
|
-
rótulo, seleciona a última ocorrência, útil quando o submenu recém-aberto
|
|
251
|
-
repete o nome da categoria pai.
|
|
342
|
+
`navigate_menu` percorre uma lista de rótulos exatos e abre `#open_btn` quando o
|
|
343
|
+
primeiro item ainda está oculto. Se vários itens visíveis tiverem o mesmo
|
|
344
|
+
rótulo, seleciona a última ocorrência, útil quando o submenu recém-aberto
|
|
345
|
+
repete o nome da categoria pai. Para o SAFI, `screen` pesquisa o nome ou código
|
|
346
|
+
na tela Acesso Rápido, exige um resultado único e clica no link oficial da linha;
|
|
347
|
+
por exemplo, `{"action":"navigate_menu","screen":"TCN00022"}`.
|
|
348
|
+
|
|
349
|
+
Em uma instância local do SAFI, `http_request` pode obter a lista de telas pela
|
|
350
|
+
sessão já aberta sem ler o HTML:
|
|
351
|
+
|
|
352
|
+
```json
|
|
353
|
+
{
|
|
354
|
+
"flow": "Consultar telas disponíveis no perfil atual do SAFI",
|
|
355
|
+
"initial_url": "http://localhost:8011/safi/",
|
|
356
|
+
"candidate_plans": {
|
|
357
|
+
"inspect": {
|
|
358
|
+
"description": "Ler a lista de telas do SAFI no ambiente local",
|
|
359
|
+
"steps": [{
|
|
360
|
+
"action": "http_request",
|
|
361
|
+
"url": "/safi/api/menu/telas_menu",
|
|
362
|
+
"include_body": true
|
|
363
|
+
}]
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
"options": { "local_only": true, "fast_path": true }
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
O endpoint usa a sessão atual e pode retornar uma lista específica do perfil.
|
|
371
|
+
Os valores de cookies nunca são retornados. O acesso ao menu continua sujeito
|
|
372
|
+
às permissões verificadas pela própria interface; não use esse diagnóstico
|
|
373
|
+
contra produção.
|
|
252
374
|
|
|
253
375
|
```json
|
|
254
376
|
{
|
|
@@ -274,13 +396,14 @@ Exemplos para controles legados sem nome acessível:
|
|
|
274
396
|
{"action":"click","selector":"#save-document"}
|
|
275
397
|
```
|
|
276
398
|
|
|
277
|
-
|
|
278
|
-
`
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
399
|
+
Por padrão, controles sem nome não são devolvidos em listas separadas. Defina
|
|
400
|
+
`options.include_unnamed_controls: true` para receber
|
|
401
|
+
`unnamed_controls_initial` e `unnamed_controls_final`, cada uma com papel,
|
|
402
|
+
índice Playwright por papel, rótulo mais próximo e um trecho HTML sanitizado.
|
|
403
|
+
Nomes vazios ou compostos apenas por espaços e glyphs da área Unicode de uso
|
|
404
|
+
privado (como ícones Font Awesome) entram nessa lista e podem ser selecionados
|
|
405
|
+
com `name: ""` e o mesmo índice. O alias redundante `unnamed_controls` foi
|
|
406
|
+
removido. O placeholder conta como nome acessível.
|
|
284
407
|
O snapshot também resume campos de formulário com `id`, `name`, valor, estado
|
|
285
408
|
desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
|
|
286
409
|
sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
|
|
@@ -291,10 +414,14 @@ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
|
|
|
291
414
|
localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
|
|
292
415
|
`textbox`, `searchbox` ou `combobox`.
|
|
293
416
|
|
|
294
|
-
Por padrão, o MCP executa todos os passos antes de avaliar
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
417
|
+
Por padrão, o MCP executa todos os passos antes de avaliar os critérios.
|
|
418
|
+
`expected_outcome` aceita texto descritivo ou uma asserção estruturada, por
|
|
419
|
+
exemplo `{"text":"Tecnologia atualizada com sucesso."}` ou
|
|
420
|
+
`{"request":"PUT */api/tecnologia","status":200}`. A forma estruturada pode
|
|
421
|
+
incluir `message_contains` e reprova se a resposta correspondente não for
|
|
422
|
+
observada. Valores dentro de campos não contam como texto visível.
|
|
423
|
+
`stop_on_expected: true` habilita parada antecipada quando o texto esperado
|
|
424
|
+
aparece fora dos campos; mantenha `false` para fluxos com várias etapas.
|
|
298
425
|
|
|
299
426
|
Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
|
|
300
427
|
de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
|
|
@@ -330,11 +457,13 @@ verificar:
|
|
|
330
457
|
{"action":"audit_accessibility","standard":"wcag2aa"}
|
|
331
458
|
```
|
|
332
459
|
|
|
333
|
-
O MCP usa `@axe-core/playwright` com as tags WCAG 2.0 e 2.1 A/AA. O retorno
|
|
334
|
-
resume as violações por regra, impacto e quantidade de nós, sem copiar HTML ou
|
|
335
|
-
trechos da página.
|
|
336
|
-
|
|
337
|
-
|
|
460
|
+
O MCP usa `@axe-core/playwright` com as tags WCAG 2.0 e 2.1 A/AA. O retorno
|
|
461
|
+
resume as violações por regra, impacto e quantidade de nós, sem copiar HTML ou
|
|
462
|
+
trechos da página. A etapa falha quando encontra violações no impacto definido
|
|
463
|
+
por `fail_on_impact`; o padrão é `minor`, e níveis abaixo do limite são relatados
|
|
464
|
+
sem bloquear o fluxo. A auditoria automática encontra problemas comuns, mas não
|
|
465
|
+
comprova conformidade WCAG completa; combine-a com revisão manual e testes com
|
|
466
|
+
usuários assistivos.
|
|
338
467
|
|
|
339
468
|
Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
|
|
340
469
|
corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
|
|
@@ -431,25 +560,68 @@ validadores.
|
|
|
431
560
|
harness e CI. O processo MCP conserva browser, contexto e página entre
|
|
432
561
|
chamadas; cookies, local storage e estado da página permanecem enquanto o
|
|
433
562
|
processo estiver ativo. Encerre o processo para descartar o contexto isolado.
|
|
434
|
-
- `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
|
|
435
|
-
persistente `browser.computer_user_data_dir`, separado por navegador
|
|
436
|
-
|
|
437
|
-
|
|
563
|
+
- `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
|
|
564
|
+
persistente `browser.computer_user_data_dir`, separado por navegador e por
|
|
565
|
+
processo MCP. Não
|
|
566
|
+
reutiliza o perfil pessoal já aberto. Faça login uma vez nesse perfil; os
|
|
567
|
+
cookies permanecem nele entre chamadas.
|
|
568
|
+
|
|
569
|
+
`fresh_context: true` abre um contexto descartável, sem cookies nem storage do
|
|
570
|
+
perfil persistente; requer `initial_url` e fecha esse contexto ao terminar. Use
|
|
571
|
+
`clear_storage: true` para limpar cookies, local/session storage, IndexedDB,
|
|
572
|
+
Cache Storage e service workers antes de recarregar a página atual. Para salvar
|
|
573
|
+
e reutilizar o estado de autenticação de uma conta de teste, use um nome simples
|
|
574
|
+
em `storage_state`:
|
|
575
|
+
|
|
576
|
+
```json
|
|
577
|
+
{"options":{"storage_state":"aluno-a"}}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
O estado fica em `storage-state/<nome>.json` dentro da pasta de artefatos, com
|
|
581
|
+
permissões restritas no sistema operacional; não use uma conta real nem
|
|
582
|
+
compartilhe esse arquivo. `storage_state` não pode ser combinado com
|
|
583
|
+
`fresh_context` ou `clear_storage`.
|
|
438
584
|
|
|
439
585
|
`browser.max_flow_steps` limita os passos de cada plano candidato; os planos
|
|
440
|
-
não são somados. `browser.max_text_entry_chars` limita cada valor digitado. O
|
|
441
|
-
`status`, o plano escolhido, as ações executadas, a última
|
|
442
|
-
se o
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
586
|
+
não são somados. `browser.max_text_entry_chars` limita cada valor digitado. O
|
|
587
|
+
resultado contém `status`, o plano escolhido, as ações executadas, a última
|
|
588
|
+
captura acessível e se o texto descritivo esperado apareceu. `expected_outcome`
|
|
589
|
+
como string é descrição, não uma asserção: `expected_outcome_visible` é
|
|
590
|
+
informado separadamente, e um plano concluído pode passar mesmo se a frase não
|
|
591
|
+
estiver visível. Use `{ "text": "..." }` ou
|
|
592
|
+
`{ "request": "...", "status": 200 }` para exigir uma condição; as
|
|
593
|
+
verificações ficam em `expected_outcome_checks`, e uma condição não satisfeita
|
|
594
|
+
reprova o fluxo. As asserções `assert_*`, auditorias de acessibilidade e
|
|
595
|
+
downloads também aparecem em campos próprios do resultado.
|
|
596
|
+
|
|
597
|
+
Os status do fluxo incluem `passed`, `failed`, `incomplete`, `environment_error`,
|
|
598
|
+
`dry_run` e `confirmation_required`. O fluxo fica `passed` se não houve falha ou
|
|
599
|
+
pausa de mutação e o texto esperado apareceu, uma asserção/auditoria/download
|
|
600
|
+
passou ou todas as etapas do plano foram executadas. `incomplete` é devolvido
|
|
601
|
+
quando nenhuma dessas condições se aplica; confiança do Jev, sozinha, não
|
|
602
|
+
comprova o resultado. `environment_error` identifica falha de
|
|
603
|
+
navegação, autenticação ou sessão do browser; `navigation_error` contém o código
|
|
604
|
+
detectado, como `ERR_CONNECTION_REFUSED`, `AUTHENTICATION_REQUIRED` ou
|
|
605
|
+
`BROWSER_DISCONNECTED`, `BROWSER_PAGE_NOT_RESTORED` ou
|
|
606
|
+
`BROWSER_PROFILE_IN_USE`, e `reason` orienta a recuperação. Se uma navegação falhar
|
|
607
|
+
e a chamada seguinte tentar reutilizar a página, o MCP informa que a navegação
|
|
608
|
+
anterior não carregou; reinicie a navegação com
|
|
609
|
+
`continue_from_current_page: false` (ou o alias `reuse_page: false`). Uma sessão
|
|
610
|
+
desconectada pode ser reaberta por `browser_health`. `run_browser_flow` também
|
|
611
|
+
tenta reconectar e repetir uma vez quando a desconexão acontece antes da primeira
|
|
612
|
+
etapa; a repetição exige `initial_url`. Sem essa URL, o resultado informa
|
|
613
|
+
`BROWSER_PAGE_NOT_RESTORED`, e chamadas posteriores em `reuse_page` continuam
|
|
614
|
+
recusadas até uma nova navegação explícita. Se qualquer etapa já executou ou
|
|
615
|
+
há token de confirmação de mutação, o MCP não repete o fluxo automaticamente.
|
|
616
|
+
|
|
617
|
+
`current_url` é devolvido para diagnóstico sem query string nem fragmento; IDs
|
|
618
|
+
longos no caminho também podem ser redigidos. `timings_ms.ready_ms` mede a espera
|
|
619
|
+
da SPA; `warnings` registra capturas vazias durante transições; e `failed_step`
|
|
620
|
+
identifica índice, ação, localizador, timeout e erro resumido quando uma etapa
|
|
621
|
+
falha. Cada etapa executada também registra a composição do localizador usado
|
|
622
|
+
e, quando disponível, `resolved_target` com tag, `id`, papel, nome acessível,
|
|
623
|
+
`title` casado e `href` sanitizado do elemento resolvido. Etapas `type` só
|
|
624
|
+
incluem o valor final do campo quando `sensitive: false`.
|
|
453
625
|
|
|
454
626
|
Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
|
|
455
627
|
origem são capturadas mesmo quando usam transferência chunked e não enviam
|
|
@@ -472,30 +644,36 @@ continua informada mesmo quando a lista é truncada.
|
|
|
472
644
|
|
|
473
645
|
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
474
646
|
`block_trackers`, `block_fonts`, `local_only`, `busy_selectors`,
|
|
475
|
-
`auto_angular_idle`, `login_url_contains`, `login_text`, `capture_console_errors`,
|
|
476
|
-
`capture_network_errors`, `capture_network_error_bodies`, `
|
|
477
|
-
`
|
|
478
|
-
`
|
|
647
|
+
`auto_angular_idle`, `login_url_contains`, `login_text`, `capture_console_errors`,
|
|
648
|
+
`capture_network_errors`, `capture_network_error_bodies`, `capture_network`,
|
|
649
|
+
`capture_network_url_contains`, `ready_timeout_seconds`,
|
|
650
|
+
`ready_network_idle`, `ready_stable_ms`, `ready_text`, `ready`, `continue_from_current_page`,
|
|
651
|
+
`reuse_page`, `reuse_page_match`, `step_timeout_seconds`, `max_flow_steps`, `return_snapshot`,
|
|
479
652
|
`screenshot_on_failure`, `screenshot_on_success`, `trace_on_failure`,
|
|
480
|
-
`trace_on_success`, `record_video`, `snapshot_include_hidden`, `stop_on_expected`,
|
|
653
|
+
`trace_on_success`, `record_video`, `snapshot_include_hidden`, `include_unnamed_controls`, `stop_on_expected`,
|
|
481
654
|
`dry_run`, `confirmation_token`, `report_path`, `permissions`, `fake_media`,
|
|
482
655
|
`viewport`, `mobile`, `device_scale_factor`, `locale`, `timezone_id`,
|
|
483
|
-
`color_scheme`, `geolocation`
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
de
|
|
488
|
-
|
|
489
|
-
|
|
656
|
+
`color_scheme`, `geolocation`, `console_levels`, `fresh_context`,
|
|
657
|
+
`clear_storage`, `storage_state`, `wait_for_http` e `allow_mutations`. Sem override,
|
|
658
|
+
os padrões são lidos de `jev_browser_mcp` em
|
|
659
|
+
`config/ui-testing.json`: um plano candidato pula a chamada Decisions;
|
|
660
|
+
captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
|
|
661
|
+
de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
|
|
662
|
+
acrescentados ao snapshot. `return_snapshot: "diff"` é o padrão, e as listas de
|
|
663
|
+
controles sem nome só aparecem com `include_unnamed_controls: true`. O browser
|
|
664
|
+
espera a SPA renderizar uma captura acessível estável na navegação inicial.
|
|
665
|
+
Depois, a continuidade fica ligada por
|
|
490
666
|
padrão: `continue_from_current_page: true` mantém a página e seu estado entre
|
|
491
667
|
chamadas na mesma origem, não repete `page.goto` e consulta um snapshot atual
|
|
492
668
|
sem esperar novamente por `load`/`networkidle`. As etapas continuam aguardando
|
|
493
669
|
seus próprios alvos e condições. `reuse_page` segue como alias legado; defina
|
|
494
670
|
`continue_from_current_page: false` para iniciar cada chamada em `initial_url`.
|
|
495
671
|
Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
|
|
496
|
-
`initial_url`.
|
|
497
|
-
|
|
498
|
-
`continue_from_current_page: false`. `
|
|
672
|
+
`initial_url`. URLs da mesma origem são comparadas após normalizar e ordenar a
|
|
673
|
+
query string. Se a rota normalizada diferir, o MCP pede uma etapa `navigate` ou
|
|
674
|
+
`continue_from_current_page: false`. `reuse_page_match: "path"` ignora a query;
|
|
675
|
+
um plano cuja primeira etapa seja `navigate` pode trocar a rota explicitamente.
|
|
676
|
+
`snapshot_scope` aceita `body`, `main` ou
|
|
499
677
|
`dialog`; se `main` não existir, o snapshot usa `body`.
|
|
500
678
|
|
|
501
679
|
`block_trackers: true` bloqueia analytics/trackers e os tipos de recurso
|
|
@@ -511,14 +689,29 @@ precisaria chamar o provedor Jev; use exatamente um plano com `fast_path: true`.
|
|
|
511
689
|
`allow_mutations: true` pula a confirmação humana somente para URLs em
|
|
512
690
|
`localhost`, `127.0.0.1` ou `::1`; use esse modo apenas em ambientes locais
|
|
513
691
|
controlados.
|
|
514
|
-
`step_timeout_seconds` define o timeout padrão por etapa e cada etapa pode
|
|
515
|
-
substituí-lo com `timeout_seconds`. `max_flow_steps` reduz o limite por chamada,
|
|
516
|
-
sem superar o teto da configuração. `return_snapshot` aceita `
|
|
517
|
-
`none`; `diff` retorna linhas acessíveis novas desde o snapshot inicial.
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
692
|
+
`step_timeout_seconds` define o timeout padrão por etapa e cada etapa pode
|
|
693
|
+
substituí-lo com `timeout_seconds`. `max_flow_steps` reduz o limite por chamada,
|
|
694
|
+
sem superar o teto da configuração. `return_snapshot` aceita `diff`, `full` ou
|
|
695
|
+
`none`; `diff` retorna linhas acessíveis novas desde o snapshot inicial.
|
|
696
|
+
|
|
697
|
+
`options.ready` aguarda condições da aplicação antes do primeiro snapshot e da
|
|
698
|
+
seleção do plano. Aceita `"network_idle"`,
|
|
699
|
+
`{"hidden_text":"Aguarde."}` e `{"selector":"#cdTecnologia","has_value":true}`;
|
|
700
|
+
uma lista combina condições, e todas precisam passar. `has_value` aceita
|
|
701
|
+
`true` (valor não vazio), `false` (vazio) ou o valor textual exato.
|
|
702
|
+
`ready_text` também pode exigir uma frase no snapshot inicial;
|
|
703
|
+
`ready_network_idle: true` solicita uma espera best-effort por `networkidle`.
|
|
704
|
+
`ready_timeout_seconds` limita a espera de inicialização e `ready_stable_ms`
|
|
705
|
+
define a janela usada para considerar o snapshot estável.
|
|
706
|
+
|
|
707
|
+
`console_levels` aceita `log`, `info`, `debug`, `warn` e `error`. Com
|
|
708
|
+
`console_levels: ["log","warn","error"]` e `capture_network_errors`, o retorno
|
|
709
|
+
traz mensagens do console agrupadas por texto e nível (`console_messages` com
|
|
710
|
+
`count`), além de `console_errors` para compatibilidade. `network_failures`
|
|
711
|
+
contém eventos limitados em quantidade e tamanho. Mensagens idênticas do console
|
|
712
|
+
são agrupadas em uma entrada com `count`.
|
|
713
|
+
Controles sem nome acessível aparecem em um único aviso com a contagem e alguns
|
|
714
|
+
exemplos, em vez de gerar uma mensagem por controle.
|
|
522
715
|
Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
|
|
523
716
|
fragmentos, valores de formulário e nomes de arquivo são removidos ou
|
|
524
717
|
sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
|
|
@@ -552,15 +745,18 @@ Para testar microfone, conceda permissão no escopo da chamada:
|
|
|
552
745
|
{
|
|
553
746
|
"options": {
|
|
554
747
|
"permissions": ["microphone"],
|
|
555
|
-
"fake_media": "fixtures/resposta-aluno.wav",
|
|
748
|
+
"fake_media": {"audio":"fixtures/resposta-aluno.wav"},
|
|
556
749
|
"block_trackers": true
|
|
557
750
|
}
|
|
558
751
|
}
|
|
559
752
|
```
|
|
560
753
|
|
|
561
|
-
`fake_media`
|
|
562
|
-
|
|
563
|
-
|
|
754
|
+
`fake_media` aceita tanto o caminho WAV direto quanto o objeto
|
|
755
|
+
`{"audio":"caminho.wav"}`. Exige um WAV RIFF válido dentro de
|
|
756
|
+
`JEV_BROWSER_UPLOAD_ROOT` e respeita os mesmos limites de upload. Ao informar
|
|
757
|
+
`fake_media`, o MCP concede automaticamente a permissão `microphone`, adiciona
|
|
758
|
+
as opções de dispositivo falso do Chromium e usa o arquivo como entrada de
|
|
759
|
+
áudio. Sem esse arquivo, a
|
|
564
760
|
permissão de microfone usa o dispositivo autorizado pelo browser; no modo
|
|
565
761
|
`computer`, o sistema operacional ainda pode pedir acesso ao dispositivo.
|
|
566
762
|
|
|
@@ -580,22 +776,62 @@ andamento, sem repetir o clique.
|
|
|
580
776
|
|
|
581
777
|
Se o Chrome/Edge não iniciar porque o perfil persistente já está aberto, o erro
|
|
582
778
|
identifica o PID que o mantém ocupado quando o sistema consegue associar o
|
|
583
|
-
perfil ao processo. Em Windows, o MCP consulta a linha de comando dos processos
|
|
584
|
-
Chrome/Edge; em outros sistemas, usa o `SingletonLock` do Chromium.
|
|
585
|
-
|
|
779
|
+
perfil ao processo. Em Windows, o MCP consulta a linha de comando dos processos
|
|
780
|
+
Chrome/Edge; em outros sistemas, usa o `SingletonLock` do Chromium. O caminho
|
|
781
|
+
padrão já separa processos por PID; configure `JEV_BROWSER_PROFILE` para mudar
|
|
782
|
+
a raiz e `JEV_BROWSER_SESSION_ID` para nomear a instância.
|
|
586
783
|
Resultados MCP incluem `server_version`; erros também começam com a versão do
|
|
587
|
-
servidor para facilitar a comparação entre instalações. A ferramenta
|
|
588
|
-
`browser_health` informa se a sessão está ativa e tenta reconectar um browser
|
|
589
|
-
que encerrou desde a chamada anterior. Passe `{"restart":true}` para fechar e
|
|
590
|
-
reiniciar somente o navegador administrado por este processo MCP.
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
`harness_browser` e `computer_browser` aceitam `chrome` ou `msedge`.
|
|
595
|
-
`computer_user_data_dir` deve ficar fora do repositório e conter `{browser}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
784
|
+
servidor para facilitar a comparação entre instalações. A ferramenta
|
|
785
|
+
`browser_health` informa se a sessão está ativa e tenta reconectar um browser
|
|
786
|
+
que encerrou desde a chamada anterior. Passe `{"restart":true}` para fechar e
|
|
787
|
+
reiniciar somente o navegador administrado por este processo MCP. Perfil ocupado
|
|
788
|
+
é devolvido como `BROWSER_PROFILE_IN_USE` com o PID detectado e não provoca
|
|
789
|
+
encerramento do Chrome/Edge existente.
|
|
790
|
+
|
|
791
|
+
`harness_browser` e `computer_browser` aceitam `chrome` ou `msedge`.
|
|
792
|
+
`computer_user_data_dir` deve ficar fora do repositório e conter `{browser}` e
|
|
793
|
+
`{session}`;
|
|
794
|
+
o diretório persistente armazena dados de login e é resolvido sob a pasta home
|
|
795
|
+
do usuário quando começa com `~`. O Playwright MCP fica desabilitado até
|
|
796
|
+
`ORQUESTRADOR_MCP_PLAYWRIGHT_ENABLED=1` ser configurado no ambiente do harness.
|
|
797
|
+
|
|
798
|
+
## Preparar smoke autenticado local
|
|
799
|
+
|
|
800
|
+
O MCP não cria a identidade nem os dados do sistema testado. Para um smoke de
|
|
801
|
+
administração, suba a API e a UI locais, use um banco descartável com dados
|
|
802
|
+
fictícios e uma identidade OIDC de teste que tenha explicitamente a claim
|
|
803
|
+
`administrator`. Mantenha as regras de autorização de produção iguais; um token
|
|
804
|
+
de operador legado não deve ser promovido para admin só para fazer o smoke.
|
|
805
|
+
|
|
806
|
+
Faça o preflight nesta ordem:
|
|
807
|
+
|
|
808
|
+
1. `browser_health` confirma a versão, o perfil/sessão e a conexão do navegador.
|
|
809
|
+
Se o perfil estiver ocupado, use outro `JEV_BROWSER_SESSION_ID` ou
|
|
810
|
+
`JEV_BROWSER_PROFILE`; não encerre o Chrome do operador.
|
|
811
|
+
2. `options.wait_for_http` aguarda a API local responder antes de abrir a UI.
|
|
812
|
+
Informe a URL da interface em `initial_url` e a rota de health da API no
|
|
813
|
+
probe.
|
|
814
|
+
3. `run_browser_flow` confirma que a tela administrativa esperada está visível
|
|
815
|
+
e que a identidade abriu com papel administrativo. Se aparecer a tela de
|
|
816
|
+
login, configure a conta de teste ou o provedor OIDC local; não copie o token
|
|
817
|
+
para `flow`, `params` ou logs. Use `text_env` para campos secretos.
|
|
818
|
+
4. Valide primeiro uma prévia read-only com `assert_*`, `assert_network` e
|
|
819
|
+
captura de evidência. Para um fluxo que poderia gravar dados, use
|
|
820
|
+
`dry_run: true`; ele para antes da primeira etapa marcada como mutável.
|
|
821
|
+
5. Só execute o passo de gravação em dados fictícios, depois de conferir o texto
|
|
822
|
+
do diálogo com `confirm_modal`/`confirm_dialog` e autorizar o token de
|
|
823
|
+
confirmação. Reinicializações de serviços e consultas diretas ao banco ficam
|
|
824
|
+
fora do smoke de tela.
|
|
825
|
+
|
|
826
|
+
Esse preflight é um roteiro composto por `browser_health`, `wait_for_http` e
|
|
827
|
+
asserções da própria aplicação; não há uma ferramenta genérica que valide a
|
|
828
|
+
claim OIDC `administrator`. A checagem do papel precisa usar um sinal visível ou
|
|
829
|
+
uma asserção específica do sistema consumidor.
|
|
830
|
+
|
|
831
|
+
Um `expected_outcome` descreve o objetivo; o resultado `passed` vem das
|
|
832
|
+
asserções explícitas ou da conclusão do plano. Verifique
|
|
833
|
+
`expected_outcome_visible` separadamente quando a frase global fizer parte do
|
|
834
|
+
critério do teste.
|
|
599
835
|
|
|
600
836
|
Defina o valor secreto na variável indicada por `jev.credential_env`, usando o
|
|
601
837
|
secret manager ou ambiente do processo que inicia o harness. Não grave a chave
|
|
@@ -639,10 +875,13 @@ valores dos controles são substituídos e hrefs têm query string e fragmento
|
|
|
639
875
|
removidos; padrões de PII também são mascarados. Com fast-path, um plano não
|
|
640
876
|
gera chamada remota. Os passos, valores digitados, valores esperados pelas
|
|
641
877
|
asserções, caminhos e conteúdo dos arquivos não são enviados.
|
|
642
|
-
Não inclua segredos em `flow`, `expected_outcome` ou nas descrições. A resposta
|
|
643
|
-
retorna o plano escolhido quando houver decisão, custo/confiança do provedor
|
|
644
|
-
quando disponíveis e o snapshot final sanitizado.
|
|
645
|
-
|
|
878
|
+
Não inclua segredos em `flow`, `expected_outcome` ou nas descrições. A resposta
|
|
879
|
+
retorna o plano escolhido quando houver decisão, custo/confiança do provedor
|
|
880
|
+
quando disponíveis e o snapshot final sanitizado. Um `expected_outcome` em
|
|
881
|
+
texto simples é descritivo: `expected_outcome_visible` indica separadamente se
|
|
882
|
+
a frase apareceu, e completar o plano pode resultar em `passed` mesmo que ela
|
|
883
|
+
não apareça. Use a forma estruturada para tornar texto ou resposta de rede uma
|
|
884
|
+
condição obrigatória; se ela não passar, o fluxo falha.
|
|
646
885
|
|
|
647
886
|
`network_idle` é uma espera limitada e opcional. Polling e conexões contínuas
|
|
648
887
|
não relacionadas a `url_contains` não bloqueiam o modo filtrado; prefira
|