wayfarer 0.4.0 → 0.4.1

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +1 -1
  3. data/Gemfile.lock +20 -15
  4. data/docs/cookbook/user_agent.md +1 -1
  5. data/docs/guides/browser_automation/capybara.md +64 -1
  6. data/docs/guides/browser_automation/custom_adapters.md +100 -0
  7. data/docs/guides/browser_automation/ferrum.md +3 -3
  8. data/docs/guides/browser_automation/selenium.md +7 -5
  9. data/docs/guides/callbacks.md +117 -10
  10. data/docs/guides/configuration.md +16 -10
  11. data/docs/guides/error_handling.md +9 -5
  12. data/docs/guides/networking.md +77 -3
  13. data/docs/index.md +9 -1
  14. data/docs/reference/api/base.md +4 -4
  15. data/docs/reference/configuration_keys.md +42 -0
  16. data/docs/reference/environment_variables.md +25 -27
  17. data/lib/wayfarer/base.rb +7 -17
  18. data/lib/wayfarer/callbacks.rb +71 -0
  19. data/lib/wayfarer/cli/base.rb +5 -1
  20. data/lib/wayfarer/cli/job.rb +7 -3
  21. data/lib/wayfarer/cli/route.rb +2 -2
  22. data/lib/wayfarer/cli/route_printer.rb +7 -7
  23. data/lib/wayfarer/config/capybara.rb +10 -0
  24. data/lib/wayfarer/config/ferrum.rb +11 -0
  25. data/lib/wayfarer/config/networking.rb +26 -0
  26. data/lib/wayfarer/config/redis.rb +14 -0
  27. data/lib/wayfarer/config/root.rb +11 -0
  28. data/lib/wayfarer/config/selenium.rb +21 -0
  29. data/lib/wayfarer/config/strconv.rb +45 -0
  30. data/lib/wayfarer/config/struct.rb +72 -0
  31. data/lib/wayfarer/gc.rb +3 -7
  32. data/lib/wayfarer/middleware/fetch.rb +7 -3
  33. data/lib/wayfarer/middleware/router.rb +2 -2
  34. data/lib/wayfarer/middleware/worker.rb +12 -9
  35. data/lib/wayfarer/networking/capybara.rb +28 -0
  36. data/lib/wayfarer/networking/context.rb +36 -0
  37. data/lib/wayfarer/networking/ferrum.rb +17 -52
  38. data/lib/wayfarer/networking/http.rb +34 -0
  39. data/lib/wayfarer/networking/pool.rb +15 -10
  40. data/lib/wayfarer/networking/result.rb +1 -1
  41. data/lib/wayfarer/networking/selenium.rb +20 -47
  42. data/lib/wayfarer/networking/strategy.rb +38 -0
  43. data/lib/wayfarer/page.rb +2 -3
  44. data/lib/wayfarer/redis/pool.rb +3 -1
  45. data/lib/wayfarer/routing/dsl.rb +8 -8
  46. data/lib/wayfarer/routing/matchers/custom.rb +23 -0
  47. data/lib/wayfarer/routing/matchers/host.rb +19 -0
  48. data/lib/wayfarer/routing/matchers/path.rb +48 -0
  49. data/lib/wayfarer/routing/matchers/query.rb +63 -0
  50. data/lib/wayfarer/routing/matchers/scheme.rb +17 -0
  51. data/lib/wayfarer/routing/matchers/suffix.rb +17 -0
  52. data/lib/wayfarer/routing/matchers/url.rb +17 -0
  53. data/lib/wayfarer/routing/route.rb +1 -1
  54. data/lib/wayfarer.rb +9 -9
  55. data/spec/base_spec.rb +14 -0
  56. data/spec/callbacks_spec.rb +102 -0
  57. data/spec/cli/job_spec.rb +6 -6
  58. data/spec/config/capybara_spec.rb +18 -0
  59. data/spec/config/ferrum_spec.rb +24 -0
  60. data/spec/config/networking_spec.rb +73 -0
  61. data/spec/config/redis_spec.rb +32 -0
  62. data/spec/config/root_spec.rb +31 -0
  63. data/spec/config/selenium_spec.rb +56 -0
  64. data/spec/config/strconv_spec.rb +58 -0
  65. data/spec/config/struct_spec.rb +66 -0
  66. data/spec/gc_spec.rb +8 -6
  67. data/spec/middleware/fetch_spec.rb +20 -8
  68. data/spec/middleware/router_spec.rb +7 -0
  69. data/spec/middleware/worker_spec.rb +64 -27
  70. data/spec/networking/capybara_spec.rb +12 -0
  71. data/spec/networking/context_spec.rb +127 -0
  72. data/spec/networking/ferrum_spec.rb +6 -22
  73. data/spec/networking/http_spec.rb +12 -0
  74. data/spec/networking/pool_spec.rb +37 -12
  75. data/spec/networking/selenium_spec.rb +6 -22
  76. data/spec/networking/strategy.rb +170 -0
  77. data/spec/redis/pool_spec.rb +1 -1
  78. data/spec/routing/dsl_spec.rb +10 -10
  79. data/spec/routing/integration_spec.rb +22 -22
  80. data/spec/routing/{custom_matcher_spec.rb → matchers/custom_spec.rb} +4 -4
  81. data/spec/routing/{host_matcher_spec.rb → matchers/host_spec.rb} +6 -6
  82. data/spec/routing/{path_matcher_spec.rb → matchers/path_spec.rb} +6 -6
  83. data/spec/routing/{query_matcher_spec.rb → matchers/query_spec.rb} +15 -15
  84. data/spec/routing/{scheme_matcher_spec.rb → matchers/scheme_spec.rb} +4 -4
  85. data/spec/routing/{suffix_matcher_spec.rb → matchers/suffix_spec.rb} +4 -4
  86. data/spec/routing/{uri_matcher_spec.rb → matchers/uri_spec.rb} +4 -4
  87. data/spec/routing/path_finder_spec.rb +1 -1
  88. data/spec/routing/root_route_spec.rb +2 -2
  89. data/spec/routing/route_spec.rb +2 -2
  90. data/spec/spec_helpers.rb +13 -5
  91. data/spec/wayfarer_spec.rb +1 -1
  92. data/wayfarer.gemspec +8 -7
  93. metadata +74 -33
  94. data/lib/wayfarer/config.rb +0 -67
  95. data/lib/wayfarer/networking/healer.rb +0 -21
  96. data/lib/wayfarer/networking/net_http.rb +0 -52
  97. data/lib/wayfarer/routing/custom_matcher.rb +0 -21
  98. data/lib/wayfarer/routing/host_matcher.rb +0 -23
  99. data/lib/wayfarer/routing/path_matcher.rb +0 -46
  100. data/lib/wayfarer/routing/query_matcher.rb +0 -67
  101. data/lib/wayfarer/routing/scheme_matcher.rb +0 -21
  102. data/lib/wayfarer/routing/suffix_matcher.rb +0 -21
  103. data/lib/wayfarer/routing/url_matcher.rb +0 -21
  104. data/spec/config_spec.rb +0 -144
  105. data/spec/networking/adapter.rb +0 -135
  106. data/spec/networking/healer_spec.rb +0 -46
  107. data/spec/networking/net_http_spec.rb +0 -37
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wayfarer
4
+ module Routing
5
+ module Matchers
6
+ URL = Struct.new(:url) do
7
+ def match(url)
8
+ url == Addressable::URI.parse(self.url)
9
+ end
10
+
11
+ def params(_)
12
+ {}
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -12,7 +12,7 @@ module Wayfarer
12
12
  :action,
