wayfarer 0.4.6 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
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 +28 -1
  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 +1 -1
  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 -53
  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 -43
  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 -29
  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