jaroslav@489: /** jaroslav@489: * Back 2 Browser Bytecode Translator jaroslav@489: * Copyright (C) 2012 Jaroslav Tulach jaroslav@489: * jaroslav@489: * This program is free software: you can redistribute it and/or modify jaroslav@489: * it under the terms of the GNU General Public License as published by jaroslav@489: * the Free Software Foundation, version 2 of the License. jaroslav@489: * jaroslav@489: * This program is distributed in the hope that it will be useful, jaroslav@489: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@489: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@489: * GNU General Public License for more details. jaroslav@489: * jaroslav@489: * You should have received a copy of the GNU General Public License jaroslav@489: * along with this program. Look for COPYING file in the top folder. jaroslav@489: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@489: */ jaroslav@489: package org.apidesign.bck2brwsr.htmlpage; jaroslav@489: jaroslav@499: import java.util.ArrayList; jaroslav@766: import java.util.Collections; jaroslav@761: import java.util.Iterator; jaroslav@499: import java.util.List; jaroslav@761: import java.util.ListIterator; jaroslav@491: import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; jaroslav@879: import org.apidesign.bck2brwsr.htmlpage.api.OnFunction; jaroslav@949: import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange; jaroslav@489: import org.apidesign.bck2brwsr.htmlpage.api.Page; jaroslav@490: import org.apidesign.bck2brwsr.htmlpage.api.Property; jaroslav@489: import static org.testng.Assert.*; jaroslav@505: import org.testng.annotations.BeforeMethod; jaroslav@489: import org.testng.annotations.Test; jaroslav@489: jaroslav@489: /** jaroslav@489: * jaroslav@489: * @author Jaroslav Tulach jaroslav@489: */ jaroslav@770: @Page(xhtml = "Empty.html", className = "Modelik", properties = { jaroslav@499: @Property(name = "value", type = int.class), jaroslav@766: @Property(name = "count", type = int.class), jaroslav@760: @Property(name = "unrelated", type = long.class), jaroslav@764: @Property(name = "names", type = String.class, array = true), jaroslav@770: @Property(name = "values", type = int.class, array = true), jaroslav@949: @Property(name = "people", type = PersonImpl.class, array = true), jaroslav@949: @Property(name = "changedProperty", type=String.class) jaroslav@490: }) jaroslav@489: public class ModelTest { jaroslav@770: private Modelik model; jaroslav@770: private static Modelik leakedModel; jaroslav@505: jaroslav@505: @BeforeMethod jaroslav@505: public void createModel() { jaroslav@770: model = new Modelik(); jaroslav@505: } jaroslav@505: jaroslav@490: @Test public void classGeneratedWithSetterGetter() { jaroslav@505: model.setValue(10); jaroslav@505: assertEquals(10, model.getValue(), "Value changed"); jaroslav@489: } jaroslav@491: jaroslav@491: @Test public void computedMethod() { jaroslav@505: model.setValue(4); jaroslav@505: assertEquals(16, model.getPowerValue()); jaroslav@491: } jaroslav@491: jaroslav@760: @Test public void arrayIsMutable() { jaroslav@760: assertEquals(model.getNames().size(), 0, "Is empty"); jaroslav@760: model.getNames().add("Jarda"); jaroslav@760: assertEquals(model.getNames().size(), 1, "One element"); jaroslav@760: } jaroslav@760: jaroslav@761: @Test public void arrayChangesNotified() { jaroslav@761: MockKnockout my = new MockKnockout(); jaroslav@761: MockKnockout.next = my; jaroslav@761: jaroslav@761: model.applyBindings(); jaroslav@761: jaroslav@761: model.getNames().add("Hello"); jaroslav@761: jaroslav@761: assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated); jaroslav@761: assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated); jaroslav@761: jaroslav@761: my.mutated.clear(); jaroslav@761: jaroslav@761: Iterator it = model.getNames().iterator(); jaroslav@761: assertEquals(it.next(), "Hello"); jaroslav@761: it.remove(); jaroslav@761: jaroslav@761: assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated); jaroslav@761: assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated); jaroslav@761: jaroslav@761: my.mutated.clear(); jaroslav@761: jaroslav@761: ListIterator lit = model.getNames().listIterator(); jaroslav@761: lit.add("Jarda"); jaroslav@761: jaroslav@761: assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated); jaroslav@761: assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated); jaroslav@761: } jaroslav@761: jaroslav@764: @Test public void autoboxedArray() { jaroslav@764: MockKnockout my = new MockKnockout(); jaroslav@764: MockKnockout.next = my; jaroslav@764: jaroslav@764: model.applyBindings(); jaroslav@764: jaroslav@764: model.getValues().add(10); jaroslav@764: jaroslav@764: assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten"); jaroslav@764: } jaroslav@766: jaroslav@766: @Test public void derivedArrayProp() { jaroslav@766: MockKnockout my = new MockKnockout(); jaroslav@766: MockKnockout.next = my; jaroslav@766: jaroslav@766: model.applyBindings(); jaroslav@766: jaroslav@766: model.setCount(10); jaroslav@766: jaroslav@766: List arr = model.getRepeat(); jaroslav@766: assertEquals(arr.size(), 10, "Ten items: " + arr); jaroslav@766: jaroslav@766: my.mutated.clear(); jaroslav@766: jaroslav@766: model.setCount(5); jaroslav@766: jaroslav@766: arr = model.getRepeat(); jaroslav@766: assertEquals(arr.size(), 5, "Five items: " + arr); jaroslav@766: jaroslav@766: assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated); jaroslav@766: assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated); jaroslav@766: assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated); jaroslav@766: } jaroslav@764: jaroslav@499: @Test public void derivedPropertiesAreNotified() { jaroslav@499: MockKnockout my = new MockKnockout(); jaroslav@499: MockKnockout.next = my; jaroslav@499: jaroslav@505: model.applyBindings(); jaroslav@499: jaroslav@505: model.setValue(33); jaroslav@499: jaroslav@949: // not interested in change of this property jaroslav@949: my.mutated.remove("changedProperty"); jaroslav@949: jaroslav@499: assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated); jaroslav@499: assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated); jaroslav@499: assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated); jaroslav@499: jaroslav@499: my.mutated.clear(); jaroslav@499: jaroslav@505: model.setUnrelated(44); jaroslav@949: jaroslav@949: jaroslav@949: // not interested in change of this property jaroslav@949: my.mutated.remove("changedProperty"); jaroslav@949: assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated); jaroslav@499: assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated"); jaroslav@499: } jaroslav@499: jaroslav@500: @Test public void computedPropertyCannotWriteToModel() { jaroslav@505: leakedModel = model; jaroslav@500: try { jaroslav@505: String res = model.getNotAllowedWrite(); jaroslav@500: fail("We should not be allowed to write to the model: " + res); jaroslav@500: } catch (IllegalStateException ex) { jaroslav@500: // OK, we can't read jaroslav@500: } jaroslav@500: } jaroslav@500: jaroslav@500: @Test public void computedPropertyCannotReadToModel() { jaroslav@505: leakedModel = model; jaroslav@500: try { jaroslav@505: String res = model.getNotAllowedRead(); jaroslav@500: fail("We should not be allowed to read from the model: " + res); jaroslav@500: } catch (IllegalStateException ex) { jaroslav@500: // OK, we can't read jaroslav@500: } jaroslav@500: } jaroslav@500: jaroslav@879: @OnFunction jaroslav@879: static void doSomething() { jaroslav@879: } jaroslav@879: jaroslav@491: @ComputedProperty jaroslav@491: static int powerValue(int value) { jaroslav@491: return value * value; jaroslav@491: } jaroslav@499: jaroslav@949: @OnPropertyChange({ "powerValue", "unrelated" }) jaroslav@949: static void aPropertyChanged(Modelik m, String name) { jaroslav@949: m.setChangedProperty(name); jaroslav@949: } jaroslav@950: jaroslav@950: @OnPropertyChange({ "values" }) jaroslav@950: static void anArrayPropertyChanged(String name, Modelik m) { jaroslav@950: m.setChangedProperty(name); jaroslav@950: } jaroslav@949: jaroslav@949: @Test public void changeAnything() { jaroslav@949: model.setCount(44); jaroslav@949: assertNull(model.getChangedProperty(), "No observed value change"); jaroslav@949: } jaroslav@949: @Test public void changeValue() { jaroslav@949: model.setValue(33); jaroslav@949: assertEquals(model.getChangedProperty(), "powerValue", "power property changed"); jaroslav@949: } jaroslav@949: @Test public void changeUnrelated() { jaroslav@949: model.setUnrelated(333); jaroslav@949: assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed"); jaroslav@949: } jaroslav@950: jaroslav@950: @Test public void changeInArray() { jaroslav@950: model.getValues().add(10); jaroslav@950: assertEquals(model.getChangedProperty(), "values", "Something added into the array"); jaroslav@950: } jaroslav@949: jaroslav@500: @ComputedProperty jaroslav@500: static String notAllowedRead() { jaroslav@505: return "Not allowed callback: " + leakedModel.getUnrelated(); jaroslav@500: } jaroslav@500: jaroslav@500: @ComputedProperty jaroslav@500: static String notAllowedWrite() { jaroslav@505: leakedModel.setUnrelated(11); jaroslav@500: return "Not allowed callback!"; jaroslav@500: } jaroslav@500: jaroslav@766: @ComputedProperty jaroslav@766: static List repeat(int count) { jaroslav@766: return Collections.nCopies(count, "Hello"); jaroslav@766: } jaroslav@766: jaroslav@499: static class MockKnockout extends Knockout { jaroslav@770: List mutated = new ArrayList<>(); jaroslav@499: jaroslav@851: public MockKnockout() { jaroslav@851: super(new Object()); jaroslav@909: } jaroslav@909: jaroslav@499: @Override jaroslav@499: public void valueHasMutated(String prop) { jaroslav@499: mutated.add(prop); jaroslav@499: } jaroslav@499: } jaroslav@770: jaroslav@770: public @Test void hasPersonPropertyAndComputedFullName() { jaroslav@770: List arr = model.getPeople(); jaroslav@770: assertEquals(arr.size(), 0, "By default empty"); jaroslav@770: Person p = null; jaroslav@770: if (p != null) { jaroslav@770: String fullNameGenerated = p.getFullName(); jaroslav@770: assertNotNull(fullNameGenerated); jaroslav@770: } jaroslav@770: } jaroslav@489: }