diff --git a/Sources/HTTPTransition.swift b/Sources/HTTPTransition.swift index da1a7a2..1b98bee 100644 --- a/Sources/HTTPTransition.swift +++ b/Sources/HTTPTransition.swift @@ -46,6 +46,16 @@ public struct HTTPTransition : TransitionType { public var hashValue:Int { return uri.hashValue } + + public var isIdempotent: Bool { + let nonIdempotent = ["POST", "PATCH"] + return !nonIdempotent.contains(method) + } + + public var isSafe: Bool { + let safe = ["GET", "OPTIONS", "HEAD"] + return safe.contains(method) + } } public func ==(lhs:HTTPTransition, rhs:HTTPTransition) -> Bool { diff --git a/Tests/HTTPTransitionTests.swift b/Tests/HTTPTransitionTests.swift index d7a69ed..917136f 100644 --- a/Tests/HTTPTransitionTests.swift +++ b/Tests/HTTPTransitionTests.swift @@ -72,4 +72,106 @@ class HTTPTransitionTests : XCTestCase { let transition2 = HTTPTransition(uri:"/self/") XCTAssertEqual(transition1.hashValue, transition2.hashValue) } + + // MARK: Idempotency + + func testGETMethodIsIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "GET" + + XCTAssertTrue(transition.isIdempotent) + } + + func testOPTIONSMethodIsIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "OPTIONS" + + XCTAssertTrue(transition.isIdempotent) + } + + func testHEADMethodIsIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "HEAD" + + XCTAssertTrue(transition.isIdempotent) + } + + func testPUTMethodIsIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "PUT" + + XCTAssertTrue(transition.isIdempotent) + } + + func testDELETEMethodIsIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "DELETE" + + XCTAssertTrue(transition.isIdempotent) + } + + func testPOSTMethodIsNotIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "POST" + + XCTAssertFalse(transition.isIdempotent) + } + + func testPATCHMethodIsNotIdempotent() { + var transition = HTTPTransition(uri: "/") + transition.method = "PATCH" + + XCTAssertFalse(transition.isIdempotent) + } + + // MARK: Safe + + func testGETMethodIsSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "GET" + + XCTAssertTrue(transition.isSafe) + } + + func testOPTIONSMethodIsSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "OPTIONS" + + XCTAssertTrue(transition.isSafe) + } + + func testHEADMethodIsSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "HEAD" + + XCTAssertTrue(transition.isSafe) + } + + func testPUTMethodIsNotSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "PUT" + + XCTAssertFalse(transition.isSafe) + } + + func testDELETEMethodIsNotSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "DELETE" + + XCTAssertFalse(transition.isSafe) + } + + func testPOSTMethodIsNotSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "POST" + + XCTAssertFalse(transition.isSafe) + } + + func testPATCHMethodIsNotSafe() { + var transition = HTTPTransition(uri: "/") + transition.method = "PATCH" + + XCTAssertFalse(transition.isSafe) + } }