new_data_magic 1.2

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.
@@ -0,0 +1,65 @@
1
+ dm:
2
+ value1: this is value 1
3
+ value2: this is value 2
4
+ full_name: ~full_name
5
+ first_name: ~first_name
6
+ last_name: ~last_name
7
+ name_prefix: ~name_prefix
8
+ name_suffix: ~name_suffix
9
+ street: ~street_address
10
+ street_plus: ~street_address(true)
11
+ city: ~city
12
+ state: ~state
13
+ state_ab: ~state_abbr
14
+ zip: ~zip_code
15
+ country: ~country
16
+ second_address: ~secondary_address
17
+ company: ~company_name
18
+ email: ~email_address
19
+ email_plus: ~email_address('buddy')
20
+ domain_name: ~domain_name
21
+ url: ~url
22
+ user_name: ~user_name
23
+ phone: ~phone_number
24
+ cell: ~cell_phone
25
+ catch_phrase: ~catch_phrase
26
+ words: ~words
27
+ sentence: ~sentence
28
+ sentences: ~sentences
29
+ paragraphs: ~paragraphs
30
+ characters: ~characters
31
+ bool_true: true
32
+ bool_false: false
33
+ random: ~randomize ['Tom', 'Dick', 'Harry']
34
+ ordered: ~sequential ['first', 'second', 'third']
35
+ range: ~randomize 1..5
36
+ mask: ~mask "###-AAA_aaa"
37
+ job_title: ~job_title
38
+ today: ~today
39
+ tomorrow: ~tomorrow
40
+ yesterday: ~yesterday
41
+ 5daysfromtoday: ~5.days_from_today
42
+ 5daysago: ~5.days_ago
43
+ some_month: ~month
44
+ month_abbr: ~month_abbr
45
+ some_day: ~day_of_week
46
+ day_abbr: ~day_of_week_abbr
47
+ this:
48
+ is_nested: Nested Value
49
+ translate_nested:
50
+ full_name: ~full_name
51
+ first_name: ~first_name
52
+ color_hex: ~color_hex
53
+ color_name: ~color_name
54
+ number: ~number(digits = 10, true)
55
+ decimal: ~decimal(before_decimal = 5, after_decimal = 3)
56
+ merge: ~merge(separator = '--', [first_name, last_name, number(3)])
57
+ date_between: ~date_between(from = '01/01/2021', to = '31/12/2021', format = '%d/%m/%y')
58
+
59
+ dynamic:
60
+ blah: ~blah
61
+
62
+ other:
63
+ name: Cheezy
64
+ address: 123 Main Street
65
+ email: cheezy@example.com
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ def deep_copy
5
+ Marshal.load(Marshal.dump(self))
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Integer
4
+ def days_from_today(format = '%D')
5
+ the_day = Date.today + self
6
+ the_day.strftime(format)
7
+ end
8
+
9
+ def days_ago(format = '%D')
10
+ the_day = Date.today - self
11
+ the_day.strftime(format)
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ def is_integer
5
+ true if Integer(self)
6
+ rescue StandardError
7
+ false
8
+ end
9
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMagic
4
+ module DateTranslation
5
+ #
6
+ # return today's date
7
+ #
8
+ # @param String the format to use for the date. Default is %D
9
+ #
10
+ # See http://ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html#method-i-strftime
11
+ # for details of the formats
12
+ #
13
+ def today(format = '%D')
14
+ Date.today.strftime(format)
15
+ end
16
+ alias dm_today today
17
+
18
+ #
19
+ # return tomorrow's date
20
+ #
21
+ # @param String the format to use for the date. Default is %D
22
+ #
23
+ # See http://ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html#method-i-strftime
24
+ # for details of the formats
25
+ #
26
+ def tomorrow(format = '%D')
27
+ tomorrow = Date.today + 1
28
+ tomorrow.strftime(format)
29
+ end
30
+ alias dm_tomorrow tomorrow
31
+
32
+ #
33
+ # return yesterday's date
34
+ #
35
+ # @param String the format to use for the date. Default is %D
36
+ #
37
+ # See http://ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html#method-i-strftime
38
+ # for details of the formats
39
+ #
40
+ def yesterday(format = '%D')
41
+ yesterday = Date.today - 1
42
+ yesterday.strftime(format)
43
+ end
44
+ alias dm_yesterday yesterday
45
+
46
+ #
47
+ # return a month
48
+ #
49
+ def month
50
+ randomize(Date::MONTHNAMES[1..-1])
51
+ end
52
+ alias dm_month month
53
+
54
+ #
55
+ # return a month abbreviation
56
+ #
57
+ def month_abbr
58
+ randomize(Date::ABBR_MONTHNAMES[1..-1])
59
+ end
60
+ alias dm_month_abbr month_abbr
61
+
62
+ #
63
+ # return a day of the week
64
+ #
65
+ def day_of_week
66
+ randomize(Date::DAYNAMES)
67
+ end
68
+ alias dm_day_of_week day_of_week
69
+
70
+ def day_of_week_abbr
71
+ randomize(Date::ABBR_DAYNAMES)
72
+ end
73
+ alias dm_day_of_week_abbr day_of_week_abbr
74
+
75
+ ##################################################################
76
+ # #
77
+ # NEW TRANSLATOR STARTS HERE #
78
+ # #
79
+ ##################################################################
80
+
81
+ #
82
+ # return random date within the range
83
+ #
84
+ def date_between(from = nil, to = nil, format = '%D')
85
+ raise ArgumentError, 'Invalid date format' if from.to_s.empty? || to.to_s.empty?
86
+
87
+ start_date = from.nil? ? Date.today.strftime(format) : Date.strptime(from, format)
88
+ end_date = to.nil? ? Date.today.strftime(format) : Date.strptime(to, format)
89
+
90
+ Faker::Date.between(from: start_date, to: end_date).strftime(format)
91
+ end
92
+ alias dm_date_between date_between
93
+
94
+ ##################################################################
95
+ # #
96
+ # NEW TRANSLATOR ENDS HERE #
97
+ # #
98
+ ##################################################################
99
+ end
100
+ end
@@ -0,0 +1,370 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMagic
4
+ module StandardTranslation
5
+ attr_reader :parent
6
+
7
+ #
8
+ # return a random name (first and last)
9
+ #
10
+ def full_name
11
+ Faker::Name.name
12
+ end
13
+ alias dm_full_name full_name
14
+
15
+ #
16
+ # return a random first name
17
+ #
18
+ def first_name
19
+ Faker::Name.first_name
20
+ end
21
+ alias dm_first_name first_name
22
+
23
+ #
24
+ # return a random last name
25
+ #
26
+ def last_name
27
+ Faker::Name.last_name
28
+ end
29
+ alias dm_last_name last_name
30
+
31
+ #
32
+ # return a random name prefix
33
+ #
34
+ def name_prefix
35
+ Faker::Name.prefix
36
+ end
37
+ alias dm_name_prefix name_prefix
38
+
39
+ #
40
+ # return a random name suffix
41
+ #
42
+ def name_suffix
43
+ Faker::Name.suffix
44
+ end
45
+ alias dm_name_suffix name_suffix
46
+
47
+ #################################################################################
48
+ # In newer version of Faker, Faker::Name.title is changed to Faker::Job.title #
49
+ #################################################################################
50
+
51
+ #
52
+ # return a random job title
53
+ #
54
+ def job_title
55
+ Faker::Job.title
56
+ end
57
+ alias dm_job_title job_title
58
+
59
+ #
60
+ # return a random street address
61
+ #
62
+ def street_address(include_secondary = false)
63
+ Faker::Address.street_address(include_secondary: include_secondary)
64
+ end
65
+ alias dm_street_address street_address
66
+
67
+ #
68
+ # return a random secondary address
69
+ #
70
+ def secondary_address
71
+ Faker::Address.secondary_address
72
+ end
73
+ alias dm_secondary_address secondary_address
74
+
75
+ #
76
+ # return a random city
77
+ #
78
+ def city
79
+ Faker::Address.city
80
+ end
81
+ alias dm_city city
82
+
83
+ #
84
+ # return a random state
85
+ #
86
+ def state
87
+ Faker::Address.state
88
+ end
89
+ alias dm_state state
90
+
91
+ #
92
+ # return a random state abbreviation
93
+ #
94
+ def state_abbr
95
+ Faker::Address.state_abbr
96
+ end
97
+ alias dm_state_abbr state_abbr
98
+
99
+ #
100
+ # return a random 5 or 9 digit zip code
101
+ #
102
+ def zip_code
103
+ Faker::Address.zip
104
+ end
105
+ alias dm_zip_code zip_code
106
+
107
+ #
108
+ # return a random country
109
+ #
110
+ def country
111
+ Faker::Address.country
112
+ end
113
+ alias dm_country country
114
+
115
+ #
116
+ # return a random company name
117
+ #
118
+ def company_name
119
+ Faker::Company.name
120
+ end
121
+ alias dm_company_name company_name
122
+
123
+ #
124
+ # return a random catch phrase
125
+ #
126
+ def catch_phrase
127
+ Faker::Company.catch_phrase
128
+ end
129
+ alias dm_catch_phrase catch_phrase
130
+
131
+ #
132
+ # return a credit card number
133
+ #
134
+ def credit_card_number
135
+ Faker::Business.credit_card_number
136
+ end
137
+ alias dm_credit_card_number credit_card_number
138
+
139
+ #
140
+ # return a credit card type
141
+ #
142
+ def credit_card_type
143
+ Faker::Business.credit_card_type
144
+ end
145
+ alias dm_credit_card_type credit_card_type
146
+
147
+ #
148
+ # return random words - default is 3 words
149
+ #
150
+ def words(number = 3)
151
+ Faker::Lorem.words(number: number).join(' ')
152
+ end
153
+ alias dm_words words
154
+
155
+ #
156
+ # return a random sentence - default minimum word count is 4
157
+ #
158
+ def sentence(min_word_count = 4)
159
+ Faker::Lorem.sentence(word_count: min_word_count)
160
+ end
161
+ alias dm_sentence sentence
162
+
163
+ #
164
+ # return random sentences - default is 3 sentences
165
+ #
166
+ def sentences(sentence_count = 3)
167
+ Faker::Lorem.sentences(number: sentence_count).join(' ')
168
+ end
169
+ alias dm_sentences sentences
170
+
171
+ #
172
+ # return random paragraphs - default is 3 paragraphs
173
+ #
174
+ def paragraphs(paragraph_count = 3)
175
+ Faker::Lorem.paragraphs(number: paragraph_count).join('\n\n')
176
+ end
177
+ alias dm_paragraphs paragraphs
178
+
179
+ #
180
+ # return random characters - default is 255 characters
181
+ #
182
+ def characters(character_count = 255)
183
+ Faker::Lorem.characters(number: character_count)
184
+ end
185
+ alias dm_characters characters
186
+
187
+ #
188
+ # return a random email address
189
+ #
190
+ def email_address(name = nil, domain = nil)
191
+ Faker::Internet.email(name: name, domain: domain)
192
+ end
193
+ alias dm_email_address email_address
194
+
195
+ #
196
+ # return a random domain name
197
+ #
198
+ def domain_name
199
+ Faker::Internet.domain_name
200
+ end
201
+ alias dm_domain_name domain_name
202
+
203
+ #
204
+ # return a random url
205
+ #
206
+ def url
207
+ Faker::Internet.url
208
+ end
209
+ alias dm_url url
210
+
211
+ #
212
+ # return a random user name
213
+ #
214
+ def user_name
215
+ Faker::Internet.user_name
216
+ end
217
+ alias dm_user_name user_name
218
+
219
+ #
220
+ # return a random phone number
221
+ #
222
+ def phone_number
223
+ value = Faker::PhoneNumber.phone_number
224
+ remove_extension(value)
225
+ end
226
+ alias dm_phone_number phone_number
227
+
228
+ #
229
+ # return a random cell number
230
+ #
231
+ def cell_phone
232
+ value = Faker::PhoneNumber.cell_phone
233
+ remove_extension(value)
234
+ end
235
+ alias dm_cell_phone cell_phone
236
+
237
+ #
238
+ # return a random value from an array or range
239
+ #
240
+ def randomize(value)
241
+ case value
242
+ when Array then value[rand(value.size)]
243
+ when Range then rand((value.last + 1) - value.first) + value.first
244
+ else value
245
+ end
246
+ end
247
+ alias dm_randomize randomize
248
+
249
+ #
250
+ # return an element from the array. The first request will return
251
+ # the first element, the second request will return the second,
252
+ # and so forth.
253
+ #
254
+ def sequential(value)
255
+ index = index_variable_for(value)
256
+ index = (index ? index + 1 : 0)
257
+ index = 0 if index == value.length
258
+ set_index_variable(value, index)
259
+ value[index]
260
+ end
261
+
262
+ #
263
+ # return a value based on a mast
264
+ # The # character will be replaced with a number
265
+ # The A character will be replaced with an upper case letter
266
+ # The a character will be replaced with a lower case letter
267
+ #
268
+ def mask(value)
269
+ result = ''
270
+ value.each_char do |ch|
271
+ result += case ch
272
+ when '#' then randomize(0..9).to_s
273
+ when 'A' then ('A'..'Z').to_a[rand(26)]
274
+ when 'a' then ('a'..'z').to_a[rand(26)]
275
+ else ch
276
+ end
277
+ end
278
+ result
279
+ end
280
+ alias dm_mask mask
281
+
282
+ ##################################################################
283
+ # #
284
+ # NEW TRANSLATOR STARTS HERE #
285
+ # #
286
+ ##################################################################
287
+
288
+ #
289
+ # return a random color code in hex
290
+ #
291
+ def color_hex
292
+ Faker::Color.hex_color
293
+ end
294
+ alias dm_color_hex color_hex
295
+
296
+ #
297
+ # return a random color name
298
+ #
299
+ def color_name
300
+ Faker::Color.color_name
301
+ end
302
+ alias dm_color_name color_name
303
+
304
+ #
305
+ # return a random number in specified digits
306
+ #
307
+ def number(digits, leading_zero = false)
308
+ leading_zero ? Faker::Number.leading_zero_number(digits: digits) : Faker::Number.number(digits: digits)
309
+ end
310
+ alias dm_number number
311
+
312
+ #
313
+ # return a random number in decimal
314
+ #
315
+ def decimal(before_decimal, after_decimal = 2)
316
+ Faker::Number.decimal(l_digits: before_decimal, r_digits: after_decimal)
317
+ end
318
+ alias dm_decimal decimal
319
+
320
+ #
321
+ # merge variables
322
+ #
323
+ def merge(separator = ' ', *params)
324
+ params.join(separator)
325
+ end
326
+ alias dm_merge merge
327
+
328
+ ##################################################################
329
+ # #
330
+ # NEW TRANSLATOR ENDS HERE #
331
+ # #
332
+ ##################################################################
333
+
334
+ private
335
+
336
+ def set_index_variable(ary, value)
337
+ index_hash[index_name(ary)] = value
338
+ end
339
+
340
+ def index_variable_for(ary)
341
+ value = index_hash[index_name(ary)]
342
+ index_hash[index_name(ary)] = -1 unless value
343
+ index_hash[index_name(ary)]
344
+ end
345
+
346
+ def index_name(ary)
347
+ "#{ary[0]}#{ary[1]}_index".gsub(' ', '_').downcase
348
+ end
349
+
350
+ def index_hash
351
+ dh = data_hash[parent]
352
+ data_hash[parent] = {} unless dh
353
+ data_hash[parent]
354
+ end
355
+
356
+ def data_hash
357
+ $data_magic_data_hash ||= {}
358
+ end
359
+
360
+ def process(value)
361
+ eval value
362
+ end
363
+
364
+ def remove_extension(phone)
365
+ index = phone.index('x')
366
+ phone = phone[0, (index - 1)] if index
367
+ phone
368
+ end
369
+ end
370
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'data_magic/date_translation'
4
+ require 'data_magic/standard_translation'
5
+
6
+ module DataMagic
7
+ class Translation
8
+ include StandardTranslation
9
+ include DateTranslation
10
+
11
+ def initialize(parent)
12
+ @parent = parent
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DataMagic
4
+ VERSION = '1.2'
5
+ end
data/lib/data_magic.rb ADDED
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'data_magic/core_ext/string'
4
+ require 'data_magic/core_ext/integer'
5
+ require 'data_magic/core_ext/hash'
6
+ require 'data_magic/version'
7
+ require 'data_magic/translation'
8
+ require 'data_magic/date_translation'
9
+ require 'data_magic/standard_translation'
10
+ require 'yml_reader'
11
+ require 'faker'
12
+ require 'byebug'
13
+
14
+ module DataMagic
15
+ extend YmlReader
16
+ extend StandardTranslation
17
+ extend DateTranslation
18
+
19
+ attr_reader :parent
20
+
21
+ I18n.enforce_available_locales = false if I18n.respond_to? :enforce_available_locales
22
+
23
+ def self.locale=(value)
24
+ Faker::Config.locale = value
25
+ end
26
+
27
+ def self.included(cls)
28
+ @parent = cls
29
+ translators.each do |translator|
30
+ Translation.send :include, translator
31
+ end
32
+ end
33
+
34
+ def data_for(key, additional = {})
35
+ if key.is_a?(String) && key.match(%r{/})
36
+ filename, record = key.split('/')
37
+ DataMagic.load("#{filename}.yml")
38
+ else
39
+ record = key.to_s
40
+ DataMagic.load(the_file) unless DataMagic.yml
41
+ end
42
+ data = DataMagic.yml[record]
43
+ raise ArgumentError, "Undefined key #{key}" unless data
44
+
45
+ prep_data(data.merge(additional.key?(record) ? additional[record] : additional).deep_copy)
46
+ end
47
+
48
+ # Given a scenario, load any fixture it needs.
49
+ # Fixture tags should be in the form of @datamagic_FIXTUREFILE
50
+ def self.load_for_scenario(scenario, fixture_folder = DataMagic.yml_directory)
51
+ orig_yml_directory = DataMagic.yml_directory
52
+ DataMagic.yml_directory = fixture_folder
53
+ fixture_files = fixture_files_on(scenario)
54
+
55
+ DataMagic.load "#{fixture_files.last}.yml" if fixture_files.count.positive?
56
+ DataMagic.yml_directory = orig_yml_directory
57
+ end
58
+
59
+ private_class_method
60
+
61
+ def the_file
62
+ ENV['DATA_MAGIC_FILE'] || 'default.yml'
63
+ end
64
+
65
+ def prep_data(data)
66
+ case data
67
+ when Hash
68
+ data.each { |key, value| data[key] = prep_data(value) }
69
+ when Array
70
+ data.each_with_index { |value, i| data[i] = prep_data(value) }
71
+ when String
72
+ return translate(data[1..-1]) if data[0, 1] == '~'
73
+ end
74
+ data
75
+ end
76
+
77
+ def translate(value)
78
+ translation.send :process, value
79
+ rescue StandardError => e
80
+ raise "Failed to translate: #{value}\n Reason: #{e.message}\n"
81
+ end
82
+
83
+ def translation
84
+ @translation ||= Translation.new parent
85
+ end
86
+
87
+ # Load a fixture and merge it with an existing hash
88
+ def self.load_fixture_and_merge_with(fixture_name, base_hash, fixture_folder = DEFAULT_FIXTURE_FOLDER)
89
+ new_hash = load_fixture(fixture_name, fixture_folder)
90
+ base_hash.deep_merge new_hash
91
+ end
92
+
93
+ def self.fixture_files_on(scenario)
94
+ # tags for cuke 2, source_tags for cuke 1
95
+ tags = scenario.send(scenario.respond_to?(:tags) ? :tags : :source_tags)
96
+ tags.map(&:name).select { |t| t =~ /@datamagic_/ }.map { |t| t.gsub('@datamagic_', '').to_sym }
97
+ end
98
+
99
+ class << self
100
+ attr_accessor :yml
101
+
102
+ def default_directory
103
+ 'config/data'
104
+ end
105
+
106
+ def add_translator(translator)
107
+ translators << translator
108
+ end
109
+
110
+ def translators
111
+ @translators ||= []
112
+ end
113
+ end
114
+ end