13
13
  :path_offset
14
14
 
15
- def initialize(matcher = CustomMatcher.new { children.any? }, path_offset = "/")
15
+ def initialize(matcher = Matchers::Custom.new { children.any? }, path_offset = "/")
16
16
  @matcher = matcher
17
17
  @children = []
18
18
  @path_offset = path_offset
data/lib/wayfarer.rb CHANGED
@@ -28,8 +28,8 @@ require "zeitwerk"
28
28
  loader = Zeitwerk::Loader.for_gem
29
29
  loader.inflector.inflect("cli" => "CLI",
30
30
  "dsl" => "DSL",
31
- "url_matcher" => "URLMatcher",
32
- "net_http" => "NetHTTP",
31
+ "http" => "HTTP",
32
+ "url" => "URL",
33
33
  "xml" => "XML",
34
34
  "json" => "JSON",
35
35
  "gc" => "GC")
@@ -39,17 +39,17 @@ module Wayfarer
39
39
  module VERSION
40
40
  MAJOR = 0
41
41
  MINOR = 4
42
- TINY = 0
42
+ TINY = 1
43
43
  STRING = [MAJOR, MINOR, TINY].join(".")
44
44
  end
45
45
 
46
- mattr_accessor :config, default: Wayfarer::Config.from_environment
46
+ mattr_accessor :config, default: Wayfarer::Config::Root.new
47
47
 
