tzu 0.1.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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