appium_failure_helper 0.6.5 → 0.6.6
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.
- checksums.yaml +4 -4
- data/README.md +75 -241
- data/lib/appium_failure_helper/report_generator.rb +23 -13
- data/lib/appium_failure_helper/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af82bef9bc09a790faa2882a886325c2da1ae7cfbd4a25541b0025f0bb9bb479
|
4
|
+
data.tar.gz: 3fe174544dba0f9453d017900968fa84f07444337b4d910648f289a81e5fa5ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c338bf9158ab769f74dbaa3be08a42581b8bcacdd997d61a27751a0cc5e4b349888e02124d8c70a2395643e46486e6213444e99a1b7222d231ed3ece9170cd4
|
7
|
+
data.tar.gz: fb6f836aa0ed1b947658b787fff8768cfff589356440137265d7cf8ffd3a8e33664c298e881fa1b1b2850c691f5df9434a71cbd602fc7b1b058677eccf51741e
|
data/README.md
CHANGED
@@ -1,290 +1,124 @@
|
|
1
|
-
#
|
1
|
+
# Diagnóstico Inteligente de Falhas Appium
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+

|
4
|
+

|
5
|
+

|
6
6
|
|
7
|
-
|
7
|
+
Uma ferramenta robusta para diagnosticar falhas em testes automatizados com Appium, transformando erros de `NoSuchElementException` em relatórios interativos e inteligentes. Chega de perder tempo depurando seletores quebrados; deixe que a análise automatizada faça o trabalho pesado por você.
|
8
8
|
|
9
|
-
|
9
|
+
## ✨ Principais Funcionalidades
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
- [Exemplos de Uso](#exemplos-de-uso)
|
19
|
-
- [Cucumber (hook After)](#cucumber-hook-after)
|
20
|
-
- [RSpec (after :each)](#rspec-after-each)
|
21
|
-
- [Formato dos Artefatos Gerados](#formato-dos-artefatos-gerados)
|
22
|
-
- [Lógica de Geração de XPaths (detalhada)](#lógica-de-geração-de-xpaths-detalhada)
|
23
|
-
- [Tratamento de Dados e Deduplicação](#tratamento-de-dados-e-deduplicação)
|
24
|
-
- [Relatório HTML Interativo](#relatório-html-interativo)
|
25
|
-
- [Logging e Observabilidade](#logging-e-observabilidade)
|
26
|
-
- [Testes e Qualidade](#testes-e-qualidade)
|
27
|
-
- [Roadmap e Contribuição](#roadmap-e-contribuição)
|
28
|
-
- [Licença](#licença)
|
11
|
+
* **Relatório HTML Interativo:** Gera um relatório visual completo a cada falha, com screenshot, análise detalhada e dump de todos os elementos da tela.
|
12
|
+
* **Análise de Mapeamento ("De/Para"):** Verifica automaticamente se o elemento que falhou está definido em alguma fonte de dados do projeto, como:
|
13
|
+
* **Arquivos `.yaml`** gerados dinamicamente durante a execução.
|
14
|
+
* **Arquivos de elementos Ruby (`.rb`)** estáticos.
|
15
|
+
* **Sugestão por Similaridade:** Utiliza o algoritmo de Levenshtein para encontrar elementos na tela que são "parecidos" com o localizador que falhou, sugerindo correções para erros de digitação.
|
16
|
+
* **Arquitetura Modular:** O código é limpo, organizado e fácil de estender, seguindo o Princípio da Responsabilidade Única.
|
17
|
+
* **Suporte Multiplataforma:** A lógica de análise e sugestão funciona tanto para **Android** quanto para **iOS**.
|
29
18
|
|
30
|
-
|
19
|
+
## 🚀 Instalação
|
31
20
|
|
32
|
-
|
33
|
-
|
34
|
-
No momento em que um teste falha, o módulo realiza, de forma atômica e thread-safe:
|
35
|
-
1. captura de screenshot,
|
36
|
-
2. extração do `page_source` completo (XML),
|
37
|
-
3. varredura da árvore de elementos para gerar localizadores sugeridos,
|
38
|
-
4. escrita de dois YAMLs (focado e completo) e um relatório HTML que agrega tudo.
|
39
|
-
|
40
|
-
Todos os artefatos são salvos em uma pasta timestamped (formato `YYYY_MM_DD_HHMMSS`) dentro de `reports_failure/`.
|
41
|
-
|
42
|
-
---
|
43
|
-
|
44
|
-
## Funcionalidades
|
45
|
-
|
46
|
-
- Captura automática de screenshot PNG.
|
47
|
-
- Export completo de `page_source` em XML.
|
48
|
-
- Geração de `failure_analysis_*.yaml` (focado no elemento que falhou).
|
49
|
-
- Geração de `all_elements_dump_*.yaml` (todos os elementos com localizadores sugeridos).
|
50
|
-
- Relatório HTML interativo que combine screenshot, XML formatado e lista de localizadores.
|
51
|
-
- Geração de XPaths otimizados para **Android** e **iOS**.
|
52
|
-
- Truncamento de atributos longos (configurável).
|
53
|
-
- Eliminação de elementos duplicados e normalização de atributos.
|
54
|
-
- Logging via `Logger` do Ruby (Níveis: DEBUG/INFO/WARN/ERROR).
|
55
|
-
- Configuração via bloco `configure` (opcional).
|
56
|
-
|
57
|
-
---
|
58
|
-
|
59
|
-
## Arquitetura e Fluxo
|
60
|
-
|
61
|
-
1. **Hook de Testes** (Cucumber/RSpec) → invoca `Capture.handler_failure(driver, exception)`
|
62
|
-
2. **Capture.handler_failure**:
|
63
|
-
- estabelece pasta de saída com timestamp;
|
64
|
-
- chama `driver.screenshot` (salva PNG);
|
65
|
-
- chama `driver.page_source` (salva XML);
|
66
|
-
- percorre XML e cria árvore de elementos;
|
67
|
-
- para cada elemento gera candidate XPaths aplicando regras por plataforma;
|
68
|
-
- grava `failure_analysis_*.yaml` (prioriza elemento indicado) e `all_elements_dump_*.yaml`;
|
69
|
-
- monta `report_*.html` agregando tudo.
|
70
|
-
3. Logs detalhados emitidos durante a execução.
|
71
|
-
|
72
|
-
---
|
73
|
-
|
74
|
-
## Instalação
|
75
|
-
|
76
|
-
**Como gem (exemplo):**
|
77
|
-
|
78
|
-
Adicione ao `Gemfile` do projeto:
|
21
|
+
Adicione esta linha ao `Gemfile` do seu projeto de automação:
|
79
22
|
|
80
23
|
```ruby
|
81
|
-
gem 'appium_failure_helper'
|
24
|
+
gem 'appium_failure_helper' # (ou o nome que você der para a sua gem)
|
82
25
|
```
|
83
26
|
|
84
|
-
|
27
|
+
E então execute no seu terminal:
|
85
28
|
|
86
|
-
```
|
29
|
+
```sh
|
87
30
|
bundle install
|
88
31
|
```
|
89
32
|
|
90
|
-
|
33
|
+
## ⚙️ Configuração e Uso
|
91
34
|
|
92
|
-
|
35
|
+
A integração com projetos baseados em **Cucumber** é extremamente simples.
|
93
36
|
|
94
|
-
|
95
|
-
|
96
|
-
```
|
97
|
-
|
98
|
-
---
|
99
|
-
|
100
|
-
## API Pública / Integração
|
101
|
-
|
102
|
-
### `AppiumFailureHelper::Capture`
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
# handler_failure(driver, exception, options = {})
|
106
|
-
# - driver: objeto de sessão Appium (Selenium::WebDriver / Appium::Driver)
|
107
|
-
# - exception: exceção capturada no momento da falha
|
108
|
-
# - options: hash com overrides (ex: output_dir:)
|
109
|
-
AppiumFailureHelper::Capture.handler_failure(appium_driver, scenario.exception)
|
110
|
-
```
|
37
|
+
1. No seu arquivo `features/support/env.rb`, adicione o `require` para carregar a ferramenta.
|
38
|
+
2. Dentro do hook `After`, adicione um bloco condicional para chamar o helper sempre que um cenário falhar.
|
111
39
|
|
112
|
-
|
40
|
+
**Exemplo completo para `features/support/env.rb`:**
|
113
41
|
|
114
42
|
```ruby
|
115
|
-
|
116
|
-
# ver bloco de configuração acima
|
117
|
-
end
|
118
|
-
```
|
43
|
+
# features/support/env.rb
|
119
44
|
|
120
|
-
|
45
|
+
require 'appium_lib'
|
46
|
+
require 'cucumber'
|
121
47
|
|
122
|
-
|
123
|
-
|
124
|
-
### Cucumber (hook `After`)
|
125
|
-
|
126
|
-
```ruby
|
127
|
-
# features/support/hooks.rb
|
48
|
+
# 1. Carrega a sua ferramenta com uma única linha
|
128
49
|
require 'appium_failure_helper'
|
129
50
|
|
51
|
+
# ... (outras configurações do seu ambiente) ...
|
52
|
+
|
53
|
+
# 2. Hook que executa após cada cenário de teste
|
130
54
|
After do |scenario|
|
55
|
+
# Se o cenário falhou, aciona o seu helper
|
131
56
|
if scenario.failed?
|
132
|
-
|
57
|
+
puts "\n--- CENÁRIO FALHOU! ACIONANDO O DIAGNÓSTICO INTELIGENTE ---"
|
58
|
+
|
59
|
+
# A chamada é simples e direta.
|
60
|
+
# Use a variável do seu driver (pode ser @driver, $driver, etc.)
|
61
|
+
AppiumFailureHelper.handler_failure(@driver, scenario.exception)
|
62
|
+
|
63
|
+
puts "--- HELPER FINALIZOU. VERIFIQUE A PASTA 'reports_failure' ---"
|
133
64
|
end
|
134
65
|
end
|
135
|
-
```
|
136
|
-
|
137
|
-
---
|
138
|
-
|
139
|
-
## Formato dos Artefatos Gerados
|
140
66
|
|
141
|
-
|
142
|
-
|
143
|
-
Arquivos gerados (ex.: TIMESTAMP = `2025_09_23_173045`):
|
144
|
-
|
145
|
-
```
|
146
|
-
screenshot_2025_09_23_173045.png
|
147
|
-
page_source_2025_09_23_173045.xml
|
148
|
-
failure_analysis_2025_09_23_173045.yaml
|
149
|
-
all_elements_dump_2025_09_23_173045.yaml
|
150
|
-
report_2025_09_23_173045.html
|
67
|
+
# ... (código para fechar o driver, etc.) ...
|
151
68
|
```
|
152
69
|
|
153
|
-
|
154
|
-
|
155
|
-
```yaml
|
156
|
-
failed_element:
|
157
|
-
platform: android
|
158
|
-
summary:
|
159
|
-
class: android.widget.Button
|
160
|
-
resource_id: com.example:id/submit
|
161
|
-
text: "Enviar"
|
162
|
-
suggested_xpaths:
|
163
|
-
- "//android.widget.Button[@resource-id='com.example:id/submit']"
|
164
|
-
- "//android.widget.Button[contains(@text,'Enviar')]"
|
165
|
-
capture_metadata:
|
166
|
-
screenshot: screenshot_2025_09_23_173045.png
|
167
|
-
page_source: page_source_2025_09_23_173045.xml
|
168
|
-
timestamp: "2025-09-23T17:30:45Z"
|
169
|
-
tips: "Priorize resource-id; se ausente, use accessibility id (content-desc) e class+text como fallback."
|
170
|
-
```
|
171
|
-
|
172
|
-
### Exemplo (simplificado) de `all_elements_dump_*.yaml`
|
173
|
-
|
174
|
-
```yaml
|
175
|
-
elements:
|
176
|
-
- id_hash: "a1b2c3..."
|
177
|
-
class: "android.widget.EditText"
|
178
|
-
resource_id: "com.example:id/input_email"
|
179
|
-
text: "example@example.com"
|
180
|
-
truncated_attributes:
|
181
|
-
hint: "Digite seu e-mail..."
|
182
|
-
suggested_xpaths:
|
183
|
-
- "//*[@resource-id='com.example:id/input_email']"
|
184
|
-
- "//android.widget.EditText[contains(@hint,'Digite seu e-mail')]"
|
185
|
-
```
|
186
|
-
|
187
|
-
---
|
188
|
-
|
189
|
-
## Lógica de Geração de XPaths (detalhada)
|
190
|
-
|
191
|
-
**Princípios gerais**
|
192
|
-
1. Priorizar identificadores estáveis (resource-id no Android / accessibility id no iOS).
|
193
|
-
2. Evitar XPaths com `index` como primeira opção (usado apenas como último recurso).
|
194
|
-
3. Combinar atributos quando necessário para aumentar a especificidade e evitar colisões.
|
195
|
-
4. Normalizar espaços e truncar textos longos.
|
70
|
+
E é isso! A ferramenta está pronta para agir.
|
196
71
|
|
197
|
-
|
72
|
+
## 📄 Entendendo o Relatório Gerado
|
198
73
|
|
199
|
-
|
200
|
-
1. `resource-id` → `//*[@resource-id='com.pkg:id/id']`
|
201
|
-
2. `content-desc` / `contentDescription` (accessibility) → `//*[@content-desc='x']`
|
202
|
-
3. `class` + `text` → `//android.widget.TextView[@class='...' and contains(normalize-space(@text),'...')]`
|
203
|
-
4. `class` + raça de atributos (combinações: enabled, clickable, package)
|
204
|
-
5. fallback: `//android.widget.Button[position()=n]` (último recurso)
|
74
|
+
Após uma falha, uma nova pasta será criada na raiz do seu projeto, seguindo o padrão: `reports_failure/failure_[timestamp]`.
|
205
75
|
|
206
|
-
|
207
|
-
1. `accessibility id` (nome accessibility) → `//*[@name='Submit']`
|
208
|
-
2. `label` / `value` → `//*[contains(@label,'...')]`
|
209
|
-
3. `type` + `label` → `//XCUIElementTypeButton[@label='OK']`
|
210
|
-
4. fallback: hierarquia / indices
|
76
|
+
Dentro dela, você encontrará 4 arquivos:
|
211
77
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
78
|
+
```
|
79
|
+
reports_failure/failure_20250924_154010/
|
80
|
+
|-- all_elements_dump_20250924_154010.yaml # Dump de todos os elementos da tela.
|
81
|
+
|-- failure_analysis_20250924_154010.yaml # Resumo da análise em formato YAML.
|
82
|
+
|-- page_source_20250924_154010.xml # O XML completo da tela no momento da falha.
|
83
|
+
`-- report_20250924_154010.html # O relatório interativo para abrir no navegador.
|
216
84
|
```
|
217
85
|
|
218
|
-
|
219
|
-
|
220
|
-
## Tratamento de Dados e Deduplicação
|
221
|
-
|
222
|
-
- **Truncamento**: atributos com comprimento acima de `attr_truncate_length` são truncados com sufixo `...` para evitar poluição do YAML.
|
223
|
-
- **Hash único por elemento**: é gerado um hash (sha1) baseado em conjunto de atributos relevantes (class+resource-id+content-desc+text) para identificar duplicados.
|
224
|
-
- **Remoção de nulos**: atributos vazios ou nulos são omitidos nos YAMLs.
|
225
|
-
- **Ordenação**: elementos no `all_elements_dump` são ordenados por prioridade de localizador (resource-id primeiro).
|
226
|
-
|
227
|
-
---
|
228
|
-
|
229
|
-
## Relatório HTML Interativo
|
230
|
-
|
231
|
-
O HTML gerado possui:
|
232
|
-
- Visualização inline do `screenshot` (img tag),
|
233
|
-
- Painel colapsável com o `page_source` (XML formatado e collapsible),
|
234
|
-
- Lista navegável de elementos com seus `suggested_xpaths` (botões para copiar),
|
235
|
-
- Ancoragem que permite focalizar: ao clicar em um XPath, realça o fragmento correspondente no XML (se possível),
|
236
|
-
- Metadados e link rápido para os YAMLs.
|
237
|
-
|
238
|
-
**Observação:** o HTML é gerado de forma estática — para realces dinâmicos é usado JavaScript simples embutido (sem dependências externas).
|
239
|
-
|
240
|
-
---
|
241
|
-
|
242
|
-
## Logging e Observabilidade
|
243
|
-
|
244
|
-
- Usa `Logger` padrão do Ruby:
|
245
|
-
- `DEBUG` para detalhamento completo (padrão em modo dev).
|
246
|
-
- `INFO` para resumo das ações realizadas.
|
247
|
-
- `WARN/ERROR` para problemas durante captura/escrita.
|
248
|
-
- Exemplos de mensagens:
|
249
|
-
- `[INFO] Creating failure report folder: reports_failure/2025_09_23_173045`
|
250
|
-
- `[DEBUG] Captured 4123 elements from page_source`
|
251
|
-
- `[ERROR] Failed to write screenshot: Permission denied`
|
252
|
-
|
253
|
-
---
|
86
|
+
### O Relatório HTML Interativo
|
254
87
|
|
255
|
-
|
88
|
+
Este é o principal artefato. Ele é dividido em seções claras para um diagnóstico rápido:
|
256
89
|
|
257
|
-
|
258
|
-
|
259
|
-
|
90
|
+
#### Análise de Mapeamento (Blocos Verde/Amarelo)
|
91
|
+
Estes blocos aparecem no topo e informam se o elemento que falhou foi encontrado nos arquivos de mapeamento do seu projeto.
|
92
|
+
* **Bloco Verde (Sucesso):** Confirma que o elemento foi encontrado em um arquivo `.yaml` ou `.rb`, mostrando o caminho e/ou o localizador correto. Isso geralmente indica um problema de timing ou de visibilidade do elemento na tela, já que a definição dele está correta.
|
93
|
+
* **Bloco Amarelo (Aviso):** Informa que o elemento **não foi encontrado** nos arquivos de mapeamento. Isso geralmente aponta para um erro de digitação no nome do elemento no seu código de teste.
|
260
94
|
|
261
|
-
|
95
|
+
#### Elemento com Falha (Bloco Vermelho)
|
96
|
+
Mostra exatamente qual `Tipo de Seletor` e `Valor Buscado` o Appium usou quando a falha ocorreu.
|
262
97
|
|
263
|
-
|
98
|
+
#### Screenshot da Falha
|
99
|
+
Uma imagem exata da tela no momento do erro.
|
264
100
|
|
265
|
-
|
266
|
-
|
267
|
-
- Export para outros formatos (JSON/CSV).
|
268
|
-
- Integração com ferramentas de observabilidade (Sentry, Datadog).
|
269
|
-
- Modo headless para gerar relatórios offline em pipelines.
|
101
|
+
#### Sugestões de Reparo (Análise de Similaridade)
|
102
|
+
Se houver elementos na tela com localizadores parecidos com o que falhou, eles serão listados aqui com uma pontuação de similaridade. É extremamente útil para corrigir pequenos erros de digitação nos seus seletores.
|
270
103
|
|
271
|
-
|
272
|
-
|
273
|
-
2. Crie branch com feature/bugfix.
|
274
|
-
3. Abra PR com descrição técnica das mudanças e testes.
|
275
|
-
4. Mantenha o estilo Ruby (RuboCop) e documentação atualizada.
|
104
|
+
#### Dump Completo da Página
|
105
|
+
Uma lista interativa de **todos os elementos** visíveis na tela, com todos os seus possíveis localizadores. Útil para explorar a tela e encontrar seletores alternativos.
|
276
106
|
|
277
|
-
|
107
|
+
## 🏛️ Arquitetura do Código
|
278
108
|
|
279
|
-
|
109
|
+
O código foi reestruturado em módulos com responsabilidades únicas para facilitar a manutenção e a extensibilidade.
|
280
110
|
|
281
|
-
|
282
|
-
|
111
|
+
* `handler.rb`: O **Maestro**. Orquestra as chamadas para os outros módulos na ordem correta.
|
112
|
+
* `analyzer.rb`: O **Analista**. Processa a mensagem de erro e calcula a similaridade dos elementos.
|
113
|
+
* `element_repository.rb`: O **Repositório**. É responsável por encontrar e carregar as definições de elementos de arquivos `.yaml` e `.rb`.
|
114
|
+
* `page_analyzer.rb`: O **Leitor de Tela**. Processa o XML da página para extrair todos os elementos, sugerir nomes e gerar localizadores.
|
115
|
+
* `report_generator.rb`: O **Gerador**. Consolida todos os dados analisados e cria os 4 arquivos de relatório.
|
116
|
+
* `utils.rb`: Funções auxiliares, como o Logger.
|
283
117
|
|
284
|
-
|
118
|
+
## 🤝 Como Contribuir
|
285
119
|
|
286
|
-
|
120
|
+
Encontrou um bug ou tem uma ideia para uma nova funcionalidade? Abra uma *Issue* no repositório do projeto. Pull Requests são sempre bem-vindos!
|
287
121
|
|
288
|
-
|
122
|
+
## 📜 Licença
|
289
123
|
|
290
|
-
|
124
|
+
Este projeto é distribuído sob a licença MIT. Veja o arquivo `LICENSE` para mais detalhes.
|
@@ -29,20 +29,27 @@ module AppiumFailureHelper
|
|
29
29
|
File.open("#{@output_folder}/all_elements_dump_#{@data[:timestamp]}.yaml", 'w') { |f| f.write(YAML.dump(@data[:all_page_elements])) }
|
30
30
|
end
|
31
31
|
|
32
|
+
# --- MÉTODO CORRIGIDO COM A LÓGICA COMPLETA ---
|
32
33
|
def generate_html_report
|
33
|
-
#
|
34
|
-
locators_html = ->(locators) { locators.map { |loc| "..." }.join }
|
35
|
-
all_elements_html = ->(elements) { elements.map { |el| "..." }.join }
|
36
|
-
|
37
|
-
# Prepara o conteúdo dinâmico
|
34
|
+
# Prepara as variáveis a partir do hash de dados
|
38
35
|
failed_info = @data[:failed_element]
|
39
36
|
similar_elements = @data[:similar_elements]
|
37
|
+
all_suggestions = @data[:all_page_elements]
|
40
38
|
de_para_yaml = @data[:de_para_yaml_analysis]
|
41
39
|
de_para_rb = @data[:de_para_rb_analysis]
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
timestamp = @data[:timestamp]
|
41
|
+
platform = @data[:platform]
|
42
|
+
screenshot_base64 = @data[:screenshot_base64]
|
45
43
|
|
44
|
+
# CORREÇÃO: Funções (lambdas) para gerar HTML restauradas na íntegra
|
45
|
+
locators_html = lambda do |locators|
|
46
|
+
locators.map { |loc| "<li class='flex justify-between items-center bg-gray-50 p-2 rounded-md mb-1 text-xs font-mono'><span class='font-bold text-indigo-600'>#{CGI.escapeHTML(loc[:strategy].upcase.gsub('_', ' '))}:</span><span class='text-gray-700 ml-2 overflow-auto max-w-[70%]'>#{CGI.escapeHTML(loc[:locator])}</span></li>" }.join
|
47
|
+
end
|
48
|
+
|
49
|
+
all_elements_html = lambda do |elements|
|
50
|
+
elements.map { |el| "<details class='border-b border-gray-200 py-3'><summary class='font-semibold text-sm text-gray-800 cursor-pointer'>#{CGI.escapeHTML(el[:name])}</summary><ul class='text-xs space-y-1 mt-2'>#{locators_html.call(el[:locators])}</ul></details>" }.join
|
51
|
+
end
|
52
|
+
|
46
53
|
# Bloco de análise YAML
|
47
54
|
de_para_yaml_html = ""
|
48
55
|
if de_para_yaml
|
@@ -58,7 +65,7 @@ module AppiumFailureHelper
|
|
58
65
|
</div>
|
59
66
|
HTML
|
60
67
|
end
|
61
|
-
|
68
|
+
|
62
69
|
# Bloco de análise Ruby
|
63
70
|
de_para_rb_html = ""
|
64
71
|
if de_para_rb
|
@@ -80,6 +87,7 @@ module AppiumFailureHelper
|
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
90
|
+
# Geração do conteúdo das seções que estavam faltando
|
83
91
|
similar_elements_content = similar_elements.empty? ? "<p class='text-gray-500'>Nenhuma alternativa semelhante foi encontrada na tela atual.</p>" : similar_elements.map { |el|
|
84
92
|
score_percent = (el[:score] * 100).round(1)
|
85
93
|
"<div class='border border-indigo-100 p-3 rounded-lg bg-indigo-50'><p class='font-bold text-indigo-800 mb-2'>#{CGI.escapeHTML(el[:name])} <span class='text-xs font-normal text-green-600 bg-green-100 rounded-full px-2 py-1'>Similaridade: #{score_percent}%</span></p><ul>#{locators_html.call(el[:locators])}</ul></div>"
|
@@ -91,13 +99,14 @@ module AppiumFailureHelper
|
|
91
99
|
"<p class='text-sm text-gray-500'>O localizador exato não pôde ser extraído da mensagem de erro.</p>"
|
92
100
|
end
|
93
101
|
|
102
|
+
# Template HTML completo
|
94
103
|
html_content = <<~HTML_REPORT
|
95
104
|
<!DOCTYPE html>
|
96
105
|
<html lang="pt-BR">
|
97
106
|
<head>
|
98
107
|
<meta charset="UTF-8">
|
99
108
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
100
|
-
<title>Relatório de Falha Appium - #{
|
109
|
+
<title>Relatório de Falha Appium - #{timestamp}</title>
|
101
110
|
<script src="https://cdn.tailwindcss.com"></script>
|
102
111
|
<style> body { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; } .tab-content { display: none; } .tab-content.active { display: block; } .tab-button.active { background-color: #4f46e5; color: white; } </style>
|
103
112
|
</head>
|
@@ -105,18 +114,19 @@ module AppiumFailureHelper
|
|
105
114
|
<div class="max-w-7xl mx-auto">
|
106
115
|
<header class="mb-8 pb-4 border-b border-gray-300">
|
107
116
|
<h1 class="text-3xl font-bold text-gray-800">Diagnóstico de Falha Automatizada</h1>
|
108
|
-
<p class="text-sm text-gray-500">Relatório gerado em: #{
|
117
|
+
<p class="text-sm text-gray-500">Relatório gerado em: #{timestamp} | Plataforma: #{platform.upcase}</p>
|
109
118
|
</header>
|
110
119
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
111
120
|
<div class="lg:col-span-1">
|
112
121
|
#{de_para_yaml_html}
|
122
|
+
#{de_para_rb_html}
|
113
123
|
<div class="bg-white p-4 rounded-lg shadow-xl mb-6 border border-red-200">
|
114
124
|
<h2 class="text-xl font-bold text-red-600 mb-4">Elemento com Falha</h2>
|
115
125
|
#{failed_info_content}
|
116
126
|
</div>
|
117
127
|
<div class="bg-white p-4 rounded-lg shadow-xl">
|
118
128
|
<h2 class="text-xl font-bold text-gray-800 mb-4">Screenshot da Falha</h2>
|
119
|
-
<img src="data:image/png;base64,#{
|
129
|
+
<img src="data:image/png;base64,#{screenshot_base64}" alt="Screenshot da Falha" class="w-full rounded-md shadow-lg border border-gray-200">
|
120
130
|
</div>
|
121
131
|
</div>
|
122
132
|
<div class="lg:col-span-2">
|
@@ -154,7 +164,7 @@ module AppiumFailureHelper
|
|
154
164
|
</html>
|
155
165
|
HTML_REPORT
|
156
166
|
|
157
|
-
File.write("#{@output_folder}/report_#{
|
167
|
+
File.write("#{@output_folder}/report_#{timestamp}.html", html_content)
|
158
168
|
end
|
159
169
|
end
|
160
170
|
end
|