Module: Varar::Runner::CLI

Defined in:
lib/varar/runner/cli.rb

Overview

The var command-line entry point (exposed by the exe/var executable). Today it offers a single sub-command, varar init, which scaffolds a new project: a varar.config.json, one Markdown spec, its step definitions, and a framework bridge that turns the specs into RSpec examples or Minitest tests.

The config, spec and steps mirror the TypeScript CLI (@varar/cli) so a project started with varar init looks the same in every language; only the bridge is Ruby-specific, because RSpec/Minitest — unlike pytest — need an explicit generator call to discover the specs.

Constant Summary collapse

CONFIG =
<<~JSON
  {
    "docs": { "include": ["varar-examples/**/*.md"], "exclude": [] },
    "steps": ["varar-examples/**/*.steps.rb"]
  }
JSON
EXAMPLE_MD =
<<~MARKDOWN
  # Hello, BDD

  Given I greet "world"
  Then the greeting is "Hello, world!"
MARKDOWN
EXAMPLE_STEPS =
<<~RUBY
  # frozen_string_literal: true

  require 'varar'

  steps(-> { { greeting: '' } }) do
    stimulus('I greet {string}') { |_state, name| { greeting: "Hello, \#{name}!" } }
    sensor('the greeting is {string}') { |state, _expected| state[:greeting] }
  end
RUBY
RSPEC_BRIDGE =
<<~RUBY
  # frozen_string_literal: true

  # Turn every Markdown spec matched by varar.config.json into RSpec examples —
  # one `it` per Markdown example, discovered when this file loads.
  require 'varar/rspec'

  # varar.config.json lives at the project root (the parent of spec/).
  Varar::RSpec.generate(root: File.expand_path('..', __dir__))
RUBY
MINITEST_BRIDGE =
<<~RUBY
  # frozen_string_literal: true

  require 'minitest/autorun'
  require 'varar/minitest'

  # Turn every Markdown spec matched by varar.config.json into Minitest tests —
  # varar.config.json lives at the project root (the parent of test/).
  Varar::Minitest.generate_tests(Object, root: File.expand_path('..', __dir__))
RUBY
USAGE =
<<~TEXT
  varar — scaffold and run Markdown specs

  Usage:
    varar init               scaffold a new project
TEXT

Class Method Summary collapse

Class Method Details

.detect_frameworkObject

RSpec when its adapter is installed, Minitest when only that one is, RSpec as the fallback (matching the tutorial's default track).



112
113
114
115
116
117
# File 'lib/varar/runner/cli.rb', line 112

def self.detect_framework
  return :rspec if gem_present?('varar-rspec')
  return :minitest if gem_present?('varar-minitest')

  :rspec
end

.gem_present?(name) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
122
123
# File 'lib/varar/runner/cli.rb', line 119

def self.gem_present?(name)
  Gem::Specification.find_all_by_name(name).any?
rescue StandardError
  false
end

.main(argv, cwd: Dir.pwd, out: $stdout) ⇒ Object



72
73
74
75
76
77
78
79
80
# File 'lib/varar/runner/cli.rb', line 72

def self.main(argv, cwd: Dir.pwd, out: $stdout)
  case argv.first
  when 'init'
    run_init(cwd, out)
  else
    out.print(USAGE)
    argv.empty? || %w[help -h --help].include?(argv.first) ? 0 : 1
  end
end

.run_init(cwd, out, framework: detect_framework) ⇒ Object

Write the scaffold into cwd, skipping any file that already exists. The framework bridge matches whichever adapter gem is installed (RSpec by default).



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/varar/runner/cli.rb', line 85

def self.run_init(cwd, out, framework: detect_framework)
  files = [
    ['varar.config.json', CONFIG],
    ['varar-examples/01-hello.md', EXAMPLE_MD],
    ['varar-examples/steps/01-hello.steps.rb', EXAMPLE_STEPS]
  ]
  files << if framework == :minitest
             ['test/var_test.rb', MINITEST_BRIDGE]
           else
             ['spec/var_spec.rb', RSPEC_BRIDGE]
           end

  files.each do |rel, content|
    target = File.join(cwd, rel)
    if File.exist?(target)
      out.puts "skipped #{rel} (already exists)"
      next
    end
    FileUtils.mkdir_p(File.dirname(target))
    File.write(target, content)
    out.puts "created #{rel}"
  end
  0
end