-
-
Notifications
You must be signed in to change notification settings - Fork 99
/
FilesTest.kt
175 lines (150 loc) · 6.78 KB
/
FilesTest.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package com.hexagonkt.http.test.examples
import com.hexagonkt.core.media.TEXT_CSS
import com.hexagonkt.core.media.TEXT_HTML
import com.hexagonkt.core.urlOf
import com.hexagonkt.http.client.HttpClientPort
import com.hexagonkt.http.model.HttpRequest
import com.hexagonkt.http.model.*
import com.hexagonkt.http.model.NOT_FOUND_404
import com.hexagonkt.http.model.HttpMethod.GET
import com.hexagonkt.http.model.HttpMethod.POST
import com.hexagonkt.http.model.OK_200
import com.hexagonkt.http.server.HttpServerPort
import com.hexagonkt.http.server.HttpServerSettings
import com.hexagonkt.http.server.callbacks.FileCallback
import com.hexagonkt.http.server.callbacks.UrlCallback
import com.hexagonkt.http.handlers.PathHandler
import com.hexagonkt.http.handlers.HttpHandler
import com.hexagonkt.http.handlers.path
import com.hexagonkt.http.test.BaseTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import java.io.File
import kotlin.test.assertEquals
@TestInstance(PER_CLASS)
@Suppress("FunctionName") // This class's functions are intended to be used only in tests
abstract class FilesTest(
final override val clientAdapter: () -> HttpClientPort,
final override val serverAdapter: () -> HttpServerPort,
final override val serverSettings: HttpServerSettings = HttpServerSettings(),
) : BaseTest() {
private val directory = File("http_test/src/main/resources/assets").let {
if (it.exists()) it.path
else "../http_test/src/main/resources/assets"
}
// files
private val path: PathHandler = path {
// Serve `public` resources folder on `/*`
after(
methods = setOf(GET),
pattern = "/*",
status = NOT_FOUND_404,
callback = UrlCallback(urlOf("classpath:public"))
)
path("/static") {
get("/files/*", UrlCallback(urlOf("classpath:assets")))
get("/resources/*", FileCallback(File(directory)))
}
get("/html/*", UrlCallback(urlOf("classpath:assets"))) // Serve `assets` files on `/html/*`
get("/pub/*", FileCallback(File(directory))) // Serve `test` folder on `/pub/*`
post("/multipart") {
val headers = parts.first().let { p ->
val name = p.name
val bodyString = p.bodyString()
val size = p.size.toString()
Headers(
Header("name", name),
Header("body", bodyString),
Header("size", size),
)
}
ok(headers = headers)
}
post("/file") {
val part = parts.first()
val content = part.bodyString()
val submittedFile = part.submittedFileName ?: ""
ok(content, headers = response.headers + Header("submitted-file", submittedFile))
}
post("/form") {
fun <T : HttpField> serializeMap(map: Collection<T>): List<String> = listOf(
map.joinToString("\n") { "${it.name}:${it.values.joinToString(",")}" }
)
val queryParams = serializeMap(queryParameters.values)
val formParams = serializeMap(formParameters.values)
val headers =
Headers(Header("query-params", queryParams), Header("form-params", formParams))
ok(headers = response.headers + headers)
}
}
// files
override val handler: HttpHandler = path
@Test fun `Parameters are separated from each other`() {
val parts = listOf(HttpPart("name", "value"))
val response = client.send(
HttpRequest(POST, path = "/form?queryName=queryValue", parts = parts)
)
assertEquals("queryName:queryValue", response.headers["query-params"]?.value)
assert(!(response.headers["query-params"]?.string()?.contains("name:value") ?: true))
assert(response.headers["form-params"]?.string()?.contains("name:value") ?: false)
assert(!(response.headers["form-params"]?.string()?.contains("queryName:queryValue") ?: true))
}
@Test fun `Requesting a folder with an existing file name returns 404`() {
val response = client.get ("/file.txt/")
assertResponseContains(response, NOT_FOUND_404)
}
@Test fun `An static file from resources can be fetched`() {
val response = client.get("/file.txt")
assertResponseEquals(response, content = "file content")
}
@Test fun `Files content type is returned properly`() {
val response = client.get("/file.css")
assertEquals(TEXT_CSS, response.contentType?.mediaType)
assertResponseEquals(response, content = "/* css */")
val responseFile = client.get("/pub/css/mkdocs.css")
assertResponseContains(responseFile, OK_200, "article")
assertEquals(TEXT_CSS, responseFile.contentType?.mediaType)
client.get("/static/resources/css/mkdocs.css").apply {
assertEquals(TEXT_CSS, contentType?.mediaType)
assertResponseContains(this, OK_200, "article")
}
}
@Test fun `Not found resources return 404`() {
assertEquals(NOT_FOUND_404, client.get("/not_found.css").status)
assertEquals(NOT_FOUND_404, client.get("/pub/not_found.css").status)
assertEquals(NOT_FOUND_404, client.get("/html/not_found.css").status)
}
@Test fun `Sending multi part content works properly`() {
// clientForm
val parts = listOf(HttpPart("name", "value"))
val response = client.send(HttpRequest(POST, path = "/multipart", parts = parts))
// clientForm
val expectedHeaders = Headers(
Header("name", "name"),
Header("body", "value"),
Header("size", "5"),
)
expectedHeaders.forEach {
assertEquals(it.value, response.headers[it.key])
}
}
@Test fun `Sending files works properly`() {
// clientFile
val stream = urlOf("classpath:assets/index.html").readBytes()
val parts = listOf(HttpPart("file", stream, "index.html"))
val response = client.send(HttpRequest(POST, path = "/file", parts = parts))
// clientFile
assertEquals("index.html", response.headers["submitted-file"]?.value)
assertResponseContains(response, OK_200, "<!DOCTYPE html>", "<title>Hexagon</title>", "</html>")
}
@Test fun `Files mounted on a path are returned properly`() {
val response = client.get("/html/index.html")
assertEquals(TEXT_HTML, response.contentType?.mediaType)
assertResponseContains(response, OK_200, "<title>Hexagon</title>")
client.get("/static/files/index.html").apply {
assertEquals(TEXT_HTML, contentType?.mediaType)
assertResponseContains(this, OK_200, "<title>Hexagon</title>")
}
}
}