[gjs/wip/installed-tests] Rework test suite to be installed



commit f7e4b445f085be31f9f409d0a968398b04f27859
Author: Colin Walters <walters verbum org>
Date:   Thu Apr 18 05:40:23 2013 -0400

    Rework test suite to be installed
    
    The test suite moves to a subdirectory "installed-tests" that
    is configured and built indepenently of the main source.
    
    This allows us to automate running it much more easily; the tests run
    in qemu and a logged in desktop session.  Thus the test suite doesn't
    have to launch its own session bus and Xvfb for example.
    
    It was necessary to change the test suite to do JUnit as a regular
    import; the previous method required a custom launcher process, but
    it's a lot saner to make the test cases just plain gjs code.
    
    See https://live.gnome.org/GnomeGoals/InstalledTests

 Makefile-test.am                                   |  177 +------
 installed-tests/.gitignore                         |   40 ++
 installed-tests/Makefile-test.am                   |   84 +++
 installed-tests/Makefile.am                        |   20 +
 installed-tests/autogen.sh                         |    2 +
 installed-tests/configure.ac                       |   49 ++
 installed-tests/gjs-installed-tests.testmeta.in    |    2 +
 installed-tests/test/gjs-unit.c                    |  147 +++++
 {test => installed-tests/test}/gjs.supp            |    0
 .../test}/js/modules/alwaysThrows.js               |    0
 .../test}/js/modules/foobar.js                     |    0
 .../test}/js/modules/modunicode.js                 |    0
 .../test}/js/modules/mutualImport/a.js             |    0
 .../test}/js/modules/mutualImport/b.js             |    0
 .../test}/js/modules/subA/.hidden/hidden.js        |    0
 .../test}/js/modules/subA/.secret.js               |    0
 {test => installed-tests/test}/js/modules/subA/foo |    0
 .../test}/js/modules/subA/subB/__init__.js         |    0
 .../test}/js/modules/subA/subB/baz.js              |    0
 .../test}/js/modules/subA/subB/foobar.js           |    0
 installed-tests/test/js/test0010basic.js           |    8 +
 installed-tests/test/js/test0020importer.js        |    9 +
 installed-tests/test/js/test0030basicBoxed.js      |   11 +
 .../test}/js/test0040mainloop.js                   |    4 +-
 installed-tests/test/js/testByteArray.js           |  122 ++++
 {test => installed-tests/test}/js/testCairo.js     |    0
 {test => installed-tests/test}/js/testClass.js     |   45 +-
 installed-tests/test/js/testEverythingBasic.js     |  624 +++++++++++++++++++
 .../test}/js/testEverythingEncapsulated.js         |  133 ++---
 {test => installed-tests/test}/js/testGDBus.js     |  186 +++---
 .../test}/js/testGIMarshalling.js                  |    0
 .../test}/js/testGObjectClass.js                   |    0
 installed-tests/test/js/testJS1_8.js               |   54 ++
 installed-tests/test/js/testJSDefault.js           |   16 +
 installed-tests/test/js/testLang.js                |  128 ++++
 {test => installed-tests/test}/js/testLocale.js    |   22 +-
 {test => installed-tests/test}/js/testMainloop.js  |   18 +-
 {test => installed-tests/test}/js/testMetaClass.js |   44 +-
 installed-tests/test/js/testParamSpec.js           |   96 +++
 {test => installed-tests/test}/js/testSignals.js   |   38 +-
 installed-tests/test/js/testSystem.js              |   15 +
 {test => installed-tests/test}/js/testTweener.js   |   80 ++--
 installed-tests/test/js/testUnicode.js             |   14 +
 installed-tests/test/js/testself.js                |   38 ++
 {test => installed-tests/test}/unittest.gdb        |    0
 test/gjs-unit.c                                    |  291 ---------
 test/js/test0010basic.js                           |    7 -
 test/js/test0020importer.js                        |    7 -
 test/js/test0030basicBoxed.js                      |   10 -
 test/js/testByteArray.js                           |  120 ----
 test/js/testEverythingBasic.js                     |  625 --------------------
 test/js/testImporter.js                            |  148 -----
 test/js/testJS1_8.js                               |   52 --
 test/js/testJSDefault.js                           |   13 -
 test/js/testLang.js                                |  126 ----
 test/js/testParamSpec.js                           |   99 ---
 test/js/testSystem.js                              |   13 -
 test/js/testUnicode.js                             |   12 -
 test/js/testself.js                                |   36 --
 59 files changed, 1773 insertions(+), 2012 deletions(-)
---
diff --git a/Makefile-test.am b/Makefile-test.am
index 60beeab..b3e1b9a 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -1,8 +1,6 @@
 RUN_WITH_DBUS = ${top_srcdir}/test/run-with-dbus --session --system
 GTESTER = ${TESTS_ENVIRONMENT} ${RUN_WITH_DBUS} gtester
 
-TEST_GIRS =
-
 ########################################################################
 TEST_PROGS += gjs-tests
 
@@ -22,69 +20,11 @@ gjs_tests_LDADD =           \
 gjs_tests_SOURCES =            \
        test/gjs-tests.c
 
-TEST_PROGS += gjs-unit
-
-gjs_unit_CPPFLAGS =            \
-       $(AM_CPPFLAGS)          \
-       $(gjs_directory_defines)\
-       $(GJS_CFLAGS)
-gjs_unit_LDADD =               \
-       libgjs.la               \
-       $(GJS_LIBS)
-
-## -rdynamic makes backtraces work
-## we -export-dynamic so we can dlopen ourselves and use gobject-introspection
-gjs_unit_LDFLAGS=-export-dynamic -rdynamic
-gjs_unit_SOURCES =     \
-       test/gjs-unit.c
-
-# noinst_ always builds a static library
-testlib_LTLIBRARIES = libregress.la libwarnlib.la libgimarshallingtests.la
-testlibdir = $(prefix)/unused
-install-testlibLTLIBRARIES: # prevent it from being installed
-
-nodist_libregress_la_SOURCES = $(GI_DATADIR)/tests/regress.c $(GI_DATADIR)/tests/regress.h
-libregress_la_CPPFLAGS =
-libregress_la_CFLAGS = $(GJS_CFLAGS)
-libregress_la_LDFLAGS = -avoid-version $(GJS_LIBS)
-libregress_scannerflags_includes = --include=Gio-2.0
-if ENABLE_CAIRO
-libregress_la_CFLAGS += $(GJS_CAIRO_CFLAGS)
-libregress_la_LDFLAGS +=  $(GJS_CAIRO_LIBS)
-libregress_scannerflags_includes += --include=cairo-1.0
-else
-libregress_la_CPPFLAGS += -D_GI_DISABLE_CAIRO
-endif
-nodist_libwarnlib_la_SOURCES = $(GI_DATADIR)/tests/warnlib.c $(GI_DATADIR)/tests/warnlib.h
-libwarnlib_la_CFLAGS = $(GJS_CFLAGS)
-libwarnlib_la_LDFLAGS = -avoid-version $(GJS_LIBS)
-nodist_libgimarshallingtests_la_SOURCES = $(GI_DATADIR)/tests/gimarshallingtests.c 
$(GI_DATADIR)/tests/gimarshallingtests.h
-libgimarshallingtests_la_CFLAGS = $(GJS_CFLAGS)
-libgimarshallingtests_la_LDFLAGS = -avoid-version $(GJS_LIBS)
-
-Regress-1.0.gir: libregress.la
-Regress_1_0_gir_LIBS = libregress.la
-Regress_1_0_gir_FILES = $(nodist_libregress_la_SOURCES)
-Regress_1_0_gir_SCANNERFLAGS = --warn-all --warn-error $(libregress_scannerflags_includes) 
$(libregress_la_CPPFLAGS)
-TEST_GIRS += Regress-1.0.gir
-
-WarnLib-1.0.gir: libwarnlib.la
-WarnLib_1_0_gir_LIBS = libwarnlib.la
-WarnLib_1_0_gir_INCLUDES = Gio-2.0
-WarnLib_1_0_gir_FILES = $(nodist_libwarnlib_la_SOURCES)
-WarnLib_1_0_gir_SCANNERFLAGS = --c-include="warnlib.h" --symbol-prefix=warnlib_
-TEST_GIRS += WarnLib-1.0.gir
-
-GIMarshallingTests-1.0.gir: libgimarshallingtests.la
-GIMarshallingTests_1_0_gir_LIBS = libgimarshallingtests.la
-GIMarshallingTests_1_0_gir_INCLUDES = Gio-2.0
-GIMarshallingTests_1_0_gir_FILES = $(nodist_libgimarshallingtests_la_SOURCES)
-GIMarshallingTests_1_0_gir_SCANNERFLAGS = --symbol-prefix=gi_marshalling_tests --warn-all --warn-error
-TEST_GIRS += GIMarshallingTests-1.0.gir
+check-local: gjs-tests
+       @test -z "${TEST_PROGS}" || ${GTESTER} --verbose ${TEST_PROGS} ${TEST_PROGS_OPTIONS}
 
-$(foreach gir,$(TEST_GIRS),$(eval $(call introspection-scanner,$(gir))))
+check: check-local
 
-########################################################################
 TESTS_ENVIRONMENT =                                                    \
        TOP_SRCDIR=$(top_srcdir)                                        \
        DBUS_SESSION_BUS_ADDRESS=''                                     \
@@ -96,114 +36,3 @@ TESTS_ENVIRONMENT =                                                 \
        GI_TYPELIB_PATH=$(builddir)                                     \
        LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$(FIREFOX_JS_LIBDIR)"       \
        G_FILENAME_ENCODING=latin1      # ensure filenames are not utf8
