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.templateContextFactory).thenReturn(TemplateContextFactory())
85 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(currentSone)
86 whenever(webInterface.core).thenReturn(core)
87 whenever(webInterface.formPassword).then { formPassword }
88 whenever(webInterface.getNotifications(currentSone)).thenAnswer { notifications.values }
89 whenever(webInterface.getNotification(ArgumentMatchers.anyString())).then { notifications[it[0]].asOptional() }
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(newElements.newPosts).then { newPosts.values }
109 whenever(newElements.newReplies).then { newReplies.values }
111 whenever(currentSone.options).thenReturn(DefaultSoneOptions())
112 currentSone.mock("soneId", "Sone_Id", true, 1000, idle)
114 whenever(freenetRequest.toadletContext).thenReturn(toadletContext)
115 whenever(freenetRequest.method).thenReturn(GET)
116 whenever(freenetRequest.httpRequest).thenReturn(httpRequest)
118 whenever(httpRequest.method).thenReturn("GET")
119 whenever(httpRequest.getHeader(ArgumentMatchers.anyString())).thenAnswer { requestHeaders[it.get<String>(0).toLowerCase()] }
120 whenever(httpRequest.getParam(ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: "" }
121 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenAnswer { requestParameters[it.getArgument(0)] ?: it.getArgument(1) }
122 whenever(httpRequest.getParam(ArgumentMatchers.anyString(), ArgumentMatchers.isNull())).thenAnswer { requestParameters[it.getArgument(0)] }
123 whenever(httpRequest.getPart(ArgumentMatchers.anyString())).thenAnswer { requestParts[it.getArgument(0)]?.let { SimpleReadOnlyArrayBucket(it.toByteArray()) } }
124 whenever(httpRequest.getPartAsBytesFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.toByteArray()?.copyOf(it.getArgument(1)) ?: ByteArray(0) }
125 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() }
126 whenever(httpRequest.getPartAsStringFailsafe(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { requestParts[it.getArgument(0)]?.substring(0, it.getArgument(1)) ?: "" }
127 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() }
128 whenever(httpRequest.getIntPart(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt())).thenAnswer { invocation -> requestParts[invocation.getArgument(0)]?.toIntOrNull() ?: invocation.getArgument(1) }
129 whenever(httpRequest.isPartSet(ArgumentMatchers.anyString())).thenAnswer { it.getArgument(0) in requestParts }
131 whenever(currentSone.profile).thenReturn(profile)
134 protected fun Sone.mock(id: String, name: String, local: Boolean = false, time: Long, status: SoneStatus = idle) = apply {
135 whenever(this.id).thenReturn(id)
136 whenever(this.name).thenReturn(name)
137 whenever(isLocal).thenReturn(local)
138 whenever(this.time).thenReturn(time)
139 whenever(this.status).thenReturn(status)
142 protected fun unsetCurrentSone() {
143 whenever(webInterface.getCurrentSone(ArgumentMatchers.eq(toadletContext))).thenReturn(null)
146 protected fun postRequest() {
147 whenever(freenetRequest.method).thenReturn(POST)
148 whenever(httpRequest.method).thenReturn("POST")
151 protected fun addRequestHeader(key: String, value: String) {
152 requestHeaders += key.toLowerCase() to value
155 protected fun addRequestParameter(key: String, value: String) {
156 requestParameters += key to value
159 protected fun addRequestPart(key: String, value: String) {
160 requestParts += key to value
163 protected fun addNotification(notification: Notification, notificationId: String? = null) {
164 notifications[notificationId ?: notification.id] = notification
167 protected fun addSone(sone: Sone, soneId: String? = null) {
168 remoteSones += (soneId ?: sone.id) to sone
171 protected fun addLocalSone(sone: Sone, id: String? = null) {
172 localSones[id ?: sone.id] = sone
175 protected fun addPost(post: Post, id: String? = null) {
176 posts[id ?: post.id] = post
179 protected fun addLikes(post: Post, vararg sones: Sone) {
180 postLikes[post] = setOf(*sones)
183 protected fun addLikes(reply: PostReply, vararg sones: Sone) {
184 replyLikes[reply] = setOf(*sones)
187 protected fun addNewPost(id: String, soneId: String, time: Long, recipientId: String? = null) =
189 whenever(this.id).thenReturn(id)
190 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
191 whenever(this.sone).thenReturn(sone)
192 whenever(this.time).thenReturn(time)
193 whenever(this.recipientId).thenReturn(recipientId.asOptional())
194 }.also { newPosts[id] = it }
196 protected fun addReply(reply: PostReply, id: String? = null) {
197 replies[id ?: reply.id] = reply
200 protected fun addNewReply(id: String, soneId: String, postId: String, postSoneId: String) {
201 newReplies[id] = mock<PostReply>().apply {
202 whenever(this.id).thenReturn(id)
203 val sone = mock<Sone>().apply { whenever(this.id).thenReturn(soneId) }
204 whenever(this.sone).thenReturn(sone)
205 val postSone = mock<Sone>().apply { whenever(this.id).thenReturn(postSoneId) }
206 val post = mock<Post>().apply {
207 whenever(this.sone).thenReturn(postSone)
209 whenever(this.post).thenReturn(post.asOptional())
210 whenever(this.postId).thenReturn(postId)
214 protected fun addLinkedElement(link: String, loading: Boolean, failed: Boolean) {
215 linkedElements[link] = LinkedElement(link, failed, loading)
218 protected fun addAlbum(album: Album, albumId: String? = null) {
219 albums[albumId ?: album.id] = album
222 protected fun addImage(image: Image, imageId: String? = null) {
223 images[imageId ?: image.id] = image
226 protected fun addTranslation(key: String, value: String) {
227 translations[key] = value