turnip 0.3.1 → 1.0.0

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.
Files changed (49) hide show
  1. data/README.md +128 -166
  2. data/examples/autoload_steps.feature +3 -2
  3. data/examples/errors.feature +8 -0
  4. data/examples/step_calling.feature +2 -0
  5. data/examples/steps/alignment_steps.rb +23 -0
  6. data/examples/{autoload_steps.rb → steps/autoload_steps.rb} +0 -0
  7. data/examples/steps/backtick_steps.rb +10 -0
  8. data/examples/steps/dragon_steps.rb +41 -0
  9. data/examples/{knight_steps.rb → steps/knight_steps.rb} +3 -1
  10. data/examples/{more_steps.rb → steps/more_steps.rb} +0 -0
  11. data/examples/{step_calling_steps.rb → steps/step_calling_steps.rb} +0 -0
  12. data/examples/{steps.rb → steps/steps.rb} +25 -1
  13. data/examples/steps_for.feature +2 -2
  14. data/examples/steps_with_variations.feature +17 -0
  15. data/lib/turnip.rb +19 -34
  16. data/lib/turnip/builder.rb +26 -24
  17. data/lib/turnip/define.rb +9 -0
  18. data/lib/turnip/dsl.rb +11 -17
  19. data/lib/turnip/execute.rb +15 -0
  20. data/lib/turnip/rspec.rb +80 -0
  21. data/lib/turnip/step_definition.rb +7 -32
  22. data/lib/turnip/version.rb +1 -1
  23. data/spec/builder_spec.rb +1 -40
  24. data/spec/define_and_execute.rb +38 -0
  25. data/spec/dsl_spec.rb +36 -19
  26. data/spec/integration_spec.rb +5 -1
  27. data/spec/spec_helper.rb +1 -3
  28. data/spec/step_definition_spec.rb +37 -51
  29. metadata +25 -55
  30. data/examples/alignment_steps.rb +0 -7
  31. data/examples/backtick_steps.rb +0 -4
  32. data/examples/dragon_steps.rb +0 -17
  33. data/examples/evil_steps.rb +0 -7
  34. data/examples/neutral_steps.rb +0 -7
  35. data/examples/red_dragon_steps.rb +0 -18
  36. data/lib/turnip/config.rb +0 -18
  37. data/lib/turnip/feature_file.rb +0 -20
  38. data/lib/turnip/loader.rb +0 -16
  39. data/lib/turnip/runner_dsl.rb +0 -9
  40. data/lib/turnip/scenario_context.rb +0 -41
  41. data/lib/turnip/scenario_runner.rb +0 -35
  42. data/lib/turnip/step_loader.rb +0 -27
  43. data/lib/turnip/step_module.rb +0 -89
  44. data/spec/feature_file_spec.rb +0 -18
  45. data/spec/runner_dsl_spec.rb +0 -23
  46. data/spec/scenario_context_spec.rb +0 -51
  47. data/spec/scenario_runner_spec.rb +0 -79
  48. data/spec/step_loader_spec.rb +0 -29
  49. data/spec/step_module_spec.rb +0 -106
