♻️ Add factory for page maker interactions
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 27 May 2019 05:11:23 +0000 (07:11 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 27 May 2019 05:11:23 +0000 (07:11 +0200)
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetTemplatePage.kt
src/main/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactory.kt [new file with mode: 0644]
src/test/java/net/pterodactylus/sone/test/TestUtil.java
src/test/java/net/pterodactylus/sone/test/TestUtils.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/page/FreenetTemplatePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactoryTest.kt [new file with mode: 0644]

index 8cf5f61..d5d8f06 100644 (file)
@@ -36,6 +36,7 @@ open class FreenetTemplatePage(
                private val invalidFormPasswordRedirectTarget: String
 ) : FreenetPage, LinkEnabledCallback {
 
+       private val pageMakerInteractionFactory: PageMakerInteractionFactory = DefaultPageMakerInteractionFactory()
        open val styleSheets: Collection<String> = emptySet()
        open val shortcutIcon: String? get() = null
        open val isFullAccessOnly get() = false
@@ -70,16 +71,11 @@ open class FreenetTemplatePage(
                                return RedirectResponse(invalidFormPasswordRedirectTarget)
                        }
                }
-               val pageMaker = toadletContext.pageMaker
-               val pageNode = pageMaker.getPageNode(getPageTitle(request), toadletContext)
 
-               styleSheets.forEach(pageNode::addCustomStyleSheet)
-               getAdditionalLinkNodes(request)
-                               .map { it to pageNode.headNode.addChild("link") }
-                               .forEach { (linkNodeParameters, linkNode) ->
-                                       linkNodeParameters.forEach(linkNode::addAttribute)
-                               }
-               shortcutIcon?.let { pageNode.addForwardLink("icon", it) }
+               val pageMakerInteraction = pageMakerInteractionFactory.createPageMaker(toadletContext, getPageTitle(request))
+               styleSheets.forEach(pageMakerInteraction::addStyleSheet)
+               getAdditionalLinkNodes(request).forEach(pageMakerInteraction::addLinkNode)
+               shortcutIcon?.let(pageMakerInteraction::addShortcutIcon)
 
                val output = try {
                        val start = System.nanoTime()
@@ -93,9 +89,9 @@ open class FreenetTemplatePage(
                        return RedirectResponse(re1.target ?: "")
                }
 
-               pageNode.content.addChild("%", output)
+               pageMakerInteraction.setContent(output)
 
-               return response.setStatusCode(200).setStatusText("OK").setContentType("text/html").write(pageNode.outer.generate())
+               return response.setStatusCode(200).setStatusText("OK").setContentType("text/html").write(pageMakerInteraction.renderPage())
        }
 
        open fun processTemplate(request: FreenetRequest, templateContext: TemplateContext) {
diff --git a/src/main/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactory.kt b/src/main/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactory.kt
new file mode 100644 (file)
index 0000000..e55e33f
--- /dev/null
@@ -0,0 +1,18 @@
+package net.pterodactylus.sone.web.page
+
+import com.google.inject.*
+import freenet.clients.http.*
+
+@ImplementedBy(DefaultPageMakerInteractionFactory::class)
+interface PageMakerInteractionFactory {
+
+       fun createPageMaker(toadletContext: ToadletContext, pageTitle: String): PageMakerInteraction
+
+}
+
+class DefaultPageMakerInteractionFactory : PageMakerInteractionFactory {
+
+       override fun createPageMaker(toadletContext: ToadletContext, pageTitle: String) =
+                       PageMakerInteraction(toadletContext, pageTitle)
+
+}
index 35e8202..745733f 100644 (file)
@@ -6,11 +6,15 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
+import kotlin.Deprecated;
+import kotlin.ReplaceWith;
+
 /**
  * Utilities for testing.
  */
 public class TestUtil {
 
+       @Deprecated(message = "It only checks the given class, not its superclasses.", replaceWith = @ReplaceWith(imports = { "net.pterodactylus.sone.test" }, expression = "setField(`object`, fieldName, value)"))
        public static void setFinalField(Object object, String fieldName, Object value) {
                try {
                        Field clientCoreField = object.getClass().getField(fieldName);
diff --git a/src/test/java/net/pterodactylus/sone/test/TestUtils.kt b/src/test/java/net/pterodactylus/sone/test/TestUtils.kt
new file mode 100644 (file)
index 0000000..9996925
--- /dev/null
@@ -0,0 +1,19 @@
+package net.pterodactylus.sone.test
+
+import java.lang.reflect.*
+
+private val modifiers = Field::class.java.getDeclaredField("modifiers").apply {
+       isAccessible = true
+}
+
+fun setField(instance: Any, name: String, value: Any?) {
+       generateSequence<Class<*>>(instance.javaClass) { it.superclass }
+                       .flatMap { it.declaredFields.asSequence() }
+                       .filter { it.name == name }
+                       .toList()
+                       .forEach { field ->
+                               field.isAccessible = true
+                               modifiers.setInt(field, field.modifiers and Modifier.FINAL.inv())
+                               field.set(instance, value)
+                       }
+}
index d680609..2474d08 100644 (file)
@@ -8,6 +8,8 @@ import org.hamcrest.MatcherAssert.*
 import org.hamcrest.Matchers.*
 import org.junit.*
 import org.mockito.Mockito.*
+import java.io.*
+import java.nio.charset.StandardCharsets.*
 
 class FreenetTemplatePageTest {
 
@@ -121,6 +123,21 @@ class FreenetTemplatePageTest {
        }
 
        @Test
+       @Dirty
+       fun `freenet template page creates page with correct title`() {
+               val page = object : TestPage(templateRenderer, loaders) {
+                       override fun getPageTitle(request: FreenetRequest) = "page title"
+               }
+               val request = deepMock<FreenetRequest>()
+               val pageMakerInteractionFactory = deepMock<PageMakerInteractionFactory>()
+               whenever(pageMakerInteractionFactory.createPageMaker(request.toadletContext, "page title").renderPage()).thenReturn("<page>")
+               setField(page, "pageMakerInteractionFactory", pageMakerInteractionFactory)
+               val response = page.handleRequest(request, Response(ByteArrayOutputStream()))
+               assertThat(response.statusCode, equalTo(200))
+               assertThat((response.content as ByteArrayOutputStream).toString(UTF_8.name()), equalTo("<page>"))
+       }
+
+       @Test
        fun `template from annotation is loaded`() {
                verify(loaders).loadTemplate("template-path")
        }
diff --git a/src/test/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactoryTest.kt b/src/test/kotlin/net/pterodactylus/sone/web/page/PageMakerInteractionFactoryTest.kt
new file mode 100644 (file)
index 0000000..8e16094
--- /dev/null
@@ -0,0 +1,28 @@
+package net.pterodactylus.sone.web.page
+
+import com.google.inject.*
+import freenet.clients.http.*
+import net.pterodactylus.sone.test.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import org.junit.*
+import org.mockito.Mockito.*
+
+class PageMakerInteractionFactoryTest {
+
+       private val pageMakerInteractionFactory: PageMakerInteractionFactory = DefaultPageMakerInteractionFactory()
+
+       @Test
+       fun `page maker interaction factory can be created by guice`() {
+               val injector = Guice.createInjector()
+               assertThat(injector.getInstance<PageMakerInteractionFactory>(), notNullValue())
+       }
+
+       @Test
+       fun `page maker interaction sets page title correctly`() {
+               val toadletContext = deepMock<ToadletContext>()
+               pageMakerInteractionFactory.createPageMaker(toadletContext, "page title")
+               verify(toadletContext.pageMaker).getPageNode("page title", toadletContext)
+       }
+
+}