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
@@ -5,16 +5,31 @@ require "spec_helpers"
5
5
  describe "Pages" do
6
6
  let(:url) { test_app_path("git-scm.com/book/en/v2.html") }
7
7
 
8
- describe Wayfarer::Base do
8
+ before do
9
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
10
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
11
+ end
12
+
13
+ shared_examples "executes" do
9
14
  specify do
10
- class self.class::DummyJob < Wayfarer::Base
11
- extend SpecHelpers
15
+ DummyJob.crawl(url)
16
+ perform_enqueued_jobs
17
+ assert_performed_jobs 1
18
+ expect(enqueued_jobs).to be_empty
19
+ end
20
+ end
21
+
22
+ describe "page content" do
23
+ before do
24
+ DummyJob.class_eval do
12
25
  include RSpec::Matchers
26
+ extend SpecHelpers
27
+ include SpecHelpers
13
28
 
14
- route { host test_app_host, to: :index }
29
+ route.host test_app_host, to: :index
15
30
 
16
31
  def index
17
- expect(page.url).to eq("http://test:9876/git-scm.com/book/en/v2.html")
32
+ expect(page.url).to eq(test_app_path("git-scm.com/book/en/v2.html"))
18
33
  expect(page.status_code).to be(200)
19
34
  expect(page.body).not_to be_empty
20
35
  expect(page.headers.count).to be(9)
@@ -24,39 +39,39 @@ describe "Pages" do
24
39
  expect(page.meta.links.external.count).to be(55)
25
40
  end
26
41
  end
27
-
28
- self.class::DummyJob.crawl(url)
29
- perform_enqueued_jobs
30
42
  end
31
- end
32
-
33
- describe Wayfarer::Handler do
34
- specify do
35
- class self.class::DummyJob < Wayfarer::Base
36
- extend SpecHelpers
37
43
 
38
- route { host test_app_host, to: DummyHandler }
44
+ it_behaves_like "executes"
45
+ end
39
46
 
40
- class DummyHandler < Wayfarer::Handler
41
- include RSpec::Matchers
47
+ describe "page content with handler" do
48
+ before do
49
+ DummyJob.class_eval do
50
+ include RSpec::Matchers
51
+ include SpecHelpers
42
52
 
43
- route { to :index }
53
+ route.to :index
44
54
 
45
- def index
46
- expect(page.url).to eq("http://test:9876/git-scm.com/book/en/v2.html")
47
- expect(page.status_code).to be(200)
48
- expect(page.body).not_to be_empty
49
- expect(page.headers.count).to be(9)
55
+ def index
56
+ expect(page.url).to eq(test_app_path("git-scm.com/book/en/v2.html"))
57
+ expect(page.status_code).to be(200)
58
+ expect(page.body).not_to be_empty
59
+ expect(page.headers.count).to be(9)
50
60
 
51
- expect(page.meta.links.all.count).to be(157)
52
- expect(page.meta.links.internal.count).to be(102)
53
- expect(page.meta.links.external.count).to be(55)
54
- end
61
+ expect(page.meta.links.all.count).to be(157)
62
+ expect(page.meta.links.internal.count).to be(102)
63
+ expect(page.meta.links.external.count).to be(55)
55
64
  end
56
65
  end
57
66
 
58
- self.class::DummyJob.crawl(url)
59
- perform_enqueued_jobs
67
+ DummyHandler.class_eval do
68
+ extend SpecHelpers
69
+ include SpecHelpers
70
+
71
+ route.host test_app_host, to: DummyHandler
72
+ end
60
73
  end
74
+
75
+ it_behaves_like "executes"
61
76
  end
62
77
  end
@@ -5,52 +5,60 @@ require "spec_helpers"
5
5
  describe "URL parameters" do
6
6
  let(:url) { test_app_path("git-scm.com/book/en/v2.html") }
7
7
 
8
- describe Wayfarer::Base do
8
+ before do
9
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
10
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
11
+ end
12
+
13
+ shared_examples "executes" do
9
14
  specify do
10
- class self.class::DummyJob < Wayfarer::Base
15
+ DummyJob.crawl(url)
16
+ perform_enqueued_jobs
17
+ assert_performed_jobs 1
18
+ expect(enqueued_jobs).to be_empty
19
+ end
20
+ end
21
+
22
+ describe "path pattern matching" do
23
+ before do
24
+ DummyJob.class_eval do
11
25
  extend SpecHelpers
12
26
  include RSpec::Matchers
13
27
 
14
- route do
15
- to :index, host: test_app_host do
16
- path "git-scm.com/book/:lang/:file"
17
- end
28
+ route.to :index, host: test_app_host do
29
+ path "git-scm.com/book/:lang/:file"
18
30
  end
