ElasticEmail 4.2.0 → 4.3.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.
data/docs/WebhookApi.md CHANGED
@@ -7,6 +7,7 @@ All URIs are relative to *https://api.elasticemail.com/v4*
7
7
  | [**webhook_by_publicid_delete**](WebhookApi.md#webhook_by_publicid_delete) | **DELETE** /webhook/{publicid} | Delete Webhook |
8
8
  | [**webhook_by_publicid_get**](WebhookApi.md#webhook_by_publicid_get) | **GET** /webhook/{publicid} | Load Webhook |
9
9
  | [**webhook_by_publicid_put**](WebhookApi.md#webhook_by_publicid_put) | **PUT** /webhook/{publicid} | Update Webhook |
10
+ | [**webhook_by_publicid_secret_rotate_post**](WebhookApi.md#webhook_by_publicid_secret_rotate_post) | **POST** /webhook/{publicid}/secret/rotate | Rotate Webhook Secret |
10
11
  | [**webhook_get**](WebhookApi.md#webhook_get) | **GET** /webhook | Load Webhooks |
11
12
  | [**webhook_post**](WebhookApi.md#webhook_post) | **POST** /webhook | Add Webhook |
12
13
 
@@ -225,6 +226,77 @@ end
225
226
  - **Accept**: application/json
226
227
 
227
228
 
229
+ ## webhook_by_publicid_secret_rotate_post
230
+
231
+ > <Webhook> webhook_by_publicid_secret_rotate_post(publicid)
232
+
233
+ Rotate Webhook Secret
234
+
235
+ Replace the signing secret of a webhook created with signing. The old secret stops being used at once - there is no grace period. The new secret is returned only in this response. Notifications your endpoint rejects while it still has the old secret are retried and signed with the new one. Required Access Level: ModifyWebNotifications
236
+
237
+ ### Examples
238
+
239
+ ```ruby
240
+ require 'time'
241
+ require 'ElasticEmail'
242
+ # setup authorization
243
+ ElasticEmail.configure do |config|
244
+ # Configure API key authorization: apikey
245
+ config.api_key['X-ElasticEmail-ApiKey'] = 'YOUR API KEY'
246
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
247
+ # config.api_key_prefix['X-ElasticEmail-ApiKey'] = 'Bearer'
248
+ end
249
+
250
+ api_instance = ElasticEmail::WebhookApi.new
251
+ publicid = 'publicid_example' # String |
252
+
253
+ begin
254
+ # Rotate Webhook Secret
255
+ result = api_instance.webhook_by_publicid_secret_rotate_post(publicid)
256
+ p result
257
+ rescue ElasticEmail::ApiError => e
258
+ puts "Error when calling WebhookApi->webhook_by_publicid_secret_rotate_post: #{e}"
259
+ end
260
+ ```
261
+
262
+ #### Using the webhook_by_publicid_secret_rotate_post_with_http_info variant
263
+
264
+ This returns an Array which contains the response data, status code and headers.
265
+
266
+ > <Array(<Webhook>, Integer, Hash)> webhook_by_publicid_secret_rotate_post_with_http_info(publicid)
267
+
268
+ ```ruby
269
+ begin
270
+ # Rotate Webhook Secret
271
+ data, status_code, headers = api_instance.webhook_by_publicid_secret_rotate_post_with_http_info(publicid)
272
+ p status_code # => 2xx
273
+ p headers # => { ... }
274
+ p data # => <Webhook>
275
+ rescue ElasticEmail::ApiError => e
276
+ puts "Error when calling WebhookApi->webhook_by_publicid_secret_rotate_post_with_http_info: #{e}"
277
+ end
278
+ ```
279
+
280
+ ### Parameters
281
+
282
+ | Name | Type | Description | Notes |
283
+ | ---- | ---- | ----------- | ----- |
284
+ | **publicid** | **String** | | |
285
+
286
+ ### Return type
287
+
288
+ [**Webhook**](Webhook.md)
289
+
290
+ ### Authorization
291
+
292
+ [apikey](../README.md#apikey)
293
+
294
+ ### HTTP request headers
295
+
296
+ - **Content-Type**: Not defined
297
+ - **Accept**: application/json
298
+
299
+
228
300
  ## webhook_get
229
301
 
230
302
  > <Array<Webhook>> webhook_get(opts)
@@ -13,6 +13,8 @@
13
13
  | **notification_for_unsubscribed** | **Boolean** | | [optional] |
14
14
  | **notification_for_abuse_report** | **Boolean** | | [optional] |
15
15
  | **notification_for_error** | **Boolean** | | [optional] |
16
+ | **enable_signing** | **Boolean** | Sign every request with HMAC-SHA256. Can be set only when the webhook is created. Default: false. | [optional] |
17
+ | **delivery_method** | [**WebhookDeliveryMethod**](WebhookDeliveryMethod.md) | | [optional][default to &#39;Get&#39;] |
16
18
 
17
19
  ## Example
18
20
 
@@ -28,7 +30,9 @@ instance = ElasticEmail::WebhookCreatePayload.new(
28
30
  notification_for_clicked: null,
29
31
  notification_for_unsubscribed: null,
30
32
  notification_for_abuse_report: null,
31
- notification_for_error: null
33
+ notification_for_error: null,
34
+ enable_signing: null,
35
+ delivery_method: null
32
36
  )
33
37
  ```
34
38
 
@@ -0,0 +1,15 @@
1
+ # ElasticEmail::WebhookDeliveryMethod
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+
8
+ ## Example
9
+
10
+ ```ruby
11
+ require 'ElasticEmail'
12
+
13
+ instance = ElasticEmail::WebhookDeliveryMethod.new()
14
+ ```
15
+
@@ -217,6 +217,69 @@ module ElasticEmail
217
217
  return data, status_code, headers
218
218
  end
219
219
 
220
+ # Rotate Webhook Secret
221
+ # Replace the signing secret of a webhook created with signing. The old secret stops being used at once - there is no grace period. The new secret is returned only in this response. Notifications your endpoint rejects while it still has the old secret are retried and signed with the new one. Required Access Level: ModifyWebNotifications
222
+ # @param publicid [String]
223
+ # @param [Hash] opts the optional parameters
224
+ # @return [Webhook]
225
+ def webhook_by_publicid_secret_rotate_post(publicid, opts = {})
226
+ data, _status_code, _headers = webhook_by_publicid_secret_rotate_post_with_http_info(publicid, opts)
227
+ data
228
+ end
229
+
230
+ # Rotate Webhook Secret
231
+ # Replace the signing secret of a webhook created with signing. The old secret stops being used at once - there is no grace period. The new secret is returned only in this response. Notifications your endpoint rejects while it still has the old secret are retried and signed with the new one. Required Access Level: ModifyWebNotifications
232
+ # @param publicid [String]
233
+ # @param [Hash] opts the optional parameters
234
+ # @return [Array<(Webhook, Integer, Hash)>] Webhook data, response status code and response headers
235
+ def webhook_by_publicid_secret_rotate_post_with_http_info(publicid, opts = {})
236
+ if @api_client.config.debugging
237
+ @api_client.config.logger.debug 'Calling API: WebhookApi.webhook_by_publicid_secret_rotate_post ...'
238
+ end
239
+ # verify the required parameter 'publicid' is set
240
+ if @api_client.config.client_side_validation && publicid.nil?
241
+ fail ArgumentError, "Missing the required parameter 'publicid' when calling WebhookApi.webhook_by_publicid_secret_rotate_post"
242
+ end
243
+ # resource path
244
+ local_var_path = '/webhook/{publicid}/secret/rotate'.sub('{' + 'publicid' + '}', CGI.escape(publicid.to_s))
245
+
246
+ # query parameters
247
+ query_params = opts[:query_params] || {}
248
+
249
+ # header parameters
250
+ header_params = opts[:header_params] || {}
251
+ # HTTP header 'Accept' (if needed)
252
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
253
+
254
+ # form parameters
255
+ form_params = opts[:form_params] || {}
256
+
257
+ # http body (model)
258
+ post_body = opts[:debug_body]
259
+
260
+ # return_type
261
+ return_type = opts[:debug_return_type] || 'Webhook'
262
+
263
+ # auth_names
264
+ auth_names = opts[:debug_auth_names] || ['apikey']
265
+
266
+ new_options = opts.merge(
267
+ :operation => :"WebhookApi.webhook_by_publicid_secret_rotate_post",
268
+ :header_params => header_params,
269
+ :query_params => query_params,
270
+ :form_params => form_params,
271
+ :body => post_body,
272
+ :auth_names => auth_names,
273
+ :return_type => return_type
274
+ )
275
+
276
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
277
+ if @api_client.config.debugging
278
+ @api_client.config.logger.debug "API called: WebhookApi#webhook_by_publicid_secret_rotate_post\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
279
+ end
280
+ return data, status_code, headers
281
+ end
282
+
220
283
  # Load Webhooks
221
284
  # Returns a list of notification webhooks. Required Access Level: ViewWebNotifications
222
285
  # @param [Hash] opts the optional parameters
@@ -47,6 +47,36 @@ module ElasticEmail
47
47
 
48
48
  attr_accessor :is_enabled
49
49
 
50
+ # Requests carry an HMAC-SHA256 signature. Chosen when the webhook is created and can't be changed.
51
+ attr_accessor :signing_enabled
52
+
53
+ attr_accessor :delivery_method
54
+
55
+ # Signing secret - returned only once, when a webhook is created with signing or its secret is rotated. Store it safely.
56
+ attr_accessor :signing_secret
57
+
58
+ class EnumAttributeValidator
59
+ attr_reader :datatype
60
+ attr_reader :allowable_values
61
+
62
+ def initialize(datatype, allowable_values)
63
+ @allowable_values = allowable_values.map do |value|
64
+ case datatype.to_s
65
+ when /Integer/i
66
+ value.to_i
67
+ when /Float/i
68
+ value.to_f
69
+ else
70
+ value
71
+ end
72
+ end
73
+ end
74
+
75
+ def valid?(value)
76
+ !value || allowable_values.include?(value)
77
+ end
78
+ end
79
+
50
80
  # Attribute mapping from ruby-style variable name to JSON key.
51
81
  def self.attribute_map
52
82
  {
@@ -62,7 +92,10 @@ module ElasticEmail
62
92
  :'notification_for_unsubscribed' => :'NotificationForUnsubscribed',
63
93
  :'notification_for_abuse_report' => :'NotificationForAbuseReport',
64
94
  :'notification_for_error' => :'NotificationForError',
65
- :'is_enabled' => :'IsEnabled'
95
+ :'is_enabled' => :'IsEnabled',
96
+ :'signing_enabled' => :'SigningEnabled',
97
+ :'delivery_method' => :'DeliveryMethod',
98
+ :'signing_secret' => :'SigningSecret'
66
99
  }
67
100
  end
68
101
 
@@ -86,7 +119,10 @@ module ElasticEmail
86
119
  :'notification_for_unsubscribed' => :'Boolean',
87
120
  :'notification_for_abuse_report' => :'Boolean',
88
121
  :'notification_for_error' => :'Boolean',
89
- :'is_enabled' => :'Boolean'
122
+ :'is_enabled' => :'Boolean',
123
+ :'signing_enabled' => :'Boolean',
124
+ :'delivery_method' => :'WebhookDeliveryMethod',
125
+ :'signing_secret' => :'String'
90
126
  }
91
127
  end
92
128
 
@@ -164,6 +200,20 @@ module ElasticEmail
164
200
  if attributes.key?(:'is_enabled')
165
201
  self.is_enabled = attributes[:'is_enabled']
166
202
  end
203
+
204
+ if attributes.key?(:'signing_enabled')
205
+ self.signing_enabled = attributes[:'signing_enabled']
206
+ end
207
+
208
+ if attributes.key?(:'delivery_method')
209
+ self.delivery_method = attributes[:'delivery_method']
210
+ else
211
+ self.delivery_method = 'Get'
212
+ end
213
+
214
+ if attributes.key?(:'signing_secret')
215
+ self.signing_secret = attributes[:'signing_secret']
216
+ end
167
217
  end
168
218
 
169
219
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -198,7 +248,10 @@ module ElasticEmail
198
248
  notification_for_unsubscribed == o.notification_for_unsubscribed &&
199
249
  notification_for_abuse_report == o.notification_for_abuse_report &&
200
250
  notification_for_error == o.notification_for_error &&
201
- is_enabled == o.is_enabled
251
+ is_enabled == o.is_enabled &&
252
+ signing_enabled == o.signing_enabled &&
253
+ delivery_method == o.delivery_method &&
254
+ signing_secret == o.signing_secret
202
255
  end
203
256
 
204
257
  # @see the `==` method
@@ -210,7 +263,7 @@ module ElasticEmail
210
263
  # Calculates hash code according to all attributes.
211
264
  # @return [Integer] Hash code
212
265
  def hash
213
- [webhook_id, name, date_created, date_updated, url, notify_once_per_email, notification_for_sent, notification_for_opened, notification_for_clicked, notification_for_unsubscribed, notification_for_abuse_report, notification_for_error, is_enabled].hash
266
+ [webhook_id, name, date_created, date_updated, url, notify_once_per_email, notification_for_sent, notification_for_opened, notification_for_clicked, notification_for_unsubscribed, notification_for_abuse_report, notification_for_error, is_enabled, signing_enabled, delivery_method, signing_secret].hash
214
267
  end
215
268
 
216
269
  # Builds the object from hash
@@ -36,6 +36,33 @@ module ElasticEmail
36
36
 
37
37
  attr_accessor :notification_for_error
38
38
 
39
+ # Sign every request with HMAC-SHA256. Can be set only when the webhook is created. Default: false.
40
+ attr_accessor :enable_signing
41
+
42
+ attr_accessor :delivery_method
43
+
44
+ class EnumAttributeValidator
45
+ attr_reader :datatype
46
+ attr_reader :allowable_values
47
+
48
+ def initialize(datatype, allowable_values)
49
+ @allowable_values = allowable_values.map do |value|
50
+ case datatype.to_s
51
+ when /Integer/i
52
+ value.to_i
53
+ when /Float/i
54
+ value.to_f
55
+ else
56
+ value
57
+ end
58
+ end
59
+ end
60
+
61
+ def valid?(value)
62
+ !value || allowable_values.include?(value)
63
+ end
64
+ end
65
+
39
66
  # Attribute mapping from ruby-style variable name to JSON key.
40
67
  def self.attribute_map
41
68
  {
@@ -47,7 +74,9 @@ module ElasticEmail
47
74
  :'notification_for_clicked' => :'NotificationForClicked',
48
75
  :'notification_for_unsubscribed' => :'NotificationForUnsubscribed',
49
76
  :'notification_for_abuse_report' => :'NotificationForAbuseReport',
50
- :'notification_for_error' => :'NotificationForError'
77
+ :'notification_for_error' => :'NotificationForError',
78
+ :'enable_signing' => :'EnableSigning',
79
+ :'delivery_method' => :'DeliveryMethod'
51
80
  }
52
81
  end
53
82
 
@@ -67,13 +96,16 @@ module ElasticEmail
67
96
  :'notification_for_clicked' => :'Boolean',
68
97
  :'notification_for_unsubscribed' => :'Boolean',
69
98
  :'notification_for_abuse_report' => :'Boolean',
70
- :'notification_for_error' => :'Boolean'
99
+ :'notification_for_error' => :'Boolean',
100
+ :'enable_signing' => :'Boolean',
101
+ :'delivery_method' => :'WebhookDeliveryMethod'
71
102
  }
72
103
  end
73
104
 
74
105
  # List of attributes with nullable: true
75
106
  def self.openapi_nullable
76
107
  Set.new([
108
+ :'enable_signing',
77
109
  ])
78
110
  end
79
111
 
@@ -131,6 +163,16 @@ module ElasticEmail
131
163
  if attributes.key?(:'notification_for_error')
132
164
  self.notification_for_error = attributes[:'notification_for_error']
133
165
  end
166
+
167
+ if attributes.key?(:'enable_signing')
168
+ self.enable_signing = attributes[:'enable_signing']
169
+ end
170
+
171
+ if attributes.key?(:'delivery_method')
172
+ self.delivery_method = attributes[:'delivery_method']
173
+ else
174
+ self.delivery_method = 'Get'
175
+ end
134
176
  end
135
177
 
136
178
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -171,7 +213,9 @@ module ElasticEmail
171
213
  notification_for_clicked == o.notification_for_clicked &&
172
214
  notification_for_unsubscribed == o.notification_for_unsubscribed &&
173
215
  notification_for_abuse_report == o.notification_for_abuse_report &&
174
- notification_for_error == o.notification_for_error
216
+ notification_for_error == o.notification_for_error &&
217
+ enable_signing == o.enable_signing &&
218
+ delivery_method == o.delivery_method
175
219
  end
176
220
 
177
221
  # @see the `==` method
@@ -183,7 +227,7 @@ module ElasticEmail
183
227
  # Calculates hash code according to all attributes.
184
228
  # @return [Integer] Hash code
185
229
  def hash
186
- [name, url, notify_once_per_email, notification_for_sent, notification_for_opened, notification_for_clicked, notification_for_unsubscribed, notification_for_abuse_report, notification_for_error].hash
230
+ [name, url, notify_once_per_email, notification_for_sent, notification_for_opened, notification_for_clicked, notification_for_unsubscribed, notification_for_abuse_report, notification_for_error, enable_signing, delivery_method].hash
187
231
  end
188
232
 
189
233
  # Builds the object from hash
@@ -0,0 +1,40 @@
1
+ =begin
2
+ #Elastic Email REST API
3
+
4
+ #This API is based on the REST API architecture, allowing the user to easily manage their data with this resource-based approach. Every API call is established on which specific request type (GET, POST, PUT, DELETE) will be used. The API has a limit of 20 concurrent connections and a hard timeout of 600 seconds per request. To start using this API, you will need your Access Token (available <a target='_blank' href='https://app.elasticemail.com/marketing/settings/new/manage-api'>here</a>). Remember to keep it safe. Required access levels are listed in the given request’s description. Downloadable library clients can be found in our Github repository <a target='_blank' href='https://github.com/ElasticEmail?tab=repositories&q=%22rest+api%22+in%3Areadme'>here</a>
5
+
6
+ The version of the OpenAPI document: 4.0.0
7
+ Contact: support@elasticemail.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.11.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module ElasticEmail
17
+ class WebhookDeliveryMethod
18
+ GET = "Get".freeze
19
+ POST_JSON = "PostJson".freeze
20
+
21
+ def self.all_vars
22
+ @all_vars ||= [GET, POST_JSON].freeze
23
+ end
24
+
25
+ # Builds the enum from string
26
+ # @param [String] The enum value in the form of the string
27
+ # @return [String] The enum value
28
+ def self.build_from_hash(value)
29
+ new.build_from_hash(value)
30
+ end
31
+
32
+ # Builds the enum from string
33
+ # @param [String] The enum value in the form of the string
34
+ # @return [String] The enum value
35
+ def build_from_hash(value)
36
+ return value if WebhookDeliveryMethod.all_vars.include?(value)
37
+ raise "Invalid ENUM value #{value} for class #WebhookDeliveryMethod"
38
+ end
39
+ end
40
+ end
@@ -11,5 +11,5 @@ Generator version: 7.11.0
11
11
  =end
12
12
 
13
13
  module ElasticEmail
14
- VERSION = '4.2.0'
14
+ VERSION = '4.3.0'
15
15
  end
data/lib/ElasticEmail.rb CHANGED
@@ -114,6 +114,7 @@ require 'ElasticEmail/models/verification_file_result_details'
114
114
  require 'ElasticEmail/models/verification_status'
115
115
  require 'ElasticEmail/models/webhook'
116
116
  require 'ElasticEmail/models/webhook_create_payload'
117
+ require 'ElasticEmail/models/webhook_delivery_method'
117
118
  require 'ElasticEmail/models/webhook_update_payload'
118
119
 
119
120
  # APIs
@@ -69,6 +69,18 @@ describe 'WebhookApi' do
69
69
  end
70
70
  end
71
71
 
72
+ # unit tests for webhook_by_publicid_secret_rotate_post
73
+ # Rotate Webhook Secret
74
+ # Replace the signing secret of a webhook created with signing. The old secret stops being used at once - there is no grace period. The new secret is returned only in this response. Notifications your endpoint rejects while it still has the old secret are retried and signed with the new one. Required Access Level: ModifyWebNotifications
75
+ # @param publicid
76
+ # @param [Hash] opts the optional parameters
77
+ # @return [Webhook]
78
+ describe 'webhook_by_publicid_secret_rotate_post test' do
79
+ it 'should work' do
80
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
81
+ end
82
+ end
83
+
72
84
  # unit tests for webhook_get
73
85
  # Load Webhooks
74
86
  # Returns a list of notification webhooks. Required Access Level: ViewWebNotifications
@@ -81,4 +81,16 @@ describe ElasticEmail::WebhookCreatePayload do
81
81
  end
82
82
  end
83
83
 
84
+ describe 'test attribute "enable_signing"' do
85
+ it 'should work' do
86
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
87
+ end
88
+ end
89
+
90
+ describe 'test attribute "delivery_method"' do
91
+ it 'should work' do
92
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
93
+ end
94
+ end
95
+
84
96
  end
@@ -0,0 +1,30 @@
1
+ =begin
2
+ #Elastic Email REST API
3
+
4
+ #This API is based on the REST API architecture, allowing the user to easily manage their data with this resource-based approach. Every API call is established on which specific request type (GET, POST, PUT, DELETE) will be used. The API has a limit of 20 concurrent connections and a hard timeout of 600 seconds per request. To start using this API, you will need your Access Token (available <a target='_blank' href='https://app.elasticemail.com/marketing/settings/new/manage-api'>here</a>). Remember to keep it safe. Required access levels are listed in the given request’s description. Downloadable library clients can be found in our Github repository <a target='_blank' href='https://github.com/ElasticEmail?tab=repositories&q=%22rest+api%22+in%3Areadme'>here</a>
5
+
6
+ The version of the OpenAPI document: 4.0.0
7
+ Contact: support@elasticemail.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.11.0
10
+
11
+ =end
12
+
13
+ require 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for ElasticEmail::WebhookDeliveryMethod
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe ElasticEmail::WebhookDeliveryMethod do
21
+ let(:instance) { ElasticEmail::WebhookDeliveryMethod.new }
22
+
23
+ describe 'test an instance of WebhookDeliveryMethod' do
24
+ it 'should create an instance of WebhookDeliveryMethod' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(ElasticEmail::WebhookDeliveryMethod)
27
+ end
28
+ end
29
+
30
+ end
@@ -105,4 +105,22 @@ describe ElasticEmail::Webhook do
105
105
  end
106
106
  end
107
107
 
108
+ describe 'test attribute "signing_enabled"' do
109
+ it 'should work' do
110
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
111
+ end
112
+ end
113
+
114
+ describe 'test attribute "delivery_method"' do
115
+ it 'should work' do
116
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
117
+ end
118
+ end
119
+
120
+ describe 'test attribute "signing_secret"' do
121
+ it 'should work' do
122
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
123
+ end
124
+ end
125
+
108
126
  end