diff --git a/.mention-bot b/.mention-bot new file mode 100644 index 0000000..2c6b66a --- /dev/null +++ b/.mention-bot @@ -0,0 +1,4 @@ +{ + "maxReviewers": 2, + "requiredOrgs": ["hyperoslo"] +} diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..8034f5f --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,30 @@ +included: + - Sources +excluded: + - Carthage + - Pods + - Packages +opt_in_rules: + - empty_count +disabled_rules: + - valid_docs +force_cast: warning +force_try: + severity: warning +line_length: 120 +function_body_length: + - 150 +type_body_length: + warning: 300 + error: 400 +file_length: + warning: 500 + error: 1200 +type_name: + min_length: 3 + max_length: + warning: 40 + error: 50 +variable_name: + min_length: 2 +reporter: "xcode" diff --git a/.travis.yml b/.travis.yml index ed6242b..38a8813 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ +os: + - osx osx_image: xcode7.3 language: objective-c - -before_install: -- brew update -- if brew outdated | grep -qx xctool; then brew upgrade xctool; fi -- carthage update --platform iOS,Mac - +install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./swiftlint.sh; fi script: -- xctool clean build -project Compass.xcodeproj -scheme Compass-iOS -sdk iphonesimulator -- xctool test -project Compass.xcodeproj -scheme Compass-iOS -sdk iphonesimulator -- xctool clean build -project Compass.xcodeproj -scheme Compass-Mac -sdk macosx -- xctool test -project Compass.xcodeproj -scheme Compass-Mac -sdk macosx + - xcodebuild clean build -project Compass.xcodeproj -scheme Compass-iOS -sdk iphonesimulator + - xcodebuild test -project Compass.xcodeproj -scheme Compass-iOS -sdk iphonesimulator + - xcodebuild clean build -project Compass.xcodeproj -scheme Compass-Mac -sdk macosx + - xcodebuild test -project Compass.xcodeproj -scheme Compass-Mac -sdk macosx +notifications: + email: false diff --git a/Cartfile b/Cartfile deleted file mode 100644 index 324ff66..0000000 --- a/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "hyperoslo/Sugar" diff --git a/Cartfile.resolved b/Cartfile.resolved deleted file mode 100644 index 8850d21..0000000 --- a/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "hyperoslo/Sugar" "1.1.1" diff --git a/Compass.podspec b/Compass.podspec index 8ee99b6..2334e6b 100644 --- a/Compass.podspec +++ b/Compass.podspec @@ -13,7 +13,6 @@ Pod::Spec.new do |s| s.requires_arc = true - s.ios.source_files = 'Sources/{iOS,Shared}/**/*' - s.osx.source_files = 'Sources/{Mac,Shared}/**/*' - s.dependency 'Sugar' + s.source_files = 'Sources/**/*' + s.frameworks = 'Foundation' end diff --git a/Compass.xcodeproj/project.pbxproj b/Compass.xcodeproj/project.pbxproj index 9cbf4cc..cd7a1c6 100644 --- a/Compass.xcodeproj/project.pbxproj +++ b/Compass.xcodeproj/project.pbxproj @@ -7,19 +7,22 @@ objects = { /* Begin PBXBuildFile section */ - BD93BC731C4D0CB5006D2D11 /* TestRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD93BC721C4D0CB5006D2D11 /* TestRouter.swift */; }; - BDF7B4091C3FF40300576737 /* Compass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B4081C3FF40300576737 /* Compass.swift */; }; - BDF7B40A1C3FF40300576737 /* Compass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B4081C3FF40300576737 /* Compass.swift */; }; - BDF7B40C1C3FF40A00576737 /* Compass+Navigate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B40B1C3FF40A00576737 /* Compass+Navigate.swift */; }; - BDF7B40E1C3FF41500576737 /* Compass+Navigate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B40D1C3FF41500576737 /* Compass+Navigate.swift */; }; - BDF7B4101C3FF43F00576737 /* TestCompass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B40F1C3FF43F00576737 /* TestCompass.swift */; }; - BDF7B4111C3FF43F00576737 /* TestCompass.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF7B40F1C3FF43F00576737 /* TestCompass.swift */; }; - BDF7B4151C3FF51100576737 /* Sugar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDF7B4141C3FF51100576737 /* Sugar.framework */; }; - BDF7B4171C3FF51800576737 /* Sugar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDF7B4161C3FF51800576737 /* Sugar.framework */; }; - D20D8C771D0708A800807EB1 /* Shuffle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20D8C761D0708A800807EB1 /* Shuffle.swift */; }; - D20D8C781D0708A800807EB1 /* Shuffle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20D8C761D0708A800807EB1 /* Shuffle.swift */; }; - D5A2A7931C4CEB1C00B51356 /* Routable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A2A7921C4CEB1C00B51356 /* Routable.swift */; }; - D5A2A7971C4CEB7C00B51356 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A2A7961C4CEB7C00B51356 /* Router.swift */; }; + D5361FF41D6C7133003C3EE8 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FEF1D6C7133003C3EE8 /* Router.swift */; }; + D5361FF51D6C7133003C3EE8 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FEF1D6C7133003C3EE8 /* Router.swift */; }; + D5361FF81D6C7133003C3EE8 /* TypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF11D6C7133003C3EE8 /* TypeAlias.swift */; }; + D5361FF91D6C7133003C3EE8 /* TypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF11D6C7133003C3EE8 /* TypeAlias.swift */; }; + D5361FFA1D6C7133003C3EE8 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF21D6C7133003C3EE8 /* String+Extensions.swift */; }; + D5361FFB1D6C7133003C3EE8 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF21D6C7133003C3EE8 /* String+Extensions.swift */; }; + D5361FFC1D6C7133003C3EE8 /* Compass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF31D6C7133003C3EE8 /* Compass.swift */; }; + D5361FFD1D6C7133003C3EE8 /* Compass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5361FF31D6C7133003C3EE8 /* Compass.swift */; }; + D53620251D6C749A003C3EE8 /* CompassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536200F1D6C743A003C3EE8 /* CompassTests.swift */; }; + D53620261D6C749A003C3EE8 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53620101D6C743A003C3EE8 /* Helpers.swift */; }; + D53620271D6C749A003C3EE8 /* RouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53620111D6C743A003C3EE8 /* RouterTests.swift */; }; + D53620281D6C749B003C3EE8 /* CompassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536200F1D6C743A003C3EE8 /* CompassTests.swift */; }; + D53620291D6C749B003C3EE8 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53620101D6C743A003C3EE8 /* Helpers.swift */; }; + D536202A1D6C749B003C3EE8 /* RouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53620111D6C743A003C3EE8 /* RouterTests.swift */; }; + D536202C1D6C8532003C3EE8 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536202B1D6C8532003C3EE8 /* Location.swift */; }; + D536202D1D6C8532003C3EE8 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536202B1D6C8532003C3EE8 /* Location.swift */; }; D5B2E8AA1C3A780C00C0327D /* Compass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5B2E89F1C3A780C00C0327D /* Compass.framework */; }; D5C6294A1C3A7FAA007F7B7C /* Compass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5C629401C3A7FAA007F7B7C /* Compass.framework */; }; /* End PBXBuildFile section */ @@ -42,24 +45,22 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - BD93BC721C4D0CB5006D2D11 /* TestRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestRouter.swift; sourceTree = ""; }; - BDF7B4081C3FF40300576737 /* Compass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Compass.swift; sourceTree = ""; }; - BDF7B40B1C3FF40A00576737 /* Compass+Navigate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Compass+Navigate.swift"; sourceTree = ""; }; - BDF7B40D1C3FF41500576737 /* Compass+Navigate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Compass+Navigate.swift"; sourceTree = ""; }; - BDF7B40F1C3FF43F00576737 /* TestCompass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestCompass.swift; sourceTree = ""; }; - BDF7B4141C3FF51100576737 /* Sugar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sugar.framework; path = Carthage/Build/Mac/Sugar.framework; sourceTree = ""; }; - BDF7B4161C3FF51800576737 /* Sugar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sugar.framework; path = Carthage/Build/iOS/Sugar.framework; sourceTree = ""; }; - D20D8C761D0708A800807EB1 /* Shuffle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shuffle.swift; sourceTree = ""; }; - D5A2A7921C4CEB1C00B51356 /* Routable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Routable.swift; sourceTree = ""; }; - D5A2A7961C4CEB7C00B51356 /* Router.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; + D5361FEF1D6C7133003C3EE8 /* Router.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; + D5361FF11D6C7133003C3EE8 /* TypeAlias.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeAlias.swift; sourceTree = ""; }; + D5361FF21D6C7133003C3EE8 /* String+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; + D5361FF31D6C7133003C3EE8 /* Compass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Compass.swift; sourceTree = ""; }; + D536200F1D6C743A003C3EE8 /* CompassTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompassTests.swift; sourceTree = ""; }; + D53620101D6C743A003C3EE8 /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; + D53620111D6C743A003C3EE8 /* RouterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = ""; }; + D53620131D6C743A003C3EE8 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; + D53620141D6C743A003C3EE8 /* Info-Mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Mac.plist"; sourceTree = ""; }; + D53620151D6C743A003C3EE8 /* Info-Tests-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Tests-iOS.plist"; sourceTree = ""; }; + D53620161D6C743A003C3EE8 /* Info-Tests-Mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Tests-Mac.plist"; sourceTree = ""; }; + D536202B1D6C8532003C3EE8 /* Location.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = ""; }; D5B2E89F1C3A780C00C0327D /* Compass.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Compass.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D5B2E8A91C3A780C00C0327D /* Compass-iOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Compass-iOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; D5C629401C3A7FAA007F7B7C /* Compass.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Compass.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D5C629491C3A7FAA007F7B7C /* Compass-Mac-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Compass-Mac-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - D5C6298B1C3A8BBD007F7B7C /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; - D5C6298C1C3A8BBD007F7B7C /* Info-Mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Mac.plist"; sourceTree = ""; }; - D5C629901C3A8BDA007F7B7C /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; - D5C629911C3A8BDA007F7B7C /* Info-Mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Mac.plist"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,7 +68,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BDF7B4171C3FF51800576737 /* Sugar.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -83,7 +83,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BDF7B4151C3FF51100576737 /* Sugar.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -98,108 +97,66 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - D5B2E8951C3A780C00C0327D = { - isa = PBXGroup; - children = ( - BDF7B4161C3FF51800576737 /* Sugar.framework */, - BDF7B4141C3FF51100576737 /* Sugar.framework */, - D5C629691C3A809D007F7B7C /* Sources */, - D5C6295C1C3A800E007F7B7C /* Compass */, - D5C6298F1C3A8BDA007F7B7C /* CompassTests */, - D5B2E8A01C3A780C00C0327D /* Products */, - ); - sourceTree = ""; - }; - D5B2E8A01C3A780C00C0327D /* Products */ = { + D536200D1D6C743A003C3EE8 /* Tests */ = { isa = PBXGroup; children = ( - D5B2E89F1C3A780C00C0327D /* Compass.framework */, - D5B2E8A91C3A780C00C0327D /* Compass-iOS-Tests.xctest */, - D5C629401C3A7FAA007F7B7C /* Compass.framework */, - D5C629491C3A7FAA007F7B7C /* Compass-Mac-Tests.xctest */, + D536200E1D6C743A003C3EE8 /* Compass */, ); - name = Products; + path = Tests; sourceTree = ""; }; - D5C6295C1C3A800E007F7B7C /* Compass */ = { + D536200E1D6C743A003C3EE8 /* Compass */ = { isa = PBXGroup; children = ( - D5C6298B1C3A8BBD007F7B7C /* Info-iOS.plist */, - D5C6298C1C3A8BBD007F7B7C /* Info-Mac.plist */, + D536200F1D6C743A003C3EE8 /* CompassTests.swift */, + D53620101D6C743A003C3EE8 /* Helpers.swift */, + D53620111D6C743A003C3EE8 /* RouterTests.swift */, ); path = Compass; sourceTree = ""; }; - D5C629691C3A809D007F7B7C /* Sources */ = { + D53620121D6C743A003C3EE8 /* Project */ = { isa = PBXGroup; children = ( - D5C6296A1C3A809D007F7B7C /* iOS */, - D5C6296C1C3A809D007F7B7C /* Mac */, - D5C6296E1C3A809D007F7B7C /* Shared */, + D53620131D6C743A003C3EE8 /* Info-iOS.plist */, + D53620141D6C743A003C3EE8 /* Info-Mac.plist */, + D53620151D6C743A003C3EE8 /* Info-Tests-iOS.plist */, + D53620161D6C743A003C3EE8 /* Info-Tests-Mac.plist */, ); - path = Sources; + path = Project; sourceTree = ""; }; - D5C6296A1C3A809D007F7B7C /* iOS */ = { - isa = PBXGroup; - children = ( - D5A2A7921C4CEB1C00B51356 /* Routable.swift */, - BDF7B40D1C3FF41500576737 /* Compass+Navigate.swift */, - D5A2A7961C4CEB7C00B51356 /* Router.swift */, - ); - path = iOS; - sourceTree = ""; - }; - D5C6296C1C3A809D007F7B7C /* Mac */ = { - isa = PBXGroup; - children = ( - BDF7B40B1C3FF40A00576737 /* Compass+Navigate.swift */, - ); - path = Mac; - sourceTree = ""; - }; - D5C6296E1C3A809D007F7B7C /* Shared */ = { - isa = PBXGroup; - children = ( - BDF7B4081C3FF40300576737 /* Compass.swift */, - ); - path = Shared; - sourceTree = ""; - }; - D5C6298F1C3A8BDA007F7B7C /* CompassTests */ = { - isa = PBXGroup; - children = ( - D5C629901C3A8BDA007F7B7C /* Info-iOS.plist */, - D5C629911C3A8BDA007F7B7C /* Info-Mac.plist */, - D5C629921C3A8BDA007F7B7C /* iOS */, - D5C629941C3A8BDA007F7B7C /* Mac */, - D5C629961C3A8BDA007F7B7C /* Shared */, - ); - path = CompassTests; - sourceTree = ""; - }; - D5C629921C3A8BDA007F7B7C /* iOS */ = { + D5B2E8951C3A780C00C0327D = { isa = PBXGroup; children = ( - BD93BC721C4D0CB5006D2D11 /* TestRouter.swift */, + D53620121D6C743A003C3EE8 /* Project */, + D5C629691C3A809D007F7B7C /* Sources */, + D536200D1D6C743A003C3EE8 /* Tests */, + D5B2E8A01C3A780C00C0327D /* Products */, ); - path = iOS; sourceTree = ""; }; - D5C629941C3A8BDA007F7B7C /* Mac */ = { + D5B2E8A01C3A780C00C0327D /* Products */ = { isa = PBXGroup; children = ( + D5B2E89F1C3A780C00C0327D /* Compass.framework */, + D5B2E8A91C3A780C00C0327D /* Compass-iOS-Tests.xctest */, + D5C629401C3A7FAA007F7B7C /* Compass.framework */, + D5C629491C3A7FAA007F7B7C /* Compass-Mac-Tests.xctest */, ); - path = Mac; + name = Products; sourceTree = ""; }; - D5C629961C3A8BDA007F7B7C /* Shared */ = { + D5C629691C3A809D007F7B7C /* Sources */ = { isa = PBXGroup; children = ( - BDF7B40F1C3FF43F00576737 /* TestCompass.swift */, - D20D8C761D0708A800807EB1 /* Shuffle.swift */, + D5361FEF1D6C7133003C3EE8 /* Router.swift */, + D5361FF11D6C7133003C3EE8 /* TypeAlias.swift */, + D5361FF21D6C7133003C3EE8 /* String+Extensions.swift */, + D5361FF31D6C7133003C3EE8 /* Compass.swift */, + D536202B1D6C8532003C3EE8 /* Location.swift */, ); - path = Shared; + path = Sources; sourceTree = ""; }; /* End PBXGroup section */ @@ -247,7 +204,6 @@ D5B2E8A51C3A780C00C0327D /* Sources */, D5B2E8A61C3A780C00C0327D /* Frameworks */, D5B2E8A71C3A780C00C0327D /* Resources */, - D5C629731C3A86E3007F7B7C /* Copy frameworks with Carthage */, ); buildRules = ( ); @@ -284,7 +240,6 @@ D5C629451C3A7FAA007F7B7C /* Sources */, D5C629461C3A7FAA007F7B7C /* Frameworks */, D5C629471C3A7FAA007F7B7C /* Resources */, - D5C629741C3A8717007F7B7C /* Copy frameworks with Carthage */, ); buildRules = ( ); @@ -302,7 +257,7 @@ D5B2E8961C3A780C00C0327D /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0720; + LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Hyper Interaktiv AS"; TargetAttributes = { @@ -371,48 +326,16 @@ }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - D5C629731C3A86E3007F7B7C /* Copy frameworks with Carthage */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/Carthage/Build/iOS/Sugar.framework", - ); - name = "Copy frameworks with Carthage"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; - }; - D5C629741C3A8717007F7B7C /* Copy frameworks with Carthage */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/Carthage/Build/Mac/Sugar.framework", - ); - name = "Copy frameworks with Carthage"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ D5B2E89A1C3A780C00C0327D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D5A2A7971C4CEB7C00B51356 /* Router.swift in Sources */, - BDF7B4091C3FF40300576737 /* Compass.swift in Sources */, - D5A2A7931C4CEB1C00B51356 /* Routable.swift in Sources */, - BDF7B40E1C3FF41500576737 /* Compass+Navigate.swift in Sources */, + D5361FFC1D6C7133003C3EE8 /* Compass.swift in Sources */, + D5361FFA1D6C7133003C3EE8 /* String+Extensions.swift in Sources */, + D5361FF81D6C7133003C3EE8 /* TypeAlias.swift in Sources */, + D5361FF41D6C7133003C3EE8 /* Router.swift in Sources */, + D536202C1D6C8532003C3EE8 /* Location.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -420,9 +343,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BD93BC731C4D0CB5006D2D11 /* TestRouter.swift in Sources */, - D20D8C771D0708A800807EB1 /* Shuffle.swift in Sources */, - BDF7B4101C3FF43F00576737 /* TestCompass.swift in Sources */, + D53620251D6C749A003C3EE8 /* CompassTests.swift in Sources */, + D53620271D6C749A003C3EE8 /* RouterTests.swift in Sources */, + D53620261D6C749A003C3EE8 /* Helpers.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -430,8 +353,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BDF7B40A1C3FF40300576737 /* Compass.swift in Sources */, - BDF7B40C1C3FF40A00576737 /* Compass+Navigate.swift in Sources */, + D5361FFD1D6C7133003C3EE8 /* Compass.swift in Sources */, + D5361FFB1D6C7133003C3EE8 /* String+Extensions.swift in Sources */, + D5361FF91D6C7133003C3EE8 /* TypeAlias.swift in Sources */, + D5361FF51D6C7133003C3EE8 /* Router.swift in Sources */, + D536202D1D6C8532003C3EE8 /* Location.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -439,8 +365,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BDF7B4111C3FF43F00576737 /* TestCompass.swift in Sources */, - D20D8C781D0708A800807EB1 /* Shuffle.swift in Sources */, + D53620281D6C749B003C3EE8 /* CompassTests.swift in Sources */, + D536202A1D6C749B003C3EE8 /* RouterTests.swift in Sources */, + D53620291D6C749B003C3EE8 /* Helpers.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -559,11 +486,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = "$(SRCROOT)/Compass/Info-iOS.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -582,11 +506,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = "$(SRCROOT)/Compass/Info-iOS.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -600,11 +521,8 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = "$(SRCROOT)/CompassTests/Info-iOS.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Tests-iOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.CompassTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -616,11 +534,8 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - INFOPLIST_FILE = "$(SRCROOT)/CompassTests/Info-iOS.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Tests-iOS.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = no.hyper.CompassTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -637,12 +552,9 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = "$(SRCROOT)/Compass/Info-Mac.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Mac.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; @@ -664,12 +576,9 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; - INFOPLIST_FILE = "$(SRCROOT)/Compass/Info-Mac.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Mac.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; @@ -685,11 +594,8 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - INFOPLIST_FILE = "$(SRCROOT)/CompassTests/Info-Mac.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Tests-Mac.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Compass-MacTests"; @@ -703,11 +609,8 @@ buildSettings = { CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - INFOPLIST_FILE = "$(SRCROOT)/CompassTests/Info-Mac.plist"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-Tests-Mac.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.Compass-MacTests"; diff --git a/CompassTests/Shared/TestCompass.swift b/CompassTests/Shared/TestCompass.swift deleted file mode 100644 index f7546b6..0000000 --- a/CompassTests/Shared/TestCompass.swift +++ /dev/null @@ -1,297 +0,0 @@ -import Foundation -import XCTest -import Compass - -class TestCompass: XCTestCase { - - override func setUp() { - Compass.scheme = "compassTests" - Compass.routes = [ - "profile:{user}", - "profile:admin", - "login", - "callback", - "user:list:{userId}:{kind}", - "user:list", - "{appId}:user:list:{userId}:{kind}" - ].shuffle() - } - - func testScheme() { - XCTAssertEqual(Compass.scheme, "compassTests://") - } - - func testRoutes() { - XCTAssert(!Compass.routes.isEmpty) - XCTAssert(Compass.routes.count == 7) - } - - func testParseArguments() { - let expectation = self.expectationWithDescription("Parse arguments") - let url = NSURL(string: "compassTests://profile:testUser")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("profile:{user}", route) - XCTAssertEqual(arguments["user"], "testUser") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseFragments() { - let expectation = self.expectationWithDescription("Parse arguments") - let url = NSURL(string: "compassTests://profile:testUser")! - - Compass.parse(url, fragments: ["meta" : "foo"]) { route, arguments, fragments in - XCTAssertEqual("profile:{user}", route) - XCTAssertEqual(arguments["user"], "testUser") - XCTAssertEqual("foo" , fragments["meta"] as? String) - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRouteConcreateMatchCount() { - let expectation = self.expectationWithDescription("Parse route having concrete match count") - let url = NSURL(string: "compassTests://profile:admin")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("profile:admin", route) - XCTAssert(arguments.isEmpty) - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRouteWildcardMatchCount() { - let expectation = self.expectationWithDescription("Parse route having wildcard match count") - let url = NSURL(string: "compassTests://profile:jack")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("profile:{user}", route) - XCTAssertEqual(arguments["user"], "jack") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRouteSamePrefix() { - let expectation = self.expectationWithDescription("Parse route having same prefix") - let url = NSURL(string: "compassTests://user:list")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("user:list", route) - XCTAssert(arguments.isEmpty) - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseMultipleArguments() { - let expectation = self.expectationWithDescription("Parse multiple arguments") - let url = NSURL(string: "compassTests://user:list:1:admin")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("user:list:{userId}:{kind}", route) - XCTAssertEqual(arguments["userId"], "1") - XCTAssertEqual(arguments["kind"], "admin") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseMultipleArgumentsWithFirstWildcard() { - let expectation = self.expectationWithDescription("Parse multiple arguments with first wild card") - let url = NSURL(string: "compassTests://12:user:list:1:admin")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("{appId}:user:list:{userId}:{kind}", route) - XCTAssertEqual(arguments["appId"], "12") - XCTAssertEqual(arguments["userId"], "1") - XCTAssertEqual(arguments["kind"], "admin") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseWithoutArguments() { - let expectation = self.expectationWithDescription("Parse without arguments") - let url = NSURL(string: "compassTests://login")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual("login", route) - XCTAssert(arguments.isEmpty) - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithFragments() { - let expectation = self.expectationWithDescription("Parse URL with fragments") - let url = NSURL(string: "compassTests://callback/#access_token=IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithFragmentsAndGoogleOAuth2AccessToken() { - let expectation = self.expectationWithDescription("Parse URL with fragments and Google OAuth 2.0 access token format") - let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithFragmentsAndAlternativeAccessToken() { - let expectation = self.expectationWithDescription("Parse URL with fragments and alternative access token format") - let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithSlashQuery() { - let expectation = self.expectationWithDescription("Parse URL with slash query") - let url = NSURL(string: "compassTests://callback/?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithSlashQueryAndGoogleOAuth2AccessToken() { - let expectation = self.expectationWithDescription("Parse URL with slash query and Google OAuth 2.0 access token format") - let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithSlashQueryAndAlternativeAccessToken() { - let expectation = self.expectationWithDescription("Parse URL with slash query and alternative access token format") - let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithQuery() { - let expectation = self.expectationWithDescription("Parse URL with query") - let url = NSURL(string: "compassTests://callback?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithQueryAndGoogleOAuth2AccessToken() { - let expectation = self.expectationWithDescription("Parse URL with query and Google OAuth 2.0 access token format") - let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } - - func testParseRegularURLWithQueryAndAlternativeAccessToken() { - let expectation = self.expectationWithDescription("Parse URL with query and alternative access token format") - let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! - - Compass.parse(url) { route, arguments, _ in - XCTAssertEqual(route, "callback") - XCTAssertEqual(arguments.count, 3) - XCTAssertEqual(arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") - XCTAssertEqual(arguments["expires_in"], "3600") - XCTAssertEqual(arguments["token_type"], "Bearer") - - expectation.fulfill() - } - - self.waitForExpectationsWithTimeout(4.0, handler:nil) - } -} diff --git a/CompassTests/iOS/TestRouter.swift b/CompassTests/iOS/TestRouter.swift deleted file mode 100644 index fdbc347..0000000 --- a/CompassTests/iOS/TestRouter.swift +++ /dev/null @@ -1,37 +0,0 @@ -import Foundation -import XCTest -import Compass - -class TestRoute: Routable { - - var resolved = false - - func resolve(arguments: [String: String], fragments: [String : AnyObject] = [:], currentController controller: UIViewController) { - resolved = true - } -} - -class TestRouter: XCTestCase { - - var router: Router! - var controller = UIViewController() - var route: TestRoute! - - override func setUp() { - router = Router() - route = TestRoute() - } - - func testNavigateIfRouteRegistered() { - router.routes["test"] = route - router.navigate("test", arguments: [:], from: controller) - - XCTAssertTrue(route.resolved) - } - - func testNavigateIfRouteNotRegistered() { - router.navigate("test", arguments: [:], from: controller) - - XCTAssertFalse(route.resolved) - } -} diff --git a/Compass/Info-Mac.plist b/Project/Info-Mac.plist similarity index 100% rename from Compass/Info-Mac.plist rename to Project/Info-Mac.plist diff --git a/CompassTests/Info-Mac.plist b/Project/Info-Tests-Mac.plist similarity index 100% rename from CompassTests/Info-Mac.plist rename to Project/Info-Tests-Mac.plist diff --git a/CompassTests/Info-iOS.plist b/Project/Info-Tests-iOS.plist similarity index 100% rename from CompassTests/Info-iOS.plist rename to Project/Info-Tests-iOS.plist diff --git a/Compass/Info-iOS.plist b/Project/Info-iOS.plist similarity index 100% rename from Compass/Info-iOS.plist rename to Project/Info-iOS.plist diff --git a/README.md b/README.md index c31e00f..631804a 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ First you need to register a URL scheme for your application #### Step 2 Now you need to configure Compass to use that URL scheme, a good place to do this is in your `AppDelegate` + ```swift func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { @@ -33,6 +34,7 @@ func application(application: UIApplication, ``` #### Step 3 Configure your application routes + ```swift func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { @@ -43,25 +45,30 @@ func application(application: UIApplication, ``` #### Step 4 Set up your application to respond to the URLs, this can be done in the `AppDelegate` but its up to you to find a more suitable place for it depending on the size of your implementation. + ```swift func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { - return Compass.parse(url) { route, arguments in - switch route { - case "profile:{username}": - let profileController = profileController(title: arguments["{username}"]) - self.navigationController?.pushViewController(profileController, - animated: true) - case "login:{username}": - let loginController = LoginController(title: arguments["{username}"]) - self.navigationController?.pushViewController(loginController, - animated: true) - case "logout": - logout() - default: break - } + guard let location = Compass.parse(url) else { + return false } + + let arguments = location.arguments + + switch location.path { + case "profile:{username}": + let profileController = profileController(title: arguments["{username}"]) + self.navigationController?.pushViewController(profileController, animated: true) + case "login:{username}": + let loginController = LoginController(title: arguments["{username}"]) + self.navigationController?.pushViewController(loginController, animated: true) + case "logout": + logout() + default: break + } + + return true } ``` @@ -79,8 +86,9 @@ route handling code and avoid huge `switch` cases. in one place: ```swift struct ProfileRoute: Routable { - func resolve(arguments: [String: String], currentController: UIViewController) { - guard let username = arguments["username"] else { return } + + func navigate(to location: Location, from currentController: UIViewController) { + guard let username = location.arguments["username"] else { return } let profileController = profileController(title: username) currentController.navigationController?.pushViewController(profileController, animated: true) @@ -103,10 +111,13 @@ router.routes = [ func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { - return Compass.parse(url) { route, arguments in - router.navigate(route, arguments: arguments, - navigationController: navigationController) + guard let location = Compass.parse(url) else { + return false } + + router.navigate(to: location, from: navigationController) + + return true } ``` @@ -114,28 +125,25 @@ func application(app: UIApplication, You could have multiple handlers depending on if a user is logged in or not. ```swift struct NavigationHandler { - static func routePreLogin(route: String, arguments: [String: String], - navigationController: UINavigationController) { - switch route { - case "forgotpassword:{username}": - let forgotPasswordController = ForgotPasswordController(title: arguments["{username}"]) - navigationController?.pushViewController(loginController, - animated: true) - default: break - } + + static func routePreLogin(location: Location, navigationController: UINavigationController) { + switch location.path { + case "forgotpassword:{username}": + let controller = ForgotPasswordController(title: location.arguments["{username}"]) + navigationController?.pushViewController(controller, animated: true) + default: break + } } - static func routePostLogin(route: String, arguments: [String: String], - navigationController: UINavigationController) { - switch route { - case "profile:{username}": - let profileController = ProfileController(title: arguments["{username}"]) - navigationController?.pushViewController(profileController, - animated: true) - case "logout": - AppDelegate.logout() - default: break - } + static func routePostLogin(location: Location, navigationController: UINavigationController) { + switch location.path { + case "profile:{username}": + let controller = ProfileController(title: location.arguments["{username}"]) + navigationController?.pushViewController(controller, animated: true) + case "logout": + AppDelegate.logout() + default: break + } } } ``` @@ -154,7 +162,7 @@ routerPostLogin.routes = [ ] let router = isLoggedIn ? routerPostLogin : routerPreLogin -router.navigate(route, arguments: arguments, navigationController: navigationController) +router.navigate(to: location, from: navigationController) ``` ##### Tip 3. Global function diff --git a/Sources/Compass.swift b/Sources/Compass.swift new file mode 100644 index 0000000..256973d --- /dev/null +++ b/Sources/Compass.swift @@ -0,0 +1,101 @@ +import Foundation + +public struct Compass { + + typealias Result = ( + route: String, + arguments: [String: String], + concreteMatchCount: Int, + wildcardMatchCount: Int) + + private static var internalScheme = "" + public static var delimiter: String = ":" + + public static var scheme: String { + set { Compass.internalScheme = newValue } + get { return "\(Compass.internalScheme)://" } + } + + public static var routes = [String]() + + public static func parse(url: NSURL, fragments: [String : AnyObject] = [:]) -> Location? { + let path = url.absoluteString.substringFromIndex(scheme.endIndex) + + guard !(path.containsString("?") || path.containsString("#")) else { + return parseAsURL(url, fragments: fragments) + } + + let results: [Result] = routes.flatMap { + return findMatch($0, pathString: path) + }.sort { (r1: Result, r2: Result) in + if r1.concreteMatchCount == r2.concreteMatchCount { + return r1.wildcardMatchCount > r2.wildcardMatchCount + } + + return r1.concreteMatchCount > r2.concreteMatchCount + } + + if let result = results.first { + return Location(path: result.route, arguments: result.arguments, fragments: fragments) + } + + return nil + } + + static func parseAsURL(url: NSURL, fragments: [String : AnyObject] = [:]) -> Location? { + guard let route = url.host else { return nil } + + let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) + var arguments = [String : String]() + + urlComponents?.queryItems?.forEach { queryItem in + arguments[queryItem.name] = queryItem.value + } + + if let fragment = urlComponents?.fragment { + arguments = fragment.queryParameters() + } + + return Location(path: route, arguments: arguments, fragments: fragments) + } + + static func findMatch(routeString: String, pathString: String) -> Result? { + let routes = routeString.split(delimiter) + let paths = pathString.split(delimiter) + + guard routes.count == paths.count else { return nil } + + var arguments: [String: String] = [:] + var concreteMatchCount = 0 + var wildcardMatchCount = 0 + + for (route, path) in zip(routes, paths) { + if route.hasPrefix("{") { + let key = route.replace("{", with: "").replace("}", with: "") + arguments[key] = path + + wildcardMatchCount += 1 + continue + } + + if route == path { + concreteMatchCount += 1 + } else { + return nil + } + } + + return (route: routeString, + arguments: arguments, + concreteMatchCount: concreteMatchCount, + wildcardMatchCount: wildcardMatchCount) + } +} + +extension Compass { + + public static func navigate(urn: String, scheme: String = Compass.scheme) { + guard let url = NSURL(string: "\(scheme)\(urn)") else { return } + openURL(url) + } +} diff --git a/Sources/Location.swift b/Sources/Location.swift new file mode 100644 index 0000000..5f26382 --- /dev/null +++ b/Sources/Location.swift @@ -0,0 +1,16 @@ +public struct Location { + + public let path: String + public let arguments: [String: String] + public let fragments: [String: AnyObject] + + public var scheme: String { + return Compass.scheme + } + + public init(path: String, arguments: [String: String] = [:], fragments: [String: AnyObject] = [:]) { + self.path = path + self.arguments = arguments + self.fragments = fragments + } +} diff --git a/Sources/Mac/Compass+Navigate.swift b/Sources/Mac/Compass+Navigate.swift deleted file mode 100644 index 87b21fa..0000000 --- a/Sources/Mac/Compass+Navigate.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Cocoa - -extension Compass { - - public static func navigate(urn: String, scheme: String = Compass.scheme) { - guard let url = NSURL(string: "\(scheme)\(urn)") else { return } - - NSWorkspace.sharedWorkspace().openURL(url) - } -} diff --git a/Sources/Router.swift b/Sources/Router.swift new file mode 100644 index 0000000..ac05da5 --- /dev/null +++ b/Sources/Router.swift @@ -0,0 +1,16 @@ +public protocol Routable { + + func navigate(to location: Location, from currentController: Controller) +} + +public struct Router: Routable { + + public var routes = [String: Routable]() + + public init() {} + + public func navigate(to location: Location, from currentController: Controller) { + guard let route = routes[location.path] else { return } + route.navigate(to: location, from: currentController) + } +} diff --git a/Sources/Shared/Compass.swift b/Sources/Shared/Compass.swift deleted file mode 100644 index c2bf090..0000000 --- a/Sources/Shared/Compass.swift +++ /dev/null @@ -1,120 +0,0 @@ -import Foundation -import Sugar - -public struct Compass { - - typealias Result = (route: String, arguments: [String: String], - concreteMatchCount: Int, wildcardMatchCount: Int) - - private static var internalScheme = "" - - public static var delimiter: String = ":" - - public static var scheme: String { - set { Compass.internalScheme = newValue } - get { return "\(Compass.internalScheme)://" } - } - - public static var routes = [String]() - - public typealias ParseCompletion = (route: String, arguments: [String : String], fragments: [String : AnyObject]) -> Void - - public static func parse(url: NSURL, fragments: [String : AnyObject] = [:], completion: ParseCompletion) -> Bool { - - let path = url.absoluteString.substringFromIndex(scheme.endIndex) - - guard !(path.containsString("?") || path.containsString("#")) - else { return parseAsURL(url, completion: completion) } - - let results: [Result] = routes.flatMap { - return findMatch($0, pathString: path) - }.sort { (r1: Result, r2: Result) in - if r1.concreteMatchCount == r2.concreteMatchCount { - return r1.wildcardMatchCount > r2.wildcardMatchCount - } - - return r1.concreteMatchCount > r2.concreteMatchCount - } - - if let result = results.first { - completion(route: result.route, arguments: result.arguments, fragments: fragments) - return true - } - - return false - } - - static func parseAsURL(url: NSURL, completion: ParseCompletion) -> Bool { - guard let route = url.host else { return false } - - let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) - - var arguments = [String : String]() - - urlComponents?.queryItems?.forEach { queryItem in - arguments[queryItem.name] = queryItem.value - } - - if let fragment = urlComponents?.fragment { - arguments = fragment.queryParameters() - } - - completion(route: route, arguments: arguments, fragments: [:]) - - return true - } - - static func findMatch(routeString: String, pathString: String) - -> Result? { - - let routes = routeString.split(delimiter) - let paths = pathString.split(delimiter) - - guard routes.count == paths.count else { return nil } - - var arguments: [String: String] = [:] - var concreteMatchCount = 0 - var wildcardMatchCount = 0 - - for (route, path) in zip(routes, paths) { - if route.hasPrefix("{") { - let key = route.replace("{", with: "").replace("}", with: "") - arguments[key] = path - - wildcardMatchCount += 1 - continue - } - - if route == path { - concreteMatchCount += 1 - } else { - return nil - } - } - - return (route: routeString, arguments: arguments, - concreteMatchCount: concreteMatchCount, wildcardMatchCount: wildcardMatchCount) - } -} - -private extension String { - - func queryParameters() -> [String: String] { - var parameters = [String: String]() - - let separatorCharacters = NSCharacterSet(charactersInString: "&;") - self.componentsSeparatedByCharactersInSet(separatorCharacters).forEach { (pair) in - - if let equalSeparator = pair.rangeOfString("=") { - let name = pair.substringToIndex(equalSeparator.startIndex) - let value = pair.substringFromIndex(equalSeparator.startIndex.advancedBy(1)) - let cleaned = value.stringByRemovingPercentEncoding ?? value - - parameters[name] = cleaned - } - } - - return parameters - } - -} diff --git a/Sources/String+Extensions.swift b/Sources/String+Extensions.swift new file mode 100644 index 0000000..eacc3e9 --- /dev/null +++ b/Sources/String+Extensions.swift @@ -0,0 +1,31 @@ +import Foundation + +extension String { + + func split(delimiter: String) -> [String] { + let components = componentsSeparatedByString(delimiter) + return components != [""] ? components : [] + } + + func replace(string: String, with withString: String) -> String { + return stringByReplacingOccurrencesOfString(string, withString: withString) + } + + func queryParameters() -> [String: String] { + var parameters = [String: String]() + + let separatorCharacters = NSCharacterSet(charactersInString: "&;") + self.componentsSeparatedByCharactersInSet(separatorCharacters).forEach { (pair) in + + if let equalSeparator = pair.rangeOfString("=") { + let name = pair.substringToIndex(equalSeparator.startIndex) + let value = pair.substringFromIndex(equalSeparator.startIndex.advancedBy(1)) + let cleaned = value.stringByRemovingPercentEncoding ?? value + + parameters[name] = cleaned + } + } + + return parameters + } +} diff --git a/Sources/TypeAlias.swift b/Sources/TypeAlias.swift new file mode 100644 index 0000000..2fcabf7 --- /dev/null +++ b/Sources/TypeAlias.swift @@ -0,0 +1,19 @@ +#if os(OSX) + import Cocoa +#else + import UIKit +#endif + +#if os(OSX) + public typealias Controller = NSViewController + + func openURL(URL: NSURL) { + NSWorkspace.sharedWorkspace().openURL(URL) + } +#else + public typealias Controller = UIViewController + + func openURL(URL: NSURL) { + UIApplication.sharedApplication().openURL(URL) + } +#endif diff --git a/Sources/iOS/Compass+Navigate.swift b/Sources/iOS/Compass+Navigate.swift deleted file mode 100644 index 11a829e..0000000 --- a/Sources/iOS/Compass+Navigate.swift +++ /dev/null @@ -1,10 +0,0 @@ -import UIKit - -extension Compass { - - public static func navigate(urn: String, scheme: String = Compass.scheme) { - guard let url = NSURL(string: "\(scheme)\(urn)") else { return } - - UIApplication.sharedApplication().openURL(url) - } -} diff --git a/Sources/iOS/Routable.swift b/Sources/iOS/Routable.swift deleted file mode 100644 index 76a8bc0..0000000 --- a/Sources/iOS/Routable.swift +++ /dev/null @@ -1,6 +0,0 @@ -import UIKit - -public protocol Routable { - - func resolve(arguments: [String: String], fragments: [String : AnyObject], currentController: UIViewController) -} diff --git a/Sources/iOS/Router.swift b/Sources/iOS/Router.swift deleted file mode 100644 index b537b93..0000000 --- a/Sources/iOS/Router.swift +++ /dev/null @@ -1,14 +0,0 @@ -import UIKit - -public struct Router { - - public var routes = [String: Routable]() - - public init() {} - - public func navigate(route: String, arguments: [String: String], fragments: [String : AnyObject] = [:], from controller: UIViewController) { - guard let route = routes[route] else { return } - - route.resolve(arguments, fragments: fragments, currentController: controller) - } -} diff --git a/Tests/Compass/CompassTests.swift b/Tests/Compass/CompassTests.swift new file mode 100644 index 0000000..d1deab3 --- /dev/null +++ b/Tests/Compass/CompassTests.swift @@ -0,0 +1,263 @@ +import Foundation +import XCTest +import Compass + +class CompassTests: XCTestCase { + + override func setUp() { + Compass.scheme = "compassTests" + Compass.routes = [ + "profile:{user}", + "profile:admin", + "login", + "callback", + "user:list:{userId}:{kind}", + "user:list", + "{appId}:user:list:{userId}:{kind}" + ].shuffle() + } + + func testScheme() { + XCTAssertEqual(Compass.scheme, "compassTests://") + } + + func testRoutes() { + XCTAssert(!Compass.routes.isEmpty) + XCTAssert(Compass.routes.count == 7) + } + + func testParseArguments() { + let url = NSURL(string: "compassTests://profile:testUser")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("profile:{user}", location.path) + XCTAssertEqual(location.arguments["user"], "testUser") + } + + func testParseFragments() { + let url = NSURL(string: "compassTests://profile:testUser")! + + guard let location = Compass.parse(url, fragments: ["meta" : "foo"]) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("profile:{user}", location.path) + XCTAssertEqual(location.arguments["user"], "testUser") + XCTAssertEqual("foo" , location.fragments["meta"] as? String) + } + + func testParseRouteConcreateMatchCount() { + let url = NSURL(string: "compassTests://profile:admin")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("profile:admin", location.path) + XCTAssert(location.arguments.isEmpty) + } + + func testParseRouteWildcardMatchCount() { + let url = NSURL(string: "compassTests://profile:jack")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("profile:{user}", location.path) + XCTAssertEqual(location.arguments["user"], "jack") + } + + func testParseRouteSamePrefix() { + let url = NSURL(string: "compassTests://user:list")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("user:list", location.path) + XCTAssert(location.arguments.isEmpty) + } + + func testParseMultipleArguments() { + let url = NSURL(string: "compassTests://user:list:1:admin")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("user:list:{userId}:{kind}", location.path) + XCTAssertEqual(location.arguments["userId"], "1") + XCTAssertEqual(location.arguments["kind"], "admin") + } + + func testParseMultipleArgumentsWithFirstWildcard() { + let url = NSURL(string: "compassTests://12:user:list:1:admin")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("{appId}:user:list:{userId}:{kind}", location.path) + XCTAssertEqual(location.arguments["appId"], "12") + XCTAssertEqual(location.arguments["userId"], "1") + XCTAssertEqual(location.arguments["kind"], "admin") + } + + func testParseWithoutArguments() { + let url = NSURL(string: "compassTests://login")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual("login", location.path) + XCTAssert(location.arguments.isEmpty) + } + + func testParseRegularURLWithFragments() { + let url = NSURL(string: "compassTests://callback/#access_token=IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "IjvcgrkQk1p7TyJxKa26rzM1wBMFZW6XoHK4t5Gkt1xQLTN8l7ppR0H3EZXpoP0uLAN49oCDqTHsvnEV") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithFragmentsAndGoogleOAuth2AccessToken() { + let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithFragmentsAndAlternativeAccessToken() { + let url = NSURL(string: "compassTests://callback/#access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithSlashQuery() { + let url = NSURL(string: "compassTests://callback/?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithSlashQueryAndGoogleOAuth2AccessToken() { + let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithSlashQueryAndAlternativeAccessToken() { + let url = NSURL(string: "compassTests://callback/?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithQuery() { + let url = NSURL(string: "compassTests://callback?access_token=Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "Yo0OMrVZbRWNmgA6BT99hyuTUTNRGvqEEAQyeN1eslclzhFD0M8AidB4Z7Vs2NU8WoSNW0vYb961O38l") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithQueryAndGoogleOAuth2AccessToken() { + let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } + + func testParseRegularURLWithQueryAndAlternativeAccessToken() { + let url = NSURL(string: "compassTests://callback?access_token=ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=&token_type=Bearer&expires_in=3600")! + + guard let location = Compass.parse(url) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.path, "callback") + XCTAssertEqual(location.arguments.count, 3) + XCTAssertEqual(location.arguments["access_token"], "ya29.Ci8nA1pNVMFffHkS5-sXooNGvTB9q8QPtoM56sWpipRyjhwwEiKyZxvRQTR8saqWzQ=") + XCTAssertEqual(location.arguments["expires_in"], "3600") + XCTAssertEqual(location.arguments["token_type"], "Bearer") + } +} diff --git a/CompassTests/Shared/Shuffle.swift b/Tests/Compass/Helpers.swift similarity index 75% rename from CompassTests/Shared/Shuffle.swift rename to Tests/Compass/Helpers.swift index d6178fd..2709968 100644 --- a/CompassTests/Shared/Shuffle.swift +++ b/Tests/Compass/Helpers.swift @@ -1,4 +1,18 @@ import Foundation +@testable import Compass + +// MARK: - Routes + +class TestRoute: Routable { + + var resolved = false + + func navigate(to location: Location, from currentController: Controller) { + resolved = true + } +} + +// MARK: - Shuffle extension CollectionType { /// Return a copy of `self` with its elements shuffled diff --git a/Tests/Compass/RouterTests.swift b/Tests/Compass/RouterTests.swift new file mode 100644 index 0000000..a14dd15 --- /dev/null +++ b/Tests/Compass/RouterTests.swift @@ -0,0 +1,28 @@ +import Foundation +import XCTest +@testable import Compass + +class RouterTests: XCTestCase { + + var router: Router! + var controller = Controller() + var route: TestRoute! + + override func setUp() { + router = Router() + route = TestRoute() + } + + func testNavigateIfRouteRegistered() { + router.routes["test"] = route + router.navigate(to: Location(path: "test"), from: controller) + + XCTAssertTrue(route.resolved) + } + + func testNavigateIfRouteNotRegistered() { + router.navigate(to: Location(path: "test"), from: controller) + + XCTAssertFalse(route.resolved) + } +} diff --git a/swiftlint.sh b/swiftlint.sh new file mode 100755 index 0000000..04d63ef --- /dev/null +++ b/swiftlint.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Installs the SwiftLint package. + +set -e + +SWIFTLINT_SOURCE_URL="https://github.com/realm/SwiftLint.git" +SWIFTLINT_SOURCE_PATH="/tmp/SwiftLint" +SWIFTLINT_PKG_PATH="/tmp/SwiftLint.pkg" +SWIFTLINT_PKG_URL="https://github.com/realm/SwiftLint/releases/download/0.11.1/SwiftLint.pkg" + +wget --output-document=$SWIFTLINT_PKG_PATH $SWIFTLINT_PKG_URL + +if [ -f $SWIFTLINT_PKG_PATH ]; then + echo "Installing SwiftLint..." + sudo installer -pkg $SWIFTLINT_PKG_PATH -target / +else + echo "Failed to install SwiftLint. Compiling from source..." && + git clone $SWIFTLINT_SOURCE_URL $SWIFTLINT_SOURCE_PATH && + cd $SWIFTLINT_SOURCE_PATH && + git submodule update --init --recursive && + sudo make install +fi