nrser 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
  3. data/lib/nrser/char.rb +0 -6
  4. data/lib/nrser/core_ext/array.rb +120 -0
  5. data/lib/nrser/core_ext/binding.rb +44 -0
  6. data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
  7. data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
  8. data/lib/nrser/core_ext/exception.rb +30 -0
  9. data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
  10. data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
  11. data/lib/nrser/core_ext/hash.rb +50 -0
  12. data/lib/nrser/core_ext/module/method_objects.rb +96 -0
  13. data/lib/nrser/core_ext/module/names.rb +69 -0
  14. data/lib/nrser/core_ext/module/source_locations.rb +214 -0
  15. data/lib/nrser/core_ext/module.rb +2 -0
  16. data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
  17. data/lib/nrser/core_ext/object.rb +46 -0
  18. data/lib/nrser/core_ext/open_struct.rb +6 -0
  19. data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
  20. data/lib/nrser/{ext → core_ext}/string.rb +6 -12
  21. data/lib/nrser/core_ext/symbol.rb +13 -0
  22. data/lib/nrser/core_ext/time.rb +46 -0
  23. data/lib/nrser/core_ext.rb +13 -0
  24. data/lib/nrser/errors/abstract_method_error.rb +150 -0
  25. data/lib/nrser/errors/argument_error.rb +42 -0
  26. data/lib/nrser/errors/nicer_error.rb +298 -72
  27. data/lib/nrser/errors/type_error.rb +46 -0
  28. data/lib/nrser/errors.rb +4 -53
  29. data/lib/nrser/ext/tree.rb +3 -0
  30. data/lib/nrser/functions/enumerable/associate.rb +6 -9
  31. data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
  32. data/lib/nrser/functions/enumerable.rb +1 -3
  33. data/lib/nrser/functions/exception.rb +1 -1
  34. data/lib/nrser/functions/hash.rb +0 -6
  35. data/lib/nrser/functions/merge_by.rb +2 -2
  36. data/lib/nrser/functions/module/method_objects.rb +77 -0
  37. data/lib/nrser/functions/module.rb +1 -2
  38. data/lib/nrser/functions/open_struct.rb +25 -35
  39. data/lib/nrser/functions/proc.rb +1 -6
  40. data/lib/nrser/functions/string/looks_like.rb +32 -1
  41. data/lib/nrser/functions/string.rb +1 -40
  42. data/lib/nrser/functions/text/lines.rb +2 -1
  43. data/lib/nrser/functions.rb +0 -1
  44. data/lib/nrser/graph/tsorter.rb +41 -0
  45. data/lib/nrser/labs/core_ext/binding.rb +37 -0
  46. data/lib/nrser/labs/stash.rb +372 -0
  47. data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
  48. data/lib/nrser/log/appender.rb +3 -0
  49. data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
  50. data/lib/nrser/log/formatters/mixin.rb +270 -0
  51. data/lib/nrser/{logging → log}/formatters.rb +0 -0
  52. data/lib/nrser/log/logger.rb +229 -0
  53. data/lib/nrser/log/mixin.rb +56 -0
  54. data/lib/nrser/log.rb +723 -0
  55. data/lib/nrser/message.rb +24 -3
  56. data/lib/nrser/meta/source/location.rb +158 -0
  57. data/lib/nrser/meta.rb +1 -1
  58. data/lib/nrser/props/class_methods.rb +118 -0
  59. data/lib/nrser/props/immutable/hash.rb +111 -0
  60. data/lib/nrser/props/immutable/hash_variable.rb +82 -0
  61. data/lib/nrser/props/immutable/instance_variables.rb +48 -0
  62. data/lib/nrser/props/immutable/vector.rb +107 -0
  63. data/lib/nrser/props/instance_methods.rb +184 -0
  64. data/lib/nrser/props/metadata.rb +359 -0
  65. data/lib/nrser/props/mutable/instance_variables.rb +60 -0
  66. data/lib/nrser/props/mutable/stash.rb +199 -0
  67. data/lib/nrser/{meta/props → props}/prop.rb +217 -112
  68. data/lib/nrser/props/storage/instance_variable.rb +85 -0
  69. data/lib/nrser/props/storage/instance_variables.rb +67 -0
  70. data/lib/nrser/props/storage/key.rb +88 -0
  71. data/lib/nrser/props.rb +9 -0
  72. data/lib/nrser/refinements/sugar.rb +41 -0
  73. data/lib/nrser/refinements/types.rb +2 -2
  74. data/lib/nrser/refinements.rb +14 -16
  75. data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
  76. data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
  77. data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
  78. data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
  79. data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
  80. data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
  81. data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
  82. data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
  83. data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
  84. data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
  85. data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
  86. data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
  87. data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
  88. data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
  89. data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
  90. data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
  91. data/lib/nrser/rspex/example_group/overrides.rb +66 -0
  92. data/lib/nrser/rspex/example_group.rb +20 -252
  93. data/lib/nrser/rspex/format.rb +83 -17
  94. data/lib/nrser/rspex.rb +4 -34
  95. data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
  96. data/lib/nrser/{env → sys/env}/path.rb +1 -2
  97. data/lib/nrser/{env.rb → sys/env.rb} +2 -1
  98. data/lib/nrser/sys.rb +5 -0
  99. data/lib/nrser/types/any.rb +36 -7
  100. data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
  101. data/lib/nrser/types/attrs.rb +68 -15
  102. data/lib/nrser/types/booleans.rb +95 -34
  103. data/lib/nrser/types/bounded.rb +12 -10
  104. data/lib/nrser/types/combinators.rb +74 -37
  105. data/lib/nrser/types/errors/check_error.rb +86 -0
  106. data/lib/nrser/types/errors/from_string_error.rb +82 -0
  107. data/lib/nrser/types/factory.rb +91 -0
  108. data/lib/nrser/types/hashes.rb +171 -26
  109. data/lib/nrser/types/in.rb +25 -12
  110. data/lib/nrser/types/is.rb +50 -18
  111. data/lib/nrser/types/is_a.rb +52 -33
  112. data/lib/nrser/types/labels.rb +6 -33
  113. data/lib/nrser/types/maybe.rb +12 -4
  114. data/lib/nrser/types/nil.rb +24 -4
  115. data/lib/nrser/types/not.rb +6 -16
  116. data/lib/nrser/types/numbers.rb +94 -57
  117. data/lib/nrser/types/pairs.rb +57 -57
  118. data/lib/nrser/types/paths.rb +112 -133
  119. data/lib/nrser/types/responds.rb +64 -74
  120. data/lib/nrser/types/shape.rb +29 -24
  121. data/lib/nrser/types/strings.rb +25 -17
  122. data/lib/nrser/types/symbols.rb +19 -17
  123. data/lib/nrser/types/trees.rb +18 -70
  124. data/lib/nrser/types/tuples.rb +36 -40
  125. data/lib/nrser/types/type.rb +342 -91
  126. data/lib/nrser/types/when.rb +40 -18
  127. data/lib/nrser/types/where.rb +94 -9
  128. data/lib/nrser/types.rb +72 -63
  129. data/lib/nrser/version.rb +1 -1
  130. data/lib/nrser.rb +18 -18
  131. data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
  132. data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
  133. data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
  134. data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
  135. data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
  136. data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
  137. data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
  138. data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
  139. data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
  140. data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
  141. data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
  142. data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
  143. data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
  144. data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
  145. data/spec/lib/nrser/refinements/array_spec.rb +2 -15
  146. data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
  147. data/spec/lib/nrser/refinements/set_spec.rb +2 -15
  148. data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
  149. data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
  150. data/spec/lib/nrser/types/array_spec.rb +8 -8
  151. data/spec/lib/nrser/types/paths_spec.rb +15 -18
  152. data/spec/spec_helper.rb +4 -0
  153. metadata +109 -69
  154. data/lib/nrser/ext/binding.rb +0 -36
  155. data/lib/nrser/ext/module.rb +0 -62
  156. data/lib/nrser/ext.rb +0 -8
  157. data/lib/nrser/functions/binding.rb +0 -76
  158. data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
  159. data/lib/nrser/functions/enumerable/map_values.rb +0 -94
  160. data/lib/nrser/functions/hash/deep_merge.rb +0 -57
  161. data/lib/nrser/functions/hash/except_keys.rb +0 -44
  162. data/lib/nrser/functions/hash/slice_keys.rb +0 -43
  163. data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
  164. data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
  165. data/lib/nrser/functions/hash/transform_keys.rb +0 -140
  166. data/lib/nrser/functions/module/methods.rb +0 -206
  167. data/lib/nrser/functions/module/source_locations.rb +0 -213
  168. data/lib/nrser/logging/appender.rb +0 -3
  169. data/lib/nrser/logging.rb +0 -353
  170. data/lib/nrser/meta/props/base.rb +0 -31
  171. data/lib/nrser/meta/props.rb +0 -357
  172. data/lib/nrser/refinements/array.rb +0 -133
  173. data/lib/nrser/refinements/binding.rb +0 -6
  174. data/lib/nrser/refinements/enumerator.rb +0 -5
  175. data/lib/nrser/refinements/exception.rb +0 -35
  176. data/lib/nrser/refinements/hash.rb +0 -150
  177. data/lib/nrser/refinements/module.rb +0 -5
  178. data/lib/nrser/refinements/object.rb +0 -42
  179. data/lib/nrser/refinements/open_struct.rb +0 -28
  180. data/lib/nrser/refinements/pathname.rb +0 -5
  181. data/lib/nrser/refinements/set.rb +0 -5
  182. data/lib/nrser/refinements/string.rb +0 -5
  183. data/lib/nrser/refinements/symbol.rb +0 -20
  184. data/lib/nrser/rspex/described.rb +0 -99
  185. data/spec/design/mapping_spec.rb +0 -42
  186. data/spec/lib/nrser/functions/hash_spec.rb +0 -41
  187. data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
  188. data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ module NRSER::RSpex::ExampleGroup
