Class: Bddgenx::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/bddgenx/generators/generator.rb

Constant Summary collapse

GHERKIN_KEYS_PT =

Palavras-chave do Gherkin em Português

%w[Dado Quando Então E Mas].freeze
GHERKIN_KEYS_EN =

Palavras-chave do Gherkin em Inglês

%w[Given When Then And But].freeze
GHERKIN_MAP_PT_EN =

Mapeamento de PT → EN

GHERKIN_KEYS_PT.zip(GHERKIN_KEYS_EN).to_h
GHERKIN_MAP_EN_PT =

Mapeamento de EN → PT

GHERKIN_KEYS_EN.zip(GHERKIN_KEYS_PT).to_h
ALL_KEYS =

Todas as palavras-chave reconhecidas

GHERKIN_KEYS_PT + GHERKIN_KEYS_EN

Class Method Summary collapse

Class Method Details

.dividir_examples(raw) ⇒ Array<String>

Extrai todas as linhas de exemplo de um array de strings.

Parameters:

  • raw (Array<String>)

    um array contendo linhas de texto

Returns:

  • (Array<String>)

    apenas as linhas que começam com ‘|’, ou seja, exemplos



31
32
33
# File 'lib/bddgenx/generators/generator.rb', line 31

def self.dividir_examples(raw)
  raw.select { |l| l.strip.start_with?('|') }
end

.gerar_feature(input, override_path = nil) ⇒ Array(String, String)

Gera o conteúdo de um arquivo ‘.feature` a partir de uma história. Pode operar em três modos: estático (hash ou arquivo estruturado), IA com Gemini, ou IA com ChatGPT.

Parameters:

  • input (String, Hash)

    caminho para um arquivo .txt ou um hash estruturado

  • override_path (String, nil) (defaults to: nil)

    caminho alternativo para salvar o arquivo gerado

Returns:

  • (Array(String, String))

    caminho do arquivo gerado e conteúdo do .feature



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/bddgenx/generators/generator.rb', line 43

def self.gerar_feature(input, override_path = nil)
  modo = ENV['BDD_MODE']&.to_sym || :static

  if input.is_a?(String) && input.end_with?('.txt') && [:gemini, :chatgpt].include?(modo)
    # Modo com IA: gera cenários automaticamente com base no texto da história
    raw_txt = File.read(input)
    historia = {
      idioma: 'pt',
      quero: File.basename(input, '.txt').tr('_', ' ').capitalize,
      como: '',
      para: '',
      grupos: []
    }

    texto_gerado = if modo == :gemini
                     GeminiCliente.gerar_cenarios(raw_txt)
                   else
                     ChatGPTCliente.gerar_cenarios(raw_txt)
                   end

    historia[:grupos] << {
      tipo: 'gerado',
      tag: 'ia',
      passos: GherkinCleaner.limpar(texto_gerado).lines.map(&:strip).reject(&:empty?)
    }
  else
    # Modo estático: utiliza estrutura vinda do Parser ou de um hash diretamente
    historia = input.is_a?(String) ? Parser.ler_historia(input) : input
  end

  idioma = historia[:idioma] || 'pt'
  cont = 1

  # Normaliza o nome base do arquivo
  nome_base = historia[:quero]
                .gsub(/[^a-z0-9]/i, '_')
                .downcase
                .split('_')
                .reject(&:empty?)
                .first(5)
                .join('_')

  caminho = override_path || "features/#{nome_base}.feature"

  # Define palavras-chave com base no idioma
  palavras = {
    feature:  idioma == 'en' ? 'Feature'          : 'Funcionalidade',
    contexto: idioma == 'en' ? 'Background'       : 'Contexto',
    cenario:  idioma == 'en' ? 'Scenario'         : 'Cenário',
    esquema:  idioma == 'en' ? 'Scenario Outline' : 'Esquema do Cenário',
    exemplos: idioma == 'en' ? 'Examples'         : 'Exemplos',
    regra:    idioma == 'en' ? 'Rule'             : 'Regra'
  }

  conteudo = <<~GHK
    # language: #{idioma}
    #{palavras[:feature]}: #{historia[:quero].sub(/^Quero\s*/i,'')}
      # #{historia[:como]}
      # #{historia[:quero]}
      # #{historia[:para]}
  GHK

  passos_unicos = Set.new
  pt_map = GHERKIN_MAP_PT_EN
  en_map = GHERKIN_MAP_EN_PT
  detect = ALL_KEYS
  cont = 1

  historia[:grupos].each do |grupo|
    passos   = grupo[:passos]  || []
    exemplos = grupo[:exemplos] || []
    next if passos.empty?

    tag_line = ["@#{grupo[:tipo].downcase}", ("@#{grupo[:tag]}" if grupo[:tag])].compact.join(' ')
    conteudo << "    #{tag_line}\n"

    if exemplos.any?
      conteudo << "    #{palavras[:esquema]}: Exemplo #{cont}\n"
      cont += 1
    else
      conteudo << "    #{palavras[:cenario]}: #{grupo[:tipo].capitalize}\n"
    end

    passos.each do |p|
      parts = p.strip.split(' ', 2)
      con_in = detect.find { |k| k.casecmp(parts[0]) == 0 } || parts[0]
      text = parts[1] || ''
      out_conn = idioma == 'en' ? pt_map[con_in] || con_in : en_map[con_in] || con_in
      linha_step = "      #{out_conn} #{text}"

      next if passos_unicos.include?(linha_step)

      passos_unicos << linha_step
      conteudo << "#{linha_step}\n"
    end

    if exemplos.any?
      conteudo << "\n      #{palavras[:exemplos]}:\n"
      exemplos.select { |l| l.strip.start_with?('|') }.each do |line|
        cleaned = line.strip.gsub(/^"|"$/, '')
        conteudo << "        #{cleaned}\n"
      end
    end

    conteudo << "\n"
  end

  [caminho, conteudo]
end

.path_para_feature(arquivo_txt) ⇒ String

Gera o caminho padrão de saída para um arquivo ‘.feature` com base no nome do `.txt`.

Parameters:

  • arquivo_txt (String)

    caminho do arquivo .txt de entrada

Returns:

  • (String)

    caminho completo do arquivo .feature correspondente



158
159
160
161
# File 'lib/bddgenx/generators/generator.rb', line 158

def self.path_para_feature(arquivo_txt)
  nome = File.basename(arquivo_txt, '.txt')
  File.join('features', "#{nome}.feature")
end

.salvar_feature(caminho, conteudo) ⇒ void

This method returns an undefined value.

Salva o conteúdo gerado no disco, criando diretórios se necessário.

Parameters:

  • caminho (String)

    caminho completo para salvar o arquivo

  • conteudo (String)

    conteúdo do arquivo .feature



169
170
171
172
173
# File 'lib/bddgenx/generators/generator.rb', line 169

def self.salvar_feature(caminho, conteudo)
  FileUtils.mkdir_p(File.dirname(caminho))
  File.write(caminho, conteudo)
  puts "✅ Arquivo .feature gerado: #{caminho}"
end