Moving archetype tests into separate module - at that moment it is possible to use the previously generated archetype
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/ko-archetype-test/pom.xml Mon May 13 14:25:37 2013 +0200
1.3 @@ -0,0 +1,37 @@
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.3-SNAPSHOT</version>
1.12 + </parent>
1.13 + <groupId>org.apidesign.html</groupId>
1.14 + <artifactId>ko-archetype-test</artifactId>
1.15 + <version>0.3-SNAPSHOT</version>
1.16 + <name>Knockout 4 Java Archetype Test</name>
1.17 + <url>http://maven.apache.org</url>
1.18 + <description>Verifies the Knockout & net.java.html.json archetype behaves properly.</description>
1.19 + <properties>
1.20 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1.21 + </properties>
1.22 + <dependencies>
1.23 + <dependency>
1.24 + <groupId>${project.groupId}</groupId>
1.25 + <artifactId>knockout4j-archetype</artifactId>
1.26 + <version>0.3-SNAPSHOT</version>
1.27 + </dependency>
1.28 + <dependency>
1.29 + <groupId>org.testng</groupId>
1.30 + <artifactId>testng</artifactId>
1.31 + <scope>test</scope>
1.32 + </dependency>
1.33 + <dependency>
1.34 + <groupId>org.apache.maven.shared</groupId>
1.35 + <artifactId>maven-verifier</artifactId>
1.36 + <version>1.4</version>
1.37 + <scope>test</scope>
1.38 + </dependency>
1.39 + </dependencies>
1.40 +</project>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java Mon May 13 14:25:37 2013 +0200
2.3 @@ -0,0 +1,106 @@
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 org.apidesign.html.archetype.test;
2.25 +
2.26 +import java.io.IOException;
2.27 +import java.net.URL;
2.28 +import javax.xml.XMLConstants;
2.29 +import javax.xml.parsers.DocumentBuilderFactory;
2.30 +import javax.xml.parsers.ParserConfigurationException;
2.31 +import javax.xml.xpath.XPathConstants;
2.32 +import javax.xml.xpath.XPathExpression;
2.33 +import javax.xml.xpath.XPathExpressionException;
2.34 +import javax.xml.xpath.XPathFactory;
2.35 +import javax.xml.xpath.XPathFactoryConfigurationException;
2.36 +import org.testng.annotations.Test;
2.37 +import static org.testng.Assert.*;
2.38 +import org.testng.annotations.BeforeClass;
2.39 +import org.w3c.dom.Document;
2.40 +import org.w3c.dom.NodeList;
2.41 +import org.xml.sax.SAXException;
2.42 +
2.43 +/**
2.44 + *
2.45 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.46 + */
2.47 +public class ArchetypeVersionTest {
2.48 + private String version;
2.49 +
2.50 + public ArchetypeVersionTest() {
2.51 + }
2.52 +
2.53 + @BeforeClass public void readCurrentVersion() throws Exception {
2.54 + version = findCurrentVersion();
2.55 + assertFalse(version.isEmpty(), "There should be some version string");
2.56 + }
2.57 +
2.58 +
2.59 + @Test public void testComparePomDepsVersions() throws Exception {
2.60 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
2.61 + URL r = l.getResource("archetype-resources/pom.xml");
2.62 + assertNotNull(r, "Archetype pom found");
2.63 +
2.64 + final XPathFactory fact = XPathFactory.newInstance();
2.65 + XPathExpression xp2 = fact.newXPath().compile(
2.66 + "//properties/net.java.html.version/text()"
2.67 + );
2.68 +
2.69 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
2.70 + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
2.71 +
2.72 + assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
2.73 + }
2.74 +
2.75 + @Test public void testNbActions() throws Exception {
2.76 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
2.77 + URL r = l.getResource("archetype-resources/nbactions.xml");
2.78 + assertNotNull(r, "Archetype nb file found");
2.79 +
2.80 + final XPathFactory fact = XPathFactory.newInstance();
2.81 + XPathExpression xp2 = fact.newXPath().compile(
2.82 + "//goal/text()"
2.83 + );
2.84 +
2.85 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
2.86 + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
2.87 +
2.88 + for (int i = 0; i < goals.getLength(); i++) {
2.89 + String s = goals.item(i).getTextContent();
2.90 + if (s.contains("apidesign")) {
2.91 + assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
2.92 + }
2.93 + }
2.94 + }
2.95 +
2.96 + static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
2.97 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
2.98 + URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml");
2.99 + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
2.100 +
2.101 + final XPathFactory fact = XPathFactory.newInstance();
2.102 + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
2.103 +
2.104 + XPathExpression xp = fact.newXPath().compile("project/version/text()");
2.105 +
2.106 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
2.107 + return xp.evaluate(dom);
2.108 + }
2.109 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java Mon May 13 14:25:37 2013 +0200
3.3 @@ -0,0 +1,64 @@
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 org.apidesign.html.archetype.test;
3.25 +
3.26 +import java.io.File;
3.27 +import java.util.Properties;
3.28 +import org.apache.maven.it.Verifier;
3.29 +import org.testng.annotations.Test;
3.30 +import static org.testng.Assert.*;
3.31 +
3.32 +/**
3.33 + *
3.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
3.35 + */
3.36 +public class VerifyArchetypeTest {
3.37 + @Test public void fxBrwsrCompiles() throws Exception {
3.38 + final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
3.39 + generateFromArchetype(dir);
3.40 +
3.41 + File created = new File(dir, "o-a-test");
3.42 + assertTrue(created.isDirectory(), "Project created");
3.43 + assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
3.44 +
3.45 + Verifier v = new Verifier(created.getAbsolutePath());
3.46 + v.executeGoal("verify");
3.47 +
3.48 + v.verifyErrorFreeLog();
3.49 + }
3.50 +
3.51 + private Verifier generateFromArchetype(final File dir) throws Exception {
3.52 + Verifier v = new Verifier(dir.getAbsolutePath());
3.53 + v.setAutoclean(false);
3.54 + v.deleteDirectory("");
3.55 + dir.mkdirs();
3.56 + Properties sysProp = v.getSystemProperties();
3.57 + sysProp.put("groupId", "org.apidesign.test");
3.58 + sysProp.put("artifactId", "o-a-test");
3.59 + sysProp.put("package", "org.apidesign.test.oat");
3.60 + sysProp.put("archetypeGroupId", "org.apidesign.html");
3.61 + sysProp.put("archetypeArtifactId", "knockout4j-archetype");
3.62 + sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
3.63 + v.executeGoal("archetype:generate");
3.64 + v.verifyErrorFreeLog();
3.65 + return v;
3.66 + }
3.67 +}
4.1 --- a/ko-archetype/pom.xml Mon May 13 11:39:33 2013 +0200
4.2 +++ b/ko-archetype/pom.xml Mon May 13 14:25:37 2013 +0200
4.3 @@ -53,36 +53,6 @@
4.4 <target>1.6</target>
4.5 </configuration>
4.6 </plugin>
4.7 - <plugin>
4.8 - <groupId>org.apache.maven.plugins</groupId>
4.9 - <artifactId>maven-surefire-plugin</artifactId>
4.10 - <configuration>
4.11 - <skipTests>true</skipTests>
4.12 - </configuration>
4.13 - <executions>
4.14 - <execution>
4.15 - <id>test</id>
4.16 - <goals>
4.17 - <goal>test</goal>
4.18 - </goals>
4.19 - <phase>integration-test</phase>
4.20 - <configuration>
4.21 - <additionalClasspathElements>
4.22 - <additionalClasspathElement>${project.build.directory}/knockout4j-archetype-${project.version}.jar</additionalClasspathElement>
4.23 - </additionalClasspathElements>
4.24 - <skipTests>false</skipTests>
4.25 - </configuration>
4.26 - </execution>
4.27 -
4.28 - </executions>
4.29 - </plugin>
4.30 </plugins>
4.31 </build>
4.32 - <dependencies>
4.33 - <dependency>
4.34 - <groupId>org.testng</groupId>
4.35 - <artifactId>testng</artifactId>
4.36 - <scope>test</scope>
4.37 - </dependency>
4.38 - </dependencies>
4.39 </project>
5.1 --- a/ko-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon May 13 11:39:33 2013 +0200
5.2 +++ b/ko-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Mon May 13 14:25:37 2013 +0200
5.3 @@ -4,7 +4,7 @@
5.4 <fileSet filtered="true" packaged="true">
5.5 <directory>src/main/java</directory>
5.6 <includes>
5.7 - <include>**/App.java</include>
5.8 + <include>**/*.java</include>
5.9 </includes>
5.10 </fileSet>
5.11 <fileSet filtered="true" packaged="true">
5.12 @@ -12,6 +12,7 @@
5.13 <includes>
5.14 <include>**/*.xhtml</include>
5.15 <include>**/*.html</include>
5.16 + <include>**/*.css</include>
5.17 </includes>
5.18 </fileSet>
5.19 <fileSet filtered="true" packaged="true">
5.20 @@ -20,6 +21,12 @@
5.21 <include>**/*Test.java</include>
5.22 </includes>
5.23 </fileSet>
5.24 + <fileSet filtered="true" packaged="false">
5.25 + <directory>src/main/assembly</directory>
5.26 + <includes>
5.27 + <include>**/*.xml</include>
5.28 + </includes>
5.29 + </fileSet>
5.30 <fileSet filtered="false" packaged="false">
5.31 <directory></directory>
5.32 <includes>
6.1 --- a/ko-archetype/src/main/resources/archetype-resources/src/main/java/App.java Mon May 13 11:39:33 2013 +0200
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,88 +0,0 @@
6.4 -package ${package};
6.5 -
6.6 -import java.util.List;
6.7 -import org.apidesign.bck2brwsr.htmlpage.api.*;
6.8 -import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
6.9 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
6.10 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
6.11 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
6.12 -
6.13 -/** This is the controller class for associated index.html page. The <code>Index</code>
6.14 - * is autogenerated by parsing the index.html page. It fields represent individual
6.15 - * elements annotated by "id" in the page.
6.16 - */
6.17 -@Page(xhtml="index.html", className="Index", properties={
6.18 - @Property(name="name", type=String.class),
6.19 - @Property(name="messages", type=String.class, array=true),
6.20 -})
6.21 -public class App {
6.22 - static {
6.23 - Index model = new Index();
6.24 - model.setName("World");
6.25 - model.applyBindings();
6.26 - }
6.27 -
6.28 - /**
6.29 - * @param m the model of the index page creates in static initializer
6.30 - */
6.31 - @On(event = CLICK, id="hello")
6.32 - static void hello(Index m) {
6.33 - display(m.getHelloMessage(), m);
6.34 - m.getMessages().add(m.getHelloMessage());
6.35 - }
6.36 -
6.37 - /** Reacts when mouse moves over the canvas.
6.38 - *
6.39 - * @param m the model of the page
6.40 - * @param x property "x" extracted from the event generated by the browser
6.41 - * @param y property "y" from the mouse event
6.42 - */
6.43 - @On(event = MOUSE_MOVE, id="canvas")
6.44 - static void clearPoint(Index m, int x, int y) {
6.45 - GraphicsContext g = m.canvas.getContext();
6.46 - boolean even = (x + y) % 2 == 0;
6.47 - if (even) {
6.48 - g.setFillStyle("blue");
6.49 - } else {
6.50 - g.setFillStyle("red");
6.51 - }
6.52 - g.clearRect(0, 0, 1000, 1000);
6.53 - g.setFont("italic 40px Calibri");
6.54 - g.fillText(m.getHelloMessage(), 10, 40);
6.55 - }
6.56 -
6.57 - /** Callback function called by the KnockOut/Java binding on elements
6.58 - * representing href's with individual messages being their data.
6.59 - *
6.60 - * @param data the data associated with the element
6.61 - * @param m the model of the page
6.62 - */
6.63 - @OnFunction
6.64 - static void display(String data, Index m) {
6.65 - GraphicsContext g = m.canvas.getContext();
6.66 - g.clearRect(0, 0, 1000, 1000);
6.67 - g.setFillStyle("black");
6.68 - g.setFont("italic 40px Calibri");
6.69 - g.fillText(data, 10, 40);
6.70 - }
6.71 -
6.72 - /** Callback function.
6.73 - *
6.74 - * @param data data associated with the actual element on the page
6.75 - * @param m the model of the page
6.76 - */
6.77 - @OnFunction
6.78 - static void remove(String data, Index m) {
6.79 - m.getMessages().remove(data);
6.80 - }
6.81 -
6.82 - @ComputedProperty
6.83 - static String helloMessage(String name) {
6.84 - return "Hello " + name + "!";
6.85 - }
6.86 -
6.87 - @ComputedProperty
6.88 - static boolean noMessages(List<String> messages) {
6.89 - return messages.isEmpty();
6.90 - }
6.91 -}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/main/java/TwitterClient.java Mon May 13 14:25:37 2013 +0200
7.3 @@ -0,0 +1,177 @@
7.4 +package ${package};
7.5 +
7.6 +import java.util.Arrays;
7.7 +import java.util.List;
7.8 +import net.java.html.json.ComputedProperty;
7.9 +import net.java.html.json.Context;
7.10 +import net.java.html.json.Function;
7.11 +import net.java.html.json.Model;
7.12 +import net.java.html.json.OnPropertyChange;
7.13 +import net.java.html.json.OnReceive;
7.14 +import net.java.html.json.Property;
7.15 +
7.16 +@Model(className="TwitterModel", properties={
7.17 + @Property(name="savedLists", type=Tweeters.class, array = true),
7.18 + @Property(name="activeTweetersName", type=String.class),
7.19 + @Property(name="activeTweeters", type=String.class, array = true),
7.20 + @Property(name="userNameToAdd", type=String.class),
7.21 + @Property(name="currentTweets", type=Tweet.class, array = true)
7.22 +})
7.23 +public class TwitterClient {
7.24 + @Model(className = "Tweeters", properties = {
7.25 + @Property(name="name", type = String.class),
7.26 + @Property(name="userNames", type = String.class, array = true)
7.27 + })
7.28 + static class Twttrs {
7.29 + }
7.30 + @Model(className = "Tweet", properties = {
7.31 + @Property(name = "from_user", type = String.class),
7.32 + @Property(name = "from_user_id", type = int.class),
7.33 + @Property(name = "profile_image_url", type = String.class),
7.34 + @Property(name = "text", type = String.class),
7.35 + @Property(name = "created_at", type = String.class),
7.36 + })
7.37 + static final class Twt {
7.38 + @ComputedProperty static String html(String text) {
7.39 + StringBuilder sb = new StringBuilder(320);
7.40 + for (int pos = 0;;) {
7.41 + int http = text.indexOf("http", pos);
7.42 + if (http == -1) {
7.43 + sb.append(text.substring(pos));
7.44 + return sb.toString();
7.45 + }
7.46 + int spc = text.indexOf(' ', http);
7.47 + if (spc == -1) {
7.48 + spc = text.length();
7.49 + }
7.50 + sb.append(text.substring(pos, http));
7.51 + String url = text.substring(http, spc);
7.52 + sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
7.53 + pos = spc;
7.54 + }
7.55 + }
7.56 +
7.57 + @ComputedProperty static String userUrl(String from_user) {
7.58 + return "http://twitter.com/" + from_user;
7.59 + }
7.60 + }
7.61 + @Model(className = "TwitterQuery", properties = {
7.62 + @Property(array = true, name = "results", type = Twt.class)
7.63 + })
7.64 + public static final class TwttrQr {
7.65 + }
7.66 +
7.67 + @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
7.68 + static void queryTweets(TwitterModel page, TwitterQuery q) {
7.69 + page.getCurrentTweets().clear();
7.70 + page.getCurrentTweets().addAll(q.getResults());
7.71 + }
7.72 +
7.73 + @OnPropertyChange("activeTweetersName")
7.74 + static void changeTweetersList(TwitterModel model) {
7.75 + Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());
7.76 + model.getActiveTweeters().clear();
7.77 + model.getActiveTweeters().addAll(people.getUserNames());
7.78 + }
7.79 +
7.80 + @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
7.81 + static void refreshTweets(TwitterModel model) {
7.82 + StringBuilder sb = new StringBuilder();
7.83 + sb.append("rpp=25&q=");
7.84 + String sep = "";
7.85 + for (String p : model.getActiveTweeters()) {
7.86 + sb.append(sep);
7.87 + sb.append("from:");
7.88 + sb.append(p);
7.89 + sep = " OR ";
7.90 + }
7.91 + model.queryTweets("http://search.twitter.com", sb.toString());
7.92 + }
7.93 +
7.94 + private static final Context DEFAULT = Context.findDefault(TwitterClient.class);
7.95 + static {
7.96 + final TwitterModel model = new TwitterModel(DEFAULT);
7.97 + final List<Tweeters> svdLst = model.getSavedLists();
7.98 + svdLst.add(newTweeters("API Design", "JaroslavTulach"));
7.99 + svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
7.100 + svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
7.101 + svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
7.102 + svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
7.103 +
7.104 + model.setActiveTweetersName("NetBeans");
7.105 +
7.106 + model.applyBindings();
7.107 + }
7.108 +
7.109 + @ComputedProperty
7.110 + static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
7.111 + Tweeters tw = findByName(savedLists, activeTweetersName);
7.112 + if (activeTweeters == null) {
7.113 + return false;
7.114 + }
7.115 + return !tw.getUserNames().equals(activeTweeters);
7.116 + }
7.117 +
7.118 + @ComputedProperty
7.119 + static int activeTweetersCount(List<String> activeTweeters) {
7.120 + return activeTweeters.size();
7.121 + }
7.122 +
7.123 + @ComputedProperty
7.124 + static boolean userNameToAddIsValid(
7.125 + String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
7.126 + ) {
7.127 + return userNameToAdd != null &&
7.128 + userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
7.129 + !activeTweeters.contains(userNameToAdd);
7.130 + }
7.131 +
7.132 + @Function
7.133 + static void deleteList(TwitterModel model) {
7.134 + final List<Tweeters> sl = model.getSavedLists();
7.135 + sl.remove(findByName(sl, model.getActiveTweetersName()));
7.136 + if (sl.isEmpty()) {
7.137 + final Tweeters t = new Tweeters(DEFAULT);
7.138 + t.setName("New");
7.139 + sl.add(t);
7.140 + }
7.141 + model.setActiveTweetersName(sl.get(0).getName());
7.142 + }
7.143 +
7.144 + @Function
7.145 + static void saveChanges(TwitterModel model) {
7.146 + Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
7.147 + int indx = model.getSavedLists().indexOf(t);
7.148 + if (indx != -1) {
7.149 + t.setName(model.getActiveTweetersName());
7.150 + t.getUserNames().clear();
7.151 + t.getUserNames().addAll(model.getActiveTweeters());
7.152 + }
7.153 + }
7.154 +
7.155 + @Function
7.156 + static void addUser(TwitterModel model) {
7.157 + String n = model.getUserNameToAdd();
7.158 + model.getActiveTweeters().add(n);
7.159 + }
7.160 + @Function
7.161 + static void removeUser(String data, TwitterModel model) {
7.162 + model.getActiveTweeters().remove(data);
7.163 + }
7.164 +
7.165 + private static Tweeters findByName(List<Tweeters> list, String name) {
7.166 + for (Tweeters l : list) {
7.167 + if (l.getName() != null && l.getName().equals(name)) {
7.168 + return l;
7.169 + }
7.170 + }
7.171 + return list.isEmpty() ? new Tweeters(DEFAULT) : list.get(0);
7.172 + }
7.173 +
7.174 + private static Tweeters newTweeters(String listName, String... userNames) {
7.175 + Tweeters t = new Tweeters(DEFAULT);
7.176 + t.setName(listName);
7.177 + t.getUserNames().addAll(Arrays.asList(userNames));
7.178 + return t;
7.179 + }
7.180 +}
8.1 --- a/ko-archetype/src/main/resources/archetype-resources/src/main/resources/index.html Mon May 13 11:39:33 2013 +0200
8.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/main/resources/index.html Mon May 13 14:25:37 2013 +0200
8.3 @@ -1,31 +1,105 @@
8.4 <?xml version="1.0" encoding="UTF-8"?>
8.5 +<!--
8.6 +
8.7 + The MIT License (MIT)
8.8 +
8.9 + Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.10 +
8.11 + Permission is hereby granted, free of charge, to any person obtaining a copy
8.12 + of this software and associated documentation files (the "Software"), to deal
8.13 + in the Software without restriction, including without limitation the rights
8.14 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8.15 + copies of the Software, and to permit persons to whom the Software is
8.16 + furnished to do so, subject to the following conditions:
8.17 +
8.18 + The above copyright notice and this permission notice shall be included in
8.19 + all copies or substantial portions of the Software.
8.20 +
8.21 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8.22 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8.23 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8.24 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8.25 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8.26 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
8.27 + THE SOFTWARE.
8.28 +
8.29 +-->
8.30 +
8.31 +<!--
8.32 + Copied from knockout.js Twitter example:
8.33 + http://knockoutjs.com/examples/twitter.html
8.34 +-->
8.35 +
8.36 <!DOCTYPE html>
8.37 <html xmlns="http://www.w3.org/1999/xhtml">
8.38 <head>
8.39 - <title>Bck2Brwsr's Hello World</title>
8.40 + <title>Bck2Brwsr's Twitter</title>
8.41 </head>
8.42 <body>
8.43 - <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
8.44 - Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
8.45 - <button id="hello">Say Hello!</button>
8.46 + <link href='twitterExample.css' rel='Stylesheet' ></link>
8.47 +
8.48 + <style type='text/css'>
8.49 + .liveExample select { height: 1.7em; }
8.50 + .liveExample button { height: 2em; }
8.51 + </style>
8.52 +
8.53 +
8.54 + <h2>Bck2Brwsr's Twitter</h2>
8.55 +
8.56 <p>
8.57 - <canvas id="canvas" width="300" height="50">
8.58 - </canvas>
8.59 + This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
8.60 + uses almost unmodified HTML code. It just changes the model. It
8.61 + is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
8.62 + virtual machine. The Java source code has about 190 lines and is available
8.63 + <a href="http://source.apidesign.org/hg/bck2brwsr/file/7fc6b7e9c982/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java">here</a>
8.64 + - in fact it may even be more dense than the original JavaScript model.
8.65 </p>
8.66
8.67 + <div class='liveExample'>
8.68 + <div class='configuration'>
8.69 + <div class='listChooser'>
8.70 + <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
8.71 + <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button>
8.72 + <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
8.73 + </div>
8.74 +
8.75 + <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
8.76 + <div class='currentUsers' >
8.77 + <ul data-bind='foreach: activeTweeters'>
8.78 + <li>
8.79 + <button data-bind='click: $root.removeUser'>Remove</button>
8.80 + <div data-bind='text: $data'> </div>
8.81 + </li>
8.82 + </ul>
8.83 + </div>
8.84 +
8.85 + <form data-bind='submit: addUser'>
8.86 + <label>Add user:</label>
8.87 + <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
8.88 + <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
8.89 + </form>
8.90 + </div>
8.91 + <div class='tweets'>
8.92 + <div class='loadingIndicator'>Loading...</div>
8.93 + <table data-bind='foreach: currentTweets' width='100%'>
8.94 + <tr>
8.95 + <td><img data-bind='attr: { src: profile_image_url }' /></td>
8.96 + <td>
8.97 + <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
8.98 + <span data-bind='html: html'> </span>
8.99 + <div class='tweetInfo' data-bind='text: created_at'> </div>
8.100 + </td>
8.101 + </tr>
8.102 + </table>
8.103 + </div>
8.104 + </div>
8.105
8.106 - <div data-bind="if: noMessages">No message displayed yet.</div>
8.107 - <ul data-bind="foreach: messages">
8.108 - <li>
8.109 - <a href="#" data-bind="text: $data, click: $root.display"></a>
8.110 - (<a href="#" data-bind="click: $root.remove">delete</a>)
8.111 - </li>
8.112 - </ul>
8.113 -
8.114 <script src="bck2brwsr.js"></script>
8.115 <script type="text/javascript">
8.116 - var vm = bck2brwsr('${artifactId}-${version}.jar');
8.117 - vm.loadClass('${package}.App');
8.118 + var vm = bck2brwsr('demo-twitter-1.0-SNAPSHOT.jar');
8.119 + vm.loadClass('org.apidesign.html.demo.twitter.TwitterClient');
8.120 </script>
8.121 +
8.122 +
8.123 </body>
8.124 </html>
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/main/resources/twitterExample.css Mon May 13 14:25:37 2013 +0200
9.3 @@ -0,0 +1,58 @@
9.4 +/**
9.5 + * The MIT License (MIT)
9.6 + *
9.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.8 + *
9.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
9.10 + * of this software and associated documentation files (the "Software"), to deal
9.11 + * in the Software without restriction, including without limitation the rights
9.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9.13 + * copies of the Software, and to permit persons to whom the Software is
9.14 + * furnished to do so, subject to the following conditions:
9.15 + *
9.16 + * The above copyright notice and this permission notice shall be included in
9.17 + * all copies or substantial portions of the Software.
9.18 + *
9.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
9.25 + * THE SOFTWARE.
9.26 + */
9.27 +
9.28 +
9.29 +
9.30 +/*
9.31 + Copied from knockout.js Twitter example:
9.32 + http://knockoutjs.com/examples/twitter.html
9.33 +*/
9.34 +
9.35 +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
9.36 +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
9.37 +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
9.38 +.tweets table { border-width: 0;}
9.39 +.tweets tr { vertical-align: top; }
9.40 +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
9.41 +.tweets img { width: 4em; }
9.42 +.tweetInfo { color: Gray; font-size: 0.9em; }
9.43 +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
9.44 +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
9.45 +
9.46 +.listChooser select, .listChooser button { vertical-align:top; }
9.47 +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
9.48 +.listChooser button { width: 19%; height:1.68em; float:right; }
9.49 +
9.50 +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
9.51 +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
9.52 +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
9.53 +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
9.54 +.currentUsers li div { padding: 0.6em; }
9.55 +.currentUsers li:hover { background-color: #EEC; }
9.56 +
9.57 +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
9.58 +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
9.59 +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
9.60 +
9.61 +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; display: none; }
10.1 --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/AppTest.java Mon May 13 11:39:33 2013 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,26 +0,0 @@
10.4 -package ${package};
10.5 -
10.6 -import static org.testng.Assert.*;
10.7 -import org.testng.annotations.BeforeMethod;
10.8 -import org.testng.annotations.Test;
10.9 -
10.10 -/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
10.11 - * as it does not reference any HTML elements or browser functionality. Just
10.12 - * operates on the page model.
10.13 - *
10.14 - * @author Jaroslav Tulach <jtulach@netbeans.org>
10.15 - */
10.16 -public class AppTest {
10.17 - private Index model;
10.18 -
10.19 -
10.20 - @BeforeMethod
10.21 - public void initModel() {
10.22 - model = new Index().applyBindings();
10.23 - }
10.24 -
10.25 - @Test public void testHelloMessage() {
10.26 - model.setName("Joe");
10.27 - assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
10.28 - }
10.29 -}
11.1 --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Mon May 13 11:39:33 2013 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,40 +0,0 @@
11.4 -package ${package};
11.5 -
11.6 -import org.apidesign.bck2brwsr.vmtest.Compare;
11.7 -import org.apidesign.bck2brwsr.vmtest.VMTest;
11.8 -import org.testng.annotations.Factory;
11.9 -
11.10 -/** Bck2brwsr cares about compatibility with real Java. Whatever API is
11.11 - * supported by bck2brwsr, it needs to behave the same way as when running
11.12 - * in HotSpot VM.
11.13 - * <p>
11.14 - * There can be bugs, however. To help us fix them, we kindly ask you to
11.15 - * write an "inconsistency" test. A test that compares behavior of the API
11.16 - * between real VM and bck2brwsr VM. This class is skeleton of such test.
11.17 - *
11.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
11.19 - */
11.20 -public class InconsistencyTest {
11.21 - /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
11.22 - * Make calls to an API that behaves strangely, return some result at
11.23 - * the end. No need to use any <code>assert</code>.
11.24 - *
11.25 - * @return value to compare between HotSpot and bck2brwsr
11.26 - */
11.27 - @Compare
11.28 - public int checkStringHashCode() throws Exception {
11.29 - return "Is string hashCode the same?".hashCode();
11.30 - }
11.31 -
11.32 - /** Factory method that creates a three tests for each method annotated with
11.33 - * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
11.34 - * HotSpot, one in Rhino and the last one compares the results.
11.35 - *
11.36 - * @see org.apidesign.bck2brwsr.vmtest.VMTest
11.37 - */
11.38 - @Factory
11.39 - public static Object[] create() {
11.40 - return VMTest.create(InconsistencyTest.class);
11.41 - }
11.42 -
11.43 -}
12.1 --- a/ko-archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Mon May 13 11:39:33 2013 +0200
12.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Mon May 13 14:25:37 2013 +0200
12.3 @@ -1,6 +1,5 @@
12.4 package ${package};
12.5
12.6 -import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
12.7 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
12.8 import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
12.9 import org.apidesign.bck2brwsr.vmtest.VMTest;
12.10 @@ -11,8 +10,6 @@
12.11 * and that is it. If your code references elements on the HTML page,
12.12 * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
12.13 * will be made available on the page before your test starts.
12.14 - *
12.15 - * @author Jaroslav Tulach <jtulach@netbeans.org>
12.16 */
12.17 public class IntegrationTest {
12.18
12.19 @@ -20,22 +17,10 @@
12.20 * Assert, as TestNG is not compiled with target 1.6 yet).
12.21 */
12.22 @HtmlFragment(
12.23 - "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
12.24 - "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
12.25 - "<button id=\"hello\">Say Hello!</button>\n" +
12.26 - "<p>\n" +
12.27 - " <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
12.28 - "</p>\n"
12.29 + "<h1>Put this snippet on the HTML page</h1>\n"
12.30 )
12.31 @BrwsrTest
12.32 - public void modifyValueAssertChangeInModel() {
12.33 - Index m = new Index();
12.34 - m.setName("Joe Hacker");
12.35 - m.applyBindings();
12.36 - assert "Joe Hacker".equals(m.input.getValue()) : "Value is really Joe Hacker: " + m.input.getValue();
12.37 - m.input.setValue("Happy Joe");
12.38 - m.triggerEvent(m.input, OnEvent.CHANGE);
12.39 - assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
12.40 + public void runThisTestInABrowser() {
12.41 }
12.42
12.43 @Factory
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterClientTest.java Mon May 13 14:25:37 2013 +0200
13.3 @@ -0,0 +1,49 @@
13.4 +package ${package};
13.5 +
13.6 +import java.util.List;
13.7 +import net.java.html.json.Context;
13.8 +import static org.testng.Assert.*;
13.9 +import org.testng.annotations.BeforeMethod;
13.10 +import org.testng.annotations.Test;
13.11 +
13.12 +/** We can unit test the TwitterModel smoothly.
13.13 + */
13.14 +public class TwitterClientTest {
13.15 + private TwitterModel model;
13.16 +
13.17 +
13.18 + @BeforeMethod
13.19 + public void initModel() {
13.20 + model = new TwitterModel(Context.EMPTY);
13.21 + }
13.22 +
13.23 + @Test public void testIsValidToAdd() {
13.24 + model.setUserNameToAdd("Joe");
13.25 + Tweeters t = new Tweeters(Context.EMPTY);
13.26 + t.setName("test");
13.27 + model.getSavedLists().add(t);
13.28 + model.setActiveTweetersName("test");
13.29 +
13.30 + assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
13.31 + TwitterClient.addUser(model);
13.32 + assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
13.33 + assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
13.34 +
13.35 + List<String> mod = model.getActiveTweeters();
13.36 + assertTrue(model.isHasUnsavedChanges(), "We have modifications");
13.37 + assertEquals(mod.size(), 1, "One element in the list");
13.38 + assertEquals(mod.get(0), "Joe", "Its name is Joe");
13.39 +
13.40 + assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
13.41 +
13.42 + TwitterClient.saveChanges(model);
13.43 + assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
13.44 +
13.45 + assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
13.46 + }
13.47 +
13.48 + @Test public void httpAtTheEnd() {
13.49 + String res = TwitterClient.Twt.html("Ahoj http://kuk");
13.50 + assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
13.51 + }
13.52 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/ko-archetype/src/main/resources/archetype-resources/src/test/java/TwitterProtocolTest.java Mon May 13 14:25:37 2013 +0200
14.3 @@ -0,0 +1,74 @@
14.4 +package ${package};
14.5 +
14.6 +import net.java.html.json.Context;
14.7 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
14.8 +import org.apidesign.bck2brwsr.vmtest.Http;
14.9 +import org.apidesign.bck2brwsr.vmtest.VMTest;
14.10 +import org.testng.annotations.Factory;
14.11 +
14.12 +public class TwitterProtocolTest {
14.13 + private TwitterModel page;
14.14 + @Http(@Http.Resource(
14.15 + path = "/search.json",
14.16 + mimeType = "application/json",
14.17 + parameters = {"callback"},
14.18 + content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\""
14.19 + + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":"
14.20 + + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\","
14.21 + + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\","
14.22 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
14.23 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344,"
14.24 + + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
14.25 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.26 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.27 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.28 + + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + "
14.29 + + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747,"
14.30 + + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872,"
14.31 + + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\","
14.32 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
14.33 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913,"
14.34 + + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
14.35 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.36 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.37 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.38 + + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"},"
14.39 + + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\","
14.40 + + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\","
14.41 + + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\","
14.42 + + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":"
14.43 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.44 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.45 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.46 + + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"},"
14.47 + + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,"
14.48 + + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,"
14.49 + + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":"
14.50 + + "{\"result_type\":\"recent\"},\"profile_image_url\":"
14.51 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.52 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
14.53 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
14.54 + + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100,"
14.55 + + "\"since_id\":0,\"since_id_str\":\"0\"})"
14.56 + ))
14.57 + @BrwsrTest public void readFromTwttr() throws InterruptedException {
14.58 + if (page == null) {
14.59 + page = new TwitterModel(Context.findDefault(TwitterProtocolTest.class));
14.60 + page.applyBindings();
14.61 + page.queryTweets("", "q=xyz");
14.62 + }
14.63 +
14.64 + if (page.getCurrentTweets().isEmpty()) {
14.65 + throw new InterruptedException();
14.66 + }
14.67 +
14.68 + assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets();
14.69 +
14.70 + String firstDate = page.getCurrentTweets().get(0).getCreated_at();
14.71 + assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate;
14.72 + }
14.73 +
14.74 + @Factory public static Object[] create() {
14.75 + return VMTest.create(TwitterProtocolTest.class);
14.76 + }
14.77 +}
15.1 --- a/ko-archetype/src/test/java/org/apidesign/html/archetype/ArchetypeVersionTest.java Mon May 13 11:39:33 2013 +0200
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,98 +0,0 @@
15.4 -/**
15.5 - * HTML via Java(tm) Language Bindings
15.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
15.7 - *
15.8 - * This program is free software: you can redistribute it and/or modify
15.9 - * it under the terms of the GNU General Public License as published by
15.10 - * the Free Software Foundation, version 2 of the License.
15.11 - *
15.12 - * This program is distributed in the hope that it will be useful,
15.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.15 - * GNU General Public License for more details. apidesign.org
15.16 - * designates this particular file as subject to the
15.17 - * "Classpath" exception as provided by apidesign.org
15.18 - * in the License file that accompanied this code.
15.19 - *
15.20 - * You should have received a copy of the GNU General Public License
15.21 - * along with this program. Look for COPYING file in the top folder.
15.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
15.23 - */
15.24 -package org.apidesign.html.archetype;
15.25 -
15.26 -import java.net.URL;
15.27 -import javax.xml.XMLConstants;
15.28 -import javax.xml.parsers.DocumentBuilderFactory;
15.29 -import javax.xml.xpath.XPathConstants;
15.30 -import javax.xml.xpath.XPathExpression;
15.31 -import javax.xml.xpath.XPathFactory;
15.32 -import org.testng.annotations.Test;
15.33 -import static org.testng.Assert.*;
15.34 -import org.testng.annotations.BeforeClass;
15.35 -import org.w3c.dom.Document;
15.36 -import org.w3c.dom.NodeList;
15.37 -
15.38 -/**
15.39 - *
15.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
15.41 - */
15.42 -public class ArchetypeVersionTest {
15.43 - private String version;
15.44 -
15.45 - public ArchetypeVersionTest() {
15.46 - }
15.47 -
15.48 - @BeforeClass public void readCurrentVersion() throws Exception {
15.49 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
15.50 - URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml");
15.51 - assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
15.52 -
15.53 - final XPathFactory fact = XPathFactory.newInstance();
15.54 - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
15.55 -
15.56 - XPathExpression xp = fact.newXPath().compile("project/version/text()");
15.57 -
15.58 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
15.59 - version = xp.evaluate(dom);
15.60 -
15.61 - assertFalse(version.isEmpty(), "There should be some version string");
15.62 - }
15.63 -
15.64 -
15.65 - @Test public void testComparePomDepsVersions() throws Exception {
15.66 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
15.67 - URL r = l.getResource("archetype-resources/pom.xml");
15.68 - assertNotNull(r, "Archetype pom found");
15.69 -
15.70 - final XPathFactory fact = XPathFactory.newInstance();
15.71 - XPathExpression xp2 = fact.newXPath().compile(
15.72 - "//properties/net.java.html.version/text()"
15.73 - );
15.74 -
15.75 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
15.76 - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
15.77 -
15.78 - assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
15.79 - }
15.80 -
15.81 - @Test public void testNbActions() throws Exception {
15.82 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
15.83 - URL r = l.getResource("archetype-resources/nbactions.xml");
15.84 - assertNotNull(r, "Archetype nb file found");
15.85 -
15.86 - final XPathFactory fact = XPathFactory.newInstance();
15.87 - XPathExpression xp2 = fact.newXPath().compile(
15.88 - "//goal/text()"
15.89 - );
15.90 -
15.91 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
15.92 - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
15.93 -
15.94 - for (int i = 0; i < goals.getLength(); i++) {
15.95 - String s = goals.item(i).getTextContent();
15.96 - if (s.contains("apidesign")) {
15.97 - assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
15.98 - }
15.99 - }
15.100 - }
15.101 -}