5
+
6
+ # Create an example group covering a source file.
7
+ #
8
+ # Useful for when method implementations are spread out across multiple
9
+ # files but you want to group examples by the source file they're in.
10
+ #
11
+ # @note
12
+ # Honestly, now that modules, classes and methods described through RSpex
13
+ # add their source locations, this is not all that useful. But it was
14
+ # there from before that, which is why for the moment it's still here.
15
+ #
16
+ # @see #describe_x
17
+ #
18
+ # @param [String | Pathname] path
19
+ # File path.
20
+ #
21
+ # @param *description (see #describe_x)
22
+ #
23
+ # @param [Hash<Symbol, Object>] **metadata
24
+ # RSpec metadata to set for the example group.
25
+ #
26
+ # See the `metadata` keyword argument to {#describe_x}.
27
+ #
28
+ # A `file` key is added pointed to the {Pathname} for `path` before
29
+ # passing up to {#describe_x}.
30
+ #
31
+ # @param &body (see #describe_x)
32
+ #
33
+ # @return (see #describe_x)
34
+ #
35
+ def describe_source_file path, *description, **metadata, &body
36
+ path = path.to_pn
37
+
38
+ describe_x \
39
+ path,
40
+ *description,
41
+ type: :source_file,
42
+ metadata: {
43
+ source_file: path,
44
+ **metadata,
45
+ },
46
+ &body
47
+ end
48
+
49
+ end # module NRSER::RSpex::ExampleGroup
@@ -4,6 +4,26 @@ using NRSER
4
4
 