19
31
 
20
32
  def index
21
33
  expect(params).to eq("lang" => "en", "file" => "v2.html")
22
34
  end
23
35
  end
24
-
25
- self.class::DummyJob.crawl(url)
26
- perform_enqueued_jobs
27
36
  end
37
+
38
+ it_behaves_like "executes"
28
39
  end
29
40
 
30
- describe Wayfarer::Handler do
31
- specify do
32
- class self.class::DummyJob < Wayfarer::Base
41
+ describe "path pattern matching with handler" do
42
+ before do
43
+ DummyJob.class_eval do
33
44
  extend SpecHelpers
34
45
 
35
- route do
36
- to DummyHandler, host: test_app_host do
37
- path "git-scm.com/book/:lang/:file"
38
- end
46
+ route.to DummyHandler, host: test_app_host do
47
+ path "git-scm.com/book/:lang/:file"
39
48
  end
49
+ end
40
50
 
41
- class DummyHandler < Wayfarer::Handler
42
- include RSpec::Matchers
51
+ DummyHandler.class_eval do
52
+ include RSpec::Matchers
43
53
 
44
- route { to :index }
54
+ route.to :index
45
55
 
46
- def index
47
- expect(params).to eq("lang" => "en", "file" => "v2.html")
48
- end
56
+ def index
57
+ expect(params).to eq("lang" => "en", "file" => "v2.html")
49
58
  end
50
59
  end
51
-
52
- self.class::DummyJob.crawl(url)
53
- perform_enqueued_jobs
54
60
  end
55
61
  end
62
+
63
+ it_behaves_like "executes"
56
64
  end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Response body parsing", 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
10
+
11
+ shared_examples "executes" do
12
+ specify do
13
+ DummyJob.crawl(url)
14
+ perform_enqueued_jobs
15
+ assert_performed_jobs 1
16
+ expect(enqueued_jobs).to be_empty
17
+ end
18
+ end
19
+
20
+ context "with XML" do
21
+ let(:url) { test_app_path("xml/dummy.xml") }
22
+
23
+ before do
24
+ DummyJob.class_eval do
25
+ include RSpec::Matchers
26
+
27
+ route.to :index
28
+
29
+ def index
30
+ expect(page.doc).to be_a(Nokogiri::XML::Document)
31
+ end
32
+ end
33
+
34
+ it_behaves_like "executes"
35
+ end
36
+ end
37
+
38
+ context "with HTML" do
39
+ let(:url) { test_app_path("finders.html") }
40
+
41
+ before do
42
+ DummyJob.class_eval do
43
+ include RSpec::Matchers
44
+
45
+ route.to :index
46
+
47
+ def index
48
+ expect(page.doc).to be_a(Nokogiri::HTML::Document)
49
+ end
50
+ end
51
+ end
52
+
53
+ it_behaves_like "executes"
54
+ end
55
+
56
+ context "with JSON" do
57
+ let(:url) { test_app_path("json/dummy.json") }
58
+
59
+ before do
60
+ DummyJob.class_eval do
61
+ include RSpec::Matchers
62
+
63
+ route.to :index
64
+
65
+ def index
66
+ expect(page.doc).to be_a(Hash)
67
+ end
68
+ end
69
+ end
70
+
71
+ it_behaves_like "executes"
72
+ end
73
+
74
+ describe "custom Content-Type parsers" do
75
+ context "with registered Content-Types" do
76
+ let(:parser) do
77
+ Class.new do
78
+ def self.parse(_body)
79
+ :ok
80
+ end
81
+ end
82
+ end
83
+
84
+ let(:parser_with_options) do
85
+ Class.new do
86
+ def self.parse(_body, options)
87
+ options
88
+ end
89
+ end
90
+ end
91
+
92
+ before do
93
+ Wayfarer::Parsing.registry["foo/bar"] = parser
94
+ Wayfarer::Parsing.registry["bar/qux"] = [parser_with_options, :ok]
95
+ end
96
+
97
+ after do
98
+ Wayfarer::Parsing.registry.delete("foo/bar")
99
+ Wayfarer::Parsing.registry.delete("bar/qux")
100
+ end
101
+
102
+ before do
103
+ DummyJob.class_eval do
104
+ route.to :index
105
+
106
+ def index
107
+ page.doc
108
+ end
109
+ end
110
+ end
111
+
112
+ def perform(content_type)
113
+ DummyJob.new.perform(
114
+ build(:task, url: test_app_path("response_header/Content-Type/#{content_type}"))
115
+ )
116
+ end
117
+
118
+ specify do
119
+ expect(perform("foo/bar")).to be(:ok)
120
+ expect(perform("bar/qux")).to be(:ok)
121
+ expect(perform("image/jpeg")).to be(nil)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe "Routing" do
6
+ let(:task) { build(:task) }
7
+
8
+ before do
9
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
10
+ end
11
+
12
+ describe "custom routing" do
13
+ before do
14
+ DummyJob.class_eval do
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,50 +2,57 @@
2
2
 
