From 20a32117feaea0e1a564442e2378e4b2a6dcc511 Mon Sep 17 00:00:00 2001 From: symphony-mariacristina Date: Wed, 21 Jul 2021 11:37:32 +0200 Subject: [PATCH] MML-291 Add multi-submit attribute to form element Goal of this PR is to add a new attribute to the form element called "multi-submit". This attribute accepts only two values depending if the user wants to reset or not the previous submit input. More info on this are available here: https://github.com/symphonyoss/messageml-utils/issues/291. Also a new BI item hs been introduce to track usage of multi-submit forms. --- .../symphony/messageml/bi/BiFields.java | 1 + .../symphony/messageml/elements/Form.java | 50 +++++++++-- .../messageml/markdown/nodes/EmojiNode.java | 2 +- .../messageml/elements/form/FormTest.java | 89 +++++++++++++------ 4 files changed, 107 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/symphonyoss/symphony/messageml/bi/BiFields.java b/src/main/java/org/symphonyoss/symphony/messageml/bi/BiFields.java index a3214ce9..515dd28b 100644 --- a/src/main/java/org/symphonyoss/symphony/messageml/bi/BiFields.java +++ b/src/main/java/org/symphonyoss/symphony/messageml/bi/BiFields.java @@ -57,6 +57,7 @@ public enum BiFields { TYPE_MASKED_TRUE("masked", BiEventType.MESSAGEML_ELEMENT_SENT), TYPE_MASKED_FALSE("normal", BiEventType.MESSAGEML_ELEMENT_SENT), ENTITY_TYPE("entity_type", BiEventType.MESSAGEML_ELEMENT_SENT), + MULTI_SUBMIT("is_multi_submit", BiEventType.MESSAGEML_ELEMENT_SENT), LABEL("has_label", BiEventType.MESSAGEML_ELEMENT_SENT), OPTIONS_COUNT("options_count", BiEventType.MESSAGEML_ELEMENT_SENT), VALIDATION("validation", BiEventType.MESSAGEML_ELEMENT_SENT), diff --git a/src/main/java/org/symphonyoss/symphony/messageml/elements/Form.java b/src/main/java/org/symphonyoss/symphony/messageml/elements/Form.java index da63b8bc..8f79e985 100644 --- a/src/main/java/org/symphonyoss/symphony/messageml/elements/Form.java +++ b/src/main/java/org/symphonyoss/symphony/messageml/elements/Form.java @@ -4,17 +4,22 @@ import static org.symphonyoss.symphony.messageml.elements.Button.ACTION_TYPE; import static org.symphonyoss.symphony.messageml.elements.FormElement.TYPE_ATTR; +import org.symphonyoss.symphony.messageml.MessageMLContext; import org.symphonyoss.symphony.messageml.MessageMLParser; import org.symphonyoss.symphony.messageml.bi.BiContext; import org.symphonyoss.symphony.messageml.bi.BiFields; import org.symphonyoss.symphony.messageml.bi.BiItem; import org.symphonyoss.symphony.messageml.exceptions.InvalidInputException; import org.symphonyoss.symphony.messageml.markdown.nodes.form.FormNode; +import org.symphonyoss.symphony.messageml.util.XmlPrintStream; import org.w3c.dom.Node; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * Class representing a Symphony Elements form @@ -26,9 +31,12 @@ public class Form extends Element { public static final String MESSAGEML_TAG = "form"; private static final String ID_ATTR = "id"; + private static final String MULTI_SUBMIT = "multi-submit"; + private static final String PRESENTATIONML_MULTI_SUBMIT = "data-multi-submit"; private static final int MAX_COUNT_PER_CHILD_TYPE = 50; - + private static final int MAX_LENGTH = 64; private static final String ERR_MSG_MISSING_ACTION_BTN = "The form with id '%s' should have at least one action button"; + private static final List ALLOWED_MULTI_SUBMIT = Arrays.asList("reset", "no-reset"); public Form(Element parent, FormatEnum format) { super(parent, MESSAGEML_TAG, format); @@ -49,15 +57,21 @@ public void validate() throws InvalidInputException { if (!getParent().getClass().equals(Dialog.class)) { assertAtLeastOneActionButton(); } + if(getAttribute(MULTI_SUBMIT) != null) { + assertAttributeMaxLength(MULTI_SUBMIT, MAX_LENGTH); + assertAttributeValue(MULTI_SUBMIT, ALLOWED_MULTI_SUBMIT); + } } @Override - protected void buildAttribute(MessageMLParser parser, - Node item) throws InvalidInputException { - if (ID_ATTR.equals(item.getNodeName())) { - setAttribute(ID_ATTR, getStringAttribute(item)); - } else { - throwInvalidInputException(item); + protected void buildAttribute(MessageMLParser parser, Node item) throws InvalidInputException { + switch (item.getNodeName()) { + case ID_ATTR: + case MULTI_SUBMIT: + setAttribute(item.getNodeName(), getStringAttribute(item)); + break; + default: + throwInvalidInputException(item); } } @@ -77,6 +91,26 @@ private void assertAtLeastOneActionButton() throws InvalidInputException { @Override void updateBiContext(BiContext context) { - context.addItem(new BiItem(BiFields.FORM.getValue(), new HashMap<>())); + Map formMap = new HashMap<>(); + if(getAttribute(MULTI_SUBMIT) != null){ + formMap.put(BiFields.MULTI_SUBMIT.getValue(), 1); + } + context.addItem(new BiItem(BiFields.FORM.getValue(), formMap)); + } + + @Override + void asPresentationML(XmlPrintStream out, MessageMLContext context) { + Map presentationAttrs = new LinkedHashMap<>(); + if (getAttribute(ID_ATTR) != null) { + presentationAttrs.put(ID_ATTR, getAttribute(ID_ATTR)); + } + if (getAttribute(MULTI_SUBMIT) != null) { + presentationAttrs.put(PRESENTATIONML_MULTI_SUBMIT, getAttribute(MULTI_SUBMIT)); + } + out.openElement(getPresentationMLTag(), presentationAttrs); + for (Element child : getChildren()) { + child.asPresentationML(out, context); + } + out.closeElement(); } } diff --git a/src/main/java/org/symphonyoss/symphony/messageml/markdown/nodes/EmojiNode.java b/src/main/java/org/symphonyoss/symphony/messageml/markdown/nodes/EmojiNode.java index 9fd98c1d..7d49b109 100644 --- a/src/main/java/org/symphonyoss/symphony/messageml/markdown/nodes/EmojiNode.java +++ b/src/main/java/org/symphonyoss/symphony/messageml/markdown/nodes/EmojiNode.java @@ -68,7 +68,7 @@ public String getAnnotation() { */ @Deprecated public void setAnnotation(String name) { - this.annotation = annotation; + this.annotation = name; } } diff --git a/src/test/java/org/symphonyoss/symphony/messageml/elements/form/FormTest.java b/src/test/java/org/symphonyoss/symphony/messageml/elements/form/FormTest.java index 781c40ff..0bed2ec8 100644 --- a/src/test/java/org/symphonyoss/symphony/messageml/elements/form/FormTest.java +++ b/src/test/java/org/symphonyoss/symphony/messageml/elements/form/FormTest.java @@ -1,15 +1,31 @@ package org.symphonyoss.symphony.messageml.elements.form; import org.junit.Test; +import org.symphonyoss.symphony.messageml.bi.BiFields; +import org.symphonyoss.symphony.messageml.bi.BiItem; import org.symphonyoss.symphony.messageml.elements.*; import org.symphonyoss.symphony.messageml.exceptions.InvalidInputException; +import org.symphonyoss.symphony.messageml.exceptions.ProcessingException; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; public class FormTest extends ElementTest { - private static final String ID_ATTR = "id"; - + private static final String MESSAGE_ML_WITH_MULTI_SUBMIT = "" + + "
" + + "" + + "" + + "" + + "
"; + @Test public void testEmptyForm() { String id = "empty-form"; @@ -22,14 +38,14 @@ public void testEmptyForm() { "The form with id 'empty-form' should have at least one action button", e.getMessage()); } } - + @Test public void testFormWithoutId() throws Exception { String input = "
"; expectedException.expect(InvalidInputException.class); expectedException.expectMessage("The attribute \"id\" is required"); - + context.parseMessageML(input, null, MessageML.MESSAGEML_VERSION); } @@ -86,31 +102,11 @@ public void testMultipleFormsUsingSameId() throws Exception { + ""; expectedException.expect(InvalidInputException.class); - expectedException.expectMessage("Elements must have unique ids. The following value is not unique: [" + notUniqueId + "]."); + expectedException.expectMessage( + "Elements must have unique ids. The following value is not unique: [" + notUniqueId + "]."); context.parseMessageML(message, null, MessageML.MESSAGEML_VERSION); } - private String getExpectedFormPresentationML(Form form) { - return "
"; - } - - private void verifyFormPresentation(Form form, String id) { - assertEquals(id, form.getAttribute(ID_ATTR)); - assertEquals(getExpectedFormPresentationML(form), context.getPresentationML()); - } - - - private String getExpectedFormMarkdown() { - return String.format("Form (log into desktop client to answer):\n---\n\n---\n"); - } - - private void verifyFormMarkdown() { - String markdown = context.getMarkdown(); - String expectedMarkdown = getExpectedFormMarkdown(); - assertEquals(expectedMarkdown, markdown); - } - @Test public void testWithMultipleDialogs() throws Exception { String input = "" @@ -156,5 +152,46 @@ public void testWithMultipleDialogs() throws Exception { assertTrue(presentationML.matches(expectedPattern)); } + @Test + public void testMultiSubmitReset() throws InvalidInputException, IOException, ProcessingException { + String expectedPresentationML = "
" + + "
" + + "" + + "" + + "
" + + "
"; + context.parseMessageML(MESSAGE_ML_WITH_MULTI_SUBMIT, null, MessageML.MESSAGEML_VERSION); + assertEquals(context.getPresentationML(), expectedPresentationML); + } + + @Test + public void testMultiSubmitNotAllowedValue() throws InvalidInputException, IOException, ProcessingException { + String messageML = "" + + "
" + + "" + + "" + + "" + + "
"; + expectedException.expect(InvalidInputException.class); + expectedException.expectMessage("Attribute \"multi-submit\" of element \"form\" can only be one " + + "of the following values: [reset, no-reset]."); + context.parseMessageML(messageML, null, MessageML.MESSAGEML_VERSION); + + } + @Test + public void testBiContextWithMultiForm() throws InvalidInputException, IOException, ProcessingException { + context.parseMessageML(MESSAGE_ML_WITH_MULTI_SUBMIT, null, MessageML.MESSAGEML_VERSION); + Map textFieldMap = new HashMap<>(); + textFieldMap.put(BiFields.PLACEHOLDER.getValue(), 1); + textFieldMap.put(BiFields.REQUIRED.getValue(), 1); + List expectedBiItems = + Arrays.asList( + new BiItem(BiFields.TEXT_FIELD.getValue(), textFieldMap), + new BiItem(BiFields.BUTTON.getValue(), Collections.singletonMap(BiFields.TYPE.getValue(), "action")), + new BiItem(BiFields.FORM.getValue(), Collections.singletonMap(BiFields.MULTI_SUBMIT.getValue(), 1)), + new BiItem(BiFields.MESSAGE_LENGTH.getValue(), Collections.singletonMap(BiFields.COUNT.getValue(), 190))); + List biItems = context.getBiContext().getItems(); + assertIterableEquals(expectedBiItems, biItems); + } }