web_pipe 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a993e68cff01cb6b0ef493b6bdf3207e62a7baca650302c9f65024f3981c18a
4
- data.tar.gz: dc94f7dfabc97ad712a058f725e85831c38fe2658f42adeca3243b29f10273f9
3
+ metadata.gz: 248232882dde49a235e15080f2c9c2abb1188e29e10f228f43d0c30c6c5f116f
4
+ data.tar.gz: ad6afa0399cdb99d80ef46fb1bcdde037e987e8fe01756f2c667301a9f622d5e
5
5
  SHA512:
6
- metadata.gz: 2e5925278ef21f20b3c9b8ae25f7bd614c7e17b278693f3521f018cefe1acd1ef63116aba61a9722bc1f4d5b98bfbeb56a6e03d0d246ac359aa595e4c451f6eb
7
- data.tar.gz: baf191023d9a19ed7facfc77f3107db45e2adb1949a25e4fc306b0a9f85e061e474fc557848beb469aaf0c5ad0446918b9c285b63cc5501bf21d31c19229878c
6
+ metadata.gz: 399f912c144ac66bd1bfeaf58708a8e52ed7e296f5e592c9f9422fd3fd6553a4e3c16c0fec2986cf4fd278857d5acd1078d7b1a7e9e0e07ad9f18824303953ba
7
+ data.tar.gz: 41c539bee15aa9d3f8ae23bc88cd02ba5dc113ad9245290c330a269917716d12da5637852153d2f9bd7b324e8101f2a1329b267e5ebc409ae0c5cb419cd932f8
data/.rubocop.yml CHANGED
@@ -13,3 +13,6 @@ Metrics/BlockLength:
13
13
 
14
14
  Naming/AccessorMethodName:
15
15
  Enabled: false
