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.getNewPosts(currentSone)).thenAnswer { newPosts.values }
89 whenever(webInterface.getNewReplies(currentSone)).thenAnswer { newReplies.values }
90 whenever(webInterface.translation).thenReturn(translation)
92 whenever(core.preferences).thenReturn(preferences)
93 whenever(core.updateChecker).thenReturn(updateChecker)
94 whenever(core.getSone(ArgumentMatchers.anyString())).thenAnswer { (localSones + remoteSones)[it.getArgument(0)] }
95 whenever(core.getLocalSone(ArgumentMatchers.anyString())).thenAnswer { localSones[it[0]] }
96 whenever(core.getPost(ArgumentMatchers.anyString())).thenAnswer { (posts + newPosts)[it[0]] }
97 whenever(core.getLikes(ArgumentMatchers.any<Post>())).then { postLikes[it[0]] ?: emptySet<Sone>() }
98 whenever(core.getLikes(ArgumentMatchers.any<PostReply>())).then { replyLikes[it[0]] ?: emptySet<Sone>() }
99 whenever(core.getPostReply(ArgumentMatchers.anyString())).then { replies[it[0]] }
100 whenever(core.getAlbum(ArgumentMatchers.anyString())).then { albums[it[0]] }
101 whenever(core.getImage(ArgumentMatchers.anyString())).then { images[it[0]] }
102 whenever(core.getImage(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())).then { images[it[0]] }
104 whenever(elementLoader.loadElement(ArgumentMatchers.anyString())).thenAnswer {
105 linkedElements[it.getArgument(0)] ?: LinkedElement(it.getArgument(0), loading = true)
108 whenever(currentSone.options).thenReturn(DefaultSoneOptions())
109 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
111 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
112 whenever(freenetRequest.method).thenReturn(GET)
113 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
115 whenever(httpRequest.method).thenReturn("GET")
116 whenever(httpRequest.getHeader(ArgumentMatchers.anyString())).thenAnswer { requestHeaders[it.get<String>(0).toLowerCase()] }
117 whenever(httpRequest.getParam(ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
118 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
119 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
120 whenever(httpRequest.getPart(ArgumentMatchers.anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
121 whenever(httpRequest.getPartAsBytesFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
122 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() }
123 whenever(httpRequest.getPartAsStringFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
124 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() }
125 whenever(httpRequest.getIntPart(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
126 whenever(httpRequest.isPartSet(ArgumentMatchers.anyString())).thenAnswer { it.getArgument(0) in requestParts }
128 whenever(currentSone.profile).thenReturn(profile)
131 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
132 whenever(this.id).thenReturn(id)
133 whenever(this.name).thenReturn(name)
134 whenever(isLocal).thenReturn(local)
135 whenever(this.time).thenReturn(time)
136 whenever(this.status).thenReturn(status)
139 protected fun unsetCurrentSone() {
140 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(null)
143 protected fun postRequest() {
144 whenever(freenetRequest.method).thenReturn(POST)
145 whenever(httpRequest.method).thenReturn("POST")
148 protected fun addRequestHeader(key: String, value: String) {
149 requestHeaders += key.toLowerCase() to value
152 protected fun addRequestParameter(key: String, value: String) {
153 requestParameters += key to value
156 protected fun addRequestPart(key: String, value: String) {
157 requestParts += key to value
160 protected fun addNotification(notification: Notification, notificationId: String? = null) {
161 notifications[notificationId ?: notification.id] = notification
164 protected fun addSone(sone: Sone, soneId: String? = null) {
165 remoteSones += (soneId ?: sone.id) to sone
168 protected fun addLocalSone(sone: Sone, id: String? = null) {
169 localSones[id ?: sone.id] = sone
172 protected fun addPost(post: Post, id: String? = null) {
173 posts[id ?: post.id] = post
176 protected fun addLikes(post: Post, vararg sones: Sone) {
177 postLikes[post] = setOf(*sones)
180 protected fun addLikes(reply: PostReply, vararg sones: Sone) {
181 replyLikes[reply] = setOf(*sones)
184 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
186 whenever(this.id).thenReturn(id)
187 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
188 whenever(this.sone).thenReturn(sone)
189 whenever(this.time).thenReturn(time)
190 whenever(this.recipientId).thenReturn(recipientId.asOptional())
191 }.also { newPosts[id] = it }
193 protected fun addReply(reply: PostReply, id: String? = null) {
194 replies[id ?: reply.id] = reply
197 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
198 newReplies[id] = mock<PostReply>().apply {
199 whenever(this.id).thenReturn(id)
200 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
201 whenever(this.sone).thenReturn(sone)
202 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
203 val post = mock<Post>().apply {
204 whenever(this.sone).thenReturn(postSone)
206 whenever(this.post).thenReturn(post.asOptional())
207 whenever(this.postId).thenReturn(postId)
211 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
212 linkedElements[link] = LinkedElement(link, failed, loading)
215 protected fun addAlbum(album: Album, albumId: String? = null) {
216 albums[albumId ?: album.id] = album
219 protected fun addImage(image: Image, imageId: String? = null) {
220 images[imageId ?: image.id] = image
223 protected fun addTranslation(key: String, value: String) {
224 translations[key] = value