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.template.Template
24 import net.pterodactylus.util.template.TemplateContext
25 import net.pterodactylus.util.web.Method
26 import net.pterodactylus.util.web.Method.GET
27 import net.pterodactylus.util.web.Response
28 import org.junit.Assert.fail
29 import org.junit.Before
30 import org.mockito.ArgumentMatchers.anyBoolean
31 import org.mockito.ArgumentMatchers.anyInt
32 import org.mockito.ArgumentMatchers.anyLong
33 import org.mockito.ArgumentMatchers.anyString
34 import org.mockito.ArgumentMatchers.eq
35 import java.io.ByteArrayOutputStream
37 import java.nio.charset.Charset
38 import kotlin.text.Charsets.UTF_8
41 * Base class for web page tests.
43 open class WebPageTest2(pageSupplier: (Template, WebInterface) -> SoneTemplatePage = { _, _ -> mock<SoneTemplatePage>() }) {
45 val currentSone = mock<Sone>()
46 val template = mock<Template>()
47 val webInterface = deepMock<WebInterface>()
48 val core = webInterface.core!!
49 val eventBus = mock<EventBus>()
50 val preferences = Preferences(eventBus)
51 val l10n = webInterface.l10n!!
53 val page by lazy { pageSupplier(template, webInterface) }
54 val httpRequest = mock<HTTPRequest>()
55 val freenetRequest = mock<FreenetRequest>()
56 val templateContext = TemplateContext()
57 val toadletContext = deepMock<ToadletContext>()
58 val responseContent = ByteArrayOutputStream()
59 val response = Response(responseContent)
61 private val requestHeaders = mutableMapOf<String, String>()
62 private val getRequestParameters = mutableMapOf<String, MutableList<String>>()
63 private val postRequestParameters = mutableMapOf<String, ByteArray>()
64 private val ownIdentities = mutableSetOf<OwnIdentity>()
65 private val allSones = mutableMapOf<String, Sone>()
66 private val localSones = mutableMapOf<String, Sone>()
67 private val allPosts = mutableMapOf<String, Post>()
68 private val allPostReplies = mutableMapOf<String, PostReply>()
69 private val perPostReplies = mutableMapOf<String, PostReply>()
70 private val allAlbums = mutableMapOf<String, Album>()
71 private val allImages = mutableMapOf<String, Image>()
72 private val translations = mutableMapOf<String, String>()
82 private fun setupCore() {
83 whenever(core.preferences).thenReturn(preferences)
84 whenever(core.identityManager.allOwnIdentities).then { ownIdentities }
85 whenever(core.sones).then { allSones.values }
86 whenever(core.getSone(anyString())).then { allSones[it[0]].asOptional() }
87 whenever(core.localSones).then { localSones.values }
88 whenever(core.getLocalSone(anyString())).then { localSones[it[0]] }
89 whenever(core.getPost(anyString())).then { allPosts[it[0]].asOptional() }
90 whenever(core.getPostReply(anyString())).then { allPostReplies[it[0]].asOptional() }
91 whenever(core.getReplies(anyString())).then { perPostReplies[it[0]].asList() }
92 whenever(core.getAlbum(anyString())).then { allAlbums[it[0]] }
93 whenever(core.getImage(anyString())).then { allImages[it[0]]}
94 whenever(core.getImage(anyString(), anyBoolean())).then { allImages[it[0]]}
95 whenever(core.getTemporaryImage(anyString())).thenReturn(null)
98 private fun setupWebInterface() {
99 whenever(webInterface.getCurrentSoneCreatingSession(eq(toadletContext))).thenReturn(currentSone)
100 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(currentSone)
101 whenever(webInterface.getCurrentSoneWithoutCreatingSession(eq(toadletContext))).thenReturn(currentSone)
102 whenever(webInterface.getNotifications(currentSone)).thenReturn(emptyList())
105 private fun setupHttpRequest() {
106 whenever(httpRequest.method).thenReturn("GET")
107 whenever(httpRequest.getHeader(anyString())).then { requestHeaders[it.get<String>(0).toLowerCase()] }
108 whenever(httpRequest.hasParameters()).then { getRequestParameters.isNotEmpty() }
109 whenever(httpRequest.parameterNames).then { getRequestParameters.keys }
110 whenever(httpRequest.isParameterSet(anyString())).then { it[0] in getRequestParameters }
111 whenever(httpRequest.getParam(anyString())).then { getRequestParameters[it[0]]?.firstOrNull() ?: "" }
112 whenever(httpRequest.getParam(anyString(), anyString())).then { getRequestParameters[it[0]]?.firstOrNull() ?: it[1] }
113 whenever(httpRequest.getIntParam(anyString())).then { getRequestParameters[it[0]]?.first()?.toIntOrNull() ?: 0 }
114 whenever(httpRequest.getIntParam(anyString(), anyInt())).then { getRequestParameters[it[0]]?.first()?.toIntOrNull() ?: it[1] }
115 whenever(httpRequest.getLongParam(anyString(), anyLong())).then { getRequestParameters[it[0]]?.first()?.toLongOrNull() ?: it[1] }
116 whenever(httpRequest.getMultipleParam(anyString())).then { getRequestParameters[it[0]]?.toTypedArray() ?: emptyArray<String>() }
117 whenever(httpRequest.getMultipleIntParam(anyString())).then { getRequestParameters[it[0]]?.map { it.toIntOrNull() ?: 0 } ?: emptyArray<Int>() }
118 whenever(httpRequest.isPartSet(anyString())).then { it[0] in postRequestParameters }
119 whenever(httpRequest.getPartAsStringFailsafe(anyString(), anyInt())).then { postRequestParameters[it[0]]?.decode()?.take(it[1]) ?: "" }
122 private fun ByteArray.decode(charset: Charset = UTF_8) = String(this, charset)
124 private fun setupFreenetRequest() {
125 whenever(freenetRequest.method).thenReturn(GET)
126 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
127 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
130 private fun setupTranslations() {
131 whenever(l10n.getString(anyString())).then { translations[it[0]] ?: it[0] }
134 fun setMethod(method: Method) {
135 whenever(httpRequest.method).thenReturn(method.name)
136 whenever(freenetRequest.method).thenReturn(method)
139 fun request(uri: String) {
140 whenever(httpRequest.path).thenReturn(uri)
141 whenever(freenetRequest.uri).thenReturn(URI(uri))
144 fun addHttpRequestHeader(name: String, value: String) {
145 requestHeaders[name.toLowerCase()] = value
148 fun addHttpRequestParameter(name: String, value: String) {
149 getRequestParameters[name] = getRequestParameters.getOrElse(name) { mutableListOf<String>() }.apply { add(value) }
152 fun addHttpRequestPart(name: String, value: String) {
153 postRequestParameters[name] = value.toByteArray(UTF_8)
156 fun unsetCurrentSone() {
157 whenever(webInterface.getCurrentSoneCreatingSession(eq(toadletContext))).thenReturn(null)
158 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(null)
159 whenever(webInterface.getCurrentSoneWithoutCreatingSession(eq(toadletContext))).thenReturn(null)
162 fun addOwnIdentity(ownIdentity: OwnIdentity) {
163 ownIdentities += ownIdentity
166 fun addSone(id: String, sone: Sone) {
170 fun addLocalSone(id: String, localSone: Sone) {
171 localSones[id] = localSone
174 fun addPost(id: String, post: Post) {
178 fun addPostReply(id: String, postReply: PostReply) {
179 allPostReplies[id] = postReply
180 postReply.postId?.also { perPostReplies[it] = postReply }
183 fun addAlbum(id: String, album: Album) {
184 allAlbums[id] = album
187 fun addImage(id: String, image: Image) {
188 allImages[id] = image
191 fun addTranslation(key: String, value: String) {
192 translations[key] = value
195 fun addTemporaryImage(id: String, temporaryImage: TemporaryImage) {
196 whenever(core.getTemporaryImage(id)).thenReturn(temporaryImage)
199 fun verifyNoRedirect(assertions: () -> Unit) {
200 var caughtException: Exception? = null
202 page.handleRequest(freenetRequest, templateContext)
203 } catch (e: Exception) {
206 caughtException?.run { throw this } ?: assertions()
209 fun verifyRedirect(target: String, assertions: () -> Unit = {}) {
211 page.handleRequest(freenetRequest, templateContext)
213 } catch (re: RedirectException) {
214 if (re.target != target) {
218 } catch (e: Exception) {