calabash-cucumber 0.16.4 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/bin/calabash-ios-generate.rb +61 -10
  3. data/dylibs/libCalabashDyn.dylib +0 -0
  4. data/dylibs/libCalabashDynSim.dylib +0 -0
  5. data/features-skeleton/sample.feature +7 -0
  6. data/features-skeleton/steps/sample_steps.rb +45 -0
  7. data/features-skeleton/support/01_launch.rb +31 -33
  8. data/features-skeleton/support/dry_run.rb +2 -0
  9. data/features-skeleton/support/env.rb +1 -0
  10. data/features-skeleton/support/patches/cucumber.rb +15 -0
  11. data/lib/calabash-cucumber.rb +4 -0
  12. data/lib/calabash-cucumber/actions/instruments_actions.rb +0 -5
  13. data/lib/calabash-cucumber/actions/playback_actions.rb +1 -6
  14. data/lib/calabash-cucumber/connection_helpers.rb +50 -1
  15. data/lib/calabash-cucumber/core.rb +94 -72
  16. data/lib/calabash-cucumber/dot_dir.rb +18 -0
  17. data/lib/calabash-cucumber/launch/simulator_launcher.rb +35 -3
  18. data/lib/calabash-cucumber/launcher.rb +46 -99
  19. data/lib/calabash-cucumber/logging.rb +79 -0
  20. data/lib/calabash-cucumber/playback_helpers.rb +2 -2
  21. data/lib/calabash-cucumber/store/preferences.rb +223 -0
  22. data/lib/calabash-cucumber/uia.rb +0 -43
  23. data/lib/calabash-cucumber/usage_tracker.rb +192 -0
  24. data/lib/calabash-cucumber/version.rb +2 -2
  25. data/lib/calabash-cucumber/wait_helpers.rb +32 -0
  26. data/scripts/.irbrc +19 -4
  27. data/staticlib/calabash.framework.zip +0 -0
  28. data/staticlib/libFrankCalabash.a +0 -0
  29. metadata +31 -19
  30. data/features-skeleton/my_first.feature +0 -12
  31. data/features-skeleton/step_definitions/calabash_steps.rb +0 -1
  32. data/features-skeleton/step_definitions/my_first_steps.rb +0 -4
  33. data/features-skeleton/support/02_pre_stop_hooks.rb +0 -0
@@ -0,0 +1,18 @@
1
+ module Calabash
2
+ module Cucumber
3
+ # A module for managing the ~/.calabash directory.
4
+ module DotDir
5
+ require "run_loop"
6
+
7
+ def self.directory
8
+ home = RunLoop::Environment.user_home_directory
9
+ dir = File.join(home, ".calabash")
10
+ if !File.exist?(dir)
11
+ FileUtils.mkdir_p(dir)
12
+ end
13
+ dir
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -34,6 +34,10 @@ module Calabash
34
34
  # The file path to the default Xcode DerivedData directory.
35
35
  DERIVED_DATA = File.expand_path('~/Library/Developer/Xcode/DerivedData')
36
36
 
37
+ # @!visibility private]
38
+ # The file path to the default Xcode preferences plist.
39
+ XCODE_PREFS = File.expand_path('~/Library/Preferences/com.apple.dt.Xcode.plist')
40
+
37
41
  # @!visibility private
38
42
  # REGEX for finding application Info.plist.
39
43
  DEFAULT_DERIVED_DATA_INFO = File.expand_path("#{DERIVED_DATA}/*/info.plist")
@@ -161,6 +165,33 @@ module Calabash
161
165
  end
162
166
  end
163
167
 
168
+ # @!visibility private
169
+ # Returns the absolute build path to the project directory.
170
+ #
171
+ # @return [String] absolute path to the projects build directory
172
+ def build_output_dir_for_project
173
+ xcode_temp_prefs = File.join(project_dir, '.cal_xcode_prefs')
174
+ FileUtils.cp(XCODE_PREFS, xcode_temp_prefs)
175
+ `plutil -convert xml1 "#{xcode_temp_prefs}"`
176
+
177
+ plist = CFPropertyList::List.new(:file => xcode_temp_prefs)
178
+ hash = CFPropertyList.native_types(plist.value)
179
+
180
+ if hash.has_key?('IDESharedBuildFolderName')
181
+ build_folder_name = hash['IDESharedBuildFolderName']
182
+ output_dir = "#{DERIVED_DATA}/#{build_folder_name}/Products"
183
+ elsif hash.has_key?('IDECustomBuildProductsPath')
184
+ products_path = hash['IDECustomBuildProductsPath']
185
+ File.join(project_dir, products_path)
186
+ else
187
+ output_dir = derived_data_dir_for_project
188
+ end
189
+
190
+ FileUtils.rm(xcode_temp_prefs)
191
+
192
+ output_dir
193
+ end
194
+
164
195
  # @!visibility private
165
196
  # Returns the absolute path to the project directory.
166
197
  #
@@ -220,12 +251,13 @@ module Calabash
220
251
  puts('-'*37)
221
252
  end
222
253
  else
223
- dd_dir = derived_data_dir_for_project
224
- sim_dirs = Dir.glob(File.join(dd_dir, 'Build', 'Products', '*-iphonesimulator', '*.app'))
254
+ bo_dir = build_output_dir_for_project
255
+ sim_dirs = Dir.glob(File.join(bo_dir, '*-iphonesimulator', '*.app'))
256
+
225
257
  if sim_dirs.empty?
226
258
  msg = ['Unable to auto detect APP_BUNDLE_PATH.']
227
259
  msg << 'Have you built your app for simulator?'
228
- msg << "Searched dir: #{dd_dir}/Build/Products"
260
+ msg << "Searched dir: #{bo_dir}"
229
261
  msg << 'Please build your app from Xcode'
230
262
  msg << 'You should build the -cal target.'
231
263
  msg << ''
@@ -8,6 +8,7 @@ require 'run_loop'
8
8
  require 'cfpropertylist'
9
9
  require 'calabash-cucumber/utils/logging'
10
10
  require 'calabash/dylibs'
11
+ require "calabash-cucumber/usage_tracker"
11
12
 
12
13
  # Used to launch apps for testing in iOS Simulator or on iOS Devices. By default
13
14
  # it uses Apple's `instruments` process to launch your app, but has legacy support
@@ -56,6 +57,7 @@ class Calabash::Cucumber::Launcher
56
57
  attr_accessor :launch_args
57
58
  attr_accessor :simulator_launcher
58
59
  attr_reader :xcode
60
+ attr_reader :usage_tracker
59
61
 
60
62
  # @!visibility private
61
63
  # Generated when calabash cannot launch the app.
@@ -81,6 +83,10 @@ class Calabash::Cucumber::Launcher
81
83
  @xcode ||= RunLoop::Xcode.new
82
84
  end
83
85
 
86
+ def usage_tracker
87
+ @usage_tracker ||= Calabash::Cucumber::UsageTracker.new
88
+ end
89
+
84
90
  # @!visibility private
85
91
  def initialize
86
92
  @simulator_launcher = Calabash::Cucumber::SimulatorLauncher.new
@@ -147,12 +153,15 @@ class Calabash::Cucumber::Launcher
147
153
  self.run_loop = run_loop
148
154
  major = self.device.ios_major_version
149
155
  if major.to_i >= 7 && self.actions.is_a?(Calabash::Cucumber::PlaybackActions)
150
- puts "\n\n WARNING \n\n"
151
- puts 'Warning Trying to connect to simulator that was not launched by Calabash/instruments.'
152
- puts 'To fix this you must let Calabash or instruments launch the app.'
153
- puts 'Query will work, but gestures will not.'
154
- puts "\n\n WARNING \n\n"
155
- puts 'Please read: https://github.com/calabash/calabash-ios/wiki/A0-UIAutomation---instruments-problems'
156
+ puts %Q{
157
+
158
+ WARNING
159
+
160
+ Connected to simulator that was not launched by Calabash.
161
+
162
+ Queries will work, but gestures will not.
163
+
164
+ }
156
165
  end
157
166
  self
158
167
  end
@@ -267,56 +276,24 @@ class Calabash::Cucumber::Launcher
267
276
  # `:all` is passed, then the sandboxes for all sdks will be deleted.
268
277
  # @option opts [String] :path (nil) path to the application bundle
269
278
  def reset_app_sandbox(opts={})
279
+ calabash_warn(%Q{
280
+ Starting in Calabash 0.17.0, this method does nothing.
270
281
 
271
- if device_target?
272
- calabash_warn("calling 'reset_app_sandbox' when targeting a device.")
273
- return
274
- end
275
-
276
- default_opts = {:sdk => nil, :path => nil}
277
- merged_opts = default_opts.merge opts
282
+ You can still control whether or not your app's sandbox is
283
+ reset between Scenarios using RESET_BETWEEN_SCENARIOS=1 or
284
+ by passing :reset => true as a launch option.
278
285
 
279
- sim_control = opts.fetch(:sim_control, RunLoop::SimControl.new)
280
- xcode = sim_control.xcode
286
+ options = {
287
+ :reset => true
288
+ }
281
289
 
282
- if sim_control.xcode_version_gte_6?
283
- default_sim = RunLoop::Core.default_simulator(xcode)
284
- name_or_udid = merged_opts[:udid] || ENV['DEVICE_TARGET'] || default_sim
290
+ launcher.relaunch(options)
285
291
 
286
- target_simulator = sim_control.simulators.find do |sim|
287
- [name_or_udid == sim.instruments_identifier(xcode),
288
- name_or_udid == sim.udid,
289
- name_or_udid == sim.name].any?
290
- end
292
+ Please do not ignore this message.
291
293
 
292
- if target_simulator.nil?
293
- raise "Could not find a simulator that matches '#{name_or_udid}'"
294
- end
295
-
296
- sim_control.reset_sim_content_and_settings({:sim_udid => target_simulator.udid})
297
- else
298
- sdk ||= merged_opts[:sdk] || sdk_version || self.simulator_launcher.sdk_detector.latest_sdk_version
299
- path ||= merged_opts[:path] || self.simulator_launcher.app_bundle_or_raise(app_path)
294
+ Remove direct calls to reset_app_sandbox.
300
295
 
301
- app = File.basename(path)
302
-
303
- directories_for_sdk_prefix(sdk).each do |sdk_dir|
304
- app_dir = File.expand_path("#{sdk_dir}/Applications")
305
- next unless File.exists?(app_dir)
306
-
307
- bundle = `find "#{app_dir}" -type d -depth 2 -name "#{app}" | head -n 1`
308
-
309
- next if bundle.empty? # Assuming we're already clean
310
-
311
- if debug_logging?
312
- puts "Reset app state for #{bundle}"
313
- end
314
- sandbox = File.dirname(bundle)
315
- ['Library', 'Documents', 'tmp'].each do |content_dir|
316
- FileUtils.rm_rf(File.join(sandbox, content_dir))
317
- end
318
- end
319
- end
296
+ })
320
297
  end
321
298
 
322
299
  # Erases the contents and setting for every available simulator.
@@ -503,36 +480,27 @@ class Calabash::Cucumber::Launcher
503
480
  end
504
481
  end
505
482
 
506
- # Launches your app on the connected device or simulator. Stops the app if it is already running.
507
- # `relaunch` does a lot of error detection and handling to reliably start the app and test. Instruments (particularly the cli)
508
- # has stability issues which we workaround by restarting the simulator process and checking that UIAutomation is correctly
509
- # attaching.
483
+ # Launches your app on the connected device or simulator.
510
484
  #
511
- # Takes optional args to specify details of the launch (e.g. device or simulator, sdk version, target device, launch method...).
512
- # @note an important part of relaunch behavior is controlled by environment variables, specified below
485
+ # `relaunch` does a lot of error detection and handling to reliably start the
486
+ # app and test. Instruments (particularly the cli) has stability issues which
487
+ # we workaround by restarting the simulator process and checking that
488
+ # UIAutomation is correctly attaching to your application.
513
489
  #
514
- # The two most important environment variables are `DEVICE_TARGET` and `APP_BUNDLE_PATH`.
490
+ # Use the `args` parameter to to control:
515
491
  #
516
- # - `DEVICE_TARGET` controls which device you're running on. To see the options run: `instruments -s devices`.
517
- # In addition you can specify `DEVICE_TARGET=device` to run on a (unique) usb-connected device.
518
- # - `APP_BUNDLE_PATH` controls which `.app` bundle to launch in simulator (don't use for on-device testing, instead use `BUNDLE_ID`).
519
- # - `BUNDLE_ID` used with `DEVICE_TARGET=device` to specify which app to launch on device
520
- # - `DEBUG` - set to "1" to obtain debug info (typically used to debug launching, UIAutomation and other issues)
521
- # - `DEBUG_HTTP` - set to "1" to show raw HTTP traffic
492
+ # * `:app` - which app to launch.
493
+ # * `:device_target` - simulator or device to target.
494
+ # * `:reset_app_sandbox - reset he app's data (sandbox) before testing
522
495
  #
496
+ # and many other behaviors.
523
497
  #
524
- # @example Launching on iPad simulator with DEBUG settings
525
- # DEBUG_HTTP=1 DEVICE_TARGET="iPad - Simulator - iOS 7.1" DEBUG=1 APP_BUNDLE_PATH=FieldServiceiOS.app bundle exec calabash-ios console
526
- # @param {Hash} args optional args to specify details of the launch (e.g. device or simulator, sdk version,
527
- # target device, launch method...).
528
- # @option args {String} :app (detect the location of the bundle from project settings) app bundle path
529
- # @option args {String} :bundle_id if launching on device, specify this or env `BUNDLE_ID` to be the bundle identifier
530
- # of the application to launch
531
- # @option args {Hash} :privacy_settings preset privacy settings for the, e.g., `{:photos => {:allow => true}}`.
532
- # See {KNOWN_PRIVACY_SETTINGS}
498
+ # Many of these behaviors can be be controlled by environment variables. The
499
+ # most important environment variables are `APP`, `DEVICE_TARGET`, and
500
+ # `DEVICE_ENDPOINT`.
501
+ #
502
+ # @param {Hash} args optional arguments to control the how the app is launched
533
503
  def relaunch(args={})
534
- #TODO stopping is currently broken, but this works anyway because instruments stop the process before relaunching
535
- RunLoop.stop(run_loop) if run_loop
536
504
 
537
505
  # @todo Don't overwrite the _args_ parameter!
538
506
  args = default_launch_args.merge(args)
@@ -577,34 +545,11 @@ class Calabash::Cucumber::Launcher
577
545
 
578
546
  args[:device] ||= detect_device_from_args(args)
579
547
 
580
- if simulator_target?(args) and args[:reset]
581
- # attempt to find the sdk version from the :device_target
582
- sdk = sdk_version_for_simulator_target(args)
583
-
584
- # *** LEGACY SUPPORT ***
585
- # If DEVICE_TARGET has not been set and is not a device UDID, then
586
- # :device_target will be 'simulator'. In that case, we cannot know what
587
- # SDK version of the app sandbox we should reset. The user _might_ give
588
- # us a hint with SDK_VERSION, but we want to deprecate that variable ASAP.
589
- #
590
- # If passed a nil SDK arg, reset_app_sandbox will reset the _latest_ SDK.
591
- # This is not good, because this is probably _not_ the SDK that should be
592
- # reset. Our only option is to reset every sandbox for all SDKs by
593
- # passing :sdk => :all to reset_app_sandbox.
594
- if sdk.nil? and args[:device_target] == 'simulator'
595
- sdk = :all
596
- end
597
- reset_app_sandbox({:sdk => sdk,
598
- :path => args[:app],
599
- :udid => args[:udid],
600
- :sim_control => args[:sim_control]})
601
- end
602
-
603
548
  if args[:privacy_settings]
604
549
  if simulator_target?(args)
605
550
  update_privacy_settings(args[:bundle_id], args[:privacy_settings])
606
551
  else
607
- #Not supported on device
552
+ # Not supported on device
608
553
  puts 'Warning: :privacy_settings not supported on device'
609
554
  end
610
555
  end
@@ -649,6 +594,8 @@ class Calabash::Cucumber::Launcher
649
594
  check_server_gem_compatibility
650
595
  end
651
596
  end
597
+
598
+ usage_tracker.post_usage_async
652
599
  end
653
600
 
654
601
  # @!visibility private
@@ -1083,7 +1030,7 @@ class Calabash::Cucumber::Launcher
1083
1030
  msgs = [
1084
1031
  'The server version is not compatible with gem version.',
1085
1032
  'Please update your server.',
1086
- 'https://github.com/calabash/calabash-ios/wiki/B1-Updating-your-Calabash-iOS-version',
1033
+ 'https://github.com/calabash/calabash-ios/wiki/Updating-your-Calabash-iOS-version',
1087
1034
  " gem version: '#{gem_version}'",
1088
1035
  "min server version: '#{min_server_version}'",
1089
1036
  " server version: '#{server_version}'"]
@@ -0,0 +1,79 @@
1
+ module Calabash
2
+ module Cucumber
3
+ require "run_loop"
4
+
5
+ # These methods are not part of the API.
6
+ #
7
+ # They may change at any time.
8
+
9
+ # !@visibility private
10
+ # blue
11
+ def self.log_warn(msg)
12
+ puts self.blue(" WARN: #{msg}") if msg
13
+ end
14
+
15
+ # !@visibility private
16
+ # magenta
17
+ def self.log_debug(msg)
18
+ if RunLoop::Environment.debug?
19
+ puts self.magenta("DEBUG: #{msg}") if msg
20
+ end
21
+ end
22
+
23
+ # !@visibility private
24
+ # green
25
+ def self.log_info(msg)
26
+ puts self.green(" INFO: #{msg}") if msg
27
+ end
28
+
29
+ # !@visibility private
30
+ # red
31
+ def self.log_error(msg)
32
+ puts self.red("ERROR: #{msg}") if msg
33
+ end
34
+
35
+ private
36
+
37
+ # @!visibility private
38
+ def self.windows_env?
39
+ RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
40
+ end
41
+
42
+ # @!visibility private
43
+ def self.colorize(string, color)
44
+ if self.windows_env?
45
+ string
46
+ elsif RunLoop::Environment.xtc?
47
+ string
48
+ else
49
+ "\033[#{color}m#{string}\033[0m"
50
+ end
51
+ end
52
+
53
+ # @!visibility private
54
+ def self.red(string)
55
+ colorize(string, 31)
56
+ end
57
+
58
+ # @!visibility private
59
+ def self.blue(string)
60
+ colorize(string, 34)
61
+ end
62
+
63
+ # @!visibility private
64
+ def self.magenta(string)
65
+ colorize(string, 35)
66
+ end
67
+
68
+ # @!visibility private
69
+ def self.cyan(string)
70
+ colorize(string, 36)
71
+ end
72
+
73
+ # @!visibility private
74
+ def self.green(string)
75
+ colorize(string, 32)
76
+ end
77
+ end
78
+ end
79
+
@@ -75,7 +75,7 @@ module Calabash
75
75
  Most likely you have updated your calabash-cucumber client
76
76
  but not your server. Please follow closely:
77
77
 
78
- https://github.com/calabash/calabash-ios/wiki/B1-Updating-your-Calabash-iOS-version
78
+ https://github.com/calabash/calabash-ios/wiki/Updating-your-Calabash-iOS-version
79
79
 
80
80
  If you are running version 0.9.120+ then please report this message as a bug.
81
81
  EOF
@@ -194,7 +194,7 @@ EOF
194
194
  Most likely you have updated your calabash-cucumber client
195
195
  but not your server. Please follow closely:
196
196
 
197
- https://github.com/calabash/calabash-ios/wiki/B1-Updating-your-Calabash-iOS-version
197
+ https://github.com/calabash/calabash-ios/wiki/Updating-your-Calabash-iOS-version
198
198
 
199
199
  If you are running version 0.9.120+ then please report this message as a bug.
200
200
  EOF
@@ -0,0 +1,223 @@
1
+ module Calabash
2
+ module Cucumber
3
+
4
+ require "fileutils"
5
+ require "securerandom"
6
+
7
+ # Users preferences persisted across runs:
8
+ #
9
+ # ~/.calabash/preferences/preferences.json
10
+ class Preferences
11
+
12
+ def initialize
13
+ dot_dir = Calabash::Cucumber::DotDir.directory
14
+ @path = File.join(dot_dir, "preferences", "preferences.json")
15
+ end
16
+
17
+ def to_s
18
+ puts "Preferences:"
19
+ ap read
20
+ end
21
+
22
+ def inspect
23
+ to_s
24
+ end
25
+
26
+ # !@visibility private
27
+ def usage_tracking
28
+ preferences = read
29
+
30
+ unless valid_user_tracking_value?(preferences[:usage_tracking])
31
+ log_defaults_reset
32
+ preferences[:usage_tracking] = defaults[:usage_tracking]
33
+ write(preferences)
34
+ end
35
+
36
+ preferences[:usage_tracking]
37
+ end
38
+
39
+ # !@visibility private
40
+ def usage_tracking=(value)
41
+ if !valid_user_tracking_value?(value)
42
+ raise ArgumentError,
43
+ "Expected '#{value}' to be one of #{VALID_USAGE_TRACKING_VALUES.join(", ")}"
44
+ end
45
+
46
+ preferences = read
47
+ preferences[:usage_tracking] = value
48
+ write(preferences)
49
+ end
50
+
51
+ # !@visibility private
52
+ def user_id
53
+ preferences = read
54
+
55
+ unless valid_user_id?(preferences[:user_id])
56
+ preferences[:user_id] = SecureRandom.uuid
57
+ write(preferences)
58
+ end
59
+
60
+ preferences[:user_id]
61
+ end
62
+
63
+ # !@visibility private
64
+ def user_id=(value)
65
+ if !valid_user_id?(value)
66
+ raise ArgumentError,
67
+ "Expected '#{value}' to not be nil and not an empty string"
68
+ end
69
+
70
+ preferences = read
71
+ preferences[:user_id] = value
72
+ write(preferences)
73
+ end
74
+
75
+ private
76
+
77
+ # @!visibility private
78
+ def valid_user_tracking_value?(value)
79
+ VALID_USAGE_TRACKING_VALUES.include?(value)
80
+ end
81
+
82
+ # @!visibility private
83
+ def valid_user_id?(value)
84
+ !value.nil? && value != "" && value.is_a?(String)
85
+ end
86
+
87
+ # @!visibility private
88
+ #
89
+ # The preferences version
90
+ VERSION = "1.0"
91
+
92
+ # @!visibility private
93
+ #
94
+ # Ordered by permissiveness left to right ascending.
95
+ #
96
+ # "system_info" implies that "events" are also allowed.
97
+ VALID_USAGE_TRACKING_VALUES = ["none", "events", "system_info"]
98
+
99
+ # @!visibility private
100
+ def version
101
+ read[:version]
102
+ end
103
+
104
+ # @!visibility private
105
+ attr_reader :path
106
+
107
+ # @!visibility private
108
+ def ensure_preferences_dir
109
+ dir = File.dirname(@path)
110
+ unless File.exist?(dir)
111
+ FileUtils.mkdir_p(dir)
112
+ end
113
+ end
114
+
115
+ # @!visibility private
116
+ def defaults
117
+ {
118
+ :version => VERSION,
119
+ :usage_tracking => "system_info",
120
+ :user_id => SecureRandom.uuid
121
+ }
122
+ end
123
+
124
+ # @!visibility private
125
+ def write(hash)
126
+ if hash.nil?
127
+ raise ArgumentError, "Hash to write cannot be nil"
128
+ end
129
+
130
+ if !hash.is_a?(Hash)
131
+ raise ArgumentError, "Expected a Hash argument"
132
+ end
133
+
134
+ if hash.count == 0
135
+ raise ArgumentError, "Hash to write cannot be empty"
136
+ end
137
+
138
+ string = generate_json(hash)
139
+
140
+ ensure_preferences_dir
141
+
142
+ File.open(path, "w:UTF-8") do |file|
143
+ file.write(string)
144
+ end
145
+
146
+ true
147
+ end
148
+
149
+ # @!visibility private
150
+ def generate_json(hash)
151
+ begin
152
+ JSON.pretty_generate(hash)
153
+ rescue TypeError, JSON::UnparserError => e
154
+ write_to_log(
155
+ %Q{Error generating JSON from:
156
+ hash: #{hash}
157
+ error: #{e}
158
+ })
159
+ log_defaults_reset
160
+
161
+ # Will always generate valid JSON
162
+ generate_json(defaults)
163
+ end
164
+ end
165
+
166
+ # @!visibility private
167
+ def read
168
+ if File.exist?(path)
169
+
170
+ string = File.read(path).force_encoding("UTF-8")
171
+
172
+ parse_json(string)
173
+ else
174
+ hash = defaults
175
+ write(hash)
176
+ hash
177
+ end
178
+ end
179
+
180
+ # @!visibility private
181
+ def parse_json(string)
182
+ begin
183
+ JSON.parse(string, {:symbolize_names => true})
184
+ rescue TypeError, JSON::ParserError => e
185
+ write_to_log(
186
+ %Q{Error parsing JSON from:
187
+ string: #{string}
188
+ error: #{e}
189
+ })
190
+ log_defaults_reset
191
+
192
+ hash = defaults
193
+ write(hash)
194
+ hash
195
+ end
196
+ end
197
+
198
+ # @!visibility private
199
+ def write_to_log(error_message)
200
+ # TODO write to a log file?
201
+ end
202
+
203
+ # @!visibility private
204
+ def log_defaults_reset
205
+ Calabash::Cucumber.log_warn(
206
+ %q{An error occurred while accessing your user preferences.
207
+
208
+ We have reset the preferences to the default settings.
209
+
210
+ If this happens on a regular basis, please create a GitHub issue.
211
+
212
+ Your preferences control various Calabash behaviors. In particular, they tell
213
+ us how much usage information you are willing to share. If you have previously
214
+ turned off usage tracking, you will need to disable it again using the command
215
+ line tools or the irb.
216
+
217
+ We do not recommend that edit the preferences file by hand.
218
+ })
219
+ end
220
+ end
221
+ end
222
+ end
223
+