├── .gitignore ├── Kagee.podspec ├── Kagee.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── Kagee.xcscheme ├── Kagee.xcworkspace └── contents.xcworkspacedata ├── Kagee ├── Body.swift ├── Enums.swift ├── Info.plist ├── Mock.swift ├── MockPool.swift ├── MockProtocol.swift └── URLConvertible.swift ├── KageeTests ├── AlamofireTests.swift ├── Info.plist ├── KageeTests.swift └── Resources │ └── test.json ├── LICENSE ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # Swift Package Manager 31 | # 32 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 33 | # Packages/ 34 | .build/ 35 | 36 | # CocoaPods 37 | # 38 | # We recommend against adding the Pods directory to your .gitignore. However 39 | # you should judge for yourself, the pros and cons are mentioned at: 40 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 41 | 42 | Pods/ 43 | 44 | # Carthage 45 | # 46 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 47 | # Carthage/Checkouts 48 | 49 | Carthage/Build 50 | 51 | # fastlane 52 | # 53 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 54 | # screenshots whenever they are needed. 55 | # For more information about the recommended setup visit: 56 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 57 | 58 | fastlane/report.xml 59 | fastlane/screenshots 60 | 61 | -------------------------------------------------------------------------------- /Kagee.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Kagee' 3 | s.version = '0.1.0' 4 | s.license = 'MIT' 5 | s.homepage = 'https://github.com/yukiasai/' 6 | s.summary = 'HTTP mocking library written in Swift.' 7 | s.authors = { 'yukiasai' => 'yukiasai@gmail.com' } 8 | s.source = { :git => 'https://github.com/yukiasai/Kagee.git', :tag => s.version } 9 | 10 | s.ios.deployment_target = '8.0' 11 | 12 | s.source_files = 'Kagee/*.swift' 13 | end 14 | 15 | -------------------------------------------------------------------------------- /Kagee.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1EFC81500C6BDEB56F276DB4 /* Pods_KageeTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB8375559D6CC1107902D19B /* Pods_KageeTests.framework */; }; 11 | 46D632F51C5F400A005CFFF0 /* Body.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632E81C5F400A005CFFF0 /* Body.swift */; }; 12 | 46D632F71C5F400A005CFFF0 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 46D632EA1C5F400A005CFFF0 /* Info.plist */; }; 13 | 46D632F81C5F400A005CFFF0 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EB1C5F400A005CFFF0 /* Mock.swift */; }; 14 | 46D632F91C5F400A005CFFF0 /* MockPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EC1C5F400A005CFFF0 /* MockPool.swift */; }; 15 | 46D632FA1C5F400A005CFFF0 /* MockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632ED1C5F400A005CFFF0 /* MockProtocol.swift */; }; 16 | 46D632FB1C5F400A005CFFF0 /* Enums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EE1C5F400A005CFFF0 /* Enums.swift */; }; 17 | 46D632FC1C5F400A005CFFF0 /* URLConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EF1C5F400A005CFFF0 /* URLConvertible.swift */; }; 18 | 46D632FD1C5F400A005CFFF0 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 46D632F11C5F400A005CFFF0 /* Info.plist */; }; 19 | 46D633001C5F4011005CFFF0 /* KageeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632F21C5F400A005CFFF0 /* KageeTests.swift */; }; 20 | 46D633011C5F4015005CFFF0 /* Body.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632E81C5F400A005CFFF0 /* Body.swift */; }; 21 | 46D633041C5F4015005CFFF0 /* Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EB1C5F400A005CFFF0 /* Mock.swift */; }; 22 | 46D633051C5F4015005CFFF0 /* MockPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EC1C5F400A005CFFF0 /* MockPool.swift */; }; 23 | 46D633061C5F4015005CFFF0 /* MockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632ED1C5F400A005CFFF0 /* MockProtocol.swift */; }; 24 | 46D633071C5F4015005CFFF0 /* Enums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EE1C5F400A005CFFF0 /* Enums.swift */; }; 25 | 46D633081C5F4015005CFFF0 /* URLConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D632EF1C5F400A005CFFF0 /* URLConvertible.swift */; }; 26 | 46D633091C5F401E005CFFF0 /* test.json in Resources */ = {isa = PBXBuildFile; fileRef = 46D632F41C5F400A005CFFF0 /* test.json */; }; 27 | 46D6330B1C5F4CC4005CFFF0 /* AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D6330A1C5F4CC4005CFFF0 /* AlamofireTests.swift */; }; 28 | B6E9410D1C52816A00E853C0 /* Kagee.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6E941021C52816A00E853C0 /* Kagee.framework */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | B6E9410E1C52816A00E853C0 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = B6E940F91C52816A00E853C0 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = B6E941011C52816A00E853C0; 37 | remoteInfo = Mockin; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 46D632E81C5F400A005CFFF0 /* Body.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Body.swift; sourceTree = ""; }; 43 | 46D632EA1C5F400A005CFFF0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | 46D632EB1C5F400A005CFFF0 /* Mock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mock.swift; sourceTree = ""; }; 45 | 46D632EC1C5F400A005CFFF0 /* MockPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockPool.swift; sourceTree = ""; }; 46 | 46D632ED1C5F400A005CFFF0 /* MockProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockProtocol.swift; sourceTree = ""; }; 47 | 46D632EE1C5F400A005CFFF0 /* Enums.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Enums.swift; sourceTree = ""; }; 48 | 46D632EF1C5F400A005CFFF0 /* URLConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLConvertible.swift; sourceTree = ""; }; 49 | 46D632F11C5F400A005CFFF0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | 46D632F21C5F400A005CFFF0 /* KageeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KageeTests.swift; sourceTree = ""; }; 51 | 46D632F41C5F400A005CFFF0 /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = ""; }; 52 | 46D6330A1C5F4CC4005CFFF0 /* AlamofireTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlamofireTests.swift; sourceTree = ""; }; 53 | 5A2E58BC6397F200014FAACA /* Pods-KageeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KageeTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-KageeTests/Pods-KageeTests.debug.xcconfig"; sourceTree = ""; }; 54 | B3CDC0350037667BF37AE0C4 /* Pods-KageeTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KageeTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-KageeTests/Pods-KageeTests.release.xcconfig"; sourceTree = ""; }; 55 | B6E941021C52816A00E853C0 /* Kagee.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kagee.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | B6E9410C1C52816A00E853C0 /* Kagee.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Kagee.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | CB8375559D6CC1107902D19B /* Pods_KageeTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_KageeTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | B6E940FE1C52816A00E853C0 /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | B6E941091C52816A00E853C0 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | B6E9410D1C52816A00E853C0 /* Kagee.framework in Frameworks */, 73 | 1EFC81500C6BDEB56F276DB4 /* Pods_KageeTests.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 46D632E71C5F400A005CFFF0 /* Kagee */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 46D632EB1C5F400A005CFFF0 /* Mock.swift */, 84 | 46D632EC1C5F400A005CFFF0 /* MockPool.swift */, 85 | 46D632ED1C5F400A005CFFF0 /* MockProtocol.swift */, 86 | 46D632E81C5F400A005CFFF0 /* Body.swift */, 87 | 46D632EE1C5F400A005CFFF0 /* Enums.swift */, 88 | 46D632EF1C5F400A005CFFF0 /* URLConvertible.swift */, 89 | 46D632EA1C5F400A005CFFF0 /* Info.plist */, 90 | ); 91 | path = Kagee; 92 | sourceTree = ""; 93 | }; 94 | 46D632F01C5F400A005CFFF0 /* KageeTests */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 46D632F11C5F400A005CFFF0 /* Info.plist */, 98 | 46D632F21C5F400A005CFFF0 /* KageeTests.swift */, 99 | 46D6330A1C5F4CC4005CFFF0 /* AlamofireTests.swift */, 100 | 46D632F31C5F400A005CFFF0 /* Resources */, 101 | ); 102 | path = KageeTests; 103 | sourceTree = ""; 104 | }; 105 | 46D632F31C5F400A005CFFF0 /* Resources */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 46D632F41C5F400A005CFFF0 /* test.json */, 109 | ); 110 | path = Resources; 111 | sourceTree = ""; 112 | }; 113 | B6E940F81C52816A00E853C0 = { 114 | isa = PBXGroup; 115 | children = ( 116 | 46D632E71C5F400A005CFFF0 /* Kagee */, 117 | 46D632F01C5F400A005CFFF0 /* KageeTests */, 118 | B6E941031C52816A00E853C0 /* Products */, 119 | EE795DDE59AD7B4202E5A483 /* Pods */, 120 | D5151238F3E09C2FE503094C /* Frameworks */, 121 | ); 122 | sourceTree = ""; 123 | }; 124 | B6E941031C52816A00E853C0 /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | B6E941021C52816A00E853C0 /* Kagee.framework */, 128 | B6E9410C1C52816A00E853C0 /* Kagee.xctest */, 129 | ); 130 | name = Products; 131 | sourceTree = ""; 132 | }; 133 | D5151238F3E09C2FE503094C /* Frameworks */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | CB8375559D6CC1107902D19B /* Pods_KageeTests.framework */, 137 | ); 138 | name = Frameworks; 139 | sourceTree = ""; 140 | }; 141 | EE795DDE59AD7B4202E5A483 /* Pods */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 5A2E58BC6397F200014FAACA /* Pods-KageeTests.debug.xcconfig */, 145 | B3CDC0350037667BF37AE0C4 /* Pods-KageeTests.release.xcconfig */, 146 | ); 147 | name = Pods; 148 | sourceTree = ""; 149 | }; 150 | /* End PBXGroup section */ 151 | 152 | /* Begin PBXHeadersBuildPhase section */ 153 | B6E940FF1C52816A00E853C0 /* Headers */ = { 154 | isa = PBXHeadersBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXHeadersBuildPhase section */ 161 | 162 | /* Begin PBXNativeTarget section */ 163 | B6E941011C52816A00E853C0 /* Kagee */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = B6E941161C52816A00E853C0 /* Build configuration list for PBXNativeTarget "Kagee" */; 166 | buildPhases = ( 167 | B6E940FD1C52816A00E853C0 /* Sources */, 168 | B6E940FE1C52816A00E853C0 /* Frameworks */, 169 | B6E940FF1C52816A00E853C0 /* Headers */, 170 | B6E941001C52816A00E853C0 /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = Kagee; 177 | productName = Mockin; 178 | productReference = B6E941021C52816A00E853C0 /* Kagee.framework */; 179 | productType = "com.apple.product-type.framework"; 180 | }; 181 | B6E9410B1C52816A00E853C0 /* KageeTests */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = B6E941191C52816A00E853C0 /* Build configuration list for PBXNativeTarget "KageeTests" */; 184 | buildPhases = ( 185 | 5632296DC0342A32F67A6261 /* Check Pods Manifest.lock */, 186 | B6E941081C52816A00E853C0 /* Sources */, 187 | B6E941091C52816A00E853C0 /* Frameworks */, 188 | B6E9410A1C52816A00E853C0 /* Resources */, 189 | 70F55659224CE803578B45E3 /* Embed Pods Frameworks */, 190 | 9CF5B2DD1E7282133EC90835 /* Copy Pods Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | B6E9410F1C52816A00E853C0 /* PBXTargetDependency */, 196 | ); 197 | name = KageeTests; 198 | productName = MockinTests; 199 | productReference = B6E9410C1C52816A00E853C0 /* Kagee.xctest */; 200 | productType = "com.apple.product-type.bundle.unit-test"; 201 | }; 202 | /* End PBXNativeTarget section */ 203 | 204 | /* Begin PBXProject section */ 205 | B6E940F91C52816A00E853C0 /* Project object */ = { 206 | isa = PBXProject; 207 | attributes = { 208 | LastSwiftUpdateCheck = 0710; 209 | LastUpgradeCheck = 0710; 210 | ORGANIZATIONNAME = yukiasai; 211 | TargetAttributes = { 212 | B6E941011C52816A00E853C0 = { 213 | CreatedOnToolsVersion = 7.1.1; 214 | DevelopmentTeam = NRUDQDRGJZ; 215 | }; 216 | B6E9410B1C52816A00E853C0 = { 217 | CreatedOnToolsVersion = 7.1.1; 218 | DevelopmentTeam = NRUDQDRGJZ; 219 | }; 220 | }; 221 | }; 222 | buildConfigurationList = B6E940FC1C52816A00E853C0 /* Build configuration list for PBXProject "Kagee" */; 223 | compatibilityVersion = "Xcode 3.2"; 224 | developmentRegion = English; 225 | hasScannedForEncodings = 0; 226 | knownRegions = ( 227 | en, 228 | ); 229 | mainGroup = B6E940F81C52816A00E853C0; 230 | productRefGroup = B6E941031C52816A00E853C0 /* Products */; 231 | projectDirPath = ""; 232 | projectRoot = ""; 233 | targets = ( 234 | B6E941011C52816A00E853C0 /* Kagee */, 235 | B6E9410B1C52816A00E853C0 /* KageeTests */, 236 | ); 237 | }; 238 | /* End PBXProject section */ 239 | 240 | /* Begin PBXResourcesBuildPhase section */ 241 | B6E941001C52816A00E853C0 /* Resources */ = { 242 | isa = PBXResourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | 46D632FD1C5F400A005CFFF0 /* Info.plist in Resources */, 246 | 46D632F71C5F400A005CFFF0 /* Info.plist in Resources */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | B6E9410A1C52816A00E853C0 /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | 46D633091C5F401E005CFFF0 /* test.json in Resources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXResourcesBuildPhase section */ 259 | 260 | /* Begin PBXShellScriptBuildPhase section */ 261 | 5632296DC0342A32F67A6261 /* Check Pods Manifest.lock */ = { 262 | isa = PBXShellScriptBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | inputPaths = ( 267 | ); 268 | name = "Check Pods Manifest.lock"; 269 | outputPaths = ( 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | shellPath = /bin/sh; 273 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 274 | showEnvVarsInLog = 0; 275 | }; 276 | 70F55659224CE803578B45E3 /* Embed Pods Frameworks */ = { 277 | isa = PBXShellScriptBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | ); 281 | inputPaths = ( 282 | ); 283 | name = "Embed Pods Frameworks"; 284 | outputPaths = ( 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | shellPath = /bin/sh; 288 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-KageeTests/Pods-KageeTests-frameworks.sh\"\n"; 289 | showEnvVarsInLog = 0; 290 | }; 291 | 9CF5B2DD1E7282133EC90835 /* Copy Pods Resources */ = { 292 | isa = PBXShellScriptBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | ); 296 | inputPaths = ( 297 | ); 298 | name = "Copy Pods Resources"; 299 | outputPaths = ( 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | shellPath = /bin/sh; 303 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-KageeTests/Pods-KageeTests-resources.sh\"\n"; 304 | showEnvVarsInLog = 0; 305 | }; 306 | /* End PBXShellScriptBuildPhase section */ 307 | 308 | /* Begin PBXSourcesBuildPhase section */ 309 | B6E940FD1C52816A00E853C0 /* Sources */ = { 310 | isa = PBXSourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | 46D632FC1C5F400A005CFFF0 /* URLConvertible.swift in Sources */, 314 | 46D632F91C5F400A005CFFF0 /* MockPool.swift in Sources */, 315 | 46D632FB1C5F400A005CFFF0 /* Enums.swift in Sources */, 316 | 46D632F51C5F400A005CFFF0 /* Body.swift in Sources */, 317 | 46D632F81C5F400A005CFFF0 /* Mock.swift in Sources */, 318 | 46D632FA1C5F400A005CFFF0 /* MockProtocol.swift in Sources */, 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | }; 322 | B6E941081C52816A00E853C0 /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 46D633001C5F4011005CFFF0 /* KageeTests.swift in Sources */, 327 | 46D633011C5F4015005CFFF0 /* Body.swift in Sources */, 328 | 46D6330B1C5F4CC4005CFFF0 /* AlamofireTests.swift in Sources */, 329 | 46D633061C5F4015005CFFF0 /* MockProtocol.swift in Sources */, 330 | 46D633041C5F4015005CFFF0 /* Mock.swift in Sources */, 331 | 46D633071C5F4015005CFFF0 /* Enums.swift in Sources */, 332 | 46D633051C5F4015005CFFF0 /* MockPool.swift in Sources */, 333 | 46D633081C5F4015005CFFF0 /* URLConvertible.swift in Sources */, 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXSourcesBuildPhase section */ 338 | 339 | /* Begin PBXTargetDependency section */ 340 | B6E9410F1C52816A00E853C0 /* PBXTargetDependency */ = { 341 | isa = PBXTargetDependency; 342 | target = B6E941011C52816A00E853C0 /* Kagee */; 343 | targetProxy = B6E9410E1C52816A00E853C0 /* PBXContainerItemProxy */; 344 | }; 345 | /* End PBXTargetDependency section */ 346 | 347 | /* Begin XCBuildConfiguration section */ 348 | B6E941141C52816A00E853C0 /* Debug */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ALWAYS_SEARCH_USER_PATHS = NO; 352 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 353 | CLANG_CXX_LIBRARY = "libc++"; 354 | CLANG_ENABLE_MODULES = YES; 355 | CLANG_ENABLE_OBJC_ARC = YES; 356 | CLANG_WARN_BOOL_CONVERSION = YES; 357 | CLANG_WARN_CONSTANT_CONVERSION = YES; 358 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 359 | CLANG_WARN_EMPTY_BODY = YES; 360 | CLANG_WARN_ENUM_CONVERSION = YES; 361 | CLANG_WARN_INT_CONVERSION = YES; 362 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 363 | CLANG_WARN_UNREACHABLE_CODE = YES; 364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 365 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 366 | COPY_PHASE_STRIP = NO; 367 | CURRENT_PROJECT_VERSION = 1; 368 | DEBUG_INFORMATION_FORMAT = dwarf; 369 | ENABLE_STRICT_OBJC_MSGSEND = YES; 370 | ENABLE_TESTABILITY = YES; 371 | GCC_C_LANGUAGE_STANDARD = gnu99; 372 | GCC_DYNAMIC_NO_PIC = NO; 373 | GCC_NO_COMMON_BLOCKS = YES; 374 | GCC_OPTIMIZATION_LEVEL = 0; 375 | GCC_PREPROCESSOR_DEFINITIONS = ( 376 | "DEBUG=1", 377 | "$(inherited)", 378 | ); 379 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 380 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 381 | GCC_WARN_UNDECLARED_SELECTOR = YES; 382 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 383 | GCC_WARN_UNUSED_FUNCTION = YES; 384 | GCC_WARN_UNUSED_VARIABLE = YES; 385 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 386 | MTL_ENABLE_DEBUG_INFO = YES; 387 | ONLY_ACTIVE_ARCH = YES; 388 | SDKROOT = iphoneos; 389 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 390 | TARGETED_DEVICE_FAMILY = "1,2"; 391 | VERSIONING_SYSTEM = "apple-generic"; 392 | VERSION_INFO_PREFIX = ""; 393 | }; 394 | name = Debug; 395 | }; 396 | B6E941151C52816A00E853C0 /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_SEARCH_USER_PATHS = NO; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN_BOOL_CONVERSION = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 407 | CLANG_WARN_EMPTY_BODY = YES; 408 | CLANG_WARN_ENUM_CONVERSION = YES; 409 | CLANG_WARN_INT_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_UNREACHABLE_CODE = YES; 412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 414 | COPY_PHASE_STRIP = NO; 415 | CURRENT_PROJECT_VERSION = 1; 416 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 417 | ENABLE_NS_ASSERTIONS = NO; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | GCC_C_LANGUAGE_STANDARD = gnu99; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 423 | GCC_WARN_UNDECLARED_SELECTOR = YES; 424 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 425 | GCC_WARN_UNUSED_FUNCTION = YES; 426 | GCC_WARN_UNUSED_VARIABLE = YES; 427 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 428 | MTL_ENABLE_DEBUG_INFO = NO; 429 | SDKROOT = iphoneos; 430 | TARGETED_DEVICE_FAMILY = "1,2"; 431 | VALIDATE_PRODUCT = YES; 432 | VERSIONING_SYSTEM = "apple-generic"; 433 | VERSION_INFO_PREFIX = ""; 434 | }; 435 | name = Release; 436 | }; 437 | B6E941171C52816A00E853C0 /* Debug */ = { 438 | isa = XCBuildConfiguration; 439 | buildSettings = { 440 | CLANG_ENABLE_MODULES = YES; 441 | DEFINES_MODULE = YES; 442 | DYLIB_COMPATIBILITY_VERSION = 1; 443 | DYLIB_CURRENT_VERSION = 1; 444 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 445 | INFOPLIST_FILE = Kagee/Info.plist; 446 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 447 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 448 | PRODUCT_BUNDLE_IDENTIFIER = yukiasai.Kagee; 449 | PRODUCT_NAME = Kagee; 450 | SKIP_INSTALL = YES; 451 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 452 | }; 453 | name = Debug; 454 | }; 455 | B6E941181C52816A00E853C0 /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | CLANG_ENABLE_MODULES = YES; 459 | DEFINES_MODULE = YES; 460 | DYLIB_COMPATIBILITY_VERSION = 1; 461 | DYLIB_CURRENT_VERSION = 1; 462 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 463 | INFOPLIST_FILE = Kagee/Info.plist; 464 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 466 | PRODUCT_BUNDLE_IDENTIFIER = yukiasai.Kagee; 467 | PRODUCT_NAME = Kagee; 468 | SKIP_INSTALL = YES; 469 | }; 470 | name = Release; 471 | }; 472 | B6E9411A1C52816A00E853C0 /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | baseConfigurationReference = 5A2E58BC6397F200014FAACA /* Pods-KageeTests.debug.xcconfig */; 475 | buildSettings = { 476 | INFOPLIST_FILE = KageeTests/Info.plist; 477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 478 | PRODUCT_BUNDLE_IDENTIFIER = yukiasai.KageeTests; 479 | PRODUCT_NAME = Kagee; 480 | }; 481 | name = Debug; 482 | }; 483 | B6E9411B1C52816A00E853C0 /* Release */ = { 484 | isa = XCBuildConfiguration; 485 | baseConfigurationReference = B3CDC0350037667BF37AE0C4 /* Pods-KageeTests.release.xcconfig */; 486 | buildSettings = { 487 | INFOPLIST_FILE = KageeTests/Info.plist; 488 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 489 | PRODUCT_BUNDLE_IDENTIFIER = yukiasai.KageeTests; 490 | PRODUCT_NAME = Kagee; 491 | }; 492 | name = Release; 493 | }; 494 | /* End XCBuildConfiguration section */ 495 | 496 | /* Begin XCConfigurationList section */ 497 | B6E940FC1C52816A00E853C0 /* Build configuration list for PBXProject "Kagee" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | B6E941141C52816A00E853C0 /* Debug */, 501 | B6E941151C52816A00E853C0 /* Release */, 502 | ); 503 | defaultConfigurationIsVisible = 0; 504 | defaultConfigurationName = Release; 505 | }; 506 | B6E941161C52816A00E853C0 /* Build configuration list for PBXNativeTarget "Kagee" */ = { 507 | isa = XCConfigurationList; 508 | buildConfigurations = ( 509 | B6E941171C52816A00E853C0 /* Debug */, 510 | B6E941181C52816A00E853C0 /* Release */, 511 | ); 512 | defaultConfigurationIsVisible = 0; 513 | defaultConfigurationName = Release; 514 | }; 515 | B6E941191C52816A00E853C0 /* Build configuration list for PBXNativeTarget "KageeTests" */ = { 516 | isa = XCConfigurationList; 517 | buildConfigurations = ( 518 | B6E9411A1C52816A00E853C0 /* Debug */, 519 | B6E9411B1C52816A00E853C0 /* Release */, 520 | ); 521 | defaultConfigurationIsVisible = 0; 522 | defaultConfigurationName = Release; 523 | }; 524 | /* End XCConfigurationList section */ 525 | }; 526 | rootObject = B6E940F91C52816A00E853C0 /* Project object */; 527 | } 528 | -------------------------------------------------------------------------------- /Kagee.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Kagee.xcodeproj/xcshareddata/xcschemes/Kagee.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Kagee.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Kagee/Body.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Body.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 1/27/16. 6 | // Copyright © 2016 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Body { 12 | var data: ResponseData { get } 13 | } 14 | 15 | extension NSData: Body { 16 | public var data: ResponseData { 17 | return .Data(self) 18 | } 19 | } 20 | 21 | extension String: Body { 22 | public var data: ResponseData { 23 | return Text(self).data 24 | } 25 | } 26 | 27 | public class JSON: Body { 28 | let object: AnyObject 29 | public init(_ object: AnyObject) { 30 | self.object = object 31 | } 32 | 33 | public var data: ResponseData { 34 | do { 35 | let data = try NSJSONSerialization.dataWithJSONObject(object, options: .PrettyPrinted) 36 | return .Data(data) 37 | } catch { 38 | return .Error(error as NSError) 39 | } 40 | } 41 | } 42 | 43 | public class File: Body { 44 | let url: NSURL 45 | 46 | public init(url urlConvertible: URLConvertible) { 47 | self.url = urlConvertible.URL 48 | } 49 | 50 | public var data: ResponseData { 51 | do { 52 | let data = try NSData(contentsOfURL: url, options: .DataReadingUncached) 53 | return .Data(data) 54 | } catch { 55 | return .Error(error as NSError) 56 | } 57 | } 58 | } 59 | 60 | public class Text: Body { 61 | let string: String 62 | let encoding: NSStringEncoding 63 | public init(_ string: String, encoding: NSStringEncoding = NSUTF8StringEncoding) { 64 | self.string = string 65 | self.encoding = encoding 66 | } 67 | 68 | public var data: ResponseData { 69 | if let data = string.dataUsingEncoding(encoding) { 70 | return .Data(data) 71 | } else { 72 | let message = "Failed to encode the string." 73 | let error = NSError(domain: errorDomain, code: 0, userInfo: [NSLocalizedFailureReasonErrorKey: message, NSLocalizedDescriptionKey: message]) 74 | return .Error(error as NSError) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Kagee/Enums.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Network.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 2016/01/28. 6 | // Copyright © 2016年 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum Response { 12 | case Success(NSURLResponse, NSData?) 13 | case Failure(NSError) 14 | } 15 | 16 | public enum ResponseData { 17 | case Data(NSData) 18 | case Error(NSError) 19 | } 20 | 21 | public enum Method: String { 22 | case GET 23 | case POST 24 | case PUT 25 | case DELETE 26 | } 27 | 28 | public enum Speed { 29 | case Prompt 30 | case Wifi 31 | case Mobile4G 32 | case Mobile3G 33 | case Edge 34 | case Custom(bps: Double) 35 | 36 | var bps: Double? { 37 | switch self { 38 | case .Prompt: 39 | return nil 40 | case .Wifi: 41 | return 45_000_000 42 | case .Mobile4G: 43 | return 10_000_000 44 | case .Mobile3G: 45 | return 1_000_000 46 | case .Edge: 47 | return 200_000 48 | case .Custom(let bps): 49 | return bps 50 | } 51 | } 52 | 53 | func sec(bytes: UInt32) -> UInt32? { 54 | guard let bps = self.bps else { 55 | return nil 56 | } 57 | return UInt32(Double(bytes * 8) / bps) 58 | } 59 | 60 | func usec(bytes: UInt32) -> UInt32? { 61 | guard let sec = sec(bytes) else { 62 | return nil 63 | } 64 | return sec * 1_000_000 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Kagee/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Kagee/Mock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Mock.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 2016/01/23. 6 | // Copyright © 2016年 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | internal let errorDomain = "yukiasai.Kagee" 12 | 13 | public typealias Header = [String: String] 14 | public typealias RequestHandler = Void -> NSURLRequest 15 | public typealias ResponseHandler = NSURLRequest -> Response 16 | 17 | public class Mock: MockType, MockRequestType, MockResponseType { 18 | var requestHandler: RequestHandler? 19 | var responseHandler: ResponseHandler? 20 | var speed: Speed? 21 | 22 | init(@noescape closure: Mock -> Void) { 23 | closure(self) 24 | } 25 | 26 | var request: NSURLRequest? { 27 | return requestHandler?() 28 | } 29 | } 30 | 31 | extension Mock { 32 | public class func install() -> MockType { 33 | return Mock { 34 | MockPool.add($0) 35 | } 36 | } 37 | 38 | public func remove() { 39 | MockPool.remove(self) 40 | } 41 | 42 | public func request(url urlConvertible: URLConvertible) -> MockRequestType { 43 | return request(url: urlConvertible, method: .GET) 44 | } 45 | 46 | public func request(url urlConvertible: URLConvertible, method: Method) -> MockRequestType { 47 | let req = NSMutableURLRequest(URL: urlConvertible.URL) 48 | req.HTTPMethod = method.rawValue 49 | return request(req) 50 | } 51 | 52 | public func request(request: NSURLRequest) -> MockRequestType { 53 | let handler: RequestHandler = { return request } 54 | return self.request(handler) 55 | } 56 | 57 | public func request(handler: RequestHandler) -> MockRequestType { 58 | requestHandler = handler 59 | return self 60 | } 61 | } 62 | 63 | extension Mock { 64 | public func response(statusCode: Int, body: Body? = nil, header: Header? = nil) -> MockResponseType { 65 | guard let url = request?.URL, let res = NSHTTPURLResponse(URL: url, statusCode: statusCode, HTTPVersion: nil, headerFields: header) else { 66 | let error = NSError(domain: errorDomain, code: 0, userInfo: [NSLocalizedFailureReasonErrorKey: "Response is not NSHTTPURLResponse.", NSLocalizedDescriptionKey: "Response is not NSHTTPURLResponse."]) 67 | return response(error) 68 | } 69 | 70 | guard let data = body?.data else { 71 | return response(res, data: nil) 72 | } 73 | 74 | switch data { 75 | case .Error(let error): 76 | return response(error) 77 | case .Data(let data): 78 | return response(res, data: data) 79 | } 80 | } 81 | 82 | public func response(response: NSURLResponse, data: NSData? = nil) -> MockResponseType { 83 | let handler: ResponseHandler = { _ in return .Success(response, data) } 84 | return self.response(handler) 85 | } 86 | 87 | public func response(error: NSError) -> MockResponseType { 88 | let handler: ResponseHandler = { _ in return .Failure(error) } 89 | return self.response(handler) 90 | } 91 | 92 | public func response(handler: ResponseHandler) -> MockResponseType { 93 | responseHandler = handler 94 | return self 95 | } 96 | } 97 | 98 | extension Mock { 99 | public func speed(speed: Speed) -> MockResponseType { 100 | self.speed = speed 101 | return self 102 | } 103 | } 104 | 105 | public protocol MockType: class { 106 | static func install() -> MockType 107 | func remove() 108 | func request(url urlConvertible: URLConvertible) -> MockRequestType 109 | func request(url urlConvertible: URLConvertible, method: Method) -> MockRequestType 110 | func request(request: NSURLRequest) -> MockRequestType 111 | func request(handler: RequestHandler) -> MockRequestType 112 | } 113 | 114 | public protocol MockRequestType: class, MockType { 115 | func response(statusCode: Int, body: Body?, header: Header?) -> MockResponseType 116 | func response(response: NSURLResponse, data: NSData?) -> MockResponseType 117 | func response(error: NSError) -> MockResponseType 118 | func response(handler: ResponseHandler) -> MockResponseType 119 | } 120 | 121 | public protocol MockResponseType: class, MockType { 122 | func speed(speed: Speed) -> MockResponseType 123 | } 124 | 125 | -------------------------------------------------------------------------------- /Kagee/MockPool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockPool.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 1/29/16. 6 | // Copyright © 2016 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class MockPool { 12 | static var mocks = [Mock]() 13 | 14 | class func add(mock: Mock) { 15 | mocks += [mock] 16 | } 17 | 18 | class func remove(mock: Mock) { 19 | if let index = (mocks.indexOf { $0 === mock }) { 20 | mocks.removeAtIndex(index) 21 | } 22 | } 23 | 24 | class func targetMock(request: NSURLRequest) -> Mock? { 25 | return mocks.filter { 26 | let isEqualMethod = $0.request?.HTTPMethod == request.HTTPMethod 27 | let isEqualHost = $0.request?.URL?.host == request.URL?.host 28 | let isEqualPath = $0.request?.URL?.path == request.URL?.path 29 | return isEqualMethod && isEqualHost && isEqualPath 30 | }.last 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Kagee/MockProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockProtocol.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 2016/01/23. 6 | // Copyright © 2016年 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class MockProtocol: NSURLProtocol { 12 | static var token: dispatch_once_t = 0 13 | public class func register() { 14 | dispatch_once(&token) { 15 | NSURLProtocol.registerClass(self) 16 | 17 | let configClass = NSURLSessionConfiguration.self 18 | let originalMethod = class_getClassMethod(configClass, Selector("defaultSessionConfiguration")) 19 | let swizzledMethod = class_getClassMethod(configClass, Selector("mockSessionConfiguration")) 20 | method_exchangeImplementations(originalMethod, swizzledMethod) 21 | } 22 | } 23 | 24 | public override class func canInitWithRequest(request: NSURLRequest) -> Bool { 25 | return targetMock(request) != nil 26 | } 27 | 28 | public override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest { 29 | return request 30 | } 31 | 32 | public override func startLoading() { 33 | guard let mock = MockProtocol.targetMock(request) else { 34 | // Should nonnull is returned by the canInitWithRequest 35 | fatalError() 36 | } 37 | 38 | guard let response = mock.responseHandler?(request) else { 39 | fatalError() 40 | } 41 | 42 | switch response { 43 | case .Failure(let error): 44 | client?.URLProtocol(self, didFailWithError: error) 45 | return 46 | case .Success(let response, let data): 47 | // Data 48 | if let d = data { 49 | client?.URLProtocol(self, didLoadData: d) 50 | 51 | // Delay 52 | if let usec = mock.speed?.usec(UInt32(d.length)) { 53 | usleep(usec) 54 | } 55 | } 56 | 57 | // Response 58 | client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed) 59 | client?.URLProtocolDidFinishLoading(self) 60 | } 61 | } 62 | 63 | public override func stopLoading() { 64 | } 65 | 66 | private class func targetMock(request: NSURLRequest) -> Mock? { 67 | return MockPool.targetMock(request) 68 | } 69 | } 70 | 71 | extension NSURLSessionConfiguration { 72 | class func mockSessionConfiguration() -> NSURLSessionConfiguration { 73 | let config = mockSessionConfiguration() 74 | config.protocolClasses = ([MockProtocol.self] as [AnyClass]) + (config.protocolClasses ?? []) 75 | return config 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Kagee/URLConvertible.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLConvertible.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 1/27/16. 6 | // Copyright © 2016 yukiasai. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol URLConvertible { 12 | var URL: NSURL { get } 13 | } 14 | 15 | extension String: URLConvertible { 16 | public var URL: NSURL { 17 | guard let ret = NSURL(string: self) else { 18 | fatalError() 19 | } 20 | return ret 21 | } 22 | } 23 | 24 | extension NSURL: URLConvertible { 25 | public var URL: NSURL { 26 | return self 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /KageeTests/AlamofireTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlamofireTests.swift 3 | // Kagee 4 | // 5 | // Created by yukiasai on 2/1/16. 6 | // Copyright © 2016 yukiasai. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import Alamofire 11 | @testable import Kagee 12 | 13 | class AlamofireTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | MockProtocol.register() 18 | } 19 | 20 | override func tearDown() { 21 | super.tearDown() 22 | } 23 | 24 | func testGet() { 25 | let ex = expectationWithDescription("") 26 | 27 | let url = "/" 28 | Mock.install().request(url: url).response(200, body: nil, header: nil) 29 | Alamofire.request(.GET, url).response { _, response, _, _ in 30 | XCTAssertEqual(response?.statusCode, 200) 31 | ex.fulfill() 32 | } 33 | 34 | waitForExpectationsWithTimeout(1000) { error in } 35 | } 36 | 37 | func testJSON() { 38 | let ex = expectationWithDescription("") 39 | 40 | let url = "/json" 41 | let json: [String: AnyObject] = ["name": "yukiasai", "age": 28] 42 | Mock.install().request(url: url).response(200, body: JSON(json), header: nil) 43 | Alamofire.request(.GET, url).responseJSON { response in 44 | switch response.result { 45 | case .Success(let json): 46 | guard let dic = json as? [String: AnyObject] else { 47 | XCTFail() 48 | return 49 | } 50 | XCTAssertEqual(dic["name"] as? String, "yukiasai") 51 | XCTAssertEqual(dic["age"] as? Int, 28) 52 | case .Failure(_): 53 | XCTFail() 54 | } 55 | 56 | ex.fulfill() 57 | } 58 | 59 | waitForExpectationsWithTimeout(1000) { error in } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /KageeTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /KageeTests/KageeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KageeTests.swift 3 | // KageeTests 4 | // 5 | // Created by yukiasai on 2016/01/23. 6 | // Copyright © 2016年 yukiasai. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Kagee 11 | 12 | class KageeTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | MockProtocol.register() 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | func testUpDown() { 24 | let initialCount = MockPool.mocks.count 25 | let mock = Mock.install().request(url: "/") 26 | XCTAssertEqual(MockPool.mocks.count, initialCount + 1) 27 | mock.remove() 28 | XCTAssertEqual(MockPool.mocks.count, initialCount) 29 | } 30 | 31 | func testGetRequest() { 32 | let ex = expectationWithDescription("") 33 | 34 | let url = "/" 35 | Mock.install().request(url: url).response(200, body: nil, header: nil) 36 | 37 | let request = NSURLRequest(URL: NSURL(string: url)!) 38 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 39 | session.dataTaskWithRequest(request) { data, response, error in 40 | guard let httpResponse = response as? NSHTTPURLResponse else { 41 | fatalError() 42 | } 43 | XCTAssertEqual(httpResponse.statusCode, 200) 44 | ex.fulfill() 45 | }.resume() 46 | 47 | waitForExpectationsWithTimeout(1000) { error in 48 | } 49 | } 50 | 51 | func testGetJSON() { 52 | let ex = expectationWithDescription("") 53 | 54 | let url = "/json" 55 | let json: [String: AnyObject] = ["name": "yukiasai", "age": 28] 56 | Mock.install().request(url: url).response(200, body: JSON(json), header: nil) 57 | 58 | let request = NSURLRequest(URL: NSURL(string: url)!) 59 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 60 | session.dataTaskWithRequest(request) { data, response, error in 61 | guard let httpResponse = response as? NSHTTPURLResponse, let responseData = data else { 62 | fatalError() 63 | } 64 | XCTAssertEqual(httpResponse.statusCode, 200) 65 | 66 | do { 67 | let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: .AllowFragments) 68 | let dic = json as? [String: AnyObject] 69 | XCTAssertNotNil(dic) 70 | XCTAssertEqual(dic?["name"] as? String, "yukiasai") 71 | XCTAssertEqual(dic?["age"] as? Int, 28) 72 | } catch { 73 | fatalError() 74 | } 75 | 76 | ex.fulfill() 77 | }.resume() 78 | 79 | waitForExpectationsWithTimeout(1000) { error in 80 | } 81 | } 82 | 83 | func testGetError() { 84 | let ex = expectationWithDescription("") 85 | 86 | let url = "/error" 87 | let error = NSError(domain: "yukiasai.Kagee", code: 1000, userInfo: nil) 88 | Mock.install().request(url: url).response(error) 89 | 90 | let request = NSURLRequest(URL: NSURL(string: url)!) 91 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 92 | session.dataTaskWithRequest(request) { data, response, error in 93 | XCTAssertNil(data) 94 | XCTAssertNil(response) 95 | XCTAssertNotNil(error) 96 | XCTAssertEqual(error?.domain, "yukiasai.Kagee") 97 | XCTAssertEqual(error?.code, 1000) 98 | ex.fulfill() 99 | }.resume() 100 | 101 | waitForExpectationsWithTimeout(1000) { error in 102 | } 103 | } 104 | 105 | func testRequestHandlerSuccess() { 106 | let ex = expectationWithDescription("") 107 | 108 | let url = "/handler_success" 109 | Mock.install().request(url: url).response { request -> Response in 110 | let response = NSHTTPURLResponse(URL: request.URL!, statusCode: 200, HTTPVersion: nil, headerFields: nil)! 111 | let data = "12345".dataUsingEncoding(NSUTF8StringEncoding) 112 | return .Success(response, data) 113 | } 114 | 115 | let request = NSURLRequest(URL: NSURL(string: url)!) 116 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 117 | session.dataTaskWithRequest(request) { data, response, error in 118 | guard let httpResponse = response as? NSHTTPURLResponse, let responseData = data else { 119 | fatalError() 120 | } 121 | XCTAssertEqual(httpResponse.statusCode, 200) 122 | XCTAssertEqual(responseData.length, 5) 123 | 124 | ex.fulfill() 125 | }.resume() 126 | 127 | waitForExpectationsWithTimeout(1000) { error in } 128 | } 129 | 130 | func testRequestHandlerFailure() { 131 | let ex = expectationWithDescription("") 132 | 133 | let url = "/handler_failure" 134 | Mock.install().request(url: url).response { _ -> Response in 135 | let error = NSError(domain: "yukiasai.Kagee", code: 2000, userInfo: nil) 136 | return .Failure(error) 137 | } 138 | 139 | let request = NSURLRequest(URL: NSURL(string: url)!) 140 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 141 | session.dataTaskWithRequest(request) { data, response, error in 142 | XCTAssertNil(data) 143 | XCTAssertNil(response) 144 | XCTAssertNotNil(error) 145 | XCTAssertEqual(error?.domain, "yukiasai.Kagee") 146 | XCTAssertEqual(error?.code, 2000) 147 | ex.fulfill() 148 | }.resume() 149 | 150 | waitForExpectationsWithTimeout(1000) { error in } 151 | } 152 | 153 | func testFile() { 154 | let ex = expectationWithDescription("") 155 | 156 | let url = "/json_file" 157 | let fileUrl = NSBundle(forClass: self.dynamicType).URLForResource("test", withExtension: "json")! 158 | Mock.install().request(url: url).response(200, body: File(url: fileUrl), header: nil) 159 | 160 | let request = NSURLRequest(URL: NSURL(string: url)!) 161 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 162 | session.dataTaskWithRequest(request) { data, response, error in 163 | guard let httpResponse = response as? NSHTTPURLResponse, let responseData = data else { 164 | fatalError() 165 | } 166 | XCTAssertEqual(httpResponse.statusCode, 200) 167 | 168 | do { 169 | let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: .AllowFragments) 170 | let dic = json as? [String: AnyObject] 171 | XCTAssertNotNil(dic) 172 | XCTAssertEqual(dic?["name"] as? String, "yukiasai") 173 | XCTAssertEqual(dic?["age"] as? Int, 28) 174 | } catch { 175 | fatalError() 176 | } 177 | 178 | ex.fulfill() 179 | }.resume() 180 | 181 | waitForExpectationsWithTimeout(1000) { error in } 182 | } 183 | 184 | 185 | func testString() { 186 | let ex = expectationWithDescription("") 187 | 188 | let url = "/plain_text" 189 | Mock.install().request(url: url).response(200, body: "{\"name\": \"yukiasai\", \"age\": 28}", header: nil) 190 | 191 | let request = NSURLRequest(URL: NSURL(string: url)!) 192 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 193 | session.dataTaskWithRequest(request) { data, response, error in 194 | guard let httpResponse = response as? NSHTTPURLResponse, let responseData = data else { 195 | fatalError() 196 | } 197 | XCTAssertEqual(httpResponse.statusCode, 200) 198 | do { 199 | let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: .AllowFragments) 200 | let dic = json as? [String: AnyObject] 201 | XCTAssertNotNil(dic) 202 | XCTAssertEqual(dic?["name"] as? String, "yukiasai") 203 | XCTAssertEqual(dic?["age"] as? Int, 28) 204 | } catch { 205 | fatalError() 206 | } 207 | 208 | ex.fulfill() 209 | }.resume() 210 | 211 | waitForExpectationsWithTimeout(1000) { error in } 212 | } 213 | 214 | func testPlainText() { 215 | let ex = expectationWithDescription("") 216 | 217 | let url = "/plain_text" 218 | Mock.install().request(url: url).response(200, body: Text("{\"name\": \"yukiasai\", \"age\": 28}"), header: nil) 219 | 220 | let request = NSURLRequest(URL: NSURL(string: url)!) 221 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 222 | session.dataTaskWithRequest(request) { data, response, error in 223 | guard let httpResponse = response as? NSHTTPURLResponse, let responseData = data else { 224 | fatalError() 225 | } 226 | XCTAssertEqual(httpResponse.statusCode, 200) 227 | do { 228 | let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: .AllowFragments) 229 | let dic = json as? [String: AnyObject] 230 | XCTAssertNotNil(dic) 231 | XCTAssertEqual(dic?["name"] as? String, "yukiasai") 232 | XCTAssertEqual(dic?["age"] as? Int, 28) 233 | } catch { 234 | fatalError() 235 | } 236 | 237 | ex.fulfill() 238 | }.resume() 239 | 240 | waitForExpectationsWithTimeout(1000) { error in } 241 | } 242 | 243 | func testURLConvertible() { 244 | let ex = expectationWithDescription("") 245 | 246 | let url = NSURL(string: "http://aaa.aaa")! 247 | Mock.install().request(url: url).response(200, body: nil, header: nil) 248 | 249 | let request = NSURLRequest(URL: url) 250 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 251 | session.dataTaskWithRequest(request) { data, response, error in 252 | guard let httpResponse = response as? NSHTTPURLResponse else { 253 | fatalError() 254 | } 255 | XCTAssertEqual(httpResponse.statusCode, 200) 256 | ex.fulfill() 257 | }.resume() 258 | 259 | waitForExpectationsWithTimeout(1000) { error in } 260 | } 261 | 262 | func testNetworkSpeed() { 263 | let ex = expectationWithDescription("") 264 | 265 | let url = "/network_speed" 266 | let data = (0..<100_000).reduce("") { sum, _ in return sum + "0" }.dataUsingEncoding(NSUTF8StringEncoding)! 267 | Mock.install().request(url: url).response(200, body: data, header: nil).speed(.Mobile3G) 268 | 269 | let request = NSURLRequest(URL: NSURL(string: url)!) 270 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 271 | session.dataTaskWithRequest(request) { data, response, error in 272 | guard let httpResponse = response as? NSHTTPURLResponse else { 273 | fatalError() 274 | } 275 | XCTAssertEqual(httpResponse.statusCode, 200) 276 | ex.fulfill() 277 | }.resume() 278 | 279 | waitForExpectationsWithTimeout(1000) { error in } 280 | } 281 | 282 | func testCustomSpeed() { 283 | let ex = expectationWithDescription("") 284 | 285 | let url = "/custom_speed" 286 | let data = (0..<1_000).reduce("") { sum, _ in return sum + "0" }.dataUsingEncoding(NSUTF8StringEncoding)! 287 | Mock.install().request(url: url).response(200, body: data, header: nil).speed(.Custom(bps: 100_000)) 288 | 289 | let request = NSURLRequest(URL: NSURL(string: url)!) 290 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 291 | session.dataTaskWithRequest(request) { data, response, error in 292 | guard let httpResponse = response as? NSHTTPURLResponse else { 293 | fatalError() 294 | } 295 | XCTAssertEqual(httpResponse.statusCode, 200) 296 | ex.fulfill() 297 | }.resume() 298 | 299 | waitForExpectationsWithTimeout(1000) { error in } 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /KageeTests/Resources/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yukiasai", 3 | "age": 28 4 | } 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 yukiasai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '8.0' 3 | # Uncomment this line if you're using Swift 4 | use_frameworks! 5 | 6 | target 'Kagee' do 7 | 8 | end 9 | 10 | target 'KageeTests' do 11 | 12 | pod 'Alamofire' 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (3.1.5) 3 | 4 | DEPENDENCIES: 5 | - Alamofire 6 | 7 | SPEC CHECKSUMS: 8 | Alamofire: 5f730ba29fd113b7ddd71c1e65d0c630acf5d7b0 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kagee 2 | Easily way to write a stub for the network request 3 | 4 | ## Usage 5 | 6 | Please call the `MockProtocol.register()` when app is launched. 7 | 8 | ##### iOS example 9 | 10 | ``` swift 11 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 12 | MockProtocol.register() 13 | return true 14 | } 15 | ``` 16 | 17 | You can create a stub with the `Mock.install()`. And using `request` and `response` to defined the content. 18 | 19 | ``` swift 20 | Mock.install().request(url: "/").response(200, body: nil, header: nil) 21 | ``` 22 | 23 | Write a network request using the usual `NSURLSession` or `Alamofire`. 24 | 25 | ##### NSURLSession 26 | 27 | ``` swift 28 | let request = NSURLRequest(URL: NSURL(string: "/")!) 29 | let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) 30 | session.dataTaskWithRequest(request) { data, response, error in 31 | let httpResponse = response as! NSHTTPURLResponse 32 | // Status code is 200 !!! 33 | ex.fulfill() 34 | }.resume() 35 | ``` 36 | 37 | ##### Alamofire 38 | 39 | ``` swift 40 | Alamofire.request(.GET, "/").response { _, response, _, _ in 41 | // Status code is 200 !!! 42 | } 43 | ``` 44 | 45 | ### Stub data of JSON object 46 | 47 | Pass the `JSON` to the `body`. 48 | 49 | ``` swift 50 | let json: [String: AnyObject] = ["name": "yukiasai", "age": 28] 51 | Mock.install().request(url: url).response(200, body: JSON(json), header: nil) 52 | ``` 53 | 54 | ### Stub data from file 55 | 56 | ``` swift 57 | let fileUrl: NSURL = NSURL(string: "path/to/file")! 58 | Mock.install().request(url: url).response(200, body: File(fileUrl), header: nil) 59 | ``` 60 | 61 | ### Response handler 62 | 63 | You can also write the `responseHandler`. 64 | 65 | ``` swift 66 | Mock.install().request(url: someUrl).response { request -> Response in 67 | let response = NSHTTPURLResponse(URL: request.URL!, statusCode: 200, HTTPVersion: nil, headerFields: nil)! 68 | let data = "12345".dataUsingEncoding(NSUTF8StringEncoding) 69 | return .Success(response, data) 70 | // or return .Failure(error) 71 | } 72 | ``` 73 | 74 | ### Network speed 75 | 76 | You can control speed by using the `speed()`. Speed will change depending on the size of the http-body data. 77 | 78 | ``` swift 79 | Mock.install().request(url: url).response(200, body: File(fileUrl), header: nil).speed(.Wifi) 80 | ``` 81 | 82 | It supports the following speed. 83 | 84 | ``` swift 85 | public enum Speed { 86 | case Prompt 87 | case Wifi // 45Mbps 88 | case Mobile4G // 10Mbps 89 | case Mobile3G // 1Mbps 90 | case Edge // 200kbps 91 | } 92 | ``` 93 | 94 | ## License 95 | 96 | Kagee is released under the MIT license. See LICENSE for details. 97 | --------------------------------------------------------------------------------