gtk: Create a ResultsFactory

This is a Gtk.ListItemFactory that creates a Label widget and binds
testcase results to it. I use the result status as the name of a CSS
class that will be created in the next patch so the ColumnView cells
have a nicer presentation.

Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
Anna Schumaker 2023-08-01 16:42:01 -04:00
parent 796cf6eec7
commit 8ef06e9571
2 changed files with 133 additions and 0 deletions

View File

@ -3,6 +3,7 @@
import unittest
import xfstestsdb.gtk.row
from gi.repository import Gtk
from gi.repository import Adw
class TestLabelFactory(unittest.TestCase):
@ -45,3 +46,91 @@ class TestLabelFactory(unittest.TestCase):
self.factory.emit("setup", self.listitem)
self.factory.emit("teardown", self.listitem)
self.assertIsNone(self.listitem.get_child())
class TestResultFactory(unittest.TestCase):
"""Tests our Gtk.Factory to show test results."""
def setup_parent(self, factory: xfstestsdb.gtk.row.ResultFactory,
listitem: Gtk.ListItem) -> None:
"""Set the child widget's parent for custom styling."""
self.parent.set_child(listitem.get_child())
def setUp(self):
"""Set up common variables."""
self.testcase = xfstestsdb.gtk.model.TestCase("test/case")
self.parent = Adw.Bin()
self.listitem = Gtk.ListItem()
self.listitem.get_item = unittest.mock.Mock(return_value=self.testcase)
self.factory = xfstestsdb.gtk.row.ResultFactory("xunit-1")
self.factory.connect("setup", self.setup_parent)
def test_init(self):
"""Test that the factory was initialized correctly."""
self.assertIsInstance(self.factory, Gtk.SignalListItemFactory)
self.assertEqual(self.factory.xunit, "xunit-1")
def test_setup(self):
"""Test that the factory implements the 'setup' signal."""
self.factory.emit("setup", self.listitem)
self.assertIsInstance(self.listitem.get_child(), Gtk.Label)
self.assertTrue(self.listitem.get_child().has_css_class("numeric"))
self.assertEqual(self.parent.get_child(), self.listitem.get_child())
def test_bind_passed(self):
"""Test binding to a passing test."""
self.testcase.add_xunit("xunit-1", "passed", 3, "", None, None)
self.factory.emit("setup", self.listitem)
self.factory.emit("bind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "3 seconds")
self.assertIsNone(self.listitem.get_child().get_tooltip_text())
self.assertTrue(self.parent.has_css_class("passed"))
self.factory.emit("unbind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "")
self.assertFalse(self.parent.has_css_class("passed"))
def test_bind_skipped(self):
"""Test binding to a skipped test."""
self.testcase.add_xunit("xunit-1", "skipped", 0,
"test skipped for ... reasons", None, None)
self.factory.emit("setup", self.listitem)
self.factory.emit("bind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "skipped")
self.assertEqual(self.listitem.get_child().get_tooltip_text(),
"test skipped for ... reasons")
self.assertTrue(self.parent.has_css_class("skipped"))
self.factory.emit("unbind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "")
self.assertFalse(self.parent.has_css_class("skipped"))
def test_bind_failed(self):
"""Test binding to a failed test."""
self.testcase.add_xunit("xunit-1", "failure", 8,
"- failed. see output", None, None)
self.factory.emit("setup", self.listitem)
self.factory.emit("bind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "failure")
self.assertEqual(self.listitem.get_child().get_tooltip_text(),
"failed. see output")
self.assertTrue(self.parent.has_css_class("failure"))
self.factory.emit("unbind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "")
self.assertFalse(self.parent.has_css_class("failure"))
def test_bind_missing(self):
"""Test binding to a missing test."""
self.factory.emit("setup", self.listitem)
self.factory.emit("bind", self.listitem)
self.assertEqual(self.listitem.get_child().get_text(), "")
self.factory.emit("unbind", self.listitem)
def test_teardown(self):
"""Test that the factory implements the 'teardown' signal."""
self.factory.emit("setup", self.listitem)
self.factory.emit("teardown", self.listitem)
self.assertIsNone(self.listitem.get_child())

View File

@ -36,3 +36,47 @@ class LabelFactory(Gtk.SignalListItemFactory):
listitem: Gtk.ListItem) -> None:
"""Clean up a ListItem child widget."""
listitem.set_child(None)
class ResultFactory(Gtk.SignalListItemFactory):
"""Factory for making test result widgets."""
xunit = GObject.Property(type=str)
def __init__(self, xunit: str):
"""Initialize our ResultFactory."""
super().__init__(xunit=xunit)
self.connect("setup", self.do_setup)
self.connect("bind", self.do_bind)
self.connect("unbind", self.do_unbind)
self.connect("teardown", self.do_teardown)
def do_setup(self, factory: typing.Self, listitem: Gtk.ListItem) -> None:
"""Set up a ListItem child widget."""
listitem.set_child(Gtk.Label())
listitem.get_child().add_css_class("numeric")
def do_bind(self, factory: typing.Self, listitem: Gtk.ListItem) -> None:
"""Bind a ListItem to the child widget."""
if (result := listitem.get_item()[self.xunit]) is None:
return
if (text := result.status) == "passed":
text = f"{result.time} seconds"
child = listitem.get_child()
child.set_text(text)
child.set_tooltip_text(result.message.lstrip(" -"))
child.get_parent().add_css_class(result.status)
def do_unbind(self, factory: typing.Self, listitem: Gtk.ListItem) -> None:
"""Unbind a ListItem from the child widget."""
if (result := listitem.get_item()[self.xunit]) is not None:
child = listitem.get_child()
child.set_text("")
child.get_parent().remove_css_class(result.status)
def do_teardown(self, factory: typing.Self,
listitem: Gtk.ListItem) -> None:
"""Clean up a ListItem child widget."""
listitem.set_child(None)