1 package net.pterodactylus.sone.web.ajax
3 import freenet.clients.http.ToadletContext
4 import freenet.support.SimpleReadOnlyArrayBucket
5 import freenet.support.api.HTTPRequest
6 import net.pterodactylus.sone.core.Core
7 import net.pterodactylus.sone.core.ElementLoader
8 import net.pterodactylus.sone.core.LinkedElement
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.Sone.SoneStatus
13 import net.pterodactylus.sone.data.Sone.SoneStatus.idle
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.asOptional
19 import net.pterodactylus.sone.web.WebInterface
20 import net.pterodactylus.sone.web.page.FreenetRequest
21 import net.pterodactylus.util.notify.Notification
22 import net.pterodactylus.util.web.Method.GET
23 import org.junit.Before
24 import org.mockito.ArgumentMatchers.anyInt
25 import org.mockito.ArgumentMatchers.anyString
26 import org.mockito.ArgumentMatchers.isNull
27 import java.util.NoSuchElementException
28 import javax.naming.SizeLimitExceededException
31 * Base class for tests for any [JsonPage] implementations.
33 open class JsonPageTest(pageSupplier: (WebInterface) -> JsonPage = { _ -> mock<JsonPage>() }) {
35 protected val webInterface = mock<WebInterface>()
36 protected val core = mock<Core>()
37 protected val elementLoader = mock<ElementLoader>()
38 protected open val page: JsonPage by lazy { pageSupplier(webInterface) }
39 protected val json by lazy { page.createJsonObject(freenetRequest)!! }
41 protected val toadletContext = mock<ToadletContext>()
42 protected val freenetRequest = mock<FreenetRequest>()
43 protected val httpRequest = mock<HTTPRequest>()
44 protected val currentSone = deepMock<Sone>()
46 private val requestParameters = mutableMapOf<String, String>()
47 private val requestParts = mutableMapOf<String, String>()
48 private val localSones = mutableMapOf<String, Sone>()
49 private val remoteSones = mutableMapOf<String, Sone>()
50 private val newPosts = mutableMapOf<String, Post>()
51 private val newReplies = mutableMapOf<String, PostReply>()
52 private val linkedElements = mutableMapOf<String, LinkedElement>()
53 private val notifications = mutableListOf<Notification>()
56 fun setupWebInterface() {
57 whenever(webInterface.getCurrentSoneCreatingSession(toadletContext)).thenReturn(currentSone)
58 whenever(webInterface.getCurrentSoneWithoutCreatingSession(toadletContext)).thenReturn(currentSone)
59 whenever(webInterface.core).thenReturn(core)
60 whenever(webInterface.getNotifications(currentSone)).thenAnswer { notifications }
61 whenever(webInterface.getNewPosts(currentSone)).thenAnswer { newPosts.values }
62 whenever(webInterface.getNewReplies(currentSone)).thenAnswer { newReplies.values }
67 whenever(core.getSone(anyString())).thenAnswer { (localSones + remoteSones)[it.getArgument(0)].asOptional() }
68 whenever(core.getPost(anyString())).thenAnswer { newPosts[it[0]].asOptional() }
72 fun setupElementLoader() {
73 whenever(elementLoader.loadElement(anyString())).thenAnswer {
74 linkedElements[it.getArgument(0)] ?: LinkedElement(it.getArgument(0), loading = true)
79 fun setupCurrentSone() {
80 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
84 fun setupFreenetRequest() {
85 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
86 whenever(freenetRequest.method).thenReturn(GET)
87 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
91 fun setupHttpRequest() {
92 whenever(httpRequest.method).thenReturn("GET")
93 whenever(httpRequest.getParam(anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
94 whenever(httpRequest.getParam(anyString(), anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
95 whenever(httpRequest.getParam(anyString(), isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
96 whenever(httpRequest.getPart(anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
97 whenever(httpRequest.getPartAsBytesFailsafe(anyString(), anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
98 whenever(httpRequest.getPartAsBytesThrowing(anyString(), anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.let { it.toByteArray().let { if (it.size > invocation.getArgument<Int>(1)) throw SizeLimitExceededException() else it } } ?: throw NoSuchElementException() }
99 whenever(httpRequest.getPartAsStringFailsafe(anyString(), anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
100 whenever(httpRequest.getPartAsStringThrowing(anyString(), anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.let { if (it.length > invocation.getArgument<Int>(1)) throw SizeLimitExceededException() else it } ?: throw NoSuchElementException() }
101 whenever(httpRequest.getIntPart(anyString(), anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
102 whenever(httpRequest.isPartSet(anyString())).thenAnswer { it.getArgument(0) in requestParts }
105 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
106 whenever(this.id).thenReturn(id)
107 whenever(this.name).thenReturn(name)
108 whenever(isLocal).thenReturn(local)
109 whenever(this.time).thenReturn(time)
110 whenever(this.status).thenReturn(status)
113 protected fun unsetCurrentSone() {
114 whenever(webInterface.getCurrentSoneWithoutCreatingSession(toadletContext)).thenReturn(null)
115 whenever(webInterface.getCurrentSoneCreatingSession(toadletContext)).thenReturn(null)
118 protected fun addRequestParameter(key: String, value: String) {
119 requestParameters += key to value
122 protected fun addRequestPart(key: String, value: String) {
123 requestParts += key to value
126 protected fun addNotification(vararg notifications: Notification) {
127 this.notifications += notifications
130 protected fun addSone(sone: Sone) {
131 remoteSones += sone.id to sone
134 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
136 whenever(this.id).thenReturn(id)
137 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
138 whenever(this.sone).thenReturn(sone)
139 whenever(this.time).thenReturn(time)
140 whenever(this.recipientId).thenReturn(recipientId.asOptional())
141 }.also { newPosts[id] = it }
143 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
144 newReplies[id] = mock<PostReply>().apply {
145 whenever(this.id).thenReturn(id)
146 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
147 whenever(this.sone).thenReturn(sone)
148 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
149 val post = mock<Post>().apply {
150 whenever(this.sone).thenReturn(postSone)
152 whenever(this.post).thenReturn(post.asOptional())
153 whenever(this.postId).thenReturn(postId)
157 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
158 linkedElements[link] = LinkedElement(link, failed, loading)