48
- mattr_accessor :core_middleware, default: [Wayfarer::Middleware::Stage.new,
49
- Wayfarer::Middleware::Dedup.new,
50
- Wayfarer::Middleware::Normalize.new,
51
- Wayfarer::Middleware::Router.new,
52
- Wayfarer::Middleware::Fetch.new]
48
+ mattr_accessor :middleware, default: [Wayfarer::Middleware::Stage.new,
49
+ Wayfarer::Middleware::Dedup.new,
50
+ Wayfarer::Middleware::Normalize.new,
51
+ Wayfarer::Middleware::Router.new,
52
+ Wayfarer::Middleware::Fetch.new]
53
53
  end
54
54
 
55
55
  loader.eager_load
data/spec/base_spec.rb CHANGED
@@ -155,6 +155,13 @@ describe Wayfarer::Base, redis: true do
155
155
  }.to change { enqueued_jobs.size }.by(-1)
156
156
  end
157
157
 
158
+ it "marks the URL seen" do
159
+ task.counter.increment # otherwise barrier gets reset
160
+ DummyJob.crawl_later(url, batch: batch)
161
+ 3.times { perform_enqueued_jobs }
162
+ expect(task.barrier.seen?(task.url)).to be(true)
163
+ end
164
+
158
165
  it "decrements the counter" do
159
166
  3.times { task.counter.increment }
160
167
 
@@ -199,6 +206,13 @@ describe Wayfarer::Base, redis: true do
199
206
  }.to change { enqueued_jobs.size }.by(-1)
200
207
  end
201
208
 
209
+ it "marks the URL seen" do
210
+ task.counter.increment # otherwise barrier gets reset
211
+ DummyJob.crawl_later(url, batch: batch)
212
+ perform_enqueued_jobs
213
+ expect(task.barrier.seen?(task.url)).to be(true)
214
+ end
215
+
202
216
  it "decrements the counter" do
203
217
  3.times { task.counter.increment }
