Add base JSON page that requires a logged-in user
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 9 Sep 2017 10:12:31 +0000 (12:12 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 9 Sep 2017 10:38:14 +0000 (12:38 +0200)
16 files changed:
src/main/java/net/pterodactylus/sone/web/ajax/FollowSoneAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/LikeAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/MoveProfileFieldAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/TrustAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/UnfollowSoneAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/UnlikeAjaxPage.java
src/main/java/net/pterodactylus/sone/web/ajax/UntrustAjaxPage.java
src/main/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/CreateReplyAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DeletePostAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DeleteProfileFieldAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DeleteReplyAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DistrustAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/EditProfileFieldAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/LoggedInJsonPage.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPageTest.kt

index 6a2d8ce..1ef8773 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import com.google.common.base.Optional;
 
 import net.pterodactylus.sone.data.Sone;
@@ -28,7 +30,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class FollowSoneAjaxPage extends JsonPage {
+public class FollowSoneAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “follow Sone” AJAX page.
@@ -43,17 +45,14 @@ public class FollowSoneAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String soneId = request.getHttpRequest().getParam("sone");
                Optional<Sone> sone = webInterface.getCore().getSone(soneId);
                if (!sone.isPresent()) {
                        return createErrorJsonObject("invalid-sone-id");
                }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
                webInterface.getCore().followSone(currentSone, soneId);
                webInterface.getCore().markSoneKnown(sone.get());
                return createSuccessJsonObject();
index f088acb..666b1bf 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.web.WebInterface;
@@ -27,7 +29,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class LikeAjaxPage extends JsonPage {
+public class LikeAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “like post” AJAX page.
@@ -42,17 +44,14 @@ public class LikeAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String type = request.getHttpRequest().getParam("type", null);
                String id = request.getHttpRequest().getParam(type, null);
                if ((id == null) || (id.length() == 0)) {
                        return createErrorJsonObject("invalid-" + type + "-id");
                }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
                if ("post".equals(type)) {
                        currentSone.addLikedPostId(id);
                        webInterface.getCore().touchConfiguration();
index e8377f9..d4685e9 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Profile.Field;
 import net.pterodactylus.sone.data.Sone;
@@ -30,7 +32,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  * @see Profile#moveFieldDown(Field)
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class MoveProfileFieldAjaxPage extends JsonPage {
+public class MoveProfileFieldAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “move profile field” AJAX page.
@@ -49,9 +51,9 @@ public class MoveProfileFieldAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
-               Sone currentSone = getCurrentSone(request.getToadletContext());
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                Profile profile = currentSone.getProfile();
                String fieldId = request.getHttpRequest().getParam("field");
                Field field = profile.getFieldById(fieldId);
index a186d46..d0247cb 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import com.google.common.base.Optional;
 
 import net.pterodactylus.sone.core.Core;
@@ -30,7 +32,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  * @see Core#trustSone(Sone, Sone)
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class TrustAjaxPage extends JsonPage {
+public class TrustAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “trust Sone” AJAX handler.
@@ -45,12 +47,9 @@ public class TrustAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
-               Sone currentSone = getCurrentSone(request.getToadletContext(), false);
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String soneId = request.getHttpRequest().getParam("sone");
                Optional<Sone> sone = webInterface.getCore().getSone(soneId);
                if (!sone.isPresent()) {
index 58af936..28ffbf2 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.web.WebInterface;
 import net.pterodactylus.sone.web.page.FreenetRequest;
@@ -26,7 +28,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class UnfollowSoneAjaxPage extends JsonPage {
+public class UnfollowSoneAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “unfollow Sone” AJAX page.
@@ -41,16 +43,13 @@ public class UnfollowSoneAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String soneId = request.getHttpRequest().getParam("sone");
                if (!webInterface.getCore().getSone(soneId).isPresent()) {
                        return createErrorJsonObject("invalid-sone-id");
                }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
                webInterface.getCore().unfollowSone(currentSone, soneId);
                return createSuccessJsonObject();
        }
index 2eaaa68..a527b94 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.web.WebInterface;
@@ -27,7 +29,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class UnlikeAjaxPage extends JsonPage {
+public class UnlikeAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “unlike post” AJAX page.
@@ -42,17 +44,14 @@ public class UnlikeAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String type = request.getHttpRequest().getParam("type", null);
                String id = request.getHttpRequest().getParam(type, null);
                if ((id == null) || (id.length() == 0)) {
                        return createErrorJsonObject("invalid-" + type + "-id");
                }
-               Sone currentSone = getCurrentSone(request.getToadletContext());
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
                if ("post".equals(type)) {
                        currentSone.removeLikedPostId(id);
                        webInterface.getCore().touchConfiguration();
index 644dfd6..5ba6693 100644 (file)
@@ -17,6 +17,8 @@
 
 package net.pterodactylus.sone.web.ajax;
 
+import javax.annotation.Nonnull;
+
 import com.google.common.base.Optional;
 
 import net.pterodactylus.sone.core.Core;
@@ -30,7 +32,7 @@ import net.pterodactylus.sone.web.page.FreenetRequest;
  * @see Core#untrustSone(Sone, Sone)
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class UntrustAjaxPage extends JsonPage {
+public class UntrustAjaxPage extends LoggedInJsonPage {
 
        /**
         * Creates a new “untrust Sone” AJAX handler.
@@ -45,12 +47,9 @@ public class UntrustAjaxPage extends JsonPage {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       protected JsonReturnObject createJsonObject(FreenetRequest request) {
-               Sone currentSone = getCurrentSone(request.getToadletContext(), false);
-               if (currentSone == null) {
-                       return createErrorJsonObject("auth-required");
-               }
+       protected JsonReturnObject createJsonObject(@Nonnull Sone currentSone, @Nonnull FreenetRequest request) {
                String soneId = request.getHttpRequest().getParam("sone");
                Optional<Sone> sone = webInterface.getCore().getSone(soneId);
                if (!sone.isPresent()) {
index c9bcf48..9e96e69 100644 (file)
@@ -12,23 +12,21 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * AJAX handler that creates a new post.
  */
-class CreatePostAjaxPage(webInterface: WebInterface) : JsonPage("createPost.ajax", webInterface) {
+class CreatePostAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("createPost.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
-                       getCurrentSone(request.toadletContext)?.let { sone ->
-                               request.parameters["text"].emptyToNull
-                                               ?.let { TextFilter.filter(request.headers["Host"], it) }
-                                               ?.let { text ->
-                                                       val sender = request.parameters["sender"].emptyToNull?.let(webInterface.core::getSone)?.orNull() ?: sone
-                                                       val recipient = request.parameters["recipient"].let(webInterface.core::getSone)
-                                                       webInterface.core.createPost(sender, recipient, text).let { post ->
-                                                               createSuccessJsonObject().apply {
-                                                                       put("postId", post.id)
-                                                                       put("sone", sender.id)
-                                                                       put("recipient", recipient.let(Sone::getId))
-                                                               }
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
+                       request.parameters["text"].emptyToNull
+                                       ?.let { TextFilter.filter(request.headers["Host"], it) }
+                                       ?.let { text ->
+                                               val sender = request.parameters["sender"].emptyToNull?.let(webInterface.core::getSone)?.orNull() ?: currentSone
+                                               val recipient = request.parameters["recipient"].let(webInterface.core::getSone)
+                                               webInterface.core.createPost(sender, recipient, text).let { post ->
+                                                       createSuccessJsonObject().apply {
+                                                               put("postId", post.id)
+                                                               put("sone", sender.id)
+                                                               put("recipient", recipient.let(Sone::getId))
                                                        }
-                                               } ?: createErrorJsonObject("text-required")
-                       } ?: createErrorJsonObject("auth-required")
+                                               }
+                                       } ?: createErrorJsonObject("text-required")
 
 }
index 7cf2e1e..c8f9317 100644 (file)
@@ -1,5 +1,6 @@
 package net.pterodactylus.sone.web.ajax
 
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.text.TextFilter
 import net.pterodactylus.sone.utils.emptyToNull
 import net.pterodactylus.sone.utils.headers
@@ -11,14 +12,14 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * This AJAX page create a reply.
  */
-class CreateReplyAjaxPage(webInterface: WebInterface) : JsonPage("createReply.ajax", webInterface) {
+class CreateReplyAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("createReply.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest): JsonReturnObject =
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest): JsonReturnObject =
                        request.parameters["post"].emptyToNull
                                        ?.let(webInterface.core::getPost)
                                        ?.let { post ->
                                                val text = TextFilter.filter(request.headers["Host"], request.parameters["text"])
-                                               val sender = request.parameters["sender"].let(webInterface.core::getLocalSone) ?: getCurrentSone(request.toadletContext)
+                                               val sender = request.parameters["sender"].let(webInterface.core::getLocalSone) ?: currentSone
                                                val reply = webInterface.core.createReply(sender, post, text)
                                                createSuccessJsonObject().apply {
                                                        put("reply", reply.id)
index 4d82063..74fd796 100644 (file)
@@ -1,5 +1,6 @@
 package net.pterodactylus.sone.web.ajax
 
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.utils.ifTrue
 import net.pterodactylus.sone.utils.let
 import net.pterodactylus.sone.utils.parameters
@@ -9,9 +10,9 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * This AJAX page deletes a post.
  */
-class DeletePostAjaxPage(webInterface: WebInterface) : JsonPage("deletePost.ajax", webInterface) {
+class DeletePostAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("deletePost.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
                        request.parameters["post"]
                                        .let(webInterface.core::getPost)
                                        ?.let { post ->
index 5e7c901..9595a8c 100644 (file)
@@ -1,5 +1,6 @@
 package net.pterodactylus.sone.web.ajax
 
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.utils.parameters
 import net.pterodactylus.sone.web.WebInterface
 import net.pterodactylus.sone.web.page.FreenetRequest
@@ -7,21 +8,19 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * AJAX page that lets the user delete a profile field.
  */
-class DeleteProfileFieldAjaxPage(webInterface: WebInterface) : JsonPage("deleteProfileField.ajax", webInterface) {
+class DeleteProfileFieldAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("deleteProfileField.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
-                       getCurrentSone(request.toadletContext)!!.let { currentSone ->
-                               currentSone.profile.let { profile ->
-                                       request.parameters["field"]
-                                                       ?.let(profile::getFieldById)
-                                                       ?.let { field ->
-                                                               createSuccessJsonObject().also {
-                                                                       profile.removeField(field)
-                                                                       currentSone.profile = profile
-                                                                       webInterface.core.touchConfiguration()
-                                                               }
-                                                       } ?: createErrorJsonObject("invalid-field-id")
-                               }
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
+                       currentSone.profile.let { profile ->
+                               request.parameters["field"]
+                                               ?.let(profile::getFieldById)
+                                               ?.let { field ->
+                                                       createSuccessJsonObject().also {
+                                                               profile.removeField(field)
+                                                               currentSone.profile = profile
+                                                               webInterface.core.touchConfiguration()
+                                                       }
+                                               } ?: createErrorJsonObject("invalid-field-id")
                        }
 
 }
index 762bc8e..010e02b 100644 (file)
@@ -1,5 +1,6 @@
 package net.pterodactylus.sone.web.ajax
 
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.utils.ifTrue
 import net.pterodactylus.sone.utils.let
 import net.pterodactylus.sone.utils.parameters
@@ -9,9 +10,9 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * This AJAX page deletes a reply.
  */
-class DeleteReplyAjaxPage(webInterface: WebInterface) : JsonPage("deleteReply.ajax", webInterface) {
+class DeleteReplyAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("deleteReply.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
                        request.parameters["reply"]
                                        .let(webInterface.core::getPostReply)
                                        ?.let { reply ->
index 0c56341..1c3506b 100644 (file)
@@ -1,6 +1,7 @@
 package net.pterodactylus.sone.web.ajax
 
 import net.pterodactylus.sone.core.Core
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.utils.let
 import net.pterodactylus.sone.utils.parameters
 import net.pterodactylus.sone.web.WebInterface
@@ -11,16 +12,16 @@ import net.pterodactylus.sone.web.page.FreenetRequest
  *
  * @see Core.distrustSone(Sone, Sone)
  */
-class DistrustAjaxPage(webInterface: WebInterface) : JsonPage("distrustSone.ajax", webInterface) {
+class DistrustAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("distrustSone.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
                        request.parameters["sone"]
                                        .let(webInterface.core::getSone)
                                        ?.let { sone ->
                                                createSuccessJsonObject()
                                                                .put("trustValue", webInterface.core.preferences.negativeTrust)
                                                                .also {
-                                                                       webInterface.core.distrustSone(getCurrentSone(request.toadletContext), sone)
+                                                                       webInterface.core.distrustSone(currentSone, sone)
                                                                }
                                        } ?: createErrorJsonObject("invalid-sone-id")
 
index 72ee005..e48c92d 100644 (file)
@@ -1,5 +1,6 @@
 package net.pterodactylus.sone.web.ajax
 
+import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.utils.ifFalse
 import net.pterodactylus.sone.utils.parameters
 import net.pterodactylus.sone.web.WebInterface
@@ -8,10 +9,10 @@ import net.pterodactylus.sone.web.page.FreenetRequest
 /**
  * AJAX page that lets the user rename a profile field.
  */
-class EditProfileFieldAjaxPage(webInterface: WebInterface) : JsonPage("editProfileField.ajax", webInterface) {
+class EditProfileFieldAjaxPage(webInterface: WebInterface) : LoggedInJsonPage("editProfileField.ajax", webInterface) {
 
-       override fun createJsonObject(request: FreenetRequest) =
-                       getCurrentSone(request.toadletContext).profile.let { profile ->
+       override fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
+                       currentSone.profile.let { profile ->
                                request.parameters["field"]!!
                                                .let(profile::getFieldById)
                                                ?.let { field ->
@@ -20,7 +21,7 @@ class EditProfileFieldAjaxPage(webInterface: WebInterface) : JsonPage("editProfi
                                                                        try {
                                                                                field.name = newName
                                                                                createSuccessJsonObject().also {
-                                                                                       getCurrentSone(request.toadletContext).profile = profile
+                                                                                       currentSone.profile = profile
                                                                                }
                                                                        } catch (_: IllegalArgumentException) {
                                                                                createErrorJsonObject("duplicate-field-name")
diff --git a/src/main/kotlin/net/pterodactylus/sone/web/ajax/LoggedInJsonPage.kt b/src/main/kotlin/net/pterodactylus/sone/web/ajax/LoggedInJsonPage.kt
new file mode 100644 (file)
index 0000000..acf1d73
--- /dev/null
@@ -0,0 +1,20 @@
+package net.pterodactylus.sone.web.ajax
+
+import net.pterodactylus.sone.data.Sone
+import net.pterodactylus.sone.web.WebInterface
+import net.pterodactylus.sone.web.page.FreenetRequest
+
+/**
+ * Base JSON page for all pages that require the user to be logged in.
+ */
+open class LoggedInJsonPage(path: String, webInterface: WebInterface) : JsonPage(path, webInterface) {
+
+       final override fun requiresLogin() = true
+
+       final override fun createJsonObject(request: FreenetRequest) =
+                       createJsonObject(getCurrentSone(request.toadletContext)!!, request)
+
+       open protected fun createJsonObject(currentSone: Sone, request: FreenetRequest) =
+                       createErrorJsonObject("not-implemented")
+
+}
index b153093..47fee5b 100644 (file)
@@ -17,13 +17,6 @@ import org.junit.Test
 class CreatePostAjaxPageTest : JsonPageTest("createPost.ajax", pageSupplier = ::CreatePostAjaxPage) {
 
        @Test
-       fun `page requires a current sone`() {
-               unsetCurrentSone()
-               assertThat(json.isSuccess, equalTo(false))
-               assertThat(json.error, equalTo("auth-required"))
-       }
-
-       @Test
        fun `missing text parameter returns error`() {
                assertThat(json.isSuccess, equalTo(false))
                assertThat(json.error, equalTo("text-required"))