wayfarer 0.4.5 → 0.4.7

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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yaml +25 -0
  3. data/.github/workflows/release.yaml +29 -0
  4. data/.github/workflows/tests.yaml +30 -0
  5. data/.gitignore +4 -0
  6. data/.rubocop.yml +5 -0
  7. data/.vale.ini +5 -0
  8. data/.yardopts +1 -3
  9. data/Dockerfile +5 -4
  10. data/Gemfile +3 -0
  11. data/Gemfile.lock +107 -102
  12. data/Rakefile +5 -56
  13. data/bin/wayfarer +1 -1
  14. data/docker-compose.yml +20 -9
  15. data/docs/cookbook/consent_screen.md +2 -2
  16. data/docs/cookbook/executing_javascript.md +3 -3
  17. data/docs/cookbook/navigation.md +12 -12
  18. data/docs/cookbook/querying_html.md +3 -3
  19. data/docs/cookbook/screenshots.md +2 -2
  20. data/docs/cookbook/user_agent.md +1 -1
  21. data/docs/design.md +36 -0
  22. data/docs/guides/callbacks.md +24 -126
  23. data/docs/guides/configuration.md +8 -8
  24. data/docs/guides/handlers.md +60 -0
  25. data/docs/guides/index.md +1 -0
  26. data/docs/guides/jobs/error_handling.md +40 -0
  27. data/docs/guides/jobs.md +99 -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 +82 -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 +76 -10
  35. data/docs/guides/redis.md +10 -0
  36. data/docs/guides/routing.md +74 -0
  37. data/docs/guides/tasks.md +33 -9
  38. data/docs/guides/tutorial.md +60 -0
  39. data/docs/guides/user_agents.md +113 -0
  40. data/docs/index.md +17 -40
  41. data/docs/reference/cli.md +35 -25
  42. data/docs/reference/configuration.md +36 -0
  43. data/lib/wayfarer/base.rb +124 -46
  44. data/lib/wayfarer/batch_completion.rb +56 -0
  45. data/lib/wayfarer/callbacks.rb +22 -48
  46. data/lib/wayfarer/cli/route_printer.rb +71 -57
  47. data/lib/wayfarer/cli.rb +121 -0
  48. data/lib/wayfarer/gc.rb +13 -6
  49. data/lib/wayfarer/handler.rb +15 -7
  50. data/lib/wayfarer/logging.rb +38 -0
  51. data/lib/wayfarer/middleware/base.rb +2 -0
  52. data/lib/wayfarer/middleware/batch_completion.rb +19 -0
  53. data/lib/wayfarer/middleware/content_type.rb +54 -0
  54. data/lib/wayfarer/middleware/controller.rb +19 -15
  55. data/lib/wayfarer/middleware/dedup.rb +16 -13
  56. data/lib/wayfarer/middleware/dispatch.rb +12 -4
  57. data/lib/wayfarer/middleware/normalize.rb +12 -11
  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 +30 -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 +2 -2
  65. data/lib/wayfarer/networking/ferrum.rb +2 -2
  66. data/lib/wayfarer/networking/follow.rb +12 -6
  67. data/lib/wayfarer/networking/http.rb +1 -1
  68. data/lib/wayfarer/networking/pool.rb +17 -12
  69. data/lib/wayfarer/networking/selenium.rb +3 -3
  70. data/lib/wayfarer/networking/strategy.rb +2 -2
  71. data/lib/wayfarer/page.rb +36 -14
  72. data/lib/wayfarer/parsing/xml.rb +6 -6
  73. data/lib/wayfarer/parsing.rb +24 -0
  74. data/lib/wayfarer/redis/barrier.rb +13 -21
  75. data/lib/wayfarer/redis/counter.rb +19 -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 +1 -0
  79. data/lib/wayfarer/routing/matchers/path.rb +4 -2
  80. data/lib/wayfarer/routing/root_route.rb +5 -1
  81. data/lib/wayfarer/routing/route.rb +4 -14
  82. data/lib/wayfarer/stringify.rb +22 -30
  83. data/lib/wayfarer/task.rb +12 -18
  84. data/lib/wayfarer.rb +29 -2
  85. data/mkdocs.yml +52 -7
  86. data/rake/docs.rake +26 -0
  87. data/rake/lint.rake +105 -0
  88. data/rake/release.rake +29 -0
  89. data/rake/tests.rake +28 -0
  90. data/requirements.txt +1 -1
  91. data/spec/base_spec.rb +140 -160
  92. data/spec/batch_completion_spec.rb +104 -0
  93. data/spec/cli/job_spec.rb +19 -23
  94. data/spec/cli/routing_spec.rb +101 -0
  95. data/spec/cli/version_spec.rb +1 -1
  96. data/spec/factories/task.rb +7 -1
  97. data/spec/fixtures/dummy_job.rb +5 -3
  98. data/spec/gc_spec.rb +8 -50
  99. data/spec/handler_spec.rb +1 -1
  100. data/spec/integration/callbacks_spec.rb +157 -45
  101. data/spec/integration/content_type_spec.rb +145 -0
  102. data/spec/integration/gc_spec.rb +44 -0
  103. data/spec/integration/handler_spec.rb +66 -0
  104. data/spec/integration/page_spec.rb +44 -29
  105. data/spec/integration/params_spec.rb +33 -25
  106. data/spec/integration/parsing_spec.rb +125 -0
  107. data/spec/integration/routing_spec.rb +18 -0
  108. data/spec/integration/stage_spec.rb +27 -20
  109. data/spec/middleware/batch_completion_spec.rb +34 -0
  110. data/spec/middleware/chain_spec.rb +8 -8
  111. data/spec/middleware/content_type_spec.rb +86 -0
  112. data/spec/middleware/controller_spec.rb +5 -5
  113. data/spec/middleware/dedup_spec.rb +38 -55
  114. data/spec/middleware/dispatch_spec.rb +23 -7
  115. data/spec/middleware/normalize_spec.rb +44 -13
  116. data/spec/middleware/router_spec.rb +29 -30
  117. data/spec/middleware/stage_spec.rb +8 -8
  118. data/spec/middleware/uri_parser_spec.rb +53 -0
  119. data/spec/middleware/{fetch_spec.rb → user_agent_spec.rb} +28 -27
  120. data/spec/networking/context_spec.rb +17 -0
  121. data/spec/networking/follow_spec.rb +2 -2
  122. data/spec/networking/pool_spec.rb +5 -5
  123. data/spec/networking/strategy.rb +2 -2
  124. data/spec/page_spec.rb +42 -20
  125. data/spec/parsing/xml_spec.rb +11 -12
  126. data/spec/redis/barrier_spec.rb +8 -48
  127. data/spec/redis/counter_spec.rb +13 -1
  128. data/spec/redis/pool_spec.rb +1 -1
  129. data/spec/spec_helpers.rb +27 -16
  130. data/spec/support/test_app.rb +8 -0
  131. data/spec/task_spec.rb +3 -24
  132. data/spec/wayfarer_spec.rb +1 -1
  133. data/wayfarer.gemspec +4 -3
  134. metadata +61 -51
  135. data/.github/workflows/ci.yaml +0 -32
  136. data/docs/guides/error_handling.md +0 -31
  137. data/docs/guides/networking.md +0 -94
  138. data/docs/guides/performance.md +0 -130
  139. data/docs/guides/reliability.md +0 -41
  140. data/docs/guides/routing/steering.md +0 -30
  141. data/docs/reference/api/base.md +0 -48
  142. data/docs/reference/configuration_keys.md +0 -42
  143. data/docs/reference/environment_variables.md +0 -83
  144. data/lib/wayfarer/cli/base.rb +0 -45
  145. data/lib/wayfarer/cli/generate.rb +0 -17
  146. data/lib/wayfarer/cli/job.rb +0 -56
  147. data/lib/wayfarer/cli/route.rb +0 -29
  148. data/lib/wayfarer/cli/runner.rb +0 -34
  149. data/lib/wayfarer/cli/templates/Gemfile.tt +0 -5
  150. data/lib/wayfarer/cli/templates/job.rb.tt +0 -10
  151. data/lib/wayfarer/config/capybara.rb +0 -10
  152. data/lib/wayfarer/config/ferrum.rb +0 -11
  153. data/lib/wayfarer/config/networking.rb +0 -26
  154. data/lib/wayfarer/config/redis.rb +0 -14
  155. data/lib/wayfarer/config/root.rb +0 -11
  156. data/lib/wayfarer/config/selenium.rb +0 -21
  157. data/lib/wayfarer/config/strconv.rb +0 -45
  158. data/lib/wayfarer/config/struct.rb +0 -72
  159. data/lib/wayfarer/middleware/fetch.rb +0 -56
  160. data/lib/wayfarer/redis/connection.rb +0 -13
  161. data/lib/wayfarer/redis/version.rb +0 -19
  162. data/lib/wayfarer/routing/router.rb +0 -28
  163. data/spec/callbacks_spec.rb +0 -102
  164. data/spec/cli/generate_spec.rb +0 -39
  165. data/spec/config/capybara_spec.rb +0 -18
  166. data/spec/config/ferrum_spec.rb +0 -24
  167. data/spec/config/networking_spec.rb +0 -73
  168. data/spec/config/redis_spec.rb +0 -32
  169. data/spec/config/root_spec.rb +0 -31
  170. data/spec/config/selenium_spec.rb +0 -56
  171. data/spec/config/strconv_spec.rb +0 -58
  172. data/spec/config/struct_spec.rb +0 -66
  173. data/spec/integration/steering_spec.rb +0 -57
  174. data/spec/redis/version_spec.rb +0 -13
  175. data/spec/routing/router_spec.rb +0 -24
