ellington 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ require_relative "test_helper"
2
+
3
+ class RouteTest < MicroTest::Test
4
+
5
+ before do
6
+ @route = BasicMath.new
7
+ end
8
+
9
+ test "lines on class" do
10
+ assert @route.lines.length == 3
11
+ assert @route.lines[0].is_a?(Addition)
12
+ assert @route.lines[1].is_a?(Division)
13
+ assert @route.lines[2].is_a?(Multiplication)
14
+ end
15
+
16
+ test "type of lines must be unique" do
17
+ begin
18
+ @route.lines << Addition.new
19
+ rescue Ellington::ListAlreadyContainsType => e
20
+ end
21
+ assert !e.nil?
22
+ end
23
+
24
+ test "lines are assigned route" do
25
+ @route.lines.each do |line|
26
+ assert line.route == BasicMath
27
+ end
28
+ end
29
+
30
+ test "goal" do
31
+ goals = @route.goal & [@route.lines[1].goal, @route.lines[2].goal].flatten
32
+ assert @route.goal.length == goals.length
33
+ end
34
+
35
+ test "fail_target" do
36
+ assert !@route.fail_target.empty?
37
+ assert((@route.fail_target & @route.pass_target).empty?)
38
+ expected = (@route.states.keys - @route.pass_target).delete_if do |state|
39
+ state.to_s =~ /\AERROR/
40
+ end
41
+ assert @route.fail_target == expected
42
+ end
43
+
44
+ test "connections" do
45
+ assert @route.connections.first.line == @route.lines[1]
46
+ assert @route.connections.first.states == @route.lines[0].pass_target
47
+ assert @route.connections.last.line == @route.lines[2]
48
+ assert @route.connections.last.states == @route.lines[0].fail_target
49
+ end
50
+
51
+ end
@@ -0,0 +1,115 @@
1
+ require_relative "test_helper"
2
+
3
+ class StationTest < MicroTest::Test
4
+
5
+ before do
6
+ @route = BasicMath.new
7
+ @line = @route.lines.first
8
+ @station = @line.stations.first
9
+ @passenger = Ellington::Passenger.new(NumberWithHistory.new(0), @route)
10
+ @passenger.current_state = @route.initial_state
11
+ @passenger.lock
12
+ end
13
+
14
+ test "name" do
15
+ assert @station.name == "Add10::Addition"
16
+ end
17
+
18
+ test "state_name" do
19
+ assert @station.state_name(:foo) == "FOO Add10::Addition"
20
+ end
21
+
22
+ test "passed" do
23
+ assert @station.passed == "PASS Add10::Addition"
24
+ end
25
+
26
+ test "failed" do
27
+ assert @station.failed == "FAIL Add10::Addition"
28
+ end
29
+
30
+ test "errored" do
31
+ assert @station.errored == "ERROR Add10::Addition"
32
+ end
33
+
34
+ test "states keys" do
35
+ assert @station.states.keys == [
36
+ @station.passed,
37
+ @station.failed,
38
+ @station.errored
39
+ ]
40
+ end
41
+
42
+ test "error state can transition to passed" do
43
+ assert @station.states.can_transition?(@station.errored => @station.passed)
44
+ end
45
+
46
+ test "error state can transition to failed" do
47
+ assert @station.states.can_transition?(@station.errored => @station.failed)
48
+ end
49
+
50
+ test "pass state is terminating" do
51
+ assert @station.states[@station.passed].nil?
52
+ assert !@station.states.can_transition?(@station.passed => @station.failed)
53
+ assert !@station.states.can_transition?(@station.passed => @station.errored)
54
+ end
55
+
56
+ test "fail state is terminating" do
57
+ assert @station.states[@station.failed].nil?
58
+ assert !@station.states.can_transition?(@station.failed => @station.passed)
59
+ assert !@station.states.can_transition?(@station.failed => @station.errored)
60
+ end
61
+
62
+ test "pass properly transitions passenger's state" do
63
+ @passenger.current_state = @route.initial_state
64
+ @station.pass @passenger
65
+ assert @passenger.current_state == @station.passed
66
+ end
67
+
68
+ test "fail properly transitions passenger's state" do
69
+ @passenger.current_state = @route.initial_state
70
+ @station.fail @passenger
71
+ assert @passenger.current_state == @station.failed
72
+ end
73
+
74
+ test "error properly transitions passenger's state" do
75
+ @passenger.current_state = @route.initial_state
76
+ @station.error @passenger
77
+ assert @passenger.current_state == @station.errored
78
+ end
79
+
80
+ test "can_engage? returns true for the expected inital state" do
81
+ @passenger.current_state = @route.initial_state
82
+ assert @station.can_engage?(@passenger)
83
+ end
84
+
85
+ test "can_engage? returns false for unexpected inital states" do
86
+ @passenger.current_state = @line.stations.last.passed
87
+ assert !@station.can_engage?(@passenger)
88
+ @passenger.current_state = :unexpected
89
+ assert !@station.can_engage?(@passenger)
90
+ end
91
+
92
+ test "engage" do
93
+ @passenger.current_state = @route.initial_state
94
+ @station.engage(@passenger, :pass => true)
95
+ assert @passenger.current_state == @station.passed
96
+ end
97
+
98
+ test "observers are notified after a station completes" do
99
+ observer = MicroMock.make.new
100
+ observer.attr :callbacks, []
101
+ observer.def :update do |info|
102
+ callbacks << info
103
+ end
104
+ @station.add_observer observer
105
+ @passenger.current_state = @route.initial_state
106
+ @station.call(@passenger, :pass => true)
107
+ assert observer.callbacks.length == 1
108
+ info = observer.callbacks.first
109
+ assert info.station == @station
110
+ assert info.passenger == @passenger
111
+ assert info.transition.old_state == @route.initial_state
112
+ assert info.transition.new_state == @station.passed
113
+ end
114
+
115
+ end
@@ -0,0 +1,54 @@
1
+ require_relative "test_helper"
2
+
3
+ class TargetTest < MicroTest::Test
4
+
5
+ before do
6
+ @number = NumberWithHistory.new(0)
7
+ end
8
+
9
+ test "basic goal" do
10
+ goal = Ellington::Target.new(:finished)
11
+ assert goal.include?(:finished)
12
+ end
13
+
14
+ test "multiple states" do
15
+ goal = Ellington::Target.new(:one, :two, :three)
16
+ assert goal.include?(:one)
17
+ assert goal.include?(:two)
18
+ assert goal.include?(:three)
19
+ end
20
+
21
+ test "not satisfied for nil passenger" do
22
+ goal = Ellington::Target.new(:finished)
23
+ assert !goal.satisfied?(nil)
24
+ end
25
+
26
+ test "not satisfied for passenger in the wrong state" do
27
+ passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
28
+ passenger.current_state = :open
29
+ goal = Ellington::Target.new(:closed)
30
+ assert !goal.satisfied?(passenger)
31
+ end
32
+
33
+ test "satisfied for passenger in the right state" do
34
+ passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
35
+ passenger.current_state = :closed
36
+ goal = Ellington::Target.new(:closed)
37
+ assert goal.satisfied?(passenger)
38
+ end
39
+
40
+ test "satisfied for passenger in an expected state" do
41
+ passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
42
+ passenger.current_state = :two
43
+ goal = Ellington::Target.new(:one, :two, :three)
44
+ assert goal.satisfied?(passenger)
45
+ end
46
+
47
+ test "not satisfied for passenger not in an expected state" do
48
+ passenger = Ellington::Passenger.new(@number, Ellington::Ticket.new, StateJacket::Catalog.new)
49
+ passenger.current_state = :four
50
+ goal = Ellington::Target.new(:one, :two, :three)
51
+ assert !goal.satisfied?(passenger)
52
+ end
53
+
54
+ end
@@ -0,0 +1,6 @@
1
+ require "logger"
2
+ require "delegate"
3
+ require 'pry-exception_explorer'
4
+ require_relative "../lib/ellington"
5
+ require_relative "example"
6
+
@@ -0,0 +1,39 @@
1
+ require_relative "test_helper"
2
+ require "digest"
3
+
4
+ class TicketTest < MicroTest::Test
5
+
6
+ before do
7
+ @route = BasicMath.new
8
+ @ticket = Ellington::Ticket.new(Ellington::Target.new(:closed),
9
+ :user_id => "458e9710-c1c4-495b-b25a-c622e893f6f7",
10
+ :debit_id => "b834fb69-2eb3-4e57-b313-16b863e91f74",
11
+ :credit_id => "9a670fce-4826-4a90-aaf7-a58738a4ce5b"
12
+ )
13
+ @passenger = Ellington::Passenger.new(0, @route, @ticket)
14
+ end
15
+
16
+ test "basic ticket" do
17
+ assert @ticket[:user_id] == "458e9710-c1c4-495b-b25a-c622e893f6f7"
18
+ assert @ticket[:debit_id] == "b834fb69-2eb3-4e57-b313-16b863e91f74"
19
+ assert @ticket[:credit_id] == "9a670fce-4826-4a90-aaf7-a58738a4ce5b"
20
+ end
21
+
22
+ test "ticket id" do
23
+ assert @ticket.id == Digest::SHA256.hexdigest(@ticket.values.map(&:to_s).join)
24
+ end
25
+
26
+ test "goal" do
27
+ assert @ticket.goal.to_a == [:closed]
28
+ end
29
+
30
+ test "goal is not achieved when passenger is not in the correct state" do
31
+ assert !@ticket.goal.satisfied?(@passenger)
32
+ end
33
+
34
+ test "goal is achieved when passenger is in the correct state" do
35
+ @passenger.current_state = :closed
36
+ assert @ticket.goal.satisfied?(@passenger)
37
+ end
38
+
39
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ellington
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,92 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-16 00:00:00.000000000 Z
13
- dependencies: []
14
- description: Write a gem description
12
+ date: 2013-02-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hero
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: state_jacket
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.0.7
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.0.7
46
+ description: ! "\n Ellington is a collection of simple concepts designed to bring
47
+ discipline, organization, and modularity to a project.\n\n The nomenclature is
48
+ taken from New York's subway system.\n We've found that using cohesive physical
49
+ metaphors helps people reason more clearly about the complexities of software.\n
50
+ \ The subway analogy isn't perfect but gets pretty close.\n\n The Ellington
51
+ architecture should only be applied after a good understanding of the problem domain
52
+ has been established.\n We recommend spiking a solution to learn your project's
53
+ requirements and then coming back to Ellington.\n "
15
54
  email:
16
55
  - natehop@gmail.com
17
56
  executables: []
18
57
  extensions: []
19
58
  extra_rdoc_files: []
20
59
  files:
21
- - .gitignore
60
+ - lib/ellington/attendant.rb
61
+ - lib/ellington/conductor.rb
62
+ - lib/ellington/connection.rb
63
+ - lib/ellington/connection_list.rb
64
+ - lib/ellington/errros.rb
65
+ - lib/ellington/has_targets.rb
66
+ - lib/ellington/line.rb
67
+ - lib/ellington/line_info.rb
68
+ - lib/ellington/line_list.rb
69
+ - lib/ellington/logger.rb
70
+ - lib/ellington/passenger.rb
71
+ - lib/ellington/route.rb
72
+ - lib/ellington/route_info.rb
73
+ - lib/ellington/station.rb
74
+ - lib/ellington/station_info.rb
75
+ - lib/ellington/station_list.rb
76
+ - lib/ellington/target.rb
77
+ - lib/ellington/ticket.rb
78
+ - lib/ellington/transition_info.rb
79
+ - lib/ellington/unique_type_array.rb
80
+ - lib/ellington/version.rb
81
+ - lib/ellington.rb
22
82
  - Gemfile
83
+ - Gemfile.lock
23
84
  - LICENSE.txt