3
3
  require "spec_helpers"
4
4
 
5
- describe "Staging" do
5
+ describe "Staging", redis: true do
6
6
  let(:url) { test_app_path("git-scm.com/book/en/v2.html") }
7
7
 
8
- describe Wayfarer::Base do
9
- specify do
10
- class self.class::DummyJob < Wayfarer::Base
8
+ before do
9
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
10
+ stub_const("DummyHandler", Class.new.include(Wayfarer::Handler))
11
+ end
12
+
13
+ describe "staging URLs" do
14
+ before do
15
+ DummyJob.class_eval do
11
16
  extend SpecHelpers
12
17
 
13
- route { host test_app_host, to: :index }
18
+ route.host test_app_host, to: :index
14
19
 
15
20
  def index
16
21
  stage page.meta.links.all
17
22
  end
18
23
  end
24
+ end
19
25
 
26
+ specify do
20
27
  expect {
21
- self.class::DummyJob.crawl(url)
28
+ DummyJob.crawl(url)
22
29
  perform_enqueued_jobs
23
- }.to change { enqueued_jobs.size }.by(156)
30
+ }.to change { enqueued_jobs.size }.by(157)
24
31
  end
25
32
  end
26
33
 
27
- describe Wayfarer::Handler do
28
- specify do
29
- class self.class::DummyJob < Wayfarer::Base
34
+ context "with handler" do
35
+ before do
36
+ DummyJob.class_eval do
30
37
  extend SpecHelpers
31
38
 
32
- route do
33
- host test_app_host, to: DummyHandler
34
- end
39
+ route.host test_app_host, to: DummyHandler
40
+ end
35
41
 
36
- class DummyHandler < Wayfarer::Handler
37
- route { to :index }
42
+ DummyHandler.class_eval do
43
+ route.to :index
38
44
 
39
- def index
40
- stage page.meta.links.all
41
- end
45
+ def index
46
+ stage page.meta.links.all
42
47
  end
43
48
  end
49
+ end
44
50
 
51
+ specify do
45
52
  expect {
46
- self.class::DummyJob.crawl(url)
53
+ DummyJob.crawl(url)
47
54
  perform_enqueued_jobs
48
- }.to change { enqueued_jobs.size }.by(156)
55
+ }.to change { enqueued_jobs.size }.by(157)
49
56
  end
50
57
  end
51
58
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Middleware::BatchCompletion, "#call" do
6
+ let(:task) { build(:task) }
7
+ let(:job) { double(exception_executions: exception_executions) }
8
+ let(:exception_executions) { {} }
9
+ subject(:batch_completion) { described_class.new }
10
+
11
+ before { task[:job] = job }
12
+
13
+ it "assigns cloned exception_executions" do
14
+ expect {
15
+ batch_completion.call(task)
16
+ }.to change {
17
+ task[:initial_exception_executions]
18
+ }.from(nil).to(exception_executions)
19
+
20
+ expect(task[:initial_exception_executions]).not_to be(exception_executions)
21
+ end
22
+
23
+ context "when already assigned" do
24
+ before { task[:initial_exception_executions] = Object.new }
25
+
26
+ specify do
27
+ expect { |spy| batch_completion.call(task, &spy) }.to yield_control
28
+ end
29
+
30
+ it "doesn't assign exception_executions" do
31
+ expect { batch_completion.call(task) }.not_to(change { task[:initial_exception_executions] })
32
+ end
33
+ end
34
+ end
@@ -65,11 +65,11 @@ describe Wayfarer::Middleware::Chain do
65
65
  describe "Return value" do
66
66
  let(:middlewares) do
67
67
  [build(:middleware, receiver: lambda do |task, &block|
68
- task.metadata.foobar = 42
68
+ task[:foobar] = 42
69
69
  block.call
70
70
  end),
71
71
  build(:middleware, receiver: lambda do |task|
72
- task.metadata.foobar *= 1337
72
+ task[:foobar] *= 1337
73
73
  end)]
74
74
  end
75
75
 
@@ -81,16 +81,16 @@ describe Wayfarer::Middleware::Chain do
81
81
  describe "Metadata" do
82
82
  let(:first) do
83
83
  build(:middleware, receiver: lambda do |task, &block|
84
- task.metadata.foobar = 42
84
+ task[:foobar] = 42
85
85
  block.call
86
- task.metadata.barqux = 1337
86
+ task[:barqux] = 1337
87
87
  end)