204
218
 
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Callbacks do
6
+ let(:url) { "https://alpha.com" }
7
+ let(:task) { build(:task, batch: "batch", url: url) }
8
+
9
+ let(:klass) do
10
+ Class.new(Wayfarer::Base) do
11
+ route.host "alpha.com", to: :alpha
12
+ route.host "beta.com", to: :beta
13
+
14
+ before_fetch do |job|
15
+ Spy.before_fetch(self, job)
16
+ end
17
+
18
+ before_fetch(except: %i[alpha beta], only: :alpha) do |job|
19
+ Spy.before_fetch_except_alpha_beta_only_alpha(self, job)
20
+ end
21
+
22
+ before_action do |job|
23
+ Spy.before_action(self, job)
24
+ end
25
+
26
+ before_action(only: :alpha) do |job|
27
+ Spy.before_action_only_alpha(self, job)
28
+ end
29
+
30
+ before_action(only: :beta) do |job|
31
+ Spy.before_action_only_beta(self, job)
32
+ end
33
+
34
+ before_action(only: %i[alpha gamma]) do |job|
35
+ Spy.before_action_only_alpha_gamma(self, job)
36
+ end
37
+
38
+ before_action(except: :alpha) do |job|
39
+ Spy.before_action_except_alpha(self, job)
40
+ end
41
+
42
+ before_action(except: %i[beta gamma]) do |job|
43
+ Spy.before_action_except_beta_gamma(self, job)
44
+ end
45
+
46
+ before_action :callback_a, only: :alpha
47
+
48
+ before_action :callback_b
49
+
50
+ before_action :callback_c, except: %i[beta]
51
+
52
+ def alpha; end
53
+
54
+ def beta; end
55
+
56
+ private
57
+
58
+ def callback_a
59
+ Spy.before_action_callback_a_only_alpha(self)
60
+ end
61
+
62
+ def callback_b
63
+ false
64
+ end
65
+
66
+ def callback_c
67
+ Spy.before_action_callback_c(self)
68
+ end
69
+ end
70
+ end
71
+
72
+ let(:job) { klass.new }
73
+
74
+ before do
75
+ stub_const("DummyJob", klass)
76
+ stub_const("Spy", spy)
77
+
78
+ allow(job).to receive(:arguments).and_return([task])
79
+ end
80
+
81
+ describe "before_fetch" do
82
+ it "fires" do
83
+ expect(Spy).to receive(:before_fetch).exactly(:once).with(job, job)
84
+ expect(Spy).not_to receive(:before_fetch_except_alpha_beta_only_alpha)
85
+ job.perform(task)
86
+ end
87
+ end
88
+
89
+ describe "before_action" do
90
+ it "fires" do
91
+ expect(Spy).to receive(:before_action).exactly(:once).with(job, job)
92
+ expect(Spy).to receive(:before_action_only_alpha).exactly(:once).with(job, job)
93
+ expect(Spy).not_to receive(:before_action_only_beta).with(job, job)
94
+ expect(Spy).to receive(:before_action_only_alpha_gamma).exactly(:once).with(job, job)
95
+ expect(Spy).not_to receive(:before_action_except_alpha).with(job, job)
96
+ expect(Spy).to receive(:before_action_except_beta_gamma).exactly(:once).with(job, job)
97
+ expect(Spy).to receive(:before_action_callback_a_only_alpha).exactly(:once).with(job)
98
+ expect(Spy).not_to receive(:before_action_callback_c).with(job)
99
+ job.perform(task)
100
+ end
101
+ end
102
+ end
data/spec/cli/job_spec.rb CHANGED
@@ -32,20 +32,20 @@ describe Wayfarer::CLI::Job, cli: true, redis: true do
32
32
  context "using MockRedis" do
33
33
  it "performs the worker using MockRedis" do
34
34
  cli.start(["job", "perform", "--mock-redis", "DummyJob", url])
35
- expect(Wayfarer.config.redis_factory.call).to be_a(MockRedis)
35
+ expect(Wayfarer.config.redis.factory.call(nil)).to be_a(MockRedis)
36
36
  end
37
37
  end
38
38
  end
39
39
 
40
40
  describe "job enqueue" do
41
41
  it "enqueues the job" do
42
- expect(DummyJob).to receive(:crawl_later).with(URI(url), batch: kind_of(String))
42
+ expect(DummyJob).to receive(:crawl_later).with(Addressable::URI.parse(url), batch: kind_of(String))
43
43
  cli.start(["job", "enqueue", "DummyJob", url])
44
44
  end
45
45
 
46
46
  context "with batch provided" do
47
47
  it "enqueues the job" do
48
- expect(DummyJob).to receive(:crawl_later).with(URI(url), batch: batch)
48
+ expect(DummyJob).to receive(:crawl_later).with(Addressable::URI.parse(url), batch: batch)
49
49
  cli.start(["job", "enqueue", "--batch", batch, "DummyJob", url])
