diff --git a/src/main/java/ai/elimu/web/content/word/WordCreateController.java b/src/main/java/ai/elimu/web/content/word/WordCreateController.java index 6f208b732..0651f310c 100644 --- a/src/main/java/ai/elimu/web/content/word/WordCreateController.java +++ b/src/main/java/ai/elimu/web/content/word/WordCreateController.java @@ -121,7 +121,8 @@ public String handleSubmit( if (StringUtils.containsAny(word.getText(), " ")) { result.rejectValue("text", "WordSpace"); } - + validateWord(word, result); + if (result.hasErrors()) { model.addAttribute("word", word); model.addAttribute("timeStart", request.getParameter("timeStart")); @@ -276,4 +277,20 @@ private void autoSelectLetterSoundCorrespondences(Word word) { word.setLetterSoundCorrespondences(letterSoundCorrespondences); } + + private void validateWord(Word word, BindingResult result) { + Word existingWord = wordDao.readByTextAndType(word.getText(), word.getWordType()); + + if (existingWord != null) { + result.rejectValue("text", "NonUnique"); + } + + if (StringUtils.containsAny(word.getText(), " ")) { + result.rejectValue("text", "WordSpace"); + } + + if (word.getText() != null && word.getText().matches("[0-9\\W_]*")) { + result.rejectValue("text", "WordNumbers"); + } + } } diff --git a/src/main/webapp/WEB-INF/i18n/errors_en.properties b/src/main/webapp/WEB-INF/i18n/errors_en.properties index 63b76e5be..cea81831c 100644 --- a/src/main/webapp/WEB-INF/i18n/errors_en.properties +++ b/src/main/webapp/WEB-INF/i18n/errors_en.properties @@ -32,3 +32,4 @@ formatHint.Integer=Number (e.g. "5000") image.too.small=The image width must be at least 640px emoji.unicode.version=Only emojis up to Unicode version 9 WordSpace=Spaces are not allowed +WordNumbers=A word cannot consist of numbers diff --git a/src/test/java/ai/elimu/web/content/word/WordCreateControllerTest.java b/src/test/java/ai/elimu/web/content/word/WordCreateControllerTest.java index 2395dc5e2..6b621df53 100644 --- a/src/test/java/ai/elimu/web/content/word/WordCreateControllerTest.java +++ b/src/test/java/ai/elimu/web/content/word/WordCreateControllerTest.java @@ -19,6 +19,12 @@ import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; + +import java.util.List; + +import static org.junit.Assert.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={ @@ -34,7 +40,7 @@ public class WordCreateControllerTest { @Autowired private WordDao wordDao; - + @Before public void setup() { assertNotNull(wordCreateController); @@ -61,29 +67,82 @@ public void testHandleSubmit_emptyText() throws Exception { // assertEquals(HttpStatus.BAD_REQUEST.value(), mvcResult.getResponse().getStatus()); // assertEquals("content/word/create", mvcResult.getModelAndView().getViewName()); } - + @Test public void testHandleSubmit_success() throws Exception { Word wordHello = wordDao.readByText("hello"); assertThat(wordHello, is(nullValue())); - + int numberOfWordsBefore = wordDao.readAll().size(); - + RequestBuilder requestBuilder = MockMvcRequestBuilders .post("/content/word/create") .param("timeStart", String.valueOf(System.currentTimeMillis())) .param("text", "hello") .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE); MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn(); - + wordHello = wordDao.readByText("hello"); assertThat(wordHello, not(nullValue())); assertThat(wordHello.getText(), is("hello")); - + int numberOfWordsAfter = wordDao.readAll().size(); assertThat(numberOfWordsAfter, is(numberOfWordsBefore + 1)); - + assertEquals(HttpStatus.MOVED_TEMPORARILY.value(), mvcResult.getResponse().getStatus()); assertEquals("redirect:/content/word/list#" + wordHello.getId(), mvcResult.getModelAndView().getViewName()); } + + @Test + public void testValidateDigitsInWord() throws Exception { + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("10")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("'10'")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("\"10\"")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("[10]")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1'0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1-0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1*0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1/0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1!0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1#0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1%0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1()0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1_0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1+0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1{}0")).getAllErrors(), "WordNumbers")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("1|?><.,0")).getAllErrors(), "WordNumbers")); + assertFalse(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("10th")).getAllErrors(), "WordNumbers")); + } + + @Test + public void testValidateSpacesInWord() throws Exception { + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("Test Test")).getAllErrors(), "WordSpace")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText(" Test")).getAllErrors(), "WordSpace")); + assertTrue(containGivenErrorCode(getBindingResult(getRequestWithSpecificText("Test ")).getAllErrors(), "WordSpace")); + } + + private RequestBuilder getRequestWithSpecificText(String text) { + return MockMvcRequestBuilders + .post("/content/word/create") + .param("timeStart", String.valueOf(System.currentTimeMillis())) + .param("text", text) + .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE); + } + + private BindingResult getBindingResult(RequestBuilder requestBuilder) throws Exception { + MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn(); + return (BindingResult) mvcResult.getModelAndView().getModel().get("org.springframework.validation.BindingResult.word"); + } + + private boolean containGivenErrorCode(List objectErrorList, String error) { + for (ObjectError objectError : objectErrorList) { + for (String errorCode : objectError.getCodes()) { + if (errorCode.equals(error)) { + return true; + } + } + } + return false; + } + }