@@ -2,11 +2,17 @@
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :task, class: Wayfarer::Task do
5
- url { "https://example.com" }
5
+ url { test_app_path("/") }
6
6
  batch { "batch" }
7
7
 
8
8
  initialize_with do
9
9
  new(url, batch)
10
10
  end
11
+
12
+ trait :redis_pool do
13
+ after(:build) do |task|
14
+ task[:redis_pool] = Wayfarer::Redis::Pool.instance
15
+ end
16
+ end
11
17
  end
12
18
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class DummyJob < Wayfarer::Base
4
- route { to :index }
3
+ class Router < ActiveJob::Base
4
+ include Wayfarer::Base
5
5
 
6
- def hello; end
6
+ def hello
7
+ stage page.meta.links.external
8
+ end
7
9
  end
data/spec/gc_spec.rb CHANGED
@@ -2,58 +2,16 @@
2
2
 
3
3
  require "spec_helpers"
4
4
 
5
- describe Wayfarer::GC, redis: true do
6
- include Wayfarer::Redis::Connection
5
+ describe Wayfarer::GC, "::run", redis: true do
6
+ let(:task) { build(:task, :redis_pool) }
7
+ let(:barrier) { instance_double(Wayfarer::Redis::Barrier) }
7
8
 
8
- let(:task) { build(:task) }
9
- subject(:gc) { described_class.new(task) }
9
+ subject(:run) { described_class.run(task) }
10
10
 
