You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2016/02/16 14:15:24 UTC

[32/75] [partial] usergrid git commit: Initial commit of the Swift SDK.

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridUser.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridUser.swift b/sdks/swift/Source/UsergridUser.swift
new file mode 100644
index 0000000..b1eedcc
--- /dev/null
+++ b/sdks/swift/Source/UsergridUser.swift
@@ -0,0 +1,441 @@
+//
+//  User.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 7/21/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/// The completion block used for checking email and/or username availablity for new `UsergridUser` objects.
+public typealias UsergridUserAvailabilityCompletion = (error: UsergridResponseError?, available:Bool) -> Void
+
+/// The completion block used for changing the password of `UsergridUser` objects.
+public typealias UsergridUserResetPasswordCompletion = (error: UsergridResponseError?, didSucceed:Bool) -> Void
+
+/**
+`UsergridUser` is a special subclass of `UsergridEntity` that supports functions and properties unique to users.
+*/
+public class UsergridUser : UsergridEntity {
+
+    static let USER_ENTITY_TYPE = "user"
+
+    // MARK: - Instance Properties -
+
+    /// The `UsergridUserAuth` object if this user was authenticated.
+    public var auth: UsergridUserAuth?
+
+    /** 
+    Property helper method for the `UsergridUser` objects `UsergridUserProperties.Name`.
+    
+    Unlike `UsergridEntity` objects, `UsergridUser`'s can change their name property which is why we provide a getter here.
+    */
+    override public var name: String? {
+        set(name) { self[UsergridUserProperties.Name.stringValue] = name }
+        get{ return super.name }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Username`.
+    public var username: String? {
+        set(username) { self[UsergridUserProperties.Username.stringValue] = username }
+        get { return self.getUserSpecificProperty(.Username) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Password`.
+    public var password: String? {
+        set(password) { self[UsergridUserProperties.Password.stringValue] = password }
+        get { return self.getUserSpecificProperty(.Password) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Email`.
+    public var email: String? {
+        set(email) { self[UsergridUserProperties.Email.stringValue] = email }
+        get { return self.getUserSpecificProperty(.Email) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Age`.
+    public var age: NSNumber? {
+        set(age) { self[UsergridUserProperties.Age.stringValue] = age }
+        get { return self.getUserSpecificProperty(.Age) as? NSNumber }
+    }
+
+    /// Property helper method to get the username or email of the `UsergridUser`.
+    public var usernameOrEmail: String? { return self.username ?? self.email }
+
+    /** 
+    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Activated`.
+    
+    Indicates whether the user account has been activated or not.
+    */
+    public var activated: Bool {
+        set(activated) { self[UsergridUserProperties.Activated.stringValue] = activated }
+        get { return self.getUserSpecificProperty(.Activated) as? Bool ?? false }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Disabled`.
+    public var disabled: Bool {
+        set(disabled) { self[UsergridUserProperties.Disabled.stringValue] = disabled }
+        get { return self.getUserSpecificProperty(.Disabled) as? Bool ?? false }
+    }
+
+    /**
+    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Picture`.
+    
+    URL path to user’s profile picture. Defaults to Gravatar for email address.
+    */
+    public var picture: String? {
+        set(picture) { self[UsergridUserProperties.Picture.stringValue] = picture }
+        get { return self.getUserSpecificProperty(.Picture) as? String }
+    }
+
+    /// The UUID or username property value if found.
+    public var uuidOrUsername: String? { return self.uuid ?? self.username }
+
+    // MARK: - Initialization -
+
+    /**
+    Designated initializer for `UsergridUser` objects.
+
+    - parameter name: The name of the user.  Note this is different from the `username` property.
+
+    - returns: A new instance of `UsergridUser`.
+    */
+    public init(name:String? = nil) {
+        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:nil)
+    }
+
+    /**
+     The required public initializer for `UsergridEntity` subclasses.
+
+     - parameter type:         The type associated with the `UsergridEntity` object.
+     - parameter name:         The optional name associated with the `UsergridEntity` object.
+     - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
+
+     - returns: A new `UsergridUser` object.
+     */
+    required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
+        super.init(type: type, name: name, propertyDict: propertyDict)
+    }
+
+    /**
+    Designated initializer for `UsergridUser` objects.
+
+    - parameter name:         The name of the user.  Note this is different from the `username` property.
+    - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
+
+    - returns: A new instance of `UsergridUser`.
+    */
+    public init(name:String,propertyDict:[String:AnyObject]? = nil) {
+        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:propertyDict)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The name of the user.  Note this is different from the `username` property.
+     - parameter email:    The user's email.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String, email:String, password:String? = nil) {
+        self.init(name:name,email:email,username:nil,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter email:    The user's email.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(email:String, password:String? = nil) {
+        self.init(name:nil,email:email,username:nil,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The name of the user.  Note this is different from the `username` property.
+     - parameter username: The username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String, username:String, password:String? = nil) {
+        self.init(name:name,email:nil,username:username,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter username: The username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(username:String, password:String? = nil) {
+        self.init(name:nil,email:nil,username:username,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The optional name of the user.  Note this is different from the `username` property.
+     - parameter email:    The optional user's email.
+     - parameter username: The optional username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String?, email:String?, username:String?, password:String? = nil) {
+        self.init(name:name)
+        self.email = email
+        self.username = username
+        self.password = password
+    }
+
+    // MARK: - NSCoding -
+
+    /**
+    NSCoding protocol initializer.
+
+    - parameter aDecoder: The decoder.
+
+    - returns: A decoded `UsergridUser` object.
+    */
+    required public init?(coder aDecoder: NSCoder) {
+        self.auth = aDecoder.decodeObjectForKey("auth") as? UsergridUserAuth
+        super.init(coder: aDecoder)
+    }
+
+    /**
+     NSCoding protocol encoder.
+
+     - parameter aCoder: The encoder.
+     */
+    public override func encodeWithCoder(aCoder: NSCoder) {
+        aCoder.encodeObject(self.auth, forKey: "auth")
+        super.encodeWithCoder(aCoder)
+    }
+
+    // MARK: - Class Methods -
+
+    /**
+    Checks the given email and/or username availablity for new `UsergridUser` objects using the shared instance of `UsergridClient`.
+
+    - parameter email:      The optional email address.
+    - parameter username:   The optional username.
+    - parameter completion: The completion block.
+    */
+    public static func checkAvailable(email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
+        self.checkAvailable(Usergrid.sharedInstance, email: email, username: username, completion: completion)
+    }
+
+    /**
+     Checks the given email and/or username availablity for new `UsergridUser` objects using with the given `UsergridClient`.
+
+     - parameter client:     The client to use for checking availability.
+     - parameter email:      The optional email address.
+     - parameter username:   The optional username.
+     - parameter completion: The completion block.
+     */
+    public static func checkAvailable(client: UsergridClient, email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
+        let query = UsergridQuery(USER_ENTITY_TYPE)
+        if let emailValue = email {
+            query.eq(UsergridUserProperties.Email.stringValue, value: emailValue)
+        }
+        if let usernameValue = username {
+            query.or().eq(UsergridUserProperties.Username.stringValue, value: usernameValue)
+        }
+        client.GET(USER_ENTITY_TYPE, query: query) { (response) -> Void in
+            completion(error: response.error, available: response.entity == nil)
+        }
+    }
+
+    // MARK: - Instance Methods -
+
+    /**
+    Creates the user object in Usergrid if the user does not already exist with the shared instance of `UsergridClient`.
+
+    - parameter completion: The optional completion block.
+    */
+    public func create(completion: UsergridResponseCompletion? = nil) {
+        self.create(Usergrid.sharedInstance, completion: completion)
+    }
+
+    /**
+    Creates the user object in Usergrid if the user does not already exist with the given `UsergridClient`.
+
+    - parameter client:     The client to use for creation.
+    - parameter completion: The optional completion block.
+    */
+    public func create(client: UsergridClient, completion: UsergridResponseCompletion? = nil) {
+        client.POST(self,completion:completion)
+    }
+
+    /**
+    Authenticates the specified user using the provided username and password with the shared instance of `UsergridClient`.
+
+    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
+
+    - parameter username:   The username.
+    - parameter password:   The password.
+    - parameter completion: The optional completion block.
+    */
+    public func login(username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
+        self.login(Usergrid.sharedInstance, username: username, password: password, completion: completion)
+    }
+
+    /**
+    Authenticates the specified user using the provided username and password.
+
+    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
+
+    - parameter client:     The client to use for login.
+    - parameter username:   The username.
+    - parameter password:   The password.
+    - parameter completion: The optional completion block.
+    */
+    public func login(client: UsergridClient, username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
+        let userAuth = UsergridUserAuth(username: username, password: password)
+        client.authenticateUser(userAuth,setAsCurrentUser:false) { [weak self] (auth, user, error) -> Void in
+            self?.auth = userAuth
+            completion?(auth: userAuth, user: user, error: error)
+        }
+    }
+
+     /**
+     Changes the User's current password with the shared instance of `UsergridClient`.
+
+     - parameter old:        The old password.
+     - parameter new:        The new password.
+     - parameter completion: The optional completion block.
+     */
+    public func resetPassword(old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
+        self.resetPassword(Usergrid.sharedInstance, old: old, new: new, completion: completion)
+    }
+
+    /**
+     Changes the User's current password with the shared instance of `UsergridClient`.
+
+     - parameter client:     The client to use for resetting the password.
+     - parameter old:        The old password.
+     - parameter new:        The new password.
+     - parameter completion: The optional completion block
+     */
+    public func resetPassword(client: UsergridClient, old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
+        client.resetPassword(self, old: old, new: new, completion: completion)
+    }
+
+    /**
+     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property with the shared instance of `UsergridClient`.
+
+     - parameter completion: The optional completion block.
+     */
+    public func reauthenticate(completion: UsergridUserAuthCompletionBlock? = nil) {
+        self.reauthenticate(Usergrid.sharedInstance, completion: completion)
+    }
+
+    /**
+     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property.
+
+     - parameter client:     The client to use for reauthentication.
+     - parameter completion: The optional completion block.
+     */
+    public func reauthenticate(client: UsergridClient, completion: UsergridUserAuthCompletionBlock? = nil) {
+        if let userAuth = self.auth {
+            client.authenticateUser(userAuth, completion: completion)
+        } else {
+            let error = UsergridResponseError(errorName: "Invalid UsergridUserAuth.", errorDescription: "No UsergridUserAuth found on the UsergridUser.")
+            completion?(auth: nil, user: self, error: error)
+        }
+    }
+
+    /**
+    Invalidates the user token locally and remotely.
+
+    - parameter completion: The optional completion block.
+    */
+    public func logout(completion:UsergridResponseCompletion? = nil) {
+        self.logout(Usergrid.sharedInstance,completion:completion)
+    }
+
+    /**
+    Invalidates the user token locally and remotely.
+
+    - parameter client:     The client to use for logout.
+    - parameter completion: The optional completion block.
+    */
+    public func logout(client: UsergridClient, completion:UsergridResponseCompletion? = nil) {
+        if self === client.currentUser {
+            client.logoutCurrentUser(completion)
+        } else if let uuidOrUsername = self.uuidOrUsername, accessToken = self.auth?.accessToken {
+            client.logoutUser(uuidOrUsername, token: accessToken) { (response) in
+                self.auth = nil
+                completion?(response: response)
+            }
+        } else {
+            completion?(response: UsergridResponse(client:client, errorName:"Logout Failed.", errorDescription:"UUID or Access Token not found on UsergridUser object."))
+        }
+    }
+
+    private func getUserSpecificProperty(userProperty: UsergridUserProperties) -> AnyObject? {
+        var propertyValue: AnyObject? = super[userProperty.stringValue]
+        NSJSONReadingOptions.AllowFragments
+        switch userProperty {
+            case .Activated,.Disabled :
+                propertyValue = propertyValue?.boolValue
+            case .Age :
+                propertyValue = propertyValue?.integerValue
+            case .Name,.Username,.Password,.Email,.Picture :
+                break
+        }
+        return propertyValue
+    }
+
+    /**
+    Subscript for the `UsergridUser` class.
+
+    - Warning: When setting a properties value must be a valid JSON object.
+
+    - Example usage:
+    ```
+    let someName = usergridUser["name"]
+    
+    usergridUser["name"] = someName
+    ```
+    */
+    override public subscript(propertyName: String) -> AnyObject? {
+        get {
+            if let userProperty = UsergridUserProperties.fromString(propertyName) {
+                return self.getUserSpecificProperty(userProperty)
+            } else {
+                return super[propertyName]
+            }
+        }
+        set(propertyValue) {
+            super[propertyName] = propertyValue
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/ASSET_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/ASSET_Tests.swift b/sdks/swift/Tests/ASSET_Tests.swift
new file mode 100644
index 0000000..23c9316
--- /dev/null
+++ b/sdks/swift/Tests/ASSET_Tests.swift
@@ -0,0 +1,82 @@
+//
+//  ASSET_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/24/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class ASSET_Tests: XCTestCase {
+
+    let sharedClient = Usergrid.initSharedInstance(orgId:ClientCreationTests.orgId, appId: ClientCreationTests.appId)
+
+    static let collectionName = "books"
+    static let entityUUID = "f4078aca-2fb1-11e5-8eb2-e13f8369aad1"
+    static let imageLocation = "TestAssets/test.png"
+    static let imageName = "test"
+
+    func getFullPathOfFile(fileLocation:String) -> String {
+        return (NSBundle(forClass: object_getClass(self)).resourcePath! as NSString).stringByAppendingPathComponent(fileLocation)
+    }
+
+    func test_IMAGE_UPLOAD() {
+        let getExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        let uploadProgress : UsergridAssetRequestProgress = { (bytes,expected) in
+            print("UPLOAD PROGRESS BLOCK: BYTES:\(bytes) --- EXPECTED:\(expected)")
+        }
+        let downloadProgress : UsergridAssetRequestProgress = { (bytes,expected) in
+            print("DOWNLOAD PROGRESS BLOCK: BYTES:\(bytes) --- EXPECTED:\(expected)")
+        }
+
+        Usergrid.GET(ASSET_Tests.collectionName, uuidOrName:ASSET_Tests.entityUUID) { (response) in
+            let entity = response.first!
+            XCTAssertNotNil(entity)
+
+            let imagePath = self.getFullPathOfFile(ASSET_Tests.imageLocation)
+            XCTAssertNotNil(imagePath)
+
+            let localImage = UIImage(contentsOfFile: imagePath)
+            XCTAssertNotNil(localImage)
+
+            let asset = UsergridAsset(fileName:ASSET_Tests.imageName,image: localImage!)
+            XCTAssertNotNil(asset)
+
+            entity.uploadAsset(self.sharedClient, asset:asset!, progress:uploadProgress) { (response, uploadedAsset, error) -> Void in
+                XCTAssertNotNil(asset)
+                XCTAssertNil(error)
+                XCTAssertTrue(response.ok)
+                entity.downloadAsset(UsergridImageContentType.Png.stringValue, progress:downloadProgress)
+                { (downloadedAsset, error) -> Void in
+                    XCTAssertNotNil(downloadedAsset)
+                    XCTAssertNil(error)
+                    let downloadedImage = UIImage(data: downloadedAsset!.data)
+                    XCTAssertEqual(UIImagePNGRepresentation(localImage!), UIImagePNGRepresentation(downloadedImage!))
+                    XCTAssertNotNil(downloadedImage)
+                    getExpect.fulfill()
+                }
+            }
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/AUTH_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/AUTH_Tests.swift b/sdks/swift/Tests/AUTH_Tests.swift
new file mode 100644
index 0000000..16ba598
--- /dev/null
+++ b/sdks/swift/Tests/AUTH_Tests.swift
@@ -0,0 +1,65 @@
+//
+//  AUTH_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/17/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class AUTH_Tests: XCTestCase {
+
+    let testAuthClient = UsergridClient(orgId: ClientCreationTests.orgId, appId: "sdk.demo")
+    let clientAuth = UsergridAppAuth(clientId: "b3U6THNcevskEeOQZLcUROUUVA", clientSecret: "b3U6RZHYznP28xieBzQPackFPmmnevU")
+    private static let collectionName = "publicevent"
+    private static let entityUUID = "fa015eaa-fe1c-11e3-b94b-63b29addea01"
+
+    func test_CLIENT_AUTH() {
+
+        let authExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        testAuthClient.authenticateApp(clientAuth) { [weak self] (auth,error) in
+
+            XCTAssertNil(error)
+            XCTAssertNotNil(self?.testAuthClient.appAuth)
+
+            if let appAuth = self?.testAuthClient.appAuth {
+
+                XCTAssertNotNil(appAuth.accessToken)
+                XCTAssertNotNil(appAuth.expiry)
+
+                self?.testAuthClient.GET(AUTH_Tests.collectionName) { (response) in
+
+                    XCTAssertNotNil(response)
+                    XCTAssertTrue(response.hasNextPage)
+                    XCTAssertEqual(response.entities!.count, 10)
+                    XCTAssertEqual(response.first!.type, AUTH_Tests.collectionName)
+                    
+                    authExpect.fulfill()
+                }
+            } else {
+                authExpect.fulfill()
+            }
+        }
+        self.waitForExpectationsWithTimeout(20, handler: nil)
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/CONNECTION_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/CONNECTION_Tests.swift b/sdks/swift/Tests/CONNECTION_Tests.swift
new file mode 100644
index 0000000..e82e0bd
--- /dev/null
+++ b/sdks/swift/Tests/CONNECTION_Tests.swift
@@ -0,0 +1,86 @@
+//
+//  CONNECTION_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 10/5/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class CONNECTION_Tests: XCTestCase {
+
+    let testAuthClient = UsergridClient(orgId:ClientCreationTests.orgId, appId: "sdk.demo")
+    let clientAuth = UsergridAppAuth(clientId: "b3U6THNcevskEeOQZLcUROUUVA", clientSecret: "b3U6RZHYznP28xieBzQPackFPmmnevU")
+    private static let collectionName = "publicevent"
+
+    func test_CLIENT_AUTH() {
+
+        let authExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        testAuthClient.authenticateApp(clientAuth) { [weak self] (auth,error) in
+            XCTAssertNil(error)
+            XCTAssertNotNil(self?.testAuthClient.appAuth)
+
+            if let appAuth = self?.testAuthClient.appAuth {
+
+                XCTAssertNotNil(appAuth.accessToken)
+                XCTAssertNotNil(appAuth.expiry)
+
+                self?.testAuthClient.GET(CONNECTION_Tests.collectionName) { (response) in
+
+                    XCTAssertNotNil(response)
+                    XCTAssertTrue(response.ok)
+                    XCTAssertTrue(response.hasNextPage)
+                    XCTAssertEqual(response.entities!.count, 10)
+
+                    let entity = response.first!
+                    let entityToConnect = response.entities![1]
+                    XCTAssertEqual(entity.type, CONNECTION_Tests.collectionName)
+
+                    entity.connect(self!.testAuthClient,relationship:"likes", toEntity: entityToConnect) { (response) -> Void in
+                        XCTAssertNotNil(response)
+                        XCTAssertTrue(response.ok)
+                        entity.getConnections(self!.testAuthClient, direction:.Out, relationship: "likes", query:nil) { (response) -> Void in
+                            XCTAssertNotNil(response)
+                            XCTAssertTrue(response.ok)
+                            let connectedEntity = response.first!
+                            XCTAssertNotNil(connectedEntity)
+                            XCTAssertEqual(connectedEntity.uuidOrName, entityToConnect.uuidOrName)
+                            entity.disconnect(self!.testAuthClient, relationship: "likes", fromEntity: connectedEntity) { (response) -> Void in
+                                XCTAssertNotNil(response)
+                                XCTAssertTrue(response.ok)
+                                entity.getConnections(self!.testAuthClient, direction:.Out, relationship: "likes", query:nil) { (response) -> Void in
+                                    XCTAssertNotNil(response)
+                                    XCTAssertTrue(response.ok)
+                                    authExpect.fulfill()
+                                }
+                            }
+                        }
+                    }
+                }
+            } else {
+                authExpect.fulfill()
+            }
+        }
+        self.waitForExpectationsWithTimeout(20, handler: nil)
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/ClientCreationTests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/ClientCreationTests.swift b/sdks/swift/Tests/ClientCreationTests.swift
new file mode 100644
index 0000000..4c673c7
--- /dev/null
+++ b/sdks/swift/Tests/ClientCreationTests.swift
@@ -0,0 +1,92 @@
+//
+//  ClientCreationTests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 7/31/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class ClientCreationTests: XCTestCase {
+
+    static let orgId = "rwalsh"
+    static let appId = "sandbox"
+
+    static let otherInstanceID = "otherInstanceID"
+    static let otherAppID = "otherAppID"
+    static let otherOrgID = "otherOrgID"
+    static let otherBaseURL = "http://www.something.com"
+    static let otherAppAuth = UsergridAppAuth(clientId: "alkdjflsdf", clientSecret: "alkdjflsdf")
+
+    static let otherConfiguration = UsergridClientConfig(orgId: ClientCreationTests.otherOrgID,
+                                                         appId: ClientCreationTests.otherAppID,
+                                                         baseUrl: ClientCreationTests.otherBaseURL,
+                                                         authFallback: .None,
+                                                         appAuth: ClientCreationTests.otherAppAuth)
+
+    let otherClient = UsergridClient(configuration: ClientCreationTests.otherConfiguration)
+
+    override func setUp() {
+        super.setUp()
+        Usergrid.initSharedInstance(orgId:ClientCreationTests.orgId, appId: ClientCreationTests.appId)
+    }
+
+    override func tearDown() {
+        Usergrid._sharedClient = nil
+        super.tearDown()
+    }
+
+    func test_INSTANCE_POINTERS() {
+        XCTAssertNotNil(Usergrid.sharedInstance)
+        XCTAssertNotNil(otherClient)
+        XCTAssertFalse(otherClient === Usergrid.sharedInstance)
+    }
+
+    func test_CLIENT_PROPERTIES() {
+        XCTAssertEqual(Usergrid.sharedInstance.appId, ClientCreationTests.appId)
+        XCTAssertEqual(Usergrid.sharedInstance.orgId, ClientCreationTests.orgId)
+        XCTAssertEqual(Usergrid.sharedInstance.authFallback, UsergridAuthFallback.App)
+        XCTAssertEqual(Usergrid.sharedInstance.baseUrl, UsergridClient.DEFAULT_BASE_URL)
+        XCTAssertNil(Usergrid.sharedInstance.currentUser)
+
+        XCTAssertEqual(otherClient.appId, ClientCreationTests.otherAppID)
+        XCTAssertEqual(otherClient.orgId, ClientCreationTests.otherOrgID)
+        XCTAssertEqual(otherClient.authFallback, UsergridAuthFallback.None)
+        XCTAssertEqual(otherClient.baseUrl, ClientCreationTests.otherBaseURL)
+        XCTAssertNil(otherClient.currentUser)
+    }
+
+    func test_CLIENT_NSCODING() {
+        let sharedInstanceAsData = NSKeyedArchiver.archivedDataWithRootObject(Usergrid.sharedInstance)
+        let newInstanceFromData = NSKeyedUnarchiver.unarchiveObjectWithData(sharedInstanceAsData) as? UsergridClient
+
+        XCTAssertNotNil(newInstanceFromData)
+
+        if let newInstance = newInstanceFromData {
+            XCTAssertEqual(Usergrid.sharedInstance.appId, newInstance.appId)
+            XCTAssertEqual(Usergrid.sharedInstance.orgId, newInstance.orgId)
+            XCTAssertEqual(Usergrid.sharedInstance.authFallback, newInstance.authFallback)
+            XCTAssertEqual(Usergrid.sharedInstance.baseUrl, newInstance.baseUrl)
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/Entity_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/Entity_Tests.swift b/sdks/swift/Tests/Entity_Tests.swift
new file mode 100644
index 0000000..439b67d
--- /dev/null
+++ b/sdks/swift/Tests/Entity_Tests.swift
@@ -0,0 +1,173 @@
+//
+//  Entity_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/22/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class Entity_Tests: XCTestCase {
+
+    let entity = UsergridEntity(type: "entityType", name:"entityName")
+    let customArrayName = "customArray"
+    let customArrayOriginalValue = [1,2,3,4,5]
+    let customPropertyName = "customProperty"
+    let customPropertyValue = 99
+
+    func test_PUT_PROPERTY() {
+
+        entity.putProperty(customArrayName, value: customArrayOriginalValue)
+
+        let propertyValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(propertyValue)
+        XCTAssertEqual(propertyValue!, customArrayOriginalValue)
+    }
+    func test_PUT_PROPERTIES() {
+
+        entity.putProperties([customArrayName:customArrayOriginalValue])
+
+        let propertyValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(propertyValue)
+        XCTAssertEqual(propertyValue!, customArrayOriginalValue)
+    }
+    func test_REMOVE_PROPERTY() {
+        entity[customArrayName] = customArrayOriginalValue
+        let propertyValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(propertyValue)
+
+        entity.removeProperty(customArrayName)
+
+        XCTAssertNil(entity[customArrayName])
+    }
+    func test_REMOVE_PROPERTIES() {
+        entity[customArrayName] = customArrayOriginalValue
+        let propertyValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(propertyValue)
+
+        entity.removeProperties([customArrayName])
+
+        XCTAssertNil(entity[customArrayName])
+    }
+    func test_PUSH() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.append(customArrayName,value:6)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,2,3,4,5,6])
+    }
+    func test_APPEND() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.append(customArrayName,value:[6,7])
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,2,3,4,5,6,7])
+    }
+    func test_INSERT_WITHOUT_INDEX() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.insert(customArrayName,value:6)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [6,1,2,3,4,5])
+    }
+    func test_INSERT_WITH_INDEX() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.insert(customArrayName,value:6,index:1)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,6,2,3,4,5])
+    }
+    func test_INSERT_ARRAY_WITHOUT_INDEX() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.insert(customArrayName,value:[6,7])
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [6,7,1,2,3,4,5])
+    }
+
+    func test_INSERT_ARRAY_WITH_INDEX() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.insert(customArrayName,value:[6,7],index:1)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,6,7,2,3,4,5])
+    }
+
+    func test_INSERT_ARRAY_TO_NON_EXISTENT_PROPERTY() {
+        entity.insert(customArrayName,value:customArrayOriginalValue)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,2,3,4,5])
+    }
+
+    func test_INSERT_ARRAY_TO_NON_ARRAY_PROPERTY_WITHOUT_INDEX() {
+        entity[customPropertyName] = customPropertyValue
+
+        entity.insert(customPropertyName,value:customArrayOriginalValue)
+
+        let newValue = entity[customPropertyName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,2,3,4,5,99])
+    }
+
+    func test_INSERT_ARRAY_TO_NON_ARRAY_PROPERTY_WITH_INDEX() {
+        entity[customPropertyName] = customPropertyValue
+
+        entity.insert(customPropertyName,value:customArrayOriginalValue,index:1)
+
+        let newValue = entity[customPropertyName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [99,1,2,3,4,5])
+    }
+    func test_POP() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.pop(customArrayName)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [1,2,3,4])
+    }
+    func test_SHIFT() {
+        entity[customArrayName] = customArrayOriginalValue
+
+        entity.shift(customArrayName)
+
+        let newValue = entity[customArrayName] as? [Int]
+        XCTAssertNotNil(newValue)
+        XCTAssertEqual(newValue!, [2,3,4,5])
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/GET_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/GET_Tests.swift b/sdks/swift/Tests/GET_Tests.swift
new file mode 100644
index 0000000..dfae0d4
--- /dev/null
+++ b/sdks/swift/Tests/GET_Tests.swift
@@ -0,0 +1,104 @@
+//
+//  GET_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/2/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class GET_Tests: XCTestCase {
+
+    let usergridClientInstance = UsergridClient(orgId:ClientCreationTests.orgId, appId: ClientCreationTests.appId)
+
+    static let collectionName = "books"
+    static let entityUUID = "f4078aca-2fb1-11e5-8eb2-e13f8369aad1"
+
+    let query = UsergridQuery(GET_Tests.collectionName)
+        .eq("title", value: "The Sun Also Rises")
+        .or()
+        .eq("title", value: "The Old Man and the Sea")
+
+
+    func test_GET_WITHOUT_QUERY() {
+
+        let getExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        usergridClientInstance.GET(GET_Tests.collectionName) { (response) in
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            XCTAssertTrue(response.hasNextPage)
+            XCTAssertEqual(response.count, 10)
+            getExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+
+    func test_GET_WITH_QUERY() {
+
+        let getExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        usergridClientInstance.GET(GET_Tests.collectionName, query:self.query) { (response) in
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            XCTAssertEqual(response.count, 3)
+            getExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+
+    func test_GET_WITH_UUID() {
+
+        let getExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        usergridClientInstance.GET(GET_Tests.collectionName, uuidOrName:GET_Tests.entityUUID) { (response) in
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            let entity = response.first!
+            XCTAssertFalse(response.hasNextPage)
+            XCTAssertEqual(response.count, 1)
+            XCTAssertNotNil(entity)
+            XCTAssertEqual(entity.uuid!, GET_Tests.entityUUID)
+            getExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+
+    func test_GET_NEXT_PAGE_WITH_NO_QUERY() {
+
+        let getExpect = self.expectationWithDescription("\(__FUNCTION__)")
+        usergridClientInstance.GET(GET_Tests.collectionName) { (response) in
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            XCTAssertTrue(response.hasNextPage)
+            XCTAssertEqual(response.count, 10)
+
+            response.loadNextPage() { (nextPageResponse) in
+                XCTAssertTrue(nextPageResponse.ok)
+                XCTAssertNotNil(nextPageResponse)
+                XCTAssertFalse(nextPageResponse.hasNextPage)
+                XCTAssertEqual(nextPageResponse.entities!.count, 6)
+                getExpect.fulfill()
+            }
+        }
+        self.waitForExpectationsWithTimeout(20, handler: nil)
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/Info.plist
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/Info.plist b/sdks/swift/Tests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/sdks/swift/Tests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/PUT_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/PUT_Tests.swift b/sdks/swift/Tests/PUT_Tests.swift
new file mode 100644
index 0000000..26f3260
--- /dev/null
+++ b/sdks/swift/Tests/PUT_Tests.swift
@@ -0,0 +1,146 @@
+//
+//  PUT_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/11/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class PUT_Tests: XCTestCase {
+
+    let client = UsergridClient(orgId:ClientCreationTests.orgId, appId: ClientCreationTests.appId)
+
+    let query = UsergridQuery(PUT_Tests.collectionName)
+        .eq("title", value: "The Sun Also Rises")
+        .or()
+        .eq("title", value: "The Old Man and the Sea")
+
+    static let collectionName = "books"
+    static let entityUUID = "f4078aca-2fb1-11e5-8eb2-e13f8369aad1"
+
+    func test_PUT_BY_SPECIFYING_UUID_AS_PARAMETER() {
+
+        let propertyNameToUpdate = "\(__FUNCTION__)"
+        let propertiesNewValue = "\(propertyNameToUpdate)_VALUE"
+        let putExpect = self.expectationWithDescription(propertyNameToUpdate)
+
+        client.PUT(PUT_Tests.collectionName, uuidOrName: PUT_Tests.entityUUID, jsonBody:[propertyNameToUpdate : propertiesNewValue]) { (response) in
+
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            XCTAssertEqual(response.entities!.count, 1)
+            let entity = response.first!
+
+            XCTAssertNotNil(entity)
+            XCTAssertEqual(entity.uuid!, PUT_Tests.entityUUID)
+
+            let updatedPropertyValue = entity[propertyNameToUpdate] as? String
+            XCTAssertNotNil(updatedPropertyValue)
+            XCTAssertEqual(updatedPropertyValue!,propertiesNewValue)
+            putExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+
+    func test_PUT_BY_SPECIFYING_UUID_WITHIN_JSON_BODY() {
+
+        let propertyNameToUpdate = "\(__FUNCTION__)"
+        let propertiesNewValue = "\(propertyNameToUpdate)_VALUE"
+        let putExpect = self.expectationWithDescription(propertyNameToUpdate)
+
+        let jsonDictToPut = [UsergridEntityProperties.UUID.stringValue : PUT_Tests.entityUUID, propertyNameToUpdate : propertiesNewValue]
+
+        client.PUT(PUT_Tests.collectionName, jsonBody: jsonDictToPut) { (response) in
+            XCTAssertNotNil(response)
+            XCTAssertTrue(response.ok)
+            XCTAssertEqual(response.entities!.count, 1)
+            let entity = response.first!
+
+            XCTAssertNotNil(entity)
+            XCTAssertEqual(entity.uuid!, PUT_Tests.entityUUID)
+
+            let updatedPropertyValue = entity[propertyNameToUpdate] as? String
+            XCTAssertNotNil(updatedPropertyValue)
+            XCTAssertEqual(updatedPropertyValue!,propertiesNewValue)
+            putExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+
+    func test_PUT_WITH_ENTITY_OBJECT() {
+        let propertyNameToUpdate = "\(__FUNCTION__)"
+        let propertiesNewValue = "\(propertyNameToUpdate)_VALUE"
+        let putExpect = self.expectationWithDescription(propertyNameToUpdate)
+
+        client.GET(PUT_Tests.collectionName, uuidOrName: PUT_Tests.entityUUID) { (getResponse) in
+            XCTAssertNotNil(getResponse)
+            XCTAssertTrue(getResponse.ok)
+            XCTAssertEqual(getResponse.entities!.count, 1)
+
+            var responseEntity = getResponse.first!
+
+            XCTAssertNotNil(responseEntity)
+            XCTAssertEqual(responseEntity.uuid!, PUT_Tests.entityUUID)
+
+            responseEntity[propertyNameToUpdate] = propertiesNewValue
+
+            self.client.PUT(responseEntity) { (putResponse) in
+                XCTAssertNotNil(putResponse)
+                XCTAssertTrue(putResponse.ok)
+                XCTAssertEqual(putResponse.entities!.count, 1)
+                responseEntity = putResponse.first!
+
+                XCTAssertNotNil(responseEntity)
+                XCTAssertEqual(responseEntity.uuid!, PUT_Tests.entityUUID)
+
+                let updatedPropertyValue = responseEntity[propertyNameToUpdate] as? String
+                XCTAssertNotNil(updatedPropertyValue)
+                XCTAssertEqual(updatedPropertyValue!,propertiesNewValue)
+                putExpect.fulfill()
+            }
+        }
+        self.waitForExpectationsWithTimeout(20, handler: nil)
+    }
+
+    func test_PUT_WITH_QUERY() {
+        let propertyNameToUpdate = "\(__FUNCTION__)"
+        let propertiesNewValue = "\(propertyNameToUpdate)_VALUE"
+        let putExpect = self.expectationWithDescription(propertyNameToUpdate)
+
+        client.PUT(self.query, jsonBody: [propertyNameToUpdate : propertiesNewValue]) { (putResponse) in
+            XCTAssertNotNil(putResponse)
+            XCTAssertTrue(putResponse.ok)
+            XCTAssertEqual(putResponse.entities!.count, 3)
+
+            let responseEntity = putResponse.first!
+            XCTAssertNotNil(responseEntity)
+
+            let updatedPropertyValue = responseEntity[propertyNameToUpdate] as? String
+            XCTAssertNotNil(updatedPropertyValue)
+            XCTAssertEqual(updatedPropertyValue!,propertiesNewValue)
+            putExpect.fulfill()
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/TestAssets/logo_apigee.png
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/TestAssets/logo_apigee.png b/sdks/swift/Tests/TestAssets/logo_apigee.png
new file mode 100644
index 0000000..5113800
Binary files /dev/null and b/sdks/swift/Tests/TestAssets/logo_apigee.png differ

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/TestAssets/test.png
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/TestAssets/test.png b/sdks/swift/Tests/TestAssets/test.png
new file mode 100644
index 0000000..4b13eaa
Binary files /dev/null and b/sdks/swift/Tests/TestAssets/test.png differ

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Tests/User_Tests.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Tests/User_Tests.swift b/sdks/swift/Tests/User_Tests.swift
new file mode 100644
index 0000000..2b1a504
--- /dev/null
+++ b/sdks/swift/Tests/User_Tests.swift
@@ -0,0 +1,121 @@
+//
+//  User_Tests.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 9/14/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import XCTest
+@testable import UsergridSDK
+
+class User_Tests: XCTestCase {
+
+    var client = UsergridClient(orgId:ClientCreationTests.orgId, appId: ClientCreationTests.appId)
+
+    let userWithNoName = UsergridUser()
+    let user = UsergridUser(name:User_Tests.name, email:User_Tests.email, username:User_Tests.username, password:User_Tests.password)
+
+    static let name = "Robert Walsh"
+    static let age = 29
+    static let email = "handsomeRob741@yahoo.com"
+    static let username = "rwalsh"
+    static let password = "password"
+    static let picture = "http://www.gravatar.com/avatar/e466d447df831ddce35fbc50763fb03a"
+    static let activated = true
+    static let disabled = false
+
+    override func setUp() {
+        super.setUp()
+        user.age = User_Tests.age
+        user.picture = User_Tests.picture
+        user.activated = User_Tests.activated
+        user.disabled = User_Tests.disabled
+    }
+
+    func test_USERS_AND_PROPERTIES_NOT_NIL() {
+        XCTAssertNotNil(user)
+        XCTAssertNotNil(user.name)
+        XCTAssertNotNil(user.age)
+        XCTAssertNotNil(user.username)
+        XCTAssertNotNil(user.email)
+        XCTAssertNotNil(user.password)
+        XCTAssertNotNil(user.picture)
+        XCTAssertNotNil(user.activated)
+        XCTAssertNotNil(user.disabled)
+
+        XCTAssertNotNil(userWithNoName)
+        XCTAssertNil(userWithNoName.name)
+    }
+
+    func test_USER_PROPERTIES_WITH_HELPERS() {
+        XCTAssertEqual(user.name!, User_Tests.name)
+        XCTAssertEqual(user.age!, User_Tests.age)
+        XCTAssertEqual(user.username!, User_Tests.username)
+        XCTAssertEqual(user.email!, User_Tests.email)
+        XCTAssertEqual(user.password!, User_Tests.password)
+        XCTAssertEqual(user.picture!, User_Tests.picture)
+        XCTAssertTrue(user.activated)
+        XCTAssertFalse(user.disabled)
+    }
+
+    func test_USER_PROPERTIES_WITHOUT_HELPERS() {
+        XCTAssertEqual(user[UsergridUserProperties.Name.stringValue]! as? String, User_Tests.name)
+        XCTAssertEqual(user[UsergridUserProperties.Age.stringValue]! as? Int, User_Tests.age)
+        XCTAssertEqual(user[UsergridUserProperties.Username.stringValue]! as? String, User_Tests.username)
+        XCTAssertEqual(user[UsergridUserProperties.Email.stringValue]! as? String, User_Tests.email)
+        XCTAssertEqual(user[UsergridUserProperties.Password.stringValue]! as? String, User_Tests.password)
+        XCTAssertEqual(user[UsergridUserProperties.Picture.stringValue]! as? String, User_Tests.picture)
+        XCTAssertTrue(user[UsergridUserProperties.Activated.stringValue]! as! Bool)
+        XCTAssertFalse(user[UsergridUserProperties.Disabled.stringValue]! as! Bool)
+    }
+
+    func test_CREATE_AND_DELETE_USER() {
+        let createUserExpect = self.expectationWithDescription("\(__FUNCTION__)")
+
+        user.create(client) { (createResponse) in
+            XCTAssertNotNil(createResponse)
+            XCTAssertTrue(createResponse.ok)
+            XCTAssertNotNil(createResponse.user)
+            XCTAssertNotNil(createResponse.users)
+
+            if let createdUser = createResponse.user {
+                XCTAssertNotNil(createdUser.uuid)
+                XCTAssertEqual(createdUser.name!, User_Tests.name)
+                XCTAssertEqual(createdUser.age!, User_Tests.age)
+                XCTAssertEqual(createdUser.username!, User_Tests.username)
+                XCTAssertEqual(createdUser.email!, User_Tests.email)
+                XCTAssertEqual(createdUser.picture!, User_Tests.picture)
+                XCTAssertTrue(createdUser.activated)
+                XCTAssertFalse(createdUser.disabled)
+
+                createdUser.remove(self.client) { (removeResponse) in
+                    XCTAssertNotNil(removeResponse)
+                    XCTAssertTrue(removeResponse.ok)
+                    XCTAssertNotNil(removeResponse.user)
+                    XCTAssertNotNil(removeResponse.users)
+                    createUserExpect.fulfill()
+                }
+            }
+        }
+        self.waitForExpectationsWithTimeout(10, handler: nil)
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/UsergridSDK.podspec
----------------------------------------------------------------------
diff --git a/sdks/swift/UsergridSDK.podspec b/sdks/swift/UsergridSDK.podspec
new file mode 100644
index 0000000..a4ee606
--- /dev/null
+++ b/sdks/swift/UsergridSDK.podspec
@@ -0,0 +1,18 @@
+Pod::Spec.new do |s|
+  s.name = 'UsergridSDK'
+  s.version = '2.1.0'
+  s.summary = 'Usergrid SDK written in Swift'
+  s.homepage = 'https://github.com/apache/usergrid/tree/master/sdks/swift'
+  s.license = 'Apache 2.0'
+  s.author = { 'Robert Walsh' => 'rjwalsh1985@gmail.com' }
+  s.social_media_url = 'https://twitter.com/usergrid'
+  s.requires_arc = true
+
+  s.ios.deployment_target = '8.0'
+  s.watchos.deployment_target = '2.1'
+  s.tvos.deployment_target = '9.1'
+  s.osx.deployment_target = '10.11'
+
+  s.source = { :git => 'https://github.com/apache/usergrid.git', :branch => 'master' }
+  s.source_files  = 'sdks/swift/Source/*.swift'
+end