Skip to content

Commit f762502

Browse files
committed
feat: implement support for the App Clip's URL
1 parent e878751 commit f762502

File tree

3 files changed

+199
-4
lines changed

3 files changed

+199
-4
lines changed

Fixtures/Schemes/AppClip.xcscheme

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1600"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES"
8+
buildArchitectures = "Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting = "YES"
12+
buildForRunning = "YES"
13+
buildForProfiling = "YES"
14+
buildForArchiving = "YES"
15+
buildForAnalyzing = "YES">
16+
<BuildableReference
17+
BuildableIdentifier = "primary"
18+
BlueprintIdentifier = "5CC725022DA91FB6004D43D4"
19+
BuildableName = "app_clip.app"
20+
BlueprintName = "app_clip"
21+
ReferencedContainer = "container:example.xcodeproj">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
25+
</BuildAction>
26+
<TestAction
27+
buildConfiguration = "Debug"
28+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
29+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Debug"
35+
appClipInvocationURLString = "https://example.com/"
36+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
37+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
38+
launchStyle = "0"
39+
useCustomWorkingDirectory = "NO"
40+
ignoresPersistentStateOnLaunch = "NO"
41+
debugDocumentVersioning = "YES"
42+
debugServiceExtension = "internal"
43+
allowLocationSimulation = "YES">
44+
<BuildableProductRunnable
45+
runnableDebuggingMode = "0">
46+
<BuildableReference
47+
BuildableIdentifier = "primary"
48+
BlueprintIdentifier = "5CC725022DA91FB6004D43D4"
49+
BuildableName = "app_clip.app"
50+
BlueprintName = "app_clip"
51+
ReferencedContainer = "container:example.xcodeproj">
52+
</BuildableReference>
53+
</BuildableProductRunnable>
54+
</LaunchAction>
55+
<ProfileAction
56+
buildConfiguration = "Release"
57+
appClipInvocationURLString = "https://example.com/"
58+
shouldUseLaunchSchemeArgsEnv = "YES"
59+
savedToolIdentifier = ""
60+
useCustomWorkingDirectory = "NO"
61+
debugDocumentVersioning = "YES">
62+
<BuildableProductRunnable
63+
runnableDebuggingMode = "0">
64+
<BuildableReference
65+
BuildableIdentifier = "primary"
66+
BlueprintIdentifier = "5CC725022DA91FB6004D43D4"
67+
BuildableName = "app_clip.app"
68+
BlueprintName = "app_clip"
69+
ReferencedContainer = "container:example.xcodeproj">
70+
</BuildableReference>
71+
</BuildableProductRunnable>
72+
</ProfileAction>
73+
<AnalyzeAction
74+
buildConfiguration = "Debug">
75+
</AnalyzeAction>
76+
<ArchiveAction
77+
buildConfiguration = "Release"
78+
revealArchiveInOrganizer = "YES">
79+
</ArchiveAction>
80+
</Scheme>

Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift

+15-4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public extension XCScheme {
8484
// To enable the option in Xcode: defaults write com.apple.dt.Xcode IDEDebuggerFeatureSetting 12
8585
public var customLaunchCommand: String?
8686
public var customLLDBInitFile: String?
87+
public var appClipInvocationURLString: String?
8788

8889
// MARK: - Init
8990

@@ -126,7 +127,8 @@ public extension XCScheme {
126127
launchAutomaticallySubstyle: String? = nil,
127128
storeKitConfigurationFileReference: StoreKitConfigurationFileReference? = nil,
128129
customLaunchCommand: String? = nil,
129-
customLLDBInitFile: String? = nil) {
130+
customLLDBInitFile: String? = nil,
131+
appClipInvocationURLString: String? = nil) {
130132
self.runnable = runnable
131133
self.macroExpansion = macroExpansion
132134
self.buildConfiguration = buildConfiguration
@@ -165,6 +167,7 @@ public extension XCScheme {
165167
self.storeKitConfigurationFileReference = storeKitConfigurationFileReference
166168
self.customLaunchCommand = customLaunchCommand
167169
self.customLLDBInitFile = customLLDBInitFile
170+
self.appClipInvocationURLString = appClipInvocationURLString
168171
super.init(preActions, postActions)
169172
}
170173

@@ -210,7 +213,8 @@ public extension XCScheme {
210213
launchAutomaticallySubstyle: String? = nil,
211214
storeKitConfigurationFileReference: StoreKitConfigurationFileReference? = nil,
212215
customLaunchCommand: String? = nil,
213-
customLLDBInitFile: String? = nil
216+
customLLDBInitFile: String? = nil,
217+
appClipInvocationURLString: String? = nil
214218
) {
215219
self.init(
216220
runnable: pathRunnable,
@@ -252,7 +256,8 @@ public extension XCScheme {
252256
launchAutomaticallySubstyle: launchAutomaticallySubstyle,
253257
storeKitConfigurationFileReference: storeKitConfigurationFileReference,
254258
customLaunchCommand: customLaunchCommand,
255-
customLLDBInitFile: customLLDBInitFile
259+
customLLDBInitFile: customLLDBInitFile,
260+
appClipInvocationURLString: appClipInvocationURLString
256261
)
257262
}
258263

@@ -338,6 +343,8 @@ public extension XCScheme {
338343
customWorkingDirectory = elementCustomWorkingDirectory
339344
}
340345

346+
appClipInvocationURLString = element.attributes["appClipInvocationURLString"]
347+
341348
try super.init(element: element)
342349
}
343350

@@ -404,6 +411,9 @@ public extension XCScheme {
404411
if let customWorkingDirectory {
405412
attributes["customWorkingDirectory"] = customWorkingDirectory
406413
}
414+
if let appClipInvocationURLString {
415+
attributes["appClipInvocationURLString"] = appClipInvocationURLString
416+
}
407417

408418
return attributes
409419
}
@@ -513,7 +523,8 @@ public extension XCScheme {
513523
launchAutomaticallySubstyle == rhs.launchAutomaticallySubstyle &&
514524
storeKitConfigurationFileReference == rhs.storeKitConfigurationFileReference &&
515525
customLaunchCommand == rhs.customLaunchCommand &&
516-
customLLDBInitFile == rhs.customLLDBInitFile
526+
customLLDBInitFile == rhs.customLLDBInitFile &&
527+
appClipInvocationURLString == rhs.appClipInvocationURLString
517528
}
518529
}
519530
}

Tests/XcodeProjTests/Scheme/XCSchemeTests.swift

+104
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ final class XCSchemeIntegrationTests: XCTestCase {
2121
initModel: XCScheme.init(path:))
2222
}
2323

