1
+ /*
2
+ * Copyright (c) 2016-2023.
3
+ *
4
+ * This file is part of Imposter.
5
+ *
6
+ * "Commons Clause" License Condition v1.0
7
+ *
8
+ * The Software is provided to you by the Licensor under the License, as
9
+ * defined below, subject to the following condition.
10
+ *
11
+ * Without limiting other conditions in the License, the grant of rights
12
+ * under the License will not include, and the License does not grant to
13
+ * you, the right to Sell the Software.
14
+ *
15
+ * For purposes of the foregoing, "Sell" means practicing any or all of
16
+ * the rights granted to you under the License to provide to third parties,
17
+ * for a fee or other consideration (including without limitation fees for
18
+ * hosting or consulting/support services related to the Software), a
19
+ * product or service whose value derives, entirely or substantially, from
20
+ * the functionality of the Software. Any license notice or attribution
21
+ * required by the License must also include this Commons Clause License
22
+ * Condition notice.
23
+ *
24
+ * Software: Imposter
25
+ *
26
+ * License: GNU Lesser General Public License version 3
27
+ *
28
+ * Licensor: Peter Cornish
29
+ *
30
+ * Imposter is free software: you can redistribute it and/or modify
31
+ * it under the terms of the GNU Lesser General Public License as published by
32
+ * the Free Software Foundation, either version 3 of the License, or
33
+ * (at your option) any later version.
34
+ *
35
+ * Imposter is distributed in the hope that it will be useful,
36
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
+ * GNU Lesser General Public License for more details.
39
+ *
40
+ * You should have received a copy of the GNU Lesser General Public License
41
+ * along with Imposter. If not, see <https://www.gnu.org/licenses/>.
42
+ */
43
+ package io.gatehill.imposter.plugin.openapi.service
44
+
45
+ import io.gatehill.imposter.http.HttpExchange
46
+ import io.gatehill.imposter.http.HttpMethod
47
+ import io.gatehill.imposter.http.HttpRequest
48
+ import io.gatehill.imposter.http.HttpResponse
49
+ import io.gatehill.imposter.plugin.openapi.model.ContentTypedHolder
50
+ import org.junit.jupiter.api.Assertions.assertFalse
51
+ import org.junit.jupiter.api.Assertions.assertTrue
52
+ import org.junit.jupiter.api.Test
53
+ import org.mockito.kotlin.any
54
+ import org.mockito.kotlin.argumentCaptor
55
+ import org.mockito.kotlin.doReturn
56
+ import org.mockito.kotlin.mock
57
+ import org.mockito.kotlin.verify
58
+
59
+ /* *
60
+ * Tests for [ResponseTransmissionServiceImpl].
61
+ *
62
+ * @author Pete Cornish
63
+ */
64
+ class ResponseTransmissionServiceImplTest {
65
+ private val service = ResponseTransmissionServiceImpl ()
66
+
67
+ private fun createMockHttpExchange (): HttpExchange {
68
+ val httpRequest = mock<HttpRequest > {
69
+ on { method } doReturn HttpMethod .GET
70
+ on { absoluteUri } doReturn " /test"
71
+ }
72
+ val httpResponse = mock<HttpResponse > {
73
+ on { putHeader(any(), any()) } doReturn mock
74
+ on { statusCode } doReturn 200
75
+ }
76
+ return mock<HttpExchange > {
77
+ on { request } doReturn httpRequest
78
+ on { response } doReturn httpResponse
79
+ }
80
+ }
81
+
82
+ @Test
83
+ fun `should serialise as JSON for application json` () {
84
+ val httpExchange = createMockHttpExchange()
85
+ val testData = mapOf (" key" to " value" , " number" to 42 )
86
+ val example = ContentTypedHolder (" application/json" , testData)
87
+
88
+ service.transmitExample(httpExchange, example)
89
+
90
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/json" )
91
+
92
+ val responseCaptor = argumentCaptor<String >()
93
+ verify(httpExchange.response).end(responseCaptor.capture())
94
+ val response = responseCaptor.firstValue
95
+
96
+ // Verify it's JSON by checking it contains expected elements
97
+ assertTrue(response.contains(" \" key\" " ))
98
+ assertTrue(response.contains(" \" value\" " ))
99
+ assertTrue(response.contains(" \" number\" " ))
100
+ assertTrue(response.contains(" 42" ))
101
+ }
102
+
103
+ @Test
104
+ fun `should serialise as JSON for structured syntax suffix json` () {
105
+ val httpExchange = createMockHttpExchange()
106
+ val testData = mapOf (" key" to " value" )
107
+ val example = ContentTypedHolder (" application/vnd.api+json" , testData)
108
+
109
+ service.transmitExample(httpExchange, example)
110
+
111
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/vnd.api+json" )
112
+
113
+ val responseCaptor = argumentCaptor<String >()
114
+ verify(httpExchange.response).end(responseCaptor.capture())
115
+ val response = responseCaptor.firstValue
116
+
117
+ // Verify it's JSON format
118
+ assertTrue(response.contains(" \" key\" " ))
119
+ assertTrue(response.contains(" \" value\" " ))
120
+ }
121
+
122
+ @Test
123
+ fun `should serialise as JSON for github issue example content type` () {
124
+ val httpExchange = createMockHttpExchange()
125
+ val testData = mapOf (" test" to " data" )
126
+ val example = ContentTypedHolder (" application/vnd.my.super.type.v1+json" , testData)
127
+
128
+ service.transmitExample(httpExchange, example)
129
+
130
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/vnd.my.super.type.v1+json" )
131
+
132
+ val responseCaptor = argumentCaptor<String >()
133
+ verify(httpExchange.response).end(responseCaptor.capture())
134
+ val response = responseCaptor.firstValue
135
+
136
+ // Verify it's JSON format
137
+ assertTrue(response.contains(" \" test\" " ))
138
+ assertTrue(response.contains(" \" data\" " ))
139
+ }
140
+
141
+ @Test
142
+ fun `should serialise as YAML for YAML content types` () {
143
+ val httpExchange = createMockHttpExchange()
144
+ val testData = mapOf (" key" to " value" )
145
+ val example = ContentTypedHolder (" application/yaml" , testData)
146
+
147
+ service.transmitExample(httpExchange, example)
148
+
149
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/yaml" )
150
+
151
+ val responseCaptor = argumentCaptor<String >()
152
+ verify(httpExchange.response).end(responseCaptor.capture())
153
+ val response = responseCaptor.firstValue
154
+
155
+ // Verify it's YAML format (starts with --- and contains key: "value")
156
+ assertTrue(response.contains(" ---" ))
157
+ assertTrue(response.contains(" key: \" value\" " ))
158
+ }
159
+
160
+ @Test
161
+ fun `should handle unsupported content types` () {
162
+ val httpExchange = createMockHttpExchange()
163
+ val testData = mapOf (" key" to " value" )
164
+ val example = ContentTypedHolder (" text/plain" , testData)
165
+
166
+ service.transmitExample(httpExchange, example)
167
+
168
+ verify(httpExchange.response).putHeader(" Content-Type" , " text/plain" )
169
+
170
+ val responseCaptor = argumentCaptor<String >()
171
+ verify(httpExchange.response).end(responseCaptor.capture())
172
+ val response = responseCaptor.firstValue
173
+
174
+ // Verify it's toString format (contains = but not quotes)
175
+ assertTrue(response.contains(" key=value" ))
176
+ assertFalse(response.contains(" \" " ))
177
+ }
178
+
179
+ @Test
180
+ fun `should handle null example value` () {
181
+ val httpExchange = createMockHttpExchange()
182
+ val example = ContentTypedHolder (" application/json" , null )
183
+
184
+ service.transmitExample(httpExchange, example)
185
+
186
+ verify(httpExchange.response).end()
187
+ }
188
+
189
+ @Test
190
+ fun `should handle string examples` () {
191
+ val httpExchange = createMockHttpExchange()
192
+ val example = ContentTypedHolder (" application/json" , " test string" )
193
+
194
+ service.transmitExample(httpExchange, example)
195
+
196
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/json" )
197
+ verify(httpExchange.response).end(" test string" )
198
+ }
199
+
200
+ @Test
201
+ fun `should handle list examples with JSON content type` () {
202
+ val httpExchange = createMockHttpExchange()
203
+ val testList = listOf (mapOf (" id" to 1 ), mapOf (" id" to 2 ))
204
+ val example = ContentTypedHolder (" application/vnd.api+json" , testList)
205
+
206
+ service.transmitExample(httpExchange, example)
207
+
208
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/vnd.api+json" )
209
+
210
+ val responseCaptor = argumentCaptor<String >()
211
+ verify(httpExchange.response).end(responseCaptor.capture())
212
+ val response = responseCaptor.firstValue
213
+
214
+ // Verify it's JSON array format
215
+ assertTrue(response.contains(" [" ))
216
+ assertTrue(response.contains(" ]" ))
217
+ assertTrue(response.contains(" \" id\" " ))
218
+ assertTrue(response.contains(" 1" ))
219
+ assertTrue(response.contains(" 2" ))
220
+ }
221
+
222
+ @Test
223
+ fun `should not serialise as JSON for non-JSON content types` () {
224
+ val httpExchange = createMockHttpExchange()
225
+ val testData = mapOf (" key" to " value" )
226
+ val example = ContentTypedHolder (" application/xml" , testData)
227
+
228
+ service.transmitExample(httpExchange, example)
229
+
230
+ verify(httpExchange.response).putHeader(" Content-Type" , " application/xml" )
231
+
232
+ val responseCaptor = argumentCaptor<String >()
233
+ verify(httpExchange.response).end(responseCaptor.capture())
234
+ val response = responseCaptor.firstValue
235
+
236
+ // Verify it's NOT JSON (toString format)
237
+ assertTrue(response.contains(" key=value" ))
238
+ assertFalse(response.contains(" \" key\" " ))
239
+ }
240
+ }
0 commit comments