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.anyBoolean
25 import org.mockito.ArgumentMatchers.anyInt
26 import org.mockito.ArgumentMatchers.anyString
27 import org.mockito.ArgumentMatchers.eq
28 import org.mockito.ArgumentMatchers.isNull
29 import java.util.NoSuchElementException
30 import javax.naming.SizeLimitExceededException
33 * Base class for tests for any [JsonPage] implementations.
35 open class JsonPageTest(pageSupplier: (WebInterface) -> JsonPage = { _ -> mock<JsonPage>() }) {
37 protected val webInterface = mock<WebInterface>()
38 protected val core = mock<Core>()
39 protected val elementLoader = mock<ElementLoader>()
40 protected open val page: JsonPage by lazy { pageSupplier(webInterface) }
41 protected val json by lazy { page.createJsonObject(freenetRequest)!! }
43 protected val toadletContext = mock<ToadletContext>()
44 protected val freenetRequest = mock<FreenetRequest>()
45 protected val httpRequest = mock<HTTPRequest>()
46 protected val currentSone = deepMock<Sone>()
48 private val requestHeaders = mutableMapOf<String, String>()
49 private val requestParameters = mutableMapOf<String, String>()
50 private val requestParts = mutableMapOf<String, String>()
51 private val localSones = mutableMapOf<String, Sone>()
52 private val remoteSones = mutableMapOf<String, Sone>()
53 private val posts = mutableMapOf<String, Post>()
54 private val newPosts = mutableMapOf<String, Post>()
55 private val newReplies = mutableMapOf<String, PostReply>()
56 private val linkedElements = mutableMapOf<String, LinkedElement>()
57 private val notifications = mutableListOf<Notification>()
60 fun setupWebInterface() {
61 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(currentSone)
62 whenever(webInterface.getCurrentSoneCreatingSession(toadletContext)).thenReturn(currentSone)
63 whenever(webInterface.getCurrentSoneWithoutCreatingSession(toadletContext)).thenReturn(currentSone)
64 whenever(webInterface.core).thenReturn(core)
65 whenever(webInterface.getNotifications(currentSone)).thenAnswer { notifications }
66 whenever(webInterface.getNewPosts(currentSone)).thenAnswer { newPosts.values }
67 whenever(webInterface.getNewReplies(currentSone)).thenAnswer { newReplies.values }
72 whenever(core.getSone(anyString())).thenAnswer { (localSones + remoteSones)[it.getArgument(0)].asOptional() }
73 whenever(core.getLocalSone(anyString())).thenAnswer { localSones[it[0]] }
74 whenever(core.getPost(anyString())).thenAnswer { (posts + newPosts)[it[0]].asOptional() }
78 fun setupElementLoader() {
79 whenever(elementLoader.loadElement(anyString())).thenAnswer {
80 linkedElements[it.getArgument(0)] ?: LinkedElement(it.getArgument(0), loading = true)
85 fun setupCurrentSone() {
86 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
90 fun setupFreenetRequest() {
91 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
92 whenever(freenetRequest.method).thenReturn(GET)
93 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
97 fun setupHttpRequest() {
98 whenever(httpRequest.method).thenReturn("GET")
99 whenever(httpRequest.getHeader(anyString())).thenAnswer { requestHeaders[it.get<String>(0).toLowerCase()] }
100 whenever(httpRequest.getParam(anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
101 whenever(httpRequest.getParam(anyString(), anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
102 whenever(httpRequest.getParam(anyString(), isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
103 whenever(httpRequest.getPart(anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
104 whenever(httpRequest.getPartAsBytesFailsafe(anyString(), anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
105 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() }
106 whenever(httpRequest.getPartAsStringFailsafe(anyString(), anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
107 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() }
108 whenever(httpRequest.getIntPart(anyString(), anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
109 whenever(httpRequest.isPartSet(anyString())).thenAnswer { it.getArgument(0) in requestParts }
112 protected val JsonReturnObject.error get() = if (this is JsonErrorReturnObject) this.error else null
114 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
115 whenever(this.id).thenReturn(id)
116 whenever(this.name).thenReturn(name)
117 whenever(isLocal).thenReturn(local)
118 whenever(this.time).thenReturn(time)
119 whenever(this.status).thenReturn(status)
122 protected fun unsetCurrentSone() {
123 whenever(webInterface.getCurrentSone(eq(toadletContext), anyBoolean())).thenReturn(null)
124 whenever(webInterface.getCurrentSoneWithoutCreatingSession(toadletContext)).thenReturn(null)
125 whenever(webInterface.getCurrentSoneCreatingSession(toadletContext)).thenReturn(null)
128 protected fun addRequestHeader(key: String, value: String) {
129 requestHeaders += key.toLowerCase() to value
132 protected fun addRequestParameter(key: String, value: String) {
133 requestParameters += key to value
136 protected fun addRequestPart(key: String, value: String) {
137 requestParts += key to value
140 protected fun addNotification(vararg notifications: Notification) {
141 this.notifications += notifications
144 protected fun addSone(sone: Sone) {
145 remoteSones += sone.id to sone
148 protected fun addLocalSone(id: String, sone: Sone) {
149 localSones += id to sone
152 protected fun addPost(id: String, post: Post) {
156 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
158 whenever(this.id).thenReturn(id)
159 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
160 whenever(this.sone).thenReturn(sone)
161 whenever(this.time).thenReturn(time)
162 whenever(this.recipientId).thenReturn(recipientId.asOptional())
163 }.also { newPosts[id] = it }
165 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
166 newReplies[id] = mock<PostReply>().apply {
167 whenever(this.id).thenReturn(id)
168 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
169 whenever(this.sone).thenReturn(sone)
170 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
171 val post = mock<Post>().apply {
172 whenever(this.sone).thenReturn(postSone)
174 whenever(this.post).thenReturn(post.asOptional())
175 whenever(this.postId).thenReturn(postId)
179 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
180 linkedElements[link] = LinkedElement(link, failed, loading)