trailblazer-macro 2.1.0.beta1
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 +7 -0
- data/.gitignore +18 -0
- data/.rubocop.yml +16 -0
- data/.rubocop_todo.yml +642 -0
- data/.travis.yml +15 -0
- data/CHANGES.md +3 -0
- data/COMM-LICENSE +91 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +9 -0
- data/README.md +5 -0
- data/Rakefile +13 -0
- data/lib/trailblazer/macro.rb +13 -0
- data/lib/trailblazer/macro/version.rb +5 -0
- data/lib/trailblazer/operation/guard.rb +18 -0
- data/lib/trailblazer/operation/input_output.rb +28 -0
- data/lib/trailblazer/operation/model.rb +52 -0
- data/lib/trailblazer/operation/nested.rb +90 -0
- data/lib/trailblazer/operation/policy.rb +44 -0
- data/lib/trailblazer/operation/pundit.rb +38 -0
- data/lib/trailblazer/operation/rescue.rb +42 -0
- data/lib/trailblazer/operation/wrap.rb +83 -0
- data/test/docs/guard_test.rb +162 -0
- data/test/docs/macro_test.rb +36 -0
- data/test/docs/model_test.rb +75 -0
- data/test/docs/nested_test.rb +113 -0
- data/test/docs/pundit_test.rb +133 -0
- data/test/docs/rescue_test.rb +126 -0
- data/test/docs/wrap_test.rb +274 -0
- data/test/lib/methods.rb +25 -0
- data/test/operation/model_test.rb +54 -0
- data/test/operation/nested_test.rb +293 -0
- data/test/operation/pundit_test.rb +106 -0
- data/test/test_helper.rb +39 -0
- data/trailblazer-macro.gemspec +36 -0
- metadata +243 -0
data/test/lib/methods.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Test
|
2
|
+
module Methods
|
3
|
+
def find_model(ctx, seq:, **)
|
4
|
+
seq << :find_model
|
5
|
+
end
|
6
|
+
|
7
|
+
def update(ctx, seq:, **)
|
8
|
+
seq << :update
|
9
|
+
end
|
10
|
+
|
11
|
+
def notify(ctx, seq:, **)
|
12
|
+
seq << :notify
|
13
|
+
end
|
14
|
+
|
15
|
+
def rehash(ctx, seq:, rehash_raise:false, **)
|
16
|
+
seq << :rehash
|
17
|
+
raise if rehash_raise
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_error(ctx, seq:, **)
|
22
|
+
seq << :log_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ModelTest < Minitest::Spec
|
4
|
+
Song = Struct.new(:id) do
|
5
|
+
def self.find(id); new(id) end
|
6
|
+
def self.find_by(id:nil); id.nil? ? nil : new(id) end
|
7
|
+
end
|
8
|
+
|
9
|
+
#---
|
10
|
+
# use Model semantics, no customizations.
|
11
|
+
class Create < Trailblazer::Operation
|
12
|
+
step Model( Song, :new )
|
13
|
+
end
|
14
|
+
|
15
|
+
# :new new.
|
16
|
+
it { Create.(params: {})[:model].inspect.must_equal %{#<struct ModelTest::Song id=nil>} }
|
17
|
+
|
18
|
+
class Update < Create
|
19
|
+
step Model( Song, :find ), override: true
|
20
|
+
end
|
21
|
+
|
22
|
+
#---
|
23
|
+
#- inheritance
|
24
|
+
|
25
|
+
# :find it
|
26
|
+
it { Update.(params: { id: 1 })[:model].inspect.must_equal %{#<struct ModelTest::Song id=1>} }
|
27
|
+
|
28
|
+
# inherited inspect is ok
|
29
|
+
it { Trailblazer::Operation::Inspect.(Update).must_equal %{[>model.build]} }
|
30
|
+
|
31
|
+
#---
|
32
|
+
# :find_by, exceptionless.
|
33
|
+
class Find < Trailblazer::Operation
|
34
|
+
step Model Song, :find_by
|
35
|
+
step :process
|
36
|
+
|
37
|
+
def process(options, **); options["x"] = true end
|
38
|
+
end
|
39
|
+
|
40
|
+
# can't find model.
|
41
|
+
#- result object, model
|
42
|
+
it do
|
43
|
+
Find.(params: {id: nil})["result.model"].failure?.must_equal true
|
44
|
+
Find.(params: {id: nil})["x"].must_be_nil
|
45
|
+
Find.(params: {id: nil}).failure?.must_equal true
|
46
|
+
end
|
47
|
+
|
48
|
+
#- result object, model
|
49
|
+
it do
|
50
|
+
Find.(params: {id: 9})["result.model"].success?.must_equal true
|
51
|
+
Find.(params: {id: 9})["x"].must_equal true
|
52
|
+
Find.(params: {id: 9})[:model].inspect.must_equal %{#<struct ModelTest::Song id=9>}
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
# exec_context nach Nested
|
4
|
+
|
5
|
+
class NestedTest < Minitest::Spec
|
6
|
+
#---
|
7
|
+
#- shared data
|
8
|
+
class B < Trailblazer::Operation
|
9
|
+
pass ->(options, **) { options["can.B.see.A.mutable.data?"] = options["mutable.data.from.A"] }
|
10
|
+
pass ->(options, **) { options["can.B.see.current_user?"] = options["current_user"] }
|
11
|
+
pass ->(options, **) { options["can.B.see.params?"] = options["params"] }
|
12
|
+
pass ->(options, **) { options["can.B.see.A.class.data?"] = options["A.class.data"] }
|
13
|
+
pass ->(options, **) { options["can.B.see.container.data?"] = options["some.container.data"] }
|
14
|
+
pass ->(options, **) { options["mutable.data.from.B"] = "from B!" }
|
15
|
+
end
|
16
|
+
|
17
|
+
class A < Trailblazer::Operation
|
18
|
+
extend ClassDependencies
|
19
|
+
self["A.class.data"] = "yes" # class data on A
|
20
|
+
|
21
|
+
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
22
|
+
step Nested( B )
|
23
|
+
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
24
|
+
end
|
25
|
+
|
26
|
+
#---
|
27
|
+
#- default behavior: share everything.
|
28
|
+
# no containers
|
29
|
+
# no runtime data
|
30
|
+
# no params
|
31
|
+
it do
|
32
|
+
result = A.("params" => {})
|
33
|
+
# everything from A visible
|
34
|
+
result["A.class.data"]. must_equal "yes"
|
35
|
+
result["mutable.data.from.A"].must_equal "from A!"
|
36
|
+
|
37
|
+
# B can see everything
|
38
|
+
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
39
|
+
result["can.B.see.current_user?"].must_be_nil
|
40
|
+
result["can.B.see.params?"].must_equal({})
|
41
|
+
result["can.B.see.A.class.data?"].must_equal "yes"
|
42
|
+
result["can.B.see.container.data?"].must_be_nil
|
43
|
+
|
44
|
+
result["can.A.see.B.mutable.data?"].must_equal "from B!"
|
45
|
+
end
|
46
|
+
|
47
|
+
#---
|
48
|
+
#- Nested::NonActivity
|
49
|
+
class AlmostB < Trailblazer::Operation
|
50
|
+
step ->(options, is_successful:raise, **) { is_successful } # {AlmostB} fails if {is_successful} isn't true.
|
51
|
+
step ->(options, **) { options["can.B.see.A.mutable.data?"] = options["mutable.data.from.A"] }
|
52
|
+
pass ->(options, **) { options["mutable.data.from.B"] = "from AlmostB!" }
|
53
|
+
end
|
54
|
+
|
55
|
+
#- Nested( ->{} )
|
56
|
+
class SomeNestedWithProc < Trailblazer::Operation
|
57
|
+
extend ClassDependencies
|
58
|
+
self["A.class.data"] = "yes" # class data on A
|
59
|
+
|
60
|
+
Decider = ->(options, use_class:raise, **) { use_class }
|
61
|
+
|
62
|
+
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
63
|
+
step Nested( Decider )
|
64
|
+
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
65
|
+
end
|
66
|
+
|
67
|
+
#- Nested( Callable )
|
68
|
+
class SomeNestedWithCallable < Trailblazer::Operation
|
69
|
+
extend ClassDependencies
|
70
|
+
self["A.class.data"] = "yes" # class data on A
|
71
|
+
|
72
|
+
class Decider
|
73
|
+
def self.call(options, use_class:raise, **)
|
74
|
+
use_class
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
79
|
+
step Nested( Decider )
|
80
|
+
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
81
|
+
end
|
82
|
+
|
83
|
+
#- Nested( :method )
|
84
|
+
class SomeNestedWithMethod < Trailblazer::Operation
|
85
|
+
extend ClassDependencies
|
86
|
+
self["A.class.data"] = "yes" # class data on A
|
87
|
+
|
88
|
+
def decider(options, use_class:raise, **)
|
89
|
+
use_class
|
90
|
+
end
|
91
|
+
|
92
|
+
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
93
|
+
step Nested( :decider )
|
94
|
+
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
#- test callable
|
99
|
+
# B with Callable, successful
|
100
|
+
it do
|
101
|
+
result = SomeNestedWithCallable.("params" => {}, use_class: B)
|
102
|
+
assert_b(result, is_successful: "whatever")
|
103
|
+
end
|
104
|
+
|
105
|
+
# AlmostB with Callable, successful
|
106
|
+
it do
|
107
|
+
result = SomeNestedWithCallable.("params" => {}, use_class: AlmostB, is_successful: true)
|
108
|
+
assert_almost_b(result, is_successful: true)
|
109
|
+
end
|
110
|
+
|
111
|
+
# AlmostB with Callable, failure
|
112
|
+
it do
|
113
|
+
result = SomeNestedWithCallable.("params" => {}, use_class: AlmostB, is_successful: false)
|
114
|
+
assert_almost_b(result, is_successful: false)
|
115
|
+
end
|
116
|
+
|
117
|
+
#- test proc
|
118
|
+
# B with proc, successful
|
119
|
+
it do
|
120
|
+
result = SomeNestedWithProc.("params" => {}, use_class: B)
|
121
|
+
assert_b(result, is_successful: "whatever")
|
122
|
+
end
|
123
|
+
|
124
|
+
# AlmostB with proc, successful
|
125
|
+
it do
|
126
|
+
result = SomeNestedWithProc.("params" => {}, use_class: AlmostB, is_successful: true)
|
127
|
+
|
128
|
+
assert_almost_b(result, is_successful: true)
|
129
|
+
end
|
130
|
+
|
131
|
+
# AlmostB with proc, failure.
|
132
|
+
it do
|
133
|
+
result = SomeNestedWithProc.("params" => {}, use_class: AlmostB, is_successful: false)
|
134
|
+
|
135
|
+
assert_almost_b(result, is_successful: false)
|
136
|
+
end
|
137
|
+
|
138
|
+
#- test :method
|
139
|
+
# B with method, successful
|
140
|
+
it do
|
141
|
+
result = SomeNestedWithMethod.("params" => {}, use_class: B)
|
142
|
+
assert_b(result, is_successful: "whatever")
|
143
|
+
end
|
144
|
+
|
145
|
+
# AlmostB with method, successful
|
146
|
+
it do
|
147
|
+
result = SomeNestedWithMethod.("params" => {}, use_class: AlmostB, is_successful: true)
|
148
|
+
|
149
|
+
assert_almost_b(result, is_successful: true)
|
150
|
+
end
|
151
|
+
|
152
|
+
# AlmostB with method, failure.
|
153
|
+
it do
|
154
|
+
result = SomeNestedWithMethod.("params" => {}, use_class: AlmostB, is_successful: false)
|
155
|
+
|
156
|
+
assert_almost_b(result, is_successful: false)
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def assert_almost_b(result, is_successful:raise)
|
161
|
+
result.success?.must_equal is_successful # AlmostB was successful, so A is successful.
|
162
|
+
|
163
|
+
# everything from A visible
|
164
|
+
result["A.class.data"]. must_equal "yes"
|
165
|
+
result["mutable.data.from.A"].must_equal "from A!"
|
166
|
+
|
167
|
+
# AlmostB doesn't look for everything
|
168
|
+
result["can.B.see.current_user?"].must_be_nil
|
169
|
+
result["can.B.see.params?"].must_be_nil
|
170
|
+
if is_successful
|
171
|
+
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
172
|
+
result["can.B.see.A.class.data?"].must_be_nil # we don't look for it.
|
173
|
+
result["can.A.see.B.mutable.data?"].must_equal "from AlmostB!"
|
174
|
+
else
|
175
|
+
result["can.B.see.A.mutable.data?"].must_be_nil
|
176
|
+
result["can.B.see.A.class.data?"].must_be_nil
|
177
|
+
result["can.A.see.B.mutable.data?"].must_be_nil
|
178
|
+
end
|
179
|
+
result["can.B.see.container.data?"].must_be_nil
|
180
|
+
|
181
|
+
|
182
|
+
# result[:is_successful].must_equal is_successful # FIXME: this is wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! key is symbol
|
183
|
+
end
|
184
|
+
|
185
|
+
def assert_b(result, is_successful:raise)
|
186
|
+
# everything from A visible
|
187
|
+
result["A.class.data"]. must_equal "yes"
|
188
|
+
result["mutable.data.from.A"].must_equal "from A!"
|
189
|
+
|
190
|
+
# B can see everything
|
191
|
+
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
192
|
+
result["can.B.see.current_user?"].must_be_nil
|
193
|
+
result["can.B.see.params?"].must_equal({})
|
194
|
+
result["can.B.see.A.class.data?"].must_equal "yes"
|
195
|
+
result["can.B.see.container.data?"].must_be_nil
|
196
|
+
|
197
|
+
result["can.A.see.B.mutable.data?"].must_equal "from B!"
|
198
|
+
|
199
|
+
result[:is_successful].must_be_nil
|
200
|
+
result.success?.must_equal true # B was successful, so A is successful.
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
#---
|
205
|
+
#- :exec_context
|
206
|
+
class Create < Trailblazer::Operation
|
207
|
+
class Edit < Trailblazer::Operation
|
208
|
+
step :c!
|
209
|
+
|
210
|
+
def c!(options, **); options[:c] = 1 end
|
211
|
+
end
|
212
|
+
|
213
|
+
step :a!
|
214
|
+
step Nested( Edit )
|
215
|
+
step :b!
|
216
|
+
|
217
|
+
def a!(options, **); options[:a] = 2 end
|
218
|
+
def b!(options, **); options[:b] = 3 end
|
219
|
+
end
|
220
|
+
|
221
|
+
it { Create.().inspect(:a, :b, :c).must_equal %{<Result:true [2, 3, 1] >} }
|
222
|
+
end
|
223
|
+
|
224
|
+
class NestedWithFastTrackTest < Minitest::Spec
|
225
|
+
module Steps
|
226
|
+
def b(options, a:, **)
|
227
|
+
options["b"] = a+1
|
228
|
+
end
|
229
|
+
|
230
|
+
def f(options, **)
|
231
|
+
options["f"] = 3
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class Edit < Trailblazer::Operation
|
236
|
+
pass :a, pass_fast: true
|
237
|
+
|
238
|
+
def a(options, **)
|
239
|
+
options["a"] = 1
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class Update < Trailblazer::Operation
|
244
|
+
step Nested( Edit )
|
245
|
+
step :b
|
246
|
+
fail :f
|
247
|
+
|
248
|
+
include Steps
|
249
|
+
end
|
250
|
+
|
251
|
+
# from Nested straight to End.pass_fast.
|
252
|
+
it { Update.({}).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
|
253
|
+
|
254
|
+
#- Nested, pass_fast: true
|
255
|
+
class Upsert < Trailblazer::Operation
|
256
|
+
step Nested( Edit ), pass_fast: true # this option is unnecessary.
|
257
|
+
step :b
|
258
|
+
fail :f
|
259
|
+
|
260
|
+
include Steps
|
261
|
+
end
|
262
|
+
|
263
|
+
# from Nested straight to End.pass_fast.
|
264
|
+
it { Upsert.({}).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
|
265
|
+
|
266
|
+
#- mapping
|
267
|
+
#- Nested, :pass_fast => :failure
|
268
|
+
it "attaches :pass_fast => :failure" do
|
269
|
+
op = Class.new(Trailblazer::Operation) do
|
270
|
+
step Nested( Edit ), Output(:pass_fast) => Track(:failure)
|
271
|
+
step :b
|
272
|
+
fail :f
|
273
|
+
|
274
|
+
include Steps
|
275
|
+
end
|
276
|
+
|
277
|
+
# from Nested to :failure track.
|
278
|
+
op.({}).inspect("a", "b", "c", "f").must_equal %{<Result:false [1, nil, nil, 3] >}
|
279
|
+
end
|
280
|
+
|
281
|
+
it "goes straigt to End.failure" do
|
282
|
+
op = Class.new(Trailblazer::Operation) do
|
283
|
+
step Nested( Edit ), Output(:pass_fast) => "End.failure"
|
284
|
+
step :b
|
285
|
+
fail :f
|
286
|
+
|
287
|
+
include Steps
|
288
|
+
end
|
289
|
+
|
290
|
+
# from Nested straight to End.failure, no fail step will be visited.
|
291
|
+
op.({}).inspect("a", "b", "c", "f").must_equal %{<Result:false [1, nil, nil, nil] >}
|
292
|
+
end
|
293
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "trailblazer/operation/policy"
|
3
|
+
|
4
|
+
class PolicyTest < Minitest::Spec
|
5
|
+
Song = Struct.new(:id) do
|
6
|
+
def self.find(id); new(id) end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Auth
|
10
|
+
def initialize(user, model); @user, @model = user, model end
|
11
|
+
def only_user?; @user == Module && @model.nil? end
|
12
|
+
def user_object?; @user == Object end
|
13
|
+
def user_and_model?; @user == Module && @model.class == Song end
|
14
|
+
def inspect; "<Auth: user:#{@user.inspect}, model:#{@model.inspect}>" end
|
15
|
+
end
|
16
|
+
|
17
|
+
#---
|
18
|
+
# Instance-level: Only policy, no model
|
19
|
+
class Create < Trailblazer::Operation
|
20
|
+
step Policy::Pundit( Auth, :only_user? )
|
21
|
+
step :process
|
22
|
+
|
23
|
+
def process(options, **)
|
24
|
+
options["process"] = true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# successful.
|
29
|
+
it do
|
30
|
+
result = Create.(params: {}, current_user: Module)
|
31
|
+
result["process"].must_equal true
|
32
|
+
#- result object, policy
|
33
|
+
result["result.policy.default"].success?.must_equal true
|
34
|
+
result["result.policy.default"]["message"].must_be_nil
|
35
|
+
# result[:valid].must_be_nil
|
36
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:nil>}
|
37
|
+
end
|
38
|
+
# breach.
|
39
|
+
it do
|
40
|
+
result = Create.(params: {}, current_user: nil)
|
41
|
+
result["process"].must_be_nil
|
42
|
+
#- result object, policy
|
43
|
+
result["result.policy.default"].success?.must_equal false
|
44
|
+
result["result.policy.default"]["message"].must_equal "Breach"
|
45
|
+
end
|
46
|
+
# inject different policy.Condition it { Create.(params: {}, current_user: Object, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_equal true }
|
47
|
+
it { Create.(params: {}, current_user: Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_be_nil }
|
48
|
+
|
49
|
+
|
50
|
+
#---
|
51
|
+
# inheritance, adding Model
|
52
|
+
class Show < Create
|
53
|
+
step Model( Song, :new ), before: "policy.default.eval"
|
54
|
+
end
|
55
|
+
|
56
|
+
it { Trailblazer::Operation::Inspect.(Show).must_equal %{[>model.build,>policy.default.eval,>process]} }
|
57
|
+
|
58
|
+
# invalid because user AND model.
|
59
|
+
it do
|
60
|
+
result = Show.(params: {}, current_user: Module)
|
61
|
+
result["process"].must_be_nil
|
62
|
+
result[:model].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
63
|
+
# result["policy"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
64
|
+
end
|
65
|
+
|
66
|
+
# valid because new policy.
|
67
|
+
it do
|
68
|
+
# puts Show["pipetree"].inspect
|
69
|
+
result = Show.(params: {}, current_user: Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_and_model?))
|
70
|
+
result["process"].must_equal true
|
71
|
+
result[:model].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
72
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=nil>>}
|
73
|
+
end
|
74
|
+
|
75
|
+
##--
|
76
|
+
# TOOOODOOO: Policy and Model before Build ("External" or almost Resolver)
|
77
|
+
class Edit < Trailblazer::Operation
|
78
|
+
step Model Song, :find
|
79
|
+
step Policy::Pundit( Auth, :user_and_model? )
|
80
|
+
step :process
|
81
|
+
|
82
|
+
def process(options, **)
|
83
|
+
options["process"] = true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# successful.
|
88
|
+
it do
|
89
|
+
result = Edit.(params: { id: 1 }, current_user: Module)
|
90
|
+
result["process"].must_equal true
|
91
|
+
result[:model].inspect.must_equal %{#<struct PolicyTest::Song id=1>}
|
92
|
+
result["result.policy.default"].success?.must_equal true
|
93
|
+
result["result.policy.default"]["message"].must_be_nil
|
94
|
+
# result[:valid].must_be_nil
|
95
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=1>>}
|
96
|
+
end
|
97
|
+
|
98
|
+
# breach.
|
99
|
+
it do
|
100
|
+
result = Edit.(params: { id: 4 }, current_user: nil)
|
101
|
+
result[:model].inspect.must_equal %{#<struct PolicyTest::Song id=4>}
|
102
|
+
result["process"].must_be_nil
|
103
|
+
result["result.policy.default"].success?.must_equal false
|
104
|
+
result["result.policy.default"]["message"].must_equal "Breach"
|
105
|
+
end
|
106
|
+
end
|