json/src/test/java/net/java/html/json/ModelTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 30f20d9c0986
child 920 117b732d42d0
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
jtulach@0
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@0
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jtulach@0
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jtulach@0
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jtulach@0
    42
 */
jtulach@0
    43
package net.java.html.json;
jtulach@0
    44
jaroslav@110
    45
import net.java.html.BrwsrCtx;
jtulach@0
    46
import java.util.ArrayList;
jtulach@0
    47
import java.util.Collections;
jtulach@0
    48
import java.util.Iterator;
jtulach@0
    49
import java.util.List;
jtulach@0
    50
import java.util.ListIterator;
jtulach@838
    51
import org.netbeans.html.context.spi.Contexts;
jtulach@838
    52
import org.netbeans.html.json.spi.FunctionBinding;
jtulach@838
    53
import org.netbeans.html.json.spi.PropertyBinding;
jtulach@838
    54
import org.netbeans.html.json.spi.Technology;
jtulach@0
    55
import static org.testng.Assert.*;
jtulach@0
    56
import org.testng.annotations.BeforeMethod;
jtulach@0
    57
import org.testng.annotations.Test;
jtulach@0
    58
jtulach@0
    59
/**
jtulach@0
    60
 *
jtulach@790
    61
 * @author Jaroslav Tulach
jtulach@0
    62
 */
jtulach@0
    63
@Model(className = "Modelik", properties = {
jtulach@0
    64
    @Property(name = "value", type = int.class),
jtulach@0
    65
    @Property(name = "count", type = int.class),
jtulach@0
    66
    @Property(name = "unrelated", type = long.class),
jtulach@0
    67
    @Property(name = "names", type = String.class, array = true),
jtulach@0
    68
    @Property(name = "values", type = int.class, array = true),
jtulach@0
    69
    @Property(name = "people", type = Person.class, array = true),
jtulach@0
    70
    @Property(name = "changedProperty", type=String.class)
jtulach@0
    71
})
jtulach@0
    72
