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.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
36 import java.nio.charset.Charset
37 import kotlin.text.Charsets.UTF_8
40 * Base class for web page tests.
42 open class WebPageTest2(pageSupplier: (Template, WebInterface) -> SoneTemplatePage = { _, _ -> mock<SoneTemplatePage>() }) {
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!!
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)
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>()
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]]}
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())
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]) ?: "" }
120 private fun ByteArray.decode(charset: Charset = UTF_8) = String(this, charset)
122 private fun setupFreenetRequest() {
123 whenever(freenetRequest.method).thenReturn(GET)
124 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
125 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
128 private fun setupTranslations() {
129 whenever(l10n.getString(anyString())).then { translations[it[0]] ?: it[0] }
132 fun setMethod(method: Method) {
133 whenever(httpRequest.method).thenReturn(method.name)
134 whenever(freenetRequest.method).thenReturn(method)
137 fun request(uri: String) {
138 whenever(httpRequest.path).thenReturn(uri)
139 whenever(freenetRequest.uri).thenReturn(URI(uri))
142 fun addHttpRequestHeader(name: String, value: String) {
143 requestHeaders[name.toLowerCase()] = value
146 fun addHttpRequestParameter(name: String, value: String) {
147 getRequestParameters[name] = getRequestParameters.getOrElse(name) { mutableListOf<String>() }.apply { add(value) }
150 fun addHttpRequestPart(name: String, value: String) {
151 postRequestParameters[name] = value.toByteArray(UTF_8)
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)
160 fun addOwnIdentity(ownIdentity: OwnIdentity) {
161 ownIdentities += ownIdentity
164 fun addSone(id: String, sone: Sone) {
168 fun addLocalSone(id: String, localSone: Sone) {
169 localSones[id] = localSone
172 fun addPost(id: String, post: Post) {
176 fun addPostReply(id: String, postReply: PostReply) {
177 allPostReplies[id] = postReply
178 postReply.postId?.also { perPostReplies[it] = postReply }
181 fun addAlbum(id: String, album: Album) {
182 allAlbums[id] = album
185 fun addImage(id: String, image: Image) {
186 allImages[id] = image
189 fun addTranslation(key: String, value: String) {
190 translations[key] = value
193 fun verifyNoRedirect(assertions: () -> Unit) {
194 var caughtException: Exception? = null
196 page.handleRequest(freenetRequest, templateContext)
197 } catch (e: Exception) {
200 caughtException?.run { throw this } ?: assertions()
203 fun verifyRedirect(target: String, assertions: () -> Unit = {}) {
205 page.handleRequest(freenetRequest, templateContext)
207 } catch (re: RedirectException) {
208 if (re.target != target) {
212 } catch (e: Exception) {