nrser 0.0.26 → 0.0.27
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|