nrser 0.0.26 → 0.0.27
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 +4 -4
- data/lib/nrser.rb +1 -0
- data/lib/nrser/array.rb +15 -0
- data/lib/nrser/binding.rb +7 -1
- data/lib/nrser/enumerable.rb +21 -1
- data/lib/nrser/errors.rb +56 -6
- data/lib/nrser/hash/deep_merge.rb +1 -1
- data/lib/nrser/message.rb +33 -0
- data/lib/nrser/meta/props.rb +77 -15
- data/lib/nrser/meta/props/prop.rb +276 -44
- data/lib/nrser/proc.rb +7 -3
- data/lib/nrser/refinements/array.rb +5 -0
- data/lib/nrser/refinements/enumerable.rb +5 -0
- data/lib/nrser/refinements/hash.rb +8 -0
- data/lib/nrser/refinements/object.rb +11 -1
- data/lib/nrser/refinements/string.rb +17 -3
- data/lib/nrser/refinements/symbol.rb +8 -0
- data/lib/nrser/refinements/tree.rb +22 -0
- data/lib/nrser/rspex.rb +312 -70
- data/lib/nrser/rspex/shared_examples.rb +116 -0
- data/lib/nrser/string.rb +159 -27
- data/lib/nrser/temp/unicode_math.rb +48 -0
- data/lib/nrser/text.rb +3 -0
- data/lib/nrser/text/indentation.rb +210 -0
- data/lib/nrser/text/lines.rb +52 -0
- data/lib/nrser/text/word_wrap.rb +29 -0
- data/lib/nrser/tree.rb +4 -78
- data/lib/nrser/tree/each_branch.rb +76 -0
- data/lib/nrser/tree/map_branches.rb +91 -0
- data/lib/nrser/tree/map_tree.rb +97 -0
- data/lib/nrser/tree/transform.rb +56 -13
- data/lib/nrser/types.rb +1 -0
- data/lib/nrser/types/array.rb +15 -3
- data/lib/nrser/types/is_a.rb +40 -1
- data/lib/nrser/types/nil.rb +17 -0
- data/lib/nrser/types/paths.rb +17 -2
- data/lib/nrser/types/strings.rb +57 -22
- data/lib/nrser/types/tuples.rb +5 -0
- data/lib/nrser/types/type.rb +47 -6
- data/lib/nrser/version.rb +1 -1
- data/spec/nrser/errors/abstract_method_error_spec.rb +46 -0
- data/spec/nrser/meta/props/to_and_from_data_spec.rb +74 -0
- data/spec/nrser/meta/props_spec.rb +6 -2
- data/spec/nrser/refinements/erb_spec.rb +100 -1
- data/spec/nrser/{common_prefix_spec.rb → string/common_prefix_spec.rb} +9 -0
- data/spec/nrser/text/dedent_spec.rb +80 -0
- data/spec/nrser/tree/map_branch_spec.rb +83 -0
- data/spec/nrser/tree/map_tree_spec.rb +123 -0
- data/spec/nrser/tree/transform_spec.rb +26 -29
- data/spec/nrser/tree/transformer_spec.rb +179 -0
- data/spec/nrser/types/paths_spec.rb +73 -45
- data/spec/spec_helper.rb +10 -0
- metadata +27 -7
- data/spec/nrser/dedent_spec.rb +0 -36
data/lib/nrser/proc.rb
CHANGED
@@ -31,8 +31,12 @@ module NRSER
|
|
31
31
|
#
|
32
32
|
# @return [NRSER::Message]
|
33
33
|
#
|
34
|
-
def self.message
|
35
|
-
|
34
|
+
def self.message *args, &block
|
35
|
+
if args.length == 1 && args[0].is_a?( Message )
|
36
|
+
args[0]
|
37
|
+
else
|
38
|
+
Message.new *args, &block
|
39
|
+
end
|
36
40
|
end # #message
|
37
41
|
|
38
42
|
singleton_class.send :alias_method, :msg, :message
|
@@ -102,7 +106,7 @@ module NRSER
|
|
102
106
|
# @return [Proc]
|
103
107
|
#
|
104
108
|
def self.chainer mappable, publicly: true
|
105
|
-
messages = mappable.map { |value|
|
109
|
+
messages = mappable.map { |value| message *value }
|
106
110
|
|
107
111
|
->( receiver ) {
|
108
112
|
messages.reduce( receiver ) { |receiver, message|
|
@@ -58,24 +58,32 @@ module NRSER
|
|
58
58
|
NRSER.symbolize_keys! self
|
59
59
|
end
|
60
60
|
|
61
|
+
alias_method :sym_keys!, :symbolize_keys!
|
62
|
+
|
61
63
|
|
62
64
|
# See {NRSER.symbolize_keys}
|
63
65
|
def symbolize_keys
|
64
66
|
NRSER.symbolize_keys self
|
65
67
|
end
|
66
68
|
|
69
|
+
alias_method :sym_keys, :symbolize_keys
|
70
|
+
|
67
71
|
|
68
72
|
# See {NRSER.stringify_keys!}
|
69
73
|
def stringify_keys!
|
70
74
|
NRSER.stringify_keys! self
|
71
75
|
end
|
72
76
|
|
77
|
+
alias_method :str_keys!, :stringify_keys!
|
78
|
+
|
73
79
|
|
74
80
|
# See {NRSER.stringify_keys}
|
75
81
|
def stringify_keys
|
76
82
|
NRSER.stringify_keys self
|
77
83
|
end
|
78
84
|
|
85
|
+
alias_method :str_keys, :stringify_keys
|
86
|
+
|
79
87
|
|
80
88
|
# See {NRSER.map_hash_keys}
|
81
89
|
def map_keys &block
|
@@ -19,10 +19,20 @@ module NRSER
|
|
19
19
|
refine Object do
|
20
20
|
# Yield `self`. Analogous to {#tap} but returns the result of the invoked
|
21
21
|
# block.
|
22
|
-
def
|
22
|
+
def thru
|
23
23
|
yield self
|
24
24
|
end
|
25
25
|
|
26
|
+
# Older name, depreciated because though 'pipe' was the natural name to me,
|
27
|
+
# it was probably a poor choice... it's widely used and usually denotes
|
28
|
+
# streaming of some sort (and rightfully so given Unix pipes).
|
29
|
+
#
|
30
|
+
# I think I want to move over to {Object#thru}, but will leave the old
|
31
|
+
# name for the moment.
|
32
|
+
#
|
33
|
+
alias_method :pipe, :thru
|
34
|
+
|
35
|
+
|
26
36
|
# See {NRSER.truthy?}.
|
27
37
|
def truthy?
|
28
38
|
NRSER.truthy? self
|
@@ -1,27 +1,35 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
|
+
require 'nrser/string'
|
4
|
+
require 'nrser/text'
|
5
|
+
|
3
6
|
module NRSER
|
4
7
|
refine String do
|
5
8
|
def squish
|
6
9
|
NRSER.squish self
|
7
10
|
end
|
8
11
|
|
12
|
+
|
9
13
|
def unblock
|
10
14
|
NRSER.unblock self
|
11
15
|
end
|
12
|
-
|
16
|
+
|
17
|
+
|
13
18
|
def dedent
|
14
19
|
NRSER.dedent self
|
15
20
|
end
|
16
|
-
|
21
|
+
|
22
|
+
|
17
23
|
def indent *args
|
18
24
|
NRSER.indent self, *args
|
19
25
|
end
|
20
|
-
|
26
|
+
|
27
|
+
|
21
28
|
def truncate *args
|
22
29
|
NRSER.truncate self, *args
|
23
30
|
end
|
24
31
|
|
32
|
+
|
25
33
|
# See {NRSER.constantize}
|
26
34
|
def constantize
|
27
35
|
NRSER.constantize self
|
@@ -29,6 +37,7 @@ module NRSER
|
|
29
37
|
|
30
38
|
alias_method :to_const, :constantize
|
31
39
|
|
40
|
+
|
32
41
|
# @return [Pathname]
|
33
42
|
# Convert self into a {Pathname}
|
34
43
|
#
|
@@ -36,5 +45,10 @@ module NRSER
|
|
36
45
|
Pathname.new self
|
37
46
|
end
|
38
47
|
|
48
|
+
|
49
|
+
def whitespace?
|
50
|
+
NRSER.whitespace? self
|
51
|
+
end
|
52
|
+
|
39
53
|
end # refine String
|
40
54
|
end # NRSER
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module NRSER
|
2
2
|
refine ::Symbol do
|
3
3
|
|
4
|
+
# See {NRSER.retriever}.
|
4
5
|
def to_retriever
|
5
6
|
NRSER.retriever self
|
6
7
|
end
|
@@ -8,5 +9,12 @@ module NRSER
|
|
8
9
|
alias_method :retriever, :to_retriever
|
9
10
|
alias_method :rtvr, :to_retriever
|
10
11
|
|
12
|
+
|
13
|
+
# Alias 'sender' methods to built-in {#to_proc} so symbols can behave like
|
14
|
+
# arrays in this way
|
15
|
+
alias_method :to_sender, :to_proc
|
16
|
+
alias_method :sender, :to_sender
|
17
|
+
alias_method :sndr, :to_sender
|
18
|
+
|
11
19
|
end # refine ::Symbol
|
12
20
|
end # NRSER
|
@@ -32,10 +32,32 @@ module NRSER::Refinements::Tree
|
|
32
32
|
end # #leaves
|
33
33
|
|
34
34
|
|
35
|
+
# Calls {NRSER.map_leaves} on `self` with `&block`.
|
36
|
+
#
|
37
|
+
def map_leaves &block
|
38
|
+
NRSER.map_leaves self, &block
|
39
|
+
end
|
40
|
+
|
41
|
+
|
35
42
|
# Sends `self` and the optional `block` to {NRSER.each_branch}.
|
43
|
+
#
|
36
44
|
def each_branch &block
|
37
45
|
NRSER.each_branch self, &block
|
38
46
|
end
|
39
47
|
|
48
|
+
|
49
|
+
# Calls {NRSER.map_branches} on `self` with `&block`.
|
50
|
+
#
|
51
|
+
def map_branches &block
|
52
|
+
NRSER.map_branches self, &block
|
53
|
+
end # #map_branches
|
54
|
+
|
55
|
+
|
56
|
+
# Calls {NRSER.map_tree} on `self` with `&block`.
|
57
|
+
#
|
58
|
+
def map_tree **options, &block
|
59
|
+
NRSER.map_tree self, **options, &block
|
60
|
+
end
|
61
|
+
|
40
62
|
end # module NRSER::Refinements::Tree
|
41
63
|
|
data/lib/nrser/rspex.rb
CHANGED
@@ -22,7 +22,8 @@
|
|
22
22
|
|
23
23
|
# Project / Package
|
24
24
|
# -----------------------------------------------------------------------
|
25
|
-
|
25
|
+
require 'nrser/message'
|
26
|
+
require 'nrser/rspex/shared_examples'
|
26
27
|
|
27
28
|
|
28
29
|
# Helpers
|
@@ -83,23 +84,214 @@ def unwrap obj, context: nil
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
87
|
+
|
88
|
+
def List *args
|
89
|
+
NRSER::RSpex::List.new args
|
90
|
+
end
|
91
|
+
|
92
|
+
def Args *args
|
93
|
+
NRSER::RSpex::Args.new args
|
94
|
+
end
|
95
|
+
|
86
96
|
# Extensions
|
87
97
|
# =====================================================================
|
88
98
|
|
89
99
|
module NRSER; end
|
90
100
|
|
91
|
-
module NRSER::RSpex
|
92
|
-
|
93
|
-
|
94
|
-
|
101
|
+
module NRSER::RSpex
|
102
|
+
|
103
|
+
# Constants
|
104
|
+
# =====================================================================
|
105
|
+
|
106
|
+
|
107
|
+
# Symbols
|
108
|
+
# ---------------------------------------------------------------------
|
109
|
+
#
|
110
|
+
# Sources:
|
111
|
+
#
|
112
|
+
# - https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode
|
113
|
+
#
|
114
|
+
|
115
|
+
PREFIXES_BASE = {
|
95
116
|
section: '§',
|
96
|
-
|
117
|
+
group: '•',
|
118
|
+
invocation: '⟮⟯',
|
97
119
|
}
|
98
120
|
|
121
|
+
PREFIXES_MATH_ITALIC = PREFIXES_BASE.merge(
|
122
|
+
module: '𝑀',
|
123
|
+
method: '𝑚',
|
124
|
+
class: '𝐶',
|
125
|
+
attribute: '𝑎',
|
126
|
+
file: '𝐹',
|
127
|
+
)
|
128
|
+
|
129
|
+
PREFIXES_MATH_CURSIVE_WORDS = PREFIXES_BASE.merge(
|
130
|
+
module: '𝓜 𝓸𝓭𝓾𝓵𝓮',
|
131
|
+
method: '𝓶𝓮𝓽',
|
132
|
+
class: '𝐶',
|
133
|
+
attribute: '𝑎',
|
134
|
+
file: '𝐹',
|
135
|
+
)
|
136
|
+
|
137
|
+
# PREFIXES_MATH_GREEK = PREFIXES_BASE.merge(
|
138
|
+
# # module: "𝓜 𝓸𝓭𝓾𝓵𝓮",
|
139
|
+
# module: '𝛭',
|
140
|
+
# method: '𝜆',
|
141
|
+
# class: '𝛤',
|
142
|
+
# attribute: '𝛼',
|
143
|
+
# )
|
144
|
+
|
145
|
+
PREFIXES = PREFIXES_MATH_ITALIC
|
146
|
+
|
147
|
+
|
148
|
+
# Module (Class) Functions
|
149
|
+
# =====================================================================
|
150
|
+
|
151
|
+
|
152
|
+
# @todo Document short_s method.
|
153
|
+
#
|
154
|
+
# @param [type] arg_name
|
155
|
+
# @todo Add name param description.
|
156
|
+
#
|
157
|
+
# @return [return_type]
|
158
|
+
# @todo Document return value.
|
159
|
+
#
|
160
|
+
def self.short_s value, max = 64
|
161
|
+
NRSER.smart_ellipsis value.inspect, max
|
162
|
+
end # .short_s
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
# @todo Document format_type method.
|
167
|
+
#
|
168
|
+
# @param [type] arg_name
|
169
|
+
# @todo Add name param description.
|
170
|
+
#
|
171
|
+
# @return [return_type]
|
172
|
+
# @todo Document return value.
|
173
|
+
#
|
174
|
+
def self.format_type type, description
|
175
|
+
prefixes = RSpec.configuration.x_type_prefixes
|
176
|
+
|
177
|
+
return description if type.nil? || !prefixes.key?( type )
|
178
|
+
|
179
|
+
"#{ prefixes[type] } #{ description }"
|
180
|
+
end # .format_type
|
181
|
+
|
182
|
+
|
183
|
+
|
184
|
+
# @todo Document format method.
|
185
|
+
#
|
186
|
+
# @param [type] arg_name
|
187
|
+
# @todo Add name param description.
|
188
|
+
#
|
189
|
+
# @return [return_type]
|
190
|
+
# @todo Document return value.
|
191
|
+
#
|
192
|
+
def self.format *parts, type: nil
|
193
|
+
format_type \
|
194
|
+
type,
|
195
|
+
parts.
|
196
|
+
map { |part|
|
197
|
+
if part.respond_to? :to_desc
|
198
|
+
part.to_desc
|
199
|
+
elsif part.is_a? String
|
200
|
+
part
|
201
|
+
else
|
202
|
+
short_s part
|
203
|
+
end
|
204
|
+
}.
|
205
|
+
join( ' ' )
|
206
|
+
end # .format
|
207
|
+
|
208
|
+
|
209
|
+
class List < Array
|
210
|
+
def to_desc max = nil
|
211
|
+
max = [16, 64 / self.length].max if max.nil?
|
212
|
+
map { |entry| NRSER::RSpex.short_s entry, max }.join ", "
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
class Opts < Hash
|
218
|
+
def to_desc max = nil
|
219
|
+
max = [16, ( 64 / self.count )].max if max.nil?
|
220
|
+
|
221
|
+
map { |key, value|
|
222
|
+
if key.is_a? Symbol
|
223
|
+
"#{ key }: #{ NRSER::RSpex.short_s value, max }"
|
224
|
+
else
|
225
|
+
"#{ NRSER::RSpex.short_s key, max } => #{ NRSER::RSpex.short_s value, max }"
|
226
|
+
end
|
227
|
+
}.join( ", " )
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
class Args < Array
|
233
|
+
def to_desc max = nil
|
234
|
+
if last.is_a?( Hash )
|
235
|
+
[
|
236
|
+
List.new( self[0..-2] ).to_desc,
|
237
|
+
Opts[ last ].to_desc,
|
238
|
+
].reject( &:empty? ).join( ", " )
|
239
|
+
else
|
240
|
+
super
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
|
99
246
|
# Instance methods to extend example groups with.
|
100
247
|
#
|
101
248
|
module ExampleGroup
|
102
249
|
|
250
|
+
|
251
|
+
# @todo Document describe_x method.
|
252
|
+
#
|
253
|
+
# @param [type] arg_name
|
254
|
+
# @todo Add name param description.
|
255
|
+
#
|
256
|
+
# @return [return_type]
|
257
|
+
# @todo Document return value.
|
258
|
+
#
|
259
|
+
def describe_x_type *description_parts,
|
260
|
+
type:,
|
261
|
+
metadata: {},
|
262
|
+
subject_block: nil,
|
263
|
+
&body
|
264
|
+
|
265
|
+
description = NRSER::RSpex.format *description_parts, type: type
|
266
|
+
|
267
|
+
describe description, **metadata, type: type do
|
268
|
+
subject( &subject_block ) if subject_block
|
269
|
+
instance_exec &body
|
270
|
+
end # description,
|
271
|
+
|
272
|
+
end # #describe_x
|
273
|
+
|
274
|
+
|
275
|
+
# @todo Document describe_instance method.
|
276
|
+
#
|
277
|
+
# @param [type] arg_name
|
278
|
+
# @todo Add name param description.
|
279
|
+
#
|
280
|
+
# @return [return_type]
|
281
|
+
# @todo Document return value.
|
282
|
+
#
|
283
|
+
def describe_instance *constructor_args, &body
|
284
|
+
describe_x_type ".new(", Args(*constructor_args), ")",
|
285
|
+
type: :instance,
|
286
|
+
metadata: {
|
287
|
+
constructor_args: constructor_args,
|
288
|
+
},
|
289
|
+
# subject_block: -> { super().new *described_args },
|
290
|
+
subject_block: -> { super().new *described_constructor_args },
|
291
|
+
&body
|
292
|
+
end # #describe_instance
|
293
|
+
|
294
|
+
|
103
295
|
# Create a new {RSpec.describe} section where the subject is set by
|
104
296
|
# calling the parent subject with `args` and evaluate `block` in it.
|
105
297
|
#
|
@@ -119,11 +311,11 @@ module NRSER::RSpex
|
|
119
311
|
# Block to execute in the context of the example group after refining
|
120
312
|
# the subject.
|
121
313
|
#
|
122
|
-
def describe_called_with *args, &
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
314
|
+
def describe_called_with *args, &body
|
315
|
+
describe_x_type "called with", List(*args),
|
316
|
+
type: :invocation,
|
317
|
+
subject_block: -> { super().call *args },
|
318
|
+
&body
|
127
319
|
end # #describe_called_with
|
128
320
|
|
129
321
|
# Aliases to other names I was using at first... not preferring their use
|
@@ -137,7 +329,7 @@ module NRSER::RSpex
|
|
137
329
|
|
138
330
|
def describe_message symbol, *args, &body
|
139
331
|
description = \
|
140
|
-
"message #{ [symbol, *args].map(
|
332
|
+
"message #{ [symbol, *args].map( &NRSER::RSpex.method( :short_s ) ).join( ', ' ) }"
|
141
333
|
|
142
334
|
describe description, type: :message do
|
143
335
|
subject { NRSER::Message.new symbol, *args }
|
@@ -182,6 +374,16 @@ module NRSER::RSpex
|
|
182
374
|
alias_method :when_sent_to, :describe_sent_to
|
183
375
|
|
184
376
|
|
377
|
+
def describe_return_value *args, &body
|
378
|
+
msg = NRSER::Message.from *args
|
379
|
+
|
380
|
+
describe "return value from #{ msg }" do
|
381
|
+
subject { msg.send_to super() }
|
382
|
+
instance_exec &body
|
383
|
+
end # "return value from #{ msg }"
|
384
|
+
end
|
385
|
+
|
386
|
+
|
185
387
|
# Describe a "section". Just like {RSpec.describe} except it:
|
186
388
|
#
|
187
389
|
# 1. Expects a string title.
|
@@ -216,6 +418,20 @@ module NRSER::RSpex
|
|
216
418
|
alias_method :describe_topic, :describe_section
|
217
419
|
|
218
420
|
|
421
|
+
def describe_file path, **metadata, &body
|
422
|
+
title = path
|
423
|
+
|
424
|
+
describe(
|
425
|
+
"#{ NRSER::RSpex::PREFIXES[:file] } #{ title }",
|
426
|
+
type: :file,
|
427
|
+
file: path,
|
428
|
+
**metadata
|
429
|
+
) do
|
430
|
+
instance_exec &body
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
|
219
435
|
def describe_module mod, **metadata, &block
|
220
436
|
describe(
|
221
437
|
"#{ NRSER::RSpex::PREFIXES[:module] } #{ mod.name }",
|
@@ -227,15 +443,69 @@ module NRSER::RSpex
|
|
227
443
|
end # #describe_module
|
228
444
|
|
229
445
|
|
446
|
+
def describe_class klass, bind_subject: true, **metadata, &block
|
447
|
+
description = "#{ NRSER::RSpex::PREFIXES[:class] } #{ klass.name }"
|
448
|
+
|
449
|
+
describe(
|
450
|
+
description,
|
451
|
+
type: :class,
|
452
|
+
class: klass,
|
453
|
+
**metadata
|
454
|
+
) do
|
455
|
+
if bind_subject
|
456
|
+
subject { klass }
|
457
|
+
end
|
458
|
+
|
459
|
+
instance_exec &block
|
460
|
+
end
|
461
|
+
end # #describe_class
|
462
|
+
|
463
|
+
|
464
|
+
def described_class
|
465
|
+
metadata[:class] || super()
|
466
|
+
end
|
467
|
+
|
468
|
+
|
469
|
+
def describe_group title, **metadata, &block
|
470
|
+
describe(
|
471
|
+
"#{ NRSER::RSpex::PREFIXES[:group] } #{ title }",
|
472
|
+
type: :group,
|
473
|
+
**metadata
|
474
|
+
) do
|
475
|
+
instance_exec &block
|
476
|
+
end
|
477
|
+
end # #describe_class
|
478
|
+
|
479
|
+
|
230
480
|
def describe_method name, **metadata, &block
|
231
481
|
describe(
|
232
482
|
"#{ NRSER::RSpex::PREFIXES[:method] } #{ name }",
|
233
483
|
type: :method,
|
484
|
+
method_name: name,
|
234
485
|
**metadata
|
235
486
|
) do
|
487
|
+
if name.is_a? Symbol
|
488
|
+
subject { super().method name }
|
489
|
+
end
|
490
|
+
|
236
491
|
instance_exec &block
|
237
492
|
end
|
238
|
-
end # #
|
493
|
+
end # #describe_method
|
494
|
+
|
495
|
+
|
496
|
+
def describe_attribute symbol, **metadata, &block
|
497
|
+
describe(
|
498
|
+
"#{ NRSER::RSpex::PREFIXES[:attribute] } ##{ symbol }",
|
499
|
+
type: :attribute,
|
500
|
+
**metadata
|
501
|
+
) do
|
502
|
+
subject { super().public_send symbol }
|
503
|
+
instance_exec &block
|
504
|
+
end
|
505
|
+
end # #describe_attribute
|
506
|
+
|
507
|
+
# Shorter name
|
508
|
+
alias_method :describe_attr, :describe_attribute
|
239
509
|
|
240
510
|
|
241
511
|
# Define a `context` block with `let` bindings and evaluate the `body`
|
@@ -250,12 +520,15 @@ module NRSER::RSpex
|
|
250
520
|
# @return
|
251
521
|
# Whatever `context` returns.
|
252
522
|
#
|
253
|
-
def context_where **bindings, &body
|
254
|
-
description = bindings.map { |name, value|
|
255
|
-
"let #{ name } = #{ value }"
|
256
|
-
}.join( ', ' )
|
523
|
+
def context_where description = nil, **bindings, &body
|
257
524
|
|
258
|
-
|
525
|
+
if description.nil?
|
526
|
+
description = bindings.map { |name, value|
|
527
|
+
"#{ name }: #{ NRSER::RSpex.short_s value }"
|
528
|
+
}.join( ", " )
|
529
|
+
end
|
530
|
+
|
531
|
+
context "△ #{ description }", type: :where do
|
259
532
|
bindings.each { |name, value|
|
260
533
|
let( name ) { unwrap value, context: self }
|
261
534
|
}
|
@@ -267,63 +540,32 @@ module NRSER::RSpex
|
|
267
540
|
|
268
541
|
end # module ExampleGroup
|
269
542
|
|
543
|
+
|
544
|
+
# Extensions available in examples themselves via RSpec's `config.include`.
|
545
|
+
#
|
546
|
+
module Example
|
547
|
+
def described_class
|
548
|
+
self.class.metadata[:class] || super
|
549
|
+
end
|
550
|
+
|
551
|
+
def described_constructor_args
|
552
|
+
self.class.metadata[:constructor_args]
|
553
|
+
end
|
554
|
+
|
555
|
+
end
|
556
|
+
|
270
557
|
end # module NRSER:RSpex
|
271
558
|
|
559
|
+
|
272
560
|
RSpec.configure do |config|
|
273
561
|
config.extend NRSER::RSpex::ExampleGroup
|
562
|
+
config.include NRSER::RSpex::Example
|
563
|
+
|
564
|
+
config.add_setting :x_type_prefixes
|
565
|
+
config.x_type_prefixes = \
|
566
|
+
NRSER::RSpex::PREFIXES_BASE.merge( NRSER::RSpex::PREFIXES_MATH_ITALIC )
|
274
567
|
end
|
275
568
|
|
276
|
-
|
569
|
+
# Make available at the top-level
|
277
570
|
include NRSER::RSpex::ExampleGroup
|
278
571
|
|
279
|
-
|
280
|
-
# Shared Examples
|
281
|
-
# =====================================================================
|
282
|
-
|
283
|
-
shared_examples "expect subject" do |*expectations|
|
284
|
-
merge_expectations( *expectations ).each { |state, specs|
|
285
|
-
specs.each { |verb, noun|
|
286
|
-
it {
|
287
|
-
# like: is_expected.to(include(noun))
|
288
|
-
is_expected.send state, self.send(verb, noun)
|
289
|
-
}
|
290
|
-
}
|
291
|
-
}
|
292
|
-
end # is expected
|
293
|
-
|
294
|
-
|
295
|
-
# Shared example for a functional method that compares input and output pairs.
|
296
|
-
#
|
297
|
-
shared_examples "function" do |mapping: {}, raising: {}|
|
298
|
-
mapping.each { |args, expected|
|
299
|
-
args = NRSER.as_array args
|
300
|
-
|
301
|
-
context "called with #{ args.map( &:inspect ).join ', ' }" do
|
302
|
-
subject { super().call *args }
|
303
|
-
|
304
|
-
it {
|
305
|
-
expected = unwrap expected, context: self
|
306
|
-
|
307
|
-
matcher = if expected.respond_to?( :matches? )
|
308
|
-
expected
|
309
|
-
elsif expected.is_a? NRSER::Message
|
310
|
-
expected.send_to self
|
311
|
-
else
|
312
|
-
eq expected
|
313
|
-
end
|
314
|
-
|
315
|
-
is_expected.to matcher
|
316
|
-
}
|
317
|
-
end
|
318
|
-
}
|
319
|
-
|
320
|
-
raising.each { |args, error|
|
321
|
-
args = NRSER.as_array args
|
322
|
-
|
323
|
-
context "called with #{ args.map( &:inspect ).join ', ' }" do
|
324
|
-
# it "rejects #{ args.map( &:inspect ).join ', ' }" do
|
325
|
-
it { expect { subject.call *args }.to raise_error( *error ) }
|
326
|
-
end
|
327
|
-
}
|
328
|
-
end # function
|
329
|
-
|