Author: hlship
Date: Mon Jun 30 14:08:39 2008
New Revision: 672923

URL: http://svn.apache.org/viewvc?rev=672923&view=rev
Log:
TAPESTRY-2390: Components or mixins requiring external javascript files and 
rendered via AJAX do not work

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/nested/ZoneDemo.tml
      - copied, changed from r669747, 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/ZoneDemo.java
      - copied, changed from r669747, 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneDemo.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinkerTest.java
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialMarkupRendererFilter.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java?rev=672923&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
 Mon Jun 30 14:08:39 2008
@@ -0,0 +1,66 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.json.JSONArray;
+import org.apache.tapestry5.json.JSONObject;
+
+public class PartialMarkupDocumentLinker implements DocumentLinker
+{
+    private final StringBuilder buffer = new StringBuilder(1000);
+
+    private final JSONArray scripts = new JSONArray();
+
+    private final JSONArray stylesheets = new JSONArray();
+
+    public void addScriptLink(String scriptURL)
+    {
+        scripts.put(scriptURL);
+    }
+
+    public void addStylesheetLink(String styleURL, String media)
+    {
+        JSONObject object = new JSONObject();
+        object.put("href", styleURL);
+
+        if (media != null) object.put("media", media);
+
+        stylesheets.put(object);
+    }
+
+    public void addScript(String script)
+    {
+        buffer.append(script);
+        buffer.append("\n");
+    }
+
+    /**
+     * Commits changes, adding one or more keys to the reply.
+     *
+     * @param reply JSON Object to be sent to client
+     */
+    public void commit(JSONObject reply)
+    {
+        if (buffer.length() > 0)
+            reply.put("script", buffer.toString());
+
+        if (scripts.length() > 0)
+            reply.put("scripts", scripts);
+
+        if (stylesheets.length() > 0)
+            reply.put("stylesheets", stylesheets);
+
+    }
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialMarkupRendererFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialMarkupRendererFilter.java?rev=672923&r1=672922&r2=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialMarkupRendererFilter.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialMarkupRendererFilter.java
 Mon Jun 30 14:08:39 2008
@@ -24,8 +24,8 @@
  * pages and components that render.
  *
  * @see 
org.apache.tapestry5.services.TapestryModule#contributePartialMarkupRenderer(org.apache.tapestry5.ioc.OrderedConfiguration,
- *      org.apache.tapestry5.Asset, ValidationMessagesSource, 
org.apache.tapestry5.ioc.services.SymbolSource,
- *      AssetSource)
+ *      org.apache.tapestry5.Asset, 
org.apache.tapestry5.ioc.services.SymbolSource, AssetSource,
+ *      ValidationMessagesSource)
  */
 public interface PartialMarkupRendererFilter
 {

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=672923&r1=672922&r2=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 Mon Jun 30 14:08:39 2008
@@ -380,7 +380,7 @@
         // be converted to clear out at the end of the request.
 
         configuration.add("UnclaimedField", new UnclaimedFieldWorker(), 
"after:*");
-        
+
         configuration.add("PageActivationContext", new 
PageActivationContextWorker(), "before:OnEvent");
     }
 
@@ -1515,29 +1515,11 @@
 
                 String namespace = ":" + uid;
 
-                final StringBuilder buffer = new StringBuilder(1000);
-
                 IdAllocator idAllocator = new IdAllocator(namespace);
 
-                DocumentLinker builder = new DocumentLinker()
-                {
-                    public void addScriptLink(String scriptURL)
-                    {
-                    }
-
-                    public void addStylesheetLink(String styleURL, String 
media)
-                    {
-                    }
-
-                    public void addScript(String script)
-                    {
-                        buffer.append(script);
-                        buffer.append("\n");
-                    }
-                };
+                PartialMarkupDocumentLinker linker = new 
PartialMarkupDocumentLinker();
 
-
-                RenderSupportImpl support = new RenderSupportImpl(builder, 
symbolSource, assetSource,
+                RenderSupportImpl support = new RenderSupportImpl(linker, 
symbolSource, assetSource,
                                                                   idAllocator);
 
                 environment.push(RenderSupport.class, support);
@@ -1548,8 +1530,7 @@
 
                 environment.pop(RenderSupport.class);
 
-                if (buffer.length() > 0)
-                    reply.put("script", buffer.toString());
+                linker.commit(reply);
             }
         };
 

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=672923&r1=672922&r2=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
 Mon Jun 30 14:08:39 2008
@@ -30,11 +30,11 @@
     /** Event, triggered on the document object, which identifies the current 
focus element. */
     FOCUS_CHANGE_EVENT : "tapestry:focuschange",
 
-
+    /** When false, the default, the Tapestry.debug() function will be a 
no-op. */
     DEBUG_ENABLED : false,
 
     /** Time, in seconds, that console messages are visible. */
