wayfarer 0.4.6 → 0.4.8

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.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/.env +17 -0
  3. data/.github/workflows/lint.yaml +27 -0
  4. data/.github/workflows/release.yaml +30 -0
  5. data/.github/workflows/tests.yaml +21 -0
  6. data/.gitignore +5 -1
  7. data/.rubocop.yml +36 -0
  8. data/.vale.ini +8 -0
  9. data/.yardopts +1 -3
  10. data/Dockerfile +6 -4
  11. data/Gemfile +24 -0
  12. data/Gemfile.lock +274 -164
  13. data/Rakefile +7 -51
  14. data/bin/wayfarer +1 -1
  15. data/docker-compose.yml +23 -13
  16. data/docs/cookbook/consent_screen.md +2 -2
  17. data/docs/cookbook/executing_javascript.md +3 -3
  18. data/docs/cookbook/navigation.md +12 -12
  19. data/docs/cookbook/querying_html.md +3 -3
  20. data/docs/cookbook/screenshots.md +2 -2
  21. data/docs/guides/callbacks.md +25 -125
  22. data/docs/guides/cli.md +71 -0
  23. data/docs/guides/configuration.md +10 -35
  24. data/docs/guides/development.md +67 -0
  25. data/docs/guides/handlers.md +60 -0
  26. data/docs/guides/index.md +1 -0
  27. data/docs/guides/jobs.md +142 -31
  28. data/docs/guides/navigation.md +1 -1
  29. data/docs/guides/networking/capybara.md +13 -22
  30. data/docs/guides/networking/custom_adapters.md +103 -41
  31. data/docs/guides/networking/ferrum.md +4 -4
  32. data/docs/guides/networking/http.md +9 -13
  33. data/docs/guides/networking/selenium.md +10 -11
  34. data/docs/guides/pages.md +78 -10
  35. data/docs/guides/redis.md +10 -0
  36. data/docs/guides/routing.md +156 -0
  37. data/docs/guides/tasks.md +53 -9
  38. data/docs/guides/tutorial.md +66 -0
  39. data/docs/guides/user_agents.md +115 -0
  40. data/docs/index.md +17 -40
  41. data/lib/wayfarer/base.rb +125 -46
  42. data/lib/wayfarer/batch_completion.rb +60 -0
  43. data/lib/wayfarer/callbacks.rb +22 -48
  44. data/lib/wayfarer/cli/route_printer.rb +85 -89
  45. data/lib/wayfarer/cli.rb +103 -0
  46. data/lib/wayfarer/gc.rb +18 -6
  47. data/lib/wayfarer/handler.rb +15 -7
  48. data/lib/wayfarer/kv.rb +28 -0
  49. data/lib/wayfarer/logging.rb +38 -0
  50. data/lib/wayfarer/middleware/base.rb +2 -0
  51. data/lib/wayfarer/middleware/batch_completion.rb +19 -0
  52. data/lib/wayfarer/middleware/chain.rb +7 -1
  53. data/lib/wayfarer/middleware/content_type.rb +59 -0
  54. data/lib/wayfarer/middleware/controller.rb +19 -15
  55. data/lib/wayfarer/middleware/dedup.rb +22 -13
  56. data/lib/wayfarer/middleware/dispatch.rb +17 -4
  57. data/lib/wayfarer/middleware/normalize.rb +7 -14
  58. data/lib/wayfarer/middleware/redis.rb +15 -0
  59. data/lib/wayfarer/middleware/router.rb +33 -35
  60. data/lib/wayfarer/middleware/stage.rb +5 -5
  61. data/lib/wayfarer/middleware/uri_parser.rb +31 -0
  62. data/lib/wayfarer/middleware/user_agent.rb +49 -0
  63. data/lib/wayfarer/networking/capybara.rb +1 -1
  64. data/lib/wayfarer/networking/context.rb +14 -3
  65. data/lib/wayfarer/networking/ferrum.rb +1 -4
  66. data/lib/wayfarer/networking/follow.rb +14 -7
  67. data/lib/wayfarer/networking/http.rb +1 -1
  68. data/lib/wayfarer/networking/pool.rb +23 -13
  69. data/lib/wayfarer/networking/selenium.rb +15 -7
  70. data/lib/wayfarer/networking/strategy.rb +2 -2
  71. data/lib/wayfarer/page.rb +34 -14
  72. data/lib/wayfarer/parsing/xml.rb +6 -6
  73. data/lib/wayfarer/parsing.rb +21 -0
  74. data/lib/wayfarer/redis/barrier.rb +26 -21
  75. data/lib/wayfarer/redis/counter.rb +18 -9
  76. data/lib/wayfarer/redis/pool.rb +1 -1
  77. data/lib/wayfarer/redis/resettable.rb +19 -0
  78. data/lib/wayfarer/routing/dsl.rb +166 -30
  79. data/lib/wayfarer/routing/hash_stack.rb +33 -0
  80. data/lib/wayfarer/routing/matchers/custom.rb +8 -5
  81. data/lib/wayfarer/routing/matchers/{suffix.rb → empty_params.rb} +2 -6
  82. data/lib/wayfarer/routing/matchers/host.rb +15 -9
  83. data/lib/wayfarer/routing/matchers/path.rb +11 -31
  84. data/lib/wayfarer/routing/matchers/query.rb +41 -17
  85. data/lib/wayfarer/routing/matchers/result.rb +12 -0
  86. data/lib/wayfarer/routing/matchers/scheme.rb +13 -5
  87. data/lib/wayfarer/routing/matchers/url.rb +13 -5
  88. data/lib/wayfarer/routing/path_consumer.rb +130 -0
  89. data/lib/wayfarer/routing/path_finder.rb +151 -23
  90. data/lib/wayfarer/routing/result.rb +1 -1
  91. data/lib/wayfarer/routing/root_route.rb +17 -1
  92. data/lib/wayfarer/routing/route.rb +66 -19
  93. data/lib/wayfarer/routing/serializable.rb +28 -0
  94. data/lib/wayfarer/routing/sub_route.rb +53 -0
  95. data/lib/wayfarer/routing/target_route.rb +17 -1
  96. data/lib/wayfarer/stringify.rb +21 -30
  97. data/lib/wayfarer/task.rb +9 -17
  98. data/lib/wayfarer/uri/normalization.rb +120 -0
  99. data/lib/wayfarer.rb +72 -5
  100. data/mise.toml +2 -0
  101. data/mkdocs.yml +44 -8
  102. data/rake/docs.rake +26 -0
  103. data/rake/lint.rake +9 -0
  104. data/rake/release.rake +23 -0
  105. data/rake/tests.rake +32 -0
  106. data/requirements.txt +1 -1
  107. data/spec/factories/job.rb +8 -0
  108. data/spec/factories/middleware.rb +2 -2
  109. data/spec/factories/path_finder.rb +11 -0
  110. data/spec/factories/redis.rb +19 -0
  111. data/spec/factories/task.rb +46 -2
  112. data/spec/spec_helpers.rb +55 -51
  113. data/spec/support/active_job_helpers.rb +8 -0
  114. data/spec/support/integration_helpers.rb +21 -0
  115. data/spec/support/redis_helpers.rb +9 -0
  116. data/spec/support/test_app.rb +66 -37
  117. data/spec/wayfarer/base_spec.rb +200 -0
  118. data/spec/wayfarer/batch_completion_spec.rb +142 -0
  119. data/spec/wayfarer/cli/job_spec.rb +88 -0
  120. data/spec/wayfarer/cli/routing_spec.rb +322 -0
  121. data/spec/{cli → wayfarer/cli}/version_spec.rb +1 -1
  122. data/spec/wayfarer/gc_spec.rb +29 -0
  123. data/spec/wayfarer/handler_spec.rb +9 -0
  124. data/spec/wayfarer/integration/callbacks_spec.rb +200 -0
  125. data/spec/wayfarer/integration/content_type_spec.rb +37 -0
  126. data/spec/wayfarer/integration/custom_routing_spec.rb +51 -0
  127. data/spec/wayfarer/integration/gc_spec.rb +40 -0
  128. data/spec/wayfarer/integration/handler_spec.rb +65 -0
  129. data/spec/wayfarer/integration/page_spec.rb +79 -0
  130. data/spec/wayfarer/integration/params_spec.rb +64 -0
  131. data/spec/wayfarer/integration/parsing_spec.rb +99 -0
  132. data/spec/wayfarer/integration/retry_spec.rb +112 -0
  133. data/spec/wayfarer/integration/stage_spec.rb +58 -0
  134. data/spec/wayfarer/middleware/batch_completion_spec.rb +33 -0
  135. data/spec/{middleware → wayfarer/middleware}/chain_spec.rb +24 -19
  136. data/spec/wayfarer/middleware/content_type_spec.rb +83 -0
  137. data/spec/{middleware → wayfarer/middleware}/controller_spec.rb +24 -22
  138. data/spec/wayfarer/middleware/dedup_spec.rb +66 -0
  139. data/spec/wayfarer/middleware/normalize_spec.rb +32 -0
  140. data/spec/wayfarer/middleware/router_spec.rb +102 -0
  141. data/spec/wayfarer/middleware/stage_spec.rb +63 -0
  142. data/spec/wayfarer/middleware/uri_parser_spec.rb +63 -0
  143. data/spec/wayfarer/middleware/user_agent_spec.rb +158 -0
  144. data/spec/wayfarer/networking/capybara_spec.rb +13 -0
  145. data/spec/{networking → wayfarer/networking}/context_spec.rb +46 -38
  146. data/spec/wayfarer/networking/ferrum_spec.rb +13 -0
  147. data/spec/{networking → wayfarer/networking}/follow_spec.rb +11 -6
  148. data/spec/wayfarer/networking/http_spec.rb +12 -0
  149. data/spec/{networking → wayfarer/networking}/pool_spec.rb +16 -14
  150. data/spec/wayfarer/networking/selenium_spec.rb +12 -0
  151. data/spec/{networking → wayfarer/networking}/strategy.rb +33 -54
  152. data/spec/wayfarer/page_spec.rb +69 -0
  153. data/spec/{parsing → wayfarer/parsing}/json_spec.rb +1 -1
  154. data/spec/wayfarer/parsing/xml_parse_spec.rb +25 -0
  155. data/spec/wayfarer/redis/barrier_spec.rb +39 -0
  156. data/spec/wayfarer/redis/counter_spec.rb +34 -0
  157. data/spec/{redis → wayfarer/redis}/pool_spec.rb +4 -3
  158. data/spec/{routing → wayfarer/routing}/dsl_spec.rb +12 -22
  159. data/spec/wayfarer/routing/hash_stack_spec.rb +63 -0
  160. data/spec/wayfarer/routing/integration_spec.rb +101 -0
  161. data/spec/wayfarer/routing/matchers/custom_spec.rb +39 -0
  162. data/spec/wayfarer/routing/matchers/host_spec.rb +56 -0
  163. data/spec/wayfarer/routing/matchers/matcher.rb +17 -0
  164. data/spec/wayfarer/routing/matchers/path_spec.rb +43 -0
  165. data/spec/wayfarer/routing/matchers/query_spec.rb +123 -0
  166. data/spec/wayfarer/routing/matchers/scheme_spec.rb +45 -0
  167. data/spec/wayfarer/routing/matchers/url_spec.rb +33 -0
  168. data/spec/wayfarer/routing/path_consumer_spec.rb +123 -0
  169. data/spec/wayfarer/routing/path_finder_spec.rb +409 -0
  170. data/spec/wayfarer/routing/root_route_spec.rb +51 -0
  171. data/spec/wayfarer/routing/route_spec.rb +74 -0
  172. data/spec/wayfarer/routing/sub_route_spec.rb +103 -0
  173. data/spec/wayfarer/task_spec.rb +13 -0
  174. data/spec/wayfarer/uri/normalization_spec.rb +98 -0
  175. data/spec/wayfarer_spec.rb +2 -2
  176. data/wayfarer.gemspec +18 -28
  177. metadata +797 -265
  178. data/.github/workflows/ci.yaml +0 -32
  179. data/.rbenv-gemsets +0 -1
  180. data/.ruby-version +0 -1
  181. data/RELEASING.md +0 -17
  182. data/docs/cookbook/user_agent.md +0 -7
  183. data/docs/guides/error_handling.md +0 -53
  184. data/docs/guides/networking.md +0 -94
  185. data/docs/guides/performance.md +0 -130
  186. data/docs/guides/reliability.md +0 -41
  187. data/docs/guides/routing/steering.md +0 -30
  188. data/docs/reference/api/base.md +0 -48
  189. data/docs/reference/cli.md +0 -61
  190. data/docs/reference/configuration_keys.md +0 -43
  191. data/docs/reference/environment_variables.md +0 -83
  192. data/lib/wayfarer/cli/base.rb +0 -45
  193. data/lib/wayfarer/cli/generate.rb +0 -17
  194. data/lib/wayfarer/cli/job.rb +0 -56
  195. data/lib/wayfarer/cli/route.rb +0 -29
  196. data/lib/wayfarer/cli/runner.rb +0 -34
  197. data/lib/wayfarer/cli/templates/Gemfile.tt +0 -5
  198. data/lib/wayfarer/cli/templates/job.rb.tt +0 -10
  199. data/lib/wayfarer/config/capybara.rb +0 -10
  200. data/lib/wayfarer/config/ferrum.rb +0 -11
  201. data/lib/wayfarer/config/networking.rb +0 -29
  202. data/lib/wayfarer/config/redis.rb +0 -14
  203. data/lib/wayfarer/config/root.rb +0 -11
  204. data/lib/wayfarer/config/selenium.rb +0 -21
  205. data/lib/wayfarer/config/strconv.rb +0 -45
  206. data/lib/wayfarer/config/struct.rb +0 -72
  207. data/lib/wayfarer/middleware/fetch.rb +0 -56
  208. data/lib/wayfarer/redis/connection.rb +0 -13
  209. data/lib/wayfarer/redis/version.rb +0 -19
  210. data/lib/wayfarer/routing/router.rb +0 -28
  211. data/spec/base_spec.rb +0 -224
  212. data/spec/callbacks_spec.rb +0 -102
  213. data/spec/cli/generate_spec.rb +0 -39
  214. data/spec/cli/job_spec.rb +0 -78
  215. data/spec/config/capybara_spec.rb +0 -18
  216. data/spec/config/ferrum_spec.rb +0 -24
  217. data/spec/config/networking_spec.rb +0 -73
  218. data/spec/config/redis_spec.rb +0 -32
  219. data/spec/config/root_spec.rb +0 -31
  220. data/spec/config/selenium_spec.rb +0 -56
  221. data/spec/config/strconv_spec.rb +0 -58
  222. data/spec/config/struct_spec.rb +0 -66
  223. data/spec/fixtures/dummy_job.rb +0 -7
  224. data/spec/gc_spec.rb +0 -59
  225. data/spec/handler_spec.rb +0 -11
  226. data/spec/integration/callbacks_spec.rb +0 -85
  227. data/spec/integration/page_spec.rb +0 -62
  228. data/spec/integration/params_spec.rb +0 -56
  229. data/spec/integration/stage_spec.rb +0 -51
  230. data/spec/integration/steering_spec.rb +0 -57
  231. data/spec/middleware/dedup_spec.rb +0 -88
  232. data/spec/middleware/dispatch_spec.rb +0 -43
  233. data/spec/middleware/fetch_spec.rb +0 -155
  234. data/spec/middleware/normalize_spec.rb +0 -29
  235. data/spec/middleware/router_spec.rb +0 -105
  236. data/spec/middleware/stage_spec.rb +0 -62
  237. data/spec/networking/capybara_spec.rb +0 -12
  238. data/spec/networking/ferrum_spec.rb +0 -12
  239. data/spec/networking/http_spec.rb +0 -12
  240. data/spec/networking/selenium_spec.rb +0 -12
  241. data/spec/page_spec.rb +0 -47
  242. data/spec/parsing/xml_spec.rb +0 -25
  243. data/spec/redis/barrier_spec.rb +0 -78
  244. data/spec/redis/counter_spec.rb +0 -32
  245. data/spec/redis/version_spec.rb +0 -13
  246. data/spec/routing/integration_spec.rb +0 -110
  247. data/spec/routing/matchers/custom_spec.rb +0 -31
  248. data/spec/routing/matchers/host_spec.rb +0 -49
  249. data/spec/routing/matchers/path_spec.rb +0 -43
  250. data/spec/routing/matchers/query_spec.rb +0 -137
  251. data/spec/routing/matchers/scheme_spec.rb +0 -25
  252. data/spec/routing/matchers/suffix_spec.rb +0 -41
  253. data/spec/routing/matchers/uri_spec.rb +0 -27
  254. data/spec/routing/path_finder_spec.rb +0 -33
  255. data/spec/routing/root_route_spec.rb +0 -29
  256. data/spec/routing/route_spec.rb +0 -43
  257. data/spec/routing/router_spec.rb +0 -24
  258. data/spec/task_spec.rb +0 -34
  259. data/spec/{stringify_spec.rb → wayfarer/stringify_spec.rb} +2 -2
