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.NewElements
29 import net.pterodactylus.sone.web.WebInterface
30 import net.pterodactylus.sone.web.page.FreenetRequest
31 import net.pterodactylus.util.notify.Notification
32 import net.pterodactylus.util.template.TemplateContextFactory
33 import net.pterodactylus.util.web.Method.GET
34 import net.pterodactylus.util.web.Method.POST
35 import org.mockito.ArgumentMatchers
37 import javax.naming.SizeLimitExceededException
40 * Base class for tests that supplies commonly used objects.
42 open class TestObjects {
44 val objectMapper = ObjectMapper()
46 val webInterface = mock<WebInterface>()
47 var formPassword = "form-password"
48 val core = mock<Core>()
49 val eventBus = mock<EventBus>()
50 val preferences = Preferences(eventBus)
51 val updateChecker = mock<UpdateChecker>()
52 val elementLoader = mock<ElementLoader>()
53 val newElements = mock<NewElements>()
55 val toadletContext = mock<ToadletContext>()
56 val freenetRequest = mock<FreenetRequest>()
57 val httpRequest = mock<HTTPRequest>()
58 val currentSone = deepMock<Sone>()
59 val profile = Profile(currentSone)
61 val requestHeaders = mutableMapOf<String, String>()
62 val requestParameters = mutableMapOf<String, String>()
63 val requestParts = mutableMapOf<String, String>()
64 val localSones = mutableMapOf<String, Sone>()
65 val remoteSones = mutableMapOf<String, Sone>()
66 val posts = mutableMapOf<String, Post>()
67 val postLikes = mutableMapOf<Post, Set<Sone>>()
68 val newPosts = mutableMapOf<String, Post>()
69 val replies = mutableMapOf<String, PostReply>()
70 val replyLikes = mutableMapOf<PostReply, Set<Sone>>()
71 val newReplies = mutableMapOf<String, PostReply>()
72 val linkedElements = mutableMapOf<String, LinkedElement>()
73 val notifications = mutableMapOf<String, Notification>()
74 val albums = mutableMapOf<String, Album>()
75 val images = mutableMapOf<String, Image>()
76 val translations = mutableMapOf<String, String>()
78 private val translation = object : Translation {
79 override val currentLocale = Locale.ENGLISH
80 override fun translate(key: String) = translations[key] ?: ""
84 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(currentSone)
85 whenever(webInterface.core).thenReturn(core)
86 whenever(webInterface.formPassword).then { formPassword }
87 whenever(webInterface.getNotifications(currentSone)).thenAnswer { notifications.values }
88 whenever(webInterface.getNotification(ArgumentMatchers.anyString())).then { notifications[it[0]].asOptional() }
89 whenever(webInterface.translation).thenReturn(translation)
91 whenever(core.preferences).thenReturn(preferences)
92 whenever(core.updateChecker).thenReturn(updateChecker)
93 whenever(core.getSone(ArgumentMatchers.anyString())).thenAnswer { (localSones + remoteSones)[it.getArgument(0)] }
94 whenever(core.getLocalSone(ArgumentMatchers.anyString())).thenAnswer { localSones[it[0]] }
95 whenever(core.getPost(ArgumentMatchers.anyString())).thenAnswer { (posts + newPosts)[it[0]] }
96 whenever(core.getLikes(ArgumentMatchers.any<Post>())).then { postLikes[it[0]] ?: emptySet<Sone>() }
97 whenever(core.getLikes(ArgumentMatchers.any<PostReply>())).then { replyLikes[it[0]] ?: emptySet<Sone>() }
98 whenever(core.getPostReply(ArgumentMatchers.anyString())).then { replies[it[0]] }
99 whenever(core.getAlbum(ArgumentMatchers.anyString())).then { albums[it[0]] }
100 whenever(core.getImage(ArgumentMatchers.anyString())).then { images[it[0]] }
101 whenever(core.getImage(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean())).then { images[it[0]] }
103 whenever(elementLoader.loadElement(ArgumentMatchers.anyString())).thenAnswer {
104 linkedElements[it.getArgument(0)] ?: LinkedElement(it.getArgument(0), loading = true)
107 whenever(newElements.newPosts).then { newPosts.values }
108 whenever(newElements.newReplies).then { newReplies.values }
110 whenever(currentSone.options).thenReturn(DefaultSoneOptions())
111 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
113 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
114 whenever(freenetRequest.method).thenReturn(GET)
115 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
117 whenever(httpRequest.method).thenReturn("GET")
118 whenever(httpRequest.getHeader(ArgumentMatchers.anyString())).thenAnswer { requestHeaders[it.get<String>(0).toLowerCase()] }
119 whenever(httpRequest.getParam(ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
120 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
121 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
122 whenever(httpRequest.getPart(ArgumentMatchers.anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
123 whenever(httpRequest.getPartAsBytesFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
124 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() }
125 whenever(httpRequest.getPartAsStringFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
126 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() }
127 whenever(httpRequest.getIntPart(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
128 whenever(httpRequest.isPartSet(ArgumentMatchers.anyString())).thenAnswer { it.getArgument(0) in requestParts }
130 whenever(currentSone.profile).thenReturn(profile)
133 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
134 whenever(this.id).thenReturn(id)
135 whenever(this.name).thenReturn(name)
136 whenever(isLocal).thenReturn(local)
137 whenever(this.time).thenReturn(time)
138 whenever(this.status).thenReturn(status)
141 protected fun unsetCurrentSone() {
142 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(null)
145 protected fun postRequest() {
146 whenever(freenetRequest.method).thenReturn(POST)
147 whenever(httpRequest.method).thenReturn("POST")
150 protected fun addRequestHeader(key: String, value: String) {
151 requestHeaders += key.toLowerCase() to value
154 protected fun addRequestParameter(key: String, value: String) {
155 requestParameters += key to value
158 protected fun addRequestPart(key: String, value: String) {
159 requestParts += key to value
162 protected fun addNotification(notification: Notification, notificationId: String? = null) {
163 notifications[notificationId ?: notification.id] = notification
166 protected fun addSone(sone: Sone, soneId: String? = null) {
167 remoteSones += (soneId ?: sone.id) to sone
170 protected fun addLocalSone(sone: Sone, id: String? = null) {
171 localSones[id ?: sone.id] = sone
174 protected fun addPost(post: Post, id: String? = null) {
175 posts[id ?: post.id] = post
178 protected fun addLikes(post: Post, vararg sones: Sone) {
179 postLikes[post] = setOf(*sones)
182 protected fun addLikes(reply: PostReply, vararg sones: Sone) {
183 replyLikes[reply] = setOf(*sones)
186 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
188 whenever(this.id).thenReturn(id)
189 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
190 whenever(this.sone).thenReturn(sone)
191 whenever(this.time).thenReturn(time)
192 whenever(this.recipientId).thenReturn(recipientId.asOptional())
193 }.also { newPosts[id] = it }
195 protected fun addReply(reply: PostReply, id: String? = null) {
196 replies[id ?: reply.id] = reply
199 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
200 newReplies[id] = mock<PostReply>().apply {
201 whenever(this.id).thenReturn(id)
202 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
203 whenever(this.sone).thenReturn(sone)
204 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
205 val post = mock<Post>().apply {
206 whenever(this.sone).thenReturn(postSone)
208 whenever(this.post).thenReturn(post.asOptional())
209 whenever(this.postId).thenReturn(postId)
213 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
214 linkedElements[link] = LinkedElement(link, failed, loading)
217 protected fun addAlbum(album: Album, albumId: String? = null) {
218 albums[albumId ?: album.id] = album
221 protected fun addImage(image: Image, imageId: String? = null) {
222 images[imageId ?: image.id] = image
225 protected fun addTranslation(key: String, value: String) {
226 translations[key] = value