✨ Return filtered elements for get-status request
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / ajax / GetStatusAjaxPageTest.kt
1 package net.pterodactylus.sone.web.ajax
2
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
29 import org.junit.Rule
30 import org.junit.Test
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
37
38 /**
39  * Unit test for [GetStatusAjaxPage].
40  */
41 class GetStatusAjaxPageTest: JsonPageTest("getStatus.ajax", requiresLogin = false, needsFormPassword = false) {
42
43         @get:Rule
44         val overrideLocale = OverrideLocale(ENGLISH)
45
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"))
49
50         @Before
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 }
54         }
55
56         @Test
57         fun `page returns correct attribute “loggedIn” if sone is logged in`() {
58                 assertThat(json.get("loggedIn")?.asText(), equalTo("true"))
59         }
60
61         @Test
62         fun `page returns correct attribute “loggedIn” if sone is not logged in`() {
63                 unsetCurrentSone()
64                 assertThat(json.get("loggedIn")?.asText(), equalTo("false"))
65         }
66
67         @Test
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")
73                 ))
74         }
75
76         @Test
77         fun `page returns empty options if sone is not logged in`() {
78                 unsetCurrentSone()
79                 assertThat(json.get("options"), emptyIterable())
80         }
81
82         @Test
83         fun `page returns empty sones object if no sone is logged in and no sones parameter is given`() {
84                 unsetCurrentSone()
85                 assertThat(json.get("sones"), emptyIterable())
86         }
87
88         @Test
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")
92                 ))
93         }
94
95         @Test
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")
104                 ))
105         }
106
107         @Test
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) }
112                 )
113                 notifications.forEachIndexed { index, notification -> addNotification(notification, "notification$index")}
114                 assertThat(json.get("notificationHash")?.asInt(), equalTo(notifications.sortedBy { it.createdTime }.hashCode()))
115         }
116
117         @Test
118         fun `page returns new posts without current Sone`() {
119                 addNewPost("post1", "sone1", 1000)
120                 addNewPost("post2", "sone2", 2000, "sone1")
121                 unsetCurrentSone()
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")
125                 ))
126                 verify(newElements).newPosts(isNull())
127         }
128
129         @Test
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")
136                 ))
137         }
138
139         @Test
140         fun `page returns new replies without current Sone`() {
141                 addNewReply("reply1", "sone1", "post1", "sone11")
142                 addNewReply("reply2", "sone2", "post2", "sone22")
143                 unsetCurrentSone()
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")
147                 ))
148                 verify(newElements).newPosts(isNull())
149         }
150
151         @Test
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")
158                 ))
159         }
160
161         @Test
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")
171                 ))
172         }
173
174         @Test
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())
181         }
182
183         private fun JsonNode.toMap() = fields().asSequence().map { it.key!! to if (it.value.isNull) null else it.value.asText()!! }.toMap()
184
185 }