appium_failure_helper 1.10.0 → 1.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e08435a47e2a5b5382abe20a9e6a7d6eb51e72c12cd22f9fb3a7ad3bf3cbbaa1
4
- data.tar.gz: '086f706107584495fd9dafdafc762223126c7e6e677fbe86e9f6cf10809b9fb7'
3
+ metadata.gz: 3e3447e2fe35beca0103d353b7af1c813ff9156fefc2d9136f5f994657d89618
4
+ data.tar.gz: 995aa92585cc7ef2a77b01f7525087afca3fec4210ad31e06cb5c0369654f5a8
5
5
  SHA512:
6
- metadata.gz: 486211c6d651c1ce903e8a3faa3b99ad368a8ee7dfb33bf9eb0f7c12a1504cd389a4ea2bbde636a3df76f967a8439e007afb01e576b4b0e7c1be7bd1232f6093
7
- data.tar.gz: '09f7261766cb390321f040475cea639f431b0bf39ee8b387f5df742773097ef92853e5f1b891a7422eb0265e672f2d7c0d16c064ccfa26efca7a2706d08dac7d'
6
+ metadata.gz: 52ccddb3b7ae55782951d513b60d70debf1e0961876e89cb7c0bc017187ac56e025752f9063cda6e860fa86575610c9d0968daac9e890872f3d397ac85171cf1
7
+ data.tar.gz: b2888de94b644d082737ea8becc829517aa8d5e99d99176b1a5a61108a2b9076b1fb173dfda250afa3355e6f885e242f02589cf3862b8119405a6ea1b97d5417
data/README.md CHANGED
@@ -9,7 +9,7 @@ Uma GEM de diagnóstico para testes Appium em Ruby, projetada para transformar f
9
9
 
10
10
  ---
11
11
 
12
- ## Principais Funcionalidades
12
+ ## Principais Funcionalidades
13
13
 
14
14
  - **Diagnóstico Inteligente de Falhas:** Identifica automaticamente o tipo de erro (`NoSuchElementError`, `TimeoutError`, falha de asserção ou erro de código Ruby) e gera relatórios personalizados para cada caso.
15
15
  - **Análise de Código-Fonte:** Para erros "silenciosos", inspeciona o `stack trace` e extrai o seletor diretamente do código, apontando arquivo e linha exatos.
@@ -22,7 +22,7 @@ Uma GEM de diagnóstico para testes Appium em Ruby, projetada para transformar f
22
22
 
23
23
  ---
24
24
 
25
- ## 🚀 Instalação
25
+ ## Instalação
26
26
 
27
27
  Adicione ao `Gemfile` do seu projeto de automação:
28
28
 
@@ -38,9 +38,9 @@ bundle install
38
38
 
39
39
  ---
40
40
 
41
- ## 🛠️ Uso e Configuração
41
+ ## Uso e Configuração
42
42
 
43
- ### 1️⃣ Configuração Inicial (Opcional)
43
+ ### Configuração Inicial (Opcional)
44
44
 
45
45
  No arquivo de inicialização (`features/support/env.rb`), configure os caminhos de elementos se necessário:
46
46
 
@@ -55,7 +55,7 @@ end
55
55
 
56
56
  ---
57
57
 
58
- ### 2️⃣ Enriquecer Exceções (Altamente Recomendado)
58
+ ### Enriquecer Exceções (Altamente Recomendado)
59
59
 
60
60
  Para extrair o máximo de informações de falhas, ajuste seus métodos de busca de elementos:
61
61
 
@@ -90,7 +90,7 @@ end
90
90
 
91
91
  ---
92
92
 
93
- ### 3️⃣ Integração com Cucumber
93
+ ### Integração com Cucumber
94
94
 
95
95
  No `hooks.rb`, acione a GEM após cada cenário com falha:
96
96
 
@@ -104,7 +104,7 @@ end
104
104
 
105
105
  ---
106
106
 
107
- ## 📄 Relatório Gerado
107
+ ## Relatório Gerado
108
108
 
109
109
  A cada falha, a GEM cria uma pasta em `reports_failure/` com:
110
110
 
@@ -117,7 +117,7 @@ A cada falha, a GEM cria uma pasta em `reports_failure/` com:
117
117
 
