+++ /dev/null
-/*
- * 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());
- }
- }
-
-}
--- /dev/null
+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}")
+ }
+ }
+
+}
+++ /dev/null
-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);
- }
-
-}
--- /dev/null
+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")
+ }
+ }
+
+}
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 =