@@ -0,0 +1,322 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Routing", :cli, :integration do
6
+ subject(:route) { Wayfarer::CLI.start(["route", "-r", "dummy_job.rb", "DummyJob", url]) }
7
+
8
+ before do
9
+ write_file("dummy_job.rb", contents)
10
+
11
+ mock_job! :dummy_job
12
+ end
13
+
14
+ let(:contents) do
15
+ <<~RUBY
16
+ class DummyJob < ActiveJob::Base
17
+ include Wayfarer::Base
18
+
19
+ #{routes}
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ context "without routes" do
25
+ let(:url) { "http://#{test_app_host}" }
26
+ let(:routes) { "" }
27
+
28
+ let(:expected_output) do
29
+ <<~OUTPUT
30
+ ---
31
+ routed: false
32
+ root_route:
33
+ match: false
34
+ params: {}
35
+ children: []
36
+ OUTPUT
37
+ end
38
+
39
+ specify do
40
+ expect { route }.to output(expected_output).to_stdout
41
+ end
42
+ end
43
+
44
+ context "with target route only" do
45
+ let(:url) { "http://#{test_app_host}" }
46
+ let(:routes) do
47
+ <<~RUBY
48
+ route.to :index
49
+ RUBY
50
+ end
51
+
52
+ let(:expected_output) do
53
+ <<~OUTPUT
54
+ ---
55
+ routed: true
56
+ params: {}
57
+ action: :index
58
+ root_route:
59
+ match: true
60
+ params: {}
61
+ children:
62
+ - target_route:
63
+ action: :index
64
+ children: []
65
+ OUTPUT
66
+ end
67
+
68
+ specify do
69
+ expect { route }.to output(expected_output).to_stdout
70
+ end
71
+ end
72
+
73
+ context "with a symbol target" do
74
+ let(:routes) do
75
+ <<~RUBY
76
+ route.host #{test_app_hostname.inspect}, to: :index
77
+ RUBY
78
+ end
79
+
80
+ context "with matching URL" do
81
+ let(:url) { "http://#{test_app_host}" }
82
+
83
+ let(:expected_output) do
84
+ <<~OUTPUT
85
+ ---
86
+ routed: true
87
+ params: {}
88
+ action: :index
89
+ root_route:
90
+ match: true
91
+ params: {}
92
+ children:
93
+ - route:
94
+ host:
95
+ name: #{test_app_hostname}
96
+ match: true
97
+ params: {}
98
+ children:
99
+ - target_route:
100
+ action: :index
101
+ children: []
102
+ OUTPUT
103
+ end
104
+
105
+ specify do
106
+ expect { route }.to output(expected_output).to_stdout
107
+ end
108
+ end
109
+
110
+ context "with mismatching URL" do
111
+ let(:url) { "http://example.com" }
112
+
113
+ let(:expected_output) do
114
+ <<~OUTPUT
115
+ ---
116
+ routed: false
117
+ root_route:
118
+ match: true
119
+ params: {}
120
+ children:
121
+ - route:
122
+ host:
123
+ name: #{test_app_hostname}
124
+ match: false
125
+ params: {}
126
+ children: []
127
+ OUTPUT
128
+ end
129
+
130
+ specify do
131
+ expect { route }.to output(expected_output).to_stdout
132
+ end
133
+ end
134
+ end
135
+
136
+ context "with a symbol target and params" do
137
+ let(:url) { "http://#{test_app_host}/barqux" }
138
+ let(:routes) do
139
+ <<~RUBY
140
+ route.host #{test_app_hostname.inspect}, to: :index do
141
+ path ":foobar"
142
+ end
143
+ RUBY
144
+ end
145
+
146
+ let(:expected_output) do
147
+ <<~OUTPUT
148
+ ---
149
+ routed: true
150
+ params:
151
+ foobar: barqux
152
+ action: :index
153
+ root_route:
154
+ match: true
155
+ params: {}
156
+ children:
157
+ - route:
158
+ host:
159
+ name: #{test_app_hostname}
160
+ match: true
161
+ params: {}
162
+ children:
163
+ - target_route:
164
+ action: :index
165
+ children:
166
+ - route:
167
+ path:
168
+ pattern: "/:foobar"
169
+ match: true
170
+ params:
171
+ foobar: barqux
172
+ children: []
173
+ OUTPUT
174
+ end
175
+
176
+ specify do
177
+ expect { route }.to output(expected_output).to_stdout
178
+ end
179
+ end
180
+
181
+ context "with a custom route, params, and a conditional target" do
182
+ let(:url) { "http://#{test_app_host}/users/42/edit" }
183
+ let(:routes) do
184
+ <<~RUBY
185
+ route.host #{test_app_hostname.inspect}, path: ":resource" do
186
+ custom do |root, uri|
187
+ root.path ":id", path: ":action" do
188
+ if uri.host == #{test_app_hostname.inspect}
189
+ root.to :foo
190
+ end
191
+ end
192
+ end
193
+ end
194
+ RUBY
195
+ end
196
+
197
+ let(:expected_output) do
198
+ <<~OUTPUT
199
+ ---
200
+ routed: true
201
+ params:
202
+ resource: users
203
+ id: '42'
204
+ action: edit
205
+ action: :foo
206
+ root_route:
207
+ match: true
208
+ params: {}
209
+ children:
210
+ - route:
211
+ host:
212
+ name: #{test_app_hostname}
213
+ match: true
214
+ params: {}
215
+ children:
216
+ - route:
217
+ path:
218
+ pattern: "/:resource"
219
+ match: true
220
+ params:
221
+ resource: users
222
+ children:
223
+ - sub_route:
224
+ custom:
225
+ custom: Proc
226
+ match: true
227
+ params:
228
+ resource: users
229
+ id: '42'
230
+ action: edit
231
+ children: []
232
+ OUTPUT
233
+ end
234
+
235
+ specify do
236
+ expect { route }.to output(expected_output).to_stdout
237
+ end
238
+ end
239
+
240
+ describe "query parameter matching" do
241
+ let(:url) { "http://#{test_app_host}?page=10&order=desc&mobile=0&referrer=startpage&foo=bar" }
242
+ let(:routes) do
243
+ <<~RUBY
244
+ route.query({ page: 1..20, order: "desc", mobile: 0, referrer: /start/ }, to: :foo)
245
+ RUBY
246
+ end
247
+
248
+ let(:expected_output) do
249
+ <<~OUTPUT
250
+ ---
251
+ routed: true
252
+ params:
253
+ page: '10'
254
+ order: desc
255
+ mobile: '0'
256
+ referrer: startpage
257
+ action: :foo
258
+ root_route:
259
+ match: true
260
+ params: {}
261
+ children:
262
+ - route:
263
+ query:
264
+ page:
265
+ min: 1
266
+ max: 20
267
+ order: desc
268
+ mobile: 0
269
+ referrer: "/start/"
270
+ match: true
271
+ params:
272
+ page: '10'
273
+ order: desc
274
+ mobile: '0'
275
+ referrer: startpage
276
+ children:
277
+ - target_route:
278
+ action: :foo
279
+ children: []
280
+ OUTPUT
281
+ end
282
+
283
+ specify do
284
+ expect { route }.to output(expected_output).to_stdout
285
+ end
286
+ end
287
+
288
+ context "with URL matcher" do
289
+ let(:url) { "http://#{test_app_host}" }
290
+ let(:routes) do
291
+ <<~RUBY
292
+ route.url "http://#{test_app_host}", to: :index
293
+ RUBY
294
+ end
295
+
296
+ let(:expected_output) do
297
+ <<~OUTPUT
298
+ ---
299
+ routed: true
300
+ params: {}
301
+ action: :index
302
+ root_route:
303
+ match: true
304
+ params: {}
305
+ children:
306
+ - route:
307
+ url:
308
+ url: #{url}
309
+ match: true
310
+ params: {}
311
+ children:
312
+ - target_route:
313
+ action: :index
314
+ children: []
315
+ OUTPUT
316
+ end
317
+
318
+ specify do
319
+ expect { route }.to output(expected_output).to_stdout
320
+ end
321
+ end
322
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helpers"
4
4
 