-
-if !ENABLE_CAIRO
-TESTS_ENVIRONMENT += GJS_TEST_SKIP_CAIRO=1
-endif
-
-tests_dependencies = $(gjsnative_LTLIBRARIES) ${TEST_PROGS} $(TEST_GIRS:.gir=.typelib)
-
-test: $(tests_dependencies)
-       @test -z "${TEST_PROGS}" || ${GTESTER} --verbose ${TEST_PROGS} ${TEST_PROGS_OPTIONS}
-
-check: test
-
-gdb-check gdb-test: $(tests_dependencies)
-       failed=; for prog in ${TEST_PROGS}; do \
-         ${TESTS_ENVIRONMENT} GJS_TEST_TIMEOUT=0 $(RUN_WITH_DBUS) libtool --mode=execute gdb -x \
-             $(top_srcdir)/test/unittest.gdb --args $$prog; \
-         done
-
-valgrind-check valgrind-test: $(tests_dependencies)
-       @test -z "${TEST_PROGS}" || { \
-         failed=; for prog in ${TEST_PROGS}; do \
-           ${TESTS_ENVIRONMENT} G_SLICE=always-malloc  \
-           $(RUN_WITH_DBUS) \
-           $(LIBTOOL) --mode=execute valgrind          \
-           --log-file=valgrind.$$prog.log              \
-           --error-exitcode=1                          \
-           --trace-children=yes                        \
-           --tool=memcheck                             \
-           --leak-check=full                           \
-           --suppressions=$(top_srcdir)/test/gjs.supp  \
-           $$VALGRIND_ARGS                             \
-           $$prog \
-           && $(GREP) -q 'definitely lost: 0 bytes in 0 blocks' valgrind.$$prog.log \
-           || failed="$$failed $$prog"; \
-         done; \
-         test -z "$$failed" || { \
-           echo "valgrind failed for:$$failed"; exit 1; \
-         }; \
-       }
-
-.PHONY: test gdb-check gdb-test valgrind-check valgrind-test
-
-CLEANFILES +=                                  \
-       $(TEST_PROGS:%=valgrind.%.log)          \
-       uninstalled-test-bus.conf               \
-       uninstalled-system-test-bus.conf
-
-clean-local:
-       -rm -rf test_user_data
-
-EXTRA_DIST +=                                  \
-       test/js/modules/alwaysThrows.js         \
-       test/js/modules/foobar.js               \
-       test/js/modules/mutualImport/a.js       \
-       test/js/modules/mutualImport/b.js       \
-       test/js/modules/modunicode.js           \
-       test/js/modules/subA/.secret.js         \
-       test/js/modules/subA/.hidden/hidden.js  \
-       test/js/modules/subA/foo                \
-       test/js/modules/subA/subB/__init__.js   \
-       test/js/modules/subA/subB/foobar.js     \
-       test/js/modules/subA/subB/baz.js        \
-       test/js/test0010basic.js                \
-       test/js/test0020importer.js             \
-       test/js/test0030basicBoxed.js           \
-       test/js/test0040mainloop.js             \
-       test/js/testself.js                     \
-       test/js/testByteArray.js                \
-       test/js/testCairo.js                    \
-       test/js/testClass.js                    \
-       test/js/testGDBus.js                    \
-       test/js/testEverythingBasic.js          \
-       test/js/testEverythingEncapsulated.js   \
-       test/js/testGIMarshalling.js            \
-       test/js/testImporter.js                 \
-       test/js/testJS1_8.js                    \
-       test/js/testJSDefault.js                \
-       test/js/testLang.js                     \
-       test/js/testLocale.js                   \
-       test/js/testMainloop.js                 \
-       test/js/testSignals.js                  \
-       test/js/testSystem.js                   \
-       test/js/testTweener.js                  \
-       test/js/testUnicode.js                  \
-       test/run-with-dbus                      \
-       test/test-bus.conf
-
-########################################################################
-if ENABLE_COVERAGE
-lcov:
-       test -d lcov || mkdir lcov
-       $(LCOV) --compat-libtool --directory . --capture -o lcov/lcov.info
-       $(GENHTML) --legend -o lcov lcov/lcov.info
-
-lcov-clean:
-       find . -name '*.gcda' -delete
-       rm -rf lcov
-
-lcov-realclean: lcov-clean
-       find . -name '*.gcno' -delete
-
-clean-local: lcov-realclean
-
-.PHONY: lcov lcov-clean lcov-realclean
-else
-lcov:
-       @echo >&1 "*** ERROR: 'configure --enable-coverage' required"
-       @exit 1
-
-.PHONY: lcov
-endif
diff --git a/installed-tests/.gitignore b/installed-tests/.gitignore
new file mode 100644
index 0000000..d8dc1df
--- /dev/null
+++ b/installed-tests/.gitignore
@@ -0,0 +1,40 @@
+*.la
+*.lo
+*.o
+*.gir
+*.typelib
+*~
+.deps/
+.libs/
+INSTALL
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+gjs-1.0.pc
+gjs-console
+gjs-internals-1.0.pc
+gjs-gi-1.0.pc
+gjs-tests
+gjs-unit
+gjs/gjs.stp
+gjs_gi_probes.h
+install-sh
+libtool
+ltmain.sh
+missing
+stamp-h1
+test_user_data
+uninstalled-test-bus.conf
+uninstalled-system-test-bus.conf
+valgrind.gjs-tests.log
+valgrind.gjs-unit.log
diff --git a/installed-tests/Makefile-test.am b/installed-tests/Makefile-test.am
new file mode 100644
index 0000000..7d39f59
--- /dev/null
+++ b/installed-tests/Makefile-test.am
@@ -0,0 +1,84 @@
+
+installedtestmetadir = $(datadir)/installed-tests
+installedtestmeta_DATA = gjs-installed-tests.testmeta
+
+gjs-installed-tests.testmeta: gjs-installed-tests.testmeta.in Makefile
+       sed -e s,@pkglibexecdir\@,$(pkglibexecdir), < $< > $  tmp && mv $  tmp $@
+
+pkglibexec_PROGRAMS += gjs-installed-tests
+
+gjs_installed_tests_CFLAGS = $(AM_CFLAGS) $(GJS_CFLAGS)
+gjs_installed_tests_LDADD = $(GJS_LIBS)
+gjs_installed_tests_LDFLAGS = -rpath $(pkglibdir)
+gjs_installed_tests_SOURCES = test/gjs-unit.c
+
+privlib_LTLIBRARIES += libregress.la libwarnlib.la libgimarshallingtests.la
+
+nodist_libregress_la_SOURCES = $(GI_DATADIR)/tests/regress.c $(GI_DATADIR)/tests/regress.h
+libregress_la_CPPFLAGS = $(AM_CPPFLAGS)
+libregress_la_CFLAGS = $(GJS_CFLAGS)
+libregress_la_LDFLAGS = -avoid-version $(GJS_LIBS)
+libregress_scannerflags_includes = --include=Gio-2.0
+if ENABLE_CAIRO
+libregress_la_CFLAGS += $(GJS_CAIRO_CFLAGS)
+libregress_la_LDFLAGS +=  $(GJS_CAIRO_LIBS)
+libregress_scannerflags_includes += --include=cairo-1.0
+else
+libregress_la_CPPFLAGS += -D_GI_DISABLE_CAIRO
+endif
+nodist_libwarnlib_la_SOURCES = $(GI_DATADIR)/tests/warnlib.c $(GI_DATADIR)/tests/warnlib.h
+libwarnlib_la_CFLAGS = $(GJS_CFLAGS)
+libwarnlib_la_LDFLAGS = -avoid-version $(GJS_LIBS)
+nodist_libgimarshallingtests_la_SOURCES = $(GI_DATADIR)/tests/gimarshallingtests.c 
$(GI_DATADIR)/tests/gimarshallingtests.h
+libgimarshallingtests_la_CFLAGS = $(GJS_CFLAGS)
+libgimarshallingtests_la_LDFLAGS = -avoid-version $(GJS_LIBS)
+
+Regress-1.0.gir: libregress.la
+Regress_1_0_gir_LIBS = libregress.la
+Regress_1_0_gir_FILES = $(nodist_libregress_la_SOURCES)
+Regress_1_0_gir_SCANNERFLAGS = --warn-all --warn-error $(libregress_scannerflags_includes) 
$(libregress_la_CPPFLAGS)
+INTROSPECTION_GIRS += Regress-1.0.gir
+
+WarnLib-1.0.gir: libwarnlib.la
+WarnLib_1_0_gir_LIBS = libwarnlib.la
+WarnLib_1_0_gir_INCLUDES = Gio-2.0
+WarnLib_1_0_gir_FILES = $(nodist_libwarnlib_la_SOURCES)
+WarnLib_1_0_gir_SCANNERFLAGS = --c-include="warnlib.h" --symbol-prefix=warnlib_
+INTROSPECTION_GIRS += WarnLib-1.0.gir
+
+GIMarshallingTests-1.0.gir: libgimarshallingtests.la
+GIMarshallingTests_1_0_gir_LIBS = libgimarshallingtests.la
+GIMarshallingTests_1_0_gir_INCLUDES = Gio-2.0
+GIMarshallingTests_1_0_gir_FILES = $(nodist_libgimarshallingtests_la_SOURCES)
+GIMarshallingTests_1_0_gir_SCANNERFLAGS = --symbol-prefix=gi_marshalling_tests --warn-all --warn-error
+INTROSPECTION_GIRS += GIMarshallingTests-1.0.gir
+
+typelibdir = $(pkglibdir)
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+jstestsdir = $(pkglibdir)/js
+jstests_DATA =                                 \
+       test/js/test0010basic.js                \
+       test/js/test0020importer.js             \
+       test/js/test0030basicBoxed.js           \
+       test/js/test0040mainloop.js             \
+       test/js/testself.js                     \
+       test/js/testByteArray.js                \
+       test/js/testClass.js                    \
+       test/js/testGDBus.js                    \
+       test/js/testEverythingBasic.js          \
+       test/js/testEverythingEncapsulated.js   \
+       test/js/testGIMarshalling.js            \
+       test/js/testJS1_8.js                    \
+       test/js/testJSDefault.js                \
+       test/js/testLang.js                     \
+       test/js/testLocale.js                   \
+       test/js/testMainloop.js                 \
+       test/js/testSignals.js                  \
+       test/js/testSystem.js                   \
+       test/js/testTweener.js                  \
+       test/js/testUnicode.js
+
+if ENABLE_CAIRO
+jstests_DATA += test/js/testCairo.js
+endif
diff --git a/installed-tests/Makefile.am b/installed-tests/Makefile.am
new file mode 100644
index 0000000..051fcf8
--- /dev/null
+++ b/installed-tests/Makefile.am
@@ -0,0 +1,20 @@
+bin_PROGRAMS =
+lib_LTLIBRARIES =
+noinst_HEADERS =
+noinst_LTLIBRARIES =
+pkglibexec_PROGRAMS =
+privlibdir = $(pkglibdir)
+privlib_LTLIBRARIES =
+BUILT_SOURCES =
+CLEANFILES =
+EXTRA_DIST =
+TEST_PROGS =
+INTROSPECTION_GIRS =
+ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
+AM_CPPFLAGS = -DPKGLIBDIR=\"$(pkglibdir)\"
+AM_CFLAGS = $(WARN_CFLAGS)
+
+include Makefile-test.am
+
+include $(INTROSPECTION_MAKEFILE)
+
diff --git a/installed-tests/autogen.sh b/installed-tests/autogen.sh
new file mode 100755
index 0000000..c187584
--- /dev/null
+++ b/installed-tests/autogen.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec autoreconf -vfi
diff --git a/installed-tests/configure.ac b/installed-tests/configure.ac
new file mode 100644
index 0000000..0c9fc99
--- /dev/null
+++ b/installed-tests/configure.ac
@@ -0,0 +1,49 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([gjs-installed-tests], 1.36.0, [http://bugzilla.gnome.org/enter_bug.cgi?product=gjs])
+AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
+AC_CONFIG_SRCDIR([autogen.sh])
+AC_CONFIG_HEADER([config.h])
+
+AM_MAINTAINER_MODE([enable])
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+# our first pkg-config invocation is conditional, ensure macros still work
+PKG_PROG_PKG_CONFIG
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_LIBTOOL
+AM_DISABLE_STATIC
+
+GNOME_COMPILE_WARNINGS([maximum])
+GNOME_MAINTAINER_MODE_DEFINES
+
+PKG_CHECK_MODULES([GJS], [gio-unix-2.0 >= 2.36 gjs-internals-1.0 >= 1.36.0])
+
+GOBJECT_INTROSPECTION_REQUIRE([1.36.0])
+GI_DATADIR=$($PKG_CONFIG --variable=gidatadir gobject-introspection-1.0)
+AC_SUBST(GI_DATADIR)
+
+AC_ARG_WITH(cairo,
+           AS_HELP_STRING([--without-cairo], [Use cairo @<:@default=yes@:>@]),
+           [], [with_cairo=yes])
+AS_IF([test x$with_cairo = xyes], [
+  PKG_CHECK_MODULES([GJS_CAIRO], [$gjs_cairo_packages], have_cairo=yes, have_cairo=no)
+])
+AM_CONDITIONAL(ENABLE_CAIRO, test x$have_cairo = xyes)
+AS_IF([test x$have_cairo = xyes], [
+  AC_DEFINE([ENABLE_CAIRO],[1],[Define if you want to build with cairo support])
+])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+
+AC_MSG_RESULT([
+        $PACKAGE_NAME $VERSION
+
+       GJS_CFLAGS:             ${GJS_CFLAGS}
+       GJS_LIBS:               ${GJS_LIBS}
+])
diff --git a/installed-tests/gjs-installed-tests.testmeta.in b/installed-tests/gjs-installed-tests.testmeta.in
new file mode 100644
index 0000000..ef459cf
--- /dev/null
+++ b/installed-tests/gjs-installed-tests.testmeta.in
@@ -0,0 +1,2 @@
+[Test]
+Exec= pkglibexecdir@/gjs-installed-tests
diff --git a/installed-tests/test/gjs-unit.c b/installed-tests/test/gjs-unit.c
new file mode 100644
index 0000000..572763d
--- /dev/null
+++ b/installed-tests/test/gjs-unit.c
@@ -0,0 +1,147 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2008  litl, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <girepository.h>
+#include <gjs/gjs-module.h>
+#include <locale.h>
+
+#include <string.h>
+
+typedef struct {
+    GjsContext *context;
+} GjsTestJSFixture;
+
+static void
+setup(GjsTestJSFixture *fix,
+      gconstpointer     test_data)
+{
+    const char *test_filename = test_data;
+    const char *js_version;
+
+    js_version = gjs_context_scan_file_for_js_version(test_filename);
+
+    fix->context = g_object_new (GJS_TYPE_CONTEXT,
+                                 "js-version", js_version,
+                                 NULL);
+}
+
+static void
+teardown(GjsTestJSFixture *fix,
+         gconstpointer     test_data)
+{
+    gjs_memory_report("before destroying context", FALSE);
+    g_object_unref(fix->context);
+    gjs_memory_report("after destroying context", TRUE);
+}
+
+static void
+test(GjsTestJSFixture *fix,
+     gconstpointer     test_data)
+{
+    GError *error = NULL;
+    gboolean success;
+    int code;
+
+    success = gjs_context_eval_file(fix->context, (const char*)test_data, &code, &error);
+    if (!success)
+        g_error("%s", error->message);
+    g_assert(error == NULL);
+    if (code != 0)
+        g_error("Test script returned code %d; assertions will be in gjs.log", code);
+}
+
+static GSList *
+read_all_dir_sorted (const char *dirpath)
+{
+    GSList *result = NULL;
+    GDir *dir;
+    const char *name;
+
+    dir = g_dir_open(dirpath, 0, NULL);
+    g_assert(dir != NULL);
+
+    while ((name = g_dir_read_name(dir)) != NULL)
+        result = g_slist_prepend (result, g_strdup (name));
+    result = g_slist_sort(result, (GCompareFunc) strcmp);
+
+    g_dir_close(dir);
+    return result;
+}
+
+int
+main(int argc, char **argv)
+{
+    char *js_test_dir;
+    GSList *all_tests, *iter;
+    GSList *test_filenames = NULL;
+    int retval;
+
+    /* The tests are known to fail in the presence of the JIT;
+     * we leak objects.
+     * https://bugzilla.gnome.org/show_bug.cgi?id=616193
+     */
+    g_setenv("GJS_DISABLE_JIT", "1", FALSE);
+
+    setlocale(LC_ALL, "");
+    g_test_init(&argc, &argv, NULL);
+
+    g_irepository_prepend_search_path(PKGLIBDIR);
+    js_test_dir = g_build_filename(PKGLIBDIR, "js", NULL);
+
+    all_tests = read_all_dir_sorted(js_test_dir);
+    for (iter = all_tests; iter; iter = iter->next) {
+        char *name = iter->data;
+        char *test_name;
+        char *file_name;
+
+        if (!(g_str_has_prefix(name, "test") &&
+              g_str_has_suffix(name, ".js"))) {
+            g_free(name);
+            continue;
+        }
+        if (g_str_has_prefix (name, "testCairo") && g_getenv ("GJS_TEST_SKIP_CAIRO"))
+            continue;
+
+        /* pretty print, drop 'test' prefix and '.js' suffix from test name */
+        test_name = g_strconcat("/js/", name + 4, NULL);
+        test_name[strlen(test_name)-3] = '\0';
+
+        file_name = g_build_filename(js_test_dir, name, NULL);
+        g_test_add(test_name, GjsTestJSFixture, file_name, setup, test, teardown);
+        g_free(name);
+        g_free(test_name);
+        test_filenames = g_slist_prepend(test_filenames, file_name);
+        /* not freeing file_name yet as it's needed while running the test */
+    }
+    g_free(js_test_dir);
+    g_slist_free(all_tests);
+
+    retval =  g_test_run ();
+    g_slist_foreach(test_filenames, (GFunc)g_free, test_filenames);
+    g_slist_free(test_filenames);
+    return retval;
+}
diff --git a/test/gjs.supp b/installed-tests/test/gjs.supp
similarity index 100%
rename from test/gjs.supp
rename to installed-tests/test/gjs.supp
diff --git a/test/js/modules/alwaysThrows.js b/installed-tests/test/js/modules/alwaysThrows.js
similarity index 100%
rename from test/js/modules/alwaysThrows.js
rename to installed-tests/test/js/modules/alwaysThrows.js
diff --git a/test/js/modules/foobar.js b/installed-tests/test/js/modules/foobar.js
similarity index 100%
rename from test/js/modules/foobar.js
rename to installed-tests/test/js/modules/foobar.js
diff --git a/test/js/modules/modunicode.js b/installed-tests/test/js/modules/modunicode.js
similarity index 100%
rename from test/js/modules/modunicode.js
rename to installed-tests/test/js/modules/modunicode.js
diff --git a/test/js/modules/mutualImport/a.js b/installed-tests/test/js/modules/mutualImport/a.js
similarity index 100%
rename from test/js/modules/mutualImport/a.js
rename to installed-tests/test/js/modules/mutualImport/a.js
diff --git a/test/js/modules/mutualImport/b.js b/installed-tests/test/js/modules/mutualImport/b.js
similarity index 100%
rename from test/js/modules/mutualImport/b.js
rename to installed-tests/test/js/modules/mutualImport/b.js
diff --git a/test/js/modules/subA/.hidden/hidden.js b/installed-tests/test/js/modules/subA/.hidden/hidden.js
similarity index 100%
rename from test/js/modules/subA/.hidden/hidden.js
rename to installed-tests/test/js/modules/subA/.hidden/hidden.js
diff --git a/test/js/modules/subA/.secret.js b/installed-tests/test/js/modules/subA/.secret.js
similarity index 100%
rename from test/js/modules/subA/.secret.js
rename to installed-tests/test/js/modules/subA/.secret.js
diff --git a/test/js/modules/subA/foo b/installed-tests/test/js/modules/subA/foo
similarity index 100%
rename from test/js/modules/subA/foo
rename to installed-tests/test/js/modules/subA/foo
diff --git a/test/js/modules/subA/subB/__init__.js b/installed-tests/test/js/modules/subA/subB/__init__.js
similarity index 100%
rename from test/js/modules/subA/subB/__init__.js
rename to installed-tests/test/js/modules/subA/subB/__init__.js
diff --git a/test/js/modules/subA/subB/baz.js b/installed-tests/test/js/modules/subA/subB/baz.js
similarity index 100%
rename from test/js/modules/subA/subB/baz.js
rename to installed-tests/test/js/modules/subA/subB/baz.js
diff --git a/test/js/modules/subA/subB/foobar.js b/installed-tests/test/js/modules/subA/subB/foobar.js
similarity index 100%
rename from test/js/modules/subA/subB/foobar.js
rename to installed-tests/test/js/modules/subA/subB/foobar.js
diff --git a/installed-tests/test/js/test0010basic.js b/installed-tests/test/js/test0010basic.js
new file mode 100644
index 0000000..3d09d76
--- /dev/null
+++ b/installed-tests/test/js/test0010basic.js
@@ -0,0 +1,8 @@
+const JSUnit = imports.jsUnit;
+// application/javascript;version=1.8
+function testBasic1() {
+    var foo = 1+1;
+    JSUnit.assertEquals(2, foo);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
diff --git a/installed-tests/test/js/test0020importer.js b/installed-tests/test/js/test0020importer.js
new file mode 100644
index 0000000..0fb6003
--- /dev/null
+++ b/installed-tests/test/js/test0020importer.js
@@ -0,0 +1,9 @@
+// application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
+
+function testImporter1() {
+    var GLib = imports.gi.GLib;
+    JSUnit.assertEquals(GLib.MAJOR_VERSION, 2);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
diff --git a/installed-tests/test/js/test0030basicBoxed.js b/installed-tests/test/js/test0030basicBoxed.js
new file mode 100644
index 0000000..96ba7b8
--- /dev/null
+++ b/installed-tests/test/js/test0030basicBoxed.js
@@ -0,0 +1,11 @@
+// application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
+const Regress = imports.gi.Regress;
+
+function testBasicBoxed() {
+    var a = new Regress.TestSimpleBoxedA();
+    a.some_int = 42;
+    JSUnit.assertEquals(a.some_int, 42);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
diff --git a/test/js/test0040mainloop.js b/installed-tests/test/js/test0040mainloop.js
similarity index 82%
rename from test/js/test0040mainloop.js
rename to installed-tests/test/js/test0040mainloop.js
index 0b49a3f..23d5de9 100644
--- a/test/js/test0040mainloop.js
+++ b/installed-tests/test/js/test0040mainloop.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
 var Mainloop = imports.mainloop;
 
 function testBasicMainloop() {
@@ -13,4 +14,5 @@ function testDanglingIdle() {
     Mainloop.idle_add(function() { return true; });
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testByteArray.js b/installed-tests/test/js/testByteArray.js
new file mode 100644
index 0000000..0ef8503
--- /dev/null
+++ b/installed-tests/test/js/testByteArray.js
@@ -0,0 +1,122 @@
+// application/javascript;version=1.8
+// tests for imports.lang module
+
+const JSUnit = imports.jsUnit;
+const ByteArray = imports.byteArray;
+const Gio = imports.gi.Gio;
+
+function testEmptyByteArray() {
+    let a = new ByteArray.ByteArray();
+    JSUnit.assertEquals("length is 0 for empty array", 0, a.length);
+}
+
+function testInitialSizeByteArray() {
+    let a = new ByteArray.ByteArray(10);
+    JSUnit.assertEquals("length is 10 for initially-sized-10 array", 10, a.length);
+
+    let i;
+
+    for (i = 0; i < a.length; ++i) {
+        JSUnit.assertEquals("new array initialized to zeroes", 0, a[i]);
+    }
+
+    JSUnit.assertEquals("array had proper number of elements post-construct (counting for)",
+                 10, i);
+}
+
+function testAssignment() {
+    let a = new ByteArray.ByteArray(256);
+    JSUnit.assertEquals("length is 256 for initially-sized-256 array", 256, a.length);
+
+    let i;
+    let count;
+
+    count = 0;
+    for (i = 0; i < a.length; ++i) {
+        JSUnit.assertEquals("new array initialized to zeroes", 0, a[i]);
+        a[i] = 255 - i;
+        count += 1;
+    }
+
+    JSUnit.assertEquals("set proper number of values", 256, count);
+
+    count = 0;
+    for (i = 0; i < a.length; ++i) {
+        JSUnit.assertEquals("assignment set expected value", 255 - i, a[i]);
+        count += 1;
+    }
+
+    JSUnit.assertEquals("checked proper number of values", 256, count);
+}
+
+function testAssignmentPastEnd() {
+    let a = new ByteArray.ByteArray();
+    JSUnit.assertEquals("length is 0 for empty array", 0, a.length);
+
+    a[2] = 5;
+    JSUnit.assertEquals("implicitly made length 3", 3, a.length);
+    JSUnit.assertEquals("implicitly-created zero byte", 0, a[0]);
+    JSUnit.assertEquals("implicitly-created zero byte", 0, a[1]);
+    JSUnit.assertEquals("stored 5 in autocreated position", 5, a[2]);
+}
+
+function testAssignmentToLength() {
+    let a = new ByteArray.ByteArray(20);
+    JSUnit.assertEquals("length is 20 for new array", 20, a.length);
+
+    a.length = 5;
+
+    JSUnit.assertEquals("length is 5 after setting it to 5", 5, a.length);
+}
+
+function testNonIntegerAssignment() {
+    let a = new ByteArray.ByteArray();
+
+    a[0] = 5;
+    JSUnit.assertEquals("assigning 5 gives a byte 5", 5, a[0]);
+
+    a[0] = null;
+    JSUnit.assertEquals("assigning null gives a zero byte", 0, a[0]);
+
+    a[0] = 5;
+    JSUnit.assertEquals("assigning 5 gives a byte 5", 5, a[0]);
+
+    a[0] = undefined;
+    JSUnit.assertEquals("assigning undefined gives a zero byte", 0, a[0]);
+
+    a[0] = 3.14;
+    JSUnit.assertEquals("assigning a double rounds off", 3, a[0]);
+}
+
+function testFromString() {
+    let a = ByteArray.fromString('abcd');
+    JSUnit.assertEquals("from string 'abcd' gives length 4", 4, a.length);
+    JSUnit.assertEquals("'a' results in 97", 97, a[0]);
+    JSUnit.assertEquals("'b' results in 98", 98, a[1]);
+    JSUnit.assertEquals("'c' results in 99", 99, a[2]);
+    JSUnit.assertEquals("'d' results in 100", 100, a[3]);
+}
+
+function testFromArray() {
+    let a = ByteArray.fromArray([ 1, 2, 3, 4 ]);
+    JSUnit.assertEquals("from array [1,2,3,4] gives length 4", 4, a.length);
+    JSUnit.assertEquals("a[0] == 1", 1, a[0]);
+    JSUnit.assertEquals("a[1] == 2", 2, a[1]);
+    JSUnit.assertEquals("a[2] == 3", 3, a[2]);
+    JSUnit.assertEquals("a[3] == 4", 4, a[3]);
+}
+
+function testToString() {
+    let a = new ByteArray.ByteArray();
+    a[0] = 97;
+    a[1] = 98;
+    a[2] = 99;
+    a[3] = 100;
+
+    let s = a.toString();
+    JSUnit.assertEquals("toString() on 4 ascii bytes gives length 4", 4, s.length);
+    JSUnit.assertEquals("toString() gives 'abcd'", "abcd", s);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testCairo.js b/installed-tests/test/js/testCairo.js
similarity index 100%
rename from test/js/testCairo.js
rename to installed-tests/test/js/testCairo.js
diff --git a/test/js/testClass.js b/installed-tests/test/js/testClass.js
similarity index 74%
rename from test/js/testClass.js
rename to installed-tests/test/js/testClass.js
index 14d8aaf..382a85f 100644
--- a/test/js/testClass.js
+++ b/installed-tests/test/js/testClass.js
@@ -1,11 +1,12 @@
 // application/javascript;version=1.8 -*- mode: js; indent-tabs-mode: nil -*-
 
+const JSUnit = imports.jsUnit;
 const Lang = imports.lang;
 
 function assertArrayEquals(expected, got) {
-    assertEquals(expected.length, got.length);
+    JSUnit.assertEquals(expected.length, got.length);
     for (let i = 0; i < expected.length; i ++) {
-        assertEquals(expected[i], got[i]);
+        JSUnit.assertEquals(expected[i], got[i]);
     }
 }
 
@@ -113,7 +114,7 @@ const CustomConstruct = new Lang.Class({
 
 function testClassFramework() {
     let newMagic = new MagicBase('A');
-    assertEquals('A',  newMagic.a);
+    JSUnit.assertEquals('A',  newMagic.a);
 }
 
 function testInheritance() {
@@ -125,61 +126,61 @@ function testInheritance() {
     buffer = [];
     let val = newMagic.foo(10, 20, buffer);
     assertArrayEquals([10, 20], buffer);
-    assertEquals(10*6, val);
+    JSUnit.assertEquals(10*6, val);
 }
 
 function testConstructor() {
-    assertEquals(Magic, Magic.prototype.constructor);
+    JSUnit.assertEquals(Magic, Magic.prototype.constructor);
 
     let newMagic = new Magic();
-    assertEquals(Magic, newMagic.constructor);
+    JSUnit.assertEquals(Magic, newMagic.constructor);
 }
 
 function testInstanceOf() {
     let newMagic = new Magic();
 
-    assertTrue(newMagic instanceof Magic);
-    assertTrue(newMagic instanceof MagicBase);
+    JSUnit.assertTrue(newMagic instanceof Magic);
+    JSUnit.assertTrue(newMagic instanceof MagicBase);
 }
 
 function testToString() {
     let newMagic = new MagicBase();
-    assertEquals('[object MagicBase]', newMagic.toString());
+    JSUnit.assertEquals('[object MagicBase]', newMagic.toString());
 
     let override = new ToStringOverride();
-    assertEquals('[object ToStringOverride]; hello', override.toString());
+    JSUnit.assertEquals('[object ToStringOverride]; hello', override.toString());
 }
 
 function testConfigurable() {
     let newMagic = new MagicBase();
 
     delete newMagic.foo;
-    assertNotUndefined(newMagic.foo);
+    JSUnit.assertNotUndefined(newMagic.foo);
 }
 
 function testAccessor() {
     let newAccessor = new Accessor(11);
 
-    assertEquals(11, newAccessor.value);
-    assertRaises(function() {
+    JSUnit.assertEquals(11, newAccessor.value);
+    JSUnit.assertRaises(function() {
         newAccessor.value = 12;
     });
 
     newAccessor.value = 42;
-    assertEquals(42, newAccessor.value);
+    JSUnit.assertEquals(42, newAccessor.value);
 }
 
 function testAbstract() {
-    assertRaises(function() {
+    JSUnit.assertRaises(function() {
         let newAbstract = new AbstractBase();
     });
 
     let newAbstract = new AbstractImpl();
-    assertEquals(42, newAbstract.foo);
-    assertEquals(42, newAbstract.bar);
+    JSUnit.assertEquals(42, newAbstract.foo);
+    JSUnit.assertEquals(42, newAbstract.bar);
 
     newAbstract = new AbstractImpl2();
-    assertEquals(42, newAbstract.foo);
+    JSUnit.assertEquals(42, newAbstract.foo);
 }
 
 function testCrossCall() {
@@ -190,16 +191,16 @@ function testCrossCall() {
 
     let res = newMagic.bar(10, buffer);
     assertArrayEquals([10, 20], buffer);
-    assertEquals(50, res);
+    JSUnit.assertEquals(50, res);
 }
 
 function testConstruct() {
     let instance = new CustomConstruct(1, 2);
 
-    assertTrue(instance instanceof Array);
-    assertTrue(!(instance instanceof CustomConstruct));
+    JSUnit.assertTrue(instance instanceof Array);
+    JSUnit.assertTrue(!(instance instanceof CustomConstruct));
 
     assertArrayEquals([1, 2], instance);
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
diff --git a/installed-tests/test/js/testEverythingBasic.js b/installed-tests/test/js/testEverythingBasic.js
new file mode 100644
index 0000000..3b715f8
--- /dev/null
+++ b/installed-tests/test/js/testEverythingBasic.js
@@ -0,0 +1,624 @@
+// application/javascript;version=1.8
+// This used to be called "Everything"
+
+const JSUnit = imports.jsUnit;
+const Everything = imports.gi.Regress;
+const WarnLib = imports.gi.WarnLib;
+
+// We use Gio to have some objects that we know exist
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
+const Lang = imports.lang;
+
+const INT8_MIN = (-128);
+const INT16_MIN = (-32767-1);
+const INT32_MIN = (-2147483647-1);
+const INT64_MIN = (-9223372036854775807-1);
+
+const INT8_MAX = (127);
+const INT16_MAX = (32767);
+const INT32_MAX = (2147483647);
+const INT64_MAX = (9223372036854775807);
+
+const UINT8_MAX = (255);
+const UINT16_MAX = (65535);
+const UINT32_MAX = (4294967295);
+const UINT64_MAX = (18446744073709551615);
+
+function testLifeUniverseAndEverything() {
+    JSUnit.assertEquals(false, Everything.test_boolean(false));
+    JSUnit.assertEquals(true, Everything.test_boolean(true));
+
+    JSUnit.assertEquals(42, Everything.test_int8(42));
+    JSUnit.assertEquals(-42, Everything.test_int8(-42));
+
+    JSUnit.assertEquals(42, Everything.test_uint8(42));
+
+    JSUnit.assertEquals(42, Everything.test_int16(42));
+    JSUnit.assertEquals(-42, Everything.test_int16(-42));
+
+    JSUnit.assertEquals(42, Everything.test_uint16(42));
+
+    JSUnit.assertEquals(42, Everything.test_int32(42));
+    JSUnit.assertEquals(-42, Everything.test_int32(-42));
+
+    JSUnit.assertEquals(42, Everything.test_uint32(42));
+
+    JSUnit.assertEquals(42, Everything.test_int64(42));
+    JSUnit.assertEquals(-42, Everything.test_int64(-42));
+
+    JSUnit.assertEquals(42, Everything.test_uint64(42));
+
+    JSUnit.assertEquals(42, Everything.test_short(42));
+    JSUnit.assertEquals(-42, Everything.test_short(-42));
+
+    JSUnit.assertEquals(42, Everything.test_ushort(42));
+
+    JSUnit.assertEquals(42, Everything.test_int(42));
+    JSUnit.assertEquals(-42, Everything.test_int(-42));
+
+    JSUnit.assertEquals(42, Everything.test_uint(42));
+
+    JSUnit.assertEquals(42, Everything.test_long(42));
+    JSUnit.assertEquals(-42, Everything.test_long(-42));
+
+    JSUnit.assertEquals(42, Everything.test_ulong(42));
+
+    JSUnit.assertEquals(42, Everything.test_ssize(42));
+    JSUnit.assertEquals(-42, Everything.test_ssize(-42));
+
+    JSUnit.assertEquals(42, Everything.test_size(42));
+
+    JSUnit.assertEquals(42, Everything.test_float(42));
+    JSUnit.assertEquals(-42, Everything.test_float(-42));
+
+    JSUnit.assertEquals(42, Everything.test_double(42));
+    JSUnit.assertEquals(-42, Everything.test_double(-42));
+
+    JSUnit.assertEquals("c", Everything.test_unichar("c"));
+    JSUnit.assertEquals("", Everything.test_unichar(""));
+    JSUnit.assertEquals("\u2665", Everything.test_unichar("\u2665"));
+
+    let now = Math.floor(new Date().getTime() / 1000);
+    let bounced = Math.floor(Everything.test_timet(now));
+    JSUnit.assertEquals(bounced, now);
+}
+
+function testLimits() {
+    JSUnit.assertEquals(UINT8_MAX, Everything.test_uint8(UINT8_MAX));
+    JSUnit.assertEquals(UINT16_MAX, Everything.test_uint16(UINT16_MAX));
+    JSUnit.assertEquals(UINT32_MAX, Everything.test_uint32(UINT32_MAX));
+
+    // FAIL: expected 18446744073709552000, got 0
+    //assertEquals(UINT64_MAX, Everything.test_uint64(UINT64_MAX));
+
+    JSUnit.assertEquals(INT8_MIN, Everything.test_int8(INT8_MIN));
+    JSUnit.assertEquals(INT8_MAX, Everything.test_int8(INT8_MAX));
+    JSUnit.assertEquals(INT16_MIN, Everything.test_int16(INT16_MIN));
+    JSUnit.assertEquals(INT16_MAX, Everything.test_int16(INT16_MAX));
+    JSUnit.assertEquals(INT32_MIN, Everything.test_int32(INT32_MIN));
+    JSUnit.assertEquals(INT32_MAX, Everything.test_int32(INT32_MAX));
+    JSUnit.assertEquals(INT64_MIN, Everything.test_int64(INT64_MIN));
+
+    // FAIL: expected 9223372036854776000, got -9223372036854776000
+    //assertEquals(INT64_MAX, Everything.test_int64(INT64_MAX));
+}
+
+function testNoImplicitConversionToUnsigned() {
+    JSUnit.assertRaises(function() { return Everything.test_uint8(-42); });
+    JSUnit.assertRaises(function() { return Everything.test_uint16(-42); });
+    JSUnit.assertRaises(function() { return Everything.test_uint32(-42); });
+
+    JSUnit.assertRaises(function() { return Everything.test_uint64(-42); });
+
+    JSUnit.assertRaises(function() { return Everything.test_uint(-42); });
+    JSUnit.assertRaises(function() { return Everything.test_size(-42); });
+}
+
+
+function testBadConstructor() {
+    try {
+        Gio.AppLaunchContext();
+    } catch (e) {
+        JSUnit.assert(e.message.indexOf("Constructor called as normal method") >= 0);
+    }
+}
+
+function testStrv() {
+    JSUnit.assertTrue(Everything.test_strv_in(['1', '2', '3']));
+    // Second two are deliberately not strings
+    JSUnit.assertRaises(function() { Everything.test_strv_in(['1', 2, 3]); });
+
+    let strv = Everything.test_strv_out();
+    JSUnit.assertEquals(5, strv.length);
+    JSUnit.assertEquals("thanks", strv[0]);
+    JSUnit.assertEquals("for", strv[1]);
+    JSUnit.assertEquals("all", strv[2]);
+    JSUnit.assertEquals("the", strv[3]);
+    JSUnit.assertEquals("fish", strv[4]);
+
+    strv = Everything.test_strv_out_container();
+    JSUnit.assertEquals(3, strv.length);
+    JSUnit.assertEquals("1", strv[0]);
+    JSUnit.assertEquals("2", strv[1]);
+    JSUnit.assertEquals("3", strv[2]);
+}
+
+function testInAfterOut() {
+    const str = "hello";
+
+    let len = Everything.test_int_out_utf8(str);
+    JSUnit.assertEquals("testInAfterOut", str.length, len);
+}
+
+function testUtf8() {
+    const CONST_STR = "const \u2665 utf8";
+    const NONCONST_STR = "nonconst \u2665 utf8";
+
+    JSUnit.assertEquals(CONST_STR, Everything.test_utf8_const_return());
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_nonconst_return());
+    Everything.test_utf8_const_in(CONST_STR);
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_out());
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_inout(CONST_STR));
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_inout(CONST_STR));
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_inout(CONST_STR));
+    JSUnit.assertEquals(NONCONST_STR, Everything.test_utf8_inout(CONST_STR));
+}
+
+function testFilenameReturn() {
+    var filenames = Everything.test_filename_return();
+    JSUnit.assertEquals(2, filenames.length);
+    JSUnit.assertEquals('\u00e5\u00e4\u00f6', filenames[0]);
+    JSUnit.assertEquals('/etc/fstab', filenames[1]);
+}
+
+function testStaticMeth() {
+    let v = Everything.TestObj.new_from_file("/enoent");
+    JSUnit.assertTrue(v instanceof Everything.TestObj);
+}
+
+function testClosure() {
+    let arguments_length = -1;
+    let someCallback = function() {
+                           arguments_length = arguments.length;
+                           return 42;
+                       };
+
+    let i = Everything.test_closure(someCallback);
+
+    JSUnit.assertEquals('callback arguments length', 0, arguments_length);
+    JSUnit.assertEquals('callback return value', 42, i);
+}
+
+function testClosureOneArg() {
+    let arguments_length = -1;
+    let someCallback = function(someValue) {
+                           arguments_length = arguments.length;
+                           JSUnit.assertEquals(1, arguments.length);
+                           return someValue;
+                       };
+
+    let i = Everything.test_closure_one_arg(someCallback, 42);
+
+    JSUnit.assertEquals('callback arguments length', 1, arguments_length);
+    JSUnit.assertEquals('callback with one arg return value', 42, i);
+}
+
+function testCallback() {
+    let callback = function() {
+                       return 42;
+                   };
+    JSUnit.assertEquals('Callback', Everything.test_callback(callback), 42);
+
+    JSUnit.assertEquals('CallbackNull', Everything.test_callback(null), 0);
+    JSUnit.assertRaises('CallbackUndefined', function () { Everything.test_callback(undefined) });
+}
+
+function testArrayCallback() {
+    function arrayEqual(ref, one) {
+        JSUnit.assertEquals(ref.length, one.length);
+        for (let i = 0; i < ref.length; i++)
+            JSUnit.assertEquals(ref[i], one[i]);
+    }
+
+    let callback = function(ints, strings) {
+        JSUnit.assertEquals(2, arguments.length);
+
+        arrayEqual([-1, 0, 1, 2], ints);
+        arrayEqual(["one", "two", "three"], strings);
+
+        return 7;
+    }
+    JSUnit.assertEquals(Everything.test_array_callback(callback), 14);
+    JSUnit.assertRaises(function () { Everything.test_array_callback(null) });
+}
+
+function testCallbackDestroyNotify() {
+    let testObj = {
+        called: 0,
+        test: function(data) {
+            this.called++;
+            return data;
+        }
+    };
+    JSUnit.assertEquals('CallbackDestroyNotify',
+                 Everything.test_callback_destroy_notify(Lang.bind(testObj,
+                     function() {
+                         return testObj.test(42);
+                     })), 42);
+    JSUnit.assertEquals('CallbackDestroyNotify', testObj.called, 1);
+    JSUnit.assertEquals('CallbackDestroyNotify', Everything.test_callback_thaw_notifications(), 42);
+}
+
+function testCallbackAsync() {
+    let test = function(userData) {
+                   return 44;
+               };
+    Everything.test_callback_async(test, 44);
+    let i = Everything.test_callback_thaw_async();
+    JSUnit.assertEquals('testCallbackAsyncFinish', 44, i);
+}
+
+function testIntValueArg() {
+    let i = Everything.test_int_value_arg(42);
+    JSUnit.assertEquals('Method taking a GValue', 42, i);
+}
+
+function testValueReturn() {
+    let i = Everything.test_value_return(42);
+    JSUnit.assertEquals('Method returning a GValue', 42, i);
+}
+
+/* GList types */
+function testGListOut() {
+    JSUnit.assertEquals("1,2,3", Everything.test_glist_nothing_return().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_glist_nothing_return2().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_glist_container_return().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_glist_everything_return().join(','));
+}
+function testGListIn() {
+    const STR_LIST = ["1", "2", "3" ];
+    Everything.test_glist_nothing_in(STR_LIST);
+    Everything.test_glist_nothing_in2(STR_LIST);
+    //Everything.test_glist_container_in(STR_LIST);
+}
+
+/* GSList types */
+function testGSListOut() {
+    JSUnit.assertEquals("1,2,3", Everything.test_gslist_nothing_return().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_gslist_nothing_return2().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_gslist_container_return().join(','));
+    JSUnit.assertEquals("1,2,3", Everything.test_gslist_everything_return().join(','));
+}
+function testGSListIn() {
+    const STR_LIST = ["1", "2", "3" ];
+    Everything.test_gslist_nothing_in(STR_LIST);
+    Everything.test_gslist_nothing_in2(STR_LIST);
+    //Everything.test_gslist_container_in(STR_LIST);
+}
+
+/* Array tests */
+function testArrayIn() {
+    JSUnit.assertEquals(10, Everything.test_array_int_in([1,2,3,4]));
+    JSUnit.assertEquals(10, Everything.test_array_gint8_in([1,2,3,4]));
+    JSUnit.assertEquals(10, Everything.test_array_gint16_in([1,2,3,4]));
+    JSUnit.assertEquals(10, Everything.test_array_gint32_in([1,2,3,4]));
+    // FIXME: arrays of int64 are unimplemented
+    //assertEquals(10, Everything.test_array_gint64_in([1,2,3,4]));
+
+    // implicit conversions from strings to int arrays
+    JSUnit.assertEquals(10, Everything.test_array_gint8_in("\x01\x02\x03\x04"));
+    JSUnit.assertEquals(10, Everything.test_array_gint16_in("\x01\x02\x03\x04"));
+    JSUnit.assertEquals(2560, Everything.test_array_gint16_in("\u0100\u0200\u0300\u0400"));
+
+    // GType arrays
+    JSUnit.assertEquals('[GSimpleAction,GIcon,GBoxed,]',
+                 Everything.test_array_gtype_in([Gio.SimpleAction, Gio.Icon, GObject.TYPE_BOXED]));
+    JSUnit.assertRaises(function() {
+        Everything.test_array_gtype_in(42);
+    });
+    JSUnit.assertRaises(function() {
+        Everything.test_array_gtype_in([undefined]);
+    });
+    JSUnit.assertRaises(function() {
+        // 80 is G_TYPE_OBJECT, but we don't want it to work
+        Everything.test_array_gtype_in([80]);
+    });
+}
+
+function testArrayOut() {
+    function arrayEqual(ref, res) {
+        JSUnit.assertEquals(ref.length, res.length);
+        for (let i = 0; i < ref.length; i++)
+            JSUnit.assertEquals(ref[i], res[i]);
+    }
+
+    let array =  Everything.test_array_fixed_size_int_out();
+    JSUnit.assertEquals(0, array[0]);
+    JSUnit.assertEquals(4, array[4]);
+    array =  Everything.test_array_fixed_size_int_return();
+    JSUnit.assertEquals(0, array[0]);
+    JSUnit.assertEquals(4, array[4]);
+
+    array = Everything.test_array_int_none_out();
+    arrayEqual([1, 2, 3, 4, 5], array);
+
+    array = Everything.test_array_int_full_out();
+    arrayEqual([0, 1, 2, 3, 4], array);
+
+    array = Everything.test_array_int_null_out();
+    JSUnit.assertEquals(0, array.length);
+
+    Everything.test_array_int_null_in(null);
+}
+
+/* GHash type */
+
+// Convert an object to a predictable (not-hash-order-dependent) string
+function objToString(v) {
+    if (typeof(v) == "object") {
+        let keys = [];
+        for (let k in v)
+            keys.push(k);
+        keys.sort();
+        return "{" + keys.map(function(k) {
+            return k + ":" + objToString(v[k]);
+        }) + "}";
+    } else if (typeof(v) == "string") {
+        return '"' + v + '"';
+    } else {
+        return v;
+    }
+}
+
+function testGHashOut() {
+    const HASH_STR = '{baz:"bat",foo:"bar",qux:"quux"}';
+    JSUnit.assertEquals(null, Everything.test_ghash_null_return());
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_nothing_return()));
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_nothing_return2()));
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_container_return()));
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_everything_return()));
+}
+
+function testGHashIn() {
+    const STR_HASH = { foo: 'bar', baz: 'bat', qux: 'quux' };
+    Everything.test_ghash_null_in(null);
+    Everything.test_ghash_nothing_in(STR_HASH);
+    Everything.test_ghash_nothing_in2(STR_HASH);
+}
+
+function testNestedGHashOut() {
+    const HASH_STR = '{wibble:{baz:"bat",foo:"bar",qux:"quux"}}';
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_nested_everything_return()));
+    JSUnit.assertEquals(HASH_STR, objToString(Everything.test_ghash_nested_everything_return2()));
+}
+
+/* Enums */
+function testEnumParam() {
+    let e;
+
+    e = Everything.test_enum_param(Everything.TestEnum.VALUE1);
+    JSUnit.assertEquals('Enum parameter', 'value1', e);
+    e = Everything.test_enum_param(Everything.TestEnum.VALUE3);
+    JSUnit.assertEquals('Enum parameter', 'value3', e);
+
+    e = Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE1);
+    JSUnit.assertEquals('Enum parameter', 'value1', e);
+    e = Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE2);
+    JSUnit.assertEquals('Enum parameter', 'value2', e);
+
+    JSUnit.assertNotUndefined("Enum $gtype", Everything.TestEnumUnsigned.$gtype);
+    JSUnit.assertTrue("Enum $gtype enumerable", "$gtype" in Everything.TestEnumUnsigned);
+}
+
+function testSignal() {
+    let handlerCounter = 0;
+    let o = new Everything.TestObj();
+    let theObject = null;
+
+    let handlerId = o.connect('test', function(signalObject) {
+                                          handlerCounter ++;
+                                          theObject = signalObject;
+                                          o.disconnect(handlerId);
+                                      });
+
+    o.emit('test');
+    JSUnit.assertEquals('handler callled', 1, handlerCounter);
+    JSUnit.assertEquals('Signal handlers gets called with right object', o, theObject);
+    o.emit('test');
+    JSUnit.assertEquals('disconnected handler not called', 1, handlerCounter);
+}
+
+function testInvalidSignal() {
+    let o = new Everything.TestObj();
+
+    JSUnit.assertRaises('connect to invalid signal',
+                 function() { o.connect('invalid-signal', function(o) {}); });
+    JSUnit.assertRaises('emit invalid signal',
+                 function() { o.emit('invalid-signal'); });
+}
+
+function testSignalWithStaticScopeArg() {
+    let o = new Everything.TestObj();
+    let b = new Everything.TestSimpleBoxedA({ some_int: 42,
+                                              some_int8: 43,
+                                              some_double: 42.5,
+                                              some_enum: Everything.TestEnum.VALUE3 });
+
+    o.connect('test-with-static-scope-arg', function(signalObject, signalArg) {
+                                                signalArg.some_int = 44;
+                                            });
+
+    o.emit('test-with-static-scope-arg', b);
+    JSUnit.assertEquals('signal handler was passed arg as reference', 44, b.some_int);
+}
+
+function testTortureSignature0() {
+    let [y, z, q] = Everything.test_torture_signature_0(42, 'foo', 7);
+    JSUnit.assertEquals(Math.floor(y), 42);
+    JSUnit.assertEquals(z, 84);
+    JSUnit.assertEquals(q, 10);
+}
+
+function testTortureSignature1Fail() {
+    JSUnit.assertRaises(function () {
+        let [success, y, z, q] = Everything.test_torture_signature_1(42, 'foo', 7);
+    });
+}
+
+function testTortureSignature1Success() {
+    let [success, y, z, q] = Everything.test_torture_signature_1(11, 'barbaz', 8);
+    JSUnit.assertEquals(Math.floor(y), 11);
+    JSUnit.assertEquals(z, 22);
+    JSUnit.assertEquals(q, 14);
+}
+
+function testTortureSignature2() {
+    let [y, z, q] = Everything.test_torture_signature_2(42, function () {
+        }, 'foo', 7);
+    JSUnit.assertEquals(Math.floor(y), 42);
+    JSUnit.assertEquals(z, 84);
+    JSUnit.assertEquals(q, 10);
+}
+
+function testObjTortureSignature0() {
+    let o = new Everything.TestObj();
+    let [y, z, q] = o.torture_signature_0(42, 'foo', 7);
+    JSUnit.assertEquals(Math.floor(y), 42);
+    JSUnit.assertEquals(z, 84);
+    JSUnit.assertEquals(q, 10);
+}
+
+function testObjTortureSignature1Fail() {
+    let o = new Everything.TestObj();
+    JSUnit.assertRaises(function () {
+        let [success, y, z, q] = o.torture_signature_1(42, 'foo', 7);
+    });
+}
+
+function testObjTortureSignature1Success() {
+    let o = new Everything.TestObj();
+    let [success, y, z, q] = o.torture_signature_1(11, 'barbaz', 8);
+    JSUnit.assertEquals(Math.floor(y), 11);
+    JSUnit.assertEquals(z, 22);
+    JSUnit.assertEquals(q, 14);
+}
+
+function testStrvInGValue() {
+    let v = Everything.test_strv_in_gvalue();
+
+    JSUnit.assertEquals(v.length, 3);
+    JSUnit.assertEquals(v[0], "one");
+    JSUnit.assertEquals(v[1], "two");
+    JSUnit.assertEquals(v[2], "three");
+}
+
+function testVariant() {
+    // Cannot access the variant contents, for now
+    let ivar = Everything.test_gvariant_i();
+    JSUnit.assertEquals('i', ivar.get_type_string());
+    JSUnit.assertTrue(ivar.equal(GLib.Variant.new_int32(1)));
+
+    let svar = Everything.test_gvariant_s();
+    JSUnit.assertEquals('s', String.fromCharCode(svar.classify()));
+    JSUnit.assertEquals('one', svar.get_string()[0]);
+
+    let asvvar = Everything.test_gvariant_asv();
+    JSUnit.assertEquals(2, asvvar.n_children());
+
+    let asvar = Everything.test_gvariant_as();
+    let as = asvar.get_strv();
+    JSUnit.assertEquals('one', as[0]);
+    JSUnit.assertEquals('two', as[1]);
+    JSUnit.assertEquals('three', as[2]);
+    JSUnit.assertEquals(3, as.length);
+}
+
+function testGError() {
+    JSUnit.assertEquals(Gio.io_error_quark(), Number(Gio.IOErrorEnum));
+
+    try {
+        let file = Gio.file_new_for_path("\\/,.^!@&$_don't exist");
+        file.read(null);
+    } catch (x) {
+        JSUnit.assertTrue(x instanceof Gio.IOErrorEnum);
+        JSUnit.assertTrue(x.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND));
+        JSUnit.assertTrue(x.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND));
+
+        JSUnit.assertEquals(Gio.io_error_quark(), x.domain);
+        JSUnit.assertEquals(Gio.IOErrorEnum.NOT_FOUND, x.code);
+    }
+
+    Everything.test_gerror_callback(function(e) {
+        JSUnit.assertTrue(e instanceof Gio.IOErrorEnum);
+        JSUnit.assertEquals(Gio.io_error_quark(), e.domain);
+        JSUnit.assertEquals(Gio.IOErrorEnum.NOT_SUPPORTED, e.code);
+        JSUnit.assertEquals('regression test error', e.message);
+    });
+    Everything.test_owned_gerror_callback(function(e) {
+        JSUnit.assertTrue(e instanceof Gio.IOErrorEnum);
+        JSUnit.assertEquals(Gio.io_error_quark(), e.domain);
+        JSUnit.assertEquals(Gio.IOErrorEnum.PERMISSION_DENIED, e.code);
+        JSUnit.assertEquals('regression test owned error', e.message);
+    });
+
+    // Calling matches() on an unpaired error used to JSUnit.assert:
+    // https://bugzilla.gnome.org/show_bug.cgi?id=689482
+    try {
+        WarnLib.throw_unpaired();
+        JSUnit.assertTrue(false);
+    } catch (e) {
+        JSUnit.assertFalse(e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND));
+    }
+}
+
+function testWrongClassGObject() {
+    /* Function calls */
+    // Everything.func_obj_null_in expects a Everything.TestObj
+    JSUnit.assertRaises(function() {
+        Everything.func_obj_null_in(new Gio.SimpleAction);
+    });
+    JSUnit.assertRaises(function() {
+        Everything.func_obj_null_in(new GLib.KeyFile);
+    });
+    JSUnit.assertRaises(function() {
+        Everything.func_obj_null_in(Gio.File.new_for_path('/'));
+    });
+    Everything.func_obj_null_in(new Everything.TestSubObj);
+
+    /* Method calls */
+    JSUnit.assertRaises(function() {
+        Everything.TestObj.prototype.instance_method.call(new Gio.SimpleAction);
+    });
+    JSUnit.assertRaises(function() {
+        Everything.TestObj.prototype.instance_method.call(new GLib.KeyFile);
+    });
+    Everything.TestObj.prototype.instance_method.call(new Everything.TestSubObj);
+}
+
+function testWrongClassGBoxed() {
+    let simpleBoxed = new Everything.TestSimpleBoxedA;
+    // simpleBoxed.equals expects a Everything.TestSimpleBoxedA
+    JSUnit.assertRaises(function() {
+        simpleBoxed.equals(new Gio.SimpleAction);
+    })
+    JSUnit.assertRaises(function() {
+        simpleBoxed.equals(new Everything.TestObj);
+    })
+    JSUnit.assertRaises(function() {
+        simpleBoxed.equals(new GLib.KeyFile);
+    })
+    JSUnit.assertTrue(simpleBoxed.equals(simpleBoxed));
+
+    JSUnit.assertRaises(function() {
+        Everything.TestSimpleBoxedA.prototype.copy.call(new Gio.SimpleAction);
+    });
+    JSUnit.assertRaises(function() {
+        Everything.TestSimpleBoxedA.prototype.copy.call(new GLib.KeyFile);
+    })
+    Everything.TestSimpleBoxedA.prototype.copy.call(simpleBoxed);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testEverythingEncapsulated.js b/installed-tests/test/js/testEverythingEncapsulated.js
similarity index 53%
rename from test/js/testEverythingEncapsulated.js
rename to installed-tests/test/js/testEverythingEncapsulated.js
index 6dfea8c..e66ce54 100644
--- a/test/js/testEverythingEncapsulated.js
+++ b/installed-tests/test/js/testEverythingEncapsulated.js
@@ -1,37 +1,33 @@
 // application/javascript;version=1.8
 // This used to be called "Everything"
+const JSUnit = imports.jsUnit;
 const Everything = imports.gi.Regress;
 const GLib = imports.gi.GLib;
 
-if (!('assertEquals' in this)) { /* allow running this test standalone */
-    imports.lang.copyPublicProperties(imports.jsUnit, this);
-    gjstestRun = function() { return imports.jsUnit.gjstestRun(window); };
-}
-
 function testStruct() {
     let struct = new Everything.TestStructA();
     struct.some_int = 42;
     struct.some_int8 = 43;
     struct.some_double = 42.5;
     struct.some_enum = Everything.TestEnum.VALUE3;
-    assertEquals(42, struct.some_int);
-    assertEquals(43, struct.some_int8);
-    assertEquals(42.5, struct.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, struct.some_enum);
+    JSUnit.assertEquals(42, struct.some_int);
+    JSUnit.assertEquals(43, struct.some_int8);
+    JSUnit.assertEquals(42.5, struct.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, struct.some_enum);
     let b = struct.clone();
-    assertEquals(42, b.some_int);
-    assertEquals(43, b.some_int8);
-    assertEquals(42.5, b.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, b.some_enum);
+    JSUnit.assertEquals(42, b.some_int);
+    JSUnit.assertEquals(43, b.some_int8);
+    JSUnit.assertEquals(42.5, b.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, b.some_enum);
 
     struct = new Everything.TestStructB();
     struct.some_int8 = 43;
     struct.nested_a.some_int8 = 66;
-    assertEquals(43, struct.some_int8);
-    assertEquals(66, struct.nested_a.some_int8);
+    JSUnit.assertEquals(43, struct.some_int8);
+    JSUnit.assertEquals(66, struct.nested_a.some_int8);
     b = struct.clone();
-    assertEquals(43, b.some_int8);
-    assertEquals(66, struct.nested_a.some_int8);
+    JSUnit.assertEquals(43, b.some_int8);
+    JSUnit.assertEquals(66, struct.nested_a.some_int8);
 }
 
 function testStructConstructor()
@@ -42,23 +38,23 @@ function testStructConstructor()
                                               some_double: 42.5,
                                               some_enum: Everything.TestEnum.VALUE3 });
 