24+
func test_read_appClipScheme() {
25+
let subject = try? XCScheme(path: appClipScheme)
26+
XCTAssertNotNil(subject)
27+
if let subject {
28+
assert(appClip: subject)
29+
}
30+
}
31+
2432
func test_read_runnableWithoutBuildableReferenceScheme() {
2533
let subject = try? XCScheme(path: runnableWithoutBuildableReferenceSchemePath)
2634

@@ -586,6 +594,7 @@ final class XCSchemeIntegrationTests: XCTestCase {
586594
XCTAssertEqual(scheme.launchAction?.disablePerformanceAntipatternChecker, false)
587595
XCTAssertEqual(scheme.launchAction?.stopOnEveryMainThreadCheckerIssue, false)
588596
XCTAssertEqual(scheme.launchAction?.additionalOptions.isEmpty, true)
597+
XCTAssertEqual(scheme.launchAction?.appClipInvocationURLString, nil)
589598

590599
let launchEnvironmentVariables = XCTAssertNotNilAndUnwrap(scheme.launchAction?.environmentVariables)
591600
XCTAssertEqual(launchEnvironmentVariables.count, 1)
@@ -679,6 +688,7 @@ final class XCSchemeIntegrationTests: XCTestCase {
679688
XCTAssertEqual(scheme.launchAction?.macroExpansion?.blueprintName, "core-ava")
680689
XCTAssertEqual(scheme.launchAction?.macroExpansion?.referencedContainer, "container:core-ava.xcodeproj")
681690
XCTAssertNil(scheme.launchAction?.environmentVariables)
691+
XCTAssertNil(scheme.launchAction?.appClipInvocationURLString)
682692

683693
// Profile action
684694
XCTAssertEqual(scheme.profileAction?.runnable?.runnableDebuggingMode, "0")
@@ -769,6 +779,7 @@ final class XCSchemeIntegrationTests: XCTestCase {
769779
XCTAssertEqual(scheme.launchAction?.stopOnEveryMainThreadCheckerIssue, false)
770780
XCTAssertEqual(scheme.launchAction?.additionalOptions.isEmpty, true)
771781
XCTAssertNil(scheme.launchAction?.storeKitConfigurationFileReference)
782+
XCTAssertNil(scheme.launchAction?.appClipInvocationURLString)
772783

773784
let launchEnvironmentVariables = XCTAssertNotNilAndUnwrap(scheme.launchAction?.environmentVariables)
774785
XCTAssertEqual(launchEnvironmentVariables.count, 1)
@@ -797,6 +808,95 @@ final class XCSchemeIntegrationTests: XCTestCase {
797808
XCTAssertNil(scheme.archiveAction?.customArchiveName)
798809
}
799810

811+
private func assert(appClip scheme: XCScheme) {
812+
XCTAssertEqual(scheme.version, "1.7")
813+
XCTAssertEqual(scheme.lastUpgradeVersion, "1600", "\(scheme.lastUpgradeVersion!) not equals 1600")
814+
815+
// Build action
816+
XCTAssertTrue(scheme.buildAction?.parallelizeBuild == true)
817+
XCTAssertTrue(scheme.buildAction?.buildImplicitDependencies == true)
818+
XCTAssertNil(scheme.buildAction?.runPostActionsOnFailure)
819+
XCTAssertEqual(scheme.buildAction?.buildActionEntries.count, 1)
820+
XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.testing) == true)
821+
XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.running) == true)
822+
XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.profiling) == true)
823+
XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.archiving) == true)
824+
XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.analyzing) == true)
825+
XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.buildableIdentifier, "primary")
826+
XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.blueprintIdentifier, "5CC725022DA91FB6004D43D4")
827+
XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.buildableName, "app_clip.app")
828+
XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.blueprintName, "app_clip")
829+
XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.referencedContainer, "container:example.xcodeproj")
830+
831+
// Test action
832+
XCTAssertEqual(scheme.testAction?.buildConfiguration, "Debug")
833+
XCTAssertEqual(scheme.testAction?.selectedDebuggerIdentifier, "Xcode.DebuggerFoundation.Debugger.LLDB")
834+
XCTAssertEqual(scheme.testAction?.selectedLauncherIdentifier, "Xcode.DebuggerFoundation.Launcher.LLDB")
835+
XCTAssertTrue(scheme.testAction?.shouldUseLaunchSchemeArgsEnv == true)
836+
XCTAssertTrue(scheme.testAction?.codeCoverageEnabled == false)
837+
XCTAssertEqual(scheme.testAction?.onlyGenerateCoverageForSpecifiedTargets, nil)
838+
XCTAssertNil(scheme.testAction?.macroExpansion)
839+
XCTAssertEqual(scheme.testAction?.enableAddressSanitizer, false)
840+
XCTAssertEqual(scheme.testAction?.enableASanStackUseAfterReturn, false)
841+
XCTAssertEqual(scheme.testAction?.enableThreadSanitizer, false)
842+
XCTAssertEqual(scheme.testAction?.enableUBSanitizer, false)
843+
XCTAssertEqual(scheme.testAction?.disableMainThreadChecker, false)
844+
XCTAssertEqual(scheme.testAction?.additionalOptions.isEmpty, true)
845+
XCTAssertNil(scheme.testAction?.commandlineArguments)
846+
XCTAssertNil(scheme.testAction?.environmentVariables)
847+
848+
// Launch action
849+
XCTAssertEqual(scheme.launchAction?.selectedDebuggerIdentifier, XCScheme.defaultDebugger)
850+
XCTAssertEqual(scheme.launchAction?.selectedLauncherIdentifier, XCScheme.defaultLauncher)
851+
XCTAssertEqual(scheme.launchAction?.buildConfiguration, "Debug")
852+
XCTAssertEqual(scheme.launchAction?.launchStyle, XCScheme.LaunchAction.Style.auto)
853+
XCTAssertNil(scheme.launchAction?.askForAppToLaunch)
854+
XCTAssertNil(scheme.launchAction?.customWorkingDirectory)
855+
XCTAssertTrue(scheme.launchAction?.useCustomWorkingDirectory == false)
856+
XCTAssertTrue(scheme.launchAction?.ignoresPersistentStateOnLaunch == false)
857+
XCTAssertTrue(scheme.launchAction?.debugDocumentVersioning == true)
858+
XCTAssertEqual(scheme.launchAction?.debugServiceExtension, XCScheme.LaunchAction.defaultDebugServiceExtension)
859+
XCTAssertTrue(scheme.launchAction?.allowLocationSimulation == true)
860+
XCTAssertNil(scheme.launchAction?.locationScenarioReference)
861+
XCTAssertNil(scheme.launchAction?.commandlineArguments)
862+
XCTAssertEqual(scheme.launchAction?.enableAddressSanitizer, false)
863+
XCTAssertEqual(scheme.launchAction?.enableASanStackUseAfterReturn, false)
864+
XCTAssertEqual(scheme.launchAction?.enableThreadSanitizer, false)
865+
XCTAssertEqual(scheme.launchAction?.stopOnEveryThreadSanitizerIssue, false)
866+
XCTAssertEqual(scheme.launchAction?.enableUBSanitizer, false)
867+
XCTAssertEqual(scheme.launchAction?.stopOnEveryUBSanitizerIssue, false)
868+
XCTAssertEqual(scheme.launchAction?.disableMainThreadChecker, false)
869+
XCTAssertEqual(scheme.launchAction?.disablePerformanceAntipatternChecker, false)
870+
XCTAssertEqual(scheme.launchAction?.stopOnEveryMainThreadCheckerIssue, false)
871+
XCTAssertEqual(scheme.launchAction?.additionalOptions.isEmpty, true)
872+
XCTAssertNil(scheme.launchAction?.storeKitConfigurationFileReference)
873+
XCTAssertNil(scheme.launchAction?.macroExpansion?.referencedContainer)
874+
XCTAssertNil(scheme.launchAction?.environmentVariables)
875+
XCTAssertEqual(scheme.launchAction?.appClipInvocationURLString, "https://example.com/")
876+
877+
// Profile action
878+
XCTAssertEqual(scheme.profileAction?.runnable?.runnableDebuggingMode, "0")
879+
XCTAssertEqual(scheme.profileAction?.runnable?.buildableReference?.referencedContainer, "container:example.xcodeproj")
880+
XCTAssertEqual(scheme.profileAction?.buildConfiguration, "Release")
881+
XCTAssertTrue(scheme.profileAction?.shouldUseLaunchSchemeArgsEnv == true)
882+
XCTAssertEqual(scheme.profileAction?.savedToolIdentifier, "")
883+
XCTAssertNil(scheme.profileAction?.customWorkingDirectory)
884+
XCTAssertTrue(scheme.profileAction?.useCustomWorkingDirectory == false)
885+
XCTAssertTrue(scheme.profileAction?.debugDocumentVersioning == true)
886+
XCTAssertNil(scheme.profileAction?.askForAppToLaunch)
887+
XCTAssertNil(scheme.profileAction?.commandlineArguments)
888+
XCTAssertNil(scheme.profileAction?.environmentVariables)
889+
XCTAssertNil(scheme.profileAction?.launchAutomaticallySubstyle)
890+
891+
// Analyze action
892+
XCTAssertEqual(scheme.analyzeAction?.buildConfiguration, "Debug")
893+
894+
// Archive action
895+
XCTAssertEqual(scheme.archiveAction?.buildConfiguration, "Release")
896+
XCTAssertTrue(scheme.archiveAction?.revealArchiveInOrganizer == true)
897+
XCTAssertNil(scheme.archiveAction?.customArchiveName)
898+
}
899+
800900
private func buildableReferenceWithStringBluePrint(name: String = "App") throws -> XCScheme.BuildableReference {
801901
// To allow performing comparisons when serializing / deserializing we need a
802902
// buildable reference that contains a `.string` blue print
@@ -842,4 +942,8 @@ final class XCSchemeIntegrationTests: XCTestCase {
842942
private var buildArchitecturesSchemePath: Path {
843943
fixturesPath() + "Schemes/BuildArchitectures.xcscheme"
844944
}
945+
946+
private var appClipScheme: Path {
947+
fixturesPath() + "Schemes/AppClip.xcscheme"
948+
}
845949
}

0 commit comments

Comments
 (0)