5
5
  module NRSER::RSpex::ExampleGroup
6
6
 
7
+ def dive_x current, *rest, **kwds, &body
8
+ type, data = current
9
+
10
+ method_name = "describe_#{ type }"
11
+
12
+ block = if rest.empty?
13
+ body
14
+ else
15
+ -> { dive_x *rest, &body }
16
+ end
17
+
18
+ begin
19
+ public_send method_name, data, **kwds, &block
20
+ rescue NoMethodError => error
21
+ pp self.methods
22
+ raise error
23
+ end
24
+ end
25
+
26
+
7
27
  # **EXPERIMENTAL**
8
28
  #
9
29
  # Example group helper for use at the top level of each spec file to
@@ -26,7 +46,7 @@ module NRSER::RSpex::ExampleGroup
26
46
  #
27
47
  # Probably possible to extract this somehow without having to provide it?
28
48
  #
29
- # @return [nil]
49
+ # @return (see #describe_x)
30
50
  #
31
51
  def describe_spec_file description: nil,
32
52
  spec_path:,
@@ -34,118 +54,31 @@ module NRSER::RSpex::ExampleGroup
34
54
  **metadata,
35
55
  &body
36
56
 
37
- if metadata[:module] && metadata[:method]
38
- meth = metadata[:module].method metadata[:method]
39
- file, line = meth.source_location
40
- path = Pathname.new file
41
- loc = "./#{ path.relative_path_from Pathname.getwd }:#{ line }"
42
-
43
- spec_rel_path = \
44
- "./#{ Pathname.new( spec_path ).relative_path_from Pathname.getwd }"
45
-
46
- desc = [
47
- "#{ metadata[:module].name }.#{ metadata[:method] }",
48
- "(#{ loc })",
49
- description,
50
- "Spec (#{ spec_rel_path})"
51
- ].compact.join " "
52
-
53
- subj = meth
57
+ chain = []
54
58
 
