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