88
88
  end
89
89
 
90
90
  let(:last) do
91
91
  build(:middleware, receiver: lambda do |task|
92
- raise unless task.metadata.foobar == 42
93
- raise if task.metadata.barqux
92
+ raise unless task[:foobar] == 42
93
+ raise if task[:barqux]
94
94
  end)
95
95
  end
96
96
 
@@ -101,8 +101,8 @@ describe Wayfarer::Middleware::Chain do
101
101
  chain.call(task)
102
102
  }.not_to raise_error
103
103
 
104
- expect(task.metadata.foobar).to be(42)
105
- expect(task.metadata.barqux).to be(1337)
104
+ expect(task[:foobar]).to be(42)
105
+ expect(task[:barqux]).to be(1337)
106
106
  end
107
107
  end
108
108
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helpers"
4
+
5
+ describe Wayfarer::Middleware::ContentType do
6
+ let(:content_type) { "text/html" }
7
+ let(:task) { build(:task) }
8
+ let(:page) { build(:page, headers: { "Content-Type" => content_type }) }
9
+
10
+ describe "#call" do
11
+ subject { Class.new(described_class).include(described_class::API).new }
12
+
13
+ before do
14
+ task[:page] = page
15
+ task[:controller] = subject
16
+ end
17
+
18
+ before { subject.class.content_type "text/html" }
19
+
20
+ context "with permitted Content-Type" do
21
+ it "yields" do
22
+ expect { |spy| subject.call(task, &spy) }.to yield_control
23
+ end
24
+ end
25
+
26
+ context "when permitted Content-Type has parameters" do
27
+ let(:page) { build(:page, headers: { "Content-Type" => "#{content_type}; charset=UTF-" }) }
28
+
29
+ it "yields" do
30
+ expect { |spy| subject.call(task, &spy) }.to yield_control
31
+ end
32
+ end
33
+
34
+ context "with forbidden Content-Type" do
35
+ let(:content_type) { "application/json" }
36
+
37
+ it "does not yield" do
38
+ expect { |spy| subject.call(task, &spy) }.not_to yield_control
39
+ end
40
+ end
41
+
42
+ context "with permitted Regexp Content-Type" do
43
+ before do
44
+ subject.class.content_type(/text/)
45
+ end
46
+
47
+ it "yields" do
48
+ expect { |spy| subject.call(task, &spy) }.to yield_control
49
+ end
50
+ end
51
+ end
52
+
53
+ describe described_class::API do
54
+ subject(:controller) do
55
+ Struct.new(:task).include(described_class).new(task)
56
+ end
57
+
58
+ describe "::allowed_content_types" do
59
+ describe "index" do
60
+ subject { controller.class.allowed_content_types[:index] }
61
+
62
+ it { is_expected.to be_empty }
63
+ end
64
+
65
+ describe "patterns" do
66
+ subject { controller.class.allowed_content_types[:patterns] }
67
+
68
+ it { is_expected.to be_empty }
69
+ end
70
+ end
71
+
72
+ describe "#content_type" do
73
+ it "allows Content-Types" do
74
+ controller.class.content_type(content_type)
75
+
76
+ expect(controller.class.allowed_content_types[:index][content_type]).to be(true)
77
+ end
78
+
79
+ it "allows Content-Type patterns" do
80
+ controller.class.content_type(/text/)
81
+
82
+ expect(controller.class.allowed_content_types[:patterns]).to contain_exactly(/text/)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -54,28 +54,28 @@ describe Wayfarer::Middleware::Controller do
54
54
  it "assigns itself" do
55
55
  expect {
56
56
  subject.call(task)
57
- }.to change { task.metadata.job }.to(subject)
57
+ }.to change { task[:job] }.to(subject)
58
58
  end
59
59
  end
60
60
 
61
61
  context "with job assigned" do
62
- before { task.metadata.job = Object.new }
62
+ before { task[:job] = Object.new }
63
63
 
64
64
  it "does not override the job" do
65
65
  expect {
66
66
  subject.call(task)
67
- }.not_to(change { task.metadata.job })
67
+ }.not_to(change { task[:job] })
68
68
  end
69
69
  end
70
70
 
71
71
  it "assigns itself as controller" do
72
72
  expect {
73
73
  subject.call(task)
74
- }.to change { task.metadata.controller }.to(subject)
74
+ }.to change { task[:controller] }.to(subject)
75
75
  end
76
76
 
77
77
  it "calls the chain" do
78
- expect(subject.chain).to receive(:call)
78
+ expect(subject.class.chain).to receive(:call)
79
79
  subject.call(task)
80
80
  end
81
81