55
- elsif metadata[:class]
56
- klass = metadata[:class]
57
-
58
- if metadata[:instance_method]
59
- instance_method = klass.instance_method metadata[:instance_method]
60
-
61
- file, line = instance_method.source_location
62
-
63
- name = "#{ klass.name }##{ metadata[:instance_method] }"
64
-
65
- elsif metadata[:method]
66
- # Class method
67
- meth = metadata[:class].method metadata[:method]
68
- file, line = meth.source_location
69
- path = Pathname.new file
70
- loc = "./#{ path.relative_path_from Pathname.getwd }:#{ line }"
71
-
72
- spec_rel_path = \
73
- "./#{ Pathname.new( spec_path ).relative_path_from Pathname.getwd }"
74
-
75
- desc = [
76
- "#{ metadata[:class].name }.#{ metadata[:method] }",
77
- "(#{ loc })",
78
- description,
79
- "Spec (#{ spec_rel_path})"
80
- ].compact.join " "
81
-
82
- subj = meth
83
-
84
- else
85
- name = klass.name
86
-
87
- # Get a reasonable file and line for the class
88
- file, line = klass.
89
- # Get an array of all instance methods, excluding inherited ones
90
- # (the `false` arg)
91
- instance_methods( false ).
92
- # Add `#initialize` since it isn't in `#instance_methods` for some
93
- # reason
94
- <<( :initialize ).
95
- # Map those to their {UnboundMethod} objects
96
- map { |sym| klass.instance_method sym }.
97
- # Toss any `nil` values
98
- compact.
99
- # Get the source locations
100
- map( &:source_location ).
101
- # Get rid of `[nil, nil]` results, which seems to come from C exts
102
- reject { |(path, line)| path.nil? || line.nil? }.
103
- # Get the first line in the shortest path
104
- min_by { |(path, line)| [path.length, line] }
105
-
106
- # Another approach I thought of... (untested)
107
- #
108
- # Get the path
109
- # # Get frequency of the paths
110
- # count_by { |(path, line)| path }.
111
- # # Get the one with the most occurrences
112
- # max_by { |path, count| count }.
113
- # # Get just the path (not the count)
114
- # first
115
- end
116
-
117
- location = if file
118
- "(#{ NRSER::RSpex.dot_rel_path file }:#{ line })"
59
+ [
60
+ :source_file,
61
+ :module,
62
+ :class,
63
+ :instance,
64
+ :method,
65
+ :instance_method,
66
+ :called_with,
67
+ :attribute,
68
+ ].each do |type|
69
+ if data = metadata.delete( type )
70
+ chain << [type, data]
119
71
  end
120
-
121
- desc = [
122
- "𝑆𝑃𝐸𝐶 𝐹𝐼𝐿𝐸 `#{ NRSER::RSpex.dot_rel_path spec_path }` 𝐹𝑂𝑅",
123
- name,
124
- location,
125
- description,
126
- ].compact.join " "
127
-
128
- subj = klass
129
-
130
- else
131
- # TODO Make this work!
132
- raise ArgumentError.new binding.erb <<-END
133
- Not yet able to handle metadata:
134
-
135
- <%= metadata.pretty_inspect %>
136
-
137
- END
138
72
  end
