tzu 0.1.2.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: be375f294991c28ee40881e6e85a43241850517b
4
- data.tar.gz: ecc8b1aaa61056c1b9c599490c7bc29435e8188a
2
+ SHA256:
3
+ metadata.gz: 3461c8cde94996a9366831443f7bc018fea3ecc7bbbf39b051a8186dbc83941c
4
+ data.tar.gz: a68fedad1cc1379833332982bb56a683a3f5b0d68675cf4e21587bb10dacbaee
5
5
  SHA512:
6
- metadata.gz: fbbd46f7370634bb89364cc4f5e1a1fddcef871c10a263d7972b13f03476ed43f5717827c60d9d5d3405d10bf711bafabe944af9d8cfe11facec1b814e68a2d3
7
- data.tar.gz: 4a4de35db5b1d1b3bf320bacc8961b25309969384fed0cbdb28d93406bd271f0fba72c1b8d39c21543b4c889bb74513fec0c3e1b4d5d7dfda091c0422714a227
6
+ metadata.gz: 1f7a7b835a3f3340e8af96f4d733523b054cd82ee87b69024c1bc90843fa2452125f18aa12141b9bbcff9ab8adda1f89ff2c6d26a38acc457dbf367873834b2c
7
+ data.tar.gz: da137e33a5883acd558ff3fbf070055697aeeacc60766f8a71a8b78c4ab43e1e18b59c383309261e9abbf9324fc399529d3d454b77bfb228f84656cb474250a2
data/README.md CHANGED
@@ -4,7 +4,7 @@ Tzu provides a simple interface for writing classes that encapsulate a single co
4
4
 
5
5
  **Commands should:**
6
6
 
7
- - Do exactly one thing (Single Responsibility Priciple)
7
+ - Do exactly one thing (Single Responsibility Principle)
8
8
  - Be self-documenting
9
9
  - Be testable
10
10
  - Be easy to mock and stub
data/lib/tzu/failure.rb CHANGED
@@ -8,7 +8,7 @@ module Tzu
8
8
  end
9
9
 
10
10
  def errors
11
- string_error? ? { errors: @raw_errors } : @raw_errors
11
+ string_error? ? {errors: @raw_errors} : @raw_errors
12
12
  end
13
13
 
14
14
  def message
data/lib/tzu/hooks.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module Tzu
2
-
3
2
  # Provides hooks for arbitrary pre- and post- processing within a command
4
3
  module Hooks
5
4
  def self.included(base)
data/lib/tzu/match.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module Tzu
2
-
3
2
  # with thanks to https://github.com/pzol/deterministic
4
3
  class Match
5
4
  def initialize(outcome, context)
@@ -12,15 +11,15 @@ module Tzu
12
11
  @context.instance_exec(@outcome.result, &matcher.block)
13
12
  end
14
13
 
15
- %w(success failure).each do |type|
16
- define_method type.to_sym do |condition=nil, &result_block|
14
+ %w[success failure].each do |type|
15
+ define_method type.to_sym do |condition = nil, &result_block|
17
16
  push(type, condition, result_block)
18
17
  end
19
18
  end
20
19
 
21
20
  # todo: hash and define_method if more overrides identified
22
21
  def invalid(&result_block)
23
- push('failure', :validation, result_block)
22
+ push("failure", :validation, result_block)
24
23
  end
25
24
 
26
25
  private
@@ -32,12 +31,15 @@ module Tzu
32
31
  end
33
32
 
34
33
  def push(type, condition, result_block)
35
- condition_pred = case
36
- when condition.nil?; ->(v) { true }
37
- when condition.is_a?(Proc); condition
38
- when condition.is_a?(Class); ->(v) { condition === @outcome.type }
39
- else ->(v) { @outcome.type == condition }
40
- end
34
+ condition_pred = if condition.nil?
35
+ ->(v) { true }
36
+ elsif condition.is_a?(Proc)
37
+ condition
38
+ elsif condition.is_a?(Class)
39
+ ->(v) { condition === @outcome.type }
40
+ else
41
+ ->(v) { @outcome.type == condition }
42
+ end
41
43
 
42
44
  matcher_pred = compose_predicates(type_pred[type], condition_pred)
43
45
  @collection << Matcher.new(matcher_pred, result_block)
@@ -49,7 +51,7 @@ module Tzu
49
51
 
50
52
  # return a partial function for matching a matcher's type
51
53
  def type_pred
52
- (->(type, x) { @outcome.send("#{type.to_s}?") }).curry
54
+ ->(type, x) { @outcome.send(:"#{type}?") }.curry
53
55
  end
