summaryrefslogtreecommitdiff
path: root/installed-tests
diff options
context:
space:
mode:
authorFlorian Müllner <fmuellner@gnome.org>2020-04-16 03:15:43 +0200
committerFlorian Müllner <fmuellner@gnome.org>2020-04-16 19:55:22 +0200
commit0db7f3a1e464e8bbc2b27feb24bc48b8ee49a1ba (patch)
tree11328d7ce1ac6135b5242ec6d08c03b68d9fd052 /installed-tests
parent4644ea7072ae467b701fcf2e01c805b91b3a303c (diff)
downloadgjs-0db7f3a1e464e8bbc2b27feb24bc48b8ee49a1ba.tar.gz
installed-tests: Test both GTK3 and GTK4
The GTK4 tests are a copy of the existing tests with mostly minor changes to adapt to API changes. The notably exception are dropped tests for GdkAtom and container child properties, as those are no longer present in GTK4.
Diffstat (limited to 'installed-tests')
-rw-r--r--installed-tests/js/complex3.ui (renamed from installed-tests/js/complex.ui)0
-rw-r--r--installed-tests/js/complex4.ui26
-rw-r--r--installed-tests/js/jsunit.gresources.xml3
-rw-r--r--installed-tests/js/meson.build6
-rw-r--r--installed-tests/js/testGtk3.js (renamed from installed-tests/js/testGtk.js)4
-rw-r--r--installed-tests/js/testGtk4.js195
-rw-r--r--installed-tests/js/testLegacyGtk.js2
7 files changed, 231 insertions, 5 deletions
diff --git a/installed-tests/js/complex.ui b/installed-tests/js/complex3.ui
index b5136fbc..b5136fbc 100644
--- a/installed-tests/js/complex.ui
+++ b/installed-tests/js/complex3.ui
diff --git a/installed-tests/js/complex4.ui b/installed-tests/js/complex4.ui
new file mode 100644
index 00000000..f355785a
--- /dev/null
+++ b/installed-tests/js/complex4.ui
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="Gjs_MyComplexGtkSubclassFromResource" parent="GtkGrid">
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="margin_start">10</property>
+ <property name="margin_end">10</property>
+ <child>
+ <object class="GtkLabel" id="label-child">
+ <property name="label">Complex!</property>
+ <signal name="copy-clipboard" handler="templateCallback" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label-child2">
+ <property name="label">Complex as well!</property>
+ <signal name="copy-clipboard" handler="boundCallback" object="label-child" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="internal-label-child">
+ <property name="label">Complex and internal!</property>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/installed-tests/js/jsunit.gresources.xml b/installed-tests/js/jsunit.gresources.xml
index 21002005..e0060c8c 100644
--- a/installed-tests/js/jsunit.gresources.xml
+++ b/installed-tests/js/jsunit.gresources.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gjs/jsunit">
- <file preprocess="xml-stripblanks">complex.ui</file>
+ <file preprocess="xml-stripblanks">complex3.ui</file>
+ <file preprocess="xml-stripblanks">complex4.ui</file>
<file>jasmine.js</file>
<file>minijasmine.js</file>
<file>modules/alwaysThrows.js</file>
diff --git a/installed-tests/js/meson.build b/installed-tests/js/meson.build
index 79ac4633..9c424418 100644
--- a/installed-tests/js/meson.build
+++ b/installed-tests/js/meson.build
@@ -122,10 +122,14 @@ endif
if not get_option('skip_gtk_tests')
jasmine_tests += [
- 'Gtk',
+ 'Gtk3',
'GObjectDestructionAccess',
'LegacyGtk',
]
+
+ if have_gtk4
+ jasmine_tests += 'Gtk4'
+ endif
endif
installed_js_tests_dir = installed_tests_execdir / 'js'
diff --git a/installed-tests/js/testGtk.js b/installed-tests/js/testGtk3.js
index c7200c27..288bdbdc 100644
--- a/installed-tests/js/testGtk.js
+++ b/installed-tests/js/testGtk3.js
@@ -65,7 +65,7 @@ MyComplexGtkSubclass.prototype.testChildrenExist = function () {
};
const MyComplexGtkSubclassFromResource = GObject.registerClass({
- Template: 'resource:///org/gjs/jsunit/complex.ui',
+ Template: 'resource:///org/gjs/jsunit/complex3.ui',
Children: ['label-child', 'label-child2'],
InternalChildren: ['internal-label-child'],
}, class MyComplexGtkSubclassFromResource extends Gtk.Grid {
@@ -187,7 +187,7 @@ describe('Gtk overrides', function () {
w.destroy();
System.gc();
- GLib.test_assert_expected_messages_internal('Gjs', 'testGtk.js', 0,
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGtk3.js', 0,
'Gtk overrides avoid crashing and print a stack trace');
});
diff --git a/installed-tests/js/testGtk4.js b/installed-tests/js/testGtk4.js
new file mode 100644
index 00000000..a9cff2ad
--- /dev/null
+++ b/installed-tests/js/testGtk4.js
@@ -0,0 +1,195 @@
+imports.gi.versions.Gtk = '4.0';
+
+const ByteArray = imports.byteArray;
+const {GLib, Gio, GObject, Gtk} = imports.gi;
+const System = imports.system;
+
+// This is ugly here, but usually it would be in a resource
+function createTemplate(className) {
+ return `
+<interface>
+ <template class="${className}" parent="GtkGrid">
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="margin_start">10</property>
+ <property name="margin_end">10</property>
+ <child>
+ <object class="GtkLabel" id="label-child">
+ <property name="label">Complex!</property>
+ <signal name="copy-clipboard" handler="templateCallback" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label-child2">
+ <property name="label">Complex as well!</property>
+ <signal name="copy-clipboard" handler="boundCallback" object="label-child" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="internal-label-child">
+ <property name="label">Complex and internal!</property>
+ </object>
+ </child>
+ </template>
+</interface>`;
+}
+
+const MyComplexGtkSubclass = GObject.registerClass({
+ Template: ByteArray.fromString(createTemplate('Gjs_MyComplexGtkSubclass')),
+ Children: ['label-child', 'label-child2'],
+ InternalChildren: ['internal-label-child'],
+ CssName: 'complex-subclass',
+}, class MyComplexGtkSubclass extends Gtk.Grid {
+ templateCallback(widget) {
+ this.callbackEmittedBy = widget;
+ }
+
+ boundCallback(widget) {
+ widget.callbackBoundTo = this;
+ }
+});
+
+// Sadly, putting this in the body of the class will prevent calling
+// get_template_child, since MyComplexGtkSubclass will be bound to the ES6
+// class name without the GObject goodies in it
+MyComplexGtkSubclass.prototype.testChildrenExist = function () {
+ this._internalLabel = this.get_template_child(MyComplexGtkSubclass, 'label-child');
+ expect(this._internalLabel).toEqual(jasmine.anything());
+
+ expect(this.label_child2).toEqual(jasmine.anything());
+ expect(this._internal_label_child).toEqual(jasmine.anything());
+};
+
+const MyComplexGtkSubclassFromResource = GObject.registerClass({
+ Template: 'resource:///org/gjs/jsunit/complex4.ui',
+ Children: ['label-child', 'label-child2'],
+ InternalChildren: ['internal-label-child'],
+}, class MyComplexGtkSubclassFromResource extends Gtk.Grid {
+ testChildrenExist() {
+ expect(this.label_child).toEqual(jasmine.anything());
+ expect(this.label_child2).toEqual(jasmine.anything());
+ expect(this._internal_label_child).toEqual(jasmine.anything());
+ }
+
+ templateCallback(widget) {
+ this.callbackEmittedBy = widget;
+ }
+
+ boundCallback(widget) {
+ widget.callbackBoundTo = this;
+ }
+});
+
+const [templateFile, stream] = Gio.File.new_tmp(null);
+const baseStream = stream.get_output_stream();
+const out = new Gio.DataOutputStream({baseStream});
+out.put_string(createTemplate('Gjs_MyComplexGtkSubclassFromFile'), null);
+out.close(null);
+
+const MyComplexGtkSubclassFromFile = GObject.registerClass({
+ Template: templateFile.get_uri(),
+ Children: ['label-child', 'label-child2'],
+ InternalChildren: ['internal-label-child'],
+}, class MyComplexGtkSubclassFromFile extends Gtk.Grid {
+ testChildrenExist() {
+ expect(this.label_child).toEqual(jasmine.anything());
+ expect(this.label_child2).toEqual(jasmine.anything());
+ expect(this._internal_label_child).toEqual(jasmine.anything());
+ }
+
+ templateCallback(widget) {
+ this.callbackEmittedBy = widget;
+ }
+
+ boundCallback(widget) {
+ widget.callbackBoundTo = this;
+ }
+});
+
+const SubclassSubclass = GObject.registerClass(
+ class SubclassSubclass extends MyComplexGtkSubclass {});
+
+function validateTemplate(description, ClassName, pending = false) {
+ let suite = pending ? xdescribe : describe;
+ suite(description, function () {
+ let win, content;
+ beforeEach(function () {
+ win = new Gtk.Window();
+ content = new ClassName();
+ content.label_child.emit('copy-clipboard');
+ content.label_child2.emit('copy-clipboard');
+ win.add(content);
+ });
+
+ it('sets up internal and public template children', function () {
+ content.testChildrenExist();
+ });
+
+ it('sets up public template children with the correct widgets', function () {
+ expect(content.label_child.get_label()).toEqual('Complex!');
+ expect(content.label_child2.get_label()).toEqual('Complex as well!');
+ });
+
+ it('sets up internal template children with the correct widgets', function () {
+ expect(content._internal_label_child.get_label())
+ .toEqual('Complex and internal!');
+ });
+
+ it('connects template callbacks to the correct handler', function () {
+ expect(content.callbackEmittedBy).toBe(content.label_child);
+ });
+
+ it('binds template callbacks to the correct object', function () {
+ expect(content.label_child2.callbackBoundTo).toBe(content.label_child);
+ });
+
+ afterEach(function () {
+ win.destroy();
+ });
+ });
+}
+
+describe('Gtk overrides', function () {
+ beforeAll(function () {
+ Gtk.init();
+ });
+
+ afterAll(function () {
+ templateFile.delete(null);
+ });
+
+ validateTemplate('UI template', MyComplexGtkSubclass);
+ validateTemplate('UI template from resource', MyComplexGtkSubclassFromResource);
+ validateTemplate('UI template from file', MyComplexGtkSubclassFromFile);
+ validateTemplate('Class inheriting from template class', SubclassSubclass, true);
+
+ it('sets CSS names on classes', function () {
+ expect(Gtk.Widget.get_css_name.call(MyComplexGtkSubclass)).toEqual('complex-subclass');
+ });
+
+ it('avoid crashing when GTK vfuncs are called in garbage collection', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL,
+ '*during garbage collection*');
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_CRITICAL,
+ '*destroy*');
+
+ let BadLabel = GObject.registerClass(class BadLabel extends Gtk.Label {
+ vfunc_destroy() {}
+ });
+
+ let w = new Gtk.Window();
+ w.add(new BadLabel());
+
+ w.destroy();
+ System.gc();
+
+ GLib.test_assert_expected_messages_internal('Gjs', 'testGtk4.js', 0,
+ 'Gtk overrides avoid crashing and print a stack trace');
+ });
+
+ it('can create a Gtk.TreeIter with accessible stamp field', function () {
+ const iter = new Gtk.TreeIter();
+ iter.stamp = 42;
+ expect(iter.stamp).toEqual(42);
+ });
+});
diff --git a/installed-tests/js/testLegacyGtk.js b/installed-tests/js/testLegacyGtk.js
index 21f861f0..198d5c3b 100644
--- a/installed-tests/js/testLegacyGtk.js
+++ b/installed-tests/js/testLegacyGtk.js
@@ -56,7 +56,7 @@ const MyComplexGtkSubclass = new Lang.Class({
const MyComplexGtkSubclassFromResource = new Lang.Class({
Name: 'MyComplexGtkSubclassFromResource',
Extends: Gtk.Grid,
- Template: 'resource:///org/gjs/jsunit/complex.ui',
+ Template: 'resource:///org/gjs/jsunit/complex3.ui',
Children: ['label-child', 'label-child2'],
InternalChildren: ['internal-label-child'],