Skip to content

Commit fd80d39

Browse files
committed
Add unit tests for Params extension
Adds comprehensive unit tests for the Params extension: - Tests for schema definition and inheritance - Tests for validate_params method - Tests for method wrapping with both #call and custom methods via operate_on - Tests for validation failures and short-circuiting - Updates spec_helper to load the Params extension
1 parent d451d03 commit fd80d39

File tree

2 files changed

+241
-0
lines changed

2 files changed

+241
-0
lines changed

spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
require "dry/operation"
99
require "dry/operation/extensions/active_record"
10+
require "dry/operation/extensions/params"
1011
require "dry/operation/extensions/rom"
1112
require "dry/operation/extensions/sequel"
1213

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe Dry::Operation::Extensions::Params do
6+
include Dry::Monads[:result]
7+
8+
describe ".params" do
9+
it "defines a schema for the operation using a block" do
10+
klass = Class.new(Dry::Operation) do
11+
include Dry::Operation::Extensions::Params
12+
13+
params do
14+
required(:name).filled(:string)
15+
end
16+
end
17+
18+
expect(klass._params_schema).to be_a(Dry::Schema::Params)
19+
end
20+
21+
it "accepts a schema class" do
22+
schema = Dry::Schema.Params do
23+
required(:name).filled(:string)
24+
end
25+
26+
klass = Class.new(Dry::Operation) do
27+
include Dry::Operation::Extensions::Params
28+
29+
params schema
30+
end
31+
32+
expect(klass._params_schema).to eq(schema)
33+
end
34+
35+
it "accepts a schema instance" do
36+
schema_class = Class.new(Dry::Schema::Params) do
37+
define do
38+
required(:name).filled(:string)
39+
end
40+
end
41+
42+
klass = Class.new(Dry::Operation) do
43+
include Dry::Operation::Extensions::Params
44+
45+
params schema_class
46+
end
47+
48+
expect(klass._params_schema).to be_a(schema_class)
49+
end
50+
51+
it "raises error when called without arguments or block" do
52+
expect {
53+
Class.new(Dry::Operation) do
54+
include Dry::Operation::Extensions::Params
55+
56+
params
57+
end
58+
}.to raise_error(ArgumentError, "params requires either a schema class or a block")
59+
end
60+
61+
it "allows schema to be inherited by subclasses" do
62+
parent = Class.new(Dry::Operation) do
63+
include Dry::Operation::Extensions::Params
64+
65+
params do
66+
required(:name).filled(:string)
67+
end
68+
end
69+
70+
child = Class.new(parent)
71+
72+
expect(child._params_schema).to eq(parent._params_schema)
73+
end
74+
75+
it "allows subclass to override parent schema" do
76+
parent = Class.new(Dry::Operation) do
77+
include Dry::Operation::Extensions::Params
78+
79+
params do
80+
required(:name).filled(:string)
81+
end
82+
end
83+
84+
child = Class.new(parent) do
85+
params do
86+
required(:email).filled(:string)
87+
end
88+
end
89+
90+
expect(child._params_schema).not_to eq(parent._params_schema)
91+
end
92+
end
93+
94+
describe "#validate_params" do
95+
it "returns Success with input when no schema is defined" do
96+
klass = Class.new(Dry::Operation) do
97+
include Dry::Operation::Extensions::Params
98+
end
99+
100+
instance = klass.new
101+
result = instance.validate_params(name: "John")
102+
103+
expect(result).to eq(Success(name: "John"))
104+
end
105+
106+
it "returns Success with validated params when validation passes" do
107+
klass = Class.new(Dry::Operation) do
108+
include Dry::Operation::Extensions::Params
109+
110+
params do
111+
required(:name).filled(:string)
112+
end
113+
end
114+
115+
instance = klass.new
116+
result = instance.validate_params(name: "John")
117+
118+
expect(result).to eq(Success(name: "John"))
119+
end
120+
121+
it "returns Failure with errors when validation fails" do
122+
klass = Class.new(Dry::Operation) do
123+
include Dry::Operation::Extensions::Params
124+
125+
params do
126+
required(:name).filled(:string)
127+
end
128+
end
129+
130+
instance = klass.new
131+
result = instance.validate_params(name: "")
132+
133+
expect(result).to be_a(Dry::Monads::Failure)
134+
expect(result.failure).to eq([:invalid_params, {name: ["must be filled"]}])
135+
end
136+
137+
it "coerces values according to schema" do
138+
klass = Class.new(Dry::Operation) do
139+
include Dry::Operation::Extensions::Params
140+
141+
params do
142+
required(:age).value(:integer)
143+
end
144+
end
145+
146+
instance = klass.new
147+
result = instance.validate_params(age: "25")
148+
149+
expect(result).to eq(Success(age: 25))
150+
end
151+
end
152+
153+
describe "method wrapping" do
154+
it "validates params before calling the method" do
155+
klass = Class.new(Dry::Operation) do
156+
include Dry::Operation::Extensions::Params
157+
158+
params do
159+
required(:name).filled(:string)
160+
end
161+
162+
def call(input)
163+
input
164+
end
165+
end
166+
167+
instance = klass.new
168+
result = instance.call(name: "John")
169+
170+
expect(result).to eq(Success(name: "John"))
171+
end
172+
173+
it "returns validation failure without executing method body" do
174+
executed = false
175+
176+
klass = Class.new(Dry::Operation) do
177+
include Dry::Operation::Extensions::Params
178+
179+
params do
180+
required(:name).filled(:string)
181+
end
182+
183+
define_method(:call) do |input|
184+
executed = true
185+
input
186+
end
187+
end
188+
189+
instance = klass.new
190+
result = instance.call(name: "")
191+
192+
expect(result).to be_a(Dry::Monads::Failure)
193+
expect(result.failure).to eq([:invalid_params, {name: ["must be filled"]}])
194+
expect(executed).to be(false)
195+
end
196+
197+
it "works with custom methods specified via operate_on" do
198+
klass = Class.new(Dry::Operation) do
199+
include Dry::Operation::Extensions::Params
200+
201+
operate_on :process
202+
203+
params do
204+
required(:name).filled(:string)
205+
end
206+
207+
def process(input)
208+
input
209+
end
210+
end
211+
212+
instance = klass.new
213+
result = instance.process(name: "John")
214+
215+
expect(result).to eq(Success(name: "John"))
216+
end
217+
218+
it "validates custom methods when params is defined before the method" do
219+
klass = Class.new(Dry::Operation) do
220+
include Dry::Operation::Extensions::Params
221+
222+
operate_on :process
223+
224+
params do
225+
required(:name).filled(:string)
226+
end
227+
228+
def process(input)
229+
input
230+
end
231+
end
232+
233+
instance = klass.new
234+
result = instance.process(name: "")
235+
236+
expect(result).to be_a(Dry::Monads::Failure)
237+
expect(result.failure).to eq([:invalid_params, {name: ["must be filled"]}])
238+
end
239+
end
240+
end

0 commit comments

Comments
 (0)