xcode-utils 1.0.1 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/xcutils/carthage/xcconfig.rb +3 -3
- data/lib/xcutils/{carthage/colors.rb → colors.rb} +0 -0
- data/lib/xcutils/uitest.rb +128 -73
- data/lib/xcutils/version.rb +1 -1
- data/templates/UITestRunner/Base/UITestAuthorizationProvider.swift +1 -3
- data/templates/UITestRunner/Base/UITestSuite.swift +14 -10
- data/templates/UITestRunner/Suites/MainTestSuite.swift +1 -3
- data/templates/UITestRunner/UITestAuthorizationProviderImpl.swift +1 -3
- data/templates/UITestRunner/UITestRunnerViewController.swift +13 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '078c1054432a4dfb2ccd967637b74aa4cbc2aabdb67c80d000361c2407987694'
|
4
|
+
data.tar.gz: 3bd681d4b310c1f961bb9f85263965c44e73185f41cfa2a24310d987b7babb90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 654da996344614593d38fab2a17f90abd2e1a7342fcdf74b55aa1defbf2f7315005c7ea501d00a78cc12400d2a9eaa2992be3c924dff143de88332584359b211
|
7
|
+
data.tar.gz: 449501e3a2db25ede86c450c0437eec792893c4bf5a82ccd7595bb7f2a158a7f59aa1fdfab7b6af82dbe0ac04519bebe668698e197834df57df33cadde9e1341
|
data/README.md
CHANGED
@@ -9,6 +9,7 @@ $ gem install xcode-utils
|
|
9
9
|
```
|
10
10
|
|
11
11
|
## UITestRunner
|
12
|
+
Make available single test page in app as standalone
|
12
13
|
|
13
14
|
### Install UITestRunner in your xcode project
|
14
15
|
```
|
@@ -121,4 +122,4 @@ $ xcutils carthage clean
|
|
121
122
|
|
122
123
|
This project is licensed under the terms of the MIT license. See the [LICENSE](LICENSE) file.
|
123
124
|
|
124
|
-
> This project and all fastlane tools are in no way affiliated with Apple Inc or Google. This project is open source under the MIT license, which means you have full access to the source code and can modify it to fit your own needs. All fastlane tools run on your own computer or server, so your credentials or other sensitive information will never leave your own computer. You are responsible for how you use fastlane tools.
|
125
|
+
> This project and all fastlane tools are in no way affiliated with Apple Inc or Google. This project is open source under the MIT license, which means you have full access to the source code and can modify it to fit your own needs. All fastlane tools run on your own computer or server, so your credentials or other sensitive information will never leave your own computer. You are responsible for how you use fastlane tools.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'xcodeproj'
|
2
|
-
require 'xcutils/
|
2
|
+
require 'xcutils/colors'
|
3
3
|
|
4
4
|
module XcodeUtils
|
5
5
|
module Carthage
|
@@ -24,13 +24,13 @@ module XcodeUtils
|
|
24
24
|
|
25
25
|
def open_project
|
26
26
|
if !Dir.exist?(@build_path)
|
27
|
-
abort
|
27
|
+
abort "😭 The Carthage build has not yet been successful. Please try again after successful arthage build.".red
|
28
28
|
end
|
29
29
|
|
30
30
|
project_names = Dir["./*.xcodeproj"]
|
31
31
|
|
32
32
|
if project_names.first.nil?
|
33
|
-
abort
|
33
|
+
abort "😭 Does not exist project to configure.".red
|
34
34
|
end
|
35
35
|
|
36
36
|
puts "💎💎 Project Found -> #{project_names.first} 💎💎"
|
File without changes
|
data/lib/xcutils/uitest.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'xcodeproj'
|
2
2
|
require 'plist'
|
3
3
|
require 'nokogiri'
|
4
|
+
require 'xcutils/colors'
|
4
5
|
|
5
6
|
module XcodeUtils
|
6
7
|
class Command
|
@@ -14,15 +15,15 @@ module XcodeUtils
|
|
14
15
|
|
15
16
|
self.arguments = [
|
16
17
|
CLAide::Argument.new('PROJECT_NAME', :true),
|
17
|
-
CLAide::Argument.new('
|
18
|
-
CLAide::Argument.new('
|
18
|
+
CLAide::Argument.new('TARGET_CONFIG_NAME', :true),
|
19
|
+
CLAide::Argument.new('TARGET_SCHEME_NAME', :true)
|
19
20
|
]
|
20
21
|
|
21
22
|
def self.options
|
22
23
|
[
|
23
|
-
['--project-name
|
24
|
-
['--target-config
|
25
|
-
['--target-scheme
|
24
|
+
['--project-name', 'The name of your xcode project'],
|
25
|
+
['--target-config', 'The name of build configuration to be copied to uitestrunner build configuration'],
|
26
|
+
['--target-scheme', 'The name of build scheme to be copied to uitestrunner build scheme'],
|
26
27
|
]
|
27
28
|
end
|
28
29
|
|
@@ -44,100 +45,152 @@ module XcodeUtils
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def run
|
47
|
-
|
48
|
-
|
48
|
+
puts "🤖 Run: project_name: #{@project_name}, target_config: #{@taget_config}, target_scheme: #{@target_scheme}".green
|
49
|
+
open_project
|
50
|
+
generate_project_configuration
|
51
|
+
generate_build_configurations
|
52
|
+
generate_scheme_files
|
49
53
|
copy_template_files
|
54
|
+
|
55
|
+
if !@project.nil?
|
56
|
+
puts "Save project".green
|
57
|
+
@project.save()
|
58
|
+
puts "🤩 Finished".green
|
59
|
+
else
|
60
|
+
puts "😡 Aborted".red
|
61
|
+
end
|
50
62
|
end
|
51
|
-
|
52
|
-
def
|
53
|
-
puts "
|
63
|
+
|
64
|
+
def open_project
|
65
|
+
puts "Open project #{@project_name}"
|
66
|
+
|
67
|
+
if !Dir.exist?(@project_path)
|
68
|
+
abort "😭 Abort to install. Project #{project_name} does not exist".red
|
69
|
+
end
|
70
|
+
@project = Xcodeproj::Project.open(@project_path)
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_project_configuration
|
74
|
+
puts "Generating project configuration #{@uitest_name} into #{@project_name}"
|
54
75
|
|
55
|
-
|
56
|
-
configuration_list = project.root_object.build_configuration_list
|
76
|
+
configuration_list = @project.root_object.build_configuration_list
|
57
77
|
|
58
78
|
if configuration_list.build_settings(@uitest_name) != nil
|
59
|
-
puts "
|
79
|
+
puts "\tSkip to generate project configuration for #{@uitest_name}. It is already installed in the project #{@project_name}".gray
|
60
80
|
return
|
61
81
|
end
|
62
82
|
|
63
|
-
|
64
|
-
puts "Generating project configuration"
|
65
|
-
|
66
|
-
configuration = project.new(Xcodeproj::Project::Object::XCBuildConfiguration)
|
83
|
+
configuration = @project.new(Xcodeproj::Project::Object::XCBuildConfiguration)
|
67
84
|
configuration.name = @uitest_name
|
68
85
|
configuration.build_settings = configuration_list.build_settings(@taget_config)
|
69
86
|
configuration_list.build_configurations << configuration
|
87
|
+
end
|
88
|
+
|
89
|
+
def generate_build_configurations
|
90
|
+
puts "Generating build configurations"
|
70
91
|
|
71
|
-
project.targets.each
|
72
|
-
|
73
|
-
|
74
|
-
puts "Generating build configuration #{target.name}:#{@uitest_name}"
|
75
|
-
|
76
|
-
base_config = target.build_configurations.select { |e| e.name == @taget_config }.first
|
77
|
-
org_main_storyboard_file = nil
|
92
|
+
@project.targets.each { |target|
|
93
|
+
target_config = target.build_configurations.select { |e| e.name == @taget_config }.first
|
94
|
+
target_main_sb = nil
|
78
95
|
|
79
96
|
target.build_configurations.each { |e|
|
97
|
+
break if e.name == @uitest_name
|
98
|
+
|
99
|
+
puts "\tConfigure build configuration #{e.name} in #{target.name}"
|
100
|
+
|
80
101
|
path = e.build_settings['INFOPLIST_FILE']
|
81
|
-
|
82
|
-
|
83
|
-
e.build_settings['MAIN_STORYBOARD_FILE']
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
102
|
+
plist = Plist.parse_xml(path)
|
103
|
+
plist_main_sb = plist['UIMainStoryboardFile']
|
104
|
+
build_settings_main_sb = e.build_settings['MAIN_STORYBOARD_FILE']
|
105
|
+
variable_name = '$(MAIN_STORYBOARD_FILE)'
|
106
|
+
is_not_variable = plist_main_sb != variable_name
|
107
|
+
|
108
|
+
e.build_settings['MAIN_STORYBOARD_FILE'] = is_not_variable ? plist_main_sb : (target_main_sb != nil ? target_main_sb : build_settings_main_sb)
|
109
|
+
|
110
|
+
if target_main_sb.nil?
|
111
|
+
target_main_sb = build_settings_main_sb
|
88
112
|
end
|
113
|
+
|
114
|
+
plist['UIMainStoryboardFile'] = variable_name
|
89
115
|
|
90
|
-
|
116
|
+
if is_not_variable
|
117
|
+
File.write(path, plist.to_plist)
|
118
|
+
end
|
119
|
+
|
120
|
+
file_names_string = e.build_settings['EXCLUDED_SOURCE_FILE_NAMES']
|
121
|
+
file_names_string = appended(file_names_string, '$(SRCROOT)/$(PRODUCT_NAME)/UITestRunner/*')
|
122
|
+
file_names_string = appended(file_names_string, '$(SRCROOT)/$(PRODUCT_NAME)/UITestRunner/**/*')
|
123
|
+
e.build_settings['EXCLUDED_SOURCE_FILE_NAMES'] = file_names_string
|
91
124
|
}
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
125
|
+
|
126
|
+
test_config = target.build_configurations.select { |e| e.name == @uitest_name }.first
|
127
|
+
|
128
|
+
if test_config.nil?
|
129
|
+
puts "\tGenerating build configuration #{@uitest_name} into #{target.name}"
|
130
|
+
new_config = @project.new(Xcodeproj::Project::Object::XCBuildConfiguration)
|
131
|
+
new_config.name = @uitest_name
|
132
|
+
new_config.base_configuration_reference = target_config.base_configuration_reference
|
133
|
+
target.build_configurations << new_config
|
134
|
+
else
|
135
|
+
puts "\tConfigure build configuration #{@uitest_name} in #{target.name}"
|
136
|
+
new_config = test_config
|
137
|
+
end
|
138
|
+
|
139
|
+
new_config.build_settings.update(target_config.build_settings)
|
97
140
|
new_config.build_settings['MAIN_STORYBOARD_FILE'] = @uitest_name
|
141
|
+
new_config.build_settings['EXCLUDED_SOURCE_FILE_NAMES'] = nil
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def generate_scheme_files
|
146
|
+
puts "Generating scheme files"
|
98
147
|
|
99
|
-
|
148
|
+
@project.targets.each { |target|
|
149
|
+
scheme_name = "#{target.name} #{@uitest_name}"
|
150
|
+
|
151
|
+
if File.exist?(scheme_path(scheme_name))
|
152
|
+
puts "\tSkip to generate. A scheme file is already exsit, #{scheme_name}".gray
|
153
|
+
next
|
154
|
+
end
|
100
155
|
|
101
|
-
puts "
|
102
|
-
|
103
|
-
project.save()
|
104
|
-
end
|
105
|
-
end
|
156
|
+
puts "\tGenerating scheme file #{scheme_path(scheme_name)}"
|
106
157
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
scheme.launch_action.build_configuration = @uitest_name
|
114
|
-
scheme.save_as(@project_path, scheme_name)
|
158
|
+
FileUtils.copy_file(scheme_path(@target_scheme), scheme_path(scheme_name))
|
159
|
+
|
160
|
+
scheme = Xcodeproj::XCScheme.new(scheme_path(scheme_name))
|
161
|
+
scheme.launch_action.build_configuration = @uitest_name
|
162
|
+
scheme.save_as(@project_path, scheme_name)
|
163
|
+
}
|
115
164
|
end
|
116
165
|
|
117
166
|
def copy_template_files
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
167
|
+
puts "Copy template files"
|
168
|
+
|
169
|
+
@project.targets.each { |target|
|
170
|
+
template_path = "./#{target.name}/#{@uitest_name}"
|
171
|
+
|
172
|
+
if !Dir.exist?(template_path)
|
173
|
+
puts "\tCopying template files into target #{target.name}"
|
174
|
+
path = File.expand_path('../../../templates', __FILE__)
|
175
|
+
FileUtils.copy_entry path, "./#{target.name}"
|
176
|
+
else
|
177
|
+
puts "\tSkip to copy template files. Files are already exsit".gray
|
178
|
+
end
|
179
|
+
|
180
|
+
target_group = @project.groups.select { |e| e.path == target.name }.first
|
181
|
+
|
182
|
+
if target_group.groups.select { |e| e.path == @uitest_name }.first.nil?
|
183
|
+
puts "\tAdding references for files and resources into target #{target.name}"
|
184
|
+
template_group = target_group.new_group(nil, @uitest_name)
|
185
|
+
add_files("#{template_path}/*", template_group, target)
|
186
|
+
end
|
138
187
|
}
|
139
|
-
|
140
|
-
|
188
|
+
end
|
189
|
+
|
190
|
+
def appended(string, other)
|
191
|
+
return other if string == nil
|
192
|
+
return string if string.include? other
|
193
|
+
return string << " #{other}"
|
141
194
|
end
|
142
195
|
|
143
196
|
def add_files(direc, current_group, main_target)
|
@@ -157,6 +210,8 @@ module XcodeUtils
|
|
157
210
|
if item.include? ".storyboard" or item.include? ".xib"
|
158
211
|
set_custom_module(item)
|
159
212
|
main_target.add_resources([i])
|
213
|
+
else
|
214
|
+
main_target.add_resources([i])
|
160
215
|
end
|
161
216
|
end
|
162
217
|
end
|
data/lib/xcutils/version.rb
CHANGED
@@ -3,12 +3,10 @@
|
|
3
3
|
// Copyright © 2020 abc-studio. All rights reserved.
|
4
4
|
//
|
5
5
|
|
6
|
-
#if DEBUG
|
7
6
|
protocol UITestAuthorizationProvider {
|
8
7
|
var hasAccessToken: Bool {get}
|
9
8
|
var hasRefreshToken: Bool {get}
|
10
9
|
func refreshToken(completion: @escaping () -> Void)
|
11
10
|
func signIn(_ parent: UIViewController, completion: @escaping () -> Void)
|
12
11
|
func signOut()
|
13
|
-
}
|
14
|
-
#endif
|
12
|
+
}
|
@@ -3,7 +3,6 @@
|
|
3
3
|
// Copyright © 2020 abc-studio. All rights reserved.
|
4
4
|
//
|
5
5
|
|
6
|
-
#if DEBUG
|
7
6
|
import Foundation
|
8
7
|
|
9
8
|
protocol UITestSuiteInitializable {
|
@@ -20,13 +19,14 @@ class UITestSuite: UITestSuiteInitializable {
|
|
20
19
|
|
21
20
|
static var authorizationProvider: UITestAuthorizationProvider?
|
22
21
|
|
23
|
-
var
|
24
|
-
var useLogin = true
|
25
|
-
var testRunnerViewController: UITestRunnerViewController! {
|
22
|
+
weak var testRunnerViewController: UITestRunnerViewController! {
|
26
23
|
didSet {
|
27
24
|
setUp()
|
28
25
|
}
|
29
26
|
}
|
27
|
+
|
28
|
+
var isNewSession = false
|
29
|
+
var useLogin = true
|
30
30
|
var view: UIView {
|
31
31
|
return testRunnerViewController.view
|
32
32
|
}
|
@@ -62,7 +62,7 @@ class UITestSuite: UITestSuiteInitializable {
|
|
62
62
|
logout()
|
63
63
|
signIn()
|
64
64
|
} else {
|
65
|
-
Self.authorizationProvider?.
|
65
|
+
Self.authorizationProvider?.refreshToken {
|
66
66
|
self.runTests()
|
67
67
|
}
|
68
68
|
}
|
@@ -86,12 +86,16 @@ class UITestSuite: UITestSuiteInitializable {
|
|
86
86
|
}
|
87
87
|
|
88
88
|
extension UITestSuite {
|
89
|
+
func present(_ viewController: UIViewController, animated: Bool = false, completion: (() -> Void)? = nil) {
|
90
|
+
viewController.modalPresentationStyle = .fullScreen
|
91
|
+
testRunnerViewController.present(viewController, animated: animated, completion: completion)
|
92
|
+
}
|
93
|
+
|
89
94
|
@discardableResult
|
90
|
-
func present(
|
91
|
-
let navigationController = UINavigationController(rootViewController:
|
95
|
+
func present(rootViewController: UIViewController, animated: Bool = false, completion: (() -> Void)? = nil) -> UINavigationController {
|
96
|
+
let navigationController = UINavigationController(rootViewController: rootViewController)
|
92
97
|
navigationController.modalPresentationStyle = .fullScreen
|
93
|
-
testRunnerViewController.present(navigationController, animated:
|
98
|
+
testRunnerViewController.present(navigationController, animated: animated, completion: completion)
|
94
99
|
return navigationController
|
95
100
|
}
|
96
|
-
}
|
97
|
-
#endif
|
101
|
+
}
|
@@ -3,7 +3,6 @@
|
|
3
3
|
// Copyright © 2020 abc-studio. All rights reserved.
|
4
4
|
//
|
5
5
|
|
6
|
-
#if DEBUG
|
7
6
|
import Foundation
|
8
7
|
|
9
8
|
final class MainTestSuite: UITestSuite {
|
@@ -24,5 +23,4 @@ final class MainTestSuite: UITestSuite {
|
|
24
23
|
private func testExample() {
|
25
24
|
// This is an example of a functional test case.
|
26
25
|
}
|
27
|
-
}
|
28
|
-
#endif
|
26
|
+
}
|
@@ -3,7 +3,6 @@
|
|
3
3
|
// Copyright © 2020 abc-studio. All rights reserved.
|
4
4
|
//
|
5
5
|
|
6
|
-
#if DEBUG
|
7
6
|
struct UITestAuthorizationProviderImpl: UITestAuthorizationProvider {
|
8
7
|
|
9
8
|
// MARK: - Implementations of Protocol UITestAuthorizationProvider
|
@@ -23,5 +22,4 @@ struct UITestAuthorizationProviderImpl: UITestAuthorizationProvider {
|
|
23
22
|
|
24
23
|
func signOut() {
|
25
24
|
}
|
26
|
-
}
|
27
|
-
#endif
|
25
|
+
}
|
@@ -3,36 +3,39 @@
|
|
3
3
|
// Copyright © 2020 abc-studio. All rights reserved.
|
4
4
|
//
|
5
5
|
|
6
|
-
#if DEBUG
|
7
6
|
import UIKit
|
8
7
|
|
9
8
|
final class UITestRunnerViewController: UIViewController {
|
10
9
|
|
10
|
+
// MARK: - Private Properties
|
11
|
+
|
12
|
+
private var suite: UITestSuite!
|
13
|
+
|
11
14
|
// MARK: - Overridden: UIViewController
|
12
15
|
|
13
16
|
override func viewDidLoad() {
|
14
17
|
super.viewDidLoad()
|
15
18
|
|
16
|
-
title = "UITestRunner"
|
17
|
-
|
18
19
|
UITestSuite.authorizationProvider = UITestAuthorizationProviderImpl()
|
20
|
+
}
|
19
21
|
|
20
|
-
|
22
|
+
override func viewDidAppear(_ animated: Bool) {
|
23
|
+
super.viewDidAppear(animated)
|
24
|
+
|
25
|
+
if children.count < 1 {
|
26
|
+
runTestSuites()
|
27
|
+
}
|
21
28
|
}
|
22
|
-
|
23
|
-
// MARK: - Private Properties
|
24
|
-
|
25
|
-
private var suite: UITestSuite!
|
26
29
|
|
27
30
|
// MARK: - Private Methods
|
28
31
|
|
29
32
|
private func runTestSuites() {
|
30
33
|
runTestSuite(MainTestSuite.self)
|
31
34
|
}
|
35
|
+
|
32
36
|
private func runTestSuite<T: UITestSuite>(_ suiteType: T.Type) {
|
33
37
|
suite = suiteType.init()
|
34
38
|
suite.testRunnerViewController = self
|
35
39
|
suite.run()
|
36
40
|
}
|
37
|
-
}
|
38
|
-
#endif
|
41
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcode-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Kim
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: claide
|
@@ -123,8 +123,8 @@ files:
|
|
123
123
|
- bin/xcutils
|
124
124
|
- lib/xcutils.rb
|
125
125
|
- lib/xcutils/carthage.rb
|
126
|
-
- lib/xcutils/carthage/colors.rb
|
127
126
|
- lib/xcutils/carthage/xcconfig.rb
|
127
|
+
- lib/xcutils/colors.rb
|
128
128
|
- lib/xcutils/command.rb
|
129
129
|
- lib/xcutils/uitest.rb
|
130
130
|
- lib/xcutils/version.rb
|