cascadence 0.2.3 → 0.2.4
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 +4 -4
- data/VERSION +1 -1
- data/bin/cascadence +1 -1
- data/cascadence.gemspec +11 -2
- data/coverage/.last_run.json +1 -1
- data/coverage/.resultset.json +163 -32
- data/coverage/index.html +2391 -1515
- data/lib/cascadence/commander.rb +8 -62
- data/lib/cascadence/commander/flow.rb +74 -0
- data/lib/cascadence/commander/generate.rb +35 -0
- data/lib/cascadence/commander/version.rb +11 -0
- data/lib/cascadence/templates/%project_name%.rb.tt +6 -0
- data/lib/cascadence/templates/%project_name%/base_flow.rb.tt +8 -0
- data/lib/cascadence/templates/flow_helper.rb.tt +19 -0
- data/spec/cascadence/commander/flow_spec.rb +175 -0
- data/spec/cascadence/commander/generate_spec.rb +35 -0
- data/spec/cascadence/commander/version_spec.rb +0 -0
- data/spec/cascadence/commander_spec.rb +10 -168
- data/spec/spec_helper.rb +2 -1
- metadata +11 -2
data/lib/cascadence/commander.rb
CHANGED
@@ -3,74 +3,20 @@ module Cascadence
|
|
3
3
|
|
4
4
|
desc "version", "Not implemented yet. That's right, the command that tells you what version of cascadence you're running has not been implemented yet."
|
5
5
|
def version
|
6
|
-
|
6
|
+
Cascadence::Commander::Version.instance.run
|
7
7
|
end
|
8
8
|
|
9
9
|
desc "flow [FILEPATH]", "Runs the flow specified in the given file. If given a directory, runs all the flows in the directory."
|
10
10
|
def flow(filepath=Dir.pwd)
|
11
|
-
|
12
|
-
files = _get_files_from_filepath abs_file_path
|
13
|
-
_setup_environment_from_filepath!(_absolutize_filepath filepath)
|
14
|
-
tasks = files.map { |file| _get_task_from_file file }
|
15
|
-
_run_tasks tasks
|
11
|
+
Cascadence::Commander::Flow.instance.run(filepath)
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Cascadence.runner.run_tasks tasks
|
22
|
-
end
|
23
|
-
|
24
|
-
def _absolutize_filepath(filepath)
|
25
|
-
return filepath if filepath =~ /^\//
|
26
|
-
return File.expand_path(filepath) if filepath =~ /^~/
|
27
|
-
return File.join(Dir.pwd, filepath)
|
28
|
-
end
|
29
|
-
|
30
|
-
def _get_files_from_filepath(filepath)
|
31
|
-
return [filepath] if _flow_file? filepath
|
32
|
-
return [] unless File.exists? filepath
|
33
|
-
Dir[File.join(filepath, "*")].map { |file_or_dir| _get_files_from_filepath file_or_dir }.flatten
|
34
|
-
end
|
35
|
-
|
36
|
-
def _flow_file?(filepath)
|
37
|
-
(filepath =~ /_flow\.rb$/) && File.file?(filepath)
|
38
|
-
end
|
39
|
-
|
40
|
-
def _setup_environment_from_filepath!(filepath)
|
41
|
-
require _find_flow_helper_from_filepath filepath
|
42
|
-
end
|
43
|
-
|
44
|
-
def _find_flow_helper_from_filepath( filepath )
|
45
|
-
_find_flow_helper_from_filepath File.expand_path("..", filepath) unless File.directory? filepath
|
46
|
-
throw :NoFlowHelperFound if filepath == "/"
|
47
|
-
Dir[File.join(filepath, "*")].select { |file| _flow_helper? file }.first || _find_flow_helper_from_filepath( File.expand_path("..", filepath) )
|
48
|
-
end
|
49
|
-
|
50
|
-
def _flow_helper?(filepath)
|
51
|
-
(filepath =~ /\/flow_helper\.rb$/) && File.file?(filepath)
|
52
|
-
end
|
53
|
-
|
54
|
-
def _get_task_from_file(file)
|
55
|
-
flow = _get_flow_from_file file
|
56
|
-
Cascadence::Task.new(_get_zero_state_generator_from_flow flow) do |state=nil|
|
57
|
-
flow.new(state).run_states
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def _get_zero_state_generator_from_flow(flow)
|
62
|
-
return flow.zero_state_generator if flow.respond_to? :zero_state_generator
|
63
|
-
return Cascadence.config.zero_state_generator if flow == Object || !flow.respond_to?(:parent)
|
64
|
-
_get_zero_state_generator_from_flow(flow.parent)
|
65
|
-
end
|
66
|
-
|
67
|
-
def _get_flow_from_file(file)
|
68
|
-
Cascadence::Flow.subclasses.select { |subclass| _reasonably_matched?(subclass.to_s, file.chomp(".rb")) }.first
|
69
|
-
end
|
70
|
-
|
71
|
-
def _reasonably_matched?(str1, str2)
|
72
|
-
!(str2.to_s.gsub(/^\/?/, "/") =~ Regexp.new("\/" + str1.to_s.split("::").map(&:underscore).join("/") + "$")).nil?
|
14
|
+
desc "generate [FLOWNAME]", "generates the flow project as specified by the name with respect to your current directory."
|
15
|
+
def generate(flowname)
|
16
|
+
Cascadence::Commander::Generate.start ["dosomeshit", flowname, Dir.pwd]
|
73
17
|
end
|
74
18
|
|
75
19
|
end
|
76
|
-
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir[File.join(File.dirname(__FILE__), "commander", "*.rb")].each { |f| require f }
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Cascadence
|
2
|
+
class Commander
|
3
|
+
class Flow
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def run(filepath)
|
7
|
+
abs_file_path = _absolutize_filepath filepath
|
8
|
+
files = _get_files_from_filepath abs_file_path
|
9
|
+
_setup_environment_from_filepath!(_absolutize_filepath filepath)
|
10
|
+
tasks = files.map { |file| _get_task_from_file file }
|
11
|
+
_run_tasks tasks
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def _run_tasks(tasks)
|
17
|
+
Cascadence.runner.run_tasks tasks
|
18
|
+
end
|
19
|
+
|
20
|
+
def _absolutize_filepath(filepath)
|
21
|
+
return filepath if filepath =~ /^\//
|
22
|
+
return File.expand_path(filepath) if filepath =~ /^~/
|
23
|
+
return File.join(Dir.pwd, filepath)
|
24
|
+
end
|
25
|
+
|
26
|
+
def _get_files_from_filepath(filepath)
|
27
|
+
return [filepath] if _flow_file? filepath
|
28
|
+
return [] unless File.exists? filepath
|
29
|
+
Dir[File.join(filepath, "*")].map { |file_or_dir| _get_files_from_filepath file_or_dir }.flatten
|
30
|
+
end
|
31
|
+
|
32
|
+
def _flow_file?(filepath)
|
33
|
+
(filepath =~ /_flow\.rb$/) && File.file?(filepath)
|
34
|
+
end
|
35
|
+
|
36
|
+
def _setup_environment_from_filepath!(filepath)
|
37
|
+
require _find_flow_helper_from_filepath filepath
|
38
|
+
end
|
39
|
+
|
40
|
+
def _find_flow_helper_from_filepath( filepath )
|
41
|
+
_find_flow_helper_from_filepath File.expand_path("..", filepath) unless File.directory? filepath
|
42
|
+
throw :NoFlowHelperFound if filepath == "/"
|
43
|
+
Dir[File.join(filepath, "*")].select { |file| _flow_helper? file }.first || _find_flow_helper_from_filepath( File.expand_path("..", filepath) )
|
44
|
+
end
|
45
|
+
|
46
|
+
def _flow_helper?(filepath)
|
47
|
+
(filepath =~ /\/flow_helper\.rb$/) && File.file?(filepath)
|
48
|
+
end
|
49
|
+
|
50
|
+
def _get_task_from_file(file)
|
51
|
+
flow = _get_flow_from_file file
|
52
|
+
throw "Bad flow from #{file}. Available flows: #{Cascadence::Flow.subclasses.to_s}" if flow.nil?
|
53
|
+
Cascadence::Task.new(_get_zero_state_generator_from_flow flow) do |state=nil|
|
54
|
+
flow.new(state).run_states
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def _get_zero_state_generator_from_flow(flow)
|
59
|
+
return flow.zero_state_generator if flow.respond_to? :zero_state_generator
|
60
|
+
return Cascadence.config.zero_state_generator if flow == Object || !flow.respond_to?(:parent)
|
61
|
+
_get_zero_state_generator_from_flow(flow.parent)
|
62
|
+
end
|
63
|
+
|
64
|
+
def _get_flow_from_file(file)
|
65
|
+
Cascadence::Flow.subclasses.select { |subclass| _reasonably_matched?(subclass.to_s, file.chomp(".rb")) }.first
|
66
|
+
end
|
67
|
+
|
68
|
+
def _reasonably_matched?(str1, str2)
|
69
|
+
!(str2.to_s.gsub(/^\/?/, "/") =~ Regexp.new("\/" + str1.to_s.split("::").map(&:underscore).join("/") + "$")).nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Cascadence
|
2
|
+
class Commander
|
3
|
+
class Generate < Thor
|
4
|
+
include Singleton
|
5
|
+
include Thor::Actions
|
6
|
+
attr_accessor :project_name, :project_dir
|
7
|
+
|
8
|
+
desc "dosomeshit [FLOWNAME] [PROJECTDIR]", "Generates a project name."
|
9
|
+
def dosomeshit(flowname, project_dir=Dir.pwd)
|
10
|
+
_setup_instance_variables!(flowname, project_dir)
|
11
|
+
directory _get_source_path, _get_destination
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.source_root
|
15
|
+
File.expand_path("../../templates", __FILE__)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def _setup_instance_variables!(flowname, project_dir)
|
21
|
+
@project_name = flowname
|
22
|
+
@project_dir = project_dir
|
23
|
+
end
|
24
|
+
|
25
|
+
def _get_source_path
|
26
|
+
self.class.source_root
|
27
|
+
end
|
28
|
+
|
29
|
+
def _get_destination
|
30
|
+
File.join(project_dir, project_name, "flows")
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "capybara"
|
2
|
+
Dir[File.expand_path("../*.rb", __FILE__)].each { |f| require f }
|
3
|
+
|
4
|
+
Cascadence.config do |config|
|
5
|
+
# Cascadence supports parallelism when running your flows.
|
6
|
+
# Each file that ends with _flow.rb will be treated as an
|
7
|
+
# individual flow that you want cascadence to run. It is
|
8
|
+
# highly recommended that you set max_thread_count to a
|
9
|
+
# reasonably small number since running firefox instances
|
10
|
+
# tend to be fairly expensive
|
11
|
+
config.parallel = false
|
12
|
+
config.max_thread_count = 4
|
13
|
+
|
14
|
+
# The zero_state_generator creates the initial state used
|
15
|
+
# by your flows. Global configs here is just the default
|
16
|
+
# generator used in the event specific generators are not
|
17
|
+
# provided in the individual flows.
|
18
|
+
config.zero_state_generator = lambda { Capybara::Session.new :selenium }
|
19
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cascadence::Commander::Flow do
|
4
|
+
let(:lolcat) { Cascadence::Commander::Flow.instance }
|
5
|
+
context "private" do
|
6
|
+
describe "#_get_zero_state_generator_from_flow" do
|
7
|
+
module GetZero
|
8
|
+
def self.zero_state_generator
|
9
|
+
lambda { "get_zero" }
|
10
|
+
end
|
11
|
+
class Fagbar < Cascadence::Flow
|
12
|
+
class HeyzapFlow < ::Cascadence::Flow
|
13
|
+
class CrossFlow
|
14
|
+
class WeHaveToGoDeeper
|
15
|
+
def self.zero_state_generator
|
16
|
+
lambda { "we_have_to_go_deeper" }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
it "should properly give me parents where applicable" do
|
24
|
+
GetZero::Fagbar::HeyzapFlow::CrossFlow::WeHaveToGoDeeper.parent.should eq GetZero::Fagbar::HeyzapFlow::CrossFlow
|
25
|
+
end
|
26
|
+
it "should give me nil for the outer level" do
|
27
|
+
GetZero.parent.should == Object
|
28
|
+
end
|
29
|
+
let(:result) { lolcat.send "_get_zero_state_generator_from_flow", @flow }
|
30
|
+
context "warpspeed" do
|
31
|
+
before :each do
|
32
|
+
@flow = GetZero::Fagbar::HeyzapFlow::CrossFlow
|
33
|
+
end
|
34
|
+
it "should get me the first zero_state_generator" do
|
35
|
+
result.call.should eq "get_zero"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
context "inception" do
|
39
|
+
before :each do
|
40
|
+
@flow = GetZero::Fagbar::HeyzapFlow::CrossFlow::WeHaveToGoDeeper
|
41
|
+
end
|
42
|
+
it "should get the closest zero state generator" do
|
43
|
+
result.call.should eq "we_have_to_go_deeper"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
describe "#_absolutize_filepath" do
|
48
|
+
let(:path) { lolcat.send "_absolutize_filepath", @input }
|
49
|
+
let(:result) { path.should eq @expected }
|
50
|
+
context "standard usage" do
|
51
|
+
before :each do
|
52
|
+
@input = "dog"
|
53
|
+
@expected = File.join Dir.pwd, @input
|
54
|
+
end
|
55
|
+
it( "should give me an absolute path to the file regardless of existence") { result }
|
56
|
+
end
|
57
|
+
context "~" do
|
58
|
+
before :each do
|
59
|
+
@input = "~/dogfucker"
|
60
|
+
@expected = File.join File.expand_path("~"), "dogfucker"
|
61
|
+
end
|
62
|
+
it( "should expand the tilde to the absolute path") { result }
|
63
|
+
end
|
64
|
+
context "absolute path" do
|
65
|
+
before :each do
|
66
|
+
@input = "/home/shinka/something"
|
67
|
+
@expected = @input
|
68
|
+
end
|
69
|
+
it("should not touch the input if it is already absolute") { result }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
describe "#_reasonably_matched?" do
|
73
|
+
let(:match) { lambda { |s1, s2| lolcat.send "_reasonably_matched?", s1, s2 } }
|
74
|
+
context "true" do
|
75
|
+
before :each do
|
76
|
+
@expectations = {
|
77
|
+
"Dog::Cat::Bat" => "/dog/cat/bat",
|
78
|
+
"AssFuck::Shot" => "/ass_fuck/shot",
|
79
|
+
"Dicker::BatMan::Robin" => "apples/oranges/dicker/bat_man/robin",
|
80
|
+
"Snot" => "/asdf/asdf/asdf/ff/snot"
|
81
|
+
}
|
82
|
+
end
|
83
|
+
it "should be a reasonable match" do
|
84
|
+
@expectations.each { |key, val| match.call(key,val).should be_true }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
context "false" do
|
88
|
+
before :each do
|
89
|
+
@expectations = {
|
90
|
+
"Dog::Cat::Bat" => "/fdasf/dog/cat/rat",
|
91
|
+
"" => "/anything/really" ,
|
92
|
+
"Dicker::AssMan" => "/fd/dicker/ass_man/something"
|
93
|
+
}
|
94
|
+
end
|
95
|
+
it "should not be reasonable matches" do
|
96
|
+
@expectations.each { |key,val| match.call(key,val).should_not be_true }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
describe "#_get_flow_from_file" do
|
101
|
+
let(:flow) { lolcat.send "_get_flow_from_file", @file }
|
102
|
+
let(:expected) { Amazon::MadeiraFlow }
|
103
|
+
before :each do
|
104
|
+
@file = File.join RSpec::FixturePath, "amazon", "madeira_flow.rb"
|
105
|
+
require @file
|
106
|
+
end
|
107
|
+
context "standard usage" do
|
108
|
+
it "should find the flow class in question" do
|
109
|
+
flow.should eq expected
|
110
|
+
end
|
111
|
+
end
|
112
|
+
describe "#_get_task_from_file" do
|
113
|
+
let(:task) { lolcat.send("_get_task_from_file", @file) }
|
114
|
+
|
115
|
+
it "should be a lambda" do
|
116
|
+
task.should respond_to :call
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should run and give me the correct result" do
|
120
|
+
task.call.state.should eq "initialized123"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
describe "#_find_flow_helper_from_filepath" do
|
125
|
+
let(:path) { lolcat.send "_find_flow_helper_from_filepath", @starting }
|
126
|
+
context "null case" do
|
127
|
+
before :each do
|
128
|
+
@starting = File.expand_path __FILE__
|
129
|
+
end
|
130
|
+
it "should throw an symbol as it cannot find the flow helper" do
|
131
|
+
expect { path }.to throw_symbol :NoFlowHelperFound
|
132
|
+
end
|
133
|
+
end
|
134
|
+
context "dumb case" do
|
135
|
+
before :each do
|
136
|
+
@starting = File.join RSpec::FixturePath, "flow_helper.rb"
|
137
|
+
@expected = @starting
|
138
|
+
end
|
139
|
+
it "should find it right away" do
|
140
|
+
path.should eq @expected
|
141
|
+
end
|
142
|
+
end
|
143
|
+
context "standard usage" do
|
144
|
+
before :each do
|
145
|
+
@starting = File.join RSpec::FixturePath, "nile", "white_nile"
|
146
|
+
@expected = File.join RSpec::FixturePath, "flow_helper.rb"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should find the expected flow helper in the fixture folder" do
|
150
|
+
path.should eq @expected
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
describe "#_get_files_from_filepath" do
|
155
|
+
context "standard usage" do
|
156
|
+
let(:files) { lolcat.send( "_get_files_from_filepath", File.join(RSpec::FixturePath) ) }
|
157
|
+
before :each do
|
158
|
+
@expected = Dir[File.join(RSpec::FixturePath, "*_flow.rb")].map { |f| f }
|
159
|
+
@expected += Dir[File.join(RSpec::FixturePath,"**", "*_flow.rb")].map { |f| f }
|
160
|
+
@expected += Dir[File.join(RSpec::FixturePath,"**", "**", "*_flow.rb")].map { |f| f }
|
161
|
+
@expected.uniq!
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should fetch all the files that are flow rubies" do
|
165
|
+
files.sort.should eq @expected.sort
|
166
|
+
end
|
167
|
+
end
|
168
|
+
context "null usage" do
|
169
|
+
it "should out an empty array if the path doesn't exist" do
|
170
|
+
lolcat.send("_get_files_from_filepath", "nigstack").should be_empty
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Cascadence::Commander::Generate do
|
4
|
+
let(:api) { Cascadence::Commander::Generate }
|
5
|
+
context "public" do
|
6
|
+
describe "#dosomeshit" do
|
7
|
+
let(:pubic) { api.start ["dosomeshit", @project_name, RSpec::RootPath] }
|
8
|
+
before :each do
|
9
|
+
@project_name = "tmp_shit"
|
10
|
+
@directory = File.join RSpec::RootPath, @project_name
|
11
|
+
FileUtils.rm_r @directory if Dir.exists? @directory
|
12
|
+
end
|
13
|
+
it "should create the new folder with all the sorts of crap in there" do
|
14
|
+
Dir.exists?(@directory).should_not be_true
|
15
|
+
pubic
|
16
|
+
Dir.exists?(@directory).should be_true
|
17
|
+
end
|
18
|
+
after :each do
|
19
|
+
FileUtils.rm_r @directory if Dir.exists? @directory
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
context "private" do
|
24
|
+
describe "#_setup_instance_variables!" do
|
25
|
+
|
26
|
+
end
|
27
|
+
describe "#_get_source_path" do
|
28
|
+
|
29
|
+
end
|
30
|
+
describe "#_get_destination" do
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|