Replace create album page and test with Kotlin version
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 9 Feb 2017 17:07:49 +0000 (18:07 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 9 Feb 2017 17:52:16 +0000 (18:52 +0100)
src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java [deleted file]
src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.kt [new file with mode: 0644]
src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.java [deleted file]
src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/Mockotlin.kt

diff --git a/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java b/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java
deleted file mode 100644 (file)
index 7423b67..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Sone - CreateAlbumPage.java - Copyright © 2011–2016 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.web;
-
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Album.Modifier.AlbumTitleMustNotBeEmpty;
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.text.TextFilter;
-import net.pterodactylus.sone.web.page.FreenetRequest;
-import net.pterodactylus.util.template.Template;
-import net.pterodactylus.util.template.TemplateContext;
-import net.pterodactylus.util.web.Method;
-
-/**
- * Page that lets the user create a new album.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class CreateAlbumPage extends SoneTemplatePage {
-
-       /**
-        * Creates a new “create album” page.
-        *
-        * @param template
-        *            The template to render
-        * @param webInterface
-        *            The Sone web interface
-        */
-       public CreateAlbumPage(Template template, WebInterface webInterface) {
-               super("createAlbum.html", template, "Page.CreateAlbum.Title", webInterface, true);
-       }
-
-       //
-       // SONETEMPLATEPAGE METHODS
-       //
-
-       /**
-        * {@inheritDoc}
-        */
-       @Override
-       protected void handleRequest(FreenetRequest request, TemplateContext templateContext) throws RedirectException {
-               if (request.getMethod() == Method.POST) {
-                       String name = request.getHttpRequest().getPartAsStringFailsafe("name", 64).trim();
-                       if (name.length() == 0) {
-                               templateContext.set("nameMissing", true);
-                               return;
-                       }
-                       String description = request.getHttpRequest().getPartAsStringFailsafe("description", 256).trim();
-                       Sone currentSone = getCurrentSone(request.getToadletContext());
-                       String parentId = request.getHttpRequest().getPartAsStringFailsafe("parent", 36);
-                       Album parent = webInterface.getCore().getAlbum(parentId);
-                       if (parentId.equals("")) {
-                               parent = currentSone.getRootAlbum();
-                       }
-                       Album album = webInterface.getCore().createAlbum(currentSone, parent);
-                       try {
-                               album.modify().setTitle(name).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)).update();
-                       } catch (AlbumTitleMustNotBeEmpty atmnbe) {
-                               throw new RedirectException("emptyAlbumTitle.html");
-                       }
-                       webInterface.getCore().touchConfiguration();
-                       throw new RedirectException("imageBrowser.html?album=" + album.getId());
-               }
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.kt b/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.kt
new file mode 100644 (file)
index 0000000..5d47641
--- /dev/null
@@ -0,0 +1,41 @@
+package net.pterodactylus.sone.web
+
+import net.pterodactylus.sone.data.Album.Modifier.AlbumTitleMustNotBeEmpty
+import net.pterodactylus.sone.text.TextFilter
+import net.pterodactylus.sone.web.page.FreenetRequest
+import net.pterodactylus.util.template.Template
+import net.pterodactylus.util.template.TemplateContext
+import net.pterodactylus.util.web.Method.POST
+
+/**
+ * Page that lets the user create a new album.
+ */
+class CreateAlbumPage(template: Template, webInterface: WebInterface):
+               SoneTemplatePage("createAlbum.html", template, "Page.CreateAlbum.Title", webInterface, true) {
+
+       override fun handleRequest(request: FreenetRequest, templateContext: TemplateContext) {
+               if (request.method == POST) {
+                       val name = request.httpRequest.getPartAsStringFailsafe("name", 64).trim()
+                       if (name.isEmpty()) {
+                               templateContext["nameMissing"] = true
+                               return
+                       }
+                       val description = request.httpRequest.getPartAsStringFailsafe("description", 256).trim()
+                       val currentSone = webInterface.getCurrentSoneCreatingSession(request.toadletContext)
+                       val parentId = request.httpRequest.getPartAsStringFailsafe("parent", 36)
+                       val parent = if (parentId == "") currentSone.rootAlbum else webInterface.core.getAlbum(parentId)
+                       val album = webInterface.core.createAlbum(currentSone, parent)
+                       try {
+                               album.modify().apply {
+                                       setTitle(name)
+                                       setDescription(TextFilter.filter(request.httpRequest.getHeader("Host"), description))
+                               }.update()
+                       } catch (e: AlbumTitleMustNotBeEmpty) {
+                               throw RedirectException("emptyAlbumTitle.html")
+                       }
+                       webInterface.core.touchConfiguration()
+                       throw RedirectException("imageBrowser.html?album=${album.id}")
+               }
+       }
+
+}
diff --git a/src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.java b/src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.java
deleted file mode 100644 (file)
index da0ec0c..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-package net.pterodactylus.sone.web;
-
-import static net.pterodactylus.sone.web.WebTestUtils.redirectsTo;
-import static net.pterodactylus.util.web.Method.POST;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-import static org.mockito.Answers.RETURNS_SELF;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Album.Modifier;
-import net.pterodactylus.sone.data.Album.Modifier.AlbumTitleMustNotBeEmpty;
-import net.pterodactylus.sone.test.Dirty;
-
-import org.junit.Test;
-
-/**
- * Unit test for {@link CreateAlbumPage}.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class CreateAlbumPageTest extends WebPageTest {
-
-       private final CreateAlbumPage page = new CreateAlbumPage(template, webInterface);
-
-       @Test
-       public void pageReturnsCorrectPath() {
-               assertThat(page.getPath(), is("createAlbum.html"));
-       }
-
-       @Test
-       public void getRequestShowsTemplate() throws Exception {
-               page.processTemplate(freenetRequest, templateContext);
-       }
-
-       @Test
-       public void missingNameResultsInAttributeSetInTemplateContext() throws Exception {
-               request("", POST);
-               page.processTemplate(freenetRequest, templateContext);
-               assertThat(templateContext.get("nameMissing"), is((Object) true));
-       }
-
-       @Test
-       public void titleAndDescriptionAreSetCorrectlyOnTheAlbum() throws Exception {
-               request("", POST);
-               Album parentAlbum = createAlbum("parent-id");
-               when(core.getAlbum("parent-id")).thenReturn(parentAlbum);
-               Album newAlbum = createAlbum("album-id");
-               when(core.createAlbum(currentSone, parentAlbum)).thenReturn(newAlbum);
-               addHttpRequestParameter("name", "new name");
-               addHttpRequestParameter("description", "new description");
-               addHttpRequestParameter("parent", "parent-id");
-               expectedException.expect(redirectsTo("imageBrowser.html?album=album-id"));
-               try {
-                       page.processTemplate(freenetRequest, templateContext);
-               } finally {
-                       verify(newAlbum).modify();
-                       verify(newAlbum.modify()).setTitle("new name");
-                       verify(newAlbum.modify()).setDescription("new description");
-                       verify(newAlbum.modify()).update();
-                       verify(core).touchConfiguration();
-               }
-       }
-
-       private Album createAlbum(String albumId) {
-               Album newAlbum = mock(Album.class, RETURNS_DEEP_STUBS);
-               when(newAlbum.getId()).thenReturn(albumId);
-               Modifier albumModifier = mock(Modifier.class, RETURNS_SELF);
-               when(newAlbum.modify()).thenReturn(albumModifier);
-               when(albumModifier.update()).thenReturn(newAlbum);
-               return newAlbum;
-       }
-
-       @Test
-       public void rootAlbumIsUsedIfNoParentIsSpecified() throws Exception {
-               request("", POST);
-               Album parentAlbum = createAlbum("root-id");
-               when(currentSone.getRootAlbum()).thenReturn(parentAlbum);
-               Album newAlbum = createAlbum("album-id");
-               when(core.createAlbum(currentSone, parentAlbum)).thenReturn(newAlbum);
-               addHttpRequestParameter("name", "new name");
-               addHttpRequestParameter("description", "new description");
-               expectedException.expect(redirectsTo("imageBrowser.html?album=album-id"));
-               page.processTemplate(freenetRequest, templateContext);
-       }
-
-       @Test
-       @Dirty("that exception can never happen")
-       public void emptyAlbumTitleRedirectsToErrorPage() throws Exception {
-               request("", POST);
-               Album parentAlbum = createAlbum("root-id");
-               when(currentSone.getRootAlbum()).thenReturn(parentAlbum);
-               Album newAlbum = createAlbum("album-id");
-               when(core.createAlbum(currentSone, parentAlbum)).thenReturn(newAlbum);
-               when(newAlbum.modify().update()).thenThrow(AlbumTitleMustNotBeEmpty.class);
-               addHttpRequestParameter("name", "new name");
-               addHttpRequestParameter("description", "new description");
-               expectedException.expect(redirectsTo("emptyAlbumTitle.html"));
-               page.processTemplate(freenetRequest, templateContext);
-       }
-
-}
diff --git a/src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.kt b/src/test/java/net/pterodactylus/sone/web/CreateAlbumPageTest.kt
new file mode 100644 (file)
index 0000000..054917d
--- /dev/null
@@ -0,0 +1,102 @@
+package net.pterodactylus.sone.web
+
+import net.pterodactylus.sone.data.Album
+import net.pterodactylus.sone.data.Album.Modifier.AlbumTitleMustNotBeEmpty
+import net.pterodactylus.sone.test.deepMock
+import net.pterodactylus.sone.test.selfMock
+import net.pterodactylus.sone.test.whenever
+import net.pterodactylus.util.web.Method.POST
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.equalTo
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+/**
+ * Unit test for [CreateAlbumPage].
+ */
+class CreateAlbumPageTest: WebPageTest() {
+
+       private val page = CreateAlbumPage(template, webInterface)
+
+       override fun getPage() = page
+
+       private val parentAlbum = createAlbum("parent-id")
+       private val newAlbum = createAlbum("album-id")
+
+       @Before
+       fun setupAlbums() {
+               whenever(core.createAlbum(currentSone, parentAlbum)).thenReturn(newAlbum)
+               whenever(currentSone.rootAlbum).thenReturn(parentAlbum)
+       }
+
+       @Test
+       fun `page returns correct path`() {
+               assertThat(page.path, equalTo("createAlbum.html"))
+       }
+
+       @Test
+       fun `get request shows template`() {
+               page.processTemplate(freenetRequest, templateContext)
+       }
+
+       @Test
+       fun `missing name results in attribute being set in template context`() {
+               request("", POST)
+               page.processTemplate(freenetRequest, templateContext)
+               assertThat(templateContext["nameMissing"], equalTo<Any>(true))
+       }
+
+       private fun createAlbum(albumId: String) = deepMock<Album>().apply {
+               whenever(id).thenReturn(albumId)
+               selfMock<Album.Modifier>().let { modifier ->
+                       whenever(modifier.update()).thenReturn(this@apply)
+                       whenever(this@apply.modify()).thenReturn(modifier)
+               }
+       }
+
+       @Test
+       fun `title and description are set correctly on the album`() {
+               request("", POST)
+               addAlbum("parent-id", parentAlbum)
+               addHttpRequestParameter("name", "new name")
+               addHttpRequestParameter("description", "new description")
+               addHttpRequestParameter("parent", "parent-id")
+               verifyRedirect("imageBrowser.html?album=album-id") {
+                       verify(newAlbum).modify()
+                       verify(newAlbum.modify()).setTitle("new name")
+                       verify(newAlbum.modify()).setDescription("new description")
+                       verify(newAlbum.modify()).update()
+                       verify(core).touchConfiguration()
+               }
+       }
+
+       @Test
+       fun `root album is used if no parent is specified`() {
+               request("", POST)
+               addHttpRequestParameter("name", "new name")
+               addHttpRequestParameter("description", "new description")
+               verifyRedirect("imageBrowser.html?album=album-id")
+       }
+
+       @Test
+       fun `empty album title redirects to error page`() {
+               request("", POST)
+               whenever(newAlbum.modify().update()).thenThrow(AlbumTitleMustNotBeEmpty::class.java)
+               addHttpRequestParameter("name", "new name")
+               addHttpRequestParameter("description", "new description")
+               verifyRedirect("emptyAlbumTitle.html")
+       }
+
+       @Test
+       fun `album description is filtered`() {
+               request("", POST)
+               addHttpRequestParameter("name", "new name")
+               addHttpRequestParameter("description", "new http://localhost:12345/KSK@foo description")
+               addHttpRequestHeader("Host", "localhost:12345")
+               verifyRedirect("imageBrowser.html?album=album-id") {
+                       verify(newAlbum.modify()).setDescription("new KSK@foo description")
+               }
+       }
+
+}
index 38625ea..dada6eb 100644 (file)
@@ -8,6 +8,7 @@ import org.mockito.stubbing.OngoingStubbing
 inline fun <reified T : Any> mock(): T = Mockito.mock<T>(T::class.java)!!
 inline fun <reified T : Any> mockBuilder(): T = Mockito.mock<T>(T::class.java, Mockito.RETURNS_SELF)!!
 inline fun <reified T : Any> deepMock(): T = Mockito.mock<T>(T::class.java, Mockito.RETURNS_DEEP_STUBS)!!
 inline fun <reified T : Any> mock(): T = Mockito.mock<T>(T::class.java)!!
 inline fun <reified T : Any> mockBuilder(): T = Mockito.mock<T>(T::class.java, Mockito.RETURNS_SELF)!!
 inline fun <reified T : Any> deepMock(): T = Mockito.mock<T>(T::class.java, Mockito.RETURNS_DEEP_STUBS)!!
+inline fun <reified T : Any> selfMock(): T = Mockito.mock<T>(T::class.java, Mockito.RETURNS_SELF)!!
 inline fun <reified T : Any> capture(): ArgumentCaptor<T> = ArgumentCaptor.forClass(T::class.java)
 
 inline fun <reified T : Any> bind(implementation: T): Module =
 inline fun <reified T : Any> capture(): ArgumentCaptor<T> = ArgumentCaptor.forClass(T::class.java)
 
 inline fun <reified T : Any> bind(implementation: T): Module =