24
- - README.md
25
85
  - Rakefile
26
- - ellington.gemspec
27
- - lib/ellington.rb
28
- - lib/ellington/version.rb
29
- homepage: ''
86
+ - README.md
87
+ - test/attendant_test.rb
88
+ - test/conductor_test.rb
89
+ - test/example.rb
90
+ - test/line_test.rb
91
+ - test/passenger_test.rb
92
+ - test/route_test.rb
93
+ - test/station_test.rb
94
+ - test/target_test.rb
95
+ - test/test_helper.rb
96
+ - test/ticket_test.rb
97
+ homepage: https://github.com/hopsoft/ellington
30
98
  licenses: []
31
99
  post_install_message:
32
100
  rdoc_options: []
@@ -46,9 +114,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
114
  version: '0'
47
115
  requirements: []
48
116
  rubyforge_project:
49
- rubygems_version: 1.8.23
117
+ rubygems_version: 1.8.25
50
118
  signing_key:
51
119
  specification_version: 3
52
- summary: Write a gem summary
53
- test_files: []
54
- has_rdoc:
120
+ summary: A framework for moving stateful objects through a complex series of business
121
+ rules.
122
+ test_files:
123
+ - test/attendant_test.rb
124
+ - test/conductor_test.rb
125
+ - test/example.rb
126
+ - test/line_test.rb
127
+ - test/passenger_test.rb
128
+ - test/route_test.rb
129
+ - test/station_test.rb
130
+ - test/target_test.rb
131
+ - test/test_helper.rb
132
+ - test/ticket_test.rb
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
data/ellington.gemspec DELETED
@@ -1,19 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'ellington/version'
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = "ellington"
8
- gem.version = Ellington::VERSION
9
- gem.authors = ["Nathan Hopkins"]
10
- gem.email = ["natehop@gmail.com"]
11
- gem.description = %q{Write a gem description}
12
- gem.summary = %q{Write a gem summary}
13
- gem.homepage = ""
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
- end