1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/json-tck/pom.xml Wed Apr 24 18:34:31 2013 +0200
1.3 @@ -0,0 +1,51 @@
1.4 +<?xml version="1.0"?>
1.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
1.6 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1.7 + <modelVersion>4.0.0</modelVersion>
1.8 + <parent>
1.9 + <groupId>org.apidesign</groupId>
1.10 + <artifactId>html</artifactId>
1.11 + <version>0.1-SNAPSHOT</version>
1.12 + </parent>
1.13 + <groupId>org.apidesign.html</groupId>
1.14 + <artifactId>net.java.html.json.tck</artifactId>
1.15 + <version>0.1-SNAPSHOT</version>
1.16 + <name>TCK for JSON Model</name>
1.17 + <url>http://maven.apache.org</url>
1.18 + <properties>
1.19 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1.20 + </properties>
1.21 + <build>
1.22 + <plugins>
1.23 + <plugin>
1.24 + <groupId>org.apache.maven.plugins</groupId>
1.25 + <artifactId>maven-javadoc-plugin</artifactId>
1.26 + <configuration>
1.27 + <subpackages>org.apidesign.html.json.tck:org.apidesign.html.json.spi</subpackages>
1.28 + <skip>false</skip>
1.29 + <includeDependencySources>true</includeDependencySources>
1.30 + </configuration>
1.31 + </plugin>
1.32 + </plugins>
1.33 + </build>
1.34 + <dependencies>
1.35 + <dependency>
1.36 + <groupId>org.apidesign.html</groupId>
1.37 + <artifactId>net.java.html.json</artifactId>
1.38 + <version>0.1-SNAPSHOT</version>
1.39 + <type>jar</type>
1.40 + </dependency>
1.41 + <dependency>
1.42 + <groupId>org.testng</groupId>
1.43 + <artifactId>testng</artifactId>
1.44 + <scope>compile</scope>
1.45 + <type>jar</type>
1.46 + </dependency>
1.47 + <dependency>
1.48 + <groupId>org.apidesign.bck2brwsr</groupId>
1.49 + <artifactId>vmtest</artifactId>
1.50 + <version>0.6</version>
1.51 + <type>jar</type>
1.52 + </dependency>
1.53 + </dependencies>
1.54 +</project>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Wed Apr 24 18:34:31 2013 +0200
2.3 @@ -0,0 +1,67 @@
2.4 +/**
2.5 + * HTML via Java(tm) Language Bindings
2.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 2 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details. apidesign.org
2.16 + * designates this particular file as subject to the
2.17 + * "Classpath" exception as provided by apidesign.org
2.18 + * in the License file that accompanied this code.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License
2.21 + * along with this program. Look for COPYING file in the top folder.
2.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
2.23 + */
2.24 +package net.java.html.json.tests;
2.25 +
2.26 +import org.apidesign.html.json.tck.KnockoutTCK;
2.27 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.28 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
2.29 +import org.apidesign.bck2brwsr.vmtest.VMTest;
2.30 +import org.apidesign.html.json.impl.JSON;
2.31 +
2.32 +/**
2.33 + *
2.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.35 + */
2.36 +public final class ConvertTypesTest {
2.37 + @JavaScriptBody(args = { "includeSex" }, body = "var json = new Object();"
2.38 + + "json.firstName = 'son';\n"
2.39 + + "json.lastName = 'dj';\n"
2.40 + + "if (includeSex) json.sex = 'MALE';\n"
2.41 + + "return json;"
2.42 + )
2.43 + private static native Object createJSON(boolean includeSex);
2.44 +
2.45 + @BrwsrTest
2.46 + public void testConvertToPeople() throws Exception {
2.47 + final Object o = createJSON(true);
2.48 +
2.49 + Person p = JSON.read(KnockoutTCK.newContext(), Person.class, o);
2.50 +
2.51 + assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
2.52 + assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
2.53 + assert Sex.MALE.equals(p.getSex()) : "Sex: " + p.getSex();
2.54 + }
2.55 +
2.56 + @BrwsrTest
2.57 + public void testConvertToPeopleWithoutSex() throws Exception {
2.58 + final Object o = createJSON(false);
2.59 +
2.60 + Person p = JSON.read(KnockoutTCK.newContext(), Person.class, o);
2.61 +
2.62 + assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
2.63 + assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
2.64 + assert p.getSex() == null : "No sex: " + p.getSex();
2.65 + }
2.66 +
2.67 + static Object[] create() {
2.68 + return VMTest.create(ConvertTypesTest.class);
2.69 + }
2.70 +}
2.71 \ No newline at end of file
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Wed Apr 24 18:34:31 2013 +0200
3.3 @@ -0,0 +1,306 @@
3.4 +/**
3.5 + * HTML via Java(tm) Language Bindings
3.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.7 + *
3.8 + * This program is free software: you can redistribute it and/or modify
3.9 + * it under the terms of the GNU General Public License as published by
3.10 + * the Free Software Foundation, version 2 of the License.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details. apidesign.org
3.16 + * designates this particular file as subject to the
3.17 + * "Classpath" exception as provided by apidesign.org
3.18 + * in the License file that accompanied this code.
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License
3.21 + * along with this program. Look for COPYING file in the top folder.
3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
3.23 + */
3.24 +package net.java.html.json.tests;
3.25 +
3.26 +import net.java.html.json.Model;
3.27 +import net.java.html.json.OnReceive;
3.28 +import net.java.html.json.Property;
3.29 +import org.apidesign.html.json.tck.KnockoutTCK;
3.30 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
3.31 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
3.32 +import org.apidesign.bck2brwsr.vmtest.Http;
3.33 +import org.apidesign.bck2brwsr.vmtest.VMTest;
3.34 +import org.apidesign.html.json.impl.JSON;
3.35 +
3.36 +/** Need to verify that models produce reasonable JSON objects.
3.37 + *
3.38 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.39 + */
3.40 +@Model(className = "JSONik", properties = {
3.41 + @Property(name = "fetched", type = Person.class),
3.42 + @Property(name = "fetchedCount", type = int.class),
3.43 + @Property(name = "fetchedSex", type = Sex.class, array = true)
3.44 +})
3.45 +public final class JSONTest {
3.46 + private JSONik js;
3.47 + private Integer orig;
3.48 +
3.49 + @BrwsrTest public void toJSONInABrowser() throws Throwable {
3.50 + Person p = new Person(KnockoutTCK.newContext());
3.51 + p.setSex(Sex.MALE);
3.52 + p.setFirstName("Jarda");
3.53 + p.setLastName("Tulach");
3.54 +
3.55 + Object json;
3.56 + try {
3.57 + json = parseJSON(p.toString());
3.58 + } catch (Throwable ex) {
3.59 + throw new IllegalStateException("Can't parse " + p).initCause(ex);
3.60 + }
3.61 +
3.62 + Person p2 = JSON.read(KnockoutTCK.newContext(), Person.class, json);
3.63 +
3.64 + assert p2.getFirstName().equals(p.getFirstName()) :
3.65 + "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
3.66 + }
3.67 +
3.68 + @OnReceive(url="/{url}")
3.69 + static void fetch(Person p, JSONik model) {
3.70 + model.setFetched(p);
3.71 + }
3.72 +
3.73 + @OnReceive(url="/{url}")
3.74 + static void fetchArray(Person[] p, JSONik model) {
3.75 + model.setFetchedCount(p.length);
3.76 + model.setFetched(p[0]);
3.77 + }
3.78 +
3.79 + @OnReceive(url="/{url}")
3.80 + static void fetchPeople(People p, JSONik model) {
3.81 + model.setFetchedCount(p.getInfo().size());
3.82 + model.setFetched(p.getInfo().get(0));
3.83 + }
3.84 +
3.85 + @OnReceive(url="/{url}")
3.86 + static void fetchPeopleAge(People p, JSONik model) {
3.87 + int sum = 0;
3.88 + for (int a : p.getAge()) {
3.89 + sum += a;
3.90 + }
3.91 + model.setFetchedCount(sum);
3.92 + }
3.93 +
3.94 + @Http(@Http.Resource(
3.95 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
3.96 + path="/person.json",
3.97 + mimeType = "application/json"
3.98 + ))
3.99 + @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
3.100 + if (js == null) {
3.101 + js = new JSONik(KnockoutTCK.newContext());
3.102 + js.applyBindings();
3.103 +
3.104 + js.fetch("person.json");
3.105 + }
3.106 +
3.107 + Person p = js.getFetched();
3.108 + if (p == null) {
3.109 + throw new InterruptedException();
3.110 + }
3.111 +
3.112 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
3.113 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
3.114 + }
3.115 +
3.116 + @OnReceive(url="/{url}?callme={me}", jsonp = "me")
3.117 + static void fetchViaJSONP(Person p, JSONik model) {
3.118 + model.setFetched(p);
3.119 + }
3.120 +
3.121 + @Http(@Http.Resource(
3.122 + content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
3.123 + path="/person.json",
3.124 + mimeType = "application/javascript",
3.125 + parameters = { "callme" }
3.126 + ))
3.127 + @BrwsrTest public void loadAndParseJSONP() throws InterruptedException {
3.128 +
3.129 + if (js == null) {
3.130 + orig = scriptElements();
3.131 + assert orig > 0 : "There should be some scripts on the page";
3.132 +
3.133 + js = new JSONik(KnockoutTCK.newContext());
3.134 + js.applyBindings();
3.135 +
3.136 + js.fetchViaJSONP("person.json");
3.137 + }
3.138 +
3.139 + Person p = js.getFetched();
3.140 + if (p == null) {
3.141 + throw new InterruptedException();
3.142 + }
3.143 +
3.144 + assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
3.145 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
3.146 +
3.147 + int now = scriptElements();
3.148 +
3.149 + assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
3.150 + }
3.151 +
3.152 + @JavaScriptBody(args = { }, body = "return window.document.getElementsByTagName('script').length;")
3.153 + private static native int scriptElements();
3.154 +
3.155 + @JavaScriptBody(args = { "s" }, body = "return window.JSON.parse(s);")
3.156 + private static native Object parseJSON(String s);
3.157 +
3.158 + @Http(@Http.Resource(
3.159 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
3.160 + path="/person.json",
3.161 + mimeType = "application/json"
3.162 + ))
3.163 + @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
3.164 + if (js == null) {
3.165 + js = new JSONik(KnockoutTCK.newContext());
3.166 + js.applyBindings();
3.167 +
3.168 + js.fetchArray("person.json");
3.169 + }
3.170 +
3.171 + Person p = js.getFetched();
3.172 + if (p == null) {
3.173 + throw new InterruptedException();
3.174 + }
3.175 +
3.176 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
3.177 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
3.178 + }
3.179 +
3.180 + @Http(@Http.Resource(
3.181 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
3.182 + path="/person.json",
3.183 + mimeType = "application/json"
3.184 + ))
3.185 + @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
3.186 + if (js == null) {
3.187 + js = new JSONik(KnockoutTCK.newContext());
3.188 + js.applyBindings();
3.189 +
3.190 + js.fetch("person.json");
3.191 + }
3.192 +
3.193 + Person p = js.getFetched();
3.194 + if (p == null) {
3.195 + throw new InterruptedException();
3.196 + }
3.197 +
3.198 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
3.199 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
3.200 + }
3.201 +
3.202 + @Http(@Http.Resource(
3.203 + content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
3.204 + path="/people.json",
3.205 + mimeType = "application/json"
3.206 + ))
3.207 + @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
3.208 + if (js == null) {
3.209 + js = new JSONik(KnockoutTCK.newContext());
3.210 + js.applyBindings();
3.211 +
3.212 + js.fetchPeople("people.json");
3.213 + }
3.214 +
3.215 + if (0 == js.getFetchedCount()) {
3.216 + throw new InterruptedException();
3.217 + }
3.218 +
3.219 + assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
3.220 +
3.221 + Person p = js.getFetched();
3.222 +
3.223 + assert p != null : "We should get our person back: " + p;
3.224 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
3.225 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
3.226 + }
3.227 +
3.228 + @Http(@Http.Resource(
3.229 + content = "{'age':[1, 2, 3]}",
3.230 + path="/people.json",
3.231 + mimeType = "application/json"
3.232 + ))
3.233 + @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
3.234 + if (js == null) {
3.235 + js = new JSONik(KnockoutTCK.newContext());
3.236 + js.applyBindings();
3.237 +
3.238 + js.fetchPeopleAge("people.json");
3.239 + }
3.240 +
3.241 + if (0 == js.getFetchedCount()) {
3.242 + throw new InterruptedException();
3.243 + }
3.244 +
3.245 + assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
3.246 + }
3.247 +
3.248 + @OnReceive(url="/{url}")
3.249 + static void fetchPeopleSex(People p, JSONik model) {
3.250 + model.setFetchedCount(1);
3.251 + model.getFetchedSex().addAll(p.getSex());
3.252 + }
3.253 +
3.254 +
3.255 + @Http(@Http.Resource(
3.256 + content = "{'sex':['FEMALE', 'MALE', 'MALE']}",
3.257 + path="/people.json",
3.258 + mimeType = "application/json"
3.259 + ))
3.260 + @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
3.261 + if (js == null) {
3.262 + js = new JSONik(KnockoutTCK.newContext());
3.263 + js.applyBindings();
3.264 +
3.265 + js.fetchPeopleSex("people.json");
3.266 + }
3.267 +
3.268 + if (0 == js.getFetchedCount()) {
3.269 + throw new InterruptedException();
3.270 + }
3.271 +
3.272 + assert js.getFetchedCount() == 1 : "Loaded";
3.273 +
3.274 + assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
3.275 + assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
3.276 + assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
3.277 + assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
3.278 + }
3.279 +
3.280 + @Http(@Http.Resource(
3.281 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
3.282 + + "{'firstName': 'Peter', 'sex': 'MALE'}"
3.283 + + "]",
3.284 + path="/person.json",
3.285 + mimeType = "application/json"
3.286 + ))
3.287 + @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
3.288 + if (js == null) {
3.289 + js = new JSONik(KnockoutTCK.newContext());
3.290 + js.applyBindings();
3.291 + js.fetchArray("person.json");
3.292 + }
3.293 +
3.294 +
3.295 + Person p = js.getFetched();
3.296 + if (p == null) {
3.297 + throw new InterruptedException();
3.298 + }
3.299 +
3.300 + assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
3.301 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
3.302 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
3.303 + }
3.304 +
3.305 + static Object[] create() {
3.306 + return VMTest.create(JSONTest.class);
3.307 + }
3.308 +
3.309 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Wed Apr 24 18:34:31 2013 +0200
4.3 @@ -0,0 +1,251 @@
4.4 +/**
4.5 + * HTML via Java(tm) Language Bindings
4.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.7 + *
4.8 + * This program is free software: you can redistribute it and/or modify
4.9 + * it under the terms of the GNU General Public License as published by
4.10 + * the Free Software Foundation, version 2 of the License.
4.11 + *
4.12 + * This program is distributed in the hope that it will be useful,
4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.15 + * GNU General Public License for more details. apidesign.org
4.16 + * designates this particular file as subject to the
4.17 + * "Classpath" exception as provided by apidesign.org
4.18 + * in the License file that accompanied this code.
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License
4.21 + * along with this program. Look for COPYING file in the top folder.
4.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
4.23 + */
4.24 +package net.java.html.json.tests;
4.25 +
4.26 +import java.util.List;
4.27 +import net.java.html.json.ComputedProperty;
4.28 +import net.java.html.json.Function;
4.29 +import net.java.html.json.Model;
4.30 +import net.java.html.json.Property;
4.31 +import org.apidesign.html.json.tck.KnockoutTCK;
4.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
4.33 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
4.34 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
4.35 +import org.apidesign.bck2brwsr.vmtest.VMTest;
4.36 +
4.37 +/**
4.38 + *
4.39 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.40 + */
4.41 +@Model(className="KnockoutModel", properties={
4.42 + @Property(name="name", type=String.class),
4.43 + @Property(name="results", type=String.class, array = true),
4.44 + @Property(name="callbackCount", type=int.class),
4.45 + @Property(name="people", type=PersonImpl.class, array = true)
4.46 +})
4.47 +public final class KnockoutTest {
4.48 +
4.49 + @HtmlFragment(
4.50 + "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
4.51 + "Your name: <input id='input' data-bind=\"value: name\"></input>\n" +
4.52 + "<button id=\"hello\">Say Hello!</button>\n"
4.53 + )
4.54 + @BrwsrTest public void modifyValueAssertChangeInModel() {
4.55 + KnockoutModel m = new KnockoutModel(KnockoutTCK.newContext());
4.56 + m.setName("Kukuc");
4.57 + m.applyBindings();
4.58 +
4.59 + String v = getSetInput(null);
4.60 + assert "Kukuc".equals(v) : "Value is really kukuc: " + v;
4.61 +
4.62 + getSetInput("Jardo");
4.63 + triggerEvent("input", "change");
4.64 +
4.65 + assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
4.66 + }
4.67 +
4.68 + @JavaScriptBody(args = {"value"}, body
4.69 + = "var n = window.document.getElementById('input'); \n "
4.70 + + "if (value != null) n['value'] = value; \n "
4.71 + + "return n['value']; \n ")
4.72 + private static String getSetInput(String value) {
4.73 + return null;
4.74 + }
4.75 +
4.76 + @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev);")
4.77 + public static void triggerEvent(String id, String ev) {
4.78 + }
4.79 +
4.80 + @HtmlFragment(
4.81 + "<ul id='ul' data-bind='foreach: results'>\n"
4.82 + + " <li data-bind='text: $data, click: $root.call'/>\n"
4.83 + + "</ul>\n"
4.84 + )
4.85 + @BrwsrTest public void displayContentOfArray() {
4.86 + KnockoutModel m = new KnockoutModel(KnockoutTCK.newContext());
4.87 + m.getResults().add("Ahoj");
4.88 + m.applyBindings();
4.89 +
4.90 + int cnt = countChildren("ul");
4.91 + assert cnt == 1 : "One child, but was " + cnt;
4.92 +
4.93 + m.getResults().add("Hi");
4.94 +
4.95 + cnt = countChildren("ul");
4.96 + assert cnt == 2 : "Two children now, but was " + cnt;
4.97 +
4.98 + triggerChildClick("ul", 1);
4.99 +
4.100 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
4.101 + assert "Hi".equals(m.getName()) : "We got callback from 2nd child " + m.getName();
4.102 + }
4.103 +
4.104 + @HtmlFragment(
4.105 + "<ul id='ul' data-bind='foreach: cmpResults'>\n"
4.106 + + " <li><b data-bind='text: $data'></b></li>\n"
4.107 + + "</ul>\n"
4.108 + )
4.109 + @BrwsrTest public void displayContentOfDerivedArray() {
4.110 + KnockoutModel m = new KnockoutModel(KnockoutTCK.newContext());
4.111 + m.getResults().add("Ahoj");
4.112 + m.applyBindings();
4.113 +
4.114 + int cnt = countChildren("ul");
4.115 + assert cnt == 1 : "One child, but was " + cnt;
4.116 +
4.117 + m.getResults().add("hello");
4.118 +
4.119 + cnt = countChildren("ul");
4.120 + assert cnt == 2 : "Two children now, but was " + cnt;
4.121 + }
4.122 +
4.123 + @HtmlFragment(
4.124 + "<ul id='ul' data-bind='foreach: people'>\n"
4.125 + + " <li data-bind='text: $data.firstName, click: $root.removePerson'></li>\n"
4.126 + + "</ul>\n"
4.127 + )
4.128 + @BrwsrTest public void displayContentOfArrayOfPeople() {
4.129 + KnockoutModel m = new KnockoutModel(KnockoutTCK.newContext());
4.130 +
4.131 + final Person first = new Person(KnockoutTCK.newContext());
4.132 + first.setFirstName("first");
4.133 + m.getPeople().add(first);
4.134 +
4.135 + m.applyBindings();
4.136 +
4.137 + int cnt = countChildren("ul");
4.138 + assert cnt == 1 : "One child, but was " + cnt;
4.139 +
4.140 + final Person second = new Person(KnockoutTCK.newContext());
4.141 + second.setFirstName("second");
4.142 + m.getPeople().add(second);
4.143 +
4.144 + cnt = countChildren("ul");
4.145 + assert cnt == 2 : "Two children now, but was " + cnt;
4.146 +
4.147 + triggerChildClick("ul", 1);
4.148 +
4.149 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
4.150 +
4.151 + cnt = countChildren("ul");
4.152 + assert cnt == 1 : "Again one child, but was " + cnt;
4.153 +
4.154 + String txt = childText("ul", 0);
4.155 + assert "first".equals(txt) : "Expecting 'first': " + txt;
4.156 +
4.157 + first.setFirstName("changed");
4.158 +
4.159 + txt = childText("ul", 0);
4.160 + assert "changed".equals(txt) : "Expecting 'changed': " + txt;
4.161 + }
4.162 +
4.163 + @ComputedProperty
4.164 + static Person firstPerson(List<Person> people) {
4.165 + return people.isEmpty() ? null : people.get(0);
4.166 + }
4.167 +
4.168 + @HtmlFragment(
4.169 + "<p id='ul' data-bind='with: firstPerson'>\n"
4.170 + + " <span data-bind='text: firstName, click: changeSex'></span>\n"
4.171 + + "</p>\n"
4.172 + )
4.173 + @BrwsrTest public void accessFirstPersonWithOnFunction() {
4.174 + trasfertToFemale();
4.175 + }
4.176 +
4.177 + @HtmlFragment(
4.178 + "<ul id='ul' data-bind='foreach: people'>\n"
4.179 + + " <li data-bind='text: $data.firstName, click: changeSex'></li>\n"
4.180 + + "</ul>\n"
4.181 + )
4.182 + @BrwsrTest public void onPersonFunction() {
4.183 + trasfertToFemale();
4.184 + }
4.185 +
4.186 + private void trasfertToFemale() {
4.187 + KnockoutModel m = new KnockoutModel(KnockoutTCK.newContext());
4.188 +
4.189 + final Person first = new Person(KnockoutTCK.newContext());
4.190 + first.setFirstName("first");
4.191 + first.setSex(Sex.MALE);
4.192 + m.getPeople().add(first);
4.193 +
4.194 +
4.195 + m.applyBindings();
4.196 +
4.197 + int cnt = countChildren("ul");
4.198 + assert cnt == 1 : "One child, but was " + cnt;
4.199 +
4.200 +
4.201 + triggerChildClick("ul", 0);
4.202 +
4.203 + assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex();
4.204 + }
4.205 +
4.206 + @Function
4.207 + static void call(KnockoutModel m, String data) {
4.208 + m.setName(data);
4.209 + m.setCallbackCount(m.getCallbackCount() + 1);
4.210 + }
4.211 +
4.212 + @Function
4.213 + static void removePerson(KnockoutModel model, Person data) {
4.214 + model.setCallbackCount(model.getCallbackCount() + 1);
4.215 + model.getPeople().remove(data);
4.216 + }
4.217 +
4.218 +
4.219 + @ComputedProperty
4.220 + static String helloMessage(String name) {
4.221 + return "Hello " + name + "!";
4.222 + }
4.223 +
4.224 + @ComputedProperty
4.225 + static List<String> cmpResults(List<String> results) {
4.226 + return results;
4.227 + }
4.228 +
4.229 + static Object[] create() {
4.230 + return VMTest.create(KnockoutTest.class);
4.231 + }
4.232 +
4.233 + @JavaScriptBody(args = { "id" }, body =
4.234 + "var e = window.document.getElementById(id);\n "
4.235 + + "if (typeof e === 'undefined') return -2;\n "
4.236 + + "return e.children.length;\n "
4.237 + )
4.238 + private static native int countChildren(String id);
4.239 +
4.240 + @JavaScriptBody(args = { "id", "pos" }, body =
4.241 + "var e = window.document.getElementById(id);\n "
4.242 + + "var ev = window.document.createEvent('MouseEvents');\n "
4.243 + + "ev.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);\n "
4.244 + + "e.children[pos].dispatchEvent(ev);\n "
4.245 + )
4.246 + private static native void triggerChildClick(String id, int pos);
4.247 +
4.248 + @JavaScriptBody(args = { "id", "pos" }, body =
4.249 + "var e = window.document.getElementById(id);\n "
4.250 + + "var t = e.children[pos].innerHTML;\n "
4.251 + + "return t ? t : null;"
4.252 + )
4.253 + private static native String childText(String id, int pos);
4.254 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java Wed Apr 24 18:34:31 2013 +0200
5.3 @@ -0,0 +1,65 @@
5.4 +/**
5.5 + * HTML via Java(tm) Language Bindings
5.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.7 + *
5.8 + * This program is free software: you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License as published by
5.10 + * the Free Software Foundation, version 2 of the License.
5.11 + *
5.12 + * This program is distributed in the hope that it will be useful,
5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 + * GNU General Public License for more details. apidesign.org
5.16 + * designates this particular file as subject to the
5.17 + * "Classpath" exception as provided by apidesign.org
5.18 + * in the License file that accompanied this code.
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License
5.21 + * along with this program. Look for COPYING file in the top folder.
5.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
5.23 + */
5.24 +package net.java.html.json.tests;
5.25 +
5.26 +import net.java.html.json.ComputedProperty;
5.27 +import net.java.html.json.Function;
5.28 +import net.java.html.json.Model;
5.29 +import net.java.html.json.Property;
5.30 +
5.31 +/**
5.32 + *
5.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
5.34 + */
5.35 +@Model(className = "Person", properties = {
5.36 + @Property(name = "firstName", type = String.class),
5.37 + @Property(name = "lastName", type = String.class),
5.38 + @Property(name = "sex", type = Sex.class)
5.39 +})
5.40 +final class PersonImpl {
5.41 + @ComputedProperty
5.42 + public static String fullName(String firstName, String lastName) {
5.43 + return firstName + " " + lastName;
5.44 + }
5.45 +
5.46 + @ComputedProperty
5.47 + public static String sexType(Sex sex) {
5.48 + return sex == null ? "unknown" : sex.toString();
5.49 + }
5.50 +
5.51 + @Function
5.52 + static void changeSex(Person p) {
5.53 + if (p.getSex() == Sex.MALE) {
5.54 + p.setSex(Sex.FEMALE);
5.55 + } else {
5.56 + p.setSex(Sex.MALE);
5.57 + }
5.58 + }
5.59 +
5.60 + @Model(className = "People", properties = {
5.61 + @Property(array = true, name = "info", type = Person.class),
5.62 + @Property(array = true, name = "nicknames", type = String.class),
5.63 + @Property(array = true, name = "age", type = int.class),
5.64 + @Property(array = true, name = "sex", type = Sex.class)
5.65 + })
5.66 + public class PeopleImpl {
5.67 + }
5.68 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Sex.java Wed Apr 24 18:34:31 2013 +0200
6.3 @@ -0,0 +1,29 @@
6.4 +/**
6.5 + * HTML via Java(tm) Language Bindings
6.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6.7 + *
6.8 + * This program is free software: you can redistribute it and/or modify
6.9 + * it under the terms of the GNU General Public License as published by
6.10 + * the Free Software Foundation, version 2 of the License.
6.11 + *
6.12 + * This program is distributed in the hope that it will be useful,
6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 + * GNU General Public License for more details. apidesign.org
6.16 + * designates this particular file as subject to the
6.17 + * "Classpath" exception as provided by apidesign.org
6.18 + * in the License file that accompanied this code.
6.19 + *
6.20 + * You should have received a copy of the GNU General Public License
6.21 + * along with this program. Look for COPYING file in the top folder.
6.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
6.23 + */
6.24 +package net.java.html.json.tests;
6.25 +
6.26 +/**
6.27 + *
6.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
6.29 + */
6.30 +public enum Sex {
6.31 + MALE, FEMALE;
6.32 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java Wed Apr 24 18:34:31 2013 +0200
7.3 @@ -0,0 +1,91 @@
7.4 +/**
7.5 + * HTML via Java(tm) Language Bindings
7.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
7.7 + *
7.8 + * This program is free software: you can redistribute it and/or modify
7.9 + * it under the terms of the GNU General Public License as published by
7.10 + * the Free Software Foundation, version 2 of the License.
7.11 + *
7.12 + * This program is distributed in the hope that it will be useful,
7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.15 + * GNU General Public License for more details. apidesign.org
7.16 + * designates this particular file as subject to the
7.17 + * "Classpath" exception as provided by apidesign.org
7.18 + * in the License file that accompanied this code.
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License
7.21 + * along with this program. Look for COPYING file in the top folder.
7.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
7.23 + */
7.24 +package org.apidesign.html.json.tck;
7.25 +
7.26 +import net.java.html.json.tests.ConvertTypesTest;
7.27 +import net.java.html.json.tests.KnockoutTest;
7.28 +import net.java.html.json.tests.JSONTest;
7.29 +import java.util.ServiceLoader;
7.30 +import net.java.html.json.Context;
7.31 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
7.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
7.33 +import org.apidesign.html.json.spi.ContextBuilder;
7.34 +import org.openide.util.lookup.ServiceProvider;
7.35 +
7.36 +/** Entry point for providers of different HTML binding technologies (like
7.37 + * Knockout.js in bck2brwsr or in JavaFX's WebView). Sample usage:
7.38 + * <pre>
7.39 +{@link ServiceProvider @ServiceProvider}(service = KnockoutTCK.class)
7.40 +public final class Bck2BrwsrKnockoutTest extends KnockoutTCK {
7.41 + {@link Override @Override}
7.42 + protected Context createContext() {
7.43 + // use {@link ContextBuilder}.{@link ContextBuilder#build() build}();
7.44 + }
7.45 +
7.46 + {@code @Factory} public static Object[] create() {
7.47 + return VMTest.create({@link KnockoutTCK#testClasses}());
7.48 + }
7.49 +}
7.50 + * </pre>
7.51 + *
7.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
7.53 + */
7.54 +public abstract class KnockoutTCK {
7.55 + protected KnockoutTCK() {
7.56 + }
7.57 +
7.58 + /** Implement to create new context for the test.
7.59 + * Use {@link ContextBuilder} to implement context for your technology.
7.60 + */
7.61 + protected abstract Context createContext();
7.62 +
7.63 +
7.64 + /** Gives you list of classes included in the TCK. Send them
7.65 + * to {@link VMTest#create(java.lang.Class)} factory method.
7.66 + *
7.67 + * @return classes with methods annotated by {@link BrwsrTest} annotation
7.68 + */
7.69 + protected static Class<?>[] testClasses() {
7.70 + return new Class[] {
7.71 + ConvertTypesTest.class,
7.72 + JSONTest.class,
7.73 + KnockoutTest.class
7.74 + };
7.75 + }
7.76 +
7.77 +
7.78 + /** Finds registered implementation of {@link KnockoutTCK} and obtains
7.79 + * new context.
7.80 + *
7.81 + * @return context to use for currently running test
7.82 + * @throws AssertionError if no context has been found
7.83 + */
7.84 + public static Context newContext() {
7.85 + for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class)) {
7.86 + Context c = tck.createContext();
7.87 + if (c != null) {
7.88 + return c;
7.89 + }
7.90 + }
7.91 + throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
7.92 + }
7.93 +
7.94 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html Wed Apr 24 18:34:31 2013 +0200
8.3 @@ -0,0 +1,34 @@
8.4 +<!--
8.5 +
8.6 + HTML via Java(tm) Language Bindings
8.7 + Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.8 +
8.9 + This program is free software: you can redistribute it and/or modify
8.10 + it under the terms of the GNU General Public License as published by
8.11 + the Free Software Foundation, version 2 of the License.
8.12 +
8.13 + This program is distributed in the hope that it will be useful,
8.14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
8.15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.16 + GNU General Public License for more details. apidesign.org
8.17 + designates this particular file as subject to the
8.18 + "Classpath" exception as provided by apidesign.org
8.19 + in the License file that accompanied this code.
8.20 +
8.21 + You should have received a copy of the GNU General Public License
8.22 + along with this program. Look for COPYING file in the top folder.
8.23 + If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
8.24 +
8.25 +-->
8.26 +<!DOCTYPE html>
8.27 +<html>
8.28 + <head>
8.29 + <title></title>
8.30 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8.31 + </head>
8.32 + <body>
8.33 + <div>Entry point to the
8.34 + <a href="KnockoutTCK.html">test compatibility kit</a>.
8.35 + </div>
8.36 + </body>
8.37 +</html>
9.1 --- a/json/pom.xml Tue Apr 23 20:46:15 2013 +0200
9.2 +++ b/json/pom.xml Wed Apr 24 18:34:31 2013 +0200
9.3 @@ -10,7 +10,7 @@
9.4 <groupId>org.apidesign.html</groupId>
9.5 <artifactId>net.java.html.json</artifactId>
9.6 <version>0.1-SNAPSHOT</version>
9.7 - <description>JSON Model in Java</description>
9.8 + <name>JSON Model in Java</name>
9.9 <url>http://maven.apache.org</url>
9.10 <properties>
9.11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
9.12 @@ -25,6 +25,20 @@
9.13 <skip>false</skip>
9.14 </configuration>
9.15 </plugin>
9.16 + <plugin>
9.17 + <groupId>org.apache.maven.plugins</groupId>
9.18 + <artifactId>maven-source-plugin</artifactId>
9.19 + <version>2.2.1</version>
9.20 + <executions>
9.21 + <execution>
9.22 + <id>prepare-sources</id>
9.23 + <goals>
9.24 + <goal>jar</goal>
9.25 + </goals>
9.26 + <phase>package</phase>
9.27 + </execution>
9.28 + </executions>
9.29 + </plugin>
9.30 </plugins>
9.31 </build>
9.32 <dependencies>
10.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Technology.java Tue Apr 23 20:46:15 2013 +0200
10.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Technology.java Wed Apr 24 18:34:31 2013 +0200
10.3 @@ -34,7 +34,7 @@
10.4 * with {@link Model} annotation.
10.5 *
10.6 * @param model the model generated from {@link Model}
10.7 - * @return
10.8 + * @return internal object representing the model
10.9 */
10.10 public Data wrapModel(Object model);
10.11
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/json/src/main/resources/org/apidesign/html/json/spi/package.html Wed Apr 24 18:34:31 2013 +0200
11.3 @@ -0,0 +1,37 @@
11.4 +<!--
11.5 +
11.6 + HTML via Java(tm) Language Bindings
11.7 + Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
11.8 +
11.9 + This program is free software: you can redistribute it and/or modify
11.10 + it under the terms of the GNU General Public License as published by
11.11 + the Free Software Foundation, version 2 of the License.
11.12 +
11.13 + This program is distributed in the hope that it will be useful,
11.14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
11.15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.16 + GNU General Public License for more details. apidesign.org
11.17 + designates this particular file as subject to the
11.18 + "Classpath" exception as provided by apidesign.org
11.19 + in the License file that accompanied this code.
11.20 +
11.21 + You should have received a copy of the GNU General Public License
11.22 + along with this program. Look for COPYING file in the top folder.
11.23 + If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
11.24 +
11.25 +-->
11.26 +<!DOCTYPE html>
11.27 +<html>
11.28 + <head>
11.29 + <title></title>
11.30 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
11.31 + </head>
11.32 + <body>
11.33 + <div>Implement
11.34 + <a href="Technology.html">Technology</a> and
11.35 + <a href="Transfer.html">Transfer</a> and use
11.36 + <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
11.37 + of <code>Context</code> representing your technology.
11.38 + </div>
11.39 + </body>
11.40 +</html>
12.1 --- a/pom.xml Tue Apr 23 20:46:15 2013 +0200
12.2 +++ b/pom.xml Wed Apr 24 18:34:31 2013 +0200
12.3 @@ -18,6 +18,7 @@
12.4 </properties>
12.5 <modules>
12.6 <module>json</module>
12.7 + <module>json-tck</module>
12.8 </modules>
12.9 <licenses>
12.10 <license>
12.11 @@ -246,4 +247,4 @@
12.12 </dependency>
12.13 </dependencies>
12.14 </dependencyManagement>
12.15 -</project>
12.16 +</project>
12.17 \ No newline at end of file