11
- before do
12
- task.metadata.job = spy
13
- task.barrier.seen?(task.url)
14
- end
15
-
16
- describe "#run" do
17
- context "when counter reaches 0" do
18
- before { task.counter.increment }
19
-
20
- it "resets the barrier" do
21
- expect {
22
- gc.run
23
- }.to change { redis { |conn| conn.exists?(task.barrier.redis_key) } }.to(false)
24
- end
25
-
26
- it "resets the counter" do
27
- expect {
28
- gc.run
29
- }.to change { redis { |conn| conn.exists?(task.counter.redis_key) } }.to(false)
30
- end
31
-
32
- it "runs after batch callbacks" do
33
- expect(task.metadata.job).to receive(:run_callbacks).with(:batch).exactly(:once)
34
- gc.run
35
- end
36
- end
37
-
38
- context "when counter does not reach 0" do
39
- before { 2.times { task.counter.increment } }
40
-
41
- it "does not reset the barrier" do
42
- expect {
43
- gc.run
44
- }.not_to(change { redis { |conn| conn.exists?(task.barrier.redis_key) } })
45
- end
46
-
47
- it "does not reset the counter" do
48
- expect {
49
- gc.run
50
- }.not_to(change { redis { |conn| conn.exists?(task.counter.redis_key) } })
51
- end
11
+ it "resets barrier and counter" do
12
+ expect(barrier).to receive(:reset!)
13
+ expect(Wayfarer::Redis::Barrier).to receive(:new).with(task).and_return(barrier)
52
14
 
