javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/JSONTest.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 18 Apr 2013 12:47:25 +0200
changeset 1009 80c46ea076d3
parent 963 62d77cc38117
child 1412 a51c0d80ee24
permissions -rw-r--r--
Test to ensure the generated JSON can really be parse by a browser
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     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.
     8  *
     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.
    13  *
    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.
    17  */
    18 package org.apidesign.bck2brwsr.htmlpage;
    19 
    20 import java.util.Arrays;
    21 import java.util.Iterator;
    22 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    23 import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
    24 import org.apidesign.bck2brwsr.htmlpage.api.Page;
    25 import org.apidesign.bck2brwsr.htmlpage.api.Property;
    26 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    27 import org.apidesign.bck2brwsr.vmtest.Http;
    28 import org.apidesign.bck2brwsr.vmtest.VMTest;
    29 import org.json.JSONException;
    30 import org.json.JSONObject;
    31 import org.json.JSONTokener;
    32 import org.testng.annotations.Test;
    33 import static org.testng.Assert.*;
    34 import org.testng.annotations.Factory;
    35 
    36 /** Need to verify that models produce reasonable JSON objects.
    37  *
    38  * @author Jaroslav Tulach <jtulach@netbeans.org>
    39  */
    40 @Page(xhtml = "Empty.html", className = "JSONik", properties = {
    41     @Property(name = "fetched", type = PersonImpl.class),
    42     @Property(name = "fetchedCount", type = int.class),
    43     @Property(name = "fetchedSex", type = Sex.class, array = true)
    44 })
    45 public class JSONTest {
    46     private JSONik js;
    47     private Integer orig;
    48     
    49     @Test public void personToString() throws JSONException {
    50         Person p = new Person();
    51         p.setSex(Sex.MALE);
    52         p.setFirstName("Jarda");
    53         p.setLastName("Tulach");
    54         
    55         JSONTokener t = new JSONTokener(p.toString());
    56         JSONObject o;
    57         try {
    58             o = new JSONObject(t);
    59         } catch (JSONException ex) {
    60             throw new AssertionError("Can't parse " + p.toString(), ex);
    61         }
    62         
    63         Iterator it = o.sortedKeys();
    64         assertEquals(it.next(), "firstName");
    65         assertEquals(it.next(), "lastName");
    66         assertEquals(it.next(), "sex");
    67         
    68         assertEquals(o.getString("firstName"), "Jarda");
    69         assertEquals(o.getString("lastName"), "Tulach");
    70         assertEquals(o.getString("sex"), "MALE");
    71     }
    72     
    73     @BrwsrTest public void toJSONInABrowser() throws Throwable {
    74         Person p = new Person();
    75         p.setSex(Sex.MALE);
    76         p.setFirstName("Jarda");
    77         p.setLastName("Tulach");
    78 
    79         Object json;
    80         try {
    81             json = parseJSON(p.toString());
    82         } catch (Throwable ex) {
    83             throw new IllegalStateException("Can't parse " + p).initCause(ex);
    84         }
    85         
    86         Person p2 = new Person(json);
    87         
    88         assert p2.getFirstName().equals(p.getFirstName()) : 
    89             "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
    90     }
    91     
    92     @Test public void personWithWildCharactersAndNulls() throws JSONException {
    93         Person p = new Person();
    94         p.setFirstName("'\"\n");
    95         p.setLastName("\t\r\u0002");
    96         
    97         JSONTokener t = new JSONTokener(p.toString());
    98         JSONObject o;
    99         try {
   100             o = new JSONObject(t);
   101         } catch (JSONException ex) {
   102             throw new AssertionError("Can't parse " + p.toString(), ex);
   103         }
   104         
   105         Iterator it = o.sortedKeys();
   106         assertEquals(it.next(), "firstName");
   107         assertEquals(it.next(), "lastName");
   108         assertEquals(it.next(), "sex");
   109         
   110         assertEquals(o.getString("firstName"), p.getFirstName());
   111         assertEquals(o.getString("lastName"), p.getLastName());
   112         assertEquals(o.get("sex"), JSONObject.NULL);
   113     }
   114     
   115     @Test public void personsInArray() throws JSONException {
   116         Person p1 = new Person();
   117         p1.setFirstName("One");
   118 
   119         Person p2 = new Person();
   120         p2.setFirstName("Two");
   121         
   122         People arr = new People();
   123         arr.getInfo().add(p1);
   124         arr.getInfo().add(p2);
   125         arr.getNicknames().add("Prvn\u00ed k\u016f\u0148");
   126         final String n2 = "Druh\u00fd hlem\u00fd\u017e\u010f, star\u0161\u00ed";
   127         arr.getNicknames().add(n2);
   128         arr.getAge().add(33);
   129         arr.getAge().add(73);
   130         
   131         
   132         final String json = arr.toString();
   133         
   134         JSONTokener t = new JSONTokener(json);
   135         JSONObject o;
   136         try {
   137             o = new JSONObject(t);
   138         } catch (JSONException ex) {
   139             throw new AssertionError("Can't parse " + json, ex);
   140         }
   141 
   142         assertEquals(o.getJSONArray("info").getJSONObject(0).getString("firstName"), "One");
   143         assertEquals(o.getJSONArray("nicknames").getString(1), n2);
   144         assertEquals(o.getJSONArray("age").getInt(1), 73);
   145     }
   146     
   147     
   148     @OnReceive(url="/{url}")
   149     static void fetch(Person p, JSONik model) {
   150         model.setFetched(p);
   151     }
   152 
   153     @OnReceive(url="/{url}")
   154     static void fetchArray(Person[] p, JSONik model) {
   155         model.setFetchedCount(p.length);
   156         model.setFetched(p[0]);
   157     }
   158     
   159     @OnReceive(url="/{url}")
   160     static void fetchPeople(People p, JSONik model) {
   161         model.setFetchedCount(p.getInfo().size());
   162         model.setFetched(p.getInfo().get(0));
   163     }
   164 
   165     @OnReceive(url="/{url}")
   166     static void fetchPeopleAge(People p, JSONik model) {
   167         int sum = 0;
   168         for (int a : p.getAge()) {
   169             sum += a;
   170         }
   171         model.setFetchedCount(sum);
   172     }
   173     
   174     @Http(@Http.Resource(
   175         content = "{'firstName': 'Sitar', 'sex': 'MALE'}", 
   176         path="/person.json", 
   177         mimeType = "application/json"
   178     ))
   179     @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
   180         if (js == null) {
   181             js = new JSONik();
   182             js.applyBindings();
   183 
   184             js.fetch("person.json");
   185         }
   186     
   187         Person p = js.getFetched();
   188         if (p == null) {
   189             throw new InterruptedException();
   190         }
   191         
   192         assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
   193         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   194     }
   195     
   196     @OnReceive(url="/{url}?callme={me}", jsonp = "me")
   197     static void fetchViaJSONP(Person p, JSONik model) {
   198         model.setFetched(p);
   199     }
   200     
   201     @Http(@Http.Resource(
   202         content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})", 
   203         path="/person.json", 
   204         mimeType = "application/javascript",
   205         parameters = { "callme" }
   206     ))
   207     @BrwsrTest public void loadAndParseJSONP() throws InterruptedException {
   208         
   209         if (js == null) {
   210             orig = scriptElements();
   211             assert orig > 0 : "There should be some scripts on the page";
   212             
   213             js = new JSONik();
   214             js.applyBindings();
   215 
   216             js.fetchViaJSONP("person.json");
   217         }
   218     
   219         Person p = js.getFetched();
   220         if (p == null) {
   221             throw new InterruptedException();
   222         }
   223         
   224         assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
   225         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   226         
   227         int now = scriptElements();
   228         
   229         assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
   230     }
   231     
   232     @JavaScriptBody(args = {  }, body = "return window.document.getElementsByTagName('script').length;")
   233     private static native int scriptElements();
   234 
   235     @JavaScriptBody(args = { "s" }, body = "return window.JSON.parse(s);")
   236     private static native Object parseJSON(String s);
   237     
   238     @Http(@Http.Resource(
   239         content = "{'firstName': 'Sitar', 'sex': 'MALE'}", 
   240         path="/person.json", 
   241         mimeType = "application/json"
   242     ))
   243     @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
   244         if (js == null) {
   245             js = new JSONik();
   246             js.applyBindings();
   247 
   248             js.fetchArray("person.json");
   249         }
   250         
   251         Person p = js.getFetched();
   252         if (p == null) {
   253             throw new InterruptedException();
   254         }
   255         
   256         assert p != null : "We should get our person back: " + p;
   257         assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
   258         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   259     }
   260     
   261     @Http(@Http.Resource(
   262         content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]", 
   263         path="/person.json", 
   264         mimeType = "application/json"
   265     ))
   266     @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
   267         if (js == null) {
   268             js = new JSONik();
   269             js.applyBindings();
   270         
   271             js.fetch("person.json");
   272         }
   273         
   274         Person p = js.getFetched();
   275         if (p == null) {
   276             throw new InterruptedException();
   277         }
   278         
   279         assert p != null : "We should get our person back: " + p;
   280         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   281         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   282     }
   283     
   284     @Http(@Http.Resource(
   285         content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}", 
   286         path="/people.json", 
   287         mimeType = "application/json"
   288     ))
   289     @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
   290         if (js == null) {
   291             js = new JSONik();
   292             js.applyBindings();
   293         
   294             js.fetchPeople("people.json");
   295         }
   296         
   297         if (0 == js.getFetchedCount()) {
   298             throw new InterruptedException();
   299         }
   300 
   301         assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
   302         
   303         Person p = js.getFetched();
   304         
   305         assert p != null : "We should get our person back: " + p;
   306         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   307         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   308     }
   309     
   310     @Http(@Http.Resource(
   311         content = "{'age':[1, 2, 3]}", 
   312         path="/people.json", 
   313         mimeType = "application/json"
   314     ))
   315     @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
   316         if (js == null) {
   317             js = new JSONik();
   318             js.applyBindings();
   319         
   320             js.fetchPeopleAge("people.json");
   321         }
   322         
   323         if (0 == js.getFetchedCount()) {
   324             throw new InterruptedException();
   325         }
   326 
   327         assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
   328     }
   329     
   330     @OnReceive(url="/{url}")
   331     static void fetchPeopleSex(People p, JSONik model) {
   332         model.setFetchedCount(1);
   333         model.getFetchedSex().addAll(p.getSex());
   334     }
   335     
   336     
   337     @Http(@Http.Resource(
   338         content = "{'sex':['FEMALE', 'MALE', 'MALE']}", 
   339         path="/people.json", 
   340         mimeType = "application/json"
   341     ))
   342     @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
   343         if (js == null) {
   344             js = new JSONik();
   345             js.applyBindings();
   346         
   347             js.fetchPeopleSex("people.json");
   348         }
   349         
   350         if (0 == js.getFetchedCount()) {
   351             throw new InterruptedException();
   352         }
   353 
   354         assert js.getFetchedCount() == 1 : "Loaded";
   355         
   356         assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
   357         assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
   358         assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
   359         assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
   360     }
   361     
   362     @Http(@Http.Resource(
   363         content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
   364         + "{'firstName': 'Peter', 'sex': 'MALE'}"
   365         + "]", 
   366         path="/person.json", 
   367         mimeType = "application/json"
   368     ))
   369     @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
   370         if (js == null) {
   371             js = new JSONik();
   372             js.applyBindings();
   373             js.fetchArray("person.json");
   374         }
   375         
   376         
   377         Person p = js.getFetched();
   378         if (p == null) {
   379             throw new InterruptedException();
   380         }
   381         
   382         assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
   383         assert p != null : "We should get our person back: " + p;
   384         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   385         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   386     }
   387 
   388     @Factory public static Object[] create() {
   389         return VMTest.create(JSONTest.class);
   390     }
   391     
   392 }