Add some structure for interactive tests of UI components

js/ui/environment.js: Split out initial UI setup (Tweener initialization,
  ClutterContainer monkey-patching) into a separate file we can import from tests.

tests/: Directory for various types of tests
tests/run-test.sh: Shell script that to run tests with an appropriate
  environment set up.

tests/testcommon/: Common modules and data for tests
tests/interactive/: Interactive tests

tests/interactive/box-layout.js: A sample test of StLayout

https://bugzilla.gnome.org/show_bug.cgi?id=595987
This commit is contained in:
Owen W. Taylor 2009-09-18 15:51:15 -04:00
parent ed07413c20
commit b18a8ebcae
11 changed files with 170 additions and 25 deletions

1
.gitignore vendored
View File

@ -39,4 +39,5 @@ src/gnome-shell
src/test-recorder src/test-recorder
src/test-recorder.ogg src/test-recorder.ogg
stamp-h1 stamp-h1
tests/run-test.sh
xmldocs.make xmldocs.make

View File

@ -1,4 +1,4 @@
SUBDIRS = data js src po SUBDIRS = data js src tests po
EXTRA_DIST = \ EXTRA_DIST = \
.project \ .project \

View File

@ -129,5 +129,6 @@ AC_OUTPUT([
js/misc/Makefile js/misc/Makefile
js/ui/Makefile js/ui/Makefile
src/Makefile src/Makefile
tests/Makefile
po/Makefile.in po/Makefile.in
]) ])

View File

@ -9,6 +9,7 @@ dist_jsui_DATA = \
dash.js \ dash.js \
dnd.js \ dnd.js \
docDisplay.js \ docDisplay.js \
environment.js \
genericDisplay.js \ genericDisplay.js \
lightbox.js \ lightbox.js \
link.js \ link.js \

32
js/ui/environment.js Normal file
View File

@ -0,0 +1,32 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const St = imports.gi.St;
const Tweener = imports.ui.tweener;
// "monkey patch" in some varargs ClutterContainer methods; we need
// to do this per-container class since there is no representation
// of interfaces in Javascript
function _patchContainerClass(containerClass) {
// This one is a straightforward mapping of the C method
containerClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor);
for (prop in props)
meta[prop] = props[prop];
};
// clutter_container_add() actually is a an add-many-actors
// method. We conveniently, but somewhat dubiously, take the
// this opportunity to make it do something more useful.
containerClass.prototype.add = function(actor, props) {
this.add_actor(actor);
if (props)
this.child_set(actor, props);
};
}
_patchContainerClass(St.BoxLayout);
function init() {
Tweener.init();
}

View File