139
73
 
140
- describe desc, **metadata do
141
- if bind_subject
142
- subject { subj }
143
- end
144
-
145
- module_exec &body
74
+ describe_x(
75
+ NRSER::RSpex.dot_rel_path( spec_path ),
76
+ *description,
77
+ type: :spec_file,
78
+ metadata: metadata,
79
+ ) do
80
+ dive_x *chain, bind_subject: bind_subject, &body
146
81
  end
147
-
148
- nil
149
82
  end # #describe_spec_file
150
83
 
151
84
  end # module NRSER::RSpex::ExampleGroup
@@ -1,18 +1,20 @@
1
+ # encoding: UTF-8
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module NRSER::RSpex::ExampleGroup
4
5
 
5
- # Define a example group block with `let` bindings and evaluate the `body`
6
- # block in it.
6
+ # Define a example group with the keyword args as bindings.
7
+ #
8
+ # @see #describe_x
9
+ #
10
+ # @param *description (see #describe_x)
7
11
  #
8
12
  # @param [Hash<Symbol, Object>] **bindings
9
- # Map of symbol names to value to bind using `let`.
13
+ # See the `bindings` keyword arg in {#describe_x}.
10
14
  #
11
- # @param [#call] &body
12
- # Body block to evaluate in the context.
15
+ # @param &body (see #describe_x)
13
16
  #
14
- # @return
15
- # Whatever `context` returns.
17
+ # @return (see #describe_x)
16
18
  #
17
19
  def describe_when *description, **bindings, &body
18
20
  describe_x \
@@ -22,4 +24,9 @@ module NRSER::RSpex::ExampleGroup
22
24
  &body
23
25
  end
24
26
 
27
+ # Old name (used to be different method)
28
+
29
+ alias_method :context_where, :describe_when
30
+
31
+
25
32
  end # module NRSER::RSpex::ExampleGroup
@@ -23,25 +23,38 @@ module NRSER::RSpex::ExampleGroup
23
23
  # key.
24
24
  #
25
25
  # @param [Hash<Symbol, Object>] metadata:
26
- # Metadata to add to the new example group.
26
+ # [RSpec metadata][] to add to the new example group.
27
27
  #
28
28
  # In addition to the keys RSpec will reject, we prohibit `:type` *unless*
29
29
  # it is the same as the `type` keyword argument or `nil`.
30
30
  #
31
31
  # In either of these cases, the `type` keyword arg will be used for the new
32
32
  # example group's `:type` metadata value.
33
+ #
34
+ # [RSpec metadata]: https://relishapp.com/rspec/rspec-core/docs/metadata/user-defined-metadata
33
35
  #
34
36
  # @param [Hash<Symbol, Object>] bindings:
37
+ # Name to value pairs to bind in the new example group.
35
38
  #
39
+ # All values will be bound at the example group and example levels -
40
+ # though if they are {Wrapper}, that wrapper will be available at the
41
+ # group level, while they will be automatically unwrapped at the
42
+ # example level (as the requisite context is available there).
43
+ #
44
+ # @param [Boolean] bind_subject:
45
+ # When `true` (and there is a `subject_block`) bind the `subject` inside
46
+ # the new example group.
47
+ #
48
+ #
36
49
  #
37
- # @return [return_type]
38
- # @todo Document return value.
50
+ # @return [void]
39
51
  #
40
52
  def describe_x *description,
41
53
  type:,
42
54
  metadata: {},
43
55
  bindings: {},
44
56
  add_binding_desc: true,
57
+ bind_subject: true,
45
58
  subject_block: nil,
46
59
  &body
47
60
 
@@ -67,30 +80,44 @@ module NRSER::RSpex::ExampleGroup
67
80
  END
68
81
  end
69
82
 
83
+ # Add description of the bindings, if we have any and were told to
70
84
  unless bindings.empty? || add_binding_desc == false
71
- # bindings_desc = NRSER::RSpex::Opts[bindings].to_desc
72
- bindings_desc = ["(", bindings.ai( multiline: false ), ")"]
85
+ bindings_desc = NRSER::RSpex::Format.md_code_quote \
86
+ bindings.map { |name, value|
87
+ "#{ name } = #{ value.inspect }"
88
+ }.join( '; ' )
73
89
 