54
56
  end
55
57
  end
data/lib/tzu/outcome.rb CHANGED
@@ -17,10 +17,10 @@ module Tzu
17
17
  !@success
18
18
  end
19
19
 
20
- def handle(context=nil, &block)
21
- context ||= block.binding.eval('self')
20
+ def handle(context = nil, &block)
21
+ context ||= block.binding.eval("self")
22
22
  match = Match.new(self, context)
23
- match.instance_eval &block
23
+ match.instance_eval(&block)
24
24
  match.result
25
25
  end
26
26
  end
@@ -21,7 +21,7 @@ module Tzu
21
21
  if value.nil?
22
22
  @name ||= name.underscore.to_sym
23
23
  else
24
- @name = (value.presence && value.to_sym)
24
+ @name = value.presence && value.to_sym
25
25
  end
26
26
  end
27
27
 
data/lib/tzu/sequence.rb CHANGED
@@ -21,7 +21,7 @@ module Tzu
21
21
  end
22
22
 
23
23
  def step(klass, &block)
24
- @steps = [] unless @steps
24
+ @steps ||= []
25
25
 
26
26
  step = Step.new(klass)
27
27
  step.instance_eval(&block) if block
@@ -56,7 +56,7 @@ module Tzu
56
56
  private
57
57
 
58
58
  def last_outcome_is_failure?
59
- return true if (@last_outcome.respond_to?(:failure?) && @last_outcome.failure?)
59
+ return true if @last_outcome.respond_to?(:failure?) && @last_outcome.failure?
60
60
  false
61
61
  end
62
62
 
data/lib/tzu/step.rb CHANGED
@@ -1,8 +1,11 @@
1
+ require "active_support"
2
+ require "active_support/core_ext/object/blank"
3
+ require "active_support/core_ext/string/inflections"
4
+
1
5
  module Tzu
2
6
  class Step
3
- DOUBLE_MUTATOR = 'You cannot define both receives and receives_many'
7
+ DOUBLE_MUTATOR = "You cannot define both receives and receives_many"
4
8
 
5
- String.send(:include, ::Tzu::CoreExtensions::String)
6
9
  attr_reader :klass, :single_mutator, :splat_mutator
7
10
 
8
11
  def initialize(klass)
@@ -21,8 +24,9 @@ module Tzu
21
24
  end
22
25
 
23
26
  def name
24
- return @name if @name && @name.is_a?(Symbol)
25
- @klass.to_s.split('::').last.symbolize
27
+ return @name if @name&.is_a?(Symbol)
28
+
29
+ @klass.to_s.split("::").last.underscore.to_sym
26
30
  end
27
31
 
28
32
  def receives(&block)
@@ -1,6 +1,5 @@
1
1
  module Tzu
2
2
  module Validation
3
-
4
3
  def self.included(base)
5
4
  base.class_eval do
6
5
  # registers validation as a before hook
@@ -16,12 +15,13 @@ module Tzu
16
15
 
17
16
  def validate(params)
18
17
  return ValidationResult.new(params.valid?, params.errors) if params.respond_to?(:valid?)
18
+
19
19
  ValidationResult.new(true)
20
20
  end
21
21
 
22
22
  def invalid!(obj)
23
23
  output = [:errors, :messages, :message].reduce(obj) do |result, m|
24
- result = result.respond_to?(m) ? result.send(m) : result
24
+ result.respond_to?(m) ? result.send(m) : result
25
25
  end
26
26
 
27
27
  raise Invalid.new(output)
@@ -10,4 +10,4 @@ module Tzu
10
10
  @valid
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzu
4
+ VERSION = "1.0.0"
5
+ end
data/lib/tzu.rb CHANGED
@@ -1,15 +1,14 @@
1
- require 'tzu/core_extensions/string'
2
- require 'tzu/errors'
3
- require 'tzu/run_methods'
4
- require 'tzu/failure'
5
- require 'tzu/hooks'
6
- require 'tzu/invalid'
7
- require 'tzu/match'
8
- require 'tzu/sequence'
9
- require 'tzu/step'
10
- require 'tzu/outcome'
11
- require 'tzu/validation'
12
- require 'tzu/validation_result'
1
+ require "tzu/errors"
2
+ require "tzu/run_methods"
3
+ require "tzu/failure"
4
+ require "tzu/hooks"
5
+ require "tzu/invalid"
6
+ require "tzu/match"
7
+ require "tzu/sequence"
8
+ require "tzu/step"
9
+ require "tzu/outcome"
10
+ require "tzu/validation"
11
+ require "tzu/validation_result"
13
12
 