-    assertEquals(42, struct.some_int);
-    assertEquals(43, struct.some_int8);
-    assertEquals(42.5, struct.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, struct.some_enum);
+    JSUnit.assertEquals(42, struct.some_int);
+    JSUnit.assertEquals(43, struct.some_int8);
+    JSUnit.assertEquals(42.5, struct.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, struct.some_enum);
 
     // Make sure we catch bad field names
-    assertRaises(function() {
+    JSUnit.assertRaises(function() {
         let t = new Everything.TestStructA({ junk: 42 });
     });
 
     // Copy an object from another object of the same type, shortcuts to memcpy()
     let copy = new Everything.TestStructA(struct);
 
-    assertEquals(42, copy.some_int);
-    assertEquals(43, copy.some_int8);
-    assertEquals(42.5, copy.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, copy.some_enum);
+    JSUnit.assertEquals(42, copy.some_int);
+    JSUnit.assertEquals(43, copy.some_int8);
+    JSUnit.assertEquals(42.5, copy.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, copy.some_enum);
 }
 
 function testSimpleBoxed() {
@@ -67,10 +63,10 @@ function testSimpleBoxed() {
     simple_boxed.some_int8 = 43;
     simple_boxed.some_double = 42.5;
     simple_boxed.some_enum = Everything.TestEnum.VALUE3;
-    assertEquals(42, simple_boxed.some_int);
-    assertEquals(43, simple_boxed.some_int8);
-    assertEquals(42.5, simple_boxed.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, simple_boxed.some_enum);
+    JSUnit.assertEquals(42, simple_boxed.some_int);
+    JSUnit.assertEquals(43, simple_boxed.some_int8);
+    JSUnit.assertEquals(42.5, simple_boxed.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, simple_boxed.some_enum);
 }
 
 function testBoxedCopyConstructor()
@@ -81,24 +77,24 @@ function testBoxedCopyConstructor()
                                                          some_double: 42.5,
                                                          some_enum: Everything.TestEnum.VALUE3 });
 
