centric_data_magic 1.2.4

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,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.4'
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 'debug'
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
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ class UserPage
6
+ include DataMagic
7
+ end
8
+
9
+ class MockScenario
10
+ attr_accessor :tags
11
+
12
+ def initialize(tags)
13
+ @tags = tags
14
+ end
15
+ end
16
+
17
+ class MockTag
18
+ attr_reader :name, :line
19
+
20
+ def initialize(name, line)
21
+ @name = name
22
+ @line = line
23
+ end
24
+ end
25
+
26
+ describe DataMagic do
27
+ context 'when configuring the yml directory' do
28
+ before(:each) do
29
+ DataMagic.yml_directory = nil
30
+ end
31
+
32
+ it 'should default to a directory named config' do
33
+ expect(DataMagic.yml_directory).to eql 'config/data'
34
+ end
35
+
36
+ it 'should store a yml directory' do
37
+ DataMagic.yml_directory = 'test_dir'
38
+ expect(DataMagic.yml_directory).to eql 'test_dir'
39
+ end
40
+
41
+ it 'should accept and use locale' do
42
+ expect(Faker::Config).to receive(:locale=).with('blah')
43
+ DataMagic.locale = 'blah'
44
+ end
45
+ end
46
+
47
+ context 'when reading yml files' do
48
+ it 'should read files from the config directory' do
49
+ DataMagic.yml = nil
50
+ DataMagic.load('user.yml')
51
+ data = UserPage.new.data_for 'valid'
52
+ expect(data.keys.sort).to eq(%w[job name])
53
+ end
54
+
55
+ it 'should default to reading a file named default.yml' do
56
+ DataMagic.yml_directory = 'config/data'
57
+ DataMagic.yml = nil
58
+ data = UserPage.new.data_for :dm
59
+ expect(data.keys).to include('value1')
60
+ end
61
+
62
+ it 'should use the value of DATA_MAGIC_FILE if it exists' do
63
+ DataMagic.yml_directory = 'config/data'
64
+ DataMagic.yml = nil
65
+ ENV['DATA_MAGIC_FILE'] = 'user.yml'
66
+ data = UserPage.new.data_for 'valid'
67
+ expect(data.keys.sort).to eq(%w[job name])
68
+ ENV['DATA_MAGIC_FILE'] = nil
69
+ end
70
+
71
+ it 'should merge additional data to the same key if not present in addtional' do
72
+ DataMagic.yml_directory = 'config/data'
73
+ data = UserPage.new.data_for 'user/valid', { 'job' => 'Overlord' }
74
+ expect(data['job']).to eq('Overlord')
75
+ end
76
+ it 'should merge additional data to resulting hash if present in additional data' do
77
+ DataMagic.yml_directory = 'config/data'
78
+ data = UserPage.new.data_for 'user/valid', { 'valid' => { 'job' => 'Overlord' } }
79
+ expect(data['job']).to eq('Overlord')
80
+ end
81
+ end
82
+
83
+ context 'namespaced keys' do
84
+ it 'loads correct file and retrieves data' do
85
+ DataMagic.yml_directory = 'config/data'
86
+ data = UserPage.new.data_for 'user/valid'
87
+ expect(data.keys.sort).to eq(%w[job name])
88
+ end
89
+ end
90
+
91
+ context 'loading fixtures for cucumber scenarios' do
92
+ it 'loads the fixture for a scenario' do
93
+ DataMagic.yml_directory = 'config/data'
94
+ scenario = MockScenario.new([MockTag.new('@tag', 1), MockTag.new('@datamagic_user', 1)])
95
+ expect(DataMagic).to receive(:load).with('user.yml')
96
+ DataMagic.load_for_scenario scenario
97
+ end
98
+
99
+ it 'uses the last fixture listed for a scenario if multiple exist' do
100
+ scenario = MockScenario.new([MockTag.new('@fixture_default', 1), MockTag.new('@datamagic_user', 1)])
101
+ expect(DataMagic).to receive(:load).with('user.yml')
102
+ DataMagic.load_for_scenario scenario
103
+ end
104
+
105
+ it 'allows you to force loading from a different folder without stepping on the global folder' do
106
+ DataMagic.yml_directory = 'features'
107
+ scenario = MockScenario.new([MockTag.new('@tag', 1), MockTag.new('@datamagic_user', 1)])
108
+ expect(DataMagic).to receive(:load).with('user.yml')
109
+ DataMagic.load_for_scenario scenario, 'config/data'
110
+ expect(DataMagic.yml_directory).to eq('features')
111
+ end
112
+ end
113
+ end