Repository: vapor/vapor
File: Tests/VaporTests/ContentTests.swift (Swift)

Code before:
            try res.content.encode(FooContent())
            try res.content.encode(FooContent(), as: .json)
            try res.content.encode(FooEncodable(), as: .json)
            return res
        }

        try app.testable().test(.GET, "/encode") { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertContains(res.body.string, "hi")
        }
    }

    func testContentContainerDecode() throws {
        struct FooContent: Content, Equatable {
            var message: String = "hi"
        }
        struct FooDecodable: Decodable, Equatable {
            var message: String = "hi"
        }

        let app = Application(.testing)
        defer { app.shutdown() }

        app.routes.get("decode") { req async throws -> String in
            XCTAssertEqual(try req.content.decode(FooContent.self), FooContent())
            XCTAssertEqual(try req.content.decode(FooDecodable.self, as: .json), FooDecodable())
            return "decoded!"
        }

        try app.testable().test(.GET, "/decode") { req in
            try req.content.encode(FooContent())
        } afterResponse: { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertContains(res.body.string, "decoded!")
        }
    }
    
    func testMultipartDecode() throws {
        let data = """
        --123\r
        Content-Disposition: form-data; name="name"\r
        \r
        Vapor\r
        --123\r
        Content-Disposition: form-data; name="age"\r
        \r
        4\r
        --123\r
        Content-Disposition: form-data; name="image"; filename="droplet.png"\r
        \r
        <contents of image>\r

Review comment (suggestion):
I would like to see another test route (either new test or the same test) where you send a request body that's JSON but some random content-type and then ensure we can decode the JSON body. This matches the behaviour we want and problems people have hit

Code after:
            try res.content.encode(FooContent())
            try res.content.encode(FooContent(), as: .json)
            try res.content.encode(FooEncodable(), as: .json)
            return res
        }

        try app.testable().test(.GET, "/encode") { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertContains(res.body.string, "hi")
        }
    }

    func testContentContainerDecode() throws {
        struct FooContent: Content, Equatable {
            var message: String = "hi"
        }
        struct FooDecodable: Decodable, Equatable {
            var message: String = "hi"
        }

        let app = Application(.testing)
        defer { app.shutdown() }

        app.routes.post("decode") { req async throws -> String in
            XCTAssertEqual(try req.content.decode(FooContent.self), FooContent())
            XCTAssertEqual(try req.content.decode(FooDecodable.self, as: .json), FooDecodable())
            return "decoded!"
        }

        try app.testable().test(.POST, "/decode") { req in
            try req.content.encode(FooContent())
        } afterResponse: { res in
            XCTAssertEqual(res.status, .ok)
            XCTAssertContains(res.body.string, "decoded!")
        }

        app.routes.post("decode-bad-header") { req async throws -> String in
            XCTAssertEqual(req.headers.contentType, .audio)
            XCTAssertThrowsError(try req.content.decode(FooContent.self)) { error in
                guard let abort = error as? Abort, abort.status == .unsupportedMediaType else {
                    XCTFail("Unexpected error: \(error)")
                    return
                }
            }
            XCTAssertEqual(try req.content.decode(FooDecodable.self, as: .json), FooDecodable())
            return "decoded!"
        }

        try app.testable().test(.POST, "/decode-bad-header") { req in
            try req.content.encode(FooContent())
            req.headers.contentType = .audio