public class ModelTest {
jaroslav@7
    73
    private MockTechnology my;
jtulach@0
    74
    private Modelik model;
jtulach@0
    75
    private static Modelik leakedModel;
jtulach@0
    76
    
jtulach@0
    77
    @BeforeMethod
jtulach@0
    78
    public void createModel() {
jaroslav@7
    79
        my = new MockTechnology();
jaroslav@111
    80
        final BrwsrCtx c = Contexts.newBuilder().register(Technology.class, my, 1).build();
jaroslav@111
    81
        model = Models.bind(new Modelik(), c);
jtulach@0
    82
    }
jtulach@0
    83
    
jtulach@0
    84
    @Test public void classGeneratedWithSetterGetter() {
jtulach@0
    85
        model.setValue(10);
jtulach@0
    86
        assertEquals(10, model.getValue(), "Value changed");
jtulach@0
    87
    }
jtulach@0
    88
    
jtulach@0
    89
    @Test public void computedMethod() {
jtulach@0
    90
        model.setValue(4);
jtulach@0
    91
        assertEquals(16, model.getPowerValue());
jtulach@0
    92
    }
jtulach@0
    93
    
jaroslav@281
    94
    @Test public void equalsAndHashCode() {
jaroslav@281
    95
        Modelik m1 = new Modelik(10, 20, 30, "changed", "firstName");
jaroslav@281
    96
        Modelik m2 = new Modelik(10, 20, 30, "changed", "firstName");
jaroslav@281
    97
        
jaroslav@281
    98
        assertTrue(m1.equals(m2), "They are the same");
jaroslav@281
    99
        assertEquals(m1.hashCode(), m2.hashCode(), "Hashcode is the same");
jaroslav@281
   100
        
jaroslav@281
   101
        m1.setCount(33);
jaroslav@281
   102
        
jaroslav@281
   103
        assertFalse(m1.equals(m2), "No longer the same");
jaroslav@281
   104
        assertFalse(m1.hashCode() == m2.hashCode(), "No longe is hashcode is the same");
jaroslav@281
   105
    }
jaroslav@281
   106
    
jtulach@0
   107
    @Test public void arrayIsMutable() {
jtulach@0
   108
        assertEquals(model.getNames().size(), 0, "Is empty");
jtulach@0
   109
        model.getNames().add("Jarda");
jtulach@0
   110
        assertEquals(model.getNames().size(), 1, "One element");
jtulach@0
   111
    }
jaroslav@6
   112
jaroslav@278
   113
    @Test public void arrayChangesNotNotifiedUntilInitied() {
jaroslav@278
   114
        model.getNames().add("Hello");
jaroslav@278
   115
        assertTrue(my.mutated.isEmpty(), "No change now " + my.mutated);
jaroslav@278
   116
        model.getNames().remove("Hello");
jaroslav@278
   117
        assertTrue(my.mutated.isEmpty(), "No change still " + my.mutated);
jaroslav@278
   118
        assertTrue(model.getNames().isEmpty(), "No empty");
jaroslav@278
   119
    }
jaroslav@278
   120
    
jtulach@0
   121
    @Test public void arrayChangesNotified() {
jaroslav@453
   122
        Models.applyBindings(model);
jtulach@0
   123
        model.getNames().add("Hello");
jtulach@0
   124
        
jtulach@0
   125
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   126
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   127
jtulach@0
   128
        my.mutated.clear();
jtulach@0
   129
        
jtulach@0
   130
        Iterator<String> it = model.getNames().iterator();
jtulach@0
   131
        assertEquals(it.next(), "Hello");
jtulach@0
   132
        it.remove();
jtulach@0
   133
        
jtulach@0
   134
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   135
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   136
jtulach@0
   137
        my.mutated.clear();
jtulach@0
   138
        
jtulach@0
   139
        ListIterator<String> lit = model.getNames().listIterator();
jtulach@0
   140
        lit.add("Jarda");
jtulach@0
   141
        
jtulach@0
   142
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   143
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   144
    }
jaroslav@7
   145
jtulach@0
   146
    @Test public void autoboxedArray() {
jtulach@0
   147
        model.getValues().add(10);
jtulach@0
   148
        
jtulach@0
   149
        assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
jtulach@0
   150
    }
jtulach@0
   151
jtulach@0
   152
    @Test public void derivedArrayProp() {
jaroslav@280
   153
        model.applyBindings();
jtulach@0
   154
        model.setCount(10);
jtulach@0
   155
        
jtulach@0
   156
        List<String> arr = model.getRepeat();
jtulach@0
   157
        assertEquals(arr.size(), 10, "Ten items: " + arr);
jtulach@0
   158
        
jtulach@0
   159
        my.mutated.clear();
jtulach@0
   160
        
jtulach@0
   161
        model.setCount(5);
jtulach@0
   162
        
jtulach@0
   163
        arr = model.getRepeat();
jtulach@0
   164
        assertEquals(arr.size(), 5, "Five items: " + arr);
jtulach@0
   165
jtulach@0
   166
        assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
jtulach@0
   167
        assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
jtulach@0
   168
        assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
jtulach@0
   169
    }
jtulach@0
   170
    
jtulach@0
   171
    @Test public void derivedPropertiesAreNotified() {
jaroslav@280
   172
        model.applyBindings();
jaroslav@280
   173
        
jtulach@0
   174
        model.setValue(33);
jtulach@0
   175
        
jtulach@0
   176
        // not interested in change of this property
jtulach@0
   177
        my.mutated.remove("changedProperty");
jtulach@0
   178
        
jtulach@0
   179
        assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
jtulach@0
   180
        assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
jtulach@0
   181
        assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
jtulach@0
   182
        
jtulach@0
   183
        my.mutated.clear();
jtulach@0
   184
        
jtulach@0
   185
        model.setUnrelated(44);
jtulach@0
   186
        
jtulach@0
   187
        
jtulach@0
   188
        // not interested in change of this property
jtulach@0
   189
        my.mutated.remove("changedProperty");
jtulach@0
   190
        assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
jtulach@0
   191
        assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
jtulach@0
   192
    }
jaroslav@8
   193
jtulach@0
   194
    @Test public void computedPropertyCannotWriteToModel() {
jtulach@0
   195
        leakedModel = model;
jtulach@0
   196
        try {
jtulach@0
   197
            String res = model.getNotAllowedWrite();
jtulach@0
   198
            fail("We should not be allowed to write to the model: " + res);
jtulach@0
   199
        } catch (IllegalStateException ex) {
jtulach@0
   200
            // OK, we can't read
jtulach@0
   201
        }
jtulach@0
   202
    }
jtulach@0
   203
jtulach@0
   204
    @Test public void computedPropertyCannotReadToModel() {
jtulach@0
   205
        leakedModel = model;
jtulach@0
   206
        try {
jtulach@0
   207
            String res = model.getNotAllowedRead();
jtulach@0
   208
            fail("We should not be allowed to read from the model: " + res);
jtulach@0
   209
        } catch (IllegalStateException ex) {
jtulach@0
   210
            // OK, we can't read
jtulach@0
   211
        }
jtulach@0
   212
    }
jtulach@0
   213
    
jaroslav@245
   214
    @OnReceive(url = "{protocol}://{host}?query={query}", data = Person.class, onError = "errorState")
jaroslav@13
   215
    static void loadPeople(Modelik thiz, People p) {
jaroslav@12
   216
        Modelik m = null;
jaroslav@14
   217
        m.applyBindings();
jaroslav@111
   218
        m.loadPeople("http", "apidesign.org", "query", new Person());
jaroslav@12
   219
    }
jaroslav@245
   220
    
jaroslav@245
   221
    static void errorState(Modelik thiz, Exception ex) {
jaroslav@245
   222
        
jaroslav@245
   223
    }
jaroslav@24
   224
jaroslav@24
   225
    @OnReceive(url = "{protocol}://{host}?callback={back}&query={query}", jsonp = "back")
jaroslav@24
   226
    static void loadPeopleViaJSONP(Modelik thiz, People p) {
jaroslav@24
   227
        Modelik m = null;
jaroslav@24
   228
        m.applyBindings();
jaroslav@24
   229
        m.loadPeopleViaJSONP("http", "apidesign.org", "query");
jaroslav@24
   230
    }
jaroslav@12
   231
    
jtulach@0
   232
    @Function 
jtulach@0
   233
    static void doSomething() {
jtulach@0
   234
    }
jtulach@0
   235
    
jtulach@0
   236
    @ComputedProperty
jtulach@0
   237
    static int powerValue(int value) {
jtulach@0
   238
        return value * value;
jtulach@0
   239
    }
jtulach@0
   240
    
jtulach@0
   241
    @OnPropertyChange({ "powerValue", "unrelated" })
jtulach@0
   242
    static void aPropertyChanged(Modelik m, String name) {
jtulach@0
   243
        m.setChangedProperty(name);
jtulach@0
   244
    }
jtulach@0
   245
jtulach@0
   246
    @OnPropertyChange({ "values" })
jtulach@0
   247
    static void anArrayPropertyChanged(String name, Modelik m) {
jtulach@0
   248
        m.setChangedProperty(name);
jtulach@0
   249
    }
jtulach@0
   250
    
jtulach@0
   251
    @Test public void changeAnything() {
jtulach@0
   252
        model.setCount(44);
jtulach@0
   253
        assertNull(model.getChangedProperty(), "No observed value change");
jtulach@0
   254
    }
jtulach@0
   255
    @Test public void changeValue() {
jtulach@0
   256
        model.setValue(33);
jtulach@0
   257
        assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
jtulach@0
   258
    }
jtulach@0
   259
    @Test public void changeUnrelated() {
jtulach@0
   260
        model.setUnrelated(333);
jtulach@0
   261
        assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
jtulach@0
   262
    }
jtulach@0
   263
jtulach@0
   264
    @Test public void changeInArray() {
jtulach@0
   265
        model.getValues().add(10);
jaroslav@278
   266
        assertNull(model.getChangedProperty(), "No change before applyBindings");
jaroslav@278
   267
        model.applyBindings();
jaroslav@278
   268
        model.getValues().add(10);
jtulach@0
   269
        assertEquals(model.getChangedProperty(), "values", "Something added into the array");
jtulach@0
   270
    }
jtulach@0
   271
    
jtulach@0
   272
    @ComputedProperty
jtulach@0
   273
    static String notAllowedRead() {
jtulach@0
   274
        return "Not allowed callback: " + leakedModel.getUnrelated();
jtulach@0
   275
    }
jtulach@0
   276
jtulach@0
   277
    @ComputedProperty
jtulach@0
   278
    static String notAllowedWrite() {
jtulach@0
   279
        leakedModel.setUnrelated(11);
jtulach@0
   280
        return "Not allowed callback!";
jtulach@0
   281
    }
jtulach@0
   282
    
jtulach@0
   283
    @ComputedProperty
jtulach@0
   284
    static List<String> repeat(int count) {
jtulach@0
   285
        return Collections.nCopies(count, "Hello");
jtulach@0
   286
    }
jtulach@0
   287
    
jtulach@0
   288
    public @Test void hasPersonPropertyAndComputedFullName() {
jtulach@0
   289
        List<Person> arr = model.getPeople();
jtulach@0
   290
        assertEquals(arr.size(), 0, "By default empty");
jtulach@0
   291
        Person p = null;
jtulach@0
   292
        if (p != null) {
jtulach@0
   293
            String fullNameGenerated = p.getFullName();
jtulach@0
   294
            assertNotNull(fullNameGenerated);
jtulach@0
   295
        }
jtulach@0
   296
    }
jaroslav@7
   297
    
jaroslav@562
   298
    public @Test void computedListIsOfTypeString() {
jaroslav@562
   299
        Person p = new Person("1st", "2nd", Sex.MALE);
jaroslav@562
   300
        String first = p.getBothNames().get(0);
jaroslav@562
   301
        String last = p.getBothNames().get(1);
jaroslav@562
   302
        assertEquals(first, "1st");
jaroslav@562
   303
        assertEquals(last, "2nd");
jaroslav@562
   304
    }
jaroslav@562
   305
    
jaroslav@7
   306
    private static class MockTechnology implements Technology<Object> {
jaroslav@100
   307
        private final List<String> mutated = new ArrayList<String>();
jaroslav@7
   308
jaroslav@7
   309
        @Override
jaroslav@7
   310
        public Object wrapModel(Object model) {
jaroslav@7
   311
            return this;
jaroslav@7
   312
        }
jaroslav@7
   313
jaroslav@7
   314
        @Override
jaroslav@7
   315
        public void valueHasMutated(Object data, String propertyName) {
jaroslav@7
   316
            mutated.add(propertyName);
jaroslav@7
   317
        }
jaroslav@9
   318
jaroslav@9
   319
        @Override
jaroslav@9
   320
        public void bind(PropertyBinding b, Object model, Object data) {
jaroslav@9
   321
        }
jaroslav@11
   322
jaroslav@11
   323
        @Override
jaroslav@11
   324
        public void expose(FunctionBinding fb, Object model, Object d) {
jaroslav@11
   325
        }
jaroslav@14
   326
jaroslav@14
   327
        @Override
jaroslav@14
   328
        public void applyBindings(Object data) {
jaroslav@14
   329
        }
jaroslav@17
   330
jaroslav@17
   331
        @Override
jaroslav@17
   332
        public Object wrapArray(Object[] arr) {
jaroslav@17
   333
            return arr;
jaroslav@17
   334
        }
jaroslav@38
   335
jaroslav@38
   336
        @Override
jaroslav@38
   337
        public <M> M toModel(Class<M> modelClass, Object data) {
jaroslav@38
   338
            return modelClass.cast(data);
jaroslav@38
   339
        }
jaroslav@240
   340
jaroslav@240
   341
        @Override
jaroslav@240
   342
        public void runSafe(Runnable r) {
jaroslav@240
   343
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@240
   344
        }
jaroslav@7
   345
    }
jtulach@0
   346
}