web_pipe 0.13.0 → 0.14.0

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.
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.