11# frozen_string_literal: true
22
33require 'spec_helper'
4+ require 'rack'
45require_relative '../../../../app'
56
67RSpec . describe Html2rss ::Web ::Feeds ::Responder do
78 let ( :response ) { Rack ::Response . new }
8- let ( :request ) { instance_double ( Struct . new ( :response ) , response : response ) }
9-
10- def feed_request ( representation )
11- Html2rss ::Web ::Feeds ::Contracts ::Request . new (
12- target_kind : :token ,
13- representation : representation ,
14- feed_name : nil ,
15- token : 'token' ,
16- params : { }
9+ let ( :result ) do
10+ Html2rss ::Web ::Feeds ::Contracts ::RenderResult . new (
11+ status : :ok ,
12+ payload : nil ,
13+ message : nil ,
14+ ttl_seconds : 600 ,
15+ cache_key : 'feed_result:test' ,
16+ error_message : nil
1717 )
1818 end
19+ let ( :static_config ) do
20+ {
21+ channel : { url : 'https://example.com' , ttl : 10 } ,
22+ strategy : :faraday
23+ }
24+ end
1925
20- def resolved_source
21- Html2rss ::Web ::Feeds ::Contracts ::ResolvedSource . new (
22- source_kind : :token ,
23- cache_identity : 'token:abc' ,
24- generator_input : { strategy : :faraday , channel : { url : 'https://example.com' } } ,
25- ttl_seconds : 600
26- )
26+ before do
27+ allow ( Html2rss ::Web ::LocalConfig ) . to receive ( :find ) . with ( 'example' ) . and_return ( static_config )
28+ allow ( Html2rss ::Web ::Observability ) . to receive ( :emit )
2729 end
2830
2931 context 'with a cacheable success result' do
3032 subject ( :write_response ) do
3133 described_class . call (
32- request : request ,
33- target_kind : :token ,
34- identifier : 'token'
35- )
36- end
37-
38- let ( :representation ) { Html2rss ::Web ::FeedResponseFormat ::RSS }
39-
40- let ( :result ) do
41- Html2rss ::Web ::Feeds ::Contracts ::RenderResult . new (
42- status : :ok ,
43- payload : nil ,
44- message : nil ,
45- ttl_seconds : 600 ,
46- cache_key : 'feed_result:test' ,
47- error_message : nil
34+ request : request_for ( path : '/example' , accept : 'application/xml' ) ,
35+ target_kind : :static ,
36+ identifier : 'example'
4837 )
4938 end
5039
5140 before do
52- allow ( Html2rss ::Web ::Feeds ::Request ) . to receive ( :call ) . and_return ( feed_request ( representation ) )
53- allow ( Html2rss ::Web ::Feeds ::SourceResolver ) . to receive ( :call ) . and_return ( resolved_source )
5441 allow ( Html2rss ::Web ::Feeds ::Service ) . to receive ( :call ) . and_return ( result )
55- allow ( Html2rss ::Web ::Observability ) . to receive ( :emit )
5642 allow ( Html2rss ::Web ::Feeds ::RssRenderer ) . to receive ( :call ) . with ( result ) . and_return ( '<rss/>' )
5743 end
5844
5945 it 'writes the expected response tuple' do
6046 expect ( response_tuple ( write_response ) ) . to eq ( [ 200 , 'application/xml' , '<rss/>' ] )
6147 end
6248
63- it 'marks the response as cacheable ' , :aggregate_failures do
49+ it 'resolves the source through the real request and source resolver path ' , :aggregate_failures do
6450 write_response
6551
52+ expect ( Html2rss ::Web ::Feeds ::Service ) . to have_received ( :call ) . with (
53+ have_attributes (
54+ source_kind : :static ,
55+ cache_identity : a_string_starting_with ( 'static:example:' ) ,
56+ generator_input : include ( strategy : :faraday , channel : { url : 'https://example.com' , ttl : 10 } ) ,
57+ ttl_seconds : 600
58+ )
59+ )
6660 expect ( response [ 'Cache-Control' ] ) . to include ( 'max-age=600' )
6761 expect ( response [ 'Cache-Control' ] ) . to include ( 'public' )
6862 expect ( response [ 'Vary' ] ) . to eq ( 'Accept' )
@@ -74,7 +68,7 @@ def resolved_source
7468 expect ( Html2rss ::Web ::Observability ) . to have_received ( :emit ) . with (
7569 event_name : 'feed.render' ,
7670 outcome : 'success' ,
77- details : include ( strategy : :faraday , url : 'https://example.com' ) ,
71+ details : include ( strategy : :faraday , url : 'https://example.com' , feed_name : 'example' ) ,
7872 level : :info
7973 )
8074 end
@@ -83,14 +77,12 @@ def resolved_source
8377 context 'with an error result' do
8478 subject ( :write_response ) do
8579 described_class . call (
86- request : request ,
87- target_kind : :token ,
88- identifier : 'token '
80+ request : request_for ( path : '/example.json' , accept : 'application/feed+json' ) ,
81+ target_kind : :static ,
82+ identifier : 'example.json '
8983 )
9084 end
9185
92- let ( :representation ) { Html2rss ::Web ::FeedResponseFormat ::JSON_FEED }
93-
9486 let ( :result ) do
9587 Html2rss ::Web ::Feeds ::Contracts ::RenderResult . new (
9688 status : :error ,
@@ -103,10 +95,7 @@ def resolved_source
10395 end
10496
10597 before do
106- allow ( Html2rss ::Web ::Feeds ::Request ) . to receive ( :call ) . and_return ( feed_request ( representation ) )
107- allow ( Html2rss ::Web ::Feeds ::SourceResolver ) . to receive ( :call ) . and_return ( resolved_source )
10898 allow ( Html2rss ::Web ::Feeds ::Service ) . to receive ( :call ) . and_return ( result )
109- allow ( Html2rss ::Web ::Observability ) . to receive ( :emit )
11099 allow ( Html2rss ::Web ::Feeds ::JsonRenderer ) . to receive ( :call ) . with ( result ) . and_return ( '{"title":"Error"}' )
111100 end
112101
@@ -125,30 +114,14 @@ def resolved_source
125114 context 'when response rendering fails after feed generation succeeds' do
126115 subject ( :write_response ) do
127116 described_class . call (
128- request : request ,
129- target_kind : :token ,
130- identifier : 'token'
131- )
132- end
133-
134- let ( :representation ) { Html2rss ::Web ::FeedResponseFormat ::RSS }
135-
136- let ( :result ) do
137- Html2rss ::Web ::Feeds ::Contracts ::RenderResult . new (
138- status : :ok ,
139- payload : nil ,
140- message : nil ,
141- ttl_seconds : 600 ,
142- cache_key : 'feed_result:test' ,
143- error_message : nil
117+ request : request_for ( path : '/example' , accept : 'application/xml' ) ,
118+ target_kind : :static ,
119+ identifier : 'example'
144120 )
145121 end
146122
147123 before do
148- allow ( Html2rss ::Web ::Feeds ::Request ) . to receive ( :call ) . and_return ( feed_request ( representation ) )
149- allow ( Html2rss ::Web ::Feeds ::SourceResolver ) . to receive ( :call ) . and_return ( resolved_source )
150124 allow ( Html2rss ::Web ::Feeds ::Service ) . to receive ( :call ) . and_return ( result )
151- allow ( Html2rss ::Web ::Observability ) . to receive ( :emit )
152125 allow ( Html2rss ::Web ::Feeds ::RssRenderer ) . to receive ( :call ) . and_raise ( StandardError , 'render failed' )
153126 end
154127
@@ -158,14 +131,27 @@ def resolved_source
158131 expect ( Html2rss ::Web ::Observability ) . to have_received ( :emit ) . once . with (
159132 event_name : 'feed.render' ,
160133 outcome : 'failure' ,
161- details : include ( error_class : 'StandardError' , error_message : 'render failed' ) ,
134+ details : include ( error_class : 'StandardError' , error_message : 'render failed' , feed_name : 'example' ) ,
162135 level : :warn
163136 )
164137 end
165138 end
166139
167140 private
168141
142+ # @param path [String]
143+ # @param accept [String]
144+ # @return [Rack::Request]
145+ def request_for ( path :, accept :)
146+ rack_response = response
147+
148+ Rack ::Request . new (
149+ Rack ::MockRequest . env_for ( path , 'HTTP_ACCEPT' => accept )
150+ ) . tap do |request |
151+ request . define_singleton_method ( :response ) { rack_response }
152+ end
153+ end
154+
169155 # @param body [String]
170156 # @return [Array<(Integer, String, String)>]
171157 def response_tuple ( body )
0 commit comments