1 package net.pterodactylus.sone.web.ajax
3 import com.fasterxml.jackson.databind.ObjectMapper
4 import com.google.common.eventbus.EventBus
5 import freenet.clients.http.ToadletContext
6 import freenet.support.SimpleReadOnlyArrayBucket
7 import freenet.support.api.HTTPRequest
8 import net.pterodactylus.sone.core.Core
9 import net.pterodactylus.sone.core.ElementLoader
10 import net.pterodactylus.sone.core.LinkedElement
11 import net.pterodactylus.sone.core.Preferences
12 import net.pterodactylus.sone.core.UpdateChecker
13 import net.pterodactylus.sone.data.Album
14 import net.pterodactylus.sone.data.Image
15 import net.pterodactylus.sone.data.Post
16 import net.pterodactylus.sone.data.PostReply
17 import net.pterodactylus.sone.data.Profile
18 import net.pterodactylus.sone.data.Sone
19 import net.pterodactylus.sone.data.Sone.SoneStatus
20 import net.pterodactylus.sone.data.Sone.SoneStatus.idle
21 import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions
22 import net.pterodactylus.sone.freenet.*
23 import net.pterodactylus.sone.test.deepMock
24 import net.pterodactylus.sone.test.get
25 import net.pterodactylus.sone.test.mock
26 import net.pterodactylus.sone.test.whenever
27 import net.pterodactylus.sone.utils.asOptional
28 import net.pterodactylus.sone.web.WebInterface
29 import net.pterodactylus.sone.web.page.FreenetRequest
30 import net.pterodactylus.util.notify.Notification
31 import net.pterodactylus.util.template.TemplateContextFactory
32 import net.pterodactylus.util.web.Method.GET
33 import net.pterodactylus.util.web.Method.POST
34 import org.mockito.ArgumentMatchers
36 import javax.naming.SizeLimitExceededException
39 * Base class for tests that supplies commonly used objects.
41 open class TestObjects {
43 val objectMapper = ObjectMapper()
45 val webInterface = mock<WebInterface>()
46 var formPassword = "form-password"
47 val core = mock<Core>()
48 val eventBus = mock<EventBus>()
49 val preferences = Preferences(eventBus)
50 val updateChecker = mock<UpdateChecker>()
51 val elementLoader = mock<ElementLoader>()
53 val toadletContext = mock<ToadletContext>()
54 val freenetRequest = mock<FreenetRequest>()
55 val httpRequest = mock<HTTPRequest>()
56 val currentSone = deepMock<Sone>()
57 val profile = Profile(currentSone)
59 val requestHeaders = mutableMapOf<String, String>()
60 val requestParameters = mutableMapOf<String, String>()
61 val requestParts = mutableMapOf<String, String>()
62 val localSones = mutableMapOf<String, Sone>()
63 val remoteSones = mutableMapOf<String, Sone>()
64 val posts = mutableMapOf<String, Post>()
65 val postLikes = mutableMapOf<Post, Set<Sone>>()
66 val newPosts = mutableMapOf<String, Post>()
67 val replies = mutableMapOf<String, PostReply>()
68 val replyLikes = mutableMapOf<PostReply, Set<Sone>>()
69 val newReplies = mutableMapOf<String, PostReply>()
70 val linkedElements = mutableMapOf<String, LinkedElement>()
71 val notifications = mutableMapOf<String, Notification>()
72 val albums = mutableMapOf<String, Album>()
73 val images = mutableMapOf<String, Image>()
74 val translations = mutableMapOf<String, String>()
76 private val translation = object : Translation {
77 override val currentLocale = Locale.ENGLISH
78 override fun translate(key: String) = translations[key] ?: ""
82 whenever(webInterface.templateContextFactory).thenReturn(TemplateContextFactory())
83 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(currentSone)
84 whenever(webInterface.core).thenReturn(core)
85 whenever(webInterface.formPassword).then { formPassword }
86 whenever(webInterface.getNotifications(currentSone)).thenAnswer { notifications.values }
87 whenever(webInterface.getNotification(ArgumentMatchers.anyString())).then { notifications[it[0]].asOptional() }
88 whenever(webInterface.translation).thenReturn(translation)
90 whenever(core.preferences).thenReturn(preferences)
91 whenever(core.updateChecker).thenReturn(updateChecker)
92 whenever(core.getSone(ArgumentMatchers.anyString())).thenAnswer { (localSones + remoteSones)[it.getArgument(0)] }
93 whenever(core.getLocalSone(ArgumentMatchers.anyString())).thenAnswer { localSones[it[0]] }
94 whenever(core.getPost(ArgumentMatchers.anyString())).thenAnswer { (posts + newPosts)[it[0]] }
95 whenever(core.getLikes(ArgumentMatchers.any<Post>())).then { postLikes[it[0]] ?: emptySet<Sone>() }
96 whenever(core.getLikes(ArgumentMatchers.any<PostReply>())).then { replyLikes[it[0]] ?: emptySet<Sone>() }
97 whenever(core.getPostReply(ArgumentMatchers.anyString())).then { replies[it[0]] }
98 whenever(core.getAlbum(ArgumentMatchers.anyString())).then { albums[it[0]] }
99 whenever(core.getImage(ArgumentMatchers.anyString())).then { images[it[0]] }
100 whenever(core.getImage(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())).then { images[it[0]] }
102 whenever(elementLoader.loadElement(ArgumentMatchers.anyString())).thenAnswer {
103 linkedElements[it.getArgument(0)] ?: LinkedElement(it.getArgument(0), loading = true)
106 whenever(currentSone.options).thenReturn(DefaultSoneOptions())
107 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
109 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
110 whenever(freenetRequest.method).thenReturn(GET)
111 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
113 whenever(httpRequest.method).thenReturn("GET")
114 whenever(httpRequest.getHeader(ArgumentMatchers.anyString())).thenAnswer { requestHeaders[it.get<String>(0).toLowerCase()] }
115 whenever(httpRequest.getParam(ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
116 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
117 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
118 whenever(httpRequest.getPart(ArgumentMatchers.anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
119 whenever(httpRequest.getPartAsBytesFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
120 whenever(httpRequest.getPartAsBytesThrowing(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.let { it.toByteArray().let { if (it.size > invocation.getArgument<Int>(1)) throw SizeLimitExceededException() else it } } ?: throw NoSuchElementException() }
121 whenever(httpRequest.getPartAsStringFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
122 whenever(httpRequest.getPartAsStringThrowing(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.let { if (it.length > invocation.getArgument<Int>(1)) throw SizeLimitExceededException() else it } ?: throw NoSuchElementException() }
123 whenever(httpRequest.getIntPart(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
124 whenever(httpRequest.isPartSet(ArgumentMatchers.anyString())).thenAnswer { it.getArgument(0) in requestParts }
126 whenever(currentSone.profile).thenReturn(profile)
129 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
130 whenever(this.id).thenReturn(id)
131 whenever(this.name).thenReturn(name)
132 whenever(isLocal).thenReturn(local)
133 whenever(this.time).thenReturn(time)
134 whenever(this.status).thenReturn(status)
137 protected fun unsetCurrentSone() {
138 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(null)
141 protected fun postRequest() {
142 whenever(freenetRequest.method).thenReturn(POST)
143 whenever(httpRequest.method).thenReturn("POST")
146 protected fun addRequestHeader(key: String, value: String) {
147 requestHeaders += key.toLowerCase() to value
150 protected fun addRequestParameter(key: String, value: String) {
151 requestParameters += key to value
154 protected fun addRequestPart(key: String, value: String) {
155 requestParts += key to value
158 protected fun addNotification(notification: Notification, notificationId: String? = null) {
159 notifications[notificationId ?: notification.id] = notification
162 protected fun addSone(sone: Sone, soneId: String? = null) {
163 remoteSones += (soneId ?: sone.id) to sone
166 protected fun addLocalSone(sone: Sone, id: String? = null) {
167 localSones[id ?: sone.id] = sone
170 protected fun addPost(post: Post, id: String? = null) {
171 posts[id ?: post.id] = post
174 protected fun addLikes(post: Post, vararg sones: Sone) {
175 postLikes[post] = setOf(*sones)
178 protected fun addLikes(reply: PostReply, vararg sones: Sone) {
179 replyLikes[reply] = setOf(*sones)
182 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
184 whenever(this.id).thenReturn(id)
185 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
186 whenever(this.sone).thenReturn(sone)
187 whenever(this.time).thenReturn(time)
188 whenever(this.recipientId).thenReturn(recipientId.asOptional())
189 }.also { newPosts[id] = it }
191 protected fun addReply(reply: PostReply, id: String? = null) {
192 replies[id ?: reply.id] = reply
195 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
196 newReplies[id] = mock<PostReply>().apply {
197 whenever(this.id).thenReturn(id)
198 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
199 whenever(this.sone).thenReturn(sone)
200 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
201 val post = mock<Post>().apply {
202 whenever(this.sone).thenReturn(postSone)
204 whenever(this.post).thenReturn(post.asOptional())
205 whenever(this.postId).thenReturn(postId)
209 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
210 linkedElements[link] = LinkedElement(link, failed, loading)
213 protected fun addAlbum(album: Album, albumId: String? = null) {
214 albums[albumId ?: album.id] = album
217 protected fun addImage(image: Image, imageId: String? = null) {
218 images[imageId ?: image.id] = image
221 protected fun addTranslation(key: String, value: String) {
222 translations[key] = value