2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
9 * The contents of this file are subject to the terms of either the GNU
10 * General Public License Version 2 only ("GPL") or the Common
11 * Development and Distribution License("CDDL") (collectively, the
12 * "License"). You may not use this file except in compliance with the
13 * License. You can obtain a copy of the License at
14 * http://www.netbeans.org/cddl-gplv2.html
15 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16 * specific language governing permissions and limitations under the
17 * License. When distributing the software, include this License Header
18 * Notice in each file and include the License file at
19 * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20 * particular file as subject to the "Classpath" exception as provided
21 * by Oracle in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the
23 * License Header, with the fields enclosed by brackets [] replaced by
24 * your own identifying information:
25 * "Portions Copyrighted [year] [name of copyright owner]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
32 * If you wish your version of this file to be governed by only the CDDL
33 * or only the GPL Version 2, indicate your decision by adding
34 * "[Contributor] elects to include this software in this distribution
35 * under the [CDDL or GPL Version 2] license." If you do not indicate a
36 * single choice of license, a recipient has the option to distribute
37 * your version of this file under either the CDDL, the GPL Version 2 or
38 * to extend the choice of license to its licensees as provided above.
39 * However, if you add GPL Version 2 code and therefore, elected the GPL
40 * Version 2 license, then the option applies only if the new code is
41 * made subject to such option by the copyright holder.
43 package net.java.html.json.tests;
45 import java.io.ByteArrayInputStream;
46 import net.java.html.BrwsrCtx;
47 import net.java.html.json.Model;
48 import net.java.html.json.ModelOperation;
49 import net.java.html.json.Models;
50 import net.java.html.json.OnReceive;
51 import net.java.html.json.Property;
52 import org.netbeans.html.json.impl.JSON;
53 import org.apidesign.html.json.tck.KOTest;
55 /** Need to verify that models produce reasonable JSON objects.
57 * @author Jaroslav Tulach <jtulach@netbeans.org>
59 @Model(className = "JSONik", properties = {
60 @Property(name = "fetched", type = Person.class),
61 @Property(name = "fetchedCount", type = int.class),
62 @Property(name = "fetchedResponse", type = String.class),
63 @Property(name = "fetchedSex", type = Sex.class, array = true)
65 public final class JSONTest {
70 @ModelOperation static void assignFetched(JSONik m, Person p) {
74 @KOTest public void toJSONInABrowser() throws Throwable {
75 Person p = Models.bind(new Person(), newContext());
77 p.setFirstName("Jarda");
78 p.setLastName("Tulach");
82 json = parseJSON(p.toString());
83 } catch (Throwable ex) {
84 throw new IllegalStateException("Can't parse " + p).initCause(ex);
87 Person p2 = JSON.read(newContext(), Person.class, json);
89 assert p2.getFirstName().equals(p.getFirstName()) :
90 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
93 @KOTest public void toJSONWithEscapeCharactersInABrowser() throws Throwable {
94 Person p = Models.bind(new Person(), newContext());
96 p.setFirstName("/*\n * Copyright (c) 2013");
99 final String txt = p.toString();
102 json = parseJSON(txt);
103 } catch (Throwable ex) {
104 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
107 Person p2 = JSON.read(newContext(), Person.class, json);
109 assert p2.getFirstName().equals(p.getFirstName()) :
110 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
113 @KOTest public void toJSONWithDoubleSlashInABrowser() throws Throwable {
114 Person p = Models.bind(new Person(), newContext());
116 p.setFirstName("/*\\n * Copyright (c) 2013");
119 final String txt = p.toString();
122 json = parseJSON(txt);
123 } catch (Throwable ex) {
124 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
127 Person p2 = JSON.read(newContext(), Person.class, json);
129 assert p2.getFirstName().equals(p.getFirstName()) :
130 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
133 @KOTest public void toJSONWithApostrophInABrowser() throws Throwable {
134 Person p = Models.bind(new Person(), newContext());
136 p.setFirstName("Jimmy 'Jim' Rambo");
139 final String txt = p.toString();
142 json = parseJSON(txt);
143 } catch (Throwable ex) {
144 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
147 Person p2 = JSON.read(newContext(), Person.class, json);
149 assert p2.getFirstName().equals(p.getFirstName()) :
150 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
153 @OnReceive(url="{url}")
154 static void fetch(Person p, JSONik model) {
158 @OnReceive(url="{url}", onError = "setMessage")
159 static void fetchArray(Person[] p, JSONik model) {
160 model.setFetchedCount(p.length);
161 model.setFetched(p[0]);
164 static void setMessage(JSONik m, Exception t) {
166 m.setFetchedResponse("Exception");
169 @OnReceive(url="{url}")
170 static void fetchPeople(People p, JSONik model) {
171 model.setFetchedCount(p.getInfo().size());
172 model.setFetched(p.getInfo().get(0));
175 @OnReceive(url="{url}")
176 static void fetchPeopleAge(People p, JSONik model) {
178 for (int a : p.getAge()) {
181 model.setFetchedCount(sum);
184 @KOTest public void loadAndParseJSON() throws InterruptedException {
186 url = Utils.prepareURL(
187 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}",
190 js = Models.bind(new JSONik(), newContext());
197 Person p = js.getFetched();
199 throw new InterruptedException();
202 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
203 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
206 @OnReceive(url="{url}?callme={me}", jsonp = "me")
207 static void fetchViaJSONP(Person p, JSONik model) {
211 @KOTest public void loadAndParseJSONP() throws InterruptedException, Exception {
213 url = Utils.prepareURL(
214 JSONTest.class, "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
215 "application/javascript",
218 orig = scriptElements();
219 assert orig > 0 : "There should be some scripts on the page";
221 js = Models.bind(new JSONik(), newContext());
225 js.fetchViaJSONP(url);
228 Person p = js.getFetched();
230 throw new InterruptedException();
233 assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
234 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
236 int now = scriptElements();
238 assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
243 @OnReceive(url="{url}", method = "PUT", data = Person.class)
244 static void putPerson(JSONik model, String reply) {
245 model.setFetchedCount(1);
246 model.setFetchedResponse(reply);
249 @KOTest public void putPeopleUsesRightMethod() throws InterruptedException, Exception {
251 url = Utils.prepareURL(
252 JSONTest.class, "$0\n$1",
254 "http.method", "http.requestBody"
256 orig = scriptElements();
257 assert orig > 0 : "There should be some scripts on the page";
259 js = Models.bind(new JSONik(), newContext());
262 Person p = Models.bind(new Person(), BrwsrCtx.EMPTY);
263 p.setFirstName("Jarda");
264 js.putPerson(url, p);
267 int cnt = js.getFetchedCount();
269 throw new InterruptedException();
271 String res = js.getFetchedResponse();
272 int line = res.indexOf('\n');
275 msg = res.substring(line + 1);
276 res = res.substring(0, line);
281 assert "PUT".equals(res) : "Server was queried with PUT method: " + js.getFetchedResponse();
283 assert msg.contains("Jarda") : "Data transferred to the server: " + msg;
286 private static int scriptElements() throws Exception {
287 return ((Number)Utils.executeScript(
289 "return window.document.getElementsByTagName('script').length;")).intValue();
292 private static Object parseJSON(String s) throws Exception {
293 return Utils.executeScript(
295 "return window.JSON.parse(arguments[0]);", s);
298 @KOTest public void loadAndParseJSONSentToArray() throws InterruptedException {
300 url = Utils.prepareURL(
301 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}",
305 js = Models.bind(new JSONik(), newContext());
312 Person p = js.getFetched();
314 throw new InterruptedException();
317 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
318 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
321 @KOTest public void loadAndParseJSONArraySingle() throws InterruptedException {
323 url = Utils.prepareURL(
324 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
327 js = Models.bind(new JSONik(), newContext());
334 Person p = js.getFetched();
336 throw new InterruptedException();
339 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
340 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
343 @KOTest public void loadAndParseArrayInPeople() throws InterruptedException {
345 url = Utils.prepareURL(
346 JSONTest.class, "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
349 js = Models.bind(new JSONik(), newContext());
355 if (0 == js.getFetchedCount()) {
356 throw new InterruptedException();
359 assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
361 Person p = js.getFetched();
363 assert p != null : "We should get our person back: " + p;
364 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
365 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
368 @KOTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
370 url = Utils.prepareURL(
371 JSONTest.class, "{'age':[1, 2, 3]}",
374 js = Models.bind(new JSONik(), newContext());
377 js.fetchPeopleAge(url);
380 if (0 == js.getFetchedCount()) {
381 throw new InterruptedException();
384 assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
387 @OnReceive(url="{url}")
388 static void fetchPeopleSex(People p, JSONik model) {
389 model.setFetchedCount(1);
390 model.getFetchedSex().addAll(p.getSex());
393 @KOTest public void loadAndParseArrayOfEnums() throws InterruptedException {
395 url = Utils.prepareURL(
396 JSONTest.class, "{'sex':['FEMALE', 'MALE', 'MALE']}",
399 js = Models.bind(new JSONik(), newContext());
402 js.fetchPeopleSex(url);
405 if (0 == js.getFetchedCount()) {
406 throw new InterruptedException();
409 assert js.getFetchedCount() == 1 : "Loaded";
411 assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
412 assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
413 assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
414 assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
417 @KOTest public void loadAndParseJSONArray() throws InterruptedException {
419 url = Utils.prepareURL(
420 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
421 + "{'firstName': 'Peter', 'sex': 'MALE'}"
425 js = Models.bind(new JSONik(), newContext());
433 Person p = js.getFetched();
435 throw new InterruptedException();
438 assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
439 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
440 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
443 @KOTest public void loadError() throws InterruptedException {
445 js = Models.bind(new JSONik(), newContext());
449 js.fetchArray("http://127.0.0.1:54253/does/not/exist.txt");
453 if (js.getFetchedResponse() == null) {
454 throw new InterruptedException();
457 assert "Exception".equals(js.getFetchedResponse()) : js.getFetchedResponse();
460 @Model(className = "NameAndValue", properties = {
461 @Property(name = "name", type = String.class),
462 @Property(name = "value", type = long.class),
463 @Property(name = "small", type = byte.class)
468 @KOTest public void parseNullNumber() throws Exception {
469 String txt = "{ \"name\":\"M\" }";
470 ByteArrayInputStream is = new ByteArrayInputStream(txt.getBytes("UTF-8"));
471 NameAndValue v = Models.parse(newContext(), NameAndValue.class, is);
472 assert "M".equals(v.getName()) : "Name is 'M': " + v.getName();
473 assert 0 == v.getValue() : "Value is empty: " + v.getValue();
474 assert 0 == v.getSmall() : "Small value is empty: " + v.getSmall();
477 @KOTest public void deserializeWrongEnum() throws Exception {
478 String str = "{ \"sex\" : \"unknown\" }";
479 ByteArrayInputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"));
480 Person p = Models.parse(newContext(), Person.class, is);
481 assert p.getSex() == null : "Wrong sex means null, but was: " + p.getSex();
485 private static BrwsrCtx newContext() {
486 return Utils.newContext(JSONTest.class);