/*
* Copyright 2004-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springmodules.validation.valang.javascript;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import junit.framework.TestCase;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.springframework.context.support.MessageSourceAccessor;
import org.springmodules.validation.util.date.DateParseException;
import org.springmodules.validation.util.date.DefaultDateParser;
import org.springmodules.validation.valang.parser.ParseException;
import org.springmodules.validation.valang.parser.Person;
import org.springmodules.validation.valang.parser.ValangParser;
/**
* Tests for {@link ValangJavaScriptTranslator}
*
* @author Oliver Hutchison
*/
public class ValangJavaScriptTranslatorTests extends TestCase {
private Context cx;
private Scriptable scope;
public void setUp() throws Exception {
cx = Context.enter();
cx.setOptimizationLevel(-1);
cx.setLanguageVersion(Context.VERSION_1_2);
scope = cx.initStandardObjects();
cx.evaluateReader(scope, ValangJavaScriptTranslator.getCodebaseReader(), "valang_codebase.js", 1, null);
cx.evaluateReader(scope, new InputStreamReader(ValangJavaScriptTranslatorTests.class
.getResourceAsStream("test_codebase_overides.js")), "test_codebase_overides.js", 1, null);
}
protected void tearDown() throws Exception {
Context.exit();
}
private ValangParser getParser(String text) {
return new ValangParser(new StringReader(text));
}
protected Collection parseRules(String text) {
try {
return getParser(text).parseValidation();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
protected boolean validate(Object target, String text) {
return validate(target, text, null);
}
protected boolean validate(Object target, String text, MessageSourceAccessor messageSource) {
try {
Collection rules = parseRules(text);
StringWriter code = new StringWriter();
new ValangJavaScriptTranslator().writeJavaScriptValangValidator(code, "someName", false, rules,
messageSource);
code.write(".validate()");
ScriptableObject.putProperty(scope, "formObject", Context.javaToJS(target, scope));
System.out.println(code.toString());
Object evaluateString = cx.evaluateString(scope, code.toString(), "code", 1, null);
Boolean result = (Boolean) cx.jsToJava(evaluateString, Boolean.class);
return result.booleanValue();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage());
}
}
public void testTranslator1SimpleRule() {
String text = "{age : age <= 120 : 'We do not do business with the undead.'}";
assertTrue(validate(new Person(30, "Steven"), text));
}
public void testTranslator2TwoSimpleRules() {
String text = "{age : age >= 18 : 'Our customers must be 18 years or older.'}\n"
+ "{age : age <= 120 : 'We do not do business with the undead.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(150, "Steven"), text));
}
public void testTranslator3LengthRule() {
String text = "{firstName : length (firstName) < 7 and length (firstName) > -1 : 'First name must be no longer than 30 characters.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(7, "Benjamin"), text));
}
public void testTranslator4NullRule() {
String text = "{firstName : firstName is null : 'First name must be null.'}";
assertTrue(validate(new Person(20, null), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator5NotNullRule() {
String text = "{firstName : firstName is not null : 'First name must not be null.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(20, null), text));
}
public void testTranslator6HasLengthRule() {
String text = "{firstName : firstName has length : 'First name is required.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(20, ""), text));
}
public void testTranslator7HasNoLengthRule() {
String text = "{firstName : firstName has no length : 'First name is not allowed.'}";
assertTrue(validate(new Person(20, null), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator8HasTextRule() {
String text = "{firstName : firstName has text : 'First name is required.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(20, " "), text));
}
public void testTranslator9HasNoTextRule() {
String text = "{firstName : firstName has no text and !(false) = true : 'First name is not allowed.'}";
assertTrue(validate(new Person(20, " "), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator10NotRule() {
String text = "{firstName : not length (firstName) > 7 : 'First name must be not longer than 7 characters.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(7, "Benjamin"), text));
}
public void testTranslator11ComplexNotRule() {
String text = "{firstName : not length (firstName) > 7 or not(len (firstName) > 5 and len (firstName) > 7) : 'First name is not valid'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, "Coraline"), text));
}
public void testTranslator12ComplexRule1() {
String text = "{firstName : (length (firstName) > 5 and age <= 30) or (firstName has length and age > 20) : 'Arrggh!!'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertTrue(validate(new Person(30, "Marie-Claire"), text));
assertFalse(validate(new Person(7, "test"), text));
}
public void testTranslator13InRule() {
String text = "{size : upper(?) in upper(lower('S')), upper(upper(lower(lower('M')))), upper('L'), 'XL' : 'Not a valid size.'}";
assertTrue(validate(new Person("M"), text));
assertFalse(validate(new Person("XXL"), text));
}
public void testTranslator14NotInRule() {
String text = "{firstName : firstName not in 'Bill', 'George' : 'We do not do business with Bill and George.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(60, "Bill"), text));
}
public void testTranslator15LengthBetweenRule() {
String text = "{firstName : length (firstName) between 0 and 6 : 'First name is required and must be not longer than 6 characters.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, "Marie-Claire"), text));
}
public void testTranslator16LengthNotBetweenRule() {
String text = "{firstName : firstName is null or length (firstName) not between 0 and 6 : 'First name must not have a length between 0 and 6.'}";
assertTrue(validate(new Person(30, "Marie-Claire"), text));
assertTrue(validate(new Person(20, null), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator17BetweenRule() {
String text = "{age : age = 0 or age between 18 and 120 : 'Age must be between 18 and 120.'}";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(7, "Benjamin"), text));
}
public void testTranslator18NotBetweenRule() {
String text = "{age : ? = 0 or age not between 20 and 30 : 'Age must not be between 20 and 30.'}";
assertTrue(validate(new Person(7, "Benjamin"), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator19Dates1() throws DateParseException {
String text = "{ dateOfBirth : dateOfBirth >= [1970-01-01] : 'You must be born after 1 January 1970.' }";
assertTrue(validate(new Person(new DefaultDateParser().parse("1974-11-24")), text));
assertFalse(validate(new Person(new DefaultDateParser().parse("1950-07-14")), text));
}
public void testTranslator20Dates2() throws DateParseException {
String text = "{ dateOfBirth : ? is null or (dateOfBirth >= [T<d] and [T>d] > dateOfBirth) : 'You must be born today.' }";
assertTrue(validate(new Person(new DefaultDateParser().parse("T")), text));
assertFalse(validate(new Person(new DefaultDateParser().parse("T-1d")), text));
}
public void testTranslatorErrorKey() {
MessageSourceAccessor mockAccessor = new MessageSourceAccessor(null) {
public String getMessage(String code, String defaultMessage) {
assertEquals("18_years_or_older", code);
assertEquals("Customers must be 18 years or older.", defaultMessage);
return defaultMessage;
}
};
String text = "{ age : age >= 18 : 'Customers must be 18 years or older.' : '18_years_or_older' }";
assertTrue(validate(new Person(30, "Steven"), text, mockAccessor));
assertFalse(validate(new Person(7, "Benjamin"), text, mockAccessor));
}
public void testTranslatorErrorArgs() {
MessageSourceAccessor mockAccessor = new MessageSourceAccessor(null) {
public String getMessage(String code, String defaultMessage) {
assertEquals("not_old_enough", code);
assertEquals("Customers must be older than {0}.", defaultMessage);
return defaultMessage;
}
};
String text = "{ age : age >= minAge : 'Customers must be older than {0}.' : 'not_old_enough' : minAge }";
assertTrue(validate(new Person(33, "Steven"), text, mockAccessor));
assertFalse(validate(new Person(7, "Benjamin"), text, mockAccessor));
}
//
// TODO: The following commented tests all fail.
//
// public void testTranslator23InCollection() {
// String text =
// "{ size : ? in @sizes and ? in @map[sizes] : 'Size is not correct.' }";
// ;
// assertTrue(validate(new Person("M"), text));
// assertFalse(validate(new Person("XXL"), text));
// }
//
// public void testTranslator23MapKey() {
// String text =
// "{ firstName : ? = map[firstName] : 'First name is not correct.' }"
// ;
// assertTrue(validate(new Person(30, "Steven"), text));
// assertFalse(validate(new Person(30, "Marie-Claire"), text));
// }
//
// public void testTranslator25MapTarget() {
// Map customer = new HashMap();
// customer.put("name", "Steven");
// Map order = new HashMap();
// order.put("customer", customer);
//
// String text =
// "{ customer.name : ? = 'Steven' : 'Customer name is incorrect.' }"
// ;
// assertTrue(validate(order, text));
// }
public void testTranslator26IsBlank() {
String text = "{ firstName : ? is blank : 'First name is not blank.' }";
assertTrue(validate(new Person(30, ""), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator27IsNotBlank() {
String text = "{ firstName : ? is not blank : 'First name is blank.' }";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, ""), text));
}
public void testTranslator28IsWord() {
String text = "{ firstName : ? is word : 'First name must be one word.' }";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, "Steven Devijver"), text));
}
public void testTranslator29IsNotWord() {
String text = "{ firstName : ? is not word : 'First name must not be one word.' }";
assertTrue(validate(new Person(30, "Steven Devijver"), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator30IsUpperCase() {
String text = "{ firstName : ? is uppercase : 'First name must be upper case.' }";
assertTrue(validate(new Person(30, "STEVEN"), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator31IsNotUpperCase() {
String text = "{ firstName : ? is not uppercase : 'First name must not be upper case.' }";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, "STEVEN"), text));
}
public void testTranslator32IsLowerCase() {
String text = "{ firstName : ? is lowercase : 'First name must be lower case.' }";
assertTrue(validate(new Person(30, "steven"), text));
assertFalse(validate(new Person(30, "Steven"), text));
}
public void testTranslator33IsNotLowerCase() {
String text = "{ firstName : ? is not lowercase : 'First name must not be lower case.' }";
assertTrue(validate(new Person(30, "Steven"), text));
assertFalse(validate(new Person(30, "steven"), text));
}
public void testTranslator34SimpleMath() {
String text = "{ firstName : (2 + 3 = 5 and 3 - 1 = 2) and (3 * 3 = 9 and 9 / 3 = 3) and 10 % 3 = 1 and 21 div 7 = 3 and 7 mod 3 = 1 : '' }";
assertTrue(validate(new Person(30, "Steven"), text));
}
public void testTranslator35ComplexMath() {
String text = "{ firstName : 2 - 3 + 5 = 4 and (2 + 3) - 4 = 1 and ((2 - 3) + 4) - 1 = 2 and (length(?) - 2) + 1 = 5 and 2 = ((age / 2) / (1/2)) % 7 : '' }";
assertTrue(validate(new Person(30, "Steven"), text));
}
public void testTranslator36EscapedString() {
String text = "{firstName : 'Steven\\'' = firstName and matches('(Steven|Hans|Erwin)\\'', firstName) = true and length('\\\\') = 1 : ''}";
assertTrue(validate(new Person(30, "Steven'"), text));
}
public void testTranslator37LengthWithNullValue() {
String text = "{firstName : length(?) > 2: ''}";
assertFalse(validate(new Person("Size'"), text));
}
public void testTranslator37Email() {
Person person = new Person("size");
person.setEmail("a@b.com");
String text = "{email : email(?) == true: ''}";
assertTrue(validate(person, text));
}
public void testTranslator37EmailWithNull() {
Person person = new Person("size");
String text = "{email : email(?) == true: ''}";
assertFalse(validate(person, text));
}
public void testTranslator37InvalidEmail() {
Person person = new Person("size");
person.setEmail("-@b.com");
String text = "{email : email(?) == true: ''}";
assertFalse(validate(person, text));
}
}