2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. Look for COPYING file in the top folder.
16 * If not, see http://opensource.org/licenses/GPL-2.0.
18 package org.apidesign.bck2brwsr.htmlpage;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.ListIterator;
25 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
26 import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
27 import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
28 import org.apidesign.bck2brwsr.htmlpage.api.Page;
29 import org.apidesign.bck2brwsr.htmlpage.api.Property;
30 import static org.testng.Assert.*;
31 import org.testng.annotations.BeforeMethod;
32 import org.testng.annotations.Test;
36 * @author Jaroslav Tulach <jtulach@netbeans.org>
38 @Page(xhtml = "Empty.html", className = "Modelik", properties = {
39 @Property(name = "value", type = int.class),
40 @Property(name = "count", type = int.class),
41 @Property(name = "unrelated", type = long.class),
42 @Property(name = "names", type = String.class, array = true),
43 @Property(name = "values", type = int.class, array = true),
44 @Property(name = "people", type = PersonImpl.class, array = true),
45 @Property(name = "changedProperty", type=String.class)
47 public class ModelTest {
48 private Modelik model;
49 private static Modelik leakedModel;
52 public void createModel() {
53 model = new Modelik();
56 @Test public void classGeneratedWithSetterGetter() {
58 assertEquals(10, model.getValue(), "Value changed");
61 @Test public void computedMethod() {
63 assertEquals(16, model.getPowerValue());
66 @Test public void arrayIsMutable() {
67 assertEquals(model.getNames().size(), 0, "Is empty");
68 model.getNames().add("Jarda");
69 assertEquals(model.getNames().size(), 1, "One element");
72 @Test public void arrayChangesNotified() {
73 MockKnockout my = new MockKnockout();
74 MockKnockout.next = my;
76 model.applyBindings();
78 model.getNames().add("Hello");
80 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
81 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
85 Iterator<String> it = model.getNames().iterator();
86 assertEquals(it.next(), "Hello");
89 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
90 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
94 ListIterator<String> lit = model.getNames().listIterator();
97 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
98 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
101 @Test public void autoboxedArray() {
102 MockKnockout my = new MockKnockout();
103 MockKnockout.next = my;
105 model.applyBindings();
107 model.getValues().add(10);
109 assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
112 @Test public void derivedArrayProp() {
113 MockKnockout my = new MockKnockout();
114 MockKnockout.next = my;
116 model.applyBindings();
120 List<String> arr = model.getRepeat();
121 assertEquals(arr.size(), 10, "Ten items: " + arr);
127 arr = model.getRepeat();
128 assertEquals(arr.size(), 5, "Five items: " + arr);
130 assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
131 assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
132 assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
135 @Test public void derivedPropertiesAreNotified() {
136 MockKnockout my = new MockKnockout();
137 MockKnockout.next = my;
139 model.applyBindings();
143 // not interested in change of this property
144 my.mutated.remove("changedProperty");
146 assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
147 assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
148 assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
152 model.setUnrelated(44);
155 // not interested in change of this property
156 my.mutated.remove("changedProperty");
157 assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
158 assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
161 @Test public void computedPropertyCannotWriteToModel() {
164 String res = model.getNotAllowedWrite();
165 fail("We should not be allowed to write to the model: " + res);
166 } catch (IllegalStateException ex) {
171 @Test public void computedPropertyCannotReadToModel() {
174 String res = model.getNotAllowedRead();
175 fail("We should not be allowed to read from the model: " + res);
176 } catch (IllegalStateException ex) {
182 static void doSomething() {
186 static int powerValue(int value) {
187 return value * value;
190 @OnPropertyChange({ "powerValue", "unrelated" })
191 static void aPropertyChanged(Modelik m, String name) {
192 m.setChangedProperty(name);
195 @OnPropertyChange({ "values" })
196 static void anArrayPropertyChanged(String name, Modelik m) {
197 m.setChangedProperty(name);
200 @Test public void changeAnything() {
202 assertNull(model.getChangedProperty(), "No observed value change");
204 @Test public void changeValue() {
206 assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
208 @Test public void changeUnrelated() {
209 model.setUnrelated(333);
210 assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
213 @Test public void changeInArray() {
214 model.getValues().add(10);
215 assertEquals(model.getChangedProperty(), "values", "Something added into the array");
219 static String notAllowedRead() {
220 return "Not allowed callback: " + leakedModel.getUnrelated();
224 static String notAllowedWrite() {
225 leakedModel.setUnrelated(11);
226 return "Not allowed callback!";
230 static List<String> repeat(int count) {
231 return Collections.nCopies(count, "Hello");
234 static class MockKnockout extends Knockout {
235 List<String> mutated = new ArrayList<>();
242 public void valueHasMutated(String prop) {
247 public @Test void hasPersonPropertyAndComputedFullName() {
248 List<Person> arr = model.getPeople();
249 assertEquals(arr.size(), 0, "By default empty");
252 String fullNameGenerated = p.getFullName();
253 assertNotNull(fullNameGenerated);