50
50
  end
51
51
  end
@@ -53,13 +53,13 @@ describe Wayfarer::CLI::Job, cli: true, redis: true do
53
53
 
54
54
  describe "job execute" do
55
55
  it "executes the job" do
56
- expect(DummyJob).to receive(:crawl_later).with(URI(url), batch: kind_of(String))
56
+ expect(DummyJob).to receive(:crawl_later).with(Addressable::URI.parse(url), batch: kind_of(String))
57
57
  cli.start(["job", "execute", "DummyJob", url])
58
58
  end
59
59
 
60
60
  context "with batch provided" do
61
61
  it "enqueues the job" do
62
- expect(DummyJob).to receive(:crawl_later).with(URI(url), batch: batch)
62
+ expect(DummyJob).to receive(:crawl_later).with(Addressable::URI.parse(url), batch: batch)
63
63
  cli.start(["job", "execute", "--batch", batch, "DummyJob", url])
64
64
  end
65
65
  end
@@ -67,7 +67,7 @@ describe Wayfarer::CLI::Job, cli: true, redis: true do
67
67
  context "using MockRedis" do
68
68
  it "performs the worker using MockRedis" do
69
69
  cli.start(["job", "execute", "--mock-redis", "DummyJob", url])
70
- expect(Wayfarer.config.redis_factory.call).to be_a(MockRedis)
70
+ expect(Wayfarer.config.redis.factory.call(nil)).to be_a(MockRedis)
71
71
  end
72
72
  end
