rspec-junklet 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZWQwYjZkZmNlNjlkNmM0MTE2YTMyNzBmYTEwMjU0MThjMjNlYzUzMA==
5
+ data.tar.gz: !binary |-
6
+ MjQwNmUwNzQxYTljYWQ1NjhiMTgxNzU0NTk0NzNjNTk4MDhkYjdkNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTFlNmUzYTRhNzgzNjQyNjViZjA4YWNmYzI5Mjk4NWQ3N2VmNDhkYjZmNzIx
10
+ NmM5MWE5MDkzNzk1Y2E2YmM2MTEyM2U2YWI0YTU4NjVkOTA1MTdiYjNhZGFj
11
+ MThhZjU2MWY2ZDRhYTI2ODQ4MTI2YzJkZmM1NTM0ODJiM2Q1YmQ=
12
+ data.tar.gz: !binary |-
13
+ OWY2NjNiNmY2ZDM1NTVlNWNmODNmZDIxMGNjODI1N2Y2M2MzMmJkOWY4Nzc4
14
+ NDY1NTFjZmFjZjU1NjA2YmJiZWI3NzUyYzQ0ZjZmZjYxNjIxYmJlMThkM2Y5
15
+ OTYyMjA0ZjEwMTk5MGU1ZmQ2N2UxYWZjMmVlYjQyZWEyZWM4NDQ=
data/.gitignore ADDED
@@ -0,0 +1,34 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p551
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in junklet.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rspec-junklet (1.0.4)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ builder (3.2.2)
10
+ coderay (1.1.0)
11
+ cucumber (1.3.18)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.3)
14
+ gherkin (~> 2.12)
15
+ multi_json (>= 1.7.5, < 2.0)
16
+ multi_test (>= 0.1.1)
17
+ diff-lcs (1.2.5)
18
+ gherkin (2.12.2)
19
+ multi_json (~> 1.3)
20
+ method_source (0.8.2)
21
+ multi_json (1.10.1)
22
+ multi_test (0.1.1)
23
+ pry (0.10.1)
24
+ coderay (~> 1.1.0)
25
+ method_source (~> 0.8.1)
26
+ slop (~> 3.4)
27
+ rake (10.4.2)
28
+ rspec (2.99.0)
29
+ rspec-core (~> 2.99.0)
30
+ rspec-expectations (~> 2.99.0)
31
+ rspec-mocks (~> 2.99.0)
32
+ rspec-core (2.99.2)
33
+ rspec-expectations (2.99.2)
34
+ diff-lcs (>= 1.1.3, < 2.0)
35
+ rspec-mocks (2.99.2)
36
+ slop (3.6.0)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bundler (~> 1.7)
43
+ cucumber
44
+ pry
45
+ rake (~> 10.0)
46
+ rspec (~> 2.0)
47
+ rspec-junklet!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 CoverMyMeds
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,314 @@
1
+ # Junklet
2
+
3
+ Cache tiny chunks of unique junk data in RSpec with `junklet :name`; get handy
4
+ clumps of junk data at any time with `junk`. Size your junk with e.g. `junk 100`
5
+ or `junk 4`.
6
+
7
+ Junklet data is fixture data that:
8
+
9
+ * We essentially don't care about,
10
+ * But we might want to test for equality somewhere later,
11
+ * And we might need to be unique between runs in case a spec crashes and
12
+ SQLServer fails to clean up the test database
13
+
14
+ So,
15
+
16
+ * We want it to be easy to create junk data fields quickly and easily, and
17
+ * If equality fails we want to be led to the offending field by the error
18
+ message and not just the line number in the stack trace.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ ```ruby
25
+ gem 'rspec-junklet'
26
+ ```
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ Or install it yourself as:
33
+
34
+ $ gem install rspec-junklet
35
+
36
+ # Usage
37
+
38
+ junklet adds two keywords to RSpec's DSL: `junklet`, which defines a `let`
39
+ statement containing junk data, and `junk`, which is a method that returns many
40
+ and varied types of junk data. The former is meant to be used as part of the DSL
41
+ to declare pieces of data to be junk, while the latter is intended to be used
42
+ anywhere inside RSpec to supply the junk data itself.
43
+
44
+ To illustrate, these statements are functionally identical:
45
+
46
+ ```ruby
47
+ junklet :pigtruck
48
+ let(:pigtruck) { junk }
49
+ ```
50
+
51
+ ## Junklet
52
+
53
+ `junklet` declares a memoized variable containing random junk.
54
+
55
+ junklet :var [, :var_2 [...]] [, options_hash]
56
+
57
+ So, for example,
58
+
59
+ junklet :first_name
60
+
61
+ Creates a `let :first_name` with the value of
62
+ `first_name-774030d0f58d4f588c5edddbdc7f9580` (the hex number is a uuid without
63
+ hyphens and will change with each test _case_, not just each test run).
64
+
65
+ Currently the options hash only gives you control over the variable names appear
66
+ in the junk data, not the junk data itself. For example,
67
+
68
+ ```ruby
69
+ junklet :host_name, separator: '-'
70
+ ```
71
+
72
+ Creates a `let :host_name`, but changes underscores to hyphens in the string
73
+ value, e.g. `host-name-774030d0f58d4f588c5edddbdc7f9580`. Useful specifically
74
+ for host names, which cannot have underscores in them.
75
+
76
+ ```ruby
77
+ junklet :a_a, :b_b, :c_c, separator: '.'
78
+ ```
79
+
80
+ Does what it says on the tin: creates 3 items with string values of
81
+ `a.a.774...`, `b.b.1234...`, and `c.c.234abc...` respectively. I don't know why
82
+ you'd need this, but hey, if you do there it is.
83
+
84
+ ## Junk
85
+
86
+ `junk` returns random junk, which can be finely tuned and fiddled with.
87
+
88
+ ```ruby
89
+ junk
90
+ junk (integer|symbol|enumerable|proc) [options]
91
+ ```
92
+
93
+ By default, just calling `junk` from inside a spec or let block returns a random
94
+ hex string 32 bytes long.
95
+
96
+ ### integer
97
+
98
+ Give junk an integer argument and it will return that many hexadecimal digits of
99
+ junk data. Note that this is HALF the number of digits returned if you were to
100
+ call `SecureRandom.hex(n)`, because `hex(n)` returns n _bytes_, each of which
101
+ requires two hex digits to represent. Since we're more concerned about specific
102
+ byte lengths, `junk(n)` gives you n digits, not n*2 digits representing n bytes.
103
+
104
+
105
+ ```ruby
106
+ junk 17 - return 17 bytes of junk data
107
+ ```
108
+
109
+ ### symbol
110
+
111
+ junk may be given a symbol denoting the type of data to be returned. Currently
112
+ `:int` and `:bool` are the only supported types. `junk :bool` merely returns
113
+ true or false; `junk :int` is much more complicated and interesting.
114
+
115
+ ```ruby
116
+ junk :bool # Boring. Well, 50% chance of boring.
117
+ ```
118
+
119
+ `junk :int` is the most complicated and/or interesting type of junk. It returns
120
+ a random decimal number, and it has the most options such as `size` (number of
121
+ digits), and `min` and `max` (which sort of do what you'd expect).
122
+
123
+ By default, `junk :int` returns a random number from 0 to the largest possible
124
+ `Fixnum`, which is 2**62-1.
125
+
126
+ ```ruby
127
+ junk :int # return a random integer from 0 to 2**62-1 (maximum size of
128
+ a Fixnum)
129
+ ```
130
+
131
+ `size`, `min` and `max` control the size and bounds of the random number.
132
+
133
+ ```ruby
134
+ junk :int, size: 3 # returns a 3-digit decimal from 100 to 999.
135
+ junk :int, max: 10 # returns a random number from 0 to 10.
136
+ junk :int, min: 100 # returns a random number from 100 to 2**62-1.
137
+ ```
138
+
139
+ Note: You can mix size with min or max, but they can only be used to further
140
+ restrict the range, not expand it, because that would change the size
141
+ constraint. So these examples work the way you'd expect:
142
+
143
+ ```ruby
144
+ junk :int, size: 4, min: 2000 # random number 2000-9999
145
+ junk :int, size: 4, max: 2000 # random number 1000-2000
146
+ ```
147
+
148
+ But in these examples, `min` and `max` have no effect:
149
+
150
+ ```ruby
151
+ junk :int, size: 2, min: 0 # nope, still gonna get 10-99
152
+ junk :int, size: 2, max: 200 # nope, still gonna get 10-99
153
+ ```
154
+
155
+ Technically, you CAN use BOTH `min` and `max` with `size` to constrain both
156
+ bounds of the number, but this effectively makes the `size` option redundant. It
157
+ will work correctly, but if you remove the size constraint you'll still get the
158
+ same exact range:
159
+
160
+ ```ruby
161
+ # Don't do this - size argument is redundant
162
+ junk :int, size: 3, min: 125, max: 440 # 125-440. size is now redundant.
163
+ ```
164
+
165
+ ### Array / Enumerable
166
+
167
+ If you give junk an `Array`, `Range`, or any other object that implements
168
+ `Enumerable`, it will select an element at random from the collection.
169
+
170
+ ```ruby
171
+ junk [1,3,5,7,9] # pick a 1-digit odd number
172
+ junk (1..5).map {|x| x*2-1 } # pick a 1-digit odd number while trying way too hard
173
+ junk (1..9).step(2) # pick a 1-digit odd number, but now I'm just showing off
174
+ ```
175
+
176
+ *IMPORTANT CAVEAT*: the Enumerable forms all use `.to_a.sample` to get the
177
+ random value, and `.to_a` will cheerfully exhaust all the memory Ruby has if you
178
+ use it on a sufficiently large array.
179
+
180
+ *LESS-IMPORTANT CAVEAT*: Technically anything that can be converted to an array
181
+ and then sampled can go through here, so `words.split` would do what you want,
182
+ but remember that hashes get turned into an array of _pairs_, so expect this
183
+ weirdness if you ask for it:
184
+
185
+ ```ruby
186
+ junk({a: 42, b: 13}) # either [:a, 42] or [:b, 13]
187
+ ```
188
+
189
+ ### Proc
190
+
191
+ When all else fails, it's time to haul out the lambdas, amirite? The first
192
+ argument ot `junk` can be a proc that yields the desired random value. Let's get
193
+ those odd numbers again:
194
+
195
+ ```ruby
196
+ junk ->{ rand(5)*2 + 1 } # 1-digit odd number
197
+ ```
198
+
199
+ ### Other Options
200
+
201
+ ### Exclude
202
+
203
+ Besides the options that `:int` will take, all of the types will accept an
204
+ `exclude` argument. This is useful if you want to generate more than one piece
205
+ of junk data and ensure that they are different. The exclude option can be given
206
+ a single element, an array, or an enumerable, and if all that fails you can give
207
+ it a proc that accepts the generated value and returns true if the value should
208
+ be excluded. Let's use all these excludes to generate odd numbers again:
209
+
210
+ ```ruby
211
+ junk :int, min: 1, max: 3, exclude: 2 # stupid, but it works
212
+ junk (1..9), exclude: [2,4,6,8]
213
+ junk (1..9), exclude: (2..8) # okay, only returns 1 or 9 but hey,
214
+ # they're both odd
215
+ junk :int, exclude: ->(x) { x % 2 == 0 } # reject even numbers
216
+ ```
217
+
218
+ But again, the real advantage is being able to avoid collisions:
219
+
220
+ ```ruby
221
+ let(:id1) { junk (0..9) }
222
+ let(:id2) { junk (0..9), exclude: id1 }
223
+ let(:id3) { junk (0..9), exclude: [id1, id2] }
224
+
225
+ let(:coinflip) { junk :bool }
226
+ let(:otherside) { junk :bool, exclude: coinflip } # Look I never said
227
+ # all of these were great ideas, I'm just saying you can DO them.
228
+ ```
229
+
230
+ *VERY IMPORTANT CAVEAT* If you exclude all of the possibilities from the random
231
+ key space, junk will cheerfully go into an infinite loop.
232
+
233
+ ### Format
234
+
235
+ Formats are here, but need documentating! For now: `format: :int` will cast your
236
+ junk to an integer by calling `.to_i` on it. Other formats include:
237
+
238
+ * `format: :int` calls `.to_i` on the junk before returning it
239
+ * `format: :string` calls `.to_s` on the junk
240
+ * `format: "%s"` (or any other string) calls sprintf on the junk with the
241
+ string as the format string
242
+ * `format: SomeClass` passes the junk to `SomeClass.new`, returning an instance
243
+ of `SomeClass`. *Note:* If you plan on combining this with `exclude`, make
244
+ sure your class implements the `==` operator.
245
+ * `format: ->(x) { ... }` passes the junk to your Proc
246
+
247
+ # TODO
248
+
249
+ * Allow all args to junk to be passed to junklet. Use explicit `type` option to
250
+ specify the type. E.g. `junklet :foo, :bar, :baz, type: :int, max: 14,
251
+ exclude: [:qaz, :qux]`. _(Do we want to allow a flag for mutually exclusive?)_
252
+
253
+ # Background
254
+
255
+ At CoverMyMeds we have a legacy impingement that prevents us sometimes from
256
+ clearing out data from previous test runs. As a result we often have required
257
+ fields in tests that must be unique but are tested elsewhere, so we don't really
258
+ care about them in the current test run. For the current test we just want to
259
+ stub out that field with something unique but we also want to communicate to the
260
+ developer that the contents of the field are not what we currently care about.
261
+
262
+ Currently we do this with `SecureRandom.uuid`, so we'll see code like
263
+ this frequently in RSpec:
264
+
265
+ ```ruby
266
+ let(:first_name) { SecureRandom.uuid }
267
+ let(:last_name) { SecureRandom.uuid }
268
+ let(:address) { SecureRandom.uuid }
269
+ let(:city) { SecureRandom.uuid }
270
+ let(:state) { SecureRandom.uuid }
271
+ let(:phone) { SecureRandom.uuid }
272
+ ```
273
+
274
+ ...etc. Later in the spec we'll often test against those stubs, e.g. with
275
+ `expect(user.first_name).to eq(first_name)` but this idiom expresses that we
276
+ only care about the equality, not the actual contents.
277
+
278
+ Junklet seeks to improve the readability and conciseness of this intention. One
279
+ thing that bugs me about the above approach is that if a weird regression bug
280
+ appears and an unimportant field is the source of a crash. So with Junklet I
281
+ also wanted to add the ability to call out the offending field by name. In
282
+ theory we could just write `let(:first_name) { 'first_name-' + SecureRandom.uuid
283
+ }` but in practice that creates duplication in the code and muddies the original
284
+ idiom of "uncared-about" data.
285
+
286
+ Enter Junklet:
287
+
288
+ ```ruby
289
+ junklet :first_name
290
+ junklet :last_name
291
+ junklet :address
292
+ junklet :city
293
+ junklet :state
294
+ junklet :phone
295
+ ```
296
+
297
+ Or, if you don't want the junklets to sprawl vertically,
298
+
299
+ ```ruby
300
+ junklet :first_name, :last_name, :address, :city, :state, :phone
301
+ ```
302
+
303
+ This will have the same effect as calling `let` on the named fields and setting
304
+ the fieldname and a 32-byte hex string (a uuid with hyphens removed) to be the
305
+ memoized value.
306
+
307
+ ## Contributing
308
+
309
+ 1. Fork it ( https://github.com/[my-github-username]/junklet/fork )
310
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
311
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
312
+ 4. Write specs to document how your change is to be used
313
+ 5. Push to the branch (`git push origin my-new-feature`)
314
+ 6. Create a new Pull Request
@@ -0,0 +1,118 @@
1
+ module Junklet
2
+ module Junk
3
+ def junk(*args)
4
+ # TODO: It's long past time to extract this....
5
+
6
+ # args.first can be
7
+ # - an integer indicating the size of the hex string to return
8
+ # - a symbol denoting the base type, e.g. :int
9
+ # - an array to sample from
10
+ # - a range or Enumerable to sample from. WARNING: will call
11
+ # .to_a on it first, which might be expensive
12
+ # - a generator Proc which, when called, will generate the
13
+ # value to use.
14
+ #
15
+ # args.rest is a hash of options:
16
+ # - sequence: Proc or Array of values to choose from.
17
+ # - exclude: value, array of values, or proc to exclude. If a
18
+ # Proc is given, it takes the value generated and returns
19
+ # true if the value should be excluded.
20
+ #
21
+ # - for int:
22
+ # - min: minimum number to return. Default: 0
23
+ # - max: upper limit of range
24
+ # - exclude: number, array of numbers, or proc to
25
+ # exclude. If Proc is provided, tests the number against
26
+ # the Proc an excludes it if the Proc returns true. This
27
+ # is implemented except for the proc.
28
+
29
+ # FIXME: Raise Argument error unless *args.size is 0-2
30
+ # FIXME: If arg 1 is a hash, it's the options hash, raise
31
+ # ArgumentError unless args.size == 1
32
+ # FIXME: If arg 2 present, Raise Argument error unless it's a
33
+ # hash.
34
+ # FIXME: Figure out what our valid options are and parse them;
35
+ # raise errors if present.
36
+
37
+ junk_types = [Symbol, Array, Enumerable, Proc]
38
+ if args.size > 0 && junk_types.any? {|klass| args.first.is_a?(klass) }
39
+ type = args.shift
40
+ opts = args.last || {}
41
+
42
+ excluder = if opts[:exclude]
43
+ if opts[:exclude].is_a?(Proc)
44
+ opts[:exclude]
45
+ else
46
+ ->(x) { Array(opts[:exclude]).include?(x) }
47
+ end
48
+ else
49
+ ->(x) { false }
50
+ end
51
+
52
+ formatter = case opts[:format]
53
+ when :string
54
+ ->(x) { x.to_s }
55
+ when :int
56
+ ->(x) { x.to_i }
57
+ when String
58
+ ->(x) { sprintf(opts[:format], x) }
59
+ when Class
60
+ ->(x) { opts[:format].new(x) }
61
+ when Proc
62
+ opts[:format]
63
+ else
64
+ ->(x) { x }
65
+ end
66
+
67
+ # TODO: Refactor me. Seriously, this is a functional
68
+ # programming version of the strategy pattern. Wouldn't it
69
+ # be neat if we had some kind of object-oriented language
70
+ # available here?
71
+ case type
72
+ when :int
73
+ # min,max cooperate with size to further constrain it. So
74
+ # size: 2, min: 30 would be min 30, max 99.
75
+ if opts[:size]
76
+ sized_min = 10**(opts[:size]-1)
77
+ sized_max = 10**opts[:size]-1
78
+ end
79
+ explicit_min = opts[:min] || 0
80
+ explicit_max = (opts[:max] || 2**62-2) + 1
81
+
82
+ if sized_min
83
+ min = [sized_min, explicit_min].max
84
+ max = [sized_max, explicit_max].min
85
+ else
86
+ min = sized_min || explicit_min
87
+ max = sized_max || explicit_max
88
+ end
89
+
90
+ min,max = max,min if min>max
91
+
92
+ generator = -> { rand(max-min) + min }
93
+ when :bool
94
+ generator = -> { [true, false].sample }
95
+ when Array, Enumerable
96
+ generator = -> { type.to_a.sample }
97
+ when Proc
98
+ generator = type
99
+ else
100
+ raise "Unrecognized junk type: '#{type}'"
101
+ end
102
+
103
+ begin
104
+ val = formatter.call(generator.call)
105
+ end while excluder.call(val)
106
+ val
107
+ else
108
+ size = args.first.is_a?(Numeric) ? args.first : 32
109
+ # hex returns size*2 digits, because it returns a 0..255 byte
110
+ # as a hex pair. But when we want junt, we want *bytes* of
111
+ # junk. Get (size+1)/2 chars, which will be correct for even
112
+ # sizes and 1 char too many for odds, so trim off with
113
+ # [0...size] (note three .'s to trim off final char)
114
+ SecureRandom.hex((size+1)/2)[0...size]
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,25 @@
1
+ module Junklet
2
+ module Junklet
3
+ def junklet(*args)
4
+ # TODO: figure out how to use this to wrap junk in junklet,
5
+ # so that junklet can basically have all the same options as
6
+ # junk does. E.g. junklet :ddid, :pcn, :group, type: :int,
7
+ # min: 100000, max: 999999, etc, and you'd get back 3
8
+ # junklets of 6-digit numbers.
9
+ opts = args.size > 1 && !args.last.is_a?(Symbol) && args.pop || {}
10
+
11
+ names = args.map(&:to_s)
12
+
13
+ separator = opts[:separator] || '_'
14
+ names = names.map {|name| name.gsub(/_/, separator)}
15
+
16
+ args.zip(names).each do |arg, name|
17
+ make_junklet arg, name, separator, junk
18
+ end
19
+ end
20
+
21
+ def make_junklet(let_name, name, separator, junk_data)
22
+ let(let_name) { "#{name}#{separator}#{junk_data}" }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Junklet
2
+ VERSION = "1.1.0"
3
+ end
data/lib/junklet.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "junklet/version"
2
+ require "junklet/junk"
3
+ require "junklet/junklet"
4
+
5
+ RSpec.configure do |config|
6
+ config.extend(Junklet::Junklet)
7
+ config.extend(Junklet::Junk) # when metaprogramming cases, you may need junk in ExampleGroups
8
+ config.include(Junklet::Junk)
9
+ end
data/lib/line.rb ADDED
@@ -0,0 +1,44 @@
1
+ class Line < String
2
+ def initialize(line="")
3
+ super
4
+ end
5
+
6
+ def indent
7
+ ' ' * (size - lstrip.size)
8
+ end
9
+
10
+ def let?
11
+ match(/^\s*let\s*\(/) && !junklet?
12
+ end
13
+
14
+ def junklet?
15
+ already_junklet? || secure_random?
16
+ end
17
+
18
+ def already_junklet?
19
+ match(/^\s*junklet\b/)
20
+ end
21
+
22
+ def secure_random?
23
+ match(/^\s*(let)\s*\(?([^)]*)\)\s*{\s*SecureRandom.(uuid|hex)\s*}/)
24
+ end
25
+
26
+ def code?
27
+ empty? || (!let? && !junklet?)
28
+ end
29
+
30
+ def names
31
+ return nil unless let? || junklet?
32
+ match(/^\s*(let|junklet)\s*\(?([^)]*)\)?/) \
33
+ .captures[1..-1] \
34
+ .join('') \
35
+ .split(/,/) \
36
+ .map(&:strip)
37
+ end
38
+
39
+ def convert
40
+ return nil unless junklet?
41
+ return self if already_junklet?
42
+ Line.new("#{indent}junklet #{names.first}")
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'junklet/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rspec-junklet"
8
+ spec.version = Junklet::VERSION
9
+ spec.authors = ["David Brady"]
10
+ spec.email = ["dbrady@shinybit.com"]
11
+ spec.summary = "Easily create junk data for specs"
12
+ spec.description = "Works like let for rspec, but creates unique random junk data"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 2.0"
24
+ spec.add_development_dependency "cucumber"
25
+ spec.add_development_dependency "pry"
26
+ end
@@ -0,0 +1,6 @@
1
+ let(:name) { "Bob" }
2
+ let(:city) { "Faketown" }
3
+ let(:extra) { true }
4
+ let(:pants) { ON_FIRE }
5
+
6
+ junklet :address, :state, :zip
@@ -0,0 +1,7 @@
1
+ let(:name) { "Bob" }
2
+ junklet :address
3
+ let(:city) { "Faketown" }
4
+ junklet :state
5
+ junklet :zip
6
+ let(:extra) { true }
7
+ let(:pants) { ON_FIRE }