testcentricity_mobile 4.1.6 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae8677f880d39fd72ae439f29c84d531c75ef52db5f0854005ed68bd04443e4a
4
- data.tar.gz: 531df29401e26c9544f9fc65d0c16651879aafaf90682b2b2b6e1497b6dad839
3
+ metadata.gz: 4961bdc97a13ad7e08236fad109326f00a67a8d790a79257cb44691f1c435d61
4
+ data.tar.gz: 3b82d3cfb16db8d46264fb149ac8bf0d34866c437e5461e92f14b26697dfea09
5
5
  SHA512:
6
- metadata.gz: 9c8d3586d71645951b4ffbfb1330f640ea4b5536b570394fe8d3d40fcd7ea29a4b2331bf8d933a672ff151ef7e4ac6a93ecafec9ad200af414ce68b7ef95ee81
7
- data.tar.gz: f57743549f4439b9eeb0c922c522dc970e0ebda8ac21ad15c991f53bd86301198c7c780fab714471af34211fe214ace14bc5653ef71d01ac882b6d22e5252783
6
+ metadata.gz: 581d29d4727c72b30aa217a16cb91e542d05c183beba6f912788852b7dccebeb8ca3ea6d467298145509ea2efda4bc8115b31c8243dfbc6ac51bf2ad4da4baf4
7
+ data.tar.gz: 1a330c7e44dde5c2e727d02e47c4bf8d9048b6ccd2a6af0e129882533ce81564f8f9cccfc7ddedf6fc57175f96c3d5f6702332acfbcdca1430658c452ed5722e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
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
+
25
+ ## [4.1.7] - 25-NOV-2025
26
+
27
+ ### Changed
28
+
29
+ * Appium version 1.x is no longer supported.
30
+
31
+
5
32
  ## [4.1.6] - 04-OCT-2025
6
33
 
7
34
  ### Changed
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2025, Tony Mrozinski
1
+ Copyright (c) 2014-2026, Tony Mrozinski
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
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 only
99
- one location - in the `ScreenObject` class definition. By adopting a **Screen Object Model**, Cucumber feature files and
100
- step definitions are no longer required to hold specific information about a screen's UI objects, thus minimizing maintenance
101
- requirements. If any element on, or property of a screen changes (text field attributes, button captions, element states,
102
- etc.), maintenance is performed in the `ScreenObject` class definition only, typically with no need to update the affected
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
@@ -1200,10 +1200,6 @@ Refer to [this page](https://appium.io/docs/en/2.4/guides/caps/) for information
1200
1200
  to invoking Cucumber to run your features/scenarios on locally hosted iOS or Android simulators or physical devices. Refer
1201
1201
  to [**section 8.2.3 (Starting and Stopping Appium Server)**](#starting-and-stopping-appium-server) below.
1202
1202
 
1203
- ⚠️ If you are running locally hosted mobile tests on iOS or Android simulators or devices using version 1.x of the Appium
1204
- server, the `APPIUM_SERVER_VERSION` environment variable must be set to `1` in order to ensure that the correct Appium server
1205
- endpoint is used.
1206
-
1207
1203
  #### Connecting to Locally Hosted iOS Simulators or Physical Devices
1208
1204
 
1209
1205
  You can run your automated tests on locally hosted iOS simulators or physically connected devices using Appium and XCode
@@ -1420,13 +1416,6 @@ starting your Cucumber test suite(s):
1420
1416
 
1421
1417
  run_appium: APPIUM_SERVER=run
1422
1418
 
1423
- If you are running locally hosted mobile tests on iOS or Android simulators or devices using version 1.x of the Appium server,
1424
- the `APPIUM_SERVER_VERSION` environment variable must be set to `1` in order to ensure that the correct Appium server endpoint
1425
- is used. This can be set by adding the following to your `cucumber.yml` file and including `-p appium_1x` in your command line
1426
- when starting your Cucumber test suite(s):
1427
-
1428
- appium_1x: APPIUM_SERVER_VERSION=1
1429
-
1430
1419
  Refer to [**section 8.4 (Using Configuration Specific Profiles in `cucumber.yml`)**](#using-configuration-specific-profiles-in-cucumber-yml) below.
1431
1420
 
1432
1421
 
@@ -1447,9 +1436,6 @@ body of an example group:
1447
1436
  $server.stop if Environ.driver == :appium && $server.running?
1448
1437
  end
1449
1438
  ```
1450
- If you are running locally hosted mobile tests on iOS or Android simulators or devices using version 1.x of the Appium server,
1451
- the `APPIUM_SERVER_VERSION` environment variable must be set to `1` in order to ensure that the correct Appium server endpoint
1452
- is used.
1453
1439
 
1454
1440
 
1455
1441
  ### Connecting to Remote Cloud Hosted iOS and Android Simulators or Physical Devices
@@ -1873,7 +1859,6 @@ with access to your version control system.
1873
1859
  # physical devices
1874
1860
  #==============
1875
1861
  run_appium: APPIUM_SERVER=run
1876
- appium_1x: APPIUM_SERVER_VERSION=1
1877
1862
 
1878
1863
 
1879
1864
  #==============
@@ -2025,7 +2010,7 @@ the `/features/support/<platform>/sections` folder, where `<platform>` is typica
2025
2010
  ---
2026
2011
  ## Copyright and License
2027
2012
 
2028
- TestCentricity™ Framework is Copyright (c) 2014-2025, Tony Mrozinski.
2013
+ TestCentricity™ Framework is Copyright (c) 2014-2026, Tony Mrozinski.
2029
2014
  All rights reserved.
2030
2015
 
2031
2016
  Redistribution and use in source and binary forms, with or without
@@ -390,13 +390,7 @@ module TestCentricity
390
390
 
391
391
  def self.appium_local_capabilities
392
392
  # specify endpoint url
393
- if @endpoint.nil?
394
- @endpoint = if ENV['APPIUM_SERVER_VERSION'] && ENV['APPIUM_SERVER_VERSION'].to_i == 1
395
- 'http://127.0.0.1:4723/wd/hub'
396
- else
397
- 'http://127.0.0.1:4723'
398
- end
399
- end
393
+ @endpoint = 'http://127.0.0.1:4723' if @endpoint.nil?
400
394
  # define local Appium capabilities
401
395
  if @capabilities.nil?
402
396
  Environ.device_name = ENV['APP_DEVICE']
@@ -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'
@@ -38,11 +38,7 @@ module TestCentricity
38
38
  # Check to see if Appium Server is running
39
39
  #
40
40
  def running?
41
- endpoint = if ENV['APPIUM_SERVER_VERSION'] && ENV['APPIUM_SERVER_VERSION'].to_i == 1
42
- 'http://0.0.0.0:4723/wd/hub/sessions'
43
- else
44
- 'http://0.0.0.0:4723/sessions'
45
- end
41
+ endpoint = 'http://0.0.0.0:4723/sessions'
46
42
  response = false
47
43
  begin
48
44
  response = Net::HTTP.get_response(URI(endpoint))
@@ -1,47 +1,28 @@
1
- require 'yaml'
2
- require 'json'
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 :node
39
+ attr_accessor :file_extension
60
40
 
61
- def read_yaml_node_data(file_name, node_name)
62
- @file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
63
- @node = node_name
64
- data = YAML.load_file(@file_path)
65
- data[node_name]
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
- def read_json_node_data(file_name, node_name)
69
- @file_path = "#{PRIMARY_DATA_PATH}#{file_name}"
70
- @node = node_name
71
- raw_data = File.read(@file_path)
72
- data = JSON.parse(raw_data)
73
- data[node_name]
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
- private
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
- when 'Date'
83
- result = eval("Chronic.parse('#{parameter[1]}')")
84
- when 'FormattedDate', 'FormatDate'
85
- date_time_params = parameter[1].split(' format! ', 2)
86
- date_time = eval("Chronic.parse('#{date_time_params[0].strip}')")
87
- result = date_time.to_s.format_date_time("#{date_time_params[1].strip}")
88
- else
89
- result = if Faker.constants.include?(parameter[0].to_sym)
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
- end
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
- raw_data = File.read(JSON_PRIMARY_DATA_FILE)
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
- node_data = @environ_specific_data[key_name][node_name]
48
- else
49
- raise "No key named #{key_name} in generic and environment-specific data" unless @generic_data.key?(key_name)
50
- raise "No node named #{node_name} in #{key_name} section of generic and environment-specific data" unless @generic_data[key_name].key?(node_name)
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
- if node_data.is_a?(Hash)
56
- node_data.each do |key, value|
57
- node_data[key] = calculate_dynamic_value(value) if value.to_s.start_with?('eval!')
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 < TestCentricity::DataObject
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
- super
143
+ def self.current=(current)
144
+ @current = current
145
145
  end
146
146
 
147
147
  def self.new_app_session
@@ -1,3 +1,3 @@
1
1
  module TestCentricityMobile
2
- VERSION = '4.1.6'
2
+ VERSION = '4.1.8'
3
3
  end
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.6
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: 2025-10-04 00:00:00.000000000 Z
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.1.0
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.1.0
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.36.0
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.36.0
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.0
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.0
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