118
118
  ---
119
119
 
120
- ## 🏛️ Arquitetura
120
+ ## Arquitetura
121
121
 
122
122
  - **Handler:** Captura falhas e aciona o fluxo de análise.
123
123
  - **SourceCodeAnalyzer:** Extrai seletores diretamente do código-fonte.
@@ -127,7 +127,7 @@ A cada falha, a GEM cria uma pasta em `reports_failure/` com:
127
127
 
128
128
  ---
129
129
 
130
- ## 🔄 Fluxo Interno da GEM
130
+ ## Fluxo Interno da GEM
131
131
 
132
132
  ```
133
133
  Falha Appium
@@ -34,31 +34,13 @@ module AppiumFailureHelper
34
34
 
35
35
  if triage_result == :locator_issue
36
36
  page_source = safe_page_source
37
- # tenta extrair detalhes do Analyzer (se existir), senão usa fetch_failed_element
38
- failed_info = {}
39
- begin
40
- failed_info = Analyzer.extract_failure_details(@exception) if Analyzer.respond_to?(:extract_failure_details)
41
- rescue
42
- failed_info = {}
43
- end
44
-
45
- if failed_info.nil? || failed_info.empty?
46
- # tenta extrair do próprio handler (regex mais robusta)
47
- failed_info = fetch_failed_element || {}
48
- end
37
+ failed_info = fetch_failed_element || {}
49
38
 
50
- # fallback para extrair do código-fonte (se existir)
51
- if (failed_info.nil? || failed_info.empty?) && SourceCodeAnalyzer.respond_to?(:extract_from_exception)
52
- begin
53
- failed_info = SourceCodeAnalyzer.extract_from_exception(@exception) || {}
54
- rescue
55
- failed_info = {}
56
- end
39
+ if failed_info.empty? && SourceCodeAnalyzer.respond_to?(:extract_from_exception)
40
+ failed_info = SourceCodeAnalyzer.extract_from_exception(@exception) || {}
57
41
  end
58
42
 
59
- # garante que exista ao menos um objeto failed_element
60
- if failed_info.nil? || failed_info.empty?
61
- failed_info = { selector_type: 'unknown', selector_value: @exception&.message.to_s }
43
+ if failed_info.empty?
62
44
  report_data[:triage_result] = :unidentified_locator_issue
63
45
  end
64
46
 
@@ -66,51 +48,31 @@ module AppiumFailureHelper
66
48
  best_candidate_analysis = nil
67
49
  alternative_xpaths = []
68
50
 
69
- if page_source
70
- begin
71
- doc = Nokogiri::XML(page_source)
72
- page_analyzer = PageAnalyzer.new(page_source, platform)
73
- all_page_elements = page_analyzer.analyze || []
74
- best_candidate_analysis = Analyzer.perform_advanced_analysis(failed_info, all_page_elements, platform) rescue nil
75
- rescue => e
76
- Utils.logger.warn("Erro analisando page_source: #{e.message}")
77
- end
78
- end
79
-
80
- # se não encontrou candidato, gera alternativas a partir do locator bruto
81
- if best_candidate_analysis.nil?
82
- # tenta parse por Analyzer (se exposto), senão regex fallback
83
- failed_attrs = {}
84
- begin
85
- if Analyzer.respond_to?(:parse_locator) || Analyzer.private_methods.include?(:parse_locator)
86
- failed_attrs = Analyzer.send(:parse_locator, failed_info[:selector_type], failed_info[:selector_value], platform) rescue {}
87
- end
88
- rescue
89
- failed_attrs = {}
90
- end
91
-
92
- if failed_attrs.nil? || failed_attrs.empty?
51
+ if page_source && !failed_info.empty?
52
+ doc = Nokogiri::XML(page_source)
53
+ page_analyzer = PageAnalyzer.new(page_source, platform)
54
+ all_page_elements = page_analyzer.analyze || []
55
+ best_candidate_analysis = Analyzer.perform_advanced_analysis(failed_info, all_page_elements, platform) rescue nil
56
+
57
+ # --- SUA REGRA DE NEGÓCIO INTEGRADA AQUI ---
58
+ target_node = nil
59
+ if best_candidate_analysis && best_candidate_analysis[:attributes] && (path = best_candidate_analysis[:attributes][:path])
60
+ # Se encontrou um candidato, ele é o alvo para a XPathFactory
61
+ target_node = doc.at_xpath(path)
62
+ else
63
+ # Se NÃO encontrou, o alvo é o próprio elemento que falhou
93
64
  failed_attrs = parse_attrs_from_locator_string(failed_info[:selector_value] || '')
94
- end
95
-
96
- if failed_attrs && !failed_attrs.empty?
97
- temp_doc = Nokogiri::XML::Document.new
98
- tag = (failed_attrs.delete('tag') || failed_attrs.delete(:tag) || 'element').to_s
99
- target_node = Nokogiri::XML::Node.new(tag, temp_doc)
100
- failed_attrs.each { |k, v| target_node[k.to_s] = v.to_s unless k.to_s == 'tag' }
101
- alternative_xpaths = XPathFactory.generate_for_node(target_node) || []
102
- end
103
- else
104
- # se encontrou candidato, tenta gerar alternativas a partir do node encontrado
105
- if best_candidate_analysis[:attributes] && (path = best_candidate_analysis[:attributes][:path])
106
- begin
107
- doc = Nokogiri::XML(page_source) unless defined?(doc) && doc
108
- target_node = doc.at_xpath(path) rescue nil
109
- alternative_xpaths = XPathFactory.generate_for_node(target_node) if target_node
110
- rescue
111
- # ignore, já temos best_candidate_analysis
65
+ if !failed_attrs.empty?
66
+ temp_doc = Nokogiri::XML::Document.new
67
+ tag = (failed_attrs.delete('tag') || 'element').to_s
68
+ target_node = Nokogiri::XML::Node.new(tag, temp_doc)
69
+ failed_attrs.each { |k, v| target_node[k.to_s] = v.to_s }
112
70
  end
113
71
  end
72
+
73
+ # Gera as estratégias para o nó alvo, seja ele real ou "fantasma"
74
+ alternative_xpaths = XPathFactory.generate_for_node(target_node) if target_node
75
+ # -----------------------------------------------
114
76
  end
115
77
 
116
78
  report_data.merge!({
@@ -92,7 +92,11 @@ module AppiumFailureHelper
92
92
 
93
93
  suggestion_text = "O `resource-id` pode ter mudado ou o `text` está diferente. Considere usar um seletor mais robusto baseado nos atributos que corresponderam."
94
94
  if (best_candidate[:analysis][:id] || {})[:match] == true && (best_candidate[:analysis][:text] || {})[:similarity].to_f < 0.7
95
- suggestion_text = "O `resource-id` corresponde, mas o texto é diferente. **Recomendamos fortemente usar o `resource-id` para este seletor.**"
95
+ suggestion_text = "Prefira usar atributos estáveis, como resource-id ou content-desc.",
96
+ "Evite caminhos absolutos (//hierarchy/...); prefira XPaths curtos e relativos.",
97
+ "Use normalize-space() para lidar com espaços e maiúsculas/minúsculas.",
98
+ "Combine atributos, ex: //*[@resource-id='id' and @text='Texto'].",
99
+ "Evite localizar por texto dinâmico, prefira IDs únicos."
96
100
  end
97
101
 
98
102
  <<~HTML
@@ -298,7 +302,7 @@ module AppiumFailureHelper
298
302
  </div>
299
303
  <div class="md:col-span-2 space-y-6">
300
304
  <div class="bg-white p-6 rounded-lg shadow-md">
301
- <h2 class="text-xl font-bold text-red-600 mb-4">Diagnóstico: #{title}</h2>
305
+ <h2 class="text-xl font-bold text-red-600 mb-4">#{title}</h2>
302
306
  <div class="bg-red-50 border-l-4 border-red-500 text-red-800 p-4 rounded-r-lg">
303
307
  <p class="font-semibold">Causa Provável:</p>
304
308
  <p>#{message}</p>
@@ -1,3 +1,3 @@
1
1
  module AppiumFailureHelper
2
- VERSION = "1.10.0"
2
+ VERSION = "1.10.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_failure_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Nascimento
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-10-06 00:00:00.000000000 Z
11
+ date: 2025-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri