deliver 0.5.0 → 0.6.0
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/README.md +5 -3
- data/bin/deliver +58 -13
- data/lib/assets/DeliverfileDefault +0 -5
- data/lib/deliver.rb +1 -1
- data/lib/deliver/app.rb +7 -6
- data/lib/deliver/app_metadata.rb +8 -148
- data/lib/deliver/app_metadata_screenshots.rb +153 -0
- data/lib/deliver/deliver_process.rb +24 -0
- data/lib/deliver/deliverer.rb +19 -0
- data/lib/deliver/deliverfile/deliverfile_creator.rb +1 -1
- data/lib/deliver/deliverfile/dsl.rb +7 -3
- data/lib/deliver/itunes_connect/itunes_connect.rb +72 -0
- data/lib/deliver/itunes_connect/itunes_connect_additional.rb +90 -0
- data/lib/deliver/itunes_connect/itunes_connect_app_icon.rb +35 -0
- data/lib/deliver/itunes_connect/itunes_connect_app_rating.rb +68 -0
- data/lib/deliver/itunes_connect/itunes_connect_helper.rb +83 -0
- data/lib/deliver/itunes_connect/itunes_connect_login.rb +61 -0
- data/lib/deliver/itunes_connect/itunes_connect_new_version.rb +57 -0
- data/lib/deliver/itunes_connect/itunes_connect_reader.rb +60 -0
- data/lib/deliver/itunes_connect/itunes_connect_submission.rb +222 -0
- data/lib/deliver/version.rb +1 -1
- metadata +12 -5
- data/lib/deliver/commands/init.rb +0 -10
- data/lib/deliver/commands/run.rb +0 -24
- data/lib/deliver/itunes_connect.rb +0 -552
@@ -42,6 +42,8 @@ module Deliver
|
|
42
42
|
|
43
43
|
verify_pdf_file
|
44
44
|
|
45
|
+
additional_itc_information # e.g. copyright, age rating
|
46
|
+
|
45
47
|
trigger_metadata_upload
|
46
48
|
trigger_ipa_upload
|
47
49
|
|
@@ -173,8 +175,11 @@ module Deliver
|
|
173
175
|
@app.metadata.update_privacy_url(@deploy_information[Deliverer::ValKey::PRIVACY_URL]) if @deploy_information[Deliverer::ValKey::PRIVACY_URL]
|
174
176
|
|
175
177
|
@app.metadata.update_keywords(@deploy_information[Deliverer::ValKey::KEYWORDS]) if @deploy_information[Deliverer::ValKey::KEYWORDS]
|
178
|
+
|
179
|
+
@app.metadata.update_price_tier(@deploy_information[Deliverer::ValKey::PRICE_TIER]) if @deploy_information[Deliverer::ValKey::PRICE_TIER]
|
176
180
|
end
|
177
181
|
|
182
|
+
|
178
183
|
def set_screenshots
|
179
184
|
screens_path = @deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH]
|
180
185
|
|
@@ -226,6 +231,25 @@ module Deliver
|
|
226
231
|
raise "Error uploading app metadata".red unless result == true
|
227
232
|
end
|
228
233
|
|
234
|
+
def additional_itc_information
|
235
|
+
# e.g. rating or copyright
|
236
|
+
itc = ItunesConnect.new
|
237
|
+
itc.set_copyright!(@app, @deploy_information[Deliverer::ValKey::COPYRIGHT]) if @deploy_information[Deliverer::ValKey::COPYRIGHT]
|
238
|
+
itc.set_app_review_information!(@app, @deploy_information[Deliverer::ValKey::APP_REVIEW_INFORMATION]) if @deploy_information[Deliverer::ValKey::APP_REVIEW_INFORMATION]
|
239
|
+
itc.set_release_after_approval!(@app, @deploy_information[Deliverer::ValKey::AUTOMATIC_RELEASE]) if @deploy_information[Deliverer::ValKey::AUTOMATIC_RELEASE]
|
240
|
+
|
241
|
+
# Categories
|
242
|
+
primary = @deploy_information[Deliverer::ValKey::PRIMARY_CATEGORY]
|
243
|
+
secondary = @deploy_information[Deliverer::ValKey::SECONDARY_CATEGORY]
|
244
|
+
itc.set_categories!(@app, primary, secondary) if (primary or secondary)
|
245
|
+
|
246
|
+
# App Rating
|
247
|
+
itc.set_app_rating!(@app, @deploy_information[Deliverer::ValKey::RATINGS_CONFIG_PATH]) if @deploy_information[Deliverer::ValKey::RATINGS_CONFIG_PATH]
|
248
|
+
|
249
|
+
# App Icon
|
250
|
+
itc.upload_app_icon!(@app, @deploy_information[Deliverer::ValKey::APP_ICON]) if @deploy_information[Deliverer::ValKey::APP_ICON]
|
251
|
+
end
|
252
|
+
|
229
253
|
def trigger_ipa_upload
|
230
254
|
if @ipa
|
231
255
|
@ipa.app = @app # we now have the resulting app
|
data/lib/deliver/deliverer.rb
CHANGED
@@ -33,6 +33,25 @@ module Deliver
|
|
33
33
|
CONFIG_JSON_FOLDER = :config_json_folder # Path to a folder containing a configuration file and including screenshots
|
34
34
|
SKIP_PDF = :skip_pdf
|
35
35
|
SUBMIT_FURTHER_INFORMATION = :submit_further_information # export compliance, content rights and advertising identifier
|
36
|
+
PRICE_TIER = :price_tier
|
37
|
+
APP_ICON = :app_icon
|
38
|
+
|
39
|
+
COPYRIGHT = :copyright
|
40
|
+
PRIMARY_CATEGORY = :primary_category
|
41
|
+
SECONDARY_CATEGORY = :secondary_category
|
42
|
+
|
43
|
+
AUTOMATIC_RELEASE = :automatic_release # should the update go live after approval
|
44
|
+
RATINGS_CONFIG_PATH = :ratings_config_path # a path to the configuration for the app's ratings
|
45
|
+
|
46
|
+
APP_REVIEW_INFORMATION = :app_review_information
|
47
|
+
# Supported
|
48
|
+
# first_name
|
49
|
+
# last_name
|
50
|
+
# phone_number
|
51
|
+
# email_address
|
52
|
+
# demo_user
|
53
|
+
# demo_password
|
54
|
+
# notes
|
36
55
|
end
|
37
56
|
|
38
57
|
module AllBlocks
|
@@ -9,7 +9,7 @@ module Deliver
|
|
9
9
|
# @param deliver_path (String) The path in which the Deliverfile should be created
|
10
10
|
# @param project_name (String) The default name of the project, which is used in the generated Deliverfile
|
11
11
|
def self.create(deliver_path, project_name = nil)
|
12
|
-
deliver_file_path =
|
12
|
+
deliver_file_path = File.join(deliver_path, Deliver::Deliverfile::Deliverfile::FILE_NAME)
|
13
13
|
raise "Deliverfile already exists at path '#{deliver_file_path}'. Run 'deliver' to use Deliver.".red if File.exists?(deliver_file_path)
|
14
14
|
|
15
15
|
project_name ||= Dir.pwd.split("/").last
|
@@ -18,12 +18,16 @@ module Deliver
|
|
18
18
|
# Setting all the metadata
|
19
19
|
def method_missing(method_sym, *arguments, &block)
|
20
20
|
allowed = Deliver::Deliverer.all_available_keys_to_set
|
21
|
-
not_translated = [:ipa, :app_identifier, :apple_id, :screenshots_path, :config_json_folder,
|
21
|
+
not_translated = [:ipa, :app_identifier, :apple_id, :screenshots_path, :config_json_folder,
|
22
|
+
:submit_further_information, :copyright, :primary_category, :secondary_category,
|
23
|
+
:automatic_release, :app_review_information, :ratings_config_path, :price_tier,
|
24
|
+
:app_icon]
|
22
25
|
|
23
26
|
if allowed.include?(method_sym)
|
24
|
-
value = arguments.first
|
27
|
+
value = arguments.first
|
28
|
+
value = block.call if (value == nil and block != nil)
|
25
29
|
|
26
|
-
|
30
|
+
if value == nil
|
27
31
|
Helper.log.error(caller)
|
28
32
|
Helper.log.fatal("No value or block passed to method '#{method_sym}'")
|
29
33
|
raise DeliverfileDSLError.new(MISSING_VALUE_ERROR_MESSAGE.red)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'capybara'
|
2
|
+
require 'capybara/poltergeist'
|
3
|
+
require 'fastimage'
|
4
|
+
require 'credentials_manager/password_manager'
|
5
|
+
|
6
|
+
# Import all the actions
|
7
|
+
require 'deliver/itunes_connect/itunes_connect_submission'
|
8
|
+
require 'deliver/itunes_connect/itunes_connect_reader'
|
9
|
+
require 'deliver/itunes_connect/itunes_connect_helper'
|
10
|
+
require 'deliver/itunes_connect/itunes_connect_new_version'
|
11
|
+
require 'deliver/itunes_connect/itunes_connect_login'
|
12
|
+
require 'deliver/itunes_connect/itunes_connect_app_icon'
|
13
|
+
require 'deliver/itunes_connect/itunes_connect_app_rating'
|
14
|
+
require 'deliver/itunes_connect/itunes_connect_additional'
|
15
|
+
|
16
|
+
module Deliver
|
17
|
+
# Everything that can't be achived using the {Deliver::ItunesTransporter}
|
18
|
+
# will be scripted using the iTunesConnect frontend.
|
19
|
+
#
|
20
|
+
# Every method you call here, might take a time
|
21
|
+
class ItunesConnect
|
22
|
+
# This error occurs only if there is something wrong with the given login data
|
23
|
+
class ItunesConnectLoginError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
# This error can occur for many reaons. It is
|
27
|
+
# usually raised when a UI element could not be found
|
28
|
+
class ItunesConnectGeneralError < StandardError
|
29
|
+
end
|
30
|
+
|
31
|
+
include Capybara::DSL
|
32
|
+
|
33
|
+
ITUNESCONNECT_URL = "https://itunesconnect.apple.com/"
|
34
|
+
APP_DETAILS_URL = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/[[app_id]]"
|
35
|
+
|
36
|
+
BUTTON_STRING_NEW_VERSION = "New Version"
|
37
|
+
BUTTON_STRING_SUBMIT_FOR_REVIEW = "Submit for Review"
|
38
|
+
BUTTON_ADD_NEW_BUILD = 'Click + to add a build before you submit your app.'
|
39
|
+
|
40
|
+
WAITING_FOR_REVIEW = "Waiting For Review"
|
41
|
+
PROCESSING_TEXT = "Processing"
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
super
|
45
|
+
|
46
|
+
return if Helper.is_test?
|
47
|
+
|
48
|
+
DependencyChecker.check_dependencies
|
49
|
+
|
50
|
+
Capybara.run_server = false
|
51
|
+
Capybara.default_driver = :poltergeist
|
52
|
+
Capybara.javascript_driver = :poltergeist
|
53
|
+
Capybara.current_driver = :poltergeist
|
54
|
+
Capybara.app_host = ITUNESCONNECT_URL
|
55
|
+
|
56
|
+
# Since Apple has some SSL errors, we have to configure the client properly:
|
57
|
+
# https://github.com/ariya/phantomjs/issues/11239
|
58
|
+
Capybara.register_driver :poltergeist do |a|
|
59
|
+
conf = ['--debug=no', '--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1']
|
60
|
+
Capybara::Poltergeist::Driver.new(a, {
|
61
|
+
phantomjs_options: conf,
|
62
|
+
phantomjs_logger: File.open("/tmp/poltergeist_log.txt", "a"),
|
63
|
+
js_errors: false
|
64
|
+
})
|
65
|
+
end
|
66
|
+
|
67
|
+
page.driver.headers = { "Accept-Language" => "en" }
|
68
|
+
|
69
|
+
login
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Deliver
|
2
|
+
class ItunesConnect
|
3
|
+
# This file sets additional information like copyright and age rating
|
4
|
+
|
5
|
+
def set_copyright!(app, text)
|
6
|
+
verify_app(app)
|
7
|
+
open_app_page(app)
|
8
|
+
|
9
|
+
Helper.log.info "Setting copyright to '#{text}'".green
|
10
|
+
|
11
|
+
first("input[ng-model='versionInfo.copyright.value']").set text
|
12
|
+
|
13
|
+
(click_on "Save" rescue nil) # if nothing has changed, there is no back button and we don't care
|
14
|
+
rescue => ex
|
15
|
+
error_occured(ex)
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_app_review_information!(app, hash)
|
19
|
+
verify_app(app)
|
20
|
+
open_app_page(app)
|
21
|
+
|
22
|
+
Helper.log.info "Setting review information: #{hash}"
|
23
|
+
|
24
|
+
first("input[ng-model='versionInfo.appReviewInfo.firstName.value']").set hash[:first_name]
|
25
|
+
first("input[ng-model='versionInfo.appReviewInfo.lastName.value']").set hash[:last_name]
|
26
|
+
first("input[ng-model='versionInfo.appReviewInfo.phoneNumber.value']").set hash[:phone_number]
|
27
|
+
first("input[ng-model='versionInfo.appReviewInfo.emailAddress.value']").set hash[:email_address]
|
28
|
+
first("input[ng-model='versionInfo.appReviewInfo.userName.value']").set hash[:demo_user]
|
29
|
+
first("input[ng-model='versionInfo.appReviewInfo.password.value']").set hash[:demo_password]
|
30
|
+
first("span[ng-show='versionInfo.appReviewInfo.reviewNotes.isEditable'] > * > textarea").set hash[:notes]
|
31
|
+
|
32
|
+
(click_on "Save" rescue nil) # if nothing has changed, there is no back button and we don't care
|
33
|
+
|
34
|
+
Helper.log.info "Successfully saved review information".green
|
35
|
+
rescue => ex
|
36
|
+
error_occured(ex)
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_release_after_approval!(app, automatic_release)
|
40
|
+
verify_app(app)
|
41
|
+
open_app_page(app)
|
42
|
+
|
43
|
+
Helper.log.info "Setting automatic release to '#{automatic_release}'".green
|
44
|
+
|
45
|
+
# Find the correct radio button
|
46
|
+
first("div[itc-radio='versionInfo.releaseOnApproval.value'][radio-value='#{automatic_release.to_s}'] > * > a").click
|
47
|
+
|
48
|
+
(click_on "Save" rescue nil) # if nothing has changed, there is no back button and we don't care
|
49
|
+
rescue => ex
|
50
|
+
error_occured(ex)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_categories!(app, primary, secondary)
|
54
|
+
verify_app(app)
|
55
|
+
open_app_page(app)
|
56
|
+
|
57
|
+
Helper.log.info "Setting primary/secondary category.'".green
|
58
|
+
if primary
|
59
|
+
all("select[ng-model='versionInfo.primaryCategory.value'] > option").each do |category|
|
60
|
+
if category.text.to_s == primary.to_s
|
61
|
+
category.select_option
|
62
|
+
primary = nil
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if primary
|
67
|
+
Helper.log.info "Could not find category '#{primary}'. Make sure it's available on iTC".red
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if secondary
|
72
|
+
all("select[ng-model='versionInfo.secondaryCategory.value'] > option").each do |category|
|
73
|
+
if category.text.to_s == secondary.to_s
|
74
|
+
category.select_option
|
75
|
+
secondary = nil
|
76
|
+
break
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if secondary
|
80
|
+
Helper.log.info "Could not find category '#{secondary}'. Make sure it's available on iTC".red
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
(click_on "Save" rescue nil) # if nothing has changed, there is no back button and we don't care
|
86
|
+
rescue => ex
|
87
|
+
error_occured(ex)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fastimage'
|
2
|
+
|
3
|
+
module Deliver
|
4
|
+
class ItunesConnect
|
5
|
+
# Uploading a new full size app icon
|
6
|
+
|
7
|
+
def upload_app_icon!(app, path)
|
8
|
+
path = File.expand_path(path)
|
9
|
+
raise "Could not find app icon at path '#{path}'".red unless File.exists?path
|
10
|
+
|
11
|
+
size = FastImage.size(path)
|
12
|
+
raise "App icon must have the resolution of 1024x1024px".red unless (size[0] == 1024 and size[1] == 1024)
|
13
|
+
|
14
|
+
begin
|
15
|
+
verify_app(app)
|
16
|
+
open_app_page(app)
|
17
|
+
|
18
|
+
Helper.log.info "Starting upload of new app icon".green
|
19
|
+
|
20
|
+
evaluate_script("$('.appversionicon > .ios7-style-icon').prev().click()") # delete button
|
21
|
+
evaluate_script("$('[style-class=\"appversionicon rounded\"] [itc-launch-filechooser] + input').attr('id', 'deliverFileUploadInput')") # set div
|
22
|
+
evaluate_script("URL = webkitURL; URL.createObjectURL = function(){return 'blob:abc'}"); # shim URL
|
23
|
+
page.attach_file("deliverFileUploadInput", path) # add file
|
24
|
+
|
25
|
+
sleep 10
|
26
|
+
|
27
|
+
click_on "Save"
|
28
|
+
|
29
|
+
Helper.log.info "Finished uploading the new app icon".green
|
30
|
+
rescue => ex
|
31
|
+
error_occured(ex)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Deliver
|
4
|
+
class ItunesConnect
|
5
|
+
# Setting the app's age restrictions
|
6
|
+
|
7
|
+
def set_app_rating!(app, path_to_json)
|
8
|
+
path_to_json = File.expand_path(path_to_json)
|
9
|
+
raise "Could not find app rating JSON file" unless File.exists?(path_to_json)
|
10
|
+
|
11
|
+
config = JSON.parse(File.read(path_to_json))
|
12
|
+
|
13
|
+
verify_app(app)
|
14
|
+
open_app_page(app)
|
15
|
+
|
16
|
+
Helper.log.info "Updating the app's rating".green
|
17
|
+
|
18
|
+
first("a[ng-show='versionInfo.ratings.isEditable']").click # open the ratings screen
|
19
|
+
|
20
|
+
rows = wait_for_elements(".defaultTable.ratingsTable > tbody > tr.ng-scope") # .ng-scope, since there is one empty row
|
21
|
+
|
22
|
+
if rows.count != config.count
|
23
|
+
raise "The number of options passed in the config file does not match the number of options available on iTC!".red
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
# Setting all the values based on config file
|
29
|
+
rows.each_with_index do |row, index|
|
30
|
+
current = config[index]
|
31
|
+
|
32
|
+
level = name_for_level(current['level'], current['type'] == 'boolean')
|
33
|
+
|
34
|
+
Helper.log.info "Setting '#{current['comment']}' to #{level}.".green
|
35
|
+
|
36
|
+
radio_value = "ITC.apps.ratings.level.#{level}"
|
37
|
+
|
38
|
+
row.first("td > div[radio-value='#{radio_value}']").click
|
39
|
+
end
|
40
|
+
|
41
|
+
# Check if there is a warning or error message because of this rating
|
42
|
+
error_message = first("p[ng-show='tempPageContent.ratingDialog.showErrorMessage']")
|
43
|
+
Helper.log.error error_message.text if error_message
|
44
|
+
|
45
|
+
Helper.log.info "Finished setting updated app rating"
|
46
|
+
|
47
|
+
(click_on "Done" rescue nil)
|
48
|
+
|
49
|
+
(click_on "Save" rescue nil) # if nothing has changed, there is no back button and we don't care
|
50
|
+
rescue => ex
|
51
|
+
error_occured(ex)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def name_for_level(level, is_boolean)
|
56
|
+
if is_boolean
|
57
|
+
return "NO" if level == 0
|
58
|
+
return "YES" if level == 1
|
59
|
+
else
|
60
|
+
return "NONE" if level == 0
|
61
|
+
return "INFREQUENT_MILD" if level == 1
|
62
|
+
return "FREQUENT_INTENSE" if level == 2
|
63
|
+
end
|
64
|
+
|
65
|
+
raise "Unknown level '#{level}' - must be 0, 1 or 2".red
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Deliver
|
2
|
+
class ItunesConnect
|
3
|
+
# All the private helpers
|
4
|
+
private
|
5
|
+
# Opens the app details page of the given app.
|
6
|
+
# @param app (Deliver::App) the app that should be opened
|
7
|
+
# @return (bool) true if everything worked fine
|
8
|
+
# @raise [ItunesConnectGeneralError] General error while executing
|
9
|
+
# this action
|
10
|
+
# @raise [ItunesConnectLoginError] Login data is wrong
|
11
|
+
def open_app_page(app)
|
12
|
+
verify_app(app)
|
13
|
+
|
14
|
+
Helper.log.info "Opening detail page for app #{app}"
|
15
|
+
|
16
|
+
visit APP_DETAILS_URL.gsub("[[app_id]]", app.apple_id.to_s)
|
17
|
+
|
18
|
+
wait_for_elements('.page-subnav')
|
19
|
+
sleep 5
|
20
|
+
|
21
|
+
if current_url.include?"wa/defaultError" # app could not be found
|
22
|
+
raise "Could not open app details for app '#{app}'. Make sure you're using the correct Apple ID and the correct Apple developer account (#{CredentialsManager::PasswordManager.shared_manager.username}).".red
|
23
|
+
end
|
24
|
+
|
25
|
+
true
|
26
|
+
rescue => ex
|
27
|
+
error_occured(ex)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def verify_app(app)
|
32
|
+
raise ItunesConnectGeneralError.new("No valid Deliver::App given") unless app.kind_of?Deliver::App
|
33
|
+
raise ItunesConnectGeneralError.new("App is missing information (apple_id not given)") unless (app.apple_id || '').to_s.length > 5
|
34
|
+
end
|
35
|
+
|
36
|
+
def error_occured(ex)
|
37
|
+
snap
|
38
|
+
raise ex # re-raise the error after saving the snapshot
|
39
|
+
end
|
40
|
+
|
41
|
+
def snap
|
42
|
+
path = "Error#{Time.now.to_i}.png"
|
43
|
+
save_screenshot(path, :full => true)
|
44
|
+
system("open '#{path}'")
|
45
|
+
end
|
46
|
+
|
47
|
+
# Since Apple takes for ages, after the upload is properly processed, we have to wait here
|
48
|
+
def wait_for_preprocessing
|
49
|
+
started = Time.now
|
50
|
+
|
51
|
+
# Wait, while iTunesConnect is processing the uploaded file
|
52
|
+
while page.has_content?"Uploaded"
|
53
|
+
# iTunesConnect is super slow... so we have to wait...
|
54
|
+
Helper.log.info("Sorry, we have to wait for iTunesConnect, since it's still processing the uploaded ipa file\n" +
|
55
|
+
"If this takes longer than 45 minutes, you have to re-upload the ipa file again.\n" +
|
56
|
+
"You can always open the browser page yourself: '#{current_url}'\n" +
|
57
|
+
"Passed time: ~#{((Time.now - started) / 60.0).to_i} minute(s)")
|
58
|
+
sleep 60
|
59
|
+
visit current_url
|
60
|
+
sleep 10
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def wait_for_elements(name)
|
65
|
+
counter = 0
|
66
|
+
results = all(name)
|
67
|
+
while results.count == 0
|
68
|
+
# Helper.log.debug "Waiting for #{name}"
|
69
|
+
sleep 0.2
|
70
|
+
|
71
|
+
results = all(name)
|
72
|
+
|
73
|
+
counter += 1
|
74
|
+
if counter > 100
|
75
|
+
Helper.log.debug page.html
|
76
|
+
Helper.log.debug caller
|
77
|
+
raise ItunesConnectGeneralError.new("Couldn't find element '#{name}' after waiting for quite some time")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
return results
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|