@diegosouzacdv/jev-browser-mcp 0.4.0 → 0.4.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/README.md +104 -30
- package/config/ui-testing.json +3 -0
- package/docs/jev-browser-mcp.md +104 -30
- package/mcp_servers/jev-browser-npm/src/config.mjs +6 -0
- package/mcp_servers/jev-browser-npm/src/flow.mjs +1016 -350
- package/mcp_servers/jev-browser-npm/src/jev-client.mjs +5 -4
- package/mcp_servers/jev-browser-npm/src/server.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
|
|
|
69
69
|
passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
|
|
70
70
|
hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
|
|
71
71
|
raiz local configurada e reações idempotentes a um comentário único. Também
|
|
72
|
-
aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
|
|
73
|
-
JavaScript enviado pelo harness
|
|
74
|
-
|
|
72
|
+
aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
|
|
73
|
+
JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
|
|
74
|
+
aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
|
|
75
|
+
são o último recurso e geram um aviso no resultado. Ele usa a
|
|
76
|
+
biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
|
|
75
77
|
Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
|
|
76
78
|
`stderr` para não misturar com JSON-RPC.
|
|
77
79
|
|
|
@@ -87,29 +89,55 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
|
|
|
87
89
|
plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
|
|
88
90
|
resultado esperado na tela.
|
|
89
91
|
|
|
90
|
-
Cada plano pode usar:
|
|
91
|
-
|
|
92
|
-
- `click`, `type`, `hover
|
|
92
|
+
Cada plano pode usar:
|
|
93
|
+
|
|
94
|
+
- `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
|
|
95
|
+
papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
|
|
96
|
+
`text`, `test_id` ou `selector`;
|
|
97
|
+
- `near: {"text":"..."}` para localizar o controle logo depois de um texto,
|
|
98
|
+
e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
|
|
99
|
+
- `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
|
|
100
|
+
o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
|
|
101
|
+
com `opacity: 0`;
|
|
102
|
+
- `name: ""` com `index` não negativo para controles sem nome. O resultado
|
|
103
|
+
inclui um aviso porque a posição pode mudar entre execuções. O índice é
|
|
104
|
+
zero-based para o mesmo papel e segue o localizador Playwright
|
|
105
|
+
`{role, name: ""}`; controles desabilitados não aparecem no diagnóstico, mas
|
|
106
|
+
continuam contando para que o índice aponte ao controle correto;
|
|
107
|
+
- `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
|
|
108
|
+
em `warnings`; não é permitido enviar JavaScript nem coordenadas;
|
|
93
109
|
- `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
|
|
94
110
|
- `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
|
|
95
111
|
`blur: true` para desfocar o campo e `sensitive: false` para permitir que o
|
|
96
|
-
valor apareça nas evidências;
|
|
112
|
+
valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
|
|
97
113
|
- `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
|
|
98
|
-
`text_hidden`)
|
|
99
|
-
|
|
100
|
-
`
|
|
114
|
+
`text_hidden`). `wait_for_text` aceita `fail_on: {"role":"alert"}` para
|
|
115
|
+
interromper a espera assim que um alerta visível aparecer e incluir seu texto
|
|
116
|
+
no erro. `network_idle` aceita `url_contains` para aguardar só as requisições
|
|
117
|
+
correspondentes;
|
|
118
|
+
- `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
|
|
119
|
+
`Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
|
|
120
|
+
envia a tecla ao elemento focado; com alvo, usa o localizador informado;
|
|
101
121
|
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
|
|
102
122
|
pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
|
|
103
123
|
- `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
|
|
104
124
|
dropzone;
|
|
105
125
|
- `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
|
|
106
|
-
- `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
|
|
107
|
-
não repetem uma reação já no estado pedido e distinguem `Curtir` de
|
|
108
|
-
`Descurtir`.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
- `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
|
|
127
|
+
não repetem uma reação já no estado pedido e distinguem `Curtir` de
|
|
128
|
+
`Descurtir`.
|
|
129
|
+
|
|
130
|
+
Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
|
|
131
|
+
localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
|
|
132
|
+
aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
|
|
133
|
+
`url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
|
|
134
|
+
esperar que ela termine.
|
|
135
|
+
|
|
136
|
+
Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
|
|
137
|
+
container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
|
|
138
|
+
ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
|
|
139
|
+
um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
|
|
140
|
+
controle próximo ao texto visível do rótulo.
|
|
113
141
|
|
|
114
142
|
```json
|
|
115
143
|
{
|
|
@@ -121,8 +149,43 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
|
|
|
121
149
|
```
|
|
122
150
|
|
|
123
151
|
```json
|
|
124
|
-
{"action":"click","role":"button","name":"Add to cart","index":0}
|
|
125
|
-
```
|
|
152
|
+
{"action":"click","role":"button","name":"Add to cart","index":0}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Exemplos para controles legados sem nome acessível:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
|
|
159
|
+
{"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
|
|
160
|
+
{"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
|
|
161
|
+
{"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
|
|
162
|
+
{"action":"click","role":"button","name":"","index":0}
|
|
163
|
+
{"action":"click","selector":"#save-document"}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
O reconhecimento retorna `unnamed_controls_initial` e
|
|
167
|
+
`unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
|
|
168
|
+
mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
|
|
169
|
+
sem nome. `unnamed_controls` continua disponível como alias da lista final. O
|
|
170
|
+
placeholder conta como nome acessível. O snapshot também resume campos de
|
|
171
|
+
formulário com `id`, `name`, valor, estado
|
|
172
|
+
desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
|
|
173
|
+
sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
|
|
174
|
+
é `false` por padrão; defina `true` somente quando precisar inspecionar campos
|
|
175
|
+
ocultos também.
|
|
176
|
+
|
|
177
|
+
Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
|
|
178
|
+
localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
|
|
179
|
+
`textbox`, `searchbox` ou `combobox`.
|
|
180
|
+
|
|
181
|
+
Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
|
|
182
|
+
Valores dentro de campos não contam como resultado visível. `stop_on_expected:
|
|
183
|
+
true` habilita parada antecipada quando o texto esperado aparece fora dos
|
|
184
|
+
campos; mantenha `false` para fluxos com várias etapas.
|
|
185
|
+
|
|
186
|
+
Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
|
|
187
|
+
de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
|
|
188
|
+
e erro.
|
|
126
189
|
|
|
127
190
|
### Captura de downloads
|
|
128
191
|
|
|
@@ -159,12 +222,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
|
|
|
159
222
|
encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
|
|
160
223
|
com revisão manual e testes com usuários assistivos.
|
|
161
224
|
|
|
162
|
-
Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
|
|
163
|
-
corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
|
|
164
|
-
conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
|
|
165
|
-
configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
|
|
166
|
-
próximos quando o snapshot os encontrar.
|
|
167
|
-
|
|
225
|
+
Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
|
|
226
|
+
corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
|
|
227
|
+
conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
|
|
228
|
+
configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
|
|
229
|
+
próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
|
|
230
|
+
localizadores explícitos de último recurso e geram aviso. O plano não aceita
|
|
231
|
+
JavaScript enviado pelo harness nem coordenadas.
|
|
168
232
|
|
|
169
233
|
Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
|
|
170
234
|
asserções são aceitos. `comment` também é aceito em planos e passos, mas é
|
|
@@ -265,8 +329,16 @@ esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
|
265
329
|
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
266
330
|
confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
|
|
267
331
|
espera da SPA; `warnings` registra capturas vazias durante transições; e
|
|
268
|
-
`failed_step` identifica índice, ação,
|
|
269
|
-
etapa falha.
|
|
332
|
+
`failed_step` identifica índice, ação, localizador, timeout e erro resumido
|
|
333
|
+
quando uma etapa falha. Cada etapa executada também registra a composição do
|
|
334
|
+
localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel
|
|
335
|
+
e nome acessível do elemento resolvido. Etapas `type` só incluem o valor final
|
|
336
|
+
do campo quando `sensitive: false`.
|
|
337
|
+
|
|
338
|
+
Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
|
|
339
|
+
origem são capturadas mesmo quando usam transferência chunked e não enviam
|
|
340
|
+
`Content-Length`. Corpos acima do limite, com formato inválido ou que não
|
|
341
|
+
podem ser lidos com segurança são omitidos e explicados em `warnings`.
|
|
270
342
|
|
|
271
343
|
`jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
|
|
272
344
|
seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
|
|
@@ -285,11 +357,13 @@ continua informada mesmo quando a lista é truncada.
|
|
|
285
357
|
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
286
358
|
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
287
359
|
`capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
|
|
288
|
-
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure
|
|
289
|
-
`trace_on_failure`. Sem override,
|
|
360
|
+
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
|
|
361
|
+
`trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
|
|
362
|
+
os padrões são lidos de `jev_browser_mcp` em
|
|
290
363
|
`config/ui-testing.json`: um plano candidato pula a chamada Decisions;
|
|
291
364
|
captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
|
|
292
|
-
de recursos ficam desligados
|
|
365
|
+
de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
|
|
366
|
+
acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
|
|
293
367
|
acessível estável. `ready_text` pode identificar o conteúdo que marca a
|
|
294
368
|
prontidão. `reuse_page: true` pula a navegação somente quando a página e
|
|
295
369
|
`initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
|
package/config/ui-testing.json
CHANGED
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"max_step_timeout_seconds": 60,
|
|
33
33
|
"key_delay_ms_default": 30,
|
|
34
34
|
"reuse_page_default": false,
|
|
35
|
+
"stop_on_expected_default": false,
|
|
36
|
+
"snapshot_include_hidden_default": false,
|
|
37
|
+
"visibility_poll_interval_ms_default": 50,
|
|
35
38
|
"capture_network_error_bodies_default": false,
|
|
36
39
|
"max_network_error_body_bytes": 65536,
|
|
37
40
|
"max_network_error_message_chars": 300,
|
package/docs/jev-browser-mcp.md
CHANGED
|
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
|
|
|
69
69
|
passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
|
|
70
70
|
hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
|
|
71
71
|
raiz local configurada e reações idempotentes a um comentário único. Também
|
|
72
|
-
aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
|
|
73
|
-
JavaScript enviado pelo harness
|
|
74
|
-
|
|
72
|
+
aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
|
|
73
|
+
JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
|
|
74
|
+
aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
|
|
75
|
+
são o último recurso e geram um aviso no resultado. Ele usa a
|
|
76
|
+
biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
|
|
75
77
|
Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
|
|
76
78
|
`stderr` para não misturar com JSON-RPC.
|
|
77
79
|
|
|
@@ -87,29 +89,55 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
|
|
|
87
89
|
plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
|
|
88
90
|
resultado esperado na tela.
|
|
89
91
|
|
|
90
|
-
Cada plano pode usar:
|
|
91
|
-
|
|
92
|
-
- `click`, `type`, `hover
|
|
92
|
+
Cada plano pode usar:
|
|
93
|
+
|
|
94
|
+
- `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
|
|
95
|
+
papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
|
|
96
|
+
`text`, `test_id` ou `selector`;
|
|
97
|
+
- `near: {"text":"..."}` para localizar o controle logo depois de um texto,
|
|
98
|
+
e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
|
|
99
|
+
- `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
|
|
100
|
+
o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
|
|
101
|
+
com `opacity: 0`;
|
|
102
|
+
- `name: ""` com `index` não negativo para controles sem nome. O resultado
|
|
103
|
+
inclui um aviso porque a posição pode mudar entre execuções. O índice é
|
|
104
|
+
zero-based para o mesmo papel e segue o localizador Playwright
|
|
105
|
+
`{role, name: ""}`; controles desabilitados não aparecem no diagnóstico, mas
|
|
106
|
+
continuam contando para que o índice aponte ao controle correto;
|
|
107
|
+
- `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
|
|
108
|
+
em `warnings`; não é permitido enviar JavaScript nem coordenadas;
|
|
93
109
|
- `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
|
|
94
110
|
- `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
|
|
95
111
|
`blur: true` para desfocar o campo e `sensitive: false` para permitir que o
|
|
96
|
-
valor apareça nas evidências;
|
|
112
|
+
valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
|
|
97
113
|
- `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
|
|
98
|
-
`text_hidden`)
|
|
99
|
-
|
|
100
|
-
`
|
|
114
|
+
`text_hidden`). `wait_for_text` aceita `fail_on: {"role":"alert"}` para
|
|
115
|
+
interromper a espera assim que um alerta visível aparecer e incluir seu texto
|
|
116
|
+
no erro. `network_idle` aceita `url_contains` para aguardar só as requisições
|
|
117
|
+
correspondentes;
|
|
118
|
+
- `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
|
|
119
|
+
`Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
|
|
120
|
+
envia a tecla ao elemento focado; com alvo, usa o localizador informado;
|
|
101
121
|
- `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
|
|
102
122
|
pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
|
|
103
123
|
- `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
|
|
104
124
|
dropzone;
|
|
105
125
|
- `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
|
|
106
|
-
- `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
|
|
107
|
-
não repetem uma reação já no estado pedido e distinguem `Curtir` de
|
|
108
|
-
`Descurtir`.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
- `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
|
|
127
|
+
não repetem uma reação já no estado pedido e distinguem `Curtir` de
|
|
128
|
+
`Descurtir`.
|
|
129
|
+
|
|
130
|
+
Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
|
|
131
|
+
localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
|
|
132
|
+
aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
|
|
133
|
+
`url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
|
|
134
|
+
esperar que ela termine.
|
|
135
|
+
|
|
136
|
+
Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
|
|
137
|
+
container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
|
|
138
|
+
ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
|
|
139
|
+
um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
|
|
140
|
+
controle próximo ao texto visível do rótulo.
|
|
113
141
|
|
|
114
142
|
```json
|
|
115
143
|
{
|
|
@@ -121,8 +149,43 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
|
|
|
121
149
|
```
|
|
122
150
|
|
|
123
151
|
```json
|
|
124
|
-
{"action":"click","role":"button","name":"Add to cart","index":0}
|
|
125
|
-
```
|
|
152
|
+
{"action":"click","role":"button","name":"Add to cart","index":0}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Exemplos para controles legados sem nome acessível:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
|
|
159
|
+
{"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
|
|
160
|
+
{"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
|
|
161
|
+
{"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
|
|
162
|
+
{"action":"click","role":"button","name":"","index":0}
|
|
163
|
+
{"action":"click","selector":"#save-document"}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
O reconhecimento retorna `unnamed_controls_initial` e
|
|
167
|
+
`unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
|
|
168
|
+
mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
|
|
169
|
+
sem nome. `unnamed_controls` continua disponível como alias da lista final. O
|
|
170
|
+
placeholder conta como nome acessível. O snapshot também resume campos de
|
|
171
|
+
formulário com `id`, `name`, valor, estado
|
|
172
|
+
desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
|
|
173
|
+
sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
|
|
174
|
+
é `false` por padrão; defina `true` somente quando precisar inspecionar campos
|
|
175
|
+
ocultos também.
|
|
176
|
+
|
|
177
|
+
Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
|
|
178
|
+
localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
|
|
179
|
+
`textbox`, `searchbox` ou `combobox`.
|
|
180
|
+
|
|
181
|
+
Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
|
|
182
|
+
Valores dentro de campos não contam como resultado visível. `stop_on_expected:
|
|
183
|
+
true` habilita parada antecipada quando o texto esperado aparece fora dos
|
|
184
|
+
campos; mantenha `false` para fluxos com várias etapas.
|
|
185
|
+
|
|
186
|
+
Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
|
|
187
|
+
de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
|
|
188
|
+
e erro.
|
|
126
189
|
|
|
127
190
|
### Captura de downloads
|
|
128
191
|
|
|
@@ -159,12 +222,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
|
|
|
159
222
|
encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
|
|
160
223
|
com revisão manual e testes com usuários assistivos.
|
|
161
224
|
|
|
162
|
-
Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
|
|
163
|
-
corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
|
|
164
|
-
conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
|
|
165
|
-
configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
|
|
166
|
-
próximos quando o snapshot os encontrar.
|
|
167
|
-
|
|
225
|
+
Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
|
|
226
|
+
corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
|
|
227
|
+
conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
|
|
228
|
+
configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
|
|
229
|
+
próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
|
|
230
|
+
localizadores explícitos de último recurso e geram aviso. O plano não aceita
|
|
231
|
+
JavaScript enviado pelo harness nem coordenadas.
|
|
168
232
|
|
|
169
233
|
Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
|
|
170
234
|
asserções são aceitos. `comment` também é aceito em planos e passos, mas é
|
|
@@ -265,8 +329,16 @@ esse resultado e `expected_outcome_visible` continua descrevendo somente o
|
|
|
265
329
|
texto global. `incomplete` significa que nenhum critério foi comprovado;
|
|
266
330
|
confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
|
|
267
331
|
espera da SPA; `warnings` registra capturas vazias durante transições; e
|
|
268
|
-
`failed_step` identifica índice, ação,
|
|
269
|
-
etapa falha.
|
|
332
|
+
`failed_step` identifica índice, ação, localizador, timeout e erro resumido
|
|
333
|
+
quando uma etapa falha. Cada etapa executada também registra a composição do
|
|
334
|
+
localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel
|
|
335
|
+
e nome acessível do elemento resolvido. Etapas `type` só incluem o valor final
|
|
336
|
+
do campo quando `sensitive: false`.
|
|
337
|
+
|
|
338
|
+
Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
|
|
339
|
+
origem são capturadas mesmo quando usam transferência chunked e não enviam
|
|
340
|
+
`Content-Length`. Corpos acima do limite, com formato inválido ou que não
|
|
341
|
+
podem ser lidos com segurança são omitidos e explicados em `warnings`.
|
|
270
342
|
|
|
271
343
|
`jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
|
|
272
344
|
seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
|
|
@@ -285,11 +357,13 @@ continua informada mesmo quando a lista é truncada.
|
|
|
285
357
|
O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
|
|
286
358
|
`block_trackers`, `capture_console_errors`, `capture_network_errors`,
|
|
287
359
|
`capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
|
|
288
|
-
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure
|
|
289
|
-
`trace_on_failure`. Sem override,
|
|
360
|
+
`ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
|
|
361
|
+
`trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
|
|
362
|
+
os padrões são lidos de `jev_browser_mcp` em
|
|
290
363
|
`config/ui-testing.json`: um plano candidato pula a chamada Decisions;
|
|
291
364
|
captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
|
|
292
|
-
de recursos ficam desligados
|
|
365
|
+
de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
|
|
366
|
+
acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
|
|
293
367
|
acessível estável. `ready_text` pode identificar o conteúdo que marca a
|
|
294
368
|
prontidão. `reuse_page: true` pula a navegação somente quando a página e
|
|
295
369
|
`initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
|
|
@@ -27,6 +27,9 @@ const CONFIG_KEYS = {
|
|
|
27
27
|
"max_step_timeout_seconds",
|
|
28
28
|
"key_delay_ms_default",
|
|
29
29
|
"reuse_page_default",
|
|
30
|
+
"stop_on_expected_default",
|
|
31
|
+
"snapshot_include_hidden_default",
|
|
32
|
+
"visibility_poll_interval_ms_default",
|
|
30
33
|
"capture_network_error_bodies_default",
|
|
31
34
|
"max_network_error_body_bytes",
|
|
32
35
|
"max_network_error_message_chars",
|
|
@@ -264,6 +267,7 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
264
267
|
postStepReadyTimeoutMs: postStepReadyTimeoutSeconds * 1000,
|
|
265
268
|
maxStepTimeoutSeconds: positiveNumber(browserOptions.max_step_timeout_seconds, "jev_browser_mcp.browser.max_step_timeout_seconds"),
|
|
266
269
|
keyDelayMs: positiveNumber(browserOptions.key_delay_ms_default, "jev_browser_mcp.browser.key_delay_ms_default", true),
|
|
270
|
+
visibilityPollMs: positiveNumber(browserOptions.visibility_poll_interval_ms_default, "jev_browser_mcp.browser.visibility_poll_interval_ms_default", true),
|
|
267
271
|
maxNetworkErrorBodyBytes: positiveNumber(browserOptions.max_network_error_body_bytes, "jev_browser_mcp.browser.max_network_error_body_bytes", true),
|
|
268
272
|
maxNetworkErrorMessageChars: positiveNumber(browserOptions.max_network_error_message_chars, "jev_browser_mcp.browser.max_network_error_message_chars", true),
|
|
269
273
|
maxUploadFiles: positiveNumber(browserOptions.max_upload_files, "jev_browser_mcp.browser.max_upload_files", true),
|
|
@@ -287,6 +291,8 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
287
291
|
blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
|
|
288
292
|
readyNetworkIdle: booleanValue(browserOptions.ready_network_idle_default, "jev_browser_mcp.browser.ready_network_idle_default"),
|
|
289
293
|
reusePage: booleanValue(browserOptions.reuse_page_default, "jev_browser_mcp.browser.reuse_page_default"),
|
|
294
|
+
stopOnExpected: booleanValue(browserOptions.stop_on_expected_default, "jev_browser_mcp.browser.stop_on_expected_default"),
|
|
295
|
+
snapshotIncludeHidden: booleanValue(browserOptions.snapshot_include_hidden_default, "jev_browser_mcp.browser.snapshot_include_hidden_default"),
|
|
290
296
|
readyTimeoutSeconds: readyTimeoutSecondsDefault,
|
|
291
297
|
readyStableMs: readyStableMsDefault,
|
|
292
298
|
snapshotScope,
|