Turn web page test base into class that can be used with composition
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / pages / WebPageTest2.kt
1 package net.pterodactylus.sone.web.pages
2
3 import com.google.common.eventbus.EventBus
4 import freenet.clients.http.ToadletContext
5 import freenet.support.api.HTTPRequest
6 import net.pterodactylus.sone.core.Preferences
7 import net.pterodactylus.sone.data.Album
8 import net.pterodactylus.sone.data.Image
9 import net.pterodactylus.sone.data.Post
10 import net.pterodactylus.sone.data.PostReply
11 import net.pterodactylus.sone.data.Sone
12 import net.pterodactylus.sone.freenet.wot.OwnIdentity
13 import net.pterodactylus.sone.test.deepMock
14 import net.pterodactylus.sone.test.get
15 import net.pterodactylus.sone.test.mock
16 import net.pterodactylus.sone.test.whenever
17 import net.pterodactylus.sone.utils.asList
18 import net.pterodactylus.sone.utils.asOptional
19 import net.pterodactylus.sone.web.WebInterface
20 import net.pterodactylus.sone.web.page.FreenetRequest
21 import net.pterodactylus.sone.web.page.FreenetTemplatePage.RedirectException
22 import net.pterodactylus.util.template.Template
23 import net.pterodactylus.util.template.TemplateContext
24 import net.pterodactylus.util.web.Method
25 import net.pterodactylus.util.web.Method.GET
26 import net.pterodactylus.util.web.Response
27 import org.junit.Assert.fail
28 import org.junit.Before
29 import org.mockito.ArgumentMatchers.anyBoolean
30 import org.mockito.ArgumentMatchers.anyInt
31 import org.mockito.ArgumentMatchers.anyLong
32 import org.mockito.ArgumentMatchers.anyString
33 import org.mockito.ArgumentMatchers.eq
34 import java.io.ByteArrayOutputStream
35 import java.net.URI
36 import java.nio.charset.Charset
37 import kotlin.text.Charsets.UTF_8
38
39 /**
40  * Base class for web page tests.
41  */
42 open class WebPageTest2(pageSupplier: (Template, WebInterface) -> SoneTemplatePage = { _, _ -> mock<SoneTemplatePage>() }) {
43
44         val currentSone = mock<Sone>()
45         val template = mock<Template>()
46         val webInterface = deepMock<WebInterface>()
47         val core = webInterface.core!!
48         val eventBus = mock<EventBus>()
49         val preferences = Preferences(eventBus)
50         val l10n = webInterface.l10n!!
51
52         val page by lazy { pageSupplier(template, webInterface) }
53         val httpRequest = mock<HTTPRequest>()
54         val freenetRequest = mock<FreenetRequest>()
55         val templateContext = TemplateContext()
56         val toadletContext = deepMock<ToadletContext>()
57         val responseContent = ByteArrayOutputStream()
58         val response = Response(responseContent)
59
60         private val requestHeaders = mutableMapOf<String, String>()
61         private val getRequestParameters = mutableMapOf<String, MutableList<String>>()
62         private val postRequestParameters = mutableMapOf<String, ByteArray>()
63         private val ownIdentities = mutableSetOf<OwnIdentity>()
64         private val allSones = mutableMapOf<String, Sone>()
65         private val localSones = mutableMapOf<String, Sone>()
66         private val allPosts = mutableMapOf<String, Post>()
67         private val allPostReplies = mutableMapOf<String, PostReply>()
68         private val perPostReplies = mutableMapOf<String, PostReply>()
69         private val allAlbums = mutableMapOf<String, Album>()
70         private val allImages = mutableMapOf<String, Image>()
71         private val translations = mutableMapOf<String, String>()
72
73         init {
74                 setupCore()
75                 setupWebInterface()
76                 setupHttpRequest()
77                 setupFreenetRequest()
78                 setupTranslations()
79         }
80
81         private fun setupCore() {
82                 whenever(core.preferences).thenReturn(preferences)
83                 whenever(core.identityManager.allOwnIdentities).then { ownIdentities }
84                 whenever(core.sones).then { allSones.values }
85                 whenever(core.getSone(anyString())).then { allSones[it[0]].asOptional() }
86                 whenever(core.localSones).then { localSones.values }
87                 whenever(core.getLocalSone(anyString())).then { localSones[it[0]] }
88                 whenever(core.getPost(anyString())).then { allPosts[it[0]].asOptional() }
89                 whenever(core.getPostReply(anyString())).then { allPostReplies[it[0]].asOptional() }
90                 whenever(core.getReplies(anyString())).then { perPostReplies[it[0]].asList() }
91                 whenever(core.getAlbum(anyString())).then { allAlbums[it[0]] }
92                 whenever(core.getImage(anyString())).then { allImages[it[0]]}
93                 whenever(core.getImage(anyString(), anyBoolean())).then { allImages[it[0]]}
94         }
95
96         private fun setupWebInterface() {
97                 whenever(webInterface.getCurrentSoneCreatingSession(eq(toadletContext))).thenReturn(currentSone)
98                 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(currentSone)
99                 whenever(webInterface.getCurrentSoneWithoutCreatingSession(eq(toadletContext))).thenReturn(currentSone)
100                 whenever(webInterface.getNotifications(currentSone)).thenReturn(emptyList())
101         }
102
103         private fun setupHttpRequest() {
104                 whenever(httpRequest.method).thenReturn("GET")
105                 whenever(httpRequest.getHeader(anyString())).then { requestHeaders[it.get<String>(0).toLowerCase()] }
106                 whenever(httpRequest.hasParameters()).then { getRequestParameters.isNotEmpty() }
107                 whenever(httpRequest.parameterNames).then { getRequestParameters.keys }
108                 whenever(httpRequest.isParameterSet(anyString())).then { it[0] in getRequestParameters }
109                 whenever(httpRequest.getParam(anyString())).then { getRequestParameters[it[0]]?.firstOrNull() ?: "" }
110                 whenever(httpRequest.getParam(anyString(), anyString())).then { getRequestParameters[it[0]]?.firstOrNull() ?: it[1] }
111                 whenever(httpRequest.getIntParam(anyString())).then { getRequestParameters[it[0]]?.first()?.toIntOrNull() ?: 0 }
112                 whenever(httpRequest.getIntParam(anyString(), anyInt())).then { getRequestParameters[it[0]]?.first()?.toIntOrNull() ?: it[1] }
113                 whenever(httpRequest.getLongParam(anyString(), anyLong())).then { getRequestParameters[it[0]]?.first()?.toLongOrNull() ?: it[1] }
114                 whenever(httpRequest.getMultipleParam(anyString())).then { getRequestParameters[it[0]]?.toTypedArray() ?: emptyArray<String>() }
115                 whenever(httpRequest.getMultipleIntParam(anyString())).then { getRequestParameters[it[0]]?.map { it.toIntOrNull() ?: 0 } ?: emptyArray<Int>() }
116                 whenever(httpRequest.isPartSet(anyString())).then { it[0] in postRequestParameters }
117                 whenever(httpRequest.getPartAsStringFailsafe(anyString(), anyInt())).then { postRequestParameters[it[0]]?.decode()?.take(it[1]) ?: "" }
118         }
119
120         private fun ByteArray.decode(charset: Charset = UTF_8) = String(this, charset)
121
122         private fun setupFreenetRequest() {
123                 whenever(freenetRequest.method).thenReturn(GET)
124                 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
125                 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
126         }
127
128         private fun setupTranslations() {
129                 whenever(l10n.getString(anyString())).then { translations[it[0]] ?: it[0] }
130         }
131
132         fun setMethod(method: Method) {
133                 whenever(httpRequest.method).thenReturn(method.name)
134                 whenever(freenetRequest.method).thenReturn(method)
135         }
136
137         fun request(uri: String) {
138                 whenever(httpRequest.path).thenReturn(uri)
139                 whenever(freenetRequest.uri).thenReturn(URI(uri))
140         }
141
142         fun addHttpRequestHeader(name: String, value: String) {
143                 requestHeaders[name.toLowerCase()] = value
144         }
145
146         fun addHttpRequestParameter(name: String, value: String) {
147                 getRequestParameters[name] = getRequestParameters.getOrElse(name) { mutableListOf<String>() }.apply { add(value) }
148         }
149
150         fun addHttpRequestPart(name: String, value: String) {
151                 postRequestParameters[name] = value.toByteArray(UTF_8)
152         }
153
154         fun unsetCurrentSone() {
155                 whenever(webInterface.getCurrentSoneCreatingSession(eq(toadletContext))).thenReturn(null)
156                 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(null)
157                 whenever(webInterface.getCurrentSoneWithoutCreatingSession(eq(toadletContext))).thenReturn(null)
158         }
159
160         fun addOwnIdentity(ownIdentity: OwnIdentity) {
161                 ownIdentities += ownIdentity
162         }
163
164         fun addSone(id: String, sone: Sone) {
165                 allSones[id] = sone
166         }
167
168         fun addLocalSone(id: String, localSone: Sone) {
169                 localSones[id] = localSone
170         }
171
172         fun addPost(id: String, post: Post) {
173                 allPosts[id] = post
174         }
175
176         fun addPostReply(id: String, postReply: PostReply) {
177                 allPostReplies[id] = postReply
178                 postReply.postId?.also { perPostReplies[it] = postReply }
179         }
180
181         fun addAlbum(id: String, album: Album) {
182                 allAlbums[id] = album
183         }
184
185         fun addImage(id: String, image: Image) {
186                 allImages[id] = image
187         }
188
189         fun addTranslation(key: String, value: String) {
190                 translations[key] = value
191         }
192
193         fun verifyNoRedirect(assertions: () -> Unit) {
194                 var caughtException: Exception? = null
195                 try {
196                         page.handleRequest(freenetRequest, templateContext)
197                 } catch (e: Exception) {
198                         caughtException = e
199                 }
200                 caughtException?.run { throw this } ?: assertions()
201         }
202
203         fun verifyRedirect(target: String, assertions: () -> Unit = {}) {
204                 try {
205                         page.handleRequest(freenetRequest, templateContext)
206                         fail()
207                 } catch (re: RedirectException) {
208                         if (re.target != target) {
209                                 throw re
210                         }
211                         assertions()
212                 } catch (e: Exception) {
213                         throw e
214                 }
215         }
216
217 }