53
- it "does not run after batch callbacks" do
54
- expect(task.metadata.job).not_to receive(:run_callbacks).with(:batch)
55
- gc.run
56
- end
57
- end
15
+ run
58
16
  end
59
17
  end
data/spec/handler_spec.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "spec_helpers"
4
4
 
5
5
  describe Wayfarer::Handler do
6
- subject { Class.new(described_class) }
6
+ subject { Class.new.include(described_class) }
7
7
 
8
8
  it "undefines ::after_batch" do
9
9
  expect(subject).not_to respond_to(:after_batch)
@@ -2,84 +2,196 @@
2
2
 
3
3
  require "spec_helpers"
4
4
 
5
- describe "Callbacks" do
6
- let(:url) { test_app_path("git-scm.com/book/en/v2.html") }
5
+ describe Wayfarer::Callbacks, redis: true do
6
+ before do
7
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
8
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
9
+ end
7
10
 
8
- describe Wayfarer::Base do
9
- specify do
10
- class self.class::DummyJob < Wayfarer::Base
11
- extend SpecHelpers
12
- include RSpec::Matchers
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
13
16
 
14
- route { host test_app_host, to: :index }
17
+ def callbacks_fired
18
+ @callbacks_fired ||= []
19
+ end
15
20
 
16
- attr_accessor :callbacks_fired
21
+ before_fetch do |job|
22
+ callbacks_fired << [:before_fetch, job]
23
+ end
17
24
 
18
- before_fetch do
19
- self.callbacks_fired = %i[before_fetch]
25
+ before_fetch if: -> { %i[alpha beta].exclude?(action) } do |job|
26
+ callbacks_fired << [:before_fetch_except_alpha_beta, job]
20
27
  end
21
28
 
22
- before_action do
23
- callbacks_fired.push(:before_action)
29
+ before_action do |job|
30
+ callbacks_fired << [:before_action, job]
24
31
  end
25
32
 
26
- after_batch do
27
- expect(callbacks_fired).to eq(%i[before_fetch before_action])
33
+ before_action if: -> { action == :alpha } do |job|
34
+ callbacks_fired << [:before_action_only_alpha, job]
28
35
  end
29
36
 
30
- def index; end
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
31
76
  end
77
+ end
32
78
 
33
- self.class::DummyJob.crawl(url)
34
- perform_enqueued_jobs
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
+ ])
35
102
  end
36
103
  end
37
104
 
38
- describe Wayfarer::Handler do
39
- specify do
40
- class self.class::DummyJob < Wayfarer::Base
41
- extend SpecHelpers
42
- include RSpec::Matchers
105
+ describe "job callbacks with handler" do
106
+ before { stub_const("CallbacksFired", []) }
107
+
108
+ before do
109
+ DummyJob.class_eval do
110
+ route.to [DummyHandler, :index]
43
111
 
44
- route { host test_app_host, to: DummyHandler }
112
+ before_fetch do |job|
113
+ CallbacksFired << [:before_fetch, job.class]
114
+ end
45
115
 
46
- attr_accessor :callbacks_fired
116
+ around_fetch do |job, block|
117
+ CallbacksFired << [:around_fetch, job.class]
47
118
 
48
- before_fetch do
49
- self.callbacks_fired = %i[before_fetch_job]
119
+ block.call
50
120
  end
51
121
 
52
- before_action do
53
- callbacks_fired.push(:before_action_job)
122
+ after_fetch do |job|
123
+ CallbacksFired << [:after_fetch, job.class]
54
124
  end
55
125
 
56
- after_batch do
57
- expect(callbacks_fired).to eq(%i[before_fetch_job before_action_job])
126
+ before_action do |job|
127
+ CallbacksFired << [:before_action, job.class]
58
128
  end
59
129
 
60
- class DummyHandler < Wayfarer::Handler
61
- include RSpec::Matchers
130
+ around_action do |job, block|
131
+ CallbacksFired << [:around_action, job.class]
62
132
 
63
- route { to :index }
133
+ block.call
134
+ end
64
135
 
65
- attr_accessor :callbacks_fired
136
+ after_action do |job|
137
+ CallbacksFired << [:after_action, job.class]
138
+ end
139
+ end
66
140
 
67
- before_fetch do
68
- raise "before_fetch ran in handler"
69
- end
141
+ DummyHandler.class_eval do
142
+ before_action do |handler|
143
+ CallbacksFired << [:before_action, handler.class]
144
+ end
70
145
 