-    assertEquals(42, simple_boxed.some_int);
-    assertEquals(43, simple_boxed.some_int8);
-    assertEquals(42.5, simple_boxed.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, simple_boxed.some_enum);
+    JSUnit.assertEquals(42, simple_boxed.some_int);
+    JSUnit.assertEquals(43, simple_boxed.some_int8);
+    JSUnit.assertEquals(42.5, simple_boxed.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, simple_boxed.some_enum);
 
     // Make sure we catch bad field names
-    assertRaises(function() {
+    JSUnit.assertRaises(function() {
         let t = new Everything.TestSimpleBoxedA({ junk: 42 });
     });
 
     // Copy an object from another object of the same type, shortcuts to the boxed copy
     let copy = new Everything.TestSimpleBoxedA(simple_boxed);
 
-    assertTrue(copy instanceof Everything.TestSimpleBoxedA);
-    assertEquals(42, copy.some_int);
-    assertEquals(43, copy.some_int8);
-    assertEquals(42.5, copy.some_double);
-    assertEquals(Everything.TestEnum.VALUE3, copy.some_enum);
+    JSUnit.assertTrue(copy instanceof Everything.TestSimpleBoxedA);
+    JSUnit.assertEquals(42, copy.some_int);
+    JSUnit.assertEquals(43, copy.some_int8);
+    JSUnit.assertEquals(42.5, copy.some_double);
+    JSUnit.assertEquals(Everything.TestEnum.VALUE3, copy.some_enum);
  }
 
 function testNestedSimpleBoxed() {
@@ -107,16 +103,16 @@ function testNestedSimpleBoxed() {
     // Test reading fields and nested fields
     simple_boxed.some_int8 = 42;
     simple_boxed.nested_a.some_int = 43;
-    assertEquals(42, simple_boxed.some_int8);
-    assertEquals(43, simple_boxed.nested_a.some_int);
+    JSUnit.assertEquals(42, simple_boxed.some_int8);
+    JSUnit.assertEquals(43, simple_boxed.nested_a.some_int);
 
     // Try assigning the nested struct field from an instance
     simple_boxed.nested_a = new Everything.TestSimpleBoxedA({ some_int: 53 });
-    assertEquals(53, simple_boxed.nested_a.some_int);
+    JSUnit.assertEquals(53, simple_boxed.nested_a.some_int);
 
     // And directly from a hash of field values
     simple_boxed.nested_a = { some_int: 63 };
-    assertEquals(63, simple_boxed.nested_a.some_int);
+    JSUnit.assertEquals(63, simple_boxed.nested_a.some_int);
 
     // Try constructing with a nested hash of field values
     let simple2 = new Everything.TestSimpleBoxedB({
@@ -127,31 +123,31 @@ function testNestedSimpleBoxed() {
             some_double: 43.5
         }
     });
-    assertEquals(42, simple2.some_int8);
-    assertEquals(43, simple2.nested_a.some_int);
-    assertEquals(44, simple2.nested_a.some_int8);
-    assertEquals(43.5, simple2.nested_a.some_double);
+    JSUnit.assertEquals(42, simple2.some_int8);
+    JSUnit.assertEquals(43, simple2.nested_a.some_int);
+    JSUnit.assertEquals(44, simple2.nested_a.some_int8);
+    JSUnit.assertEquals(43.5, simple2.nested_a.some_double);
 }
 
 function testBoxed() {
     let boxed = new Everything.TestBoxed();
     boxed.some_int8 = 42;
-    assertEquals(42, boxed.some_int8);
+    JSUnit.assertEquals(42, boxed.some_int8);
 }
 
 function testTestStructFixedArray() {
     let struct = new Everything.TestStructFixedArray();
     struct.frob();
-    assertEquals(7, struct.just_int);
-    assertEquals(42, struct.array[0]);
-    assertEquals(43, struct.array[1]);
-    assertEquals(51, struct.array[9]);
+    JSUnit.assertEquals(7, struct.just_int);
+    JSUnit.assertEquals(42, struct.array[0]);
+    JSUnit.assertEquals(43, struct.array[1]);
+    JSUnit.assertEquals(51, struct.array[9]);
 }
 
 function testComplexConstructor() {
     let boxed = new Everything.TestBoxedD('abcd', 8);
 
-    assertEquals(12, boxed.get_magic());
+    JSUnit.assertEquals(12, boxed.get_magic());
 }
 
 function testComplexConstructorBackwardCompatibility() {
@@ -162,17 +158,17 @@ function testComplexConstructorBackwardCompatibility() {
     // Clutter.Color and Clutter.ActorBox.
     let boxed = new Everything.TestBoxedB({ some_int8: 7, some_long: 5 });
 
-    assertEquals(7, boxed.some_int8);
-    assertEquals(5, boxed.some_long);
+    JSUnit.assertEquals(7, boxed.some_int8);
+    JSUnit.assertEquals(5, boxed.some_long);
 }
 
 function testVariantConstructor() {
     let str_variant = new GLib.Variant('s', 'mystring');
-    assertEquals('mystring', str_variant.get_string()[0]);
-    assertEquals('mystring', str_variant.deep_unpack());
+    JSUnit.assertEquals('mystring', str_variant.get_string()[0]);
+    JSUnit.assertEquals('mystring', str_variant.deep_unpack());
 
     let str_variant_old = GLib.Variant.new('s', 'mystring');
-    assertTrue(str_variant.equal(str_variant_old));
+    JSUnit.assertTrue(str_variant.equal(str_variant_old));
 
     let struct_variant = new GLib.Variant('(sogvau)',
                                          [ 'a string',
@@ -181,16 +177,17 @@ function testVariantConstructor() {
                                            new GLib.Variant('s', 'variant'),
                                            [ 7, 3 ]
                                          ]);
-    assertEquals(5, struct_variant.n_children());
+    JSUnit.assertEquals(5, struct_variant.n_children());
 
     let unpacked = struct_variant.deep_unpack();
-    assertEquals('a string', unpacked[0]);
-    assertEquals('/a/object/path', unpacked[1]);
-    assertEquals('asig', unpacked[2]);
-    assertTrue(unpacked[3] instanceof GLib.Variant);
-    assertEquals('variant', unpacked[3].deep_unpack());
-    assertTrue(unpacked[4] instanceof Array);
-    assertEquals(2, unpacked[4].length);
+    JSUnit.assertEquals('a string', unpacked[0]);
+    JSUnit.assertEquals('/a/object/path', unpacked[1]);
+    JSUnit.assertEquals('asig', unpacked[2]);
+    JSUnit.assertTrue(unpacked[3] instanceof GLib.Variant);
+    JSUnit.assertEquals('variant', unpacked[3].deep_unpack());
+    JSUnit.assertTrue(unpacked[4] instanceof Array);
+    JSUnit.assertEquals(2, unpacked[4].length);
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testGDBus.js b/installed-tests/test/js/testGDBus.js
similarity index 72%
rename from test/js/testGDBus.js
rename to installed-tests/test/js/testGDBus.js
index d973c17..53dc766 100644
--- a/test/js/testGDBus.js
+++ b/installed-tests/test/js/testGDBus.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Mainloop = imports.mainloop;
@@ -94,8 +95,8 @@ Test.prototype = {
         this._propWriteOnly = PROP_WRITE_ONLY_INITIAL_VALUE;
         this._propReadWrite = PROP_READ_WRITE_INITIAL_VALUE;
 
-       this._impl = Gio.DBusExportedObject.wrapJSObject(TestIface, this);
-       this._impl.export(Gio.DBus.session, '/org/gnome/gjs/Test');
+        this._impl = Gio.DBusExportedObject.wrapJSObject(TestIface, this);
+        this._impl.export(Gio.DBus.session, '/org/gnome/gjs/Test');
     },
 
     frobateStuff: function(args) {
@@ -176,7 +177,7 @@ Test.prototype = {
     /* This one is implemented asynchronously. Returns
      * the input arguments */
     echoAsync: function(parameters, invocation) {
-       var [someString, someInt] = parameters;
+        var [someString, someInt] = parameters;
         Mainloop.idle_add(function() {
             invocation.return_value(new GLib.Variant('(si)', [someString, someInt]));
             return false;
@@ -213,15 +214,15 @@ function testExportStuff() {
     new Test();
 
     own_name_id = Gio.DBus.session.own_name('org.gnome.gjs.Test',
-                                           Gio.BusNameOwnerFlags.NONE,
-                                           function(name) {
-                                               log("Acquired name " + name);
-                                               
-                                               Mainloop.quit('testGDBus');
-                                           },
-                                           function(name) {
-                                               log("Lost name " + name);
-                                           });
+                                            Gio.BusNameOwnerFlags.NONE,
+                                            function(name) {
+                                                log("Acquired name " + name);
+                                                
+                                                Mainloop.quit('testGDBus');
+                                            },
+                                            function(name) {
+                                                log("Lost name " + name);
+                                            });
 
     Mainloop.run('testGDBus');
 }
@@ -232,32 +233,32 @@ var proxy;
 function testInitStuff() {
     var theError;
     proxy = new ProxyClass(Gio.DBus.session,
-                          'org.gnome.gjs.Test',
-                          '/org/gnome/gjs/Test',
-                          function (obj, error) {
-                              theError = error;
-                              proxy = obj;
+                           'org.gnome.gjs.Test',
+                           '/org/gnome/gjs/Test',
+                           function (obj, error) {
+                               theError = error;
+                               proxy = obj;
 
-                              Mainloop.quit('testGDBus');
-                          });
+                               Mainloop.quit('testGDBus');
+                           });
 
     Mainloop.run('testGDBus');
 
-    assertNotNull(proxy);
-    assertNull(theError);
+    JSUnit.assertNotNull(proxy);
+    JSUnit.assertNull(theError);
 }
 
 function testFrobateStuff() {
     let theResult, theExcp;
     proxy.frobateStuffRemote({}, function(result, excp) {
-       [theResult] = result;
-       theExcp = excp;
-       Mainloop.quit('testGDBus');
+        [theResult] = result;
+        theExcp = excp;
+        Mainloop.quit('testGDBus');
     });
 
     Mainloop.run('testGDBus');
 
-    assertEquals("world", theResult.hello.deep_unpack());
+    JSUnit.assertEquals("world", theResult.hello.deep_unpack());
 }
 
 /* excp must be exactly the exception thrown by the remote method
@@ -265,15 +266,15 @@ function testFrobateStuff() {
 function testThrowException() {
     let theResult, theExcp;
     proxy.alwaysThrowExceptionRemote({}, function(result, excp) {
-       theResult = result;
-       theExcp = excp;
-       Mainloop.quit('testGDBus');
+        theResult = result;
+        theExcp = excp;
+        Mainloop.quit('testGDBus');
     });
 
     Mainloop.run('testGDBus');
 
-    assertNull(theResult);
-    assertNotNull(theExcp);
+    JSUnit.assertNull(theResult);
+    JSUnit.assertNotNull(theExcp);
 }
 
 /* We check that the exception in the answer is not null when we try to call
@@ -285,15 +286,15 @@ function testDoesNotExist() {
     delete Test.prototype.thisDoesNotExist;
 
     proxy.thisDoesNotExistRemote(function (result, excp) {
-       theResult = result;
-       theExcp = excp;
-       Mainloop.quit('testGDBus');
+        theResult = result;
+        theExcp = excp;
+        Mainloop.quit('testGDBus');
     });
 
     Mainloop.run('testGDBus');
 
-    assertNotNull(theExcp);
-    assertNull(theResult);
+    JSUnit.assertNotNull(theExcp);
+    JSUnit.assertNull(theResult);
 }
 
 function testNonJsonFrobateStuff() {
@@ -306,8 +307,8 @@ function testNonJsonFrobateStuff() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals("42 it is!", theResult);
-    assertNull(theExcp);
+    JSUnit.assertEquals("42 it is!", theResult);
+    JSUnit.assertNull(theExcp);
 }
 
 function testNoInParameter() {
@@ -320,8 +321,8 @@ function testNoInParameter() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals("Yes!", theResult);
-    assertNull(theExcp);
+    JSUnit.assertEquals("Yes!", theResult);
+    JSUnit.assertNull(theExcp);
 }
 
 function testMultipleInArgs() {
@@ -334,8 +335,8 @@ function testMultipleInArgs() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals("1 2 3 4 5", theResult);
-    assertNull(theExcp);
+    JSUnit.assertEquals("1 2 3 4 5", theResult);
+    JSUnit.assertNull(theExcp);
 }
 
 function testNoReturnValue() {
@@ -348,8 +349,8 @@ function testNoReturnValue() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals(undefined, theResult);
-    assertNull(theExcp);
+    JSUnit.assertEquals(undefined, theResult);
+    JSUnit.assertNull(theExcp);
 }
 
 function testEmitSignal() {
@@ -357,12 +358,12 @@ function testEmitSignal() {
     let signalReceived = 0;
     let signalArgument = null;
     let id = proxy.connectSignal('signalFoo',
-                                function(emitter, senderName, parameters) {
-                                    signalReceived ++;
-                                    [signalArgument] = parameters;
+                                 function(emitter, senderName, parameters) {
+                                     signalReceived ++;
+                                     [signalArgument] = parameters;
 
-                                    proxy.disconnectSignal(id);
-                                });
+                                     proxy.disconnectSignal(id);
+                                 });
     proxy.emitSignalRemote(function(result, excp) {
         [theResult] = result;
         theExcp = excp;
@@ -373,10 +374,10 @@ function testEmitSignal() {
 
     Mainloop.run('testGDBus');
 
-    assertUndefined('result should be undefined', theResult);
-    assertNull('no exception set', theExcp);
-    assertEquals('number of signals received', signalReceived, 1);
-    assertEquals('signal argument', signalArgument, "foobar");
+    JSUnit.assertUndefined('result should be undefined', theResult);
+    JSUnit.assertNull('no exception set', theExcp);
+    JSUnit.assertEquals('number of signals received', signalReceived, 1);
+    JSUnit.assertEquals('signal argument', signalArgument, "foobar");
 
 }
 
@@ -390,10 +391,10 @@ function testMultipleOutValues() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals("Hello", theResult[0]);
-    assertEquals("World", theResult[1]);
-    assertEquals("!", theResult[2]);
-    assertNull(theExcp);
+    JSUnit.assertEquals("Hello", theResult[0]);
+    JSUnit.assertEquals("World", theResult[1]);
+    JSUnit.assertEquals("!", theResult[2]);
+    JSUnit.assertNull(theExcp);
 }
 
 function testOneArrayOut() {
@@ -406,10 +407,10 @@ function testOneArrayOut() {
 
     Mainloop.run('testGDBus');
 
-    assertEquals("Hello", theResult[0]);
-    assertEquals("World", theResult[1]);
-    assertEquals("!", theResult[2]);
-    assertNull(theExcp);
+    JSUnit.assertEquals("Hello", theResult[0]);
+    JSUnit.assertEquals("World", theResult[1]);
+    JSUnit.assertEquals("!", theResult[2]);
+    JSUnit.assertNull(theExcp);
 }
 
 function testArrayOfArrayOut() {
@@ -425,13 +426,13 @@ function testArrayOfArrayOut() {
     let a1 = theResult[0];
     let a2 = theResult[1];
 
-    assertEquals("Hello", a1[0]);
-    assertEquals("World", a1[1]);
+    JSUnit.assertEquals("Hello", a1[0]);
+    JSUnit.assertEquals("World", a1[1]);
 
-    assertEquals("World", a2[0]);
-    assertEquals("Hello", a2[1]);;
+    JSUnit.assertEquals("World", a2[0]);
+    JSUnit.assertEquals("Hello", a2[1]);;
 
-    assertNull(theExcp);
+    JSUnit.assertNull(theExcp);
 }
 
 function testMultipleArrayOut() {
@@ -447,13 +448,13 @@ function testMultipleArrayOut() {
     let a1 = theResult[0];
     let a2 = theResult[1];
 
-    assertEquals("Hello", a1[0]);
-    assertEquals("World", a1[1]);
+    JSUnit.assertEquals("Hello", a1[0]);
+    JSUnit.assertEquals("World", a1[1]);
 
-    assertEquals("World", a2[0]);
-    assertEquals("Hello", a2[1]);;
+    JSUnit.assertEquals("World", a2[0]);
+    JSUnit.assertEquals("Hello", a2[1]);;
 
-    assertNull(theExcp);
+    JSUnit.assertNull(theExcp);
 }
 
 /* We are returning an array but the signature says it's an integer,
@@ -468,8 +469,8 @@ function testArrayOutBadSig() {
     });
 
     Mainloop.run('testGDBus');
-    assertNull(theResult);
-    assertNotNull(theExcp);
+    JSUnit.assertNull(theResult);
+    JSUnit.assertNotNull(theExcp);
 }
 
 function testAsyncImplementation() {
@@ -484,10 +485,10 @@ function testAsyncImplementation() {
                      });
 
     Mainloop.run('testGDBus');
-    assertNull(theExcp);
-    assertNotNull(theResult);
-    assertEquals(theResult[0], someString);
-    assertEquals(theResult[1], someInt);
+    JSUnit.assertNull(theExcp);
+    JSUnit.assertNotNull(theResult);
+    JSUnit.assertEquals(theResult[0], someString);
+    JSUnit.assertEquals(theResult[1], someInt);
 }
 
 function testBytes() {
@@ -503,9 +504,9 @@ function testBytes() {
         });
 
         Mainloop.run('testGDBus');
-        assertNull(theExcp);
-        assertNotNull(theResult);
-        assertEquals(someBytes[i], theResult);
+        JSUnit.assertNull(theExcp);
+        JSUnit.assertNotNull(theResult);
+        JSUnit.assertEquals(someBytes[i], theResult);
     }
 }
 
@@ -517,12 +518,12 @@ function testStructArray() {
         Mainloop.quit('testGDBus');
     });
     Mainloop.run('testGDBus');
-    assertNull(theExcp);
-    assertNotNull(theResult);
-    assertEquals(theResult[0][0], 128);
-    assertEquals(theResult[0][1], 123456);
-    assertEquals(theResult[1][0], 42);
-    assertEquals(theResult[1][1], 654321);
+    JSUnit.assertNull(theExcp);
+    JSUnit.assertNotNull(theResult);
+    JSUnit.assertEquals(theResult[0][0], 128);
+    JSUnit.assertEquals(theResult[0][1], 123456);
+    JSUnit.assertEquals(theResult[1][0], 42);
+    JSUnit.assertEquals(theResult[1][1], 654321);
 }
 
 function testDictSignatures() {
@@ -541,19 +542,19 @@ function testDictSignatures() {
     });
 
     Mainloop.run('testGDBus');
-    assertNull(theExcp);
-    assertNotNull(theResult);
+    JSUnit.assertNull(theExcp);
+    JSUnit.assertNotNull(theResult);
 
     // verify the fractional part was dropped off int
-    assertEquals(11, theResult['anInteger'].deep_unpack());
+    JSUnit.assertEquals(11, theResult['anInteger'].deep_unpack());
 
     // and not dropped off a double
-    assertEquals(10.5, theResult['aDoubleBeforeAndAfter'].deep_unpack());
+    JSUnit.assertEquals(10.5, theResult['aDoubleBeforeAndAfter'].deep_unpack());
 
-    // this assertion is useless, it will work
+    // this JSUnit.assertion is useless, it will work
     // anyway if the result is really an int,
     // but it at least checks we didn't lose data
-    assertEquals(10.0, theResult['aDouble'].deep_unpack());
+    JSUnit.assertEquals(10.0, theResult['aDouble'].deep_unpack());
 }
 
 function testFinalize() {
@@ -563,4 +564,5 @@ function testFinalize() {
     Gio.DBus.session.unown_name(own_name_id);
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testGIMarshalling.js b/installed-tests/test/js/testGIMarshalling.js
similarity index 100%
rename from test/js/testGIMarshalling.js
rename to installed-tests/test/js/testGIMarshalling.js
diff --git a/test/js/testGObjectClass.js b/installed-tests/test/js/testGObjectClass.js
similarity index 100%
rename from test/js/testGObjectClass.js
rename to installed-tests/test/js/testGObjectClass.js
diff --git a/installed-tests/test/js/testJS1_8.js b/installed-tests/test/js/testJS1_8.js
new file mode 100644
index 0000000..1cdb6b7
--- /dev/null
+++ b/installed-tests/test/js/testJS1_8.js
@@ -0,0 +1,54 @@
+// application/javascript;version=1.8
+
+// Test SpiderMonkey JS extensions; see
+// https://developer.mozilla.org/en/JavaScript/New_in_JavaScript/1.8
+
+// "const"
+const JSUnit = imports.jsUnit;
+const Everything = imports.gi.Regress;
+
+function testLet() {
+    // "let"
+    let foo = "bar";
+    let cow = "moo";
+
+    JSUnit.assertEquals(foo, "bar");
+}
+
+function testMultiReturn() {
+    // "destructuring bind"
+    let [y, z, q] = Everything.test_torture_signature_0(42, 'foo', 7);
+    JSUnit.assertEquals(z, 84);
+}
+
+function testYield() {
+    function fib() {
+        var i = 0, j = 1;
+        while (true) {
+            yield i;
+            var t = i;
+            i = j;
+            j += t;
+        }
+    }
+
+    var v = [];
+    var g = fib();
+    for (var i = 0; i < 10; i++) {
+        v.push(g.next());
+    }
+
+    JSUnit.assertEquals(v[0], 0);
+    JSUnit.assertEquals(v[1], 1);
+    JSUnit.assertEquals(v[2], 1);
+    JSUnit.assertEquals(v[3], 2);
+    JSUnit.assertEquals(v[4], 3);
+    JSUnit.assertEquals(v[5], 5);
+    JSUnit.assertEquals(v[6], 8);
+    JSUnit.assertEquals(v[7], 13);
+    JSUnit.assertEquals(v[8], 21);
+    JSUnit.assertEquals(v[9], 34);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testJSDefault.js b/installed-tests/test/js/testJSDefault.js
new file mode 100644
index 0000000..ac04312
--- /dev/null
+++ b/installed-tests/test/js/testJSDefault.js
@@ -0,0 +1,16 @@
+// Test that we *don't* get SpiderMonkey extensions; see
+// testJS1_8.js.
+// application/javascript;version=ECMAv3
+
+const JSUnit = imports.jsUnit;
+
+function testLet() {
+    JSUnit.assertRaises('missing ; before statement', function () { eval("let result = 1+1; result;") });
+}
+
+function testYield() {
+    JSUnit.assertRaises('missing ; before statement', function() { eval("function foo () { yield 42; }; 
foo();"); });
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testLang.js b/installed-tests/test/js/testLang.js
new file mode 100644
index 0000000..b649805
--- /dev/null
+++ b/installed-tests/test/js/testLang.js
@@ -0,0 +1,128 @@
+// application/javascript;version=1.8
+// tests for imports.lang module
+
+const JSUnit = imports.jsUnit;
+const Lang = imports.lang;
+
+function testCountProperties() {
+    var foo = { 'a' : 10, 'b' : 11 };
+    JSUnit.assertEquals("number of props", 2, Lang.countProperties(foo));
+}
+
+function testCopyProperties() {
+    var foo = { 'a' : 10, 'b' : 11 };
+    var bar = {};
+
+    Lang.copyProperties(foo, bar);
+
+    JSUnit.assertTrue("a in bar", ('a' in bar));
+    JSUnit.assertTrue("b in bar", ('b' in bar));
+    JSUnit.assertEquals("a is 10", 10, bar.a);
+    JSUnit.assertEquals("b is 11", 11, bar.b);
+    JSUnit.assertEquals("2 items in bar", 2, Lang.countProperties(bar));
+}
+
+function testCopyPublicProperties() {
+    var foo = { 'a' : 10, 'b' : 11, '_c' : 12 };
+    var bar = {};
+
+    Lang.copyPublicProperties(foo, bar);
+
+    JSUnit.assertTrue("a in bar", ('a' in bar));
+    JSUnit.assertTrue("b in bar", ('b' in bar));
+    JSUnit.assertFalse("_c in bar", ('_c' in bar));
+    JSUnit.assertEquals("a is 10", 10, bar.a);
+    JSUnit.assertEquals("b is 11", 11, bar.b);
+    JSUnit.assertEquals("2 items in bar", 2, Lang.countProperties(bar));
+}
+
+function testCopyGetterSetterProperties() {
+    var foo = {
+        'a' : 10,
+        'b' : 11,
+        get c() {
+            return this.a;
+        },
+        set c(n) {
+            this.a = n;
+        }};
+    var bar = {};
+
+    Lang.copyProperties(foo, bar);
+
+    let getterFunc = bar.__lookupGetter__("c");
+    let setterFunc = bar.__lookupSetter__("c");
+
+    // this should return the value of 'a'
+    let c = bar.c;
+
+    // this should set 'a' value
+    bar.c = 13;
+
+    JSUnit.assertTrue("bar has 'c' getter", (getterFunc != null));
+    JSUnit.assertTrue("bar has 'c' setter", (setterFunc != null));
+    JSUnit.assertTrue("bar 'c' value is 10", (c == 10));
+    JSUnit.assertTrue("bar 'a' new value is 13", (bar.a == 13));
+}
+
+function testBind() {
+
+    function Obj() {
+    }
+
+    Obj.prototype = {
+        callback: function() {
+            this.obj = this;
+            this.args = arguments;
+            return true;
+        }
+    };
+
+    let callback;
+
+    let o = new Obj();
+    callback = Lang.bind(o, o.callback);
+    JSUnit.assertEquals(callback(), true);
+    JSUnit.assertNotEquals("o.obj in callback", undefined, o.obj);
+    JSUnit.assertEquals("o.obj in callback", o, o.obj);
+    JSUnit.assertEquals("o.args in callback", 0, o.args.length);
+    JSUnit.assertRaises(function() { return Lang.bind(o, undefined); });
+    JSUnit.assertRaises(function() { return Lang.bind(undefined, function() {}); });
+
+    let o2 = new Obj();
+    callback = Lang.bind(o2, o2.callback, 42, 1138);
+    JSUnit.assertEquals(callback(), true);
+    JSUnit.assertNotEquals("o2.args in callback", undefined, o2.args);
+    JSUnit.assertEquals("o2.args.length in callback", 2, o2.args.length);
+    JSUnit.assertEquals("o2.args[0] in callback", 42, o2.args[0]);
+    JSUnit.assertEquals("o2.args[1] in callback", 1138, o2.args[1]);
+
+    let o3 = new Obj();
+    callback = Lang.bind(o3, o3.callback, 42, 1138);
+    JSUnit.assertEquals(callback(1, 2, 3), true);
+    JSUnit.assertNotEquals("o3.args in callback", undefined, o3.args);
+    JSUnit.assertEquals("o3.args.length in callback", 5, o3.args.length);
+    JSUnit.assertEquals("o3.args[0] in callback", 1, o3.args[0]);
+    JSUnit.assertEquals("o3.args[1] in callback", 2, o3.args[1]);
+    JSUnit.assertEquals("o3.args[2] in callback", 3, o3.args[2]);
+    JSUnit.assertEquals("o3.args[3] in callback", 42, o3.args[3]);
+    JSUnit.assertEquals("o3.args[4] in callback", 1138, o3.args[4]);
+}
+
+function testDefineAccessorProperty() {
+    var obj = {};
+    var storage = 42;
+
+    JSUnit.assertEquals(obj.foo, undefined);
+
+    Lang.defineAccessorProperty(obj, 'foo',
+                                function () { return storage; },
+                                function (val) { storage = val; });
+
+    JSUnit.assertEquals(obj.foo, 42);
+    obj.foo = 43;
+    JSUnit.assertEquals(obj.foo, 43);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testLocale.js b/installed-tests/test/js/testLocale.js
similarity index 63%
rename from test/js/testLocale.js
rename to installed-tests/test/js/testLocale.js
index 0b4f58f..ddd07b1 100644
--- a/test/js/testLocale.js
+++ b/installed-tests/test/js/testLocale.js
@@ -1,5 +1,6 @@
 // application/javascript;version=1.8
 // tests for JS_SetLocaleCallbacks().
+const JSUnit = imports.jsUnit;
 
 function testToLocaleDateString() {
     let date = new Date();
@@ -11,35 +12,36 @@ function testToLocaleDateString() {
 }
 
 function testToLocaleLowerCase() {
-    assertEquals("aaa", "AAA".toLocaleLowerCase());
+    JSUnit.assertEquals("aaa", "AAA".toLocaleLowerCase());
 
     // String conversion is implemented internally to GLib,
     // and is more-or-less independent of locale. (A few
     // characters are handled specially for a few locales,
     // like i in Turkish. But not A WITH ACUTE)
-    assertEquals("\u00e1", "\u00c1".toLocaleLowerCase());
+    JSUnit.assertEquals("\u00e1", "\u00c1".toLocaleLowerCase());
 
     // Unpaired surrogate, can't be converted to UTF-8
-    assertRaises(function() { "\ud800".toLocaleLowerCase(); });
+    JSUnit.assertRaises(function() { "\ud800".toLocaleLowerCase(); });
 }
 
 function testToLocaleUpperCase() {
-    assertEquals("AAA", "aaa".toLocaleUpperCase());
-    assertEquals("\u00c1", "\u00e1".toLocaleUpperCase());
-    assertRaises(function() { "\ud800".toLocaleUpperCase(); });
+    JSUnit.assertEquals("AAA", "aaa".toLocaleUpperCase());
+    JSUnit.assertEquals("\u00c1", "\u00e1".toLocaleUpperCase());
+    JSUnit.assertRaises(function() { "\ud800".toLocaleUpperCase(); });
 }
 
 function testToLocaleCompare() {
     // GLib calls out to libc for collation, so we can't really
     // assume anything - we could even be running in the
     // C locale. The below is pretty safe.
-    assertEquals(-1, "a".localeCompare("b"));
-    assertEquals( 0, "a".localeCompare("a"));
-    assertEquals( 1, "b".localeCompare("a"));
+    JSUnit.assertEquals(-1, "a".localeCompare("b"));
+    JSUnit.assertEquals( 0, "a".localeCompare("a"));
+    JSUnit.assertEquals( 1, "b".localeCompare("a"));
 
     // Again test error handling when conversion fails
     //assertRaises(function() { "\ud800".localeCompare("a"); });
     //assertRaises(function() { "a".localeCompare("\ud800"); });
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testMainloop.js b/installed-tests/test/js/testMainloop.js
similarity index 84%
rename from test/js/testMainloop.js
rename to installed-tests/test/js/testMainloop.js
index 09d22af..792e006 100644
--- a/test/js/testMainloop.js
+++ b/installed-tests/test/js/testMainloop.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
 const Mainloop = imports.mainloop;
 
 function testTimeout() {
@@ -34,9 +35,9 @@ function testTimeout() {
     Mainloop.run('testtimeout');
 
     with (trackTimeout) {
-        assertEquals("run ten times", 10, runTenTimes);
-        assertEquals("run only once", 1, runOnlyOnce);
-        assertEquals("never run", 0, neverRun);
+        JSUnit.assertEquals("run ten times", 10, runTenTimes);
+        JSUnit.assertEquals("run only once", 1, runOnlyOnce);
+        JSUnit.assertEquals("never run", 0, neverRun);
     }
 }
 
@@ -77,10 +78,10 @@ function testIdle() {
 
     Mainloop.run('foobar');
 
-    assertEquals("one-shot ran once", 1, trackIdles.runOnceCount);
-    assertEquals("two-shot ran twice", 2, trackIdles.runTwiceCount);
-    assertEquals("removed never ran", 0, trackIdles.neverRunsCount);
-    assertEquals("quit after many ran 11", 11, trackIdles.quitAfterManyRunsCount);
+    JSUnit.assertEquals("one-shot ran once", 1, trackIdles.runOnceCount);
+    JSUnit.assertEquals("two-shot ran twice", 2, trackIdles.runTwiceCount);
+    JSUnit.assertEquals("removed never ran", 0, trackIdles.neverRunsCount);
+    JSUnit.assertEquals("quit after many ran 11", 11, trackIdles.quitAfterManyRunsCount);
 
     // check re-entrancy of removing closures while they
     // are being invoked
@@ -102,4 +103,5 @@ function testIdle() {
                       });
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testMetaClass.js b/installed-tests/test/js/testMetaClass.js
similarity index 64%
rename from test/js/testMetaClass.js
rename to installed-tests/test/js/testMetaClass.js
index fd2df91..3ae3123 100644
--- a/test/js/testMetaClass.js
+++ b/installed-tests/test/js/testMetaClass.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8 -*- mode: js; indent-tabs-mode: nil -*-
+const JSUnit = imports.jsUnit;
 
 if (!('assertEquals' in this)) { /* allow running this test standalone */
     imports.lang.copyPublicProperties(imports.jsUnit, this);
@@ -8,9 +9,9 @@ if (!('assertEquals' in this)) { /* allow running this test standalone */
 const Lang = imports.lang;
 
 function assertArrayEquals(expected, got) {
-    assertEquals(expected.length, got.length);
+    JSUnit.assertEquals(expected.length, got.length);
     for (let i = 0; i < expected.length; i ++) {
-        assertEquals(expected[i], got[i]);
+        JSUnit.assertEquals(expected[i], got[i]);
     }
 }
 
@@ -84,43 +85,44 @@ function testMetaClass() {
                        'CustomMetaTwo',
                        'CustomMetaSubclass'], Subclassed);
 
-    assertTrue(NormalClass instanceof Lang.Class);
-    assertTrue(MetaClass instanceof Lang.Class);
+    JSUnit.assertTrue(NormalClass instanceof Lang.Class);
+    JSUnit.assertTrue(MetaClass instanceof Lang.Class);
 
-    assertTrue(CustomMetaOne instanceof Lang.Class);
-    assertTrue(CustomMetaOne instanceof MetaClass);
+    JSUnit.assertTrue(CustomMetaOne instanceof Lang.Class);
+    JSUnit.assertTrue(CustomMetaOne instanceof MetaClass);
 
-    assertEquals(2, CustomMetaTwo.DYNAMIC_CONSTANT);
-    assertUndefined(CustomMetaOne.DYNAMIC_CONSTANT);
+    JSUnit.assertEquals(2, CustomMetaTwo.DYNAMIC_CONSTANT);
+    JSUnit.assertUndefined(CustomMetaOne.DYNAMIC_CONSTANT);
 }
 
 function testMetaInstance() {
     let instanceOne = new CustomMetaOne();
 
-    assertEquals(1, instanceOne.one);
-    assertEquals(2, instanceOne.two);
+    JSUnit.assertEquals(1, instanceOne.one);
+    JSUnit.assertEquals(2, instanceOne.two);
 
-    assertRaises(function() {
+    JSUnit.assertRaises(function() {
         instanceOne.dynamic_method();
     });
 
     let instanceTwo = new CustomMetaTwo();
-    assertEquals(1, instanceTwo.one);
-    assertEquals(2, instanceTwo.two);
-    assertEquals(73, instanceTwo.dynamic_method());
+    JSUnit.assertEquals(1, instanceTwo.one);
+    JSUnit.assertEquals(2, instanceTwo.two);
+    JSUnit.assertEquals(73, instanceTwo.dynamic_method());
 }
 
 function testMetaSubclass() {
-    assertTrue(CustomMetaSubclass instanceof MetaClass);
+    JSUnit.assertTrue(CustomMetaSubclass instanceof MetaClass);
 
     let instance = new CustomMetaSubclass();
 
-    assertEquals(1, instance.one);
-    assertEquals(2, instance.two);
-    assertEquals(3, instance.three);
+    JSUnit.assertEquals(1, instance.one);
+    JSUnit.assertEquals(2, instance.two);
+    JSUnit.assertEquals(3, instance.three);
 
-    assertEquals(73, instance.dynamic_method());
-    assertEquals(2, CustomMetaSubclass.DYNAMIC_CONSTANT);
+    JSUnit.assertEquals(73, instance.dynamic_method());
+    JSUnit.assertEquals(2, CustomMetaSubclass.DYNAMIC_CONSTANT);
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testParamSpec.js b/installed-tests/test/js/testParamSpec.js
new file mode 100644
index 0000000..d75867b
--- /dev/null
+++ b/installed-tests/test/js/testParamSpec.js
@@ -0,0 +1,96 @@
+// application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
+
+const Regress = imports.gi.Regress;
+const GObject = imports.gi.GObject;
+
+let name = 'foo-property';
+let nick = 'Foo property';
+let blurb = 'This is the foo property';
+let flags = GObject.ParamFlags.READABLE;
+
+function testStringParamSpec() {
+    let stringSpec = GObject.ParamSpec.string(name, nick, blurb, flags,
+                                              'Default Value');
+
+    JSUnit.assertEquals(name, stringSpec.name);
+    JSUnit.assertEquals(nick, stringSpec._nick);
+    JSUnit.assertEquals(blurb, stringSpec._blurb);
+    JSUnit.assertEquals(flags, stringSpec.flags);
+    JSUnit.assertEquals('Default Value', stringSpec.default_value);
+}
+
+function testIntParamSpec() {
+    let intSpec = GObject.ParamSpec.int(name, nick, blurb, flags,
+                                        -100, 100, -42);
+
+    JSUnit.assertEquals(name, intSpec.name);
+    JSUnit.assertEquals(nick, intSpec._nick);
+    JSUnit.assertEquals(blurb, intSpec._blurb);
+    JSUnit.assertEquals(flags, intSpec.flags);
+    JSUnit.assertEquals(-42, intSpec.default_value);
+}
+
+function testUIntParamSpec() {
+    let uintSpec = GObject.ParamSpec.uint(name, nick, blurb, flags,
+                                          20, 100, 42);
+
+    JSUnit.assertEquals(name, uintSpec.name);
+    JSUnit.assertEquals(nick, uintSpec._nick);
+    JSUnit.assertEquals(blurb, uintSpec._blurb);
+    JSUnit.assertEquals(flags, uintSpec.flags);
+    JSUnit.assertEquals(42, uintSpec.default_value);
+}
+
+function testInt64ParamSpec() {
+    let int64Spec = GObject.ParamSpec.int64(name, nick, blurb, flags,
+                                            0x4000,
+                                            0xffffffff,
+                                            0x2266bbff);
+
+    JSUnit.assertEquals(name, int64Spec.name);
+    JSUnit.assertEquals(nick, int64Spec._nick);
+    JSUnit.assertEquals(blurb, int64Spec._blurb);
+    JSUnit.assertEquals(flags, int64Spec.flags);
+    JSUnit.assertEquals(0x2266bbff, int64Spec.default_value);
+}
+
+function testUInt64ParamSpec() {
+    let uint64Spec = GObject.ParamSpec.uint64(name, nick, blurb, flags,
+                                              0,
+                                              0xffffffff,
+                                              0x2266bbff);
+
+    JSUnit.assertEquals(name, uint64Spec.name);
+    JSUnit.assertEquals(nick, uint64Spec._nick);
+    JSUnit.assertEquals(blurb, uint64Spec._blurb);
+    JSUnit.assertEquals(flags, uint64Spec.flags);
+    JSUnit.assertEquals(0x2266bbff, uint64Spec.default_value);
+}
+
+function testEnumParamSpec() {
+    let enumSpec = GObject.ParamSpec.enum(name, nick, blurb, flags,
+                                          Regress.TestEnum,
+                                          Regress.TestEnum.VALUE2);
+
+    JSUnit.assertEquals(name, enumSpec.name);
+    JSUnit.assertEquals(nick, enumSpec._nick);
+    JSUnit.assertEquals(blurb, enumSpec._blurb);
+    JSUnit.assertEquals(flags, enumSpec.flags);
+    JSUnit.assertEquals(Regress.TestEnum.VALUE2, enumSpec.default_value);
+}
+
+function testFlagsParamSpec() {
+    let flagsSpec = GObject.ParamSpec.flags(name, nick, blurb, flags,
+                                            Regress.TestFlags,
+                                            Regress.TestFlags.FLAG2);
+
+    JSUnit.assertEquals(name, flagsSpec.name);
+    JSUnit.assertEquals(nick, flagsSpec._nick);
+    JSUnit.assertEquals(blurb, flagsSpec._blurb);
+    JSUnit.assertEquals(flags, flagsSpec.flags);
+    JSUnit.assertEquals(Regress.TestFlags.FLAG2, flagsSpec.default_value);
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testSignals.js b/installed-tests/test/js/testSignals.js
similarity index 75%
rename from test/js/testSignals.js
rename to installed-tests/test/js/testSignals.js
index d1f7aa3..e0f4c83 100644
--- a/test/js/testSignals.js
+++ b/installed-tests/test/js/testSignals.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
 const Signals = imports.signals;
 
 function Foo() {
@@ -20,14 +21,14 @@ function testSimple() {
                              theFoo.b = b;
                          });
     foo.emit('bar', "This is a", "This is b");
-    assertEquals("This is a", foo.a);
-    assertEquals("This is b", foo.b);
+    JSUnit.assertEquals("This is a", foo.a);
+    JSUnit.assertEquals("This is b", foo.b);
     foo.disconnect(id);
     // this emission should do nothing
     foo.emit('bar', "Another a", "Another b");
     // so these values should be unchanged
-    assertEquals("This is a", foo.a);
-    assertEquals("This is b", foo.b);
+    JSUnit.assertEquals("This is a", foo.a);
+    JSUnit.assertEquals("This is b", foo.b);
 }
 
 function testDisconnectDuringEmit() {
@@ -58,7 +59,7 @@ function testDisconnectDuringEmit() {
     foo.disconnect(firstId);
 
     // poke in private implementation to sanity-check
-    assertEquals('no handlers left', 0, foo._signalConnections.length);
+    JSUnit.assertEquals('no handlers left', 0, foo._signalConnections.length);
 }
 
 function testMultipleSignals() {
@@ -80,18 +81,18 @@ function testMultipleSignals() {
                 });
     foo.emit('bar');
 
-    assertEquals(2, foo.barHandlersCalled);
-    assertEquals(0, foo.bonkHandlersCalled);
+    JSUnit.assertEquals(2, foo.barHandlersCalled);
+    JSUnit.assertEquals(0, foo.bonkHandlersCalled);
 
     foo.emit('bonk');
 
-    assertEquals(2, foo.barHandlersCalled);
-    assertEquals(1, foo.bonkHandlersCalled);
+    JSUnit.assertEquals(2, foo.barHandlersCalled);
+    JSUnit.assertEquals(1, foo.bonkHandlersCalled);
 
     foo.emit('bar');
 
-    assertEquals(4, foo.barHandlersCalled);
-    assertEquals(1, foo.bonkHandlersCalled);
+    JSUnit.assertEquals(4, foo.barHandlersCalled);
+    JSUnit.assertEquals(1, foo.bonkHandlersCalled);
 
     foo.disconnectAll();
 
@@ -99,8 +100,8 @@ function testMultipleSignals() {
     foo.emit('bar');
     foo.emit('bonk');
 
-    assertEquals(4, foo.barHandlersCalled);
-    assertEquals(1, foo.bonkHandlersCalled);
+    JSUnit.assertEquals(4, foo.barHandlersCalled);
+    JSUnit.assertEquals(1, foo.bonkHandlersCalled);
 }
 
 function testExceptionInCallback() {
@@ -120,13 +121,14 @@ function testExceptionInCallback() {
 
     // exception in callback does not effect other callbacks
     foo.emit('bar');
-    assertEquals(1, foo.bar1Called);
-    assertEquals(1, foo.bar2Called);
+    JSUnit.assertEquals(1, foo.bar1Called);
+    JSUnit.assertEquals(1, foo.bar2Called);
 
     // exception in callback does not disconnect the callback
     foo.emit('bar');
-    assertEquals(2, foo.bar1Called);
-    assertEquals(2, foo.bar2Called);
+    JSUnit.assertEquals(2, foo.bar1Called);
+    JSUnit.assertEquals(2, foo.bar2Called);
 }
 
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testSystem.js b/installed-tests/test/js/testSystem.js
new file mode 100644
index 0000000..f87a325
--- /dev/null
+++ b/installed-tests/test/js/testSystem.js
@@ -0,0 +1,15 @@
+// application/javascript;version=1.8
+
+const JSUnit = imports.jsUnit;
+const System = imports.system;
+
+function testAddressOf() {
+    let o1 = new Object();
+    let o2 = new Object();
+
+    JSUnit.assert(System.addressOf(o1) == System.addressOf(o1));
+    JSUnit.assert(System.addressOf(o1) != System.addressOf(o2));
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/test/js/testTweener.js b/installed-tests/test/js/testTweener.js
similarity index 82%
rename from test/js/testTweener.js
rename to installed-tests/test/js/testTweener.js
index 6761875..72c3f93 100644
--- a/test/js/testTweener.js
+++ b/installed-tests/test/js/testTweener.js
@@ -1,4 +1,5 @@
 // application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
 const Tweener = imports.tweener.tweener;
 const Mainloop = imports.mainloop;
 
@@ -60,13 +61,13 @@ function testSimpleTween() {
     Mainloop.run('testTweener');
 
     with (objectA) {
-        assertEquals("A: x coordinate", 10, x);
-        assertEquals("A: y coordinate", 10, y);
+        JSUnit.assertEquals("A: x coordinate", 10, x);
+        JSUnit.assertEquals("A: y coordinate", 10, y);
     }
 
     with (objectB) {
-        assertEquals("B: x coordinate", 5, x);
-        assertEquals("B: y coordinate", 5, y);
+        JSUnit.assertEquals("B: x coordinate", 5, x);
+        JSUnit.assertEquals("B: y coordinate", 5, y);
     }
 }
 
@@ -92,9 +93,9 @@ function testOnFunctions() {
     Mainloop.run('testOnFunctions');
 
     with (object) {
-        assertEquals("onStart was run", true, start);
-        assertEquals("onUpdate was run", true, update);
-        assertEquals("onComplete was run", true, complete);
+        JSUnit.assertEquals("onStart was run", true, start);
+        JSUnit.assertEquals("onUpdate was run", true, update);
+        JSUnit.assertEquals("onComplete was run", true, complete);
     }
 }
 
@@ -116,7 +117,7 @@ function testPause() {
     Tweener.addTween(objectB, { bar: 100, time: 0.1,
                                onComplete: function() { Mainloop.quit('testPause');}});
     Tweener.pauseTweens(objectA);
-    assertEquals(false, Tweener.pauseTweens(objectB, "quux")); // This should do nothing
+    JSUnit.assertEquals(false, Tweener.pauseTweens(objectB, "quux")); // This should do nothing
 
     /* Pause and resume should be equal to doing nothing */
     Tweener.pauseTweens(objectC, "baaz");
@@ -125,15 +126,15 @@ function testPause() {
     Mainloop.run('testPause');
 
     with (objectA) {
-        assertEquals(0, foo);
+        JSUnit.assertEquals(0, foo);
     }
 
     with (objectB) {
-        assertEquals(100, bar);
+        JSUnit.assertEquals(100, bar);
     }
 
     with (objectC) {
-        assertEquals(100, baaz);
+        JSUnit.assertEquals(100, baaz);
     }
 }
 
@@ -154,9 +155,9 @@ function testRemoveTweens() {
     Mainloop.run('testRemoveTweens');
 
     with (object) {
-        assertEquals(50, foo);
-        assertEquals(0, bar);
-        assertEquals(0, baaz);
+        JSUnit.assertEquals(50, foo);
+        JSUnit.assertEquals(0, bar);
+        JSUnit.assertEquals(0, baaz);
     }
 }
 
@@ -187,11 +188,11 @@ function testConcurrent() {
     Mainloop.run('testConcurrent');
 
     with (objectA) {
-        assertEquals(0, foo);
+        JSUnit.assertEquals(0, foo);
     }
 
     with (objectB) {
-        assertEquals(150, bar);
+        JSUnit.assertEquals(150, bar);
     }
 }
 
@@ -217,11 +218,11 @@ function testPauseAllResumeAll() {
     Mainloop.run('testPauseAllResumeAll');
 
     with (objectA) {
-        assertEquals(100, foo);
+        JSUnit.assertEquals(100, foo);
     }
 
     with (objectB) {
-        assertEquals(100, bar);
+        JSUnit.assertEquals(100, bar);
     }
 }
 
@@ -240,8 +241,8 @@ function testRemoveAll() {
 
     Mainloop.timeout_add(200,
                         function () {
-                            assertEquals(0, objectA.foo);
-                            assertEquals(0, objectB.bar);
+                            JSUnit.assertEquals(0, objectA.foo);
+                            JSUnit.assertEquals(0, objectB.bar);
                             Mainloop.quit('testRemoveAll');
                             return false;
                         });
@@ -258,7 +259,7 @@ function testImmediateTween() {
     Tweener.addTween(object, { foo: 200, time: 0.1,
                                onStart: function () {
                                    /* The immediate tween should set it to 50 before we run */
-                                   assertEquals(50, object.foo);
+                                   JSUnit.assertEquals(50, object.foo);
                                },
                                onComplete: function () {
                                    Mainloop.quit('testImmediateTween');
@@ -267,7 +268,7 @@ function testImmediateTween() {
     Mainloop.run('testImmediateTween');
 
     with (object) {
-        assertEquals(200, foo);
+        JSUnit.assertEquals(200, foo);
     }
 }
 
@@ -288,7 +289,7 @@ function testAddCaller() {
     Mainloop.run('testAddCaller');
 
     with (object) {
-        assertEquals(10, foo);
+        JSUnit.assertEquals(10, foo);
     }
 }
 
@@ -300,26 +301,26 @@ function testGetTweenCount() {
         quux: 0
     };
 
-    assertEquals(0, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(0, Tweener.getTweenCount(object));
 
     Tweener.addTween(object, { foo: 100, time: 0.1 });
-    assertEquals(1, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(1, Tweener.getTweenCount(object));
     Tweener.addTween(object, { bar: 100, time: 0.1 });
-    assertEquals(2, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(2, Tweener.getTweenCount(object));
     Tweener.addTween(object, { baaz: 100, time: 0.1 });
-    assertEquals(3, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(3, Tweener.getTweenCount(object));
     Tweener.addTween(object, { quux: 100, time: 0.1,
                                onComplete: function () {
                                    Mainloop.quit('testGetTweenCount');}});
-    assertEquals(4, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(4, Tweener.getTweenCount(object));
 
     Tweener.removeTweens(object, "bar", "baaz");
 
-    assertEquals(2, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(2, Tweener.getTweenCount(object));
 
     Mainloop.run('testGetTweenCount');
 
-    assertEquals(0, Tweener.getTweenCount(object));
+    JSUnit.assertEquals(0, Tweener.getTweenCount(object));
 }
 
 Tweener.registerSpecialProperty(
@@ -341,8 +342,8 @@ function testSpecialProperty() {
     Mainloop.run('testSpecialProperty');
 
     with (objectA) {
-        assertEquals("A: x coordinate", -10, x);
-        assertEquals("A: y coordinate", 10, y);
+        JSUnit.assertEquals("A: x coordinate", -10, x);
+        JSUnit.assertEquals("A: y coordinate", 10, y);
     }
 }
 
@@ -378,10 +379,10 @@ function testSpecialPropertyModifier() {
     Mainloop.run('testSpecialPropertyModifier');
 
     with (objectA) {
-        assertEquals("A: x coordinate", 10, x);
-        assertEquals("A: y coordinate", 10, y);
-        assertEquals("A: x was fractional", false, xFraction);
-        assertEquals("A: y was fractional", true, yFraction);
+        JSUnit.assertEquals("A: x coordinate", 10, x);
+        JSUnit.assertEquals("A: y coordinate", 10, y);
+        JSUnit.assertEquals("A: x was fractional", false, xFraction);
+        JSUnit.assertEquals("A: y was fractional", true, yFraction);
     }
 }
 
@@ -404,11 +405,12 @@ function testSpecialPropertySplitter() {
     Mainloop.run('testSpecialPropertySplitter');
 
     with (objectA) {
-        assertEquals("A: x coordinate", 10, x);
-        assertEquals("A: y coordinate", -10, y);
+        JSUnit.assertEquals("A: x coordinate", 10, x);
+        JSUnit.assertEquals("A: y coordinate", -10, y);
     }
 }
 
 installFrameTicker();
-gjstestRun();
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
 
diff --git a/installed-tests/test/js/testUnicode.js b/installed-tests/test/js/testUnicode.js
new file mode 100644
index 0000000..4d43b07
--- /dev/null
+++ b/installed-tests/test/js/testUnicode.js
@@ -0,0 +1,14 @@
+// application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
+
+function testUnicode() {
+    JSUnit.assertEquals(6, 'Погода'.length);
+    JSUnit.assertEquals(1055, 'Погода'.charCodeAt(0));
+    JSUnit.assertEquals(1086, 'Погода'.charCodeAt(3));
+    JSUnit.assertEquals("\u65e5", "日本語".charAt(0));
+    JSUnit.assertEquals("\u672c", "日本語".charAt(1));
+    JSUnit.assertEquals("\u8a9e", "日本語".charAt(2));
+}
+
+JSUnit.gjstestRun(this, JSUnit.setUp, JSUnit.tearDown);
+
diff --git a/installed-tests/test/js/testself.js b/installed-tests/test/js/testself.js
new file mode 100644
index 0000000..4da9690
--- /dev/null
+++ b/installed-tests/test/js/testself.js
@@ -0,0 +1,38 @@
+// application/javascript;version=1.8
+const JSUnit = imports.jsUnit;
+
+var someUndefined;
+var someNumber = 1;
+var someOtherNumber = 42;
+var someString = "hello";
+var someOtherString = "world";
+
+JSUnit.assert(true);
+JSUnit.assertTrue(true);
+JSUnit.assertFalse(false);
+
+JSUnit.assertEquals(someNumber, someNumber);
+JSUnit.assertEquals(someString, someString);
+
+JSUnit.assertNotEquals(someNumber, someOtherNumber);
+JSUnit.assertNotEquals(someString, someOtherString);
+
+JSUnit.assertNull(null);
+JSUnit.assertNotNull(someNumber);
+JSUnit.assertUndefined(someUndefined);
+JSUnit.assertNotUndefined(someNumber);
+JSUnit.assertNaN(0/0);
+JSUnit.assertNotNaN(someNumber);
+
+// test assertRaises()
+JSUnit.assertRaises(function() { throw new Object(); });
+try {   // calling assertRaises with non-function is an error, not assertion failure
+    JSUnit.assertRaises(true);
+} catch(e) {
+    JSUnit.assertUndefined(e.isJsUnitException);
+}
+try {   // function not throwing an exception is assertion failure
+    JSUnit.assertRaises(function() { return true; });
+} catch(e) {
+    JSUnit.assertTrue(e.isJsUnitException);
+}
diff --git a/test/unittest.gdb b/installed-tests/test/unittest.gdb
similarity index 100%
rename from test/unittest.gdb
rename to installed-tests/test/unittest.gdb


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]