Skip to content

Commit f21e414

Browse files
committed
unit tests
1 parent fdeb522 commit f21e414

File tree

13 files changed

+321
-22
lines changed

13 files changed

+321
-22
lines changed

Chapter 12/myProject/Sources/App/Modules/Api/Controllers/ApiUpdateController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ extension ApiUpdateController {
2929
func setupUpdateRoutes(_ routes: RoutesBuilder) {
3030
let baseRoutes = getBaseRoutes(routes)
3131
let existingModelRoutes = baseRoutes.grouped(ApiModel.pathIdComponent)
32-
existingModelRoutes.post(use: updateApi)
32+
existingModelRoutes.put(use: updateApi)
3333
}
3434
}

Chapter 13/myProject/Sources/App/Modules/Api/Controllers/ApiUpdateController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ extension ApiUpdateController {
3535
func setupUpdateRoutes(_ routes: RoutesBuilder) {
3636
let baseRoutes = getBaseRoutes(routes)
3737
let existingModelRoutes = baseRoutes.grouped(ApiModel.pathIdComponent)
38-
existingModelRoutes.post(use: updateApi)
38+
existingModelRoutes.put(use: updateApi)
3939
}
4040
}

Chapter 14/myProject/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Chapter 14/myProject/Package.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ let package = Package(
1313
.package(url: "https://github.com/binarybirds/liquid", from: "1.3.0"),
1414
.package(url: "https://github.com/binarybirds/liquid-local-driver", from: "1.3.0"),
1515
.package(url: "https://github.com/binarybirds/swift-html", from: "1.2.0"),
16+
.package(url: "https://github.com/binarybirds/spec", from: "1.2.0"),
1617
],
1718
targets: [
1819
.target(name: "App", dependencies: [
@@ -28,6 +29,7 @@ let package = Package(
2829
.testTarget(name: "AppTests", dependencies: [
2930
.target(name: "App"),
3031
.product(name: "XCTVapor", package: "vapor"),
32+
.product(name: "Spec", package: "spec"),
3133
])
3234
]
3335
)

Chapter 14/myProject/Sources/App/Modules/Api/Controllers/ApiUpdateController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ extension ApiUpdateController {
3535
func setupUpdateRoutes(_ routes: RoutesBuilder) {
3636
let baseRoutes = getBaseRoutes(routes)
3737
let existingModelRoutes = baseRoutes.grouped(ApiModel.pathIdComponent)
38-
existingModelRoutes.post(use: updateApi)
38+
existingModelRoutes.put(use: updateApi)
3939
}
4040
}

Chapter 14/myProject/Sources/App/Modules/Blog/Controllers/BlogFrontendController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct BlogFrontendController {
3232
let post = try await BlogPostModel
3333
.query(on: req.db)
3434
.filter(\.$slug == slug)
35-
.with(\.$category)
35+
// .with(\.$category)
3636
.first()
3737
else {
3838
return req.redirect(to: "/")

Chapter 14/myProject/Sources/App/Modules/Blog/Controllers/BlogPostApiController.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,19 @@ struct BlogPostApiController: ApiController {
3939
}
4040

4141
func detailOutput(_ req: Request, _ model: DatabaseModel) async throws -> Blog.Post.Detail {
42-
.init(id: model.id!,
42+
guard
43+
let categoryModel = try await BlogCategoryModel.find(model.$category.id, on: req.db),
44+
let category = try await BlogCategoryApiController().listOutput(req, [categoryModel]).first
45+
else {
46+
throw Abort(.internalServerError)
47+
}
48+
return .init(id: model.id!,
4349
title: model.title,
4450
slug: model.slug,
4551
image: model.imageKey,
4652
excerpt: model.excerpt,
4753
date: model.date,
48-
category: .init(id: model.category.id!,
49-
title: model.category.title),
54+
category: category,
5055
content: model.content)
5156
}
5257

@@ -55,22 +60,28 @@ struct BlogPostApiController: ApiController {
5560
model.slug = input.slug
5661
model.imageKey = input.image
5762
model.excerpt = input.excerpt
63+
model.date = input.date
5864
model.content = input.content
65+
model.$category.id = input.categoryId
5966
}
6067

6168
func updateInput(_ req: Request, _ model: DatabaseModel, _ input: Blog.Post.Update) async throws {
6269
model.title = input.title
6370
model.slug = input.slug
6471
model.imageKey = input.image
6572
model.excerpt = input.excerpt
73+
model.date = input.date
6674
model.content = input.content
75+
model.$category.id = input.categoryId
6776
}
6877

6978
func patchInput(_ req: Request, _ model: DatabaseModel, _ input: Blog.Post.Patch) async throws {
7079
model.title = input.title ?? model.title
7180
model.slug = input.slug ?? model.slug
7281
model.imageKey = input.image ?? model.imageKey
7382
model.excerpt = input.excerpt ?? model.excerpt
83+
model.date = input.date ?? model.date
7484
model.content = input.content ?? model.content
85+
model.$category.id = input.categoryId ?? model.$category.id
7586
}
7687
}

Chapter 14/myProject/Sources/App/Modules/Blog/Objects/BlogPost.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ extension Blog.Post {
4343
let excerpt: String
4444
let date: Date
4545
let content: String
46+
let categoryId: UUID
4647
}
4748

4849
struct Update: Codable {
@@ -52,6 +53,7 @@ extension Blog.Post {
5253
let excerpt: String
5354
let date: Date
5455
let content: String
56+
let categoryId: UUID
5557
}
5658

5759
struct Patch: Codable {
@@ -61,5 +63,6 @@ extension Blog.Post {
6163
let excerpt: String?
6264
let date: Date?
6365
let content: String?
66+
let categoryId: UUID?
6467
}
6568
}
Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
1+
//
2+
// FILE.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2021. 12. 25..
6+
//
7+
18
@testable import App
29
import XCTVapor
310

4-
final class AppTests: XCTestCase {
5-
6-
func testRoutes() throws {
7-
let app = Application(.testing)
11+
final class AppTests: AppTestCase {
12+
13+
func testHomePage() throws {
14+
let app = try createTestApp()
815
defer { app.shutdown() }
9-
try configure(app)
10-
11-
try app.test(.GET, "") { res in
12-
XCTAssertEqual(res.status, .ok)
13-
}
14-
15-
try app.test(.GET, "/blog/") { res in
16+
17+
try app.testable(method: .inMemory).test(.GET, "") { res in
1618
XCTAssertEqual(res.status, .ok)
17-
}
18-
19-
try app.test(.GET, "/blog") { res in
20-
XCTAssertEqual(res.status, .movedPermanently)
19+
20+
let contentType = try XCTUnwrap(res.headers.contentType)
21+
XCTAssertEqual(contentType, .html)
22+
XCTAssertTrue(res.body.string.contains("Home"))
2123
}
2224
}
25+
26+
func testAuth() throws {
27+
let app = try createTestApp()
28+
defer { app.shutdown() }
29+
30+
let email = "[email protected]"
31+
let token = try authenticate(.init(email: email, password: "ChangeMe1"), app)
32+
XCTAssertEqual(token.user.email, email)
33+
}
2334
}
35+
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Tibor Bodecs on 2022. 01. 08..
6+
//
7+
8+
@testable import App
9+
import XCTVapor
10+
11+
extension Blog.Category.Create: Content {}
12+
13+
final class BlogCategoryApiTests: AppTestCase {
14+
15+
func testList() throws {
16+
let app = try createTestApp()
17+
let token = try authenticateRoot(app)
18+
defer { app.shutdown() }
19+
20+
let headers = HTTPHeaders([("Authorization", "Bearer \(token.value)")])
21+
22+
try app
23+
//.testable(method: .inMemory)
24+
.testable(method: .running(port: 8081))
25+
.test(.GET, "/api/blog/categories/", headers: headers) { res in
26+
XCTAssertEqual(res.status, .ok)
27+
let contentType = try XCTUnwrap(res.headers.contentType)
28+
XCTAssertEqual(contentType, .json)
29+
XCTAssertContent([Blog.Category.List].self, res) { content in
30+
XCTAssertEqual(content.count, 4)
31+
}
32+
}
33+
}
34+
35+
func testCreate() throws {
36+
let app = try createTestApp()
37+
let token = try authenticateRoot(app)
38+
defer { app.shutdown() }
39+
40+
let headers = HTTPHeaders([("Authorization", "Bearer \(token.value)")])
41+
42+
let newCategory = Blog.Category.Create(title: "Test category")
43+
44+
try app.test(.POST, "/api/blog/categories/",
45+
headers: headers,
46+
content: newCategory) { res in
47+
XCTAssertEqual(res.status, .created)
48+
let contentType = try XCTUnwrap(res.headers.contentType)
49+
XCTAssertEqual(contentType, .json)
50+
XCTAssertContent(Blog.Category.Detail.self, res) { content in
51+
XCTAssertEqual(content.title, newCategory.title)
52+
}
53+
}
54+
}
55+
56+
func testCreateListUpdate() throws {
57+
let app = try createTestApp()
58+
let token = try authenticateRoot(app)
59+
defer { app.shutdown() }
60+
61+
let headers = HTTPHeaders([("Authorization", "Bearer \(token.value)")])
62+
63+
let newCategory = Blog.Category.Create(title: "Test category")
64+
65+
try app
66+
.test(.POST, "/api/blog/categories/",
67+
headers: headers,
68+
content: newCategory) { res in
69+
XCTAssertEqual(res.status, .created)
70+
let contentType = try XCTUnwrap(res.headers.contentType)
71+
XCTAssertEqual(contentType, .json)
72+
XCTAssertContent(Blog.Category.Detail.self, res) { content in
73+
XCTAssertEqual(content.title, newCategory.title)
74+
}
75+
}
76+
.test(.GET, "/api/blog/categories/", headers: headers) { res in
77+
XCTAssertEqual(res.status, .ok)
78+
let contentType = try XCTUnwrap(res.headers.contentType)
79+
XCTAssertEqual(contentType, .json)
80+
XCTAssertContent([Blog.Category.List].self, res) { content in
81+
XCTAssertEqual(content.count, 5)
82+
}
83+
}
84+
}
85+
}
86+

0 commit comments

Comments
 (0)