71
- before_action do
72
- self.callbacks_fired = %i[before_action_handler]
73
- end
146
+ around_action do |handler, block|
147
+ CallbacksFired << [:around_action, handler.class]
74
148
 
75
- def index
76
- expect(callbacks_fired).to eq(%i[before_action_handler])
77
- end
149
+ block.call
78
150
  end
151
+
152
+ after_action do |handler|
153
+ CallbacksFired << [:after_action, handler.class]
154
+ end
155
+
156
+ def index; end
79
157
  end
158
+ end
80
159
 
81
- self.class::DummyJob.crawl(url)
160
+ specify do
161
+ DummyJob.crawl(test_app_path("/"))
82
162
  perform_enqueued_jobs
163
+
164
+ expect(CallbacksFired).to eq([
165
+ [:before_fetch, DummyJob],
166
+ [:around_fetch, DummyJob],
167
+ [:after_fetch, DummyJob],
168
+ [:before_action, DummyJob],
169
+ [:around_action, DummyJob],
170
+ [:before_action, DummyHandler],
171
+ [:around_action, DummyHandler],
172
+ [:after_action, DummyHandler],
173
+ [:after_action, DummyJob]
174
+ ])
175
+ end
176
+ end
177
+
178
+ describe "accessing user agent in before_fetch" do
179
+ before do
180
+ DummyJob.class_eval do
181
+ include RSpec::Matchers
182
+
183
+ route.to :index
184
+
185
+ before_fetch do
186
+ expect(user_agent).to be_a(Net::HTTP::Persistent)
187
+ end
188
+
189
+ def index; end
190
+ end
191
+ end
192
+
193
+ specify do
194
+ DummyJob.new.perform(build(:task, url: test_app_path("alpha")))
83
195
  end
84
196
  end
85
197
  end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Content-Type allow listing", redis: true do
