2 * HTML via Java(tm) Language Bindings
3 * Copyright (C) 2013 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. apidesign.org
13 * designates this particular file as subject to the
14 * "Classpath" exception as provided by apidesign.org
15 * in the License file that accompanied this code.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. Look for COPYING file in the top folder.
19 * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
21 package net.java.html.json.tests;
23 import java.io.ByteArrayInputStream;
24 import net.java.html.BrwsrCtx;
25 import net.java.html.json.Model;
26 import net.java.html.json.Models;
27 import net.java.html.json.OnReceive;
28 import net.java.html.json.Property;
29 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
30 import org.apidesign.bck2brwsr.vmtest.Http;
31 import org.apidesign.bck2brwsr.vmtest.VMTest;
32 import org.apidesign.html.json.impl.JSON;
34 /** Need to verify that models produce reasonable JSON objects.
36 * @author Jaroslav Tulach <jtulach@netbeans.org>
38 @Model(className = "JSONik", properties = {
39 @Property(name = "fetched", type = Person.class),
40 @Property(name = "fetchedCount", type = int.class),
41 @Property(name = "fetchedResponse", type = String.class),
42 @Property(name = "fetchedSex", type = Sex.class, array = true)
44 public final class JSONTest {
48 @BrwsrTest public void toJSONInABrowser() throws Throwable {
49 Person p = Models.bind(new Person(), Utils.newContext());
51 p.setFirstName("Jarda");
52 p.setLastName("Tulach");
56 json = parseJSON(p.toString());
57 } catch (Throwable ex) {
58 throw new IllegalStateException("Can't parse " + p).initCause(ex);
61 Person p2 = JSON.read(Utils.newContext(), Person.class, json);
63 assert p2.getFirstName().equals(p.getFirstName()) :
64 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
67 @OnReceive(url="/{url}")
68 static void fetch(Person p, JSONik model) {
72 @OnReceive(url="/{url}")
73 static void fetchArray(Person[] p, JSONik model) {
74 model.setFetchedCount(p.length);
75 model.setFetched(p[0]);
78 @OnReceive(url="/{url}")
79 static void fetchPeople(People p, JSONik model) {
80 model.setFetchedCount(p.getInfo().size());
81 model.setFetched(p.getInfo().get(0));
84 @OnReceive(url="/{url}")
85 static void fetchPeopleAge(People p, JSONik model) {
87 for (int a : p.getAge()) {
90 model.setFetchedCount(sum);
94 content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
96 mimeType = "application/json"
98 @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
100 js = Models.bind(new JSONik(), Utils.newContext());
103 js.fetch("person.json");
106 Person p = js.getFetched();
108 throw new InterruptedException();
111 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
112 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
115 @OnReceive(url="/{url}?callme={me}", jsonp = "me")
116 static void fetchViaJSONP(Person p, JSONik model) {
120 @Http(@Http.Resource(
121 content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
123 mimeType = "application/javascript",
124 parameters = { "callme" }
126 @BrwsrTest public void loadAndParseJSONP() throws InterruptedException, Exception {
129 orig = scriptElements();
130 assert orig > 0 : "There should be some scripts on the page";
132 js = Models.bind(new JSONik(), Utils.newContext());
135 js.fetchViaJSONP("person.json");
138 Person p = js.getFetched();
140 throw new InterruptedException();
143 assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
144 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
146 int now = scriptElements();
148 assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
153 @OnReceive(url="{url}", method = "PUT", data = Person.class)
154 static void putPerson(JSONik model, String reply) {
155 model.setFetchedCount(1);
156 model.setFetchedResponse(reply);
158 @Http(@Http.Resource(
161 mimeType = "text/plain",
162 parameters = { "http.method", "http.requestBody" }
164 @BrwsrTest public void putPeopleUsesRightMethod() throws InterruptedException, Exception {
166 orig = scriptElements();
167 assert orig > 0 : "There should be some scripts on the page";
169 js = Models.bind(new JSONik(), Utils.newContext());
172 Person p = Models.bind(new Person(), BrwsrCtx.EMPTY);
173 p.setFirstName("Jarda");
174 js.putPerson("person.json", p);
177 int cnt = js.getFetchedCount();
179 throw new InterruptedException();
181 String res = js.getFetchedResponse();
182 int line = res.indexOf('\n');
185 msg = res.substring(line + 1);
186 res = res.substring(0, line);
191 assert "PUT".equals(res) : "Server was queried with PUT method: " + js.getFetchedResponse();
193 assert msg.contains("Jarda") : "Data transferred to the server: " + msg;
196 private static int scriptElements() throws Exception {
197 return ((Number)Utils.executeScript("return window.document.getElementsByTagName('script').length;")).intValue();
200 private static Object parseJSON(String s) throws Exception {
201 return Utils.executeScript("return window.JSON.parse(arguments[0]);", s);
204 @Http(@Http.Resource(
205 content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
207 mimeType = "application/json"
209 @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
211 js = Models.bind(new JSONik(), Utils.newContext());
214 js.fetchArray("person.json");
217 Person p = js.getFetched();
219 throw new InterruptedException();
222 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
223 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
226 @Http(@Http.Resource(
227 content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
229 mimeType = "application/json"
231 @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
233 js = Models.bind(new JSONik(), Utils.newContext());
236 js.fetch("person.json");
239 Person p = js.getFetched();
241 throw new InterruptedException();
244 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
245 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
248 @Http(@Http.Resource(
249 content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
251 mimeType = "application/json"
253 @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
255 js = Models.bind(new JSONik(), Utils.newContext());
258 js.fetchPeople("people.json");
261 if (0 == js.getFetchedCount()) {
262 throw new InterruptedException();
265 assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
267 Person p = js.getFetched();
269 assert p != null : "We should get our person back: " + p;
270 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
271 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
274 @Http(@Http.Resource(
275 content = "{'age':[1, 2, 3]}",
277 mimeType = "application/json"
279 @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
281 js = Models.bind(new JSONik(), Utils.newContext());
284 js.fetchPeopleAge("people.json");
287 if (0 == js.getFetchedCount()) {
288 throw new InterruptedException();
291 assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
294 @OnReceive(url="/{url}")
295 static void fetchPeopleSex(People p, JSONik model) {
296 model.setFetchedCount(1);
297 model.getFetchedSex().addAll(p.getSex());
301 @Http(@Http.Resource(
302 content = "{'sex':['FEMALE', 'MALE', 'MALE']}",
304 mimeType = "application/json"
306 @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
308 js = Models.bind(new JSONik(), Utils.newContext());
311 js.fetchPeopleSex("people.json");
314 if (0 == js.getFetchedCount()) {
315 throw new InterruptedException();
318 assert js.getFetchedCount() == 1 : "Loaded";
320 assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
321 assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
322 assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
323 assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
326 @Http(@Http.Resource(
327 content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
328 + "{'firstName': 'Peter', 'sex': 'MALE'}"
331 mimeType = "application/json"
333 @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
335 js = Models.bind(new JSONik(), Utils.newContext());
337 js.fetchArray("person.json");
341 Person p = js.getFetched();
343 throw new InterruptedException();
346 assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
347 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
348 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
351 @Model(className = "NameAndValue", properties = {
352 @Property(name = "name", type = String.class),
353 @Property(name = "value", type = long.class),
354 @Property(name = "small", type = byte.class)
359 @BrwsrTest public void parseNullNumber() throws Exception {
360 String txt = "{ \"name\":\"M\" }";
361 ByteArrayInputStream is = new ByteArrayInputStream(txt.getBytes("UTF-8"));
362 NameAndValue v = Models.parse(Utils.newContext(), NameAndValue.class, is);
363 assert "M".equals(v.getName()) : "Name is 'M': " + v.getName();
364 assert 0 == v.getValue() : "Value is empty: " + v.getValue();
365 assert 0 == v.getSmall() : "Small value is empty: " + v.getSmall();
368 static Object[] create() {
369 return VMTest.create(JSONTest.class);