deliver 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|