6
+ def perform(content_type)
7
+ DummyJob.new.perform(
8
+ build(:task, url: test_app_path("response_header/Content-Type/#{content_type}"))
9
+ )
10
+ end
11
+
12
+ before do
13
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
14
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
15
+ end
16
+
17
+ context "with registered Content-Types" do
18
+ before do
19
+ DummyJob.class_eval do
20
+ route.to :index
21
+
22
+ content_type "foo", "bar"
23
+
24
+ def index
25
+ :ok
26
+ end
27
+ end
28
+ end
29
+
30
+ specify do
31
+ expect(perform("foo")).to be(:ok)
32
+ expect(perform("bar")).to be(:ok)
33
+ expect(perform("qux")).to be(nil)
34
+ end
35
+ end
36
+
37
+ context "with registered Content-Type media type" do
38
+ before do
39
+ DummyJob.class_eval do
40
+ route.to :index
41
+
42
+ content_type(/text/)
43
+ content_type "application/vnd.scenario.custom+json"
44
+
45
+ def index
46
+ :ok
47
+ end
48
+ end
49
+ end
50
+
51
+ specify do
52
+ expect(perform("text/xml")).to be(:ok)
53
+ expect(perform("application/xml")).to be(nil)
54
+ expect(perform("application/rss+xml")).to be(nil)
55
+ expect(perform("image/svg+xml")).to be(nil)
56
+ expect(perform("application/vnd.scenario.custom+json")).to be(:ok)
57
+ end
58
+ end
59
+
60
+ context "without registered Content-Types" do
61
+ before do
62
+ DummyJob.class_eval do
63
+ route.to :index
64
+
65
+ def index
66
+ :ok
67
+ end
68
+ end
69
+ end
70
+
71
+ specify do
72
+ expect(perform("foo")).to be(:ok)
73
+ end
74
+ end
75
+
76
+ context "with regular expression Content-Type" do
77
+ before do
78
+ DummyJob.class_eval do
79
+ route.to :index
80
+
81
+ content_type(/xml/)
82
+
83
+ def index
84
+ :ok
85
+ end
86
+ end
87
+ end
88
+
89
+ specify do
90
+ expect(perform("text/xml")).to be(:ok)
91
+ expect(perform("application/xml")).to be(:ok)
92
+ expect(perform("application/rss+xml")).to be(:ok)
93
+ expect(perform("image/svg+xml")).to be(:ok)
94
+ expect(perform("application/vnd.scenario.custom+json")).to be(nil)
95
+ end
96
+ end
97
+
98
+ context "with registered Content-Types" do
99
+ before do
100
+ DummyJob.class_eval do
101
+ route.to :index
102
+
103
+ content_type(/text/, "foo")
104
+
105
+ def index
106
+ :ok
107
+ end
108
+ end
109
+ end
110
+
111
+ specify do
112
+ expect(perform("text/application")).to be(:ok)
113
+ expect(perform("foo")).to be(:ok)
114
+ expect(perform("bar")).to be(nil)
115
+ end
116
+ end
117
+
118
+ context "with handler" do
119
+ before do
120
+ DummyJob.class_eval do
121
+ route.to DummyHandler
122
+
123
+ content_type(/text/, "foo")
124
+ end
125
+ end
126
+
127
+ before do
128
+ DummyHandler.class_eval do
129
+ route.to :index
130
+
131
+ content_type "foo"
132
+
133
+ def index
134
+ :handler
135
+ end
136
+ end
137
+ end
138
+
139
+ specify do
140
+ expect(perform("text/application")).to be(nil)
141
+ expect(perform("foo")).to be(:handler)
142
+ expect(perform("bar")).to be(nil)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Garbage collection", redis: true do
6
+ let(:task) { build(:task, :redis_pool) }
7
+ let(:counter) { Wayfarer::Redis::Counter.new(task) }
8
+ let(:barrier) { Wayfarer::Redis::Barrier.new(task) }
9
+ let(:redis) { ::Redis.new(url: redis_host) }
10
+
11
+ before do
12
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
13
+
14
+ DummyJob.class_eval do
15
+ route.to :index
16
+
17
+ def index; end
18
+ end
19
+ end
20
+
21
+ before do
22
+ redis.set(counter.redis_key, 0)
23
+ redis.hset(barrier.redis_key, "", "")
24
+ end
25
+
26
+ subject(:perform) do
27
+ DummyJob.perform_later(task)
28
+ perform_enqueued_jobs
29
+ end
30
+
31
+ it "resets counter" do
32
+ expect { perform }.to change { redis.exists?(counter.redis_key) }.from(true).to(false)
33
+
34
+ assert_performed_jobs 1
35
+ expect(enqueued_jobs).to be_empty
36
+ end
37
+
38
+ it "resets barrier" do
39
+ expect { perform }.to change { redis.exists?(barrier.redis_key) }.from(true).to(false)
40
+
41
+ assert_performed_jobs 1
42
+ expect(enqueued_jobs).to be_empty
43
+ end
44
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Handlers", redis: true do
6
+ before do
7
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
8
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
9
+ stub_const("OtherHandler", Class.new.include(Wayfarer::Handler))
10
+ end
11
+
12
+ describe "bypassing the router" do
13
+ before do
14
+ DummyJob.class_eval do
15
+ route.to DummyHandler
16
+ end
17
+
18
+ DummyHandler.class_eval do
19
+ class_attribute :called
20
+
21
+ before_action do
22
+ self.class.called = true
23
+ end
24
+
25
+ route.to [OtherHandler, :foobar]
26
+ end
27
+
28
+ OtherHandler.class_eval do
29
+ class_attribute :called
30
+
31
+ def foobar
32
+ self.class.called = true
33
+ end
34
+ end
35
+ end
36
+
37
+ specify do
38
+ DummyJob.crawl(test_app_path("/"))
39
+ perform_enqueued_jobs
40
+ assert_performed_jobs 1
41
+ expect(enqueued_jobs).to be_empty
42
+ expect(DummyHandler.called).to be(true)
43
+ expect(OtherHandler.called).to be(true)
44
+ end
45
+ end
46
+
47
+ describe "dispatching to another Wayfarer::Base" do
48
+ before do
49
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
50
+ stub_const("OtherJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
51
+ end
52
+
53
+ before do
54
+ DummyJob.class_eval do
55
+ extend SpecHelpers
56
+
57
+ route.to OtherJob
58
+ end
59
+ end
60
+
61
+ specify do
62
+ DummyJob.crawl(test_app_path("/"))
63
+ expect { perform_enqueued_jobs }.to raise_error(ArgumentError, "invalid action: OtherJob")
64
+ end
65
+ end
66
+ end