14
13
  module Tzu
15
14
  def self.included(base)
@@ -32,7 +31,7 @@ module Tzu
32
31
  outcome.is_a?(Tzu::Outcome) ? outcome : Outcome.new(true, outcome)
33
32
  end
34
33
  rescue
35
- rollback! if self.respond_to?(:rollback!)
34
+ rollback! if respond_to?(:rollback!)
36
35
  raise
37
36
  end
38
37
 
metadata CHANGED
@@ -1,114 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tzu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morgan Bruce
8
8
  - Blake Turner
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-10-23 00:00:00.000000000 Z
12
+ date: 2024-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: 1.0.0
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: 1.0.0
28
- - !ruby/object:Gem::Dependency
29
- name: activerecord
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 3.2.15
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: 3.2.15
42
14
  - !ruby/object:Gem::Dependency
43
15
  name: activesupport
44
16
  requirement: !ruby/object:Gem::Requirement
45
17
  requirements:
46
18
  - - ">="
47
19
  - !ruby/object:Gem::Version
48
- version: 3.2.15
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: 3.2.15
56
- - !ruby/object:Gem::Dependency
57
- name: rspec
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 2.4.0
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - ">="
20
+ version: '4.2'
21
+ - - "<"
68
22
  - !ruby/object:Gem::Version
69
- version: 2.4.0
70
- - !ruby/object:Gem::Dependency
71
- name: sqlite3
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
23
+ version: '8'
24
+ type: :runtime
78
25
  prerelease: false
79
26
  version_requirements: !ruby/object:Gem::Requirement
80
27
  requirements:
81
28
  - - ">="
82
29
  - !ruby/object:Gem::Version
83
- version: '0'
84
- - !ruby/object:Gem::Dependency
85
- name: byebug
86
- requirement: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: '0'
91
- type: :development
92
- prerelease: false
93
- version_requirements: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- version: '0'
98
- - !ruby/object:Gem::Dependency
99
- name: virtus
100
- requirement: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- version: '0'
105
- type: :development
106
- prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - ">="
30
+ version: '4.2'
31
+ - - "<"
110
32
  - !ruby/object:Gem::Version
111
- version: '0'
33
+ version: '8'
112
34
  description: Tzu is a library for issuing commands in Ruby
113
35
  email: morgan@onfido.com
114
36
  executables: []
@@ -118,7 +40,6 @@ files:
118
40
  - LICENSE.txt
119
41
  - README.md
120
42
  - lib/tzu.rb
121
- - lib/tzu/core_extensions/string.rb
122
43
  - lib/tzu/errors.rb
123
44
  - lib/tzu/failure.rb
124
45
  - lib/tzu/hooks.rb
@@ -130,18 +51,12 @@ files:
130
51
  - lib/tzu/step.rb
131
52
  - lib/tzu/validation.rb
132
53
  - lib/tzu/validation_result.rb
133
- - spec/hooks_spec.rb
134
- - spec/outcome_spec.rb
135
- - spec/sequence_spec.rb
136
- - spec/spec_helper.rb
137
- - spec/step_spec.rb
138
- - spec/tzu_spec.rb
139
- - spec/validation_spec.rb
54
+ - lib/tzu/version.rb
140
55
  homepage: https://github.com/onfido/tzu
141
56
  licenses:
142
57
  - MIT
143
58
  metadata: {}
144
- post_install_message:
59
+ post_install_message:
145
60
  rdoc_options: []
146
61
  require_paths:
147
62
  - lib
@@ -156,16 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
71
  - !ruby/object:Gem::Version
157
72
  version: '0'
158
73
  requirements: []
159
- rubyforge_project:
160
- rubygems_version: 2.4.6
161
- signing_key:
74
+ rubygems_version: 3.4.22
75
+ signing_key:
162
76
  specification_version: 4
163
77
  summary: Standardise and encapsulate your application's actions