@@ -1,7 +0,0 @@
1
- steps_for :alignment do
2
- attr_accessor :alignment
3
-
4
- step "that alignment should be :alignment" do |expected_alignment|
5
- alignment.should eq(expected_alignment)
6
- end
7
- end
@@ -1,4 +0,0 @@
1
- step "I run `:cmd`" do |cmd|
2
- step('I attack it') if cmd == 'killall monsters'
3
- end
4
-
@@ -1,17 +0,0 @@
1
- steps_for :dragon do
2
- use_steps :knight
3
-
4
- attr_accessor :dragon
5
-
6
- def dragon_attack
7
- dragon * 10
8
- end
9
-
10
- step "there is a dragon" do
11
- self.dragon = 1
12
- end
13
-
14
- step "the dragon attacks the knight" do
15
- knight.attacked_for(dragon_attack)
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- steps_for :evil do
2
- use_steps :alignment
3
-
4
- step "the monster has an alignment" do
5
- self.alignment = 'Evil'
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- steps_for :neutral do
2
- use_steps :alignment
3
-
4
- step "the monster has an alignment" do
5
- self.alignment = 'Neutral'
6
- end
7
- end
@@ -1,18 +0,0 @@
1
- steps_for :red_dragon do
2
- use_steps :dragon
3
-
4
- attr_accessor :red_dragon
5
-
6
- def dragon_attack
7
- attack = super
8
- if red_dragon
9
- attack + 15
10
- else
11
- attack
12
- end
13
- end
14
-
15
- step "the dragon breathes fire" do
16
- self.red_dragon = 1
17
- end
18
- end
@@ -1,18 +0,0 @@
1
- module Turnip
2
- module Config
3
- extend self
4
-
5
- attr_accessor :autotag_features
6
-
7
- def step_dirs
8
- @step_dirs ||= ['spec']
9
- end
10
-
11
- def step_dirs=(dirs)
12
- @step_dirs = [] unless @step_dirs
13
- @step_dirs.concat(Array(dirs))
14
- end
15
- end
16
- end
17
-
18
- Turnip::Config.autotag_features = true
@@ -1,20 +0,0 @@
1
- module Turnip
2
- class FeatureFile
3
- attr_accessor :file_name, :content, :feature_name
4
-
5
- def initialize(file_name)
6
- @file_name = file_name
7
- end
8
-
9
- def feature_name
10
- @feature_name ||= begin
11
- file = Pathname.new(file_name).basename.to_s
12
- file[0...file.index('.feature')]
13
- end
14
- end
15
-
16
- def content
17
- @content ||= File.read(file_name)
18
- end
19
- end
20
- end
@@ -1,16 +0,0 @@
1
- module Turnip
2
- module Loader
3
- def load(*a, &b)
4
- if a.first.end_with?('.feature')
5
- begin
6
- require 'spec_helper'
7
- rescue LoadError
8
- end
9
- Turnip::StepLoader.load_steps
10
- Turnip.run(Turnip::FeatureFile.new(a.first))
11
- else
12
- super
13
- end
14
- end
15
- end
16
- end
@@ -1,9 +0,0 @@
1
- module Turnip
2
- module RunnerDSL
3
- attr_accessor :turnip_runner
4
-
5
- def step(description, extra_arg = nil)
6
- turnip_runner.run_steps([Turnip::Builder::Step.new(description, extra_arg)])
7
- end
8
- end
9
- end
@@ -1,41 +0,0 @@
1
- module Turnip
2
- class ScenarioContext
3
- attr_accessor :feature
4
- attr_accessor :scenario
5
-
6
- def initialize(feature, scenario)
7
- self.feature = feature
8
- self.scenario = scenario
9
- end
10
-
11
- def available_background_steps
12
- available_steps_for(*feature_tags)
13
- end
14
-
15
- def available_scenario_steps
16
- available_steps_for(*scenario_tags)
17
- end
18
-
19
- def backgrounds
20
- feature.backgrounds
21
- end
22
-
23
- def modules
24
- Turnip::StepModule.modules_for(*scenario_tags)
25
- end
26
-
27
- private
28
-
29
- def available_steps_for(*tags)
30
- Turnip::StepModule.all_steps_for(*tags)
31
- end
32
-
33
- def feature_tags
34
- @feature_tags ||= feature.active_tags.uniq
35
- end
36
-
37
- def scenario_tags
38
- @scenario_tags ||= (feature_tags + scenario.active_tags).uniq
39
- end
40
- end
41
- end
@@ -1,35 +0,0 @@
1
- module Turnip
2
- class ScenarioRunner
3
- attr_accessor :available_steps
4
- attr_accessor :context
5
- attr_accessor :world
6
-
7
- def initialize(world)
8
- self.world = world
9
- end
10
-
11
- def load(context)
12
- self.context = context
13
- world.extend Turnip::RunnerDSL
14
- world.turnip_runner = self
15
- context.modules.each {|mod| world.extend mod }
16
- self
17
- end
18
-
19
- def run
20
- self.available_steps = context.available_background_steps
21
- context.backgrounds.each do |background|
22
- run_steps(background.steps)
23
- end
24
-
25
- self.available_steps = context.available_scenario_steps
26
- run_steps(context.scenario.steps)
27
- end
28
-
29
- def run_steps(steps)
30
- steps.each do |step|
31
- Turnip::StepDefinition.execute(world, available_steps, step)
32
- end
33
- end
34
- end
35
- end
@@ -1,27 +0,0 @@
1
- module Turnip
2
- module StepLoader
3
- extend self
4
-
5
- attr_accessor :steps_loaded
6
-
7
- def load_steps
8
- return if steps_loaded?
9
- load_step_files
10
- self.steps_loaded = true
11
- end
12
-
13
- def steps_loaded?
14
- @steps_loaded
15
- end
16
-
17
- private
18
-
19
- def load_step_files
20
- Turnip::Config.step_dirs.each do |dir|
21
- Pathname.glob(Pathname.new(dir) + '**' + "*steps.rb").each do |step_file|
22
- load step_file, true
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,89 +0,0 @@
1
- require 'pathname'
2
-
3
- module Turnip
4
- module StepModule
5
- module DSL
6
- def placeholder(name, &block)
7
- Turnip::Placeholder.add(name, &block)
8
- end
9
-
10
- def step(description, &block)
11
- steps << Turnip::StepDefinition.new(description, &block)
12
- end
13
-
14
- def steps
15
- @steps ||= []
16
- end
17
-
18
- def use_steps(*tags)
19
- uses_steps.concat(tags)
20
- end
21
-
22
- def uses_steps
23
- @uses_steps ||= []
24
- end
25
- end
26
-
27
- class Entry < Struct.new(:for_tag, :step_module, :uses_steps)
28
- def all_modules(already_visited = [])
29
- if already_visited.include?(for_tag)
30
- []
31
- else
32
- already_visited << for_tag
33
- uses_modules(already_visited) << step_module
34
- end
35
- end
36
-
37
- def uses_modules(already_visited)
38
- uses_steps.map do |uses_tag|
39
- StepModule.module_registry[uses_tag].map do |entry|
40
- entry.all_modules(already_visited)
41
- end
42
- end.flatten.uniq
43
- end
44
- end
45
-
46
- extend self
47
-
48
- def all_steps_for(*taggings)
49
- modules_for(*taggings).map do |step_module|
50
- step_module.steps
51
- end.flatten
52
- end
53
-
54
- def clear_module_registry
55
- module_registry.clear
56
- end
57
-
58
- def modules_for(*taggings)
59
- taggings.map do |tag|
60
- module_registry[tag].map do |entry|
61
- entry.all_modules
62
- end
63
- end.flatten.uniq
64
- end
65
-
66
- def module_registry
67
- @module_registry ||= Hash.new { |hash, key| hash[key] = [] }
68
- end
69
-
70
- def registered?(module_name)
71
- module_registry.has_key? module_name
72
- end
73
-
74
- def steps_for(tag, &block)
75
- anon = step_module(&block)
76
-
77
- entry = Entry.new(tag, anon, anon.uses_steps)
78
-
79
- module_registry[tag] << entry
80
- end
81
-
82
- def step_module(&block)
83
- anon = Module.new
84
- anon.extend(Turnip::StepModule::DSL)
85
- anon.module_eval(&block)
86
- anon
87
- end
88
- end
89
- end
@@ -1,18 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Turnip::FeatureFile do
4
- let(:file_name) {File.expand_path('../examples/with_comments.feature', File.dirname(__FILE__))}
5
- let(:feature_file) {Turnip::FeatureFile.new(file_name)}
6
-
7
- describe '.feature_name' do
8
- it 'allows access to short name for the feature based on the file name' do
9
- feature_file.feature_name.should == 'with_comments'
10
- end
11
- end
12
-
13
- describe '.content' do
14
- it 'allows access to the content in the feature file' do
15
- feature_file.content.should be
16
- end
17
- end
18
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Turnip::RunnerDSL do
4
- describe '#step' do
5
- include Turnip::RunnerDSL
6
-
7
- it 'runs the step' do
8
- self.turnip_runner = Class.new do
9
- attr_accessor :args
10
- def run_steps(steps)
11
- self.args << steps
12
- end
13
- end.new
14
- self.turnip_runner.args = []
15
-
16
- step('description', 'extra_arg')
17
- step = turnip_runner.args.flatten.first
18
- step.should be_kind_of(Turnip::Builder::Step)
19
- step.description.should eq('description')
20
- step.extra_arg.should eq('extra_arg')
21
- end
22
- end
23
- end
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Turnip::ScenarioContext do
4
- let(:context) { Turnip::ScenarioContext.new(feature, scenario) }
5
- let(:feature) { stub(:active_tags => feature_tags) }
6
- let(:feature_tags) { %w(feature both) }
7
- let(:scenario) { stub(:active_tags => scenario_tags) }
8
- let(:scenario_tags) { %w(scenario both) }
9
- let(:unique_tags) { (feature_tags + scenario_tags).uniq }
10
-
11
- describe '#initialize' do
12
- let(:feature) { stub }
13
- let(:scenario) { stub }
14
-
15
- it 'keeps track of the feature' do
16
- Turnip::ScenarioContext.new(feature, scenario).feature.should eq(feature)
17
- end
18
-
19
- it 'keeps track of the scenario' do
20
- Turnip::ScenarioContext.new(feature, scenario).scenario.should eq(scenario)
21
- end
22
- end
23
-
24
- describe '#available_background_steps' do
25
- it 'gathers the steps for the feature tags' do
26
- Turnip::StepModule.should_receive(:all_steps_for).with(*feature_tags)
27
- context.available_background_steps
28
- end
29
- end
30
-
31
- describe '#available_scenario_steps' do
32
- it 'gathers the steps for the unique scenario and feature tags' do
33
- Turnip::StepModule.should_receive(:all_steps_for).with(*unique_tags)
34
- context.available_scenario_steps
35
- end
36
- end
37
-
38
- describe '#backgrounds' do
39
- it 'delegates to the feature' do
40
- feature.should_receive :backgrounds
41
- context.backgrounds
42
- end
43
- end
44
-
45
- describe '#modules' do
46
- it 'gathers the modules for the unique scenario and feature tags' do
47
- Turnip::StepModule.should_receive(:modules_for).with(*unique_tags)
48
- context.modules
49
- end
50
- end
51
- end
@@ -1,79 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Turnip::ScenarioRunner do
4
- let(:runner) { Turnip::ScenarioRunner.new(world) }
5
- let(:world) { Object.new }
6
-
7
- describe '#initialize' do
8
- it 'keeps track of the world' do
9
- Turnip::ScenarioRunner.new(world).world.should eq(world)
10
- end
11
- end
12
-
13
- describe '#load' do
14
- let(:context) { stub(:modules => [some_module]) }
15
- let(:some_module) { Module.new }
16
-
17
- it 'is chainable' do
18
- runner.load(context).should eq(runner)
19
- end
20
-
21
- it 'keeps track of the scenario context' do
22
- runner.load(context).context.should eq(context)
23
- end
24
-
25
- it 'loads the given modules into the world' do
26
- runner.load(context).world.should be_kind_of(some_module)
27
- end
28
-
29
- it 'loads the DSL module into the world' do
30
- runner.load(context).world.should be_kind_of(Turnip::RunnerDSL)
31
- end
32
-
33
- it 'adds the runner to the world' do
34
- runner.load(context).world.turnip_runner.should eq(runner)
35
- end
36
- end
37
-
38
- describe '#run' do
39
- it 'iterates over the background steps' do
40
- runner.context = stub(:backgrounds => (0..2).map { stub(:steps => [stub]) },
41
- :available_background_steps => [],
42
- :available_scenario_steps => [],
43
- :scenario => stub(:steps => []))
44
-
45
- Turnip::StepDefinition.should_receive(:execute).exactly(3).times
46
- runner.run
47
- end
48
-
49
- it 'iterates over the scenario steps' do
50
- runner.context = stub(:backgrounds => [],
51
- :available_background_steps => [],
52
- :available_scenario_steps => [],
53
- :scenario => stub(:steps => (0..3)))
54
-
55
- Turnip::StepDefinition.should_receive(:execute).exactly(4).times
56
- runner.run
57
- end
58
- end
59
-
60
- describe '#run_steps' do
61
- let(:available_steps) { stub }
62
-
63
- it 'executes the steps with the current world' do
64
- step = stub
65
- steps = [step]
66
- runner.available_steps = available_steps
67
-
68
- Turnip::StepDefinition.should_receive(:execute).with(world, available_steps, step)
69
- runner.run_steps(steps)
70
- end
71
-
72
- it 'iterates over the steps' do
73
- steps = (0..2)
74
-
75
- Turnip::StepDefinition.should_receive(:execute).exactly(3).times
76
- runner.run_steps(steps)
77
- end
78
- end
79
- end