Skip to content
This repository has been archived by the owner on Apr 20, 2024. It is now read-only.

Commit

Permalink
Added tests and updated README.
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettRToomey committed Jan 10, 2017
1 parent 46505e1 commit 663d3c7
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 5 deletions.
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,63 @@
# sanitized
Safely create Vapor models from requests.
[![Language](https://img.shields.io/badge/Swift-3-brightgreen.svg)](http://swift.org)
[![Build Status](https://travis-ci.org/nodes-vapor/sanitized.svg?branch=master)](https://travis-ci.org/nodes-vapor/sanitized)
[![codecov](https://codecov.io/gh/nodes-vapor/sanitized/branch/master/graph/badge.svg)](https://codecov.io/gh/nodes-vapor/sanitized)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nodes-vapor/sanitized/master/LICENSE)

Safely extract Vapor models from requests.

## Integration
Update your `Package.swift` file.
```swift
.Package(url: "https://github.com/nodes-vapor/sanitized", majorVersion: 0)
```

## Getting started 🚀
Before you're able to extract your model from a request it needs to conform to the protocol `Sanitizable`. To be conferment all you need to do is add a `[String]` named `permitted` with a list of keys you wish to allow.

### User.swift
```swift
struct User: Model, Sanitizable {
var id: Node?
var name: String
var email: String

// will only allow the keys `name` and `email`
static var permitted = ["name", "email"]

init(node: Node, in context: Context) throws {
id = node["id"]
name = try node.extract("name")
email = try node.extract("email")
}

//...
}
```

Now that you have a conforming model, you can safely extract it from a `Request`.

### Request body
```json
{
"id": 10,
"name": "Brett",
"email": "[email protected]"
}
```

### Main.swift
```swift
drop.post("users") { req in
var user: User = try request.extractModel()
print(user.id == nil) // prints `true`
try user.save()
return user
}
```

## 🏆 Credits
This package is developed and maintained by the Vapor team at [Nodes](https://www.nodes.dk).

## 📄 License
This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
85 changes: 81 additions & 4 deletions Tests/sanitizedTests/SanitizedTests.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,89 @@
import XCTest
import HTTP
import Vapor

@testable import Sanitized

class sanitizedTests: XCTestCase {
class SanitizedTests: XCTestCase {
static let allTests = [
("testExample", testExample)
("testBasic", testBasic)
]

func testExample() {
XCTAssertEqual(2+2, 4)
func testBasic() {
let request = buildRequest(body: [
"id": 1,
"name": "Brett",
"email": "[email protected]"
])

expectNoThrow() {
let model: TestModel = try request.extractModel()
XCTAssertNil(model.id)
XCTAssertEqual(model.name, "Brett")
XCTAssertEqual(model.email, "[email protected]")
}
}

func testPermitted() {
let json = JSON([
"id": 1,
"name": "Brett",
"email": "[email protected]"
])

let result = json.permit(["name"])
XCTAssertNil(result["id"])
XCTAssertEqual(result["name"]?.string, "Brett")
XCTAssertNil(result["email"])
}

func testEmptyPermitted() {
let json = JSON([
"id": 1,
"name": "Brett",
"email": "[email protected]"
])

let result = json.permit([])
XCTAssertNil(result["id"])
XCTAssertNil(result["name"])
XCTAssertNil(result["email"])
}
}

extension SanitizedTests {
func buildRequest(body: Node) -> Request {
let body = try! JSON(node: body).makeBytes()

return try! Request(
method: .post,
uri: "/test",
headers: [
"Content-Type": "application/json"
],
body: .data(body)
)
}
}

struct TestModel: Model, Sanitizable {
var id: Node?

var name: String
var email: String

static var permitted = ["name", "email"]

init(node: Node, in context: Context) throws {
id = node["id"]
name = try node.extract("name")
email = try node.extract("email")
}

func makeNode(context: Context) throws -> Node {
return .null
}

static func prepare(_ database: Database) throws {}
static func revert(_ database: Database) throws {}
}
47 changes: 47 additions & 0 deletions Tests/sanitizedTests/Utilities/Expect.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import XCTest

func expect<E: Error, ReturnType>(
toThrow expectedError: E,
file: StaticString = #file,
line: UInt = #line,
from closure: (Void) throws -> ReturnType
) where E: Equatable {
do {
let _ = try closure()
XCTFail("should have thrown", file: file, line: line)
} catch let error as E {
XCTAssertEqual(error, expectedError)
} catch {
XCTFail(
"expected type \(type(of: expectedError)) got \(type(of: error))",
file: file,
line: line
)
}
}

func expectNoThrow<ReturnType>(
file: StaticString = #file,
line: UInt = #line,
_ closure: (Void) throws -> ReturnType
) {
do {
let _ = try closure()
} catch {
XCTFail("closure threw: \(error)", file: file, line: line)
}
}

func expect<ReturnType>(
_ closure: (Void) throws -> ReturnType,
file: StaticString = #file,
line: UInt = #line,
toReturn expectedResult: ReturnType
) where ReturnType: Equatable {
do {
let result = try closure()
XCTAssertEqual(result, expectedResult, file: file, line: line)
} catch {
XCTFail("closure threw: \(error)", file: file, line: line)
}
}

0 comments on commit 663d3c7

Please sign in to comment.