1+ # frozen_string_literal: true
2+
3+ require_relative "../../../spec_helper"
4+
5+ describe Hooks ::Handlers ::Base do
6+ describe "#call" do
7+ let ( :handler ) { described_class . new }
8+ let ( :payload ) { { "data" => "test" } }
9+ let ( :headers ) { { "Content-Type" => "application/json" } }
10+ let ( :config ) { { "endpoint" => "/test" } }
11+
12+ it "raises NotImplementedError by default" do
13+ expect {
14+ handler . call ( payload : payload , headers : headers , config : config )
15+ } . to raise_error ( NotImplementedError , "Handler must implement #call method" )
16+ end
17+
18+ it "can be subclassed and overridden" do
19+ test_handler_class = Class . new ( described_class ) do
20+ def call ( payload :, headers :, config :)
21+ {
22+ received_payload : payload ,
23+ received_headers : headers ,
24+ received_config : config ,
25+ status : "success"
26+ }
27+ end
28+ end
29+
30+ handler = test_handler_class . new
31+ result = handler . call ( payload : payload , headers : headers , config : config )
32+
33+ expect ( result ) . to eq ( {
34+ received_payload : payload ,
35+ received_headers : headers ,
36+ received_config : config ,
37+ status : "success"
38+ } )
39+ end
40+
41+ it "accepts different payload types" do
42+ test_handler_class = Class . new ( described_class ) do
43+ def call ( payload :, headers :, config :)
44+ { payload_class : payload . class . name }
45+ end
46+ end
47+
48+ handler = test_handler_class . new
49+
50+ # Test with hash
51+ result = handler . call ( payload : { "test" => "data" } , headers : headers , config : config )
52+ expect ( result [ :payload_class ] ) . to eq ( "Hash" )
53+
54+ # Test with string
55+ result = handler . call ( payload : "raw string" , headers : headers , config : config )
56+ expect ( result [ :payload_class ] ) . to eq ( "String" )
57+
58+ # Test with nil
59+ result = handler . call ( payload : nil , headers : headers , config : config )
60+ expect ( result [ :payload_class ] ) . to eq ( "NilClass" )
61+ end
62+
63+ it "accepts different header types" do
64+ test_handler_class = Class . new ( described_class ) do
65+ def call ( payload :, headers :, config :)
66+ { headers_received : headers }
67+ end
68+ end
69+
70+ handler = test_handler_class . new
71+
72+ # Test with hash
73+ headers_hash = { "User-Agent" => "test" , "X-Custom" => "value" }
74+ result = handler . call ( payload : payload , headers : headers_hash , config : config )
75+ expect ( result [ :headers_received ] ) . to eq ( headers_hash )
76+
77+ # Test with empty hash
78+ result = handler . call ( payload : payload , headers : { } , config : config )
79+ expect ( result [ :headers_received ] ) . to eq ( { } )
80+
81+ # Test with nil
82+ result = handler . call ( payload : payload , headers : nil , config : config )
83+ expect ( result [ :headers_received ] ) . to be_nil
84+ end
85+
86+ it "accepts different config types" do
87+ test_handler_class = Class . new ( described_class ) do
88+ def call ( payload :, headers :, config :)
89+ { config_received : config }
90+ end
91+ end
92+
93+ handler = test_handler_class . new
94+
95+ # Test with complex config
96+ complex_config = {
97+ "endpoint" => "/test" ,
98+ "opts" => { "timeout" => 30 } ,
99+ "handler" => "TestHandler"
100+ }
101+ result = handler . call ( payload : payload , headers : headers , config : complex_config )
102+ expect ( result [ :config_received ] ) . to eq ( complex_config )
103+
104+ # Test with empty config
105+ result = handler . call ( payload : payload , headers : headers , config : { } )
106+ expect ( result [ :config_received ] ) . to eq ( { } )
107+ end
108+
109+ it "requires all keyword arguments" do
110+ expect {
111+ handler . call ( payload : payload , headers : headers )
112+ } . to raise_error ( ArgumentError , /missing keyword.*config/ )
113+
114+ expect {
115+ handler . call ( payload : payload , config : config )
116+ } . to raise_error ( ArgumentError , /missing keyword.*headers/ )
117+
118+ expect {
119+ handler . call ( headers : headers , config : config )
120+ } . to raise_error ( ArgumentError , /missing keyword.*payload/ )
121+ end
122+ end
123+
124+ describe "inheritance" do
125+ it "can be inherited" do
126+ child_class = Class . new ( described_class )
127+ expect ( child_class . ancestors ) . to include ( described_class )
128+ end
129+
130+ it "maintains method signature in subclasses" do
131+ child_class = Class . new ( described_class ) do
132+ def call ( payload :, headers :, config :)
133+ "child implementation"
134+ end
135+ end
136+
137+ handler = child_class . new
138+ result = handler . call (
139+ payload : { "test" => "data" } ,
140+ headers : { "Content-Type" => "application/json" } ,
141+ config : { "endpoint" => "/test" }
142+ )
143+
144+ expect ( result ) . to eq ( "child implementation" )
145+ end
146+ end
147+
148+ describe "documentation compliance" do
149+ it "has the expected public interface" do
150+ expect ( described_class . instance_methods ( false ) ) . to include ( :call )
151+ end
152+
153+ it "call method accepts the documented parameters" do
154+ method = described_class . instance_method ( :call )
155+ expect ( method . parameters ) . to include ( [ :keyreq , :payload ] )
156+ expect ( method . parameters ) . to include ( [ :keyreq , :headers ] )
157+ expect ( method . parameters ) . to include ( [ :keyreq , :config ] )
158+ end
159+ end
160+ end
0 commit comments