1 package net.pterodactylus.sone.web.ajax
3 import com.fasterxml.jackson.databind.JsonNode
4 import net.pterodactylus.sone.core.ElementLoader
5 import net.pterodactylus.sone.data.Sone
6 import net.pterodactylus.sone.data.Sone.SoneStatus.downloading
7 import net.pterodactylus.sone.data.Sone.SoneStatus.inserting
8 import net.pterodactylus.sone.freenet.L10nFilter
9 import net.pterodactylus.sone.freenet.L10nText
10 import net.pterodactylus.sone.test.OverrideLocale
11 import net.pterodactylus.sone.test.deepMock
12 import net.pterodactylus.sone.test.getInstance
13 import net.pterodactylus.sone.test.isProvidedByMock
14 import net.pterodactylus.sone.test.mock
15 import net.pterodactylus.sone.test.whenever
16 import net.pterodactylus.sone.text.TimeText
17 import net.pterodactylus.sone.text.TimeTextConverter
18 import net.pterodactylus.sone.utils.jsonArray
19 import net.pterodactylus.sone.web.baseInjector
20 import net.pterodactylus.util.notify.Notification
21 import org.hamcrest.MatcherAssert.assertThat
22 import org.hamcrest.Matchers.allOf
23 import org.hamcrest.Matchers.containsInAnyOrder
24 import org.hamcrest.Matchers.emptyIterable
25 import org.hamcrest.Matchers.equalTo
26 import org.hamcrest.Matchers.hasEntry
27 import org.hamcrest.Matchers.notNullValue
28 import org.junit.Before
31 import org.mockito.ArgumentMatchers.any
32 import org.mockito.ArgumentMatchers.anyLong
33 import org.mockito.ArgumentMatchers.isNull
34 import org.mockito.Mockito.verify
35 import java.util.Locale.ENGLISH
36 import java.util.TimeZone
39 * Unit test for [GetStatusAjaxPage].
41 class GetStatusAjaxPageTest: JsonPageTest("getStatus.ajax", requiresLogin = false, needsFormPassword = false) {
44 val overrideLocale = OverrideLocale(ENGLISH)
46 private val timeTextConverter = mock<TimeTextConverter>()
47 private val l10nFilter = mock<L10nFilter>()
48 override var page: JsonPage = GetStatusAjaxPage(webInterface, elementLoader, newElements, timeTextConverter, l10nFilter, TimeZone.getTimeZone("UTC"))
51 fun setupTimeTextConverter() {
52 whenever(timeTextConverter.getTimeText(anyLong())).thenAnswer { TimeText(L10nText(it.getArgument<Long>(0).toString()), it.getArgument(0)) }
53 whenever(l10nFilter.format(any(), any(), any())).thenAnswer { it.getArgument<L10nText>(1).text }
57 fun `page returns correct attribute “loggedIn” if sone is logged in`() {
58 assertThat(json.get("loggedIn")?.asText(), equalTo("true"))
62 fun `page returns correct attribute “loggedIn” if sone is not logged in`() {
64 assertThat(json.get("loggedIn")?.asText(), equalTo("false"))
68 fun `page returns options for sone if sone is logged in`() {
69 assertThat(json.get("options")?.toMap(), allOf(
70 hasEntry("ShowNotification/NewSones", "true"),
71 hasEntry("ShowNotification/NewPosts", "true"),
72 hasEntry("ShowNotification/NewReplies", "true")
77 fun `page returns empty options if sone is not logged in`() {
79 assertThat(json.get("options"), emptyIterable())
83 fun `page returns empty sones object if no sone is logged in and no sones parameter is given`() {
85 assertThat(json.get("sones"), emptyIterable())
89 fun `page returns a sones object with the current sone if not other sones parameter is given`() {
90 assertThat(json.get("sones")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
91 mapOf<String, String?>("id" to "soneId", "name" to "Sone_Id", "local" to "true", "status" to "idle", "modified" to "false", "locked" to "false", "lastUpdatedUnknown" to "false", "lastUpdated" to "Jan 1, 1970, 00:00:01", "lastUpdatedText" to "1000")
96 fun `page returns some sones objects with the current sone and some sones given as sones parameter`() {
97 addSone(deepMock<Sone>().mock("sone1", "Sone 1", false, 2000, downloading))
98 addSone(deepMock<Sone>().mock("sone3", "Sone 3", true, 3000, inserting))
99 addRequestParameter("soneIds", "sone1,sone2,sone3")
100 assertThat(json.get("sones")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
101 mapOf<String, String?>("id" to "soneId", "name" to "Sone_Id", "local" to "true", "status" to "idle", "modified" to "false", "locked" to "false", "lastUpdatedUnknown" to "false", "lastUpdated" to "Jan 1, 1970, 00:00:01", "lastUpdatedText" to "1000"),
102 mapOf("id" to "sone1", "name" to "Sone 1", "local" to "false", "status" to "downloading", "modified" to "false", "locked" to "false", "lastUpdatedUnknown" to "false", "lastUpdated" to "Jan 1, 1970, 00:00:02", "lastUpdatedText" to "2000"),
103 mapOf("id" to "sone3", "name" to "Sone 3", "local" to "true", "status" to "inserting", "modified" to "false", "locked" to "false", "lastUpdatedUnknown" to "false", "lastUpdated" to "Jan 1, 1970, 00:00:03", "lastUpdatedText" to "3000")
108 fun `page returns correct notifications hash`() {
109 val notifications = listOf(
110 mock<Notification>().apply { whenever(this.createdTime).thenReturn(2000) },
111 mock<Notification>().apply { whenever(this.createdTime).thenReturn(1000) }
113 notifications.forEachIndexed { index, notification -> addNotification(notification, "notification$index")}
114 assertThat(json.get("notificationHash")?.asInt(), equalTo(notifications.sortedBy { it.createdTime }.hashCode()))
118 fun `page returns new posts without current Sone`() {
119 addNewPost("post1", "sone1", 1000)
120 addNewPost("post2", "sone2", 2000, "sone1")
122 assertThat(json.get("newPosts")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
123 mapOf("id" to "post1", "sone" to "sone1", "time" to "1000", "recipient" to null),
124 mapOf("id" to "post2", "sone" to "sone2", "time" to "2000", "recipient" to "sone1")
126 verify(newElements).newPosts(isNull())
130 fun `page returns new posts with current Sone`() {
131 addNewPost("post1", "sone1", 1000)
132 addNewPost("post2", "sone2", 2000, "sone1")
133 whenever(newElements.newPosts(currentSone)).thenReturn(listOf(newPosts["post2"]!!))
134 assertThat(json.get("newPosts")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
135 mapOf("id" to "post2", "sone" to "sone2", "time" to "2000", "recipient" to "sone1")
140 fun `page returns new replies without current Sone`() {
141 addNewReply("reply1", "sone1", "post1", "sone11")
142 addNewReply("reply2", "sone2", "post2", "sone22")
144 assertThat(json.get("newReplies")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
145 mapOf<String, String?>("id" to "reply1", "sone" to "sone1", "post" to "post1", "postSone" to "sone11"),
146 mapOf("id" to "reply2", "sone" to "sone2", "post" to "post2", "postSone" to "sone22")
148 verify(newElements).newPosts(isNull())
152 fun `page returns new replies with current Sone`() {
153 addNewReply("reply1", "sone1", "post1", "sone11")
154 addNewReply("reply2", "sone2", "post2", "sone22")
155 whenever(newElements.newReplies(currentSone)).thenReturn(listOf(newReplies["reply2"]!!))
156 assertThat(json.get("newReplies")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
157 mapOf("id" to "reply2", "sone" to "sone2", "post" to "post2", "postSone" to "sone22")
162 fun `page returns information about loaded elements`() {
163 addLinkedElement("KSK@test.png", loading = false, failed = false)
164 addLinkedElement("KSK@test.html", loading = true, failed = false)
165 addLinkedElement("KSK@test.jpeg", loading = false, failed = true)
166 addRequestParameter("elements", jsonArray("KSK@test.png", "KSK@test.html", "KSK@test.jpeg").toString())
167 assertThat(json.get("linkedElements")!!.elements().asSequence().map { it.toMap() }.toList(), containsInAnyOrder(
168 mapOf<String, String?>("link" to "KSK@test.png", "loading" to "false", "failed" to "false"),
169 mapOf("link" to "KSK@test.html", "loading" to "true", "failed" to "false"),
170 mapOf("link" to "KSK@test.jpeg", "loading" to "false", "failed" to "true")
175 fun `page can be created by dependency injection`() {
176 assertThat(baseInjector.createChildInjector(
177 ElementLoader::class.isProvidedByMock(),
178 TimeTextConverter::class.isProvidedByMock(),
179 L10nFilter::class.isProvidedByMock()
180 ).getInstance<GetStatusAjaxPage>(), notNullValue())
183 private fun JsonNode.toMap() = fields().asSequence().map { it.key!! to if (it.value.isNull) null else it.value.asText()!! }.toMap()