testcentricity_mobile 4.1.7 → 4.1.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/LICENSE.md +1 -1
- data/README.md +7 -7
- data/lib/testcentricity_mobile/app_core/screen_objects_helper.rb +10 -0
- data/lib/testcentricity_mobile/data_objects/data_objects_helper.rb +148 -53
- data/lib/testcentricity_mobile/data_objects/environment.rb +19 -19
- data/lib/testcentricity_mobile/version.rb +1 -1
- metadata +36 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4961bdc97a13ad7e08236fad109326f00a67a8d790a79257cb44691f1c435d61
|
|
4
|
+
data.tar.gz: 3b82d3cfb16db8d46264fb149ac8bf0d34866c437e5461e92f14b26697dfea09
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 581d29d4727c72b30aa217a16cb91e542d05c183beba6f912788852b7dccebeb8ca3ea6d467298145509ea2efda4bc8115b31c8243dfbc6ac51bf2ad4da4baf4
|
|
7
|
+
data.tar.gz: 1a330c7e44dde5c2e727d02e47c4bf8d9048b6ccd2a6af0e129882533ce81564f8f9cccfc7ddedf6fc57175f96c3d5f6702332acfbcdca1430658c452ed5722e
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## [4.1.8] - 13-JAN-2026
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
* Added `activesupport` gem as a runtime dependency to prevent test failures if gem is not already installed.
|
|
9
|
+
* Added `DataSource.read_file` method capable of reading from `.yml`, `.json`, `.csv`, or `.xml` data files, and accepting
|
|
10
|
+
`options` hash for specifying hash key and value conversions to data being read prior to passing to `DataPresenter` objects.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
* Refactored `EnvironData.read` method to allow passing `options` hash for specifying hash key and value conversions to
|
|
14
|
+
data being read prior to passing to `DataPresenter` objects.
|
|
15
|
+
* Refactored `ScreenObject.populate_data_fields` and `ScreenSection.populate_data_fields` methods to support passing a
|
|
16
|
+
`Symbol` for a UI element's name to support using `DataPresenter` object attributes to source data.
|
|
17
|
+
* Updated `appium_lib` gem to version 16.1.1.
|
|
18
|
+
* Updated `appium_lib_core` gem to version 11.2.0.
|
|
19
|
+
|
|
20
|
+
### Removed
|
|
21
|
+
* Unused `DataObject` class has been removed.
|
|
22
|
+
* Removed unused `DataSource.read_yaml_node_data` and `DataSource.read_json_node_data` methods.
|
|
23
|
+
|
|
24
|
+
|
|
5
25
|
## [4.1.7] - 25-NOV-2025
|
|
6
26
|
|
|
7
27
|
### Changed
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
|
@@ -95,12 +95,12 @@ A **Screen Object** is an object that represents a single screen in your AUT (Ap
|
|
|
95
95
|
encapsulate the implementation details of a mobile app screen and expose an API that supports interaction with, and validation
|
|
96
96
|
of the UI elements on the screen.
|
|
97
97
|
|
|
98
|
-
**Screen Objects** makes it easier to maintain automated tests because changes to screen UI elements are updated in
|
|
99
|
-
one location - in the `ScreenObject` class definition. By adopting a **Screen Object Model**, Cucumber
|
|
100
|
-
step definitions are no longer required to hold specific information about a screen's UI objects, thus
|
|
101
|
-
requirements. If any element on, or property of a screen changes (text field attributes, button
|
|
102
|
-
etc.), maintenance is performed in the `ScreenObject` class definition only, typically
|
|
103
|
-
feature files, scenarios, or step definitions.
|
|
98
|
+
**Screen Objects** makes it easier to maintain automated tests because changes to a screen's UI elements are updated in
|
|
99
|
+
only one location - in the corresponding `ScreenObject` class definition. By adopting a **Screen Object Model**, Cucumber
|
|
100
|
+
feature files and step definitions are no longer required to hold specific information about a screen's UI objects, thus
|
|
101
|
+
minimizing maintenance requirements. If any element on, or property of a screen changes (text field attributes, button
|
|
102
|
+
captions, element states, etc.), maintenance is performed in the corresponding `ScreenObject` class definition only, typically
|
|
103
|
+
with no need to update the affected feature files, scenarios, or step definitions.
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
### Defining a ScreenObject
|
|
@@ -2010,7 +2010,7 @@ the `/features/support/<platform>/sections` folder, where `<platform>` is typica
|
|
|
2010
2010
|
---
|
|
2011
2011
|
## Copyright and License
|
|
2012
2012
|
|
|
2013
|
-
TestCentricity™ Framework is Copyright (c) 2014-
|
|
2013
|
+
TestCentricity™ Framework is Copyright (c) 2014-2026, Tony Mrozinski.
|
|
2014
2014
|
All rights reserved.
|
|
2015
2015
|
|
|
2016
2016
|
Redistribution and use in source and binary forms, with or without
|
|
@@ -51,6 +51,16 @@ module TestCentricity
|
|
|
51
51
|
timeout = wait_time.nil? ? 2 : wait_time
|
|
52
52
|
data.each do |data_field, data_param|
|
|
53
53
|
unless data_param.blank?
|
|
54
|
+
# if data_field is a Symbol, find the corresponding object reference
|
|
55
|
+
if data_field.is_a?(Symbol)
|
|
56
|
+
begin
|
|
57
|
+
obj = method(data_field)
|
|
58
|
+
rescue
|
|
59
|
+
puts "No corresponding data field found for #{data_field}" if ENV['DEBUG']
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
data_field = obj.call
|
|
63
|
+
end
|
|
54
64
|
# make sure the intended UI target element is visible before trying to set its value
|
|
55
65
|
data_field.scroll_into_view unless data_field.wait_until_visible(timeout, post_exception = false)
|
|
56
66
|
if data_param == '!DELETE'
|
|
@@ -1,47 +1,28 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
3
|
-
require 'virtus'
|
|
4
|
-
require 'time'
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_support/core_ext/hash'
|
|
5
3
|
require 'chronic'
|
|
6
4
|
require 'faker'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'rexml/document'
|
|
7
|
+
require 'smarter_csv'
|
|
8
|
+
require 'time'
|
|
9
|
+
require 'virtus'
|
|
10
|
+
require 'yaml'
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
module TestCentricity
|
|
10
14
|
|
|
11
15
|
PRIMARY_DATA_PATH ||= 'config/test_data/'
|
|
16
|
+
SECONDARY_DATA_PATH ||= 'config/data/'
|
|
12
17
|
PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_PATH}data."
|
|
13
18
|
YML_PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_FILE}yml"
|
|
14
19
|
JSON_PRIMARY_DATA_FILE ||= "#{PRIMARY_DATA_FILE}json"
|
|
15
20
|
|
|
16
21
|
|
|
17
|
-
class DataObject
|
|
18
|
-
attr_accessor :current
|
|
19
|
-
attr_accessor :context
|
|
20
|
-
attr_accessor :hash_table
|
|
21
|
-
|
|
22
|
-
def initialize(data)
|
|
23
|
-
@hash_table = data
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def self.current
|
|
27
|
-
@current
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def self.current=(current)
|
|
31
|
-
@current = current
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
|
|
36
22
|
class DataPresenter
|
|
37
23
|
include Virtus.model
|
|
38
24
|
|
|
39
25
|
attr_accessor :current
|
|
40
|
-
attr_accessor :context
|
|
41
|
-
|
|
42
|
-
def initialize(data)
|
|
43
|
-
self.attributes = data unless data.nil?
|
|
44
|
-
end
|
|
45
26
|
|
|
46
27
|
def self.current
|
|
47
28
|
@current
|
|
@@ -53,48 +34,162 @@ module TestCentricity
|
|
|
53
34
|
end
|
|
54
35
|
|
|
55
36
|
|
|
56
|
-
# :nocov:
|
|
57
37
|
class DataSource
|
|
58
38
|
attr_accessor :file_path
|
|
59
|
-
attr_accessor :
|
|
39
|
+
attr_accessor :file_extension
|
|
60
40
|
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
def read_file(file_name, key = nil, node_name = nil, options = nil)
|
|
42
|
+
# check to see if full file path was specified
|
|
43
|
+
if File.exist?(file_name)
|
|
44
|
+
@file_path = file_name
|
|
45
|
+
else
|
|
46
|
+
# construct the full file path to the file to be read
|
|
47
|
+
@file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
|
|
48
|
+
unless File.exist?(@file_path)
|
|
49
|
+
@file_path = "#{SECONDARY_DATA_PATH}#{file_name}"
|
|
50
|
+
raise "File #{file_name} not found in Primary or Secondary folders in config folder" unless File.exist?(@file_path)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
# determine file type and read in data from file
|
|
54
|
+
@file_extension = File.extname(file_name)
|
|
55
|
+
data = case @file_extension
|
|
56
|
+
when '.yml'
|
|
57
|
+
YAML.load_file(@file_path)
|
|
58
|
+
when'.json'
|
|
59
|
+
JSON.parse(File.read(@file_path))
|
|
60
|
+
when '.xml'
|
|
61
|
+
xml_data = File.read(@file_path)
|
|
62
|
+
Hash.from_xml(xml_data)
|
|
63
|
+
when '.csv'
|
|
64
|
+
if options
|
|
65
|
+
SmarterCSV.process(@file_path, options)
|
|
66
|
+
else
|
|
67
|
+
SmarterCSV.process(@file_path)
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
raise "#{file_name} is not a supported file type"
|
|
71
|
+
end
|
|
72
|
+
# return data if sourced from a .csv file
|
|
73
|
+
return data if @file_extension == '.csv'
|
|
74
|
+
|
|
75
|
+
# read data from specified key and/or node
|
|
76
|
+
result = if key
|
|
77
|
+
raise "Key #{key} not found" unless data.key?(key)
|
|
78
|
+
|
|
79
|
+
if node_name
|
|
80
|
+
raise "Node #{node_name} not found" unless data[key].key?(node_name)
|
|
81
|
+
|
|
82
|
+
data[key][node_name]
|
|
83
|
+
else
|
|
84
|
+
data[key]
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
data
|
|
88
|
+
end
|
|
89
|
+
self.class.send(:process_data, result, options)
|
|
66
90
|
end
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
data
|
|
73
|
-
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def self.process_data(data, options)
|
|
95
|
+
# calculate dynamic values if any are specified
|
|
96
|
+
if data.is_a?(Hash)
|
|
97
|
+
data.each do |key, value|
|
|
98
|
+
data[key] = calculate_dynamic_value(value) if value.to_s.start_with?('eval!')
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
return data unless options
|
|
102
|
+
|
|
103
|
+
# convert keys to symbols if :keys_as_symbols is true in options
|
|
104
|
+
if options.key?(:keys_as_symbols) && options[:keys_as_symbols]
|
|
105
|
+
data.transform_keys!(&:to_sym)
|
|
106
|
+
end
|
|
107
|
+
# convert values if :value_converters are specified in options
|
|
108
|
+
if options.key?(:value_converters)
|
|
109
|
+
map_values(data, options[:value_converters])
|
|
110
|
+
else
|
|
111
|
+
data
|
|
112
|
+
end
|
|
74
113
|
end
|
|
75
114
|
|
|
76
|
-
|
|
115
|
+
def self.map_values(data, value_converters)
|
|
116
|
+
data.each_with_object({}) do |(k, v), new_hash|
|
|
117
|
+
converter = value_converters[k]
|
|
118
|
+
v = converter.convert(v) if converter
|
|
119
|
+
new_hash[k] = v
|
|
120
|
+
end
|
|
121
|
+
end
|
|
77
122
|
|
|
78
123
|
def self.calculate_dynamic_value(value)
|
|
79
124
|
test_value = value.split('!', 2)
|
|
80
125
|
parameter = test_value[1].split('.', 2)
|
|
81
|
-
case parameter[0]
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
126
|
+
result = case parameter[0]
|
|
127
|
+
when 'Date'
|
|
128
|
+
Chronic.parse(parameter[1])
|
|
129
|
+
when 'FormattedDate', 'FormatDate'
|
|
130
|
+
date_time_params = parameter[1].split(' format! ', 2)
|
|
131
|
+
date_time = Chronic.parse(date_time_params[0].strip)
|
|
132
|
+
date_time.to_s.format_date_time("#{date_time_params[1].strip}")
|
|
133
|
+
else
|
|
134
|
+
if Faker.constants.include?(parameter[0].to_sym)
|
|
90
135
|
eval("Faker::#{parameter[0]}.#{parameter[1]}")
|
|
91
136
|
else
|
|
92
137
|
eval(test_value[1])
|
|
93
138
|
end
|
|
94
|
-
|
|
139
|
+
end
|
|
95
140
|
result.to_s
|
|
96
141
|
end
|
|
97
142
|
end
|
|
98
|
-
# :nocov:
|
|
99
143
|
end
|
|
100
144
|
|
|
145
|
+
|
|
146
|
+
# perform conversion of String to Boolean when reading data from .csv or .xml files
|
|
147
|
+
class ToBoolean
|
|
148
|
+
def self.convert(value)
|
|
149
|
+
value.to_bool unless value.nil?
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# perform conversion of Integer to String when reading data from .csv or .xml files
|
|
155
|
+
class ToString
|
|
156
|
+
def self.convert(value)
|
|
157
|
+
if value.is_a? Integer
|
|
158
|
+
value.to_s
|
|
159
|
+
else
|
|
160
|
+
value
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# perform conversion of String to Integer when reading data from .csv or .xml files
|
|
167
|
+
class ToInteger
|
|
168
|
+
def self.convert(value)
|
|
169
|
+
if value.is_a? Integer
|
|
170
|
+
value
|
|
171
|
+
else
|
|
172
|
+
if value.is_int?
|
|
173
|
+
value.to_i
|
|
174
|
+
else
|
|
175
|
+
value
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# perform conversion of String to Float when reading data from .csv or .xml files
|
|
183
|
+
class ToFloat
|
|
184
|
+
def self.convert(value)
|
|
185
|
+
if value.is_a? Float
|
|
186
|
+
value
|
|
187
|
+
else
|
|
188
|
+
if value.is_float?
|
|
189
|
+
value.to_f
|
|
190
|
+
else
|
|
191
|
+
value
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -23,8 +23,7 @@ module TestCentricity
|
|
|
23
23
|
read('Environments', environ_name)
|
|
24
24
|
when :json
|
|
25
25
|
# read generic test data from data.json file
|
|
26
|
-
|
|
27
|
-
@generic_data = JSON.parse(raw_data)
|
|
26
|
+
@generic_data = JSON.parse(File.read(JSON_PRIMARY_DATA_FILE))
|
|
28
27
|
# read environment specific test data
|
|
29
28
|
data_file = "#{PRIMARY_DATA_PATH}#{environ_name}_data.json"
|
|
30
29
|
@environ_specific_data = if File.exist?(data_file)
|
|
@@ -42,27 +41,21 @@ module TestCentricity
|
|
|
42
41
|
Environ.current = @current
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def self.read(key_name, node_name)
|
|
46
|
-
if @environ_specific_data.key?(key_name) && @environ_specific_data[key_name].key?(node_name)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
node_data = @generic_data[key_name][node_name]
|
|
53
|
-
end
|
|
44
|
+
def self.read(key_name, node_name, options = nil)
|
|
45
|
+
node_data = if @environ_specific_data.key?(key_name) && @environ_specific_data[key_name].key?(node_name)
|
|
46
|
+
@environ_specific_data[key_name][node_name]
|
|
47
|
+
else
|
|
48
|
+
raise "No key named #{key_name} in generic and environment-specific data" unless @generic_data.key?(key_name)
|
|
49
|
+
raise "No node named #{node_name} in #{key_name} section of generic and environment-specific data" unless @generic_data[key_name].key?(node_name)
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
node_data
|
|
51
|
+
@generic_data[key_name][node_name]
|
|
52
|
+
end
|
|
53
|
+
process_data(node_data, options)
|
|
61
54
|
end
|
|
62
55
|
end
|
|
63
56
|
|
|
64
57
|
|
|
65
|
-
class Environ
|
|
58
|
+
class Environ
|
|
66
59
|
@session_id = Time.now.strftime('%d%H%M%S%L')
|
|
67
60
|
@session_time_stamp = Time.now.strftime('%Y%m%d%H%M%S')
|
|
68
61
|
@test_environment = ENV['TEST_ENVIRONMENT']
|
|
@@ -71,6 +64,7 @@ module TestCentricity
|
|
|
71
64
|
@language = ENV['LANGUAGE'] || 'English'
|
|
72
65
|
@screen_shots = []
|
|
73
66
|
|
|
67
|
+
attr_accessor :current
|
|
74
68
|
attr_accessor :test_environment
|
|
75
69
|
attr_accessor :session_state
|
|
76
70
|
attr_accessor :session_code
|
|
@@ -140,8 +134,14 @@ module TestCentricity
|
|
|
140
134
|
@android_app_id = data['ANDROID_APP_ID']
|
|
141
135
|
@android_test_id = data['ANDROID_TEST_ID']
|
|
142
136
|
@deep_link_prefix = data['DEEP_LINK_PREFIX']
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def self.current
|
|
140
|
+
@current
|
|
141
|
+
end
|
|
143
142
|
|
|
144
|
-
|
|
143
|
+
def self.current=(current)
|
|
144
|
+
@current = current
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
def self.new_app_session
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: testcentricity_mobile
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.1.
|
|
4
|
+
version: 4.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- A.J. Mrozinski
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - '='
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 10.
|
|
33
|
+
version: 10.2.0
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - '='
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 10.
|
|
40
|
+
version: 10.2.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: parallel_tests
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,14 +100,14 @@ dependencies:
|
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: 4.
|
|
103
|
+
version: 4.39.0
|
|
104
104
|
type: :development
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: 4.
|
|
110
|
+
version: 4.39.0
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
112
|
name: simplecov
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -136,20 +136,34 @@ dependencies:
|
|
|
136
136
|
- - ">="
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
138
|
version: 0.9.0
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: activesupport
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '4.0'
|
|
146
|
+
type: :runtime
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '4.0'
|
|
139
153
|
- !ruby/object:Gem::Dependency
|
|
140
154
|
name: appium_lib
|
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
|
142
156
|
requirements:
|
|
143
157
|
- - "~>"
|
|
144
158
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 16.1.
|
|
159
|
+
version: 16.1.1
|
|
146
160
|
type: :runtime
|
|
147
161
|
prerelease: false
|
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
163
|
requirements:
|
|
150
164
|
- - "~>"
|
|
151
165
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: 16.1.
|
|
166
|
+
version: 16.1.1
|
|
153
167
|
- !ruby/object:Gem::Dependency
|
|
154
168
|
name: childprocess
|
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -220,6 +234,20 @@ dependencies:
|
|
|
220
234
|
- - ">="
|
|
221
235
|
- !ruby/object:Gem::Version
|
|
222
236
|
version: '0'
|
|
237
|
+
- !ruby/object:Gem::Dependency
|
|
238
|
+
name: smarter_csv
|
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
|
240
|
+
requirements:
|
|
241
|
+
- - ">="
|
|
242
|
+
- !ruby/object:Gem::Version
|
|
243
|
+
version: '0'
|
|
244
|
+
type: :runtime
|
|
245
|
+
prerelease: false
|
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
247
|
+
requirements:
|
|
248
|
+
- - ">="
|
|
249
|
+
- !ruby/object:Gem::Version
|
|
250
|
+
version: '0'
|
|
223
251
|
- !ruby/object:Gem::Dependency
|
|
224
252
|
name: test-unit
|
|
225
253
|
requirement: !ruby/object:Gem::Requirement
|