5
- describe Wayfarer::CLI::Runner, cli: true do
5
+ describe Wayfarer::CLI, :cli do # rubocop:disable RSpec/SpecFilePathFormat
6
6
  describe "version" do
7
7
  it "prints the version" do
8
8
  expect {
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::GC, :integration, :redis do
6
+ describe "::run" do
7
+ subject(:run) { described_class.run(task) }
8
+
9
+ let(:job) { instance_spy(Class.new.include(Wayfarer::Base)) }
10
+ let(:task) { build(:task, :redis_pool, job: job) }
11
+ let(:barrier) { instance_spy(Wayfarer::Redis::Barrier) }
12
+
13
+ before do
14
+ allow(Wayfarer::Redis::Barrier).to receive(:new).with(task).and_return(barrier)
15
+ end
16
+
17
+ specify do
18
+ run
19
+
20
+ expect(job).to have_received(:run_callbacks).with(:batch)
21
+ end
22
+
23
+ specify do
24
+ run
25
+
26
+ expect(barrier).to have_received(:reset!)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Handler do
6
+ subject { Class.new.include(described_class) }
7
+
8
+ it { is_expected.not_to respond_to(:after_batch) }
9
+ end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Callbacks", :integration, :redis do
6
+ before do
7
+ mock_job! :dummy_job
8
+ mock_handler! :dummy_handler
9
+ end
10
+
11
+ describe "job callbacks" do
12
+ before do
13
+ DummyJob.class_eval do
14
+ route.path "alpha", to: :alpha
15
+ route.path "beta", to: :beta
16
+
17
+ def callbacks_fired
18
+ @callbacks_fired ||= []
19
+ end
20
+
21
+ before_fetch do |job|
22
+ callbacks_fired << [:before_fetch, job]
23
+ end
24
+
25
+ before_fetch if: -> { %i[alpha beta].exclude?(action) } do |job|
26
+ callbacks_fired << [:before_fetch_except_alpha_beta, job]
27
+ end
28
+
29
+ before_action do |job|
30
+ callbacks_fired << [:before_action, job]
31
+ end
32
+
33
+ before_action if: -> { action == :alpha } do |job|
34
+ callbacks_fired << [:before_action_only_alpha, job]
35
+ end
36
+
37
+ before_action if: -> { action == :beta } do |job|
38
+ callbacks_fired << [:before_action_only_beta, job]
39
+ end
40
+
41
+ before_action if: -> { %i[alpha gamma].include?(action) } do |job|
42
+ callbacks_fired << [:before_action_only_alpha_gamma, job]
43
+ end
44
+
45
+ before_action if: -> { action != :alpha } do |job|
46
+ callbacks_fired << [:before_action_except_alpha, job]
47
+ end
48
+
49
+ before_action if: -> { %i[beta gamma].exclude?(action) } do |job|
50
+ callbacks_fired << [:before_action_except_beta_gamma, job]
51
+ end
52
+
53
+ before_action :callback_a, if: -> { action == :alpha }
54
+
55
+ before_action :callback_b
56
+
57
+ before_action :callback_c, if: -> { action != :beta }
58
+
59
+ def alpha; end
60
+
61
+ def beta; end
62
+
63
+ private
64
+
65
+ def callback_a
66
+ callbacks_fired << :before_action_callback_a
67
+ end
68
+
69
+ def callback_b
70
+ callbacks_fired << :before_action_callback_b
71
+ end
72
+
73
+ def callback_c
74
+ callbacks_fired << :before_action_callback_c
75
+ end
76
+ end
77
+ end
78
+
79
+ specify do
80
+ job = DummyJob.new
81
+ job.perform(build(:task, url: test_app_path("alpha")))
82
+ expect(job.callbacks_fired).to eq([
83
+ [:before_fetch, job],
84
+ [:before_action, job],
85
+ [:before_action_only_alpha, job],
86
+ [:before_action_only_alpha_gamma, job],
87
+ [:before_action_except_beta_gamma, job],
88
+ :before_action_callback_a,
89
+ :before_action_callback_b,
90
+ :before_action_callback_c
91
+ ])
92
+
93
+ job = DummyJob.new
94
+ job.perform(build(:task, url: test_app_path("beta")))
95
+ expect(job.callbacks_fired).to eq([
96
+ [:before_fetch, job],
97
+ [:before_action, job],
98
+ [:before_action_only_beta, job],
99
+ [:before_action_except_alpha, job],
100
+ :before_action_callback_b
101
+ ])
102
+ end
103
+ end
104
+
105
+ describe "job callbacks with handler" do
106
+ before do
107
+ stub_const("CallbacksFired", [])
108
+ DummyJob.class_eval do
109
+ route.to [DummyHandler, :index]
110
+
111
+ before_fetch do |job|
112
+ CallbacksFired << [:before_fetch, job.class]
113
+ end
114
+
115
+ around_fetch do |job, block|
116
+ CallbacksFired << [:around_fetch, job.class]
117
+
118
+ block.call
119
+ end
120
+
121
+ after_fetch do |job|
122
+ CallbacksFired << [:after_fetch, job.class]
123
+ end
124
+
125
+ before_action do |job|
126
+ CallbacksFired << [:before_action, job.class]
127
+ end
128
+
129
+ around_action do |job, block|
130
+ CallbacksFired << [:around_action, job.class]
131
+
132
+ block.call
133
+ end
134
+
135
+ after_action do |job|
136
+ CallbacksFired << [:after_action, job.class]
137
+ end
138
+ end
139
+
140
+ DummyHandler.class_eval do
141
+ before_action do |handler|
142
+ CallbacksFired << [:before_action, handler.class]
143
+ end
144
+
145
+ around_action do |handler, block|
146
+ CallbacksFired << [:around_action, handler.class]
147
+
148
+ block.call
149
+ end
150
+
151
+ after_action do |handler|
152
+ CallbacksFired << [:after_action, handler.class]
153
+ end
154
+
155
+ def index; end
156
+ end
157
+ end
158
+
159
+ specify do
160
+ DummyJob.crawl(test_app_path("/"))
161
+ perform_enqueued_jobs
162
+
163
+ expect(CallbacksFired).to eq([
164
+ [:before_fetch, DummyJob],
165
+ [:around_fetch, DummyJob],
166
+ [:after_fetch, DummyJob],
167
+ [:before_action, DummyJob],
168
+ [:around_action, DummyJob],
169
+ [:before_action, DummyHandler],
170
+ [:around_action, DummyHandler],
171
+ [:after_action, DummyHandler],
172
+ [:after_action, DummyJob]
173
+ ])
174
+ end
175
+ end
176
+
177
+ describe "accessing user agent in before_fetch" do
178
+ before do
179
+ DummyJob.class_eval do
180
+ include RSpec::Matchers
181
+
182
+ route.to :index
183
+
184
+ before_fetch do
185
+ expect(user_agent).to be_a(Net::HTTP::Persistent)
186
+ end
187
+
188
+ def index; end
189
+ end
190
+ end
191
+
192
+ specify do
193
+ DummyJob.crawl(test_app_path("alpha"))
194
+ perform_enqueued_jobs
195
+
196
+ assert_performed_jobs 1
197
+ expect(enqueued_jobs).to be_empty
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Content-Type allow listing", :redis do
6
+ using RSpec::Parameterized::TableSyntax
7
+
8
+ subject(:perform) { DummyJob.new.call(task) }
9
+
10
+ before do
11
+ mock_job! :dummy_job
12
+ end
13
+
14
+ with_them do
15
+ let(:task) { build(:task, url: url) }
16
+
17
+ specify do
18
+ types = content_types
19
+
20
+ DummyJob.class_eval do
21
+ route.to :index
22
+
23
+ content_type types
24
+
25
+ def index
26
+ true
27
+ end
28
+ end
29
+
30
+ expect(DummyJob.new.perform(task)).to be(expected)
31
+ end
32
+ end
33
+
34
+ where(:content_types, :url, :expected) do
35
+ "text/html" | test_app_path("response_header/Content-Type/text/html") | true
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Custom routing", :redis do
6
+ let(:task) { build(:task) }
7
+
8
+ before do
9
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
10
+ DummyJob.class_eval do
11
+ class_attribute :action,
12
+ :params
13
+
14
+ route.custom do |root, uri, _task|
15
+ if uri.host == "example.com"
16
+ root.path ":segment" do
17
+ path "users", path: "/:id", to: :foo
18
+ end
19
+ else
20
+ root.to :bar
21
+ end
22
+ end
23
+
24
+ after_action do
25
+ self.class.params = params
26
+ end
27
+
28
+ def foo
29
+ self.class.action = :foo
30
+ end
31
+
32
+ def bar
33
+ self.class.action = :bar
34
+ end
35
+ end
36
+ end
37
+
38
+ specify do
39
+ DummyJob.crawl("https://example.com/foobar/users/42")
40
+ perform_enqueued_jobs
41
+ expect(DummyJob.action).to be(:foo)
42
+ assert_performed_jobs 1
43
+ expect(enqueued_jobs).to be_empty
44
+
45
+ DummyJob.crawl(test_app_path("/"))
46
+ perform_enqueued_jobs
47
+ expect(DummyJob.action).to be(:bar)
48
+ assert_performed_jobs 2
49
+ expect(enqueued_jobs).to be_empty
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Garbage collection", :redis do
6
+ subject(:perform) do
7
+ DummyJob.perform_later(task)
8
+ perform_enqueued_jobs
9
+ end
10
+
11
+ let(:task) { build(:task, :redis_pool) }
12
+ let(:counter) { build(:counter, task: task) }
13
+ let(:barrier) { build(:barrier, task: task) }
14
+
15
+ before do
16
+ mock_job! :dummy_job
17
+
18
+ DummyJob.class_eval do
19
+ route.to :index
20
+
21
+ def index; end
22
+ end
23
+ redis.set(counter.redis_key, 0)
24
+ redis.hset(barrier.redis_key, "", "")
25
+ end
26
+
27
+ it "resets counter" do
28
+ expect { perform }.to change { redis.exists?(counter.redis_key) }.from(true).to(false)
29
+
30
+ assert_performed_jobs 1
31
+ expect(enqueued_jobs).to be_empty
32
+ end
33
+
34
+ it "resets barrier" do
35
+ expect { perform }.to change { redis.exists?(barrier.redis_key) }.from(true).to(false)
36
+
37
+ assert_performed_jobs 1
38
+ expect(enqueued_jobs).to be_empty
39
+ end
40
+ end