73
73
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Capybara do
6
+ let(:env) { {} }
7
+ subject(:capybara) { Wayfarer::Config::Capybara.new(env) }
8
+
9
+ describe "#driver" do
10
+ context "with env var set" do
11
+ before { env["WAYFARER_CAPYBARA_DRIVER"] = "cuprite" }
12
+
13
+ it "parses the env var" do
14
+ expect(capybara.driver).to be(:cuprite)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Ferrum do
6
+ let(:env) { {} }
7
+ subject(:ferrum) { Wayfarer::Config::Ferrum.new(env) }
8
+
9
+ describe "#options" do
10
+ context "by default" do
11
+ it "is {}" do
12
+ expect(ferrum.options).to eq({})
13
+ end
14
+ end
15
+
16
+ context "with env var set" do
17
+ before { env["WAYFARER_FERRUM_OPTIONS"] = "url:http://chrome:3000,headless:false" }
18
+
19
+ it "parses the env var" do
20
+ expect(ferrum.options).to eq(url: "http://chrome:3000", headless: false)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Networking do
6
+ let(:env) { {} }
7
+ subject(:network) { Wayfarer::Config::Networking.new(env) }
8
+
9
+ describe "#agent" do
10
+ context "by default" do
11
+ it "is :http" do
12
+ expect(network.agent).to be(:http)
13
+ end
14
+ end
15
+
16
+ context "with env var set" do
17
+ before { env["WAYFARER_NETWORK_AGENT"] = "ferrum" }
18
+
19
+ it "parses the env var" do
20
+ expect(network.agent).to be(:ferrum)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#pool_size" do
26
+ context "by default" do
27
+ it "is 3" do
28
+ expect(network.pool_size).to be(3)
29
+ end
30
+ end
31
+
32
+ context "with env var set" do
33
+ before { env["WAYFARER_NETWORK_POOL_SIZE"] = "42" }
34
+
35
+ it "parses the env var" do
36
+ expect(network.pool_size).to be(42)
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#pool_timeout" do
42
+ context "by default" do
43
+ it "is 10" do
44
+ expect(network.pool_timeout).to be(10)
45
+ end
46
+ end
47
+
48
+ context "with env var set" do
49
+ before { env["WAYFARER_NETWORK_POOL_SIZE"] = "1337" }
50
+
51
+ it "parses the env var" do
52
+ expect(network.pool_size).to be(1337)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#http_headers" do
58
+ context "by default" do
59
+ it "is {}" do
60
+ expect(network.http_headers).to eq({})
61
+ end
62
+ end
63
+
64
+ context "with env var set" do
65
+ before { env["WAYFARER_NETWORK_HTTP_HEADERS"] = "user-agent:foo,authorization:bar" }
66
+
67
+ it "parses the env var" do
68
+ expect(network.http_headers).to eq("user-agent": "foo",
69
+ authorization: "bar")
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Redis do
6
+ let(:env) { {} }
7
+ subject(:redis) { Wayfarer::Config::Redis.new(env) }
8
+
9
+ describe "#url" do
10
+ context "by default" do
11
+ it "is redis://localhost:6379" do
12
+ expect(redis.url).to eq("redis://localhost:6379")
13
+ end
14
+ end
15
+
16
+ context "with env var set" do
17
+ before { env["WAYFARER_REDIS_URL"] = "redis://redis:6379" }
18
+
19
+ it "parses the env var" do
20
+ expect(redis.url).to eq("redis://redis:6379")
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#factory" do
26
+ context "by default" do
27
+ it "instantiates Redis" do
28
+ expect(redis.factory.call(redis)).to be_a(::Redis)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Root do
6
+ subject(:config) { Wayfarer::Config::Root.new }
7
+
8
+ describe "#ferrum" do
9
+ it "returns a Ferrum config" do
10
+ expect(config.ferrum).to be_a(Wayfarer::Config::Ferrum)
11
+ end
12
+ end
13
+
14
+ describe "#network" do
15
+ it "returns a network config" do
16
+ expect(config.network).to be_a(Wayfarer::Config::Networking)
17
+ end
18
+ end
19
+
20
+ describe "#redis" do
21
+ it "returns a Redis config" do
22
+ expect(config.redis).to be_a(Wayfarer::Config::Redis)
23
+ end
24
+ end
25
+
26
+ describe "#selenium" do
27
+ it "returns a Selenium config" do
28
+ expect(config.selenium).to be_a(Wayfarer::Config::Selenium)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Selenium do
6
+ let(:env) { {} }
7
+ subject(:selenium) { Wayfarer::Config::Selenium.new(env) }
8
+
9
+ describe "#driver" do
10
+ context "by default" do
11
+ it "is :chrome" do
12
+ expect(selenium.driver).to be(:chrome)
13
+ end
14
+ end
15
+
16
+ context "with env var set" do
17
+ before { env["WAYFARER_SELENIUM_DRIVER"] = "firefox" }
18
+
19
+ it "parses the env var" do
20
+ expect(selenium.driver).to be(:firefox)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#options" do
26
+ context "by default" do
27
+ it "is {}" do
28
+ expect(selenium.options).to eq({})
29
+ end
30
+ end
31
+
32
+ context "with env var set" do
33
+ before { env["WAYFARER_SELENIUM_OPTIONS"] = "url:http://firefox" }
34
+
35
+ it "parses the env var" do
36
+ expect(selenium.options).to eq(url: "http://firefox")
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#client_timeout" do
42
+ context "by default" do
43
+ it "is 60" do
44
+ expect(selenium.client_timeout).to be(60)
45
+ end
46
+ end
47
+
48
+ context "with env var set" do
49
+ before { env["WAYFARER_SELENIUM_CLIENT_TIMEOUT"] = "10" }
50
+
51
+ it "parses the env var" do
52
+ expect(selenium.client_timeout).to be(10)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Strconv do
6
+ subject(:strconv) { Wayfarer::Config::Strconv }
7
+
8
+ describe "::parse" do
9
+ describe Hash do
10
+ it "parses" do
11
+ input = "alpha:1,beta:two,gamma:true"
12
+ output = strconv.parse(input, Hash)
13
+ expect(output).to eq(alpha: 1, beta: "two", gamma: true)
14
+ end
15
+ end
16
+
17
+ describe Array do
18
+ it "parses" do
19
+ input = "alpha, beta , gamma"
20
+ output = strconv.parse(input, Array)
21
+ expect(output).to eq(%w[alpha beta gamma])
22
+ end
23
+ end
24
+
25
+ describe Symbol do
26
+ it "parses" do
27
+ expect(strconv.parse("foobar", Symbol)).to be(:foobar)
28
+ end
29
+ end
30
+
31
+ describe Integer do
32
+ it "parses" do
33
+ expect(strconv.parse("42", Integer)).to be(42)
34
+ end
35
+ end
36
+
37
+ describe "Primitives" do
38
+ context "Booleans" do
39
+ it "parses" do
40
+ expect(strconv.parse("true")).to be(true)
41
+ expect(strconv.parse("false")).to be(false)
42
+ end
43
+ end
44
+
45
+ context "Numbers" do
46
+ it "parses" do
47
+ expect(strconv.parse("42")).to be(42)
48
+ end
49
+ end
50
+
51
+ context "Strings" do
52
+ it "parses" do
53
+ expect(strconv.parse("foobar")).to be("foobar")
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Config::Struct do
6
+ let(:struct) do
7
+ Wayfarer::Config::Struct.new(members)
8
+ end
9
+
10
+ let(:members) { { foo: options } }
11
+ let(:options) { {} }
12
+ let(:env) { {} }
13
+ subject { struct.new(env) }
14
+
15
+ describe "Reader" do
16
+ context "without environment values and default" do
17
+ let(:options) { {} }
18
+
19
+ it "returns nil" do
20
+ expect(subject.foo).to be(nil)
21
+ end
22
+ end
23
+
24
+ context "with default only" do
25
+ let(:options) { { default: 42 } }
26
+
27
+ it "returns the default" do
28
+ expect(subject.foo).to be(42)
29
+ end
30
+ end
31
+
32
+ context "with environment key specified" do
33
+ let(:options) { { env_key: "FOO" } }
34
+
35
+ context "with environment value" do
36
+ let(:env) { { "FOO" => "hello" } }
37
+
38
+ it "returns the value" do
39
+ expect(subject.foo).to eq("hello")
40
+ end
41
+
42
+ context "with type specified" do
43
+ let(:options) { { env_key: "FOO", type: Symbol } }
44
+
45
+ it "parses the value" do
46
+ expect(subject.foo).to be(:hello)
47
+ end
48
+ end
49
+ end
50
+
51
+ context "without environment value" do
52
+ it "returns nil" do
53
+ expect(subject.foo).to be(nil)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "Writer" do
60
+ it "allows overriding environment values and defaults" do
61
+ expect {
62
+ subject.foo = 3
63
+ }.to change { subject.foo }.from(nil).to(3)
64
+ end
65
+ end
66
+ end
data/spec/gc_spec.rb CHANGED
@@ -6,13 +6,13 @@ describe Wayfarer::GC, redis: true do
6
6
  include Wayfarer::Redis::Connection
7
7
 
8
8
  let(:task) { build(:task) }
9
- let(:klass) { Struct.new(:arguments) }
10
- let(:job) { klass.new([task]) }
9
+ let(:klass) { Class.new(Wayfarer::Base) }
10
+ let(:job) { klass.new }
11
11
  subject(:gc) { Wayfarer::GC.new(job) }
12
12
 
13
13
  before do
14
- allow(klass).to receive(:run_after_batch_callbacks)
15
- task.barrier.seen?("https://example.com")
14
+ job.arguments = [task]
15
+ task.barrier.seen?(task.url)
16
16
  end
17
17
 
18
18
  describe "#run" do
@@ -32,8 +32,10 @@ describe Wayfarer::GC, redis: true do
32
32
  end
33
33
 
34
34
  it "runs after batch callbacks" do
35
- expect(klass).to receive(:run_after_batch_callbacks).exactly(:once)
36
- gc.run
35
+ expect { |spy|
36
+ klass.after_batch(&spy)
37
+ gc.run
38
+ }.to yield_control
37
39
  end
38
40
  end
39
41