1) When using goog.testing, it appears that I can't access
goog.testing.TestRunner and goog.testing.TestCase unless those
specific namespaces are imported as well. For example:
(ns example.core
(:require [goog.testing :as testing]))
(defn ^:export start-test []
testing/TestCase))
If i call start_test() from the browser repl it returns null. If I add
[goog.testing.TestCase :as tc] to the requires, without changing
start-test, then the code works fine.
2) Trying to launch the TestRunner fails if i do it in a function, but
works if I return the runner and call it from the browser.
(defn ^:export start-test []
(let [runner (testing/TestRunner.)
test (testing/TestCase. "foo")]
(.add test (tc/Test. "test-html-escaping"
test-html-escaping
goog.global))
(.initialize runner test)
((.execute runner))))
This will throw an exception that the TestRunner is not initialized.
However, if I change ((.execute runner)) to runner, then call
"start_test().execute()" it runs perfectly. I can only guess that the
this object is not getting set correctly for some reason.
Note that changing the last line to (. runner (execute)) also works.
3) Is there some way to export a symbol to be global? For example,
goog.testing.jsunit will automatically search the global namespace for
test functions, but I can't figure out (aside from js*) how to stick
something in there. I basically created start-test above to get
around this.
jack.
> I'm having some trouble attempting to use interop with ClojureScript.
> I'm trying to translate examples from the Closure book into
> ClojureScript, and I keep getting stuck on various things.
>
> 1) When using goog.testing, it appears that I can't access
> goog.testing.TestRunner and goog.testing.TestCase unless those
> specific namespaces are imported as well. For example:
>
> (ns example.core
> (:require [goog.testing :as testing]))
>
> (defn ^:export start-test []
> testing/TestCase))
>
> If i call start_test() from the browser repl it returns null. If I add
> [goog.testing.TestCase :as tc] to the requires, without changing
> start-test, then the code works fine.
>
Yes, you'll have to :require all the components/files of a 'namespace'
and 'class' in order to use them from ClojureScript with Clojure-like
idioms. Since TestCase is in a different file, you need to require it
as well. You have to look at each lib to see the approach it takes,
e.g. some function oriented libs are self contained while 'class-like'
ones have a file per 'class'.
> 2) Trying to launch the TestRunner fails if i do it in a function, but
> works if I return the runner and call it from the browser.
>
> (defn ^:export start-test []
> (let [runner (testing/TestRunner.)
> test (testing/TestCase. "foo")]
> (.add test (tc/Test. "test-html-escaping"
> test-html-escaping
> goog.global))
> (.initialize runner test)
> ((.execute runner))))
>
> This will throw an exception that the TestRunner is not initialized.
> However, if I change ((.execute runner)) to runner, then call
> "start_test().execute()" it runs perfectly. I can only guess that the
> this object is not getting set correctly for some reason.
>
> Note that changing the last line to (. runner (execute)) also works.
>
(.execute runner) currently returns the value in the 'execute' slot of
runner, that value being a function object. Wrapping it in parens then
calls that function with no arguments (and thus no target object, i.e.
this) and cannot work.
(. runner (execute)) disambiguates the slot and forces it to be
considered as a method, i.e. a call. On the JVM, methods are not first-
class functions in fields, and we can use the type system to determine
if (. target member) (with no arguments) is a method call or a field
access. In JS, it is always potentially either, and there is no way
with a single syntax to determine which interpretation is desired,
thus the need to disambiguate.
(. target (method)) works, but is awkward, and, since it is so
infrequently used in Clojure proper, is not idiomatic.
One alternative is to interpret (. obj member), and thus (.member obj)
as a call always, but that begs the question as to field/slot access.
Something new will be required, and it will have to be added to
Clojure to allow for portable code. Changing Clojure was out of scope
for the first version, but I'd like to improve this ASAP.
One option is (. target :slot), possibly with the not-so-great (.:slot
target) as well.
Thoughts everyone?
> 3) Is there some way to export a symbol to be global? For example,
> goog.testing.jsunit will automatically search the global namespace for
> test functions, but I can't figure out (aside from js*) how to stick
> something in there. I basically created start-test above to get
> around this.
There is no global namespace in ClojureScript, but you can use
goog.global as a proxy (with some restrictions) for the JS global ns.
I'm not familiar with the requirements of goog.testing.jsunit, but
have you tried putting tests in goog.global. i.e.
(set! goog.global.mytest my-test)
Rich
> One option is (. target :slot), possibly with the not-so-great (.:slotWhy not simply (target :slot) and (:slot target) as one means of
> target) as well.
accessing field values. Then you can still have clojure's traditional
(.x target) execute when x is a function object and return x's value
otherwise. If you want to get a member function object instead of
executing it, use (:method target).
These two syntaxes seem to stay consistent with traditional clojure
but also accommodate javascript's equivalence between objects and
maps.
Arthur
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en