16
+
17
+ Style/HashConversion:
18
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [0.14.0] - 2021-04-14
8
+ ### Added
9
+ - Inspecting operations
10
+ [#42](https://github.com/waiting-for-dev/web_pipe/pull/42)
11
+ - Inspecting middlewares
12
+ [#43](https://github.com/waiting-for-dev/web_pipe/pull/43)
13
+ - Testing support
14
+ [#44](https://github.com/waiting-for-dev/web_pipe/pull/44)
15
+
7
16
  ## [0.13.0] - 2021-01-15
8
17
  ### Added
9
18
  - **BREAKING**. Ruby 2.5 deprecated.
data/README.md CHANGED
@@ -20,9 +20,11 @@ extension](docs/extensions/rails.md).
20
20
  1. [Resolving operations](docs/plugging_operations/resolving_operations.md)
21
21
  1. [Injecting operations](docs/plugging_operations/injecting_operations.md)
22
22
  1. [Composing operations](docs/plugging_operations/composing_operations.md)
23
+ 1. [Inspecting operations](docs/plugging_operations/inspecting_operations.md)
23
24
  1. [Using rack middlewares](docs/using_rack_middlewares.md)
24
25
  1. [Injecting middlewares](docs/using_rack_middlewares/injecting_middlewares.md)
25
26
  1. [Composing middlewares](docs/using_rack_middlewares/composing_middlewares.md)
27
+ 1. [Inspecting middlewares](docs/using_rack_middlewares/inspecting_middlewares.md)
26
28
  1. [Composing applications](docs/composing_applications.md)
27
29
  1. [Connection struct](docs/connection_struct.md)
28
30
  1. [Sharing data downstream](docs/connection_struct/sharing_data_downstream.md)
@@ -32,6 +34,7 @@ extension](docs/extensions/rails.md).
32
34
  1. [Plugs](docs/plugs.md)
33
35
  1. [Config](docs/plugs/config.md)
34
36
  1. [ContentType](docs/plugs/content_type.md)
37
+ 1. [Testing](docs/testing.md)
35
38
  1. [Extensions](docs/extensions.md)
36
39
  1. [Container](docs/extensions/container.md)
37
40
  1. [Cookies](docs/extensions/cookies.md)
@@ -0,0 +1,25 @@
1
+ # Inspecting operations
2
+
3
+ Once a `WebPipe` class is initialized all its operations get resolved. It
4
+ happens because they are whether [resolved](resolving_operations.md) or
5
+ [injected](injecting_operations.md). The final result can be accessed through
6
+ the `#operations` method:
7
+
8
+
9
+ ```ruby
10
+ require 'web_pipe'
11
+ require 'web_pipe/conn_support/builder'
12
+
13
+ class MyApp
14
+ include WebPipe
15
+
16
+ plug(:hello) do |conn|
17
+ conn.set_response_body('Hello world!')
18
+ end
19
+ end
20
+
21
+ app = MyApp.new
22
+ conn = WebPipe::ConnSupport::Builder.call(Rack::MockRequest.env_for)
23
+ new_conn = app.operations[:hello].call(con)
24
+ conn.response_body #=> ['Hello world!']
25
+ ```
data/docs/testing.md ADDED
@@ -0,0 +1,64 @@
1
+ # Testing
2
+
3
+ ## Testing the rack application
4
+
5
+ A `WebPipe` instance is a just a rack application, so you can test it as such:
6
+
7
+ ```ruby
8
+ require 'web_pipe'
9
+ require 'rack/mock'
10
+ require 'rspec'
11
+
12
+ class MyApp
13
+ include WebPipe
14
+
15
+ plug :response
16
+
17
+ private
18
+
19
+ def response(conn)
20
+ conn
21
+ .set_response_body('Hello!')
22
+ .set_status(200)
23
+ end
24
+ end
25
+
26
+ RSpec.describe MyApp do
27
+ it 'responds with 200 status code' do
28
+ env = Rack::MockRequest.env_for
29
+
30
+ status, _headers, _body = described_class.new.call(env)
31
+
32
+ expect(status).to be(200)
33
+ end
34
+ end
35
+ ```
36
+
37
+ ## Testing individual operations
38
+
39
+ Each operation in a pipe is an isolated function that takes a connection struct
40
+ as argument. You can leverage [the inspection of
41
+ operations](docs/plugging_operations/inspecting_operations.md) to unit test them.
42
+
43
+ There's also a `WebPipe::TestSupport` module that you can include to get a
44
+ helper method `#build_conn` to easily create a connection struct.
45
+
46
+ ```ruby
47
+ RSpec.describe MyApp do
48
+ include WebPipe::TestSupport
49
+
50
+ describe '#response' do
51
+ it 'responds with 200 status code' do
52
+ conn = build_conn
53
+ operation = described_class.new.operations[:response]
54
+
55
+ new_conn = operation.call(conn)
56
+
57
+ expect(new_conn.status).to be(200)
58
+ end
59
+ end
60
+ end
61
+ ```
62
+
63
+ Check the API documentation for the options you can provide to
64
+ [`#build_conn`](https://www.rubydoc.info/github/waiting-for-dev/web_pipe/master/WebPipe/TestSupport#build_conn).
@@ -0,0 +1,34 @@
1
+ # Inspecting middlewares
2
+
3
+ Once a `WebPipe` class is initialized all its middlewares get resolved. They
4
+ can be accessed through the `#middlewares` method.
5
+
6
+ Each middleware is represented by a
7
+ `WebPipe::RackSupport::MiddlewareSpecification` instance, which contains two
8
+ accessors: `middleware` returns the middleware class, while `options` returns
9
+ an array with the arguments that are provided to the middleware on initialization.
10
+
11
+ Kepp in mind that every middleware is resolved as an array. This is because it
12
+ can in fact be composed by an chain of middlewares built through
13
+ [composition](composing_middlewares.md).
14
+
15
+
16
+ ```ruby
17
+ require 'web_pipe'
18
+ require 'rack/session'
19
+
20
+ class MyApp
21
+ include WebPipe
22
+
23
+ use :session, Rack::Session::Cookie, key: 'my_app.session', secret: 'long'
24
+
25
+ plug(:hello) do |conn|
26
+ conn.set_response_body('Hello world!')
27
+ end
28
+ end
29
+
30
+ app = MyApp.new
31
+ session_middleware = app.middlewares[:session][0]
32
+ session_middleware.middleware # => Rack::Session::Cookie
33
+ session_middleware.options # => [{ key: 'my_app.session', secret: 'long' }]
34
+ ```
@@ -42,10 +42,10 @@ module WebPipe
42
42
  # @return [RackSupport::AppWithMiddlewares[]]
43
43
  attr_reader :rack_app
44
44
 
45
- # @return [ConnSupport::Composition::Operation[]]
45
+ # @return [Hash<Plug::Name[], ConnSupport::Composition::Operation[]>]
46
46
  attr_reader :operations
47
47
 
48
- # @return [Array<RackSupport::Middlewares>]
48
+ # @return [Hash<RackSupport::MiddlewareSpecification::Name[], Array<RackSupport::Middlewares>]
49
49
  attr_reader :middlewares
50
50
 
51
51
  # rubocop:disable Metrics/AbcSize
@@ -58,8 +58,8 @@ module WebPipe
58
58
  @operations = Plug.inject_and_resolve(
59
59
  self.class.plugs, injections[:plugs], container, self
60
60
  )
61
- app = App.new(operations)
62
- @rack_app = RackSupport::AppWithMiddlewares.new(middlewares, app)
61
+ app = App.new(operations.values)
62
+ @rack_app = RackSupport::AppWithMiddlewares.new(middlewares.values.flatten, app)
63
63
  end
64
64
  # rubocop:enable Metrics/AbcSize
65
65
 
@@ -105,7 +105,7 @@ module WebPipe
105
105
  # @see ConnSupport::Composition
106
106
  def to_proc
107
107
  ConnSupport::Composition
108
- .new(operations)
108
+ .new(operations.values)
109
109
  .method(:call)
110
110
  .to_proc
111
111
  end
data/lib/web_pipe/plug.rb CHANGED
@@ -97,15 +97,26 @@ module WebPipe
97
97
  # @container container [Types::Container[]]
98
98
  # @object [Object]
99
99
  #
100
- # @return [Array<ConnSupport::Composition::Operation[]>]
100
+ # @return [Hash<Name[], ConnSupport::Composition::Operation[]>]
101
101
  def self.inject_and_resolve(plugs, injections, container, object)
102
- plugs.map do |plug|
103
- if injections.key?(plug.name)
104
- plug.with(injections[plug.name])
102
+ Hash[
103
+ plugs.map do |plug|
104
+ inject_and_resolve_plug(plug, injections, container, object)
105
+ end
106
+ ]
107
+ end
108
+
109
+ def self.inject_and_resolve_plug(plug, injections, container, object)
110
+ name = plug.name
111
+ [
112
+ name,
113
+ if injections.key?(name)
114
+ plug.with(injections[name])
105
115
  else
106
116
  plug
107
117
  end.call(container, object)
108
- end
118
+ ]
109
119
  end
120
+ private_class_method :inject_and_resolve_plug
110
121
  end
111
122
  end
@@ -15,8 +15,6 @@ module WebPipe
15
15
  # - A single element array where it is an instance of a class
16
16
  # including {WebPipe}. This specifies all {RackSupport::Middlewares} for
17
17
  # that {WebPipe}.
18
- #
19
- # @api private
20
18
  class MiddlewareSpecification < Dry::Struct
21
19
  # Type for the name given to a middleware.
22
20
  Name = Types::Strict::Symbol.constructor(&:to_sym)
@@ -44,16 +42,27 @@ module WebPipe
44
42
  # @param middleware_specifications [Array<MiddlewareSpecification>]
45
43
  # @param injections [Injections[]]
46
44
  #
47
- # @return [Array<RackSupport::Middleware>]
45
+ # @return [Hash<Name[], Array<RackSupport::Middleware>]
48
46
  def self.inject_and_resolve(middleware_specifications, injections)
49
- middleware_specifications.map do |spec|
50
- if injections.key?(spec.name)
51
- spec.with(injections[spec.name])
47
+ Hash[
48
+ middleware_specifications.map do |middleware_spec|
49
+ inject_and_resolve_middleware(middleware_spec, injections)
50
+ end
51
+ ]
52
+ end
53
+
54
+ def self.inject_and_resolve_middleware(middleware_spec, injections)
55
+ name = middleware_spec.name
56
+ [
57
+ name,
58
+ if injections.key?(name)
59
+ middleware_spec.with(injections[name])
52
60
  else
53
- spec
61
+ middleware_spec
54
62
  end.call
55
- end.flatten
63
+ ]
56
64
  end
65
+ private_class_method :inject_and_resolve_middleware
57
66
 
58
67
  # Resolves {RackSupport::Middlewares} from given specification.
59
68
  #
@@ -63,7 +72,7 @@ module WebPipe
63
72
  options = spec[1..] || Types::EMPTY_ARRAY
64
73
  case klass
65
74
  when WebPipe
66
- klass.middlewares
75
+ klass.middlewares.values
67
76
  when Class
68
77
  [Middleware.new(middleware: klass, options: options)]
69
78
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'web_pipe/conn_support/builder'
4
+ require 'rack/mock'
5
+
6
+ module WebPipe
7
+ # Test helper methods.
8
+ #
9
+ # This module is meant to be included in a test file to provide helper
10
+ # methods.
11
+ module TestSupport
12
+ # Builds a {WebPipe::Conn}
13
+ #
14
+ # @param uri [String] URI that will be used to populate the request
15
+ # attributes
16
+ # @param attributes [Hash<Symbol, Any>] Manually set attributes for the
17
+ # struct. It overrides what is taken from the `uri` parameter
18
+ # @param env_opts [Hash] Options to be added to the `env` from which the
19
+ # connection struct is created. See {Rack::MockRequest.env_for}.
20
+ # @return [Conn]
21
+ def build_conn(uri = '', attributes: {}, env_opts: {})
22
+ env = Rack::MockRequest.env_for(uri, env_opts)
23
+ ConnSupport::Builder
24
+ .call(env)
25
+ .new(attributes)
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebPipe
4
- VERSION = '0.13.0'
4
+ VERSION = '0.14.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_pipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Busqué
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-15 00:00:00.000000000 Z
11
+ date: 2021-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-monads
@@ -289,6 +289,7 @@ files:
289
289
  - docs/plugging_operations.md
290
290
  - docs/plugging_operations/composing_operations.md
291
291
  - docs/plugging_operations/injecting_operations.md
292
+ - docs/plugging_operations/inspecting_operations.md
292
293
  - docs/plugging_operations/resolving_operations.md
293
294
  - docs/plugs.md
294
295
  - docs/plugs/config.md
@@ -296,9 +297,11 @@ files:
296
297
  - docs/recipes/dry_rb_integration.md
297
298
  - docs/recipes/hanami_router_integration.md
298
299
  - docs/recipes/using_all_restful_methods.md
300
+ - docs/testing.md
299
301
  - docs/using_rack_middlewares.md
300
302
  - docs/using_rack_middlewares/composing_middlewares.md
301
303
  - docs/using_rack_middlewares/injecting_middlewares.md
304
+ - docs/using_rack_middlewares/inspecting_middlewares.md
302
305
  - lib/web_pipe.rb
303
306
  - lib/web_pipe/app.rb
304
307
  - lib/web_pipe/conn.rb
@@ -331,6 +334,7 @@ files:
331
334
  - lib/web_pipe/rack_support/app_with_middlewares.rb
332
335
  - lib/web_pipe/rack_support/middleware.rb
333
336
  - lib/web_pipe/rack_support/middleware_specification.rb
337
+ - lib/web_pipe/test_support.rb
334
338
  - lib/web_pipe/types.rb
335
339
  - lib/web_pipe/version.rb
336
340
  - web_pipe.gemspec
@@ -356,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
356
360
  - !ruby/object:Gem::Version
357
361
  version: '0'
358
362
  requirements: []
359
- rubygems_version: 3.2.3
363
+ rubygems_version: 3.1.2
360
364
  signing_key:
361
365
  specification_version: 4
362
366
  summary: Rack application builder through a pipe of operations on an immutable struct.