1 package net.pterodactylus.sone.web.pages
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
38 import java.nio.charset.Charset
39 import kotlin.text.Charsets.UTF_8
42 * Base class for web page tests.
44 open class WebPageTest2(pageSupplier: (Template, WebInterface) -> SoneTemplatePage = { _, _ -> mock<SoneTemplatePage>() }) {
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!!
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)
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>()
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)
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() }
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]) ?: "" }
125 private fun ByteArray.decode(charset: Charset = UTF_8) = String(this, charset)
127 private fun setupFreenetRequest() {
128 whenever(freenetRequest.method).thenReturn(GET)
129 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
130 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
133 private fun setupTranslations() {
134 whenever(l10n.getString(anyString())).then { translations[it[0]] ?: it[0] }
137 fun setMethod(method: Method) {
138 whenever(httpRequest.method).thenReturn(method.name)
139 whenever(freenetRequest.method).thenReturn(method)
142 fun request(uri: String) {
143 whenever(httpRequest.path).thenReturn(uri)
144 whenever(freenetRequest.uri).thenReturn(URI(uri))
147 fun addHttpRequestHeader(name: String, value: String) {
148 requestHeaders[name.toLowerCase()] = value
151 fun addHttpRequestParameter(name: String, value: String) {
152 getRequestParameters[name] = getRequestParameters.getOrElse(name) { mutableListOf<String>() }.apply { add(value) }
155 fun addHttpRequestPart(name: String, value: String) {
156 postRequestParameters[name] = value.toByteArray(UTF_8)
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)
165 fun addOwnIdentity(ownIdentity: OwnIdentity) {
166 ownIdentities += ownIdentity
169 fun addSone(id: String, sone: Sone) {
173 fun addLocalSone(id: String, localSone: Sone) {
174 localSones[id] = localSone
177 fun addPost(id: String, post: Post) {
181 fun addPostReply(id: String, postReply: PostReply) {
182 allPostReplies[id] = postReply
183 postReply.postId?.also { perPostReplies[it] = postReply }
186 fun addAlbum(id: String, album: Album) {
187 allAlbums[id] = album
190 fun addImage(id: String, image: Image) {
191 allImages[id] = image
194 fun addTranslation(key: String, value: String) {
195 translations[key] = value
198 fun addNotification(id: String, notification: Notification) {
199 notifications[id] = notification
202 fun addTemporaryImage(id: String, temporaryImage: TemporaryImage) {
203 whenever(core.getTemporaryImage(id)).thenReturn(temporaryImage)
206 fun verifyNoRedirect(assertions: () -> Unit) {
207 var caughtException: Exception? = null
209 page.handleRequest(freenetRequest, templateContext)
210 } catch (e: Exception) {
213 caughtException?.run { throw this } ?: assertions()
216 fun verifyRedirect(target: String, assertions: () -> Unit = {}) {
218 page.handleRequest(freenetRequest, templateContext)
220 } catch (re: RedirectException) {
221 if (re.target != target) {
225 } catch (e: Exception) {