@ -13,13 +13,13 @@ const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Chrome = imports.ui.chrome; const Chrome = imports.ui.chrome;
const Environment = imports.ui.environment;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
const RunDialog = imports.ui.runDialog; const RunDialog = imports.ui.runDialog;
const LookingGlass = imports.ui.lookingGlass; const LookingGlass = imports.ui.lookingGlass;
const ShellDBus = imports.ui.shellDBus; const ShellDBus = imports.ui.shellDBus;
const Sidebar = imports.ui.sidebar; const Sidebar = imports.ui.sidebar;
const Tweener = imports.ui.tweener;
const WindowManager = imports.ui.windowManager; const WindowManager = imports.ui.windowManager;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
@ -37,28 +37,6 @@ let shellDBusService = null;
let modalCount = 0; let modalCount = 0;
let modalActorFocusStack = []; let modalActorFocusStack = [];
// "monkey patch" in some varargs ClutterContainer methods; we need
// to do this per-container class since there is no representation
// of interfaces in Javascript
function _patchContainerClass(containerClass) {
// This one is a straightforward mapping of the C method
containerClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor);
for (prop in props)
meta[prop] = props[prop];
};
// clutter_container_add() actually is a an add-many-actors
// method. We conveniently, but somewhat dubiously, take the
// this opportunity to make it do something more useful.
containerClass.prototype.add = function(actor, props) {
this.add_actor(actor);
if (props)
this.child_set(actor, props);
};
}
_patchContainerClass(St.BoxLayout);
function start() { function start() {
// Add a binding for "global" in the global JS namespace; (gjs // Add a binding for "global" in the global JS namespace; (gjs
// keeps the web browser convention of having that namespace be // keeps the web browser convention of having that namespace be
@ -75,7 +53,7 @@ function start() {
// back into sync ones. // back into sync ones.
DBus.session.flush(); DBus.session.flush();
Tweener.init(); Environment.init();
// Ensure ShellAppMonitor is initialized; this will // Ensure ShellAppMonitor is initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem // also initialize ShellAppSystem first. ShellAppSystem

20
tests/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
noinst_SCRIPTS = run-test.sh
EXTRA_DIST = run-test.sh.in
TEST_JS = \
testcommon/ui.js \
interactive/box-layout.js
EXTRA_DIST += $(TEST_JS)
TEST_MISC = \
testcommon/test.css
EXTRA_DIST += $(TEST_MISC)
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
run-test.sh: run-test.sh.in
$(AM_V_GEN) sed \
-e "s|@GJS_JS_DIR[@]|$(GJS_JS_DIR)|" \
-e "s|@GJS_JS_NATIVE_DIR[@]|$(GJS_JS_NATIVE_DIR)|" \
-e "s|@srcdir[@]|$(srcdir)|" \
$< > $@ && chmod a+x $@

View File

@ -0,0 +1,39 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const UI = imports.testcommon.ui;
UI.init();
let stage = Clutter.Stage.get_default();
let b = new St.BoxLayout({ vertical: true,
width: stage.width,
height: stage.height });
stage.add_actor(b);
let b2 = new St.BoxLayout();
b.add(b2, { expand: true, fill: true });
let r1 = new St.BoxLayout({ style_class: 'red',
width: 10,
height: 10 });
b2.add(r1, { expand: true });
let r2 = new St.BoxLayout({ style_class: 'green',
width: 10,
height: 10 });
b2.add(r2, { expand: true,
x_fill: false,
x_align: St.Align.MIDDLE,
y_fill: false,
y_align: St.Align.MIDDLE });
let r3 = new St.BoxLayout({ style_class: 'blue',
width: 10,
height: 10 });
b.add(r3);
stage.show();
Clutter.main();

44
tests/run-test.sh.in Normal file
View File

@ -0,0 +1,44 @@
#!/bin/sh
usage() {
echo >&2 "Usage run-test.sh [-v|--verbose] <test_js>..."
exit 1
}
tests=
verbose=false
for arg in $@ ; do
case $arg in
-v|--verbose)
verbose=true
;;
-*)
usage
;;
*)
tests="$tests $arg"
;;
esac
done
builddir=`dirname $0`
builddir=`cd $builddir && pwd`
srcdir=$builddir/@srcdir@
srcdir=`cd $srcdir && pwd`
GI_TYPELIB_PATH="$builddir/../src"
GJS_DEBUG_OUTPUT=stderr
$verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"
GNOME_SHELL_TESTSDIR="$srcdir/"
LD_PRELOAD="$builddir/../src/.libs/libgnome-shell.so"
export GI_TYPELIB_PATH GJS_DEBUG_OUTPUT GJS_DEBUG_TOPICS GNOME_SHELL_JS GNOME_SHELL_TESTSDIR LD_PRELOAD
gjs_args=
for i in $srcdir $srcdir/../js @GJS_JS_DIR@ @GJS_JS_NATIVE_DIR@ ; do
gjs_args="$gjs_args -I $i"
done
for test in $tests ; do
gjs-console $gjs_args $test || exit $?
done

13
tests/testcommon/test.css Normal file
View File

@ -0,0 +1,13 @@
@import "../../data/gnome-shell.css";
*.red {
background-color: red;
}
*.green {
background-color: green;
}
*.blue {
background-color: blue;
}

16
tests/testcommon/ui.js Normal file
View File

@ -0,0 +1,16 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const St = imports.gi.St;
const Environment = imports.ui.environment;
function init() {
Clutter.init(null, null);
Environment.init();
let style = St.Style.get_default();
let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css";
style.load_from_file(stylesheetPath);
}