Class: Bddgenx::Runner

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

Overview

Classe principal de execução da gem. Atua como ponto de entrada (CLI) para processar arquivos de entrada e gerar todos os artefatos BDD relacionados.

Class Method Summary collapse

Class Method Details

.choose_files(input_dir) ⇒ Array<String>

Retorna a lista de arquivos de entrada. Se houver argumentos em ARGV, utiliza-os como nomes de arquivos ‘.txt`. Caso contrário, chama prompt interativo.

Parameters:

  • input_dir (String)

    Caminho do diretório de entrada

Returns:

  • (Array<String>)

    Lista de arquivos ‘.txt` a processar



24
25
26
# File 'lib/bddgenx/generators/runner.rb', line 24

def self.choose_files(input_dir)
  ARGV.any? ? selecionar_arquivos_txt(input_dir) : choose_input(input_dir)
end

.choose_input(input_dir) ⇒ Array<String>

Interface interativa para o usuário selecionar arquivos ‘.txt` a processar. Exibe uma lista dos arquivos disponíveis e solicita um número ao usuário.

Parameters:

  • input_dir (String)

    Diretório de entrada

Returns:

  • (Array<String>)

    Lista com o arquivo escolhido ou todos



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/bddgenx/generators/runner.rb', line 52

def self.choose_input(input_dir)
  files = Dir.glob(File.join(input_dir, '*.txt'))
  if files.empty?
    warn "❌ Não há arquivos .txt no diretório #{input_dir}"; exit 1
  end

  puts "Selecione o arquivo de história para processar:"
  files.each_with_index { |f, i| puts "#{i+1}. #{File.basename(f)}" }
  print "Digite o número correspondente (ou ENTER para todos): "
  choice = STDIN.gets.chomp

  return files if choice.empty?
  idx = choice.to_i - 1
  unless idx.between?(0, files.size - 1)
    warn "❌ Escolha inválida."; exit 1
  end
  [files[idx]]
end

.executevoid

This method returns an undefined value.

Executa o fluxo completo de geração BDD:

  • Define o modo (static / IA)

  • Coleta arquivos de entrada

  • Valida as histórias

  • Gera arquivos ‘.feature` e `steps`

  • Exporta PDFs e faz backup de versões antigas

O modo de execução é lido da variável de ambiente ‘BDDGENX_MODE`.



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
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/bddgenx/generators/runner.rb', line 82

def self.execute
  modo = ENV['BDDGENX_MODE'] || 'static'
  input_dir = 'input'
  Dir.mkdir(input_dir) unless Dir.exist?(input_dir)

  arquivos = choose_files(input_dir)
  if arquivos.empty?
    warn I18n.t('messages.no_files')
    exit 1
  end

  # Contadores de geração
  total = features = steps = ignored = 0
  skipped_steps = []
  generated_pdfs = []
  skipped_pdfs = []

  arquivos.each do |arquivo|
    total += 1
    puts "\n🔍 #{I18n.t('messages.processing')}: #{arquivo}"

    historia = Parser.ler_historia(arquivo)
    idioma = Utils.obter_idioma_do_arquivo(arquivo) || historia[:idioma]
    historia[:idioma] = idioma
    unless Validator.validar(historia)
      ignored += 1
      puts "#{I18n.t('messages.invalid_story')}: #{arquivo}"
      next
    end

    # Geração via IA (ChatGPT, Gemini)
    if %w[gemini chatgpt].include?(modo)
      puts I18n.t('messages.start_ia', modo: modo.capitalize)
      idioma = Utils.obter_idioma_do_arquivo(arquivo) || historia[:idioma]

      feature_text = Support::Loader.run(I18n.t('messages.ia_waiting'), :default) do
        case modo
        when 'gemini'
          IA::GeminiCliente.gerar_cenarios(historia, idioma)
        when 'chatgpt'
          IA::ChatGptCliente.gerar_cenarios(historia, idioma)
        end
      end

      if feature_text
        feature_path = Generator.path_para_feature(arquivo)
        feature_content = Utils.limpar(feature_text)
      else
        ignored += 1
        puts I18n.t('messages.feature_fail', arquivo: arquivo)
        next
      end
    else
      # Geração local (modo static)
      feature_path, feature_content = Support::Loader.run(I18n.t('messages.start_static'), :dots) do
        sleep(2)
        Generator.gerar_feature(historia)
      end
    end

    Backup.salvar_versao_antiga(feature_path)
    features += 1 if Generator.salvar_feature(feature_path, feature_content)

    if StepsGenerator.gerar_passos(feature_path)
      steps += 1
    else
      skipped_steps << feature_path
    end

    FileUtils.mkdir_p('reports')
    result = PDFExporter.exportar_todos(only_new: true)
    generated_pdfs.concat(result[:generated])
    skipped_pdfs.concat(result[:skipped])
  end

  # Resumo final
  puts "\n#{I18n.t('messages.processing_done')}"
  puts "- #{I18n.t('messages.total_histories')}:    #{total}"
  puts "- #{I18n.t('messages.features_generated')}: #{features}"
  puts "- #{I18n.t('messages.steps_generated')}:    #{steps}"
end

.selecionar_arquivos_txt(input_dir) ⇒ Array<String>

Processa argumentos ARGV e converte em caminhos válidos de arquivos ‘.txt`. Adiciona extensão `.txt` se ausente e remove arquivos inexistentes.

Parameters:

  • input_dir (String)

    Diretório onde estão os arquivos

Returns:

  • (Array<String>)

    Caminhos válidos para arquivos de entrada



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bddgenx/generators/runner.rb', line 34

def self.selecionar_arquivos_txt(input_dir)
  ARGV.map do |arg|
    nome = arg.end_with?('.txt') ? arg : "#{arg}.txt"
    path = File.join(input_dir, nome)
    unless File.exist?(path)
      warn "⚠️  Arquivo não encontrado: #{path}"
      next
    end
    path
  end.compact
end