xcunique 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +22 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +73 -0
  7. data/Rakefile +11 -0
  8. data/bin/xcunique +5 -0
  9. data/lib/json2plist/json2plist +21 -0
  10. data/lib/xcunique.rb +23 -0
  11. data/lib/xcunique/cli.rb +40 -0
  12. data/lib/xcunique/hash_ext.rb +25 -0
  13. data/lib/xcunique/helpers.rb +26 -0
  14. data/lib/xcunique/options.rb +68 -0
  15. data/lib/xcunique/parser.rb +54 -0
  16. data/lib/xcunique/sorter.rb +51 -0
  17. data/lib/xcunique/uniquifier.rb +36 -0
  18. data/lib/xcunique/version.rb +3 -0
  19. data/spec/fixtures/TestProject.json +548 -0
  20. data/spec/fixtures/TestProject/TestProject.xcodeproj/project.pbxproj +510 -0
  21. data/spec/fixtures/TestProject/TestProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  22. data/spec/fixtures/TestProject/TestProject.xcodeproj/project.xcworkspace/xcuserdata/paul.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  23. data/spec/fixtures/TestProject/TestProject.xcodeproj/xcuserdata/paul.xcuserdatad/xcschemes/TestProject.xcscheme +111 -0
  24. data/spec/fixtures/TestProject/TestProject.xcodeproj/xcuserdata/paul.xcuserdatad/xcschemes/xcschememanagement.plist +47 -0
  25. data/spec/fixtures/TestProject/TestProject/AppDelegate.swift +46 -0
  26. data/spec/fixtures/TestProject/TestProject/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  27. data/spec/fixtures/TestProject/TestProject/Base.lproj/LaunchScreen.storyboard +27 -0
  28. data/spec/fixtures/TestProject/TestProject/Base.lproj/Main.storyboard +26 -0
  29. data/spec/fixtures/TestProject/TestProject/Info.plist +47 -0
  30. data/spec/fixtures/TestProject/TestProject/ViewController.swift +25 -0
  31. data/spec/fixtures/TestProject/TestProjectTests/Info.plist +24 -0
  32. data/spec/fixtures/TestProject/TestProjectTests/TestProjectTests.swift +36 -0
  33. data/spec/fixtures/TestProject/TestProjectUITests/Info.plist +24 -0
  34. data/spec/fixtures/TestProject/TestProjectUITests/TestProjectUITests.swift +36 -0
  35. data/spec/spec_helper.rb +4 -0
  36. data/spec/xcunique/hash_ext_spec.rb +36 -0
  37. data/spec/xcunique/helpers_spec.rb +58 -0
  38. data/spec/xcunique/parser_spec.rb +214 -0
  39. data/spec/xcunique/sorter_spec.rb +116 -0
  40. data/xcunique.gemspec +26 -0
  41. metadata +178 -0
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>en</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>BNDL</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>1.0</string>
19
+ <key>CFBundleSignature</key>
20
+ <string>????</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>1</string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,36 @@
1
+ //
2
+ // TestProjectUITests.swift
3
+ // TestProjectUITests
4
+ //
5
+ // Created by Paul Samuels on 18/12/2015.
6
+ // Copyright © 2015 Paul Samuels. All rights reserved.
7
+ //
8
+
9
+ import XCTest
10
+
11
+ class TestProjectUITests: XCTestCase {
12
+
13
+ override func setUp() {
14
+ super.setUp()
15
+
16
+ // Put setup code here. This method is called before the invocation of each test method in the class.
17
+
18
+ // In UI tests it is usually best to stop immediately when a failure occurs.
19
+ continueAfterFailure = false
20
+ // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21
+ XCUIApplication().launch()
22
+
23
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24
+ }
25
+
26
+ override func tearDown() {
27
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
28
+ super.tearDown()
29
+ }
30
+
31
+ func testExample() {
32
+ // Use recording to get started writing UI tests.
33
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
34
+ }
35
+
36
+ }
@@ -0,0 +1,4 @@
1
+ require 'xcunique'
2
+
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
@@ -0,0 +1,36 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Hash do
4
+
5
+ it 'performs a deep duplicate of simple types' do
6
+ input = {
7
+ "array" => [ 1, 2, 3 ],
8
+ "string" => 'value'
9
+ }
10
+
11
+ result = input.deep_dup
12
+
13
+ assert_equal input, result
14
+ refute_equal input.object_id, result.object_id
15
+ refute_equal input['array'].object_id, result['array'].object_id
16
+ end
17
+
18
+ it 'substitutes objects that match in the substitutes hash' do
19
+ input = {
20
+ 'aaaa' => [ 1, 2, 3 ],
21
+ 'bbbb' => 'cccc',
22
+ 'dddd' => 'eeee'
23
+ }
24
+
25
+ expected = {
26
+ 'AAAA' => [ 1, 2, 3 ],
27
+ 'BBBB' => 'CCCC',
28
+ 'dddd' => 'eeee'
29
+ }
30
+
31
+ result = input.deep_dup(substitutions: { 'aaaa' => 'AAAA', 'bbbb' => 'BBBB', 'cccc' => 'CCCC' })
32
+
33
+ assert_equal expected, result
34
+ end
35
+
36
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Xcunique::Helpers do
4
+
5
+ it "returns an empty string if no name, path or fileRef are found" do
6
+ objects = {
7
+ 'aaaa' => {}
8
+ }
9
+
10
+ assert_equal '', Xcunique::Helpers.resolve_attributes('aaaa', objects)
11
+ end
12
+
13
+ it 'returns the name if found on the object' do
14
+ objects = {
15
+ 'aaaa' => {
16
+ 'name' => 'Test'
17
+ }
18
+ }
19
+
20
+ assert_equal "(name: 'Test')", Xcunique::Helpers.resolve_attributes('aaaa', objects)
21
+ end
22
+
23
+ it 'returns the path if found on the object' do
24
+ objects = {
25
+ 'aaaa' => {
26
+ 'path' => 'Test'
27
+ }
28
+ }
29
+
30
+ assert_equal "(path: 'Test')", Xcunique::Helpers.resolve_attributes('aaaa', objects)
31
+ end
32
+
33
+ it 'returns the name and path if found on the object' do
34
+ objects = {
35
+ 'aaaa' => {
36
+ 'name' => 'Test',
37
+ 'path' => 'Test'
38
+ }
39
+ }
40
+
41
+ assert_equal "(name: 'Test', path: 'Test')", Xcunique::Helpers.resolve_attributes('aaaa', objects)
42
+ end
43
+
44
+ it 'resolves the fileRef if there is one' do
45
+ objects = {
46
+ 'aaaa' => {
47
+ 'fileRef' => 'bbbb'
48
+ },
49
+ 'bbbb' => {
50
+ 'name' => 'Test',
51
+ 'path' => 'Test'
52
+ }
53
+ }
54
+
55
+ assert_equal "(name: 'Test', path: 'Test')", Xcunique::Helpers.resolve_attributes('aaaa', objects)
56
+ end
57
+
58
+ end
@@ -0,0 +1,214 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Xcunique::Parser do
4
+
5
+ before do
6
+ @project = JSON.load(File.open(File.expand_path('../fixtures/TestProject.json', __dir__)))
7
+ @parser = Xcunique::Parser.new(@project)
8
+ end
9
+
10
+ let(:root_uuid) { @project['rootObject'] }
11
+ let(:main_group) { @project['objects'][root_uuid]['mainGroup'] }
12
+
13
+ it 'correctly parses files and groups' do
14
+
15
+ @parser.parse object: main_group
16
+
17
+ result = @parser.visited
18
+
19
+ expectations = {
20
+
21
+ # ├── Project
22
+ "/PBXGroup" => 'DACE56891C24A14C00E6ABB0',
23
+
24
+ # ├── TestProject
25
+ #    ├── Products
26
+ #    ├── TestProject
27
+ #    ├── TestProjectTests
28
+ #    ├── TestProjectUITests
29
+ "/PBXGroup/PBXGroup(name: 'Products')" => 'DACE56931C24A14D00E6ABB0',
30
+ "/PBXGroup/PBXGroup(path: 'TestProject')" => 'DACE56941C24A14D00E6ABB0',
31
+ "/PBXGroup/PBXGroup(path: 'TestProjectTests')" => 'DACE56A91C24A14D00E6ABB0',
32
+ "/PBXGroup/PBXGroup(path: 'TestProjectUITests')" => 'DACE56B41C24A14D00E6ABB0',
33
+
34
+ # ├── TestProject
35
+ # │   ├── AppDelegate.swift
36
+ # │   ├── Assets.xcassets
37
+ # │   ├── Base.lproj
38
+ # │   │   ├── LaunchScreen.storyboard
39
+ # │   │   └── Main.storyboard
40
+ # │   ├── Info.plist
41
+ # │   └── ViewController.swift
42
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXFileReference(path: 'AppDelegate.swift')" => 'DACE56951C24A14D00E6ABB0',
43
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXFileReference(path: 'Assets.xcassets')" => 'DACE569C1C24A14D00E6ABB0',
44
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXVariantGroup(name: 'LaunchScreen.storyboard')" => 'DACE569E1C24A14D00E6ABB0',
45
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXVariantGroup(name: 'LaunchScreen.storyboard')/PBXFileReference(name: 'Base', path: 'Base.lproj/LaunchScreen.storyboard')" => 'DACE569F1C24A14D00E6ABB0',
46
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXVariantGroup(name: 'Main.storyboard')" => 'DACE56991C24A14D00E6ABB0',
47
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXVariantGroup(name: 'Main.storyboard')/PBXFileReference(name: 'Base', path: 'Base.lproj/Main.storyboard')" => 'DACE569A1C24A14D00E6ABB0',
48
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXFileReference(path: 'Info.plist')" => 'DACE56A11C24A14D00E6ABB0',
49
+ "/PBXGroup/PBXGroup(path: 'TestProject')/PBXFileReference(path: 'ViewController.swift')" => 'DACE56971C24A14D00E6ABB0',
50
+
51
+ # ├── TestProject
52
+ #    ├── TestProjectTests
53
+ #    │   ├── Info.plist
54
+ #    │   └── TestProjectTests.swift
55
+ "/PBXGroup/PBXGroup(path: 'TestProjectTests')/PBXFileReference(path: 'Info.plist')" => 'DACE56AC1C24A14D00E6ABB0',
56
+ "/PBXGroup/PBXGroup(path: 'TestProjectTests')/PBXFileReference(path: 'TestProjectTests.swift')" => 'DACE56AA1C24A14D00E6ABB0',
57
+
58
+ # ├── TestProject
59
+ #    └── TestProjectUITests
60
+ #       ├── Info.plist
61
+ #       └── TestProjectUITests.swift
62
+ "/PBXGroup/PBXGroup(path: 'TestProjectUITests')/PBXFileReference(path: 'Info.plist')" => 'DACE56B71C24A14D00E6ABB0',
63
+ "/PBXGroup/PBXGroup(path: 'TestProjectUITests')/PBXFileReference(path: 'TestProjectUITests.swift')" => 'DACE56B51C24A14D00E6ABB0',
64
+
65
+ # ├── TestProject
66
+ #    └── Products
67
+ #       ├── TestProject.app
68
+ "/PBXGroup/PBXGroup(name: 'Products')/PBXFileReference(path: 'TestProject.app')" => 'DACE56921C24A14D00E6ABB0',
69
+ "/PBXGroup/PBXGroup(name: 'Products')/PBXFileReference(path: 'TestProjectTests.xctest')" => 'DACE56A61C24A14D00E6ABB0',
70
+ "/PBXGroup/PBXGroup(name: 'Products')/PBXFileReference(path: 'TestProjectUITests.xctest')" => 'DACE56B11C24A14D00E6ABB0',
71
+ }
72
+
73
+ expectations.each do |path, uuid|
74
+ assert_equal path, result[uuid]
75
+ end
76
+
77
+ assert_equal [], result.keys - expectations.values
78
+
79
+ end
80
+
81
+ it 'correctly parses the remaining project objects' do
82
+
83
+ @parser.parse(object: main_group)
84
+ files_and_groups = @parser.visited.keys
85
+
86
+ @parser.parse(object: root_uuid)
87
+ result = @parser.visited.reject { |key, _| files_and_groups.include?(key) }
88
+
89
+ expectations = {
90
+
91
+ # ├── mainGroup
92
+ "/PBXProject" => "DACE568A1C24A14C00E6ABB0",
93
+
94
+ # ├── mainGroup
95
+ #    └── ProjectConfigurations
96
+ #       ├── Debug
97
+ #       ├── Release
98
+ "/PBXProject/XCConfigurationList" => "DACE568D1C24A14C00E6ABB0",
99
+ "/PBXProject/XCConfigurationList/XCBuildConfiguration(name: 'Debug')" => "DACE56B81C24A14D00E6ABB0",
100
+ "/PBXProject/XCConfigurationList/XCBuildConfiguration(name: 'Release')" => "DACE56B91C24A14D00E6ABB0",
101
+
102
+ # ├── mainGroup
103
+ #    └── Target = TestProject
104
+ #       └── Configurations
105
+ #          ├── Debug
106
+ #          ├── Release
107
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')" => "DACE56911C24A14D00E6ABB0",
108
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/XCConfigurationList" => "DACE56BA1C24A14D00E6ABB0",
109
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/XCConfigurationList/XCBuildConfiguration(name: 'Debug')" => "DACE56BB1C24A14D00E6ABB0",
110
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/XCConfigurationList/XCBuildConfiguration(name: 'Release')" => "DACE56BC1C24A14D00E6ABB0",
111
+
112
+ # ├── mainGroup
113
+ #    └── Target = TestProject
114
+ #       └── Build Sources
115
+ #          ├── ViewController.swift
116
+ #          ├── AppDelegate.swift
117
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXSourcesBuildPhase" => "DACE568E1C24A14D00E6ABB0",
118
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXSourcesBuildPhase/PBXBuildFile(path: 'ViewController.swift')" => "DACE56981C24A14D00E6ABB0",
119
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXSourcesBuildPhase/PBXBuildFile(path: 'AppDelegate.swift')" => "DACE56961C24A14D00E6ABB0",
120
+
121
+ # ├── mainGroup
122
+ #    └── Target = TestProject
123
+ #       └── Copy Frameworks
124
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXFrameworksBuildPhase" => "DACE568F1C24A14D00E6ABB0",
125
+
126
+ # ├── mainGroup
127
+ #    └── Target = TestProject
128
+ #       └── Copy Resources
129
+ #          ├── LaunchScreen.storyboard
130
+ #          ├── Assets.xcassets
131
+ #          ├── Main.storyboard
132
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXResourcesBuildPhase" => "DACE56901C24A14D00E6ABB0",
133
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXResourcesBuildPhase/PBXBuildFile(name: 'LaunchScreen.storyboard')" => "DACE56A01C24A14D00E6ABB0",
134
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXResourcesBuildPhase/PBXBuildFile(path: 'Assets.xcassets')" => "DACE569D1C24A14D00E6ABB0",
135
+ "/PBXProject/PBXNativeTarget(name: 'TestProject')/PBXResourcesBuildPhase/PBXBuildFile(name: 'Main.storyboard')" => "DACE569B1C24A14D00E6ABB0",
136
+
137
+ # ├── mainGroup
138
+ #    └── Target = TestProjectTests
139
+ #       └── Configurations
140
+ #          ├── Debug
141
+ #          ├── Release
142
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')" => "DACE56A51C24A14D00E6ABB0",
143
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/XCConfigurationList" => "DACE56BD1C24A14D00E6ABB0",
144
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/XCConfigurationList/XCBuildConfiguration(name: 'Debug')" => "DACE56BE1C24A14D00E6ABB0",
145
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/XCConfigurationList/XCBuildConfiguration(name: 'Release')" => "DACE56BF1C24A14D00E6ABB0",
146
+
147
+ # ├── mainGroup
148
+ #    └── Target = TestProjectTests
149
+ #       └── Build Sources
150
+ #          ├── TestProjectTests.swift
151
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXSourcesBuildPhase" => "DACE56A21C24A14D00E6ABB0",
152
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXSourcesBuildPhase/PBXBuildFile(path: 'TestProjectTests.swift')" => "DACE56AB1C24A14D00E6ABB0",
153
+
154
+ # ├── mainGroup
155
+ #    └── Target = TestProjectTests
156
+ #       └── Copy Frameworks
157
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXFrameworksBuildPhase" => "DACE56A31C24A14D00E6ABB0",
158
+
159
+ # ├── mainGroup
160
+ #    └── Target = TestProjectTests
161
+ #       └── Copy Resources
162
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXResourcesBuildPhase" => "DACE56A41C24A14D00E6ABB0",
163
+
164
+ # ├── mainGroup
165
+ #    └── Target = TestProjectTests
166
+ #       └── Dependencies
167
+ #          ├── TestProject
168
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXTargetDependency" => "DACE56A81C24A14D00E6ABB0",
169
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectTests')/PBXTargetDependency/PBXContainerItemProxy" => "DACE56A71C24A14D00E6ABB0",
170
+
171
+ # ├── mainGroup
172
+ #    └── Target = TestProjectUITests
173
+ #       └── Configurations
174
+ #          ├── Debug
175
+ #          ├── Release
176
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')" => "DACE56B01C24A14D00E6ABB0",
177
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/XCConfigurationList" => "DACE56C01C24A14D00E6ABB0",
178
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/XCConfigurationList/XCBuildConfiguration(name: 'Debug')" => "DACE56C11C24A14D00E6ABB0",
179
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/XCConfigurationList/XCBuildConfiguration(name: 'Release')" => "DACE56C21C24A14D00E6ABB0",
180
+
181
+ # ├── mainGroup
182
+ #    └── Target = TestProjectUITests
183
+ #       └── Build Sources
184
+ #          ├── TestProjectUITests.swift
185
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXSourcesBuildPhase" => "DACE56AD1C24A14D00E6ABB0",
186
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXSourcesBuildPhase/PBXBuildFile(path: 'TestProjectUITests.swift')" => "DACE56B61C24A14D00E6ABB0",
187
+
188
+ # ├── mainGroup
189
+ #    └── Target = TestProjectUITests
190
+ #       └── Copy Frameworks
191
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXFrameworksBuildPhase" => "DACE56AE1C24A14D00E6ABB0",
192
+
193
+ # ├── mainGroup
194
+ #    └── Target = TestProjectUITests
195
+ #       └── Copy Resources
196
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXResourcesBuildPhase" => "DACE56AF1C24A14D00E6ABB0",
197
+
198
+ # ├── mainGroup
199
+ #    └── Target = TestProjectUITests
200
+ #       └── Dependencies
201
+ #          ├── TestProject
202
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXTargetDependency" => "DACE56B31C24A14D00E6ABB0",
203
+ "/PBXProject/PBXNativeTarget(name: 'TestProjectUITests')/PBXTargetDependency/PBXContainerItemProxy" => "DACE56B21C24A14D00E6ABB0"
204
+ }
205
+
206
+ expectations.each do |path, uuid|
207
+ assert_equal path, result[uuid]
208
+ end
209
+
210
+ assert_equal [], result.keys - expectations.values
211
+
212
+ end
213
+
214
+ end
@@ -0,0 +1,116 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Xcunique::Sorter do
4
+
5
+ describe "when sorting groups" do
6
+ it "sorts alphabetically by their name" do
7
+ project = {
8
+ 'objects' => {
9
+ 'PARENT' => { 'children' => [ 'groupB', 'groupA' ] },
10
+ 'groupA' => { 'name' => 'A' },
11
+ 'groupB' => { 'name' => 'B' }
12
+ }
13
+ }
14
+
15
+ result = Xcunique::Sorter.new(project).sort
16
+
17
+ assert_equal [ 'groupA', 'groupB' ], result['objects']['PARENT']['children']
18
+ end
19
+
20
+ it "sorts alphabetically by their path" do
21
+ project = {
22
+ 'objects' => {
23
+ 'PARENT' => { 'children' => [ 'groupB', 'groupA' ] },
24
+ 'groupA' => { 'path' => 'A' },
25
+ 'groupB' => { 'path' => 'B' }
26
+ }
27
+ }
28
+
29
+ result = Xcunique::Sorter.new(project).sort
30
+
31
+ assert_equal [ 'groupA', 'groupB' ], result['objects']['PARENT']['children']
32
+ end
33
+
34
+ it "sorts alphabetically by their name then path" do
35
+ project = {
36
+ 'objects' => {
37
+ 'PARENT' => { 'children' => [ 'groupB', 'groupA' ] },
38
+ 'groupA' => { 'name' => 'A', 'path' => 'B' },
39
+ 'groupB' => { 'name' => 'B', 'path' => 'A' }
40
+ }
41
+ }
42
+
43
+ result = Xcunique::Sorter.new(project).sort
44
+
45
+ assert_equal [ 'groupA', 'groupB' ], result['objects']['PARENT']['children']
46
+ end
47
+ end
48
+
49
+ describe "when sorting files" do
50
+ it "sorts alphabetically by their name" do
51
+ project = {
52
+ 'objects' => {
53
+ 'PARENT' => { 'files' => [ 'buildFileB', 'buildFileA' ] },
54
+ 'buildFileA' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileA' },
55
+ 'buildFileB' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileB' },
56
+ 'fileA' => { 'name' => 'a.swift' },
57
+ 'fileB' => { 'name' => 'b.swift' }
58
+ }
59
+ }
60
+
61
+ result = Xcunique::Sorter.new(project).sort
62
+
63
+ assert_equal [ 'buildFileA', 'buildFileB' ], result['objects']['PARENT']['files']
64
+ end
65
+
66
+ it "sorts alphabetically by their path" do
67
+ project = {
68
+ 'objects' => {
69
+ 'PARENT' => { 'files' => [ 'buildFileB', 'buildFileA' ] },
70
+ 'buildFileA' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileA' },
71
+ 'buildFileB' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileB' },
72
+ 'fileA' => { 'path' => 'a.swift' },
73
+ 'fileB' => { 'path' => 'b.swift' }
74
+ }
75
+ }
76
+
77
+ result = Xcunique::Sorter.new(project).sort
78
+
79
+ assert_equal [ 'buildFileA', 'buildFileB' ], result['objects']['PARENT']['files']
80
+ end
81
+
82
+ it "sorts alphabetically by their name then path" do
83
+ project = {
84
+ 'objects' => {
85
+ 'PARENT' => { 'files' => [ 'buildFileB', 'buildFileA' ] },
86
+ 'buildFileA' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileA' },
87
+ 'buildFileB' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileB' },
88
+ 'fileA' => { 'name' => 'a.swift', 'path' => 'b/a.swift' },
89
+ 'fileB' => { 'name' => 'b.swift', 'path' => 'a/b.swift' }
90
+ }
91
+ }
92
+
93
+ result = Xcunique::Sorter.new(project).sort
94
+
95
+ assert_equal [ 'buildFileA', 'buildFileB' ], result['objects']['PARENT']['files']
96
+ end
97
+ end
98
+
99
+ describe "when sorting groups and files" do
100
+ it "sorts groups before files" do
101
+ project = {
102
+ 'objects' => {
103
+ 'PARENT' => { 'children' => [ 'buildFileA', 'groupA' ] },
104
+ 'buildFileA' => { 'isa' => 'PBXBuildFile', 'fileRef' => 'fileA' },
105
+ 'groupA' => { 'isa' => 'PBXGroup', 'name' => 'a' },
106
+ 'fileA' => { 'name' => 'a' },
107
+ }
108
+ }
109
+
110
+ result = Xcunique::Sorter.new(project).sort
111
+
112
+ assert_equal [ 'groupA', 'buildFileA' ], result['objects']['PARENT']['children']
113
+ end
114
+ end
115
+
116
+ end