74
90
  if description.empty?
75
- description = bindings.ai( multiline: false )
91
+ description = bindings_desc
76
92
  else
77
- description += ["(", bindings.ai( multiline: false ), ")"]
93
+ description << "(" + bindings_desc + ")"
78
94
  end
79
95
  end
80
96
 
81
- formatted = NRSER::RSpex::Format.description *description, type: type
82
-
83
- describe formatted, **metadata, type: type do
84
- subject( &subject_block ) if subject_block
97
+ # Call up to RSpec's `#describe` method
98
+ describe(
99
+ NRSER::RSpex::Format.description( *description, type: type ),
100
+ **metadata,
101
+ type: type,
102
+ ) do
103
+ if subject_block && bind_subject
104
+ subject &subject_block
105
+ end
85
106
 
107
+ # Bind bindings
86
108
  unless bindings.empty?
87
109
  bindings.each { |name, value|
110
+ # Example-level binding
88
111
  let( name ) { unwrap value, context: self }
112
+
113
+ # Example group-level binding (which may return a {Wrapper} that
114
+ # of course can not be unwrapped at the group level)
115
+ define_singleton_method( name ) { value }
89
116
  }
90
117
  end
91
118
 
92
119
  module_exec &body
93
- end # description,
120
+ end # describe
94
121
 
95
122
  end # #describe_x
96
123
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+
5
+ # Definitions
6
+ # =======================================================================
7
+
8
+ module NRSER::RSpex::ExampleGroup
9
+
10
+ # HACK HACK HACK-ITY HACK - Allow for overriding RSpec methods
11
+ #
12
+ # Yeah, it has to do with mixin mixing-in ordering - seems to be that when
13
+ #
14
+ # config.extend NRSER::RSpex::ExampleGroup
15
+ #
16
+ # {NRSER::RSpex::ExampleGroup} gets mixed in *very early* in the chain,
17
+ # before {RSpec::Core::ExampleGroup}... why you would provide an explicit
18
+ # extension mechanism and not give those extensions priority I'm not sure,
19
+ # but I'm sure I shouldn't be looking into it right now, so here we are:
20
+ #
21
+ # It turns out that {NRSER::RSpex::Example}, which gets mixed with
22
+ #
23
+ # config.include NRSER::RSpex::Example
24
+ #
25
+ # gets mixed *last*, so by using it's {NRSER::RSpex::Example.included}
26
+ # hook we can use
27
+ #
28
+ # base#extend NRSER::RSpex::ExampleGroup::Overrides
29
+ #
30
+ # to mix these guys over the top of RSpec's methods.
31
+ #
32
+ # Seems like we could just mix all of {NRSER::RSpex::ExampleGroup} there
33
+ # to get the behavior I would have expected all along, but maybe it's better
34
+ # to have these explicit notes for the moment and not change much else until
35
+ # I get the chance to really check out what's going on.
36
+ #
37
+ # And really it's all to override `.described_class` to pick up our
38
+ # metadata if it's there, but that approach is in quite a bit of use at
39
+ # this point, and, no, I have no idea how it seemed to work up until this
40
+ # point :/
41
+ #
42
+ module Overrides
43
+
44
+ # Override {RSpec::Core::ExampleGroup.described_class} to use RSpex's
45
+ # `:class` metadata if it's present.
46
+ #
47
+ # Because I can't figure out how to feed RSpec the described class
48
+ # without it being the description, and we want better descriptions.
49
+ #
50
+ # Some hackery could def do it, this is RUBY after all, but whatever this
51
+ # works for now and may even be less fragile.
52
+ #
53
+ # @return [Class]
54
+ # If there's a `:class` in the metadata, or if RSpec has on through the
55
+ # standard means (`describe MyClass do ...`).
56
+ #
57
+ # @return [nil]
58
+ # If we don't have a class context around.
59
+ #
60
+ def described_class
61
+ metadata[:class] || super()
62
+ end
63
+
64
+ end # module Overrides
65
+
66
+ end # module NRSER:RSpex::ExampleGroup