♻️ Add module for configuring the web interface
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 10 Mar 2019 20:29:32 +0000 (21:29 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sun, 10 Mar 2019 20:29:32 +0000 (21:29 +0100)
src/main/kotlin/net/pterodactylus/sone/web/WebInterfaceModule.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/WebInterfaceModuleTest.kt [new file with mode: 0644]

diff --git a/src/main/kotlin/net/pterodactylus/sone/web/WebInterfaceModule.kt b/src/main/kotlin/net/pterodactylus/sone/web/WebInterfaceModule.kt
new file mode 100644 (file)
index 0000000..16f6e86
--- /dev/null
@@ -0,0 +1,123 @@
+package net.pterodactylus.sone.web
+
+import com.google.inject.*
+import freenet.l10n.*
+import freenet.support.api.*
+import net.pterodactylus.sone.core.*
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.database.*
+import net.pterodactylus.sone.freenet.*
+import net.pterodactylus.sone.freenet.wot.*
+import net.pterodactylus.sone.main.*
+import net.pterodactylus.sone.template.*
+import net.pterodactylus.sone.text.*
+import net.pterodactylus.util.template.*
+import javax.inject.Singleton
+
+class WebInterfaceModule : AbstractModule() {
+
+       @Provides
+       @Singleton
+       fun getTemplateContextFactory(
+                       soneAccessor: SoneAccessor,
+                       postAccessor: PostAccessor,
+                       replyAccessor: ReplyAccessor,
+                       identityAccessor: IdentityAccessor,
+                       profileAccessor: ProfileAccessor,
+                       l10nFilter: L10nFilter,
+                       parserFilter: ParserFilter,
+                       renderFilter: RenderFilter,
+                       linkedElementsFilter: LinkedElementsFilter,
+                       unknownDateFilter: UnknownDateFilter,
+                       imageLinkFilter: ImageLinkFilter,
+                       loaders: Loaders
+       ) =
+                       TemplateContextFactory().apply {
+                               addAccessor(Any::class.java, ReflectionAccessor())
+                               addAccessor(Collection::class.java, CollectionAccessor())
+                               addAccessor(Sone::class.java, soneAccessor)
+                               addAccessor(Post::class.java, postAccessor)
+                               addAccessor(Reply::class.java, replyAccessor)
+                               addAccessor(Album::class.java, AlbumAccessor())
+                               addAccessor(Image::class.java, ImageAccessor())
+                               addAccessor(Identity::class.java, identityAccessor)
+                               addAccessor(Trust::class.java, TrustAccessor())
+                               addAccessor(HTTPRequest::class.java, HttpRequestAccessor())
+                               addAccessor(Profile::class.java, profileAccessor)
+
+                               addFilter("date", DateFilter())
+                               addFilter("html", HtmlFilter())
+                               addFilter("replace", ReplaceFilter())
+                               addFilter("store", StoreFilter())
+                               addFilter("l10n", l10nFilter)
+                               addFilter("substring", SubstringFilter())
+                               addFilter("xml", XmlFilter())
+                               addFilter("change", RequestChangeFilter())
+                               addFilter("match", MatchFilter())
+                               addFilter("css", CssClassNameFilter())
+                               addFilter("js", JavascriptFilter())
+                               addFilter("parse", parserFilter)
+                               addFilter("shorten", ShortenFilter())
+                               addFilter("render", renderFilter)
+                               addFilter("linked-elements", linkedElementsFilter)
+                               addFilter("render-linked-element", LinkedElementRenderFilter())
+                               addFilter("reparse", ReparseFilter())
+                               addFilter("unknown", unknownDateFilter)
+                               addFilter("format", FormatFilter())
+                               addFilter("sort", CollectionSortFilter())
+                               addFilter("image-link", imageLinkFilter)
+                               addFilter("replyGroup", ReplyGroupFilter())
+                               addFilter("in", ContainsFilter())
+                               addFilter("unique", UniqueElementFilter())
+                               addFilter("mod", ModFilter())
+                               addFilter("paginate", PaginationFilter())
+
+                               addProvider(TemplateProvider.TEMPLATE_CONTEXT_PROVIDER)
+                               addProvider(loaders.templateProvider)
+                       }
+
+       @Provides
+       fun getSoneAccessor(core: Core, timeTextConverter: TimeTextConverter) =
+                       SoneAccessor(core, timeTextConverter)
+
+       @Provides
+       fun getPostAccessor(core: Core) =
+                       PostAccessor(core)
+
+       @Provides
+       fun getReplyAccessor(core: Core) =
+                       ReplyAccessor(core)
+
+       @Provides
+       fun getIdentityAccessor(core: Core) =
+                       IdentityAccessor(core)
+
+       @Provides
+       fun getProfileAccessor(core: Core) =
+                       ProfileAccessor(core)
+
+       @Provides
+       fun getL10nFilter(l10n: BaseL10n) =
+                       L10nFilter(l10n)
+
+       @Provides
+       fun getParserFilter(core: Core, soneTextParser: SoneTextParser) =
+                       ParserFilter(core, soneTextParser)
+
+       @Provides
+       fun getRenderFilter(soneProvider: SoneProvider, soneTextParser: SoneTextParser, htmlFilter: HtmlFilter) =
+                       RenderFilter(soneProvider, soneTextParser, htmlFilter)
+
+       @Provides
+       fun getLinkedElementsFilter(elementLoader: ElementLoader) =
+                       LinkedElementsFilter(elementLoader)
+
+       @Provides
+       fun getUnknownDateFilter(l10n: BaseL10n) =
+                       UnknownDateFilter(l10n, "View.Sone.Text.UnknownDate")
+
+       @Provides
+       fun getImageLinkFilter(core: Core) =
+                       ImageLinkFilter(core)
+
+}
diff --git a/src/test/kotlin/net/pterodactylus/sone/web/WebInterfaceModuleTest.kt b/src/test/kotlin/net/pterodactylus/sone/web/WebInterfaceModuleTest.kt
new file mode 100644 (file)
index 0000000..fc8964a
--- /dev/null
@@ -0,0 +1,260 @@
+package net.pterodactylus.sone.web
+
+import com.google.inject.Guice.*
+import freenet.l10n.*
+import freenet.support.api.*
+import net.pterodactylus.sone.core.*
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.database.*
+import net.pterodactylus.sone.freenet.*
+import net.pterodactylus.sone.freenet.wot.*
+import net.pterodactylus.sone.main.*
+import net.pterodactylus.sone.template.*
+import net.pterodactylus.sone.test.*
+import net.pterodactylus.sone.text.*
+import net.pterodactylus.util.template.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import org.junit.*
+
+class WebInterfaceModuleTest {
+
+       private val webInterfaceModule = WebInterfaceModule()
+       private val l10n = mock<BaseL10n>()
+       private val loaders = mock<Loaders>()
+       private val additionalModules = arrayOf(
+                       Core::class.isProvidedByMock(),
+                       SoneProvider::class.isProvidedByMock(),
+                       BaseL10n::class.isProvidedBy(l10n),
+                       SoneTextParser::class.isProvidedByMock(),
+                       ElementLoader::class.isProvidedByMock(),
+                       Loaders::class.isProvidedBy(loaders)
+       )
+       private val injector = createInjector(webInterfaceModule, *additionalModules)!!
+       private val templateContext by lazy { injector.getInstance<TemplateContextFactory>().createTemplateContext()!! }
+
+       @Test
+       fun `template context factory creates template with reflection accessor for objects`() {
+               verifyAccessor<Any, ReflectionAccessor>()
+       }
+
+       @Test
+       fun `template context factory creates template with collection accessor for collections`() {
+               verifyAccessor<Collection<*>, CollectionAccessor>()
+       }
+
+       @Test
+       fun `template context contains sone accessor for sones`() {
+               verifyAccessor<Sone, SoneAccessor>()
+       }
+
+       @Test
+       fun `template context contains post accessor for posts`() {
+               verifyAccessor<Post, PostAccessor>()
+       }
+
+       @Test
+       fun `template context contains reply accessor for replies`() {
+               verifyAccessor<Reply<*>, ReplyAccessor>()
+       }
+
+       @Test
+       fun `template context contains album accessor for albums`() {
+               verifyAccessor<Album, AlbumAccessor>()
+       }
+
+       @Test
+       fun `template context contains image accessor for images`() {
+               verifyAccessor<Image, ImageAccessor>()
+       }
+
+       @Test
+       fun `template context contains identity accessor for identities`() {
+               verifyAccessor<Identity, IdentityAccessor>()
+       }
+
+       @Test
+       fun `template context contains trust accessor for trusts`() {
+               verifyAccessor<Trust, TrustAccessor>()
+       }
+
+       @Test
+       fun `template context contains http request accessor for http requests`() {
+               verifyAccessor<HTTPRequest, HttpRequestAccessor>()
+       }
+
+       @Test
+       fun `template context contains profile accessor for profiles`() {
+               verifyAccessor<Profile, ProfileAccessor>()
+       }
+
+       private inline fun <reified O, reified A : Accessor> verifyAccessor() {
+               assertThat(templateContext.getAccessor(O::class.java), instanceOf(A::class.java))
+       }
+
+       @Test
+       fun `template context contains date filter`() {
+               verifyFilter<DateFilter>("date")
+       }
+
+       @Test
+       fun `template context contains html filter`() {
+               verifyFilter<HtmlFilter>("html")
+       }
+
+       @Test
+       fun `template context contains replace filter`() {
+               verifyFilter<ReplaceFilter>("replace")
+       }
+
+       @Test
+       fun `template context contains store filter`() {
+               verifyFilter<StoreFilter>("store")
+       }
+
+       @Test
+       fun `template context contains l10n filter`() {
+               verifyFilter<L10nFilter>("l10n")
+       }
+
+       @Test
+       fun `template context contains substring filter`() {
+               verifyFilter<SubstringFilter>("substring")
+       }
+
+       @Test
+       fun `template context contains xml filter`() {
+               verifyFilter<XmlFilter>("xml")
+       }
+
+       @Test
+       fun `template context contains change filter`() {
+               verifyFilter<RequestChangeFilter>("change")
+       }
+
+       @Test
+       fun `template context contains match filter`() {
+               verifyFilter<MatchFilter>("match")
+       }
+
+       @Test
+       fun `template context contains css filter`() {
+               verifyFilter<CssClassNameFilter>("css")
+       }
+
+       @Test
+       fun `template context contains js filter`() {
+               verifyFilter<JavascriptFilter>("js")
+       }
+
+       @Test
+       fun `template context contains parser filter`() {
+               verifyFilter<ParserFilter>("parse")
+       }
+
+       @Test
+       fun `template context contains shorten filter`() {
+               verifyFilter<ShortenFilter>("shorten")
+       }
+
+       @Test
+       fun `template context contains render filter`() {
+               verifyFilter<RenderFilter>("render")
+       }
+
+       @Test
+       fun `template context contains linked elements filter`() {
+               verifyFilter<LinkedElementsFilter>("linked-elements")
+       }
+
+       @Test
+       fun `template context contains linked elements render filter`() {
+               verifyFilter<LinkedElementRenderFilter>("render-linked-element")
+       }
+
+       @Test
+       fun `template context contains reparse filter`() {
+               verifyFilter<ReparseFilter>("reparse")
+       }
+
+       @Test
+       fun `template context contains unknown date filter`() {
+               verifyFilter<UnknownDateFilter>("unknown")
+       }
+
+       @Test
+       fun `unknown date filter uses correct l10n key`() {
+               whenever(l10n.getString("View.Sone.Text.UnknownDate")).thenReturn("unknown")
+               assertThat(getFilter("unknown")!!.format(null, 0L, emptyMap()), equalTo<Any>("unknown"))
+       }
+
+       @Test
+       fun `template context contains format filter`() {
+               verifyFilter<FormatFilter>("format")
+       }
+
+       @Test
+       fun `template context contains collection sort filter`() {
+               verifyFilter<CollectionSortFilter>("sort")
+       }
+
+       @Test
+       fun `template context contains image link filter`() {
+               verifyFilter<ImageLinkFilter>("image-link")
+       }
+
+       @Test
+       fun `template context contains reply group filter`() {
+               verifyFilter<ReplyGroupFilter>("replyGroup")
+       }
+
+       @Test
+       fun `template context contains contains filter`() {
+               verifyFilter<ContainsFilter>("in")
+       }
+
+       @Test
+       fun `template context unique elements filter`() {
+               verifyFilter<UniqueElementFilter>("unique")
+       }
+
+       @Test
+       fun `template context mod filter`() {
+               verifyFilter<ModFilter>("mod")
+       }
+
+       @Test
+       fun `template context pagination filter`() {
+               verifyFilter<PaginationFilter>("paginate")
+       }
+
+       private inline fun <reified F : Filter> verifyFilter(name: String) {
+               assertThat(getFilter(name), instanceOf(F::class.java))
+       }
+
+       private fun getFilter(name: String): Filter? = templateContext.getFilter(name)
+
+       @Test
+       fun `template context factory is created as singleton`() {
+           val factory1 = injector.getInstance<TemplateContextFactory>()
+           val factory2 = injector.getInstance<TemplateContextFactory>()
+               assertThat(factory1, sameInstance(factory2))
+       }
+
+       @Test
+       fun `template from classpath is returned`() {
+               val template = Template()
+               templateContext["testTemplate"] = template
+               assertThat(templateContext.getTemplate("testTemplate"), sameInstance(template))
+       }
+
+       @Test
+       fun `template from loaders’ provider is returned`() {
+               val template = Template()
+               whenever(loaders.templateProvider).thenReturn(TemplateProvider { _, templateName ->
+                       template.takeIf { templateName == "testTemplate" }
+               })
+               assertThat(templateContext.getTemplate("testTemplate"), sameInstance(template))
+       }
+
+}