-    CONSOLE_DURATION : 10,
+    CONSOLE_DURATION : 60,
 
     FormEvent : Class.create(),
 
@@ -50,6 +50,8 @@
 
     ErrorPopup : Class.create(),
 
+    DependentExecutor : Class.create(),
+
     // Adds a callback function that will be invoked when the DOM is loaded 
(which
     // occurs *before* window.onload, which has to wait for images and such to 
load
     // first.  This simply observes the dom:loaded event on the document 
object (support for
@@ -66,6 +68,8 @@
      */
     onDomLoadedCallback : function()
     {
+        Tapestry.ScriptManager.initialize();
+
         $$(".t-invisible").each(function(element)
         {
             element.hide();
@@ -191,13 +195,18 @@
 
     /**
      * Passed the JSON content of a Tapestry partial markup response, extracts
-     * the script key (if present) and evals it, then uses the DOM loaded 
callback
-     * to hide invisible fields and add notifications for any form elements.
+     * the script and stylesheet information.  JavaScript libraries and 
stylesheets are loaded,
+     * then any script code is evaluated.  All three keys are optional:
+     * <dl>
+     * <dt>scripts</dt><dd>Array of strings (URIs of scripts)</dd>
+     * <dt>stylesheets</dt><dd>Array of hashes, each hash has key href and 
optional key media</dd>
+     * <dt>script</dt> <dd>JavaScript to be executed once all scripts are 
loaded</dd></dl>
      */
     processScriptInReply : function(reply)
     {
-        if (reply.script != undefined)
-            eval(reply.script);
+        Tapestry.ScriptManager.addScripts(reply.scripts, reply.script);
+
+        Tapestry.ScriptManager.addStylesheets(reply.stylesheets);
 
         Tapestry.onDomLoadedCallback();
     },
@@ -267,7 +276,60 @@
     ajaxRequest : function(url, successHandler)
     {
         return new Ajax.Request(url, { onSuccess: successHandler, onFailure: 
Tapestry.ajaxFailureHandler })
+    },
+
+
+    /**
+     * Used to reconstruct a complete URL from a path that is (or may be) 
relative to window.location.
+     * This is used when determining if a JavaScript library or CSS stylesheet 
has already been loaded.
+     * Recognizes complete URLs (which are returned unchanged) and absolute 
paths (which are prefixed
+     * with the window.location protocol and host).  Otherwise the correct 
path is built.  The
+     * path may be prefixed with "./" and "../", which will be resolved 
correctly.
+     *
+     * @param path
+     * @return complete URL as string
+     */
+    rebuildURL : function(path)
+    {
+        if (path.match(/^https?:/))
+        {
+            return path;
+        }
+
+        if (path.startsWith("/"))
+        {
+            var l = window.location;
+            return l.protocol + "//" + l.host + path;
+        }
+
+        var rootPath = this.stripToLastSlash(window.location.href);
+
+        while (true)
+        {
+            if (path.startsWith("../"))
+            {
+                rootPath = this.stripToLastSlash(rootPath.substr(0, 
rootPath.length - 1));
+                path = path.substring(3);
+                continue;
+            }
+
+            if (path.startsWith("./"))
+            {
+                path = path.substr(2);
+                continue;
+            }
+
+            return rootPath + path;
+        }
+    },
+
+    stripToLastSlash : function(URL)
+    {
+        var slashx = URL.lastIndexOf("/");
+
+        return URL.substring(0, slashx + 1);
     }
+
 };
 
 /** Container of functions that may be invoked by the Tapestry.init() 
function. */
@@ -460,8 +522,9 @@
 Element.addMethods(Tapestry.ElementAdditions);
 
 // Look for the Firebug console API and rewrite the Tapestry.error|warn|debug 
methods around it.
+// This seems to be broken under FireFox 3. It has been disabled until we 
deterimine what is broken.
 
-if (window.console)
+if (false && window.console)
 {
     var createlog = function (log)
     {
@@ -1079,4 +1142,174 @@
     }
 };
 
+/**
+ * Coordinates the execution of JavaScript code blocks (via eval) with the 
loading
+ * of an array of <script> elements.
+ */
+Tapestry.DependentExecutor.prototype = {
+
+    initialize : function(prereqs, dependent)
+    {
+        this.dependent = dependent;
+        this.loaded = 0;
+        this.toload = prereqs.length;
+
+        var executor = this;
+
+        prereqs.each(function (scriptElement)
+        {
+            if (Prototype.Browser.IE)
+            {
+                var loaded = false;
+
+                scriptElement.onreadystatechange = function ()
+                {
+                    Tapestry.debug("State #{state} for #{script} (loaded is 
#{loaded})", { state:this.readyState, script:scriptElement.src, loaded:loaded 
});
+
+                    // IE may fire either loaded or complete, or perhaps even 
both.
+                    if (! loaded && (this.readyState == 'loaded' || 
this.readyState == 'complete'))
+                    {
+                        loaded = true;
+                        executor.loadComplete(scriptElement);
+                    }
+                };
+            }
+            else
+            {
+                // Much simpler in FF, Safari, etc.
+                scriptElement.onload = 
executor.loadComplete.bindAsEventListener(executor, scriptElement);
+            }
+        });
+    },
+
+    loadComplete : function(element)
+    {
+        this.loaded++;
+
+        Tapestry.debug("Script #{loaded} of #{toload} loaded", this);
+
+        // Evaluated the dependent script only once all the elements have 
loaded.
+
+        if (this.loaded == this.toload)
+            eval(this.dependent);
+    }
+};
+
+Tapestry.ScriptManager = {
+
+    initialize : function()
+    {
+
+        // Check to see if document.script is supported; if not (for example, 
FireFox),
+        // we can fake it.
+
+        this.emulated = false;
+
+        if (! document.scripts)
+        {
+            this.emulated = true;
+
+            document.scripts = new Array();
+
+            $$('script').each(function (s)
+            {
+                document.scripts.push(s);
+            });
+        }
+    },
+
+    /**
+     * Checks to see if the given collection (of <script> or <style> elements) 
contains the given asset URL.
+     * @param collection
+     * @param prop      property to check ('src' for script, 'href' to style).
+     * @param assetURL        complete URL (i.e., with protocol, host and 
port) to the asset
+     */
+    contains : function (collection, prop, assetURL)
+    {
+        Tapestry.debug("Checking previously loaded for: " + assetURL);
+
+        return $A(collection).any(function (element)
+        {
+            var existing = element[prop];
+
+            if (existing.blank()) return false;
+
+            var complete =
+                    Prototype.Browser.IE ? Tapestry.rebuildURL(existing) : 
existing;
+
+            Tapestry.debug("Previously loaded: " + complete);
+
+            return complete == assetURL;
+        });
+
+        return false;
+    },
+
+    addScripts: function(scripts, dependent)
+    {
+        var added = new Array();
+
+        if (scripts)
+        {
+            var emulated = this.emulated;
+            // Looks like IE really needs the new <script> tag to be
+            // in the <head>. FF doesn't seem to care.
+            // See http://unixpapa.com/js/dyna.html
+            var head = $$("head").first();
+
+            scripts.each(function(s)
+            {
+                var assetURL = Tapestry.rebuildURL(s);
+
+                if (Tapestry.ScriptManager.contains(document.scripts, "src", 
assetURL)) return; // continue to next script
+
+                Tapestry.debug("Loading script: " + assetURL);
+
+                var element = new Element('script', { src: assetURL, type: 
'text/javascript' });
+
+                head.insert({bottom:element});
+
+                added.push(element);
+
+                if (emulated) document.scripts.push(element);
+            });
+
+        }
+
+        if (!dependent) return;
+
+        if (added.length)
+        {
+            new Tapestry.DependentExecutor(added, dependent);
+            return;
+        }
+
+        eval(dependent);
+    },
+
+    addStylesheets : function(stylesheets)
+    {
+        if (!stylesheets) return;
+
+        var head = $$('head').first();
+
+        $(stylesheets).each(function(s)
+        {
+            var assetURL = Tapestry.rebuildURL(s);
+
+            if (Tapestry.ScriptManager.contains(document.styleSheets, 'href', 
assetURL)) return; // continue
+
+            var element = new Element('link', { type: 'text/css', rel: 
'stylesheet', href: assetURL });
+
+            // Careful about media types, some browser will break if it ends 
up as 'null'.
+
+            if (s.media != undefined)
+                element.writeAttribute('media', s.media);
+
+            head.insert({bottom: element});
+
+        });
+    }
+};
+
 Tapestry.onDOMLoaded(Tapestry.onDomLoadedCallback);

Copied: 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/nested/ZoneDemo.tml (from 
r669747, tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml)
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/nested/ZoneDemo.tml?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/app1/nested/ZoneDemo.tml&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml&r1=669747&r2=672923&rev=672923&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/nested/ZoneDemo.tml 
Mon Jun 30 14:08:39 2008
@@ -17,14 +17,24 @@
     <t:block id="registrationForm">
 
 
-        <t:beaneditform t:id="form" object="registration" zone="output"/>
+        <t:beaneditform t:id="form" object="registration" zone="output" 
add="roles">
+
+            <t:parameter name="roles">
+                <t:palette selected="registration.roles" encoder="encoder" 
model="literal:guest,user,admin"/>
+            </t:parameter>
+
+        </t:beaneditform>
 
         <t:actionlink t:id="clear" zone="output">clear</t:actionlink>
 
     </t:block>
 
     <t:block id="registrationOutput">
-        <t:beandisplay object="registration"/>
+        <t:beandisplay object="registration" add="roles">
+            <t:parameter name="roles">
+                ${registration.roles}
+            </t:parameter>
+        </t:beandisplay>
     </t:block>
 
 

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java?rev=672923&r1=672922&r2=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/data/RegistrationData.java
 Mon Jun 30 14:08:39 2008
@@ -18,6 +18,9 @@
 import org.apache.tapestry5.beaneditor.ReorderProperties;
 import org.apache.tapestry5.beaneditor.Validate;
 import org.apache.tapestry5.beaneditor.Width;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+import java.util.List;
 
 @ReorderProperties("firstname,lastname,birthyear,sex")
 public class RegistrationData
@@ -36,6 +39,8 @@
 
     private String notes;
 
+    private List<String> roles = CollectionFactory.newList();
+
     @Validate("min=1900,max=2007")
     @Width(4)
     public int getBirthYear()
@@ -113,4 +118,14 @@
     {
         this.notes = notes;
     }
+
+    public List<String> getRoles()
+    {
+        return roles;
+    }
+
+    public void setRoles(List<String> roles)
+    {
+        this.roles = roles;
+    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java?rev=672923&r1=672922&r2=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
 Mon Jun 30 14:08:39 2008
@@ -138,7 +138,7 @@
             new Item("MissingTemplate", "Missing Template Demo",
                      "Demo for what happens when a template is not found for a 
page"),
 
-            new Item("zonedemo", "Zone Demo", "dynamic updates within a page"),
+            new Item("nested/zonedemo", "Zone Demo", "dynamic updates within a 
page"),
 
             new Item("todolist", "ToDo List", "Loops and Submit inside Form 
using primary key encoder"),
 

Copied: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/ZoneDemo.java
 (from r669747, 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneDemo.java)
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/ZoneDemo.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/ZoneDemo.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneDemo.java&r1=669747&r2=672923&rev=672923&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ZoneDemo.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/ZoneDemo.java
 Mon Jun 30 14:08:39 2008
@@ -12,14 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry5.integration.app1.pages;
+package org.apache.tapestry5.integration.app1.pages.nested;
 
 import org.apache.tapestry5.Block;
+import org.apache.tapestry5.ValueEncoder;
 import org.apache.tapestry5.annotations.ApplicationState;
 import org.apache.tapestry5.annotations.Component;
 import org.apache.tapestry5.annotations.Log;
 import org.apache.tapestry5.corelib.components.BeanEditForm;
 import org.apache.tapestry5.integration.app1.data.RegistrationData;
+import org.apache.tapestry5.internal.services.StringValueEncoder;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.json.JSONObject;
 
@@ -103,4 +105,9 @@
     {
         return new Date();
     }
+
+    public ValueEncoder<String> getEncoder()
+    {
+        return new StringValueEncoder();
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinkerTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinkerTest.java?rev=672923&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinkerTest.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinkerTest.java
 Mon Jun 30 14:08:39 2008
@@ -0,0 +1,70 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.json.JSONObject;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class PartialMarkupDocumentLinkerTest extends Assert
+{
+    @Test
+    public void script()
+    {
+        PartialMarkupDocumentLinker linker = new PartialMarkupDocumentLinker();
+
+        linker.addScript("foo();");
+        linker.addScript("bar();");
+
+        JSONObject reply = new JSONObject();
+
+        linker.commit(reply);
+
+        assertEquals(reply.get("script"), "foo();\nbar();\n");
+    }
+
+    @Test
+    public void script_link()
+    {
+        PartialMarkupDocumentLinker linker = new PartialMarkupDocumentLinker();
+
+        linker.addScriptLink("foo.js");
+        linker.addScriptLink("bar.js");
+
+        JSONObject reply = new JSONObject();
+
+        linker.commit(reply);
+
+        assertEquals(reply.toString(), 
"{\"scripts\":[\"foo.js\",\"bar.js\"]}");
+
+    }
+
+    @Test
+    public void stylesheet_link()
+    {
+        PartialMarkupDocumentLinker linker = new PartialMarkupDocumentLinker();
+
+        linker.addStylesheetLink("foo.css", "print");
+        linker.addStylesheetLink("bar.css", null);
+
+        JSONObject reply = new JSONObject();
+
+        linker.commit(reply);
+
+        assertEquals(reply.toString(),
+                     
"{\"stylesheets\":[{\"href\":\"foo.css\",\"media\":\"print\"},{\"href\":\"bar.css\"}]}");
+
+    }
+}


Reply via email to