164
- test_files:
165
- - spec/hooks_spec.rb
166
- - spec/outcome_spec.rb
167
- - spec/sequence_spec.rb
168
- - spec/spec_helper.rb
169
- - spec/step_spec.rb
170
- - spec/tzu_spec.rb
171
- - spec/validation_spec.rb
78
+ test_files: []
@@ -1,17 +0,0 @@
1
- module Tzu
2
- module CoreExtensions
3
- module String
4
- def symbolize
5
- underscore.to_sym
6
- end
7
-
8
- def underscore
9
- gsub(/::/, '/')
10
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
11
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
12
- .tr('-', '_')
13
- .downcase
14
- end
15
- end
16
- end
17
- end
data/spec/hooks_spec.rb DELETED
@@ -1,169 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Tzu::Hooks do
4
- describe '#with_hooks' do
5
- def build_hooked(&block)
6
- hooked = Class.new.send(:include, Tzu::Hooks)
7
-
8
- hooked.class_eval do
9
- attr_reader :steps
10
-
11
- def self.process
12
- new.tap(&:process).steps
13
- end
14
-
15
- def initialize
16
- @steps = []
17
- end
18
-
19
- def process
20
- with_hooks({}) { steps << :process }
21
- end
22
- end
23
-
24
- hooked.class_eval(&block) if block
25
- hooked
26
- end
27
-
28
- context 'when before hook is a method' do
29
- let(:hooked) do
30
- build_hooked do
31
- before :add_before
32
-
33
- def add_before(p)
34
- steps << :before
35
- end
36
- end
37
- end
38
-
39
- it 'runs the before hook method' do
40
- expect(hooked.process).to eq([:before, :process])
41
- end
42
- end
43
-
44
- context 'when before hook is a block' do
45
- let(:hooked) do
46
- build_hooked do
47
- before do
48
- steps << :before
49
- end
50
- end
51
- end
52
-
53
- it 'runs the before hook block' do
54
- expect(hooked.process).to eq([:before, :process])
55
- end
56
- end
57
-
58
- context 'when after hook is a method' do
59
- let(:hooked) do
60
- build_hooked do
61
- after :add_after
62
-
63
- def add_after(p)
64
- steps << :after
65
- end
66
- end
67
- end
68
-
69
- it 'runs the after hook method' do
70
- expect(hooked.process).to eq([:process, :after])
71
- end
72
- end
73
-
74
- context 'when after hook is a block' do
75
- let(:hooked) do
76
- build_hooked do
77
- after do
78
- steps << :after
79
- end
80
- end
81
- end
82
-
83
- it 'runs the after hook block' do
84
- expect(hooked.process).to eq([:process, :after])
85
- end
86
- end
87
-
88
- context 'when both before and after blocks are defined' do
89
- let(:hooked) do
90
- build_hooked do
91
- before do
92
- steps << :before
93
- end
94
-
95
- after do
96
- steps << :after
97
- end
98
- end
99
- end
100
-
101
- it 'runs hooks in the expected order' do
102
- expect(hooked.process).to eq([:before, :process, :after])
103
- end
104
- end
105
-
106
-
107
- context 'when both before and after methods are defined' do
108
- let(:hooked) do
109
- build_hooked do
110
- before :add_before
111
- after :add_after
112
-
113
- def add_before(p)
114
- steps << :before
115
- end
116
-
117
- def add_after(p)
118
- steps << :after
119
- end
120
- end
121
- end
122
-
123
- it 'runs hooks in the expected order' do
124
- expect(hooked.process).to eq([:before, :process, :after])
125
- end
126
- end
127
-
128
- context 'when multiple before methods are defined' do
129
- let(:hooked) do
130
- build_hooked do
131
- before :add_before1, :add_before2
132
-
133
- def add_before1(p)
134
- steps << :before1
135
- end
136
-
137
- def add_before2(p)
138
- steps << :before2
139
- end
140
- end
141
- end
142
-
143
- it 'runs hooks in the expected order' do
144
- expect(hooked.process).to eq([:before1, :before2, :process])
145
- end
146
- end
147
-
148
- context 'when multiple after methods are defined' do
149
- let(:hooked) do
150
- build_hooked do
151
- after :add_after1, :add_after2
152
-
153
- def add_after1(p)
154
- steps << :after1
155
- end
156
-
157
- def add_after2(p)
158
- steps << :after2
159
- end
160
- end
161
- end
162
-
163
- it 'runs hooks in the expected order' do
164
- expect(hooked.process).to eq([:process, :after1, :after2])
165
- end
166
- end
167
-
168
- end
169
- end
data/spec/outcome_spec.rb DELETED
@@ -1,48 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Tzu::Outcome do
4
-
5
- context 'outcome is failed with specified type' do
6
- subject { Tzu::Outcome.new(false, 'abc', :validation) }
7
-
8
- it 'calls appropriate handler' do
9
- matched = false
10
- subject.handle do
11
- success { raise }
12
- failure(:something) { raise }
13
- failure(:validation) { matched = true }
14
- end
15
- expect(matched).to eq true
16
- end
17
- end
18
-
19
- context 'outcome is failed with unspecified type' do
20
- subject { Tzu::Outcome.new(false, 'abc', :validation) }
21
-
22
- it 'calls appropriate handler' do
23
- matched = false
24
- subject.handle do
25
- success { raise }
26
- failure { matched = true }
27
- failure(:validation) { raise }
28
- end
29
- expect(matched).to eq true
30
- end
31
- end
32
-
33
- context 'outcome is successful' do
34
- subject { Tzu::Outcome.new(true, 'abc') }
35
-
36
- it 'calls success handler' do
37
- matched = false
38
- subject.handle do
39
- success { matched = true }
40
- failure(:something) { raise }
41
- end
42
- expect(matched).to eq true
43
- end
44
- end
45
- end
46
-
47
-
48
-
@@ -1,232 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class SayMyName
4
- include Tzu
5
-
6
- def call(params)
7
- "Hello, #{params[:name]}"
8
- end
9
- end
10
-
11
- class MakeMeSoundImportant
12
- include Tzu
13
-
14
- def call(params)
15
- "#{params[:boring_message]}! You are the most important citizen of #{params[:country]}!"
16
- end
17
- end
18
-
19
- class ThrowInvalidError
20
- include Tzu
21
-
22
- def call(params)
23
- invalid!('Who am I? Why am I here?')
24
- end
25
- end
26
-
27
- class ConstructGreeting
28
- class << self
29
- def go(greeting, name)
30
- "#{greeting}, #{name}"
31
- end
32
- end
33
- end
34
-
35
- class MultiStepSimple
36
- include Tzu::Sequence
37
-
38
- step SayMyName do
39
- receives do |params|
40
- { name: params[:name] }
41
- end
42
- end
43
-
44
- step MakeMeSoundImportant do
45
- receives do |params, prior_results|
46
- {
47
- boring_message: prior_results[:say_my_name],
48
- country: params[:country]
49
- }
50
- end
51
- end
52
- end
53
-
54
- class MultiStepNonTzu
55
- include Tzu::Sequence
56
-
57
- step ConstructGreeting do
58
- as :say_my_name
59
- invoke_with :go
60
-
61
- receives_many do |greeting, name, country|
62
- [greeting, name]
63
- end
64
- end
65
-
66
- step MakeMeSoundImportant do
67
- receives do |greeting, name, country, prior_results|
68
- {
69
- boring_message: prior_results[:say_my_name],
70
- country: country
71
- }
72
- end
73
- end
74
- end
75
-
76
- class MultiStepComplex
77
- include Tzu::Sequence
78
-
79
- step SayMyName do
80
- as :first_command
81
- end
82
-
83
- step MakeMeSoundImportant do
84
- as :final_command
85
- receives do |params, prior_results|
86
- {
87
- boring_message: prior_results[:first_command],
88
- country: params[:country]
89
- }
90
- end
91
- end
92
-
93
- result :take_all
94
- end
95
-
96
- class MultiStepProcessResults
97
- include Tzu::Sequence
98
-
99
- step SayMyName do
100
- as :first_command
101
- end
102
-
103
- step MakeMeSoundImportant do
104
- as :final_command
105
- receives do |params, prior_results|
106
- {
107
- boring_message: prior_results[:first_command],
108
- country: params[:country]
109
- }
110
- end
111
- end
112
-
113
- result do |params, prior_results|
114
- {
115
- status: :important,
116
- message: "BULLETIN: #{prior_results[:final_command]}"
117
- }
118
- end
119
- end
120
-
121
- class MultiStepInvalid
122
- include Tzu::Sequence
123
-
124
- step SayMyName
125
-
126
- step ThrowInvalidError do
127
- receives do |params, prior_results|
128
- { answer: "#{params[:name]}!!! #{prior_results[:say_my_name]}" }
129
- end
130
- end
131
-
132
- step MakeMeSoundImportant do
133
- receives do |params, prior_results|
134
- {
135
- boring_message: prior_results[:say_my_name],
136
- country: params[:country]
137
- }
138
- end
139
- end
140
- end
141
-
142
- describe Tzu::Sequence do
143
- context '#steps' do
144
- context MultiStepSimple do
145
- let(:steps) { MultiStepSimple.steps }
146
-
147
- it 'returns array of Steps' do
148
- steps.each { |step| expect(step.is_a? Tzu::Step).to be true }
149
- end
150
-
151
- it 'passes the appropriate klass, name, and param_mutators to each step' do
152
- say_my_name = steps.first
153
- expect(say_my_name.klass).to eq SayMyName
154
- expect(say_my_name.name).to eq :say_my_name
155
- expect(say_my_name.single_mutator.is_a? Proc).to be true
156
-
157
- make_me_sound_important = steps.last
158
- expect(make_me_sound_important.klass).to eq MakeMeSoundImportant
159
- expect(make_me_sound_important.name).to eq :make_me_sound_important
160
- expect(make_me_sound_important.single_mutator.is_a? Proc).to be true
161
- end
162
- end
163
-
164
- context MultiStepComplex do
165
- let(:steps) { MultiStepComplex.steps }
166
-
167
- it 'returns array of Steps' do
168
- steps.each { |step| expect(step.is_a? Tzu::Step).to be true }
169
- end
170
-
171
- it 'passes the appropriate klass, name, and param_mutators to each step' do
172
- say_my_name = steps.first
173
- expect(say_my_name.klass).to eq SayMyName
174
- expect(say_my_name.name).to eq :first_command
175
-
176
- make_me_sound_important = steps.last
177
- expect(make_me_sound_important.klass).to eq MakeMeSoundImportant
178
- expect(make_me_sound_important.name).to eq :final_command
179
- expect(make_me_sound_important.single_mutator.is_a? Proc).to be true
180
- end
181
- end
182
- end
183
-
184
- context '#run' do
185
- let(:params) do
186
- {
187
- name: 'Jessica',
188
- country: 'Azerbaijan'
189
- }
190
- end
191
-
192
- context MultiStepSimple do
193
- it 'returns the outcome of the last command' do
194
- outcome = MultiStepSimple.run(params)
195
- expect(outcome.result).to eq 'Hello, Jessica! You are the most important citizen of Azerbaijan!'
196
- end
197
- end
198
-
199
- context MultiStepNonTzu do
200
- it 'returns the outcome of the last command' do
201
- outcome = MultiStepNonTzu.run('Greetings', 'Christopher', 'Canada')
202
- expect(outcome.result).to eq 'Greetings, Christopher! You are the most important citizen of Canada!'
203
- end
204
- end
205
-
206
- context MultiStepComplex do
207
- it 'returns the outcome of the last command' do
208
- outcome = MultiStepComplex.run(params)
209
- results = outcome.result
210
- expect(results[:first_command]).to eq 'Hello, Jessica'
211
- expect(results[:final_command]).to eq 'Hello, Jessica! You are the most important citizen of Azerbaijan!'
212
- end
213
- end
214
-
215
- context MultiStepProcessResults do
216
- it 'returns the outcome of the last command' do
217
- outcome = MultiStepProcessResults.run(params)
218
- result = outcome.result
219
- expect(result[:status]).to eq :important
220
- expect(result[:message]).to eq 'BULLETIN: Hello, Jessica! You are the most important citizen of Azerbaijan!'
221
- end
222
- end
223
-
224
- context MultiStepInvalid do
225
- it 'stops its execution at the invalid command, which it returns' do
226
- outcome = MultiStepInvalid.run(params)
227
- expect(outcome.success?).to be false
228
- expect(outcome.result).to eq(errors: 'Who am I? Why am I here?')
229
- end
230
- end
231
- end
232
- end
data/spec/spec_helper.rb DELETED
@@ -1,9 +0,0 @@
1
- require 'rubygems'
2
- require 'byebug'
3
- require 'rspec'
4
- require 'active_record'
5
- require 'virtus'
6
- require 'bundler/setup'
7
- Bundler.setup
8
-
9
- require 'tzu'
data/spec/step_spec.rb DELETED
@@ -1,56 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Tzu::Step do
4
- let(:dummy_mutator) { proc { 'Dummy!' } }
5
-
6
- context '#name' do
7
- context 'when name is symbol' do
8
- let(:step) { Tzu::Step.new(:step_name) }
9
-
10
- it 'returns name' do
11
- expect(step.name).to eq :step_name
12
- end
13
- end
14
-
15
- context 'when name is a class' do
16
- let(:step) { Tzu::Step.new(StandardError) }
17
- let(:outcome) { ControlledOutcome.run(result: :success) }
18
-
19
- it 'returns underscored name' do
20
- expect(step.name).to eq :standard_error
21
- end
22
- end
23
- end
24
-
25
- context '#receives' do
26
- context 'when splat_mutator is already defined' do
27
- let(:step) { Tzu::Step.new(:step_name) }
28
-
29
- before do
30
- step.receives_many do |variable|
31
- [1, 2, 3]
32
- end
33
- end
34
-
35
- it 'throws error' do
36
- expect { step.receives { |var| 'foo'} } .to raise_error(Tzu::InvalidSequence)
37
- end
38
- end
39
- end
40
-
41
- context '#receives_many' do
42
- context 'when single_mutator is already defined' do
43
- let(:step) { Tzu::Step.new(:step_name) }
44
-
45
- before do
46
- step.receives do |var|
47
- 'hello'
48
- end
49
- end
50
-
51
- it 'throws error' do
52
- expect { step.receives_many { |var| [1, 2, 3] } } .to raise_error(Tzu::InvalidSequence)
53
- end
54
- end
55
- end
56
- end
data/spec/tzu_spec.rb DELETED
@@ -1,214 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class ControlledOutcome
4
- include Tzu
5
-
6
- def call(params)
7
- result = params[:result]
8
- return 123 if result == :success
9
- return invalid!('Invalid Message') if result == :invalid
10
- return fail!(:falure_type, 'Failure Message') if result == :failure
11
- end
12
- end
13
-
14
- class MyRequestObject
15
- attr_reader :value, :errors
16
-
17
- def initialize(params)
18
- @params = params
19
- @value = params[:value]
20
- @errors = 'Error Message'
21
- end
22
-
23
- def valid?
24
- @params[:valid]
25
- end
26
- end
27
-
28
- class VirtusRequestObject
29
- include Virtus.model
30
- include ActiveModel::Validations
31
-
32
- validates :name, :age, presence: :true
33
-
34
- attribute :name, String
35
- attribute :age, Integer
36
- end
37
-
38
- class ValidatedCommand
39
- include Tzu
40
-
41
- request_object MyRequestObject
42
-
43
- def call(request)
44
- request.value
45
- end
46
- end
47
-
48
- class VirtusValidatedCommand
49
- include Tzu
50
-
51
- request_object VirtusRequestObject
52
-
53
- def call(request)
54
- "Name: #{request.name}, Age: #{request.age}"
55
- end
56
- end
57
-
58
- describe Tzu do
59
- context '#run' do
60
- context 'when command succeeds' do
61
- let(:outcome) { ControlledOutcome.run(result: :success) }
62
-
63
- it 'correctly returns sets pass/fail flags' do
64
- expect(outcome.success?).to be true
65
- expect(outcome.failure?).to be false
66
- end
67
-
68
- it 'returns result' do
69
- expect(outcome.result).to eq(123)
70
- end
71
- end
72
-
73
- context 'when command is invalid' do
74
- let(:outcome) { ControlledOutcome.run(result: :invalid) }
75
-
76
- it 'correctly returns sets pass/fail flags' do
77
- expect(outcome.success?).to be false
78
- expect(outcome.failure?).to be true
79
- end
80
-
81
- it 'returns error string as errors hash' do
82
- expect(outcome.result).to eq(errors: 'Invalid Message')
83
- end
84
-
85
- it 'sets type to validation' do
86
- expect(outcome.type).to eq(:validation)
87
- end
88
- end
89
-
90
- context 'when command fails' do
91
- let(:outcome) { ControlledOutcome.run(result: :failure) }
92
-
93
- it 'correctly returns sets pass/fail flags' do
94
- expect(outcome.success?).to be false
95
- expect(outcome.failure?).to be true
96
- end
97
-
98
- it 'returns error string as errors hash' do
99
- expect(outcome.result).to eq(errors: 'Failure Message')
100
- end
101
-
102
- it 'sets type to falure_type' do
103
- expect(outcome.type).to eq(:falure_type)
104
- end
105
- end
106
- end
107
-
108
- context '#run with block' do
109
- let(:success_spy) { spy('success') }
110
- let(:invalid_spy) { spy('invalid') }
111
- let(:failure_spy) { spy('failure') }
112
-
113
- before do
114
- ControlledOutcome.run(result: result) do
115
- success { |_| success_spy.call }
116
- invalid { |_| invalid_spy.call }
117
- failure { |_| failure_spy.call }
118
- end
119
- end
120
-
121
- context 'when command succeeds' do
122
- let(:result) { :success }
123
- it 'executes success block' do
124
- expect(success_spy).to have_received(:call)
125
- end
126
- end
127
-
128
- context 'when command is invalid' do
129
- let(:result) { :invalid }
130
- it 'executes invalid block' do
131
- expect(invalid_spy).to have_received(:call)
132
- end
133
- end
134
-
135
- context 'when command fails' do
136
- let(:result) { :failure }
137
- it 'executes failure block' do
138
- expect(failure_spy).to have_received(:call)
139
- end
140
- end
141
- end
142
-
143
- context '#run with request object' do
144
- context 'when request is valid' do
145
- let(:outcome) { ValidatedCommand.run(value: 1111, valid: true) }
146
-
147
- it 'executes successfully' do
148
- expect(outcome.success?).to be true
149
- end
150
-
151
- it 'returns value' do
152
- expect(outcome.result).to eq 1111
153
- end
154
- end
155
-
156
- context 'when request is invalid' do
157
- let(:outcome) { ValidatedCommand.run(value: 2222, valid: false) }
158
-
159
- it 'does not execute successfully' do
160
- expect(outcome.failure?).to be true
161
- end
162
-
163
- it 'has outcome type :validation' do
164
- expect(outcome.type).to eq :validation
165
- end
166
-
167
- it 'returns error string as errors hash' do
168
- expect(outcome.result).to eq(errors: 'Error Message')
169
- end
170
- end
171
-
172
- context 'with virtus/active_model request object' do
173
- let(:outcome) { VirtusValidatedCommand.run(params) }
174
-
175
- context 'when request is valid' do
176
- let(:params) { { name: 'Young Tzu', age: '19' } }
177
-
178
- it 'executes successfully' do
179
- expect(outcome.success?).to be true
180
- end
181
- end
182
-
183
- context 'when request is invalid' do
184
- let(:params) { { name: 'My Name' } }
185
-
186
- it 'does not execute successfully' do
187
- expect(outcome.failure?).to be true
188
- end
189
-
190
- it 'returns ActiveModel error object' do
191
- expect(outcome.result).to eq(age: ["can't be blank"])
192
- end
193
- end
194
- end
195
- end
196
-
197
- context '#run!' do
198
- context 'when command is invalid' do
199
- let(:outcome) { ControlledOutcome.run!(result: :invalid) }
200
-
201
- it 'raises Tzu::Invalid' do
202
- expect { outcome }.to raise_error Tzu::Invalid, 'Invalid Message'
203
- end
204
- end
205
-
206
- context 'when command fails' do
207
- let(:outcome) { ControlledOutcome.run!(result: :failure) }
208
-
209
- it 'raises Tzu::Failure' do
210
- expect { outcome }.to raise_error Tzu::Failure, 'Failure Message'
211
- end
212
- end
213
- end
214
- end
@@ -1,80 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Tzu::Validation do
4
-
5
- context 'params define valid? method' do
6
- subject do
7
- Class.new do
8
- include Tzu
9
- end
10
- end
11
-
12
- let(:errors) { [1, 2, 3] }
13
- let(:params) { spy(errors: errors, valid?: false) }
14
-
15
- it 'valid? method is called' do
16
- subject.run(params)
17
- expect(params).to have_received(:valid?)
18
- end
19
-
20
- it 'returns validation result' do
21
- result = subject.run(params)
22
- expect(result).to have_attributes(success: false, type: :validation, result: errors)
23
- end
24
- end
25
-
26
- context 'invoked directly' do
27
- context 'error message is string' do
28
- let(:str) { 'error_message' }
29
- subject { Tzu::Invalid.new(str) }
30
- it 'has string as #message' do
31
- expect(subject.message).to eq str
32
- end
33
-
34
- it '#errors converts sting to hash' do
35
- expect(subject.errors).to eq(errors: str)
36
- end
37
- end
38
- end
39
-
40
- context 'rescued' do
41
- subject do
42
- Class.new do
43
- include Tzu
44
-
45
- def call(params)
46
- raise StandardError.new(params[:message])
47
- rescue StandardError => e
48
- invalid! e
49
- end
50
- end
51
- end
52
-
53
- context 'error message is string' do
54
- let(:str) { 'error_message' }
55
- let(:params) { { message: str } }
56
-
57
- describe '#run' do
58
- it 'returns error hash as result' do
59
- outcome = subject.run(params)
60
- expect(outcome.result).to eq(errors: str)
61
- end
62
- end
63
-
64
- describe '#run!' do
65
- it 'has string as #message' do
66
- expect { subject.run!(params) }.to raise_error Tzu::Invalid, str
67
- end
68
-
69
- it 'has string as #errors' do
70
- begin
71
- subject.run!(params)
72
- expect(false).to be true # Should never reach this
73
- rescue Tzu::Invalid => e
74
- expect(e.errors).to eq(errors: str)
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end