2022-09-06 14:13:51 -04:00
|
|
|
# Copyright 2022 (c) Anna Schumaker
|
|
|
|
"""Tests our library Gio.ListModel."""
|
|
|
|
import pathlib
|
|
|
|
import emmental.db
|
|
|
|
import tests.util
|
|
|
|
import unittest.mock
|
|
|
|
|
|
|
|
|
|
|
|
class TestLibraryObject(tests.util.TestCase):
|
|
|
|
"""Tests our library object."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""Set up common variables."""
|
|
|
|
super().setUp()
|
|
|
|
self.table = self.sql.libraries
|
|
|
|
self.path = pathlib.Path("/a/b/c")
|
|
|
|
self.library = emmental.db.libraries.Library(table=self.table,
|
|
|
|
libraryid=123,
|
|
|
|
propertyid=456,
|
|
|
|
path=self.path,
|
|
|
|
name=str(self.path))
|
|
|
|
|
2023-03-10 17:03:19 -05:00
|
|
|
def tearDown(self):
|
|
|
|
"""Clean up."""
|
|
|
|
super().tearDown()
|
|
|
|
self.library.stop()
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
def test_init(self):
|
|
|
|
"""Test that the Library is set up properly."""
|
|
|
|
self.assertIsInstance(self.library, emmental.db.playlist.Playlist)
|
|
|
|
self.assertIsInstance(self.library.queue, emmental.db.idle.Queue)
|
2023-03-10 17:03:19 -05:00
|
|
|
self.assertIsNone(self.library.readdir)
|
|
|
|
self.assertIsNone(self.library.tagger)
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
self.assertEqual(self.library.table, self.table)
|
|
|
|
self.assertEqual(self.library.propertyid, 456)
|
|
|
|
self.assertEqual(self.library.libraryid, 123)
|
|
|
|
self.assertEqual(self.library.primary_key, 123)
|
|
|
|
self.assertEqual(self.library.path, self.path)
|
|
|
|
self.assertTrue(self.library.enabled)
|
|
|
|
self.assertFalse(self.library.deleting)
|
|
|
|
self.assertIsNone(self.library.parent)
|
|
|
|
|
2023-03-10 17:03:19 -05:00
|
|
|
self.assertFalse(self.library.online)
|
|
|
|
self.assertEqual(self.library.queue[0],
|
|
|
|
(self.library._Library__scan_library,))
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
def test_delete(self):
|
|
|
|
"""Test deleting a Library path."""
|
2023-04-10 10:23:14 -04:00
|
|
|
self.assertFalse(self.library.deleting)
|
|
|
|
|
|
|
|
artist = self.sql.artists.create("Test Artist")
|
|
|
|
album = self.sql.albums.create("Test Album", "Test Artist", "2023")
|
|
|
|
medium = self.sql.media.create(album, "", number=1)
|
|
|
|
genre = self.sql.genres.create("Test Genre")
|
|
|
|
decade = self.sql.decades.create(1980)
|
|
|
|
year = self.sql.years.create(1988)
|
|
|
|
playlists = [plist for plist in self.sql.playlists.store] + \
|
|
|
|
[artist, album, medium, genre, decade, year]
|
|
|
|
for playlist in playlists:
|
|
|
|
playlist.reload_tracks = unittest.mock.Mock()
|
|
|
|
|
|
|
|
self.table.delete = unittest.mock.Mock()
|
|
|
|
self.sql.tracks.clear = unittest.mock.Mock()
|
|
|
|
self.sql.tracks.load = unittest.mock.Mock()
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
with unittest.mock.patch.object(self.table, "delete") as mock_delete:
|
|
|
|
with unittest.mock.patch.object(self.table, "update"):
|
|
|
|
self.assertTrue(self.library.delete())
|
|
|
|
self.assertTrue(self.library.deleting)
|
|
|
|
mock_delete.assert_not_called()
|
|
|
|
|
2023-04-10 10:23:14 -04:00
|
|
|
tasks = [(self.library._Library__reload_playlist_tracks, plist)
|
|
|
|
for plist in playlists]
|
|
|
|
tasks.append((self.library._Library__queue_delete,))
|
|
|
|
self.assertListEqual(self.library.queue._tasks, tasks)
|
|
|
|
self.sql.tracks.clear.assert_called()
|
|
|
|
self.sql.tracks.load.assert_not_called()
|
|
|
|
|
|
|
|
self.library.queue.cancel()
|
2022-09-06 14:13:51 -04:00
|
|
|
self.assertFalse(self.library.delete())
|
2023-04-10 10:23:14 -04:00
|
|
|
self.assertListEqual(self.library.queue._tasks, [])
|
2022-09-06 14:13:51 -04:00
|
|
|
|
2023-04-10 10:23:14 -04:00
|
|
|
self.library.deleting = False
|
|
|
|
self.assertTrue(self.library.delete())
|
2022-09-06 14:13:51 -04:00
|
|
|
self.library.queue.complete()
|
2023-04-10 10:23:14 -04:00
|
|
|
for plist in playlists:
|
|
|
|
plist.reload_tracks.assert_called_with(idle=False)
|
2022-09-06 14:13:51 -04:00
|
|
|
mock_delete.assert_called_with(self.library)
|
2023-04-10 10:23:14 -04:00
|
|
|
self.sql.tracks.load.assert_called()
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
def test_online(self):
|
|
|
|
"""Test that changing the online property notifies the table."""
|
|
|
|
with unittest.mock.patch.object(self.table,
|
|
|
|
"notify_online") as mock_notify:
|
|
|
|
self.library.online = True
|
|
|
|
mock_notify.assert_called_with(self.library)
|
|
|
|
|
2023-03-10 17:03:19 -05:00
|
|
|
@unittest.mock.patch.object(pathlib.Path, "iterdir", return_value=[])
|
|
|
|
@unittest.mock.patch.object(pathlib.Path, "is_dir")
|
|
|
|
def test_scan_online(self, mock_is_dir: unittest.mock.Mock,
|
|
|
|
mock_iterdir: unittest.mock.Mock):
|
|
|
|
"""Test scanning an online Library path."""
|
|
|
|
self.assertEqual(self.library.queue[0],
|
|
|
|
(self.library._Library__scan_library,))
|
2023-04-12 16:57:49 -04:00
|
|
|
self.library.tracks.trackids = {1, 2, 3}
|
|
|
|
self.library.load_tracks = unittest.mock.Mock()
|
2023-03-10 17:03:19 -05:00
|
|
|
|
|
|
|
with unittest.mock.patch.object(self.library.queue,
|
|
|
|
"push") as mock_push:
|
|
|
|
self.library.scan()
|
|
|
|
mock_push.assert_not_called()
|
|
|
|
|
|
|
|
mock_is_dir.return_value = True
|
|
|
|
self.assertTrue(self.library.queue.run_task())
|
2023-04-12 16:57:49 -04:00
|
|
|
self.library.load_tracks.assert_called()
|
2023-03-10 17:03:19 -05:00
|
|
|
|
|
|
|
mock_is_dir.assert_called()
|
|
|
|
self.assertTrue(self.library.online)
|
|
|
|
self.assertTrue(self.library.queue.running)
|
|
|
|
self.assertIsInstance(self.library.readdir,
|
|
|
|
emmental.path.ReaddirThread)
|
|
|
|
self.assertIsInstance(self.library.tagger,
|
|
|
|
emmental.db.tagger.Thread)
|
2023-04-12 16:57:49 -04:00
|
|
|
self.assertEqual(self.library.queue._tasks,
|
|
|
|
[(self.library._Library__check_trackid, 1),
|
|
|
|
(self.library._Library__check_trackid, 2),
|
|
|
|
(self.library._Library__check_trackid, 3),
|
|
|
|
(self.library._Library__queue_tracks,)])
|
2023-03-10 17:03:19 -05:00
|
|
|
|
|
|
|
def test_scan_offline(self):
|
|
|
|
"""Test scanning an offline Library path."""
|
|
|
|
self.assertEqual(self.library.queue[0],
|
|
|
|
(self.library._Library__scan_library,))
|
|
|
|
|
|
|
|
self.assertFalse(self.library.queue.run_task())
|
|
|
|
self.assertFalse(self.library.queue.running)
|
|
|
|
self.assertFalse(self.library.online)
|
|
|
|
self.assertIsNone(self.library.readdir)
|
|
|
|
|
|
|
|
@unittest.mock.patch.object(pathlib.Path, "iterdir", return_value=[])
|
|
|
|
@unittest.mock.patch.object(pathlib.Path, "is_file", return_value=True)
|
|
|
|
def test_scan_queue_tracks(self, mock_is_file: unittest.mock.Mock,
|
|
|
|
mock_iterdir: unittest.mock.Mock):
|
|
|
|
"""Test that tracks are queued for scanning."""
|
|
|
|
self.library.stop()
|
|
|
|
self.library.readdir = unittest.mock.Mock()
|
|
|
|
readdir = self.library.readdir
|
|
|
|
|
|
|
|
readdir.poll_result.return_value = []
|
|
|
|
self.assertFalse(self.library._Library__queue_tracks())
|
|
|
|
readdir.poll_result.assert_called()
|
|
|
|
readdir.stop.assert_not_called()
|
|
|
|
|
|
|
|
tag_func = self.library._Library__tag_track
|
|
|
|
readdir.poll_result.return_value = [pathlib.Path("/a/b/c/1.ogg"),
|
|
|
|
pathlib.Path("/a/b/c/2.ogg")]
|
|
|
|
self.assertFalse(self.library._Library__queue_tracks())
|
|
|
|
self.assertListEqual(self.library.queue._tasks,
|
|
|
|
[(tag_func, pathlib.Path("/a/b/c/1.ogg")),
|
|
|
|
(tag_func, pathlib.Path("/a/b/c/2.ogg"))])
|
|
|
|
|
|
|
|
readdir.poll_result.return_value = None
|
|
|
|
self.assertTrue(self.library._Library__queue_tracks())
|
|
|
|
self.assertListEqual(self.library.queue._tasks,
|
|
|
|
[(tag_func, pathlib.Path("/a/b/c/1.ogg")),
|
|
|
|
(tag_func, pathlib.Path("/a/b/c/2.ogg")),
|
|
|
|
(self.library._Library__stop_thread, "tagger")])
|
|
|
|
readdir.stop.assert_called()
|
|
|
|
|
|
|
|
def test_scan_tag_track(self):
|
|
|
|
"""Test that tracks are tagged during scanning."""
|
|
|
|
track = pathlib.Path("/a/b/c/1.ogg")
|
|
|
|
raw_tags = emmental.audio.tagger._Tags(track, {})
|
2023-04-02 21:44:56 -04:00
|
|
|
tags = emmental.db.tagger.Tags(self.sql, raw_tags, self.library)
|
2023-03-10 17:03:19 -05:00
|
|
|
tagger = unittest.mock.Mock()
|
|
|
|
self.library.tagger = tagger
|
|
|
|
|
|
|
|
tagger.ready.is_set.return_value = False
|
|
|
|
self.assertFalse(self.library._Library__tag_track(track))
|
|
|
|
tagger.get_result.assert_not_called()
|
|
|
|
tagger.tag_file.assert_not_called()
|
|
|
|
|
|
|
|
tagger.ready.is_set.return_value = True
|
|
|
|
tagger.get_result.return_value = (None, None)
|
|
|
|
self.assertFalse(self.library._Library__tag_track(track))
|
2023-04-02 21:44:56 -04:00
|
|
|
tagger.get_result.assert_called_with(self.sql, self.library)
|
|
|
|
tagger.tag_file.assert_called_with(track, None)
|
|
|
|
|
|
|
|
self.sql.tracks.lookup = unittest.mock.Mock()
|
|
|
|
self.sql.tracks.lookup.return_value.mtime = 12345
|
|
|
|
self.assertFalse(self.library._Library__tag_track(track))
|
|
|
|
tagger.get_result.assert_called_with(self.sql, self.library)
|
|
|
|
tagger.tag_file.assert_called_with(track, 12345)
|
2023-03-10 17:03:19 -05:00
|
|
|
|
|
|
|
tagger.reset_mock()
|
|
|
|
tagger.ready.is_set.return_value = True
|
|
|
|
tagger.get_result.return_value = (track, tags)
|
|
|
|
self.assertTrue(self.library._Library__tag_track(track))
|
|
|
|
tagger.tag_file.assert_not_called()
|
2023-04-02 21:44:56 -04:00
|
|
|
tagger.get_result.assert_called_with(self.sql, self.library)
|
2023-03-10 17:03:19 -05:00
|
|
|
|
2023-04-12 16:57:49 -04:00
|
|
|
@unittest.mock.patch("emmental.db.tagger.untag_track")
|
|
|
|
def test_scan_check_trackid(self, mock_untag: unittest.mock.Mock()):
|
|
|
|
"""Test that deleted Tracks are removed during scanning."""
|
|
|
|
track = unittest.mock.Mock()
|
|
|
|
track.path = pathlib.Path("/a/b/c/1.ogg")
|
|
|
|
|
|
|
|
self.library._Library__check_trackid(1)
|
|
|
|
mock_untag.assert_not_called()
|
|
|
|
|
|
|
|
self.sql.tracks.rows[1] = track
|
|
|
|
with unittest.mock.patch.object(type(track.path),
|
|
|
|
"exists") as mock_exists:
|
|
|
|
mock_exists.return_value = True
|
|
|
|
self.library._Library__check_trackid(1)
|
|
|
|
mock_untag.assert_not_called()
|
|
|
|
track.delete.assert_not_called()
|
|
|
|
|
|
|
|
self.library._Library__check_trackid(1)
|
|
|
|
mock_untag.assert_called_with(self.sql, track)
|
|
|
|
track.delete.assert_called()
|
|
|
|
|
2023-03-10 17:03:19 -05:00
|
|
|
def test_stop(self):
|
|
|
|
"""Test stopping a Library's background work."""
|
|
|
|
readdir = unittest.mock.Mock()
|
|
|
|
tagger = unittest.mock.Mock()
|
|
|
|
self.library.readdir = readdir
|
|
|
|
self.library.tagger = tagger
|
|
|
|
self.library.queue.running = True
|
|
|
|
|
|
|
|
self.library.stop()
|
|
|
|
self.assertIsNone(self.library.readdir)
|
|
|
|
self.assertIsNone(self.library.tagger)
|
|
|
|
self.assertFalse(self.library.queue.running)
|
|
|
|
|
|
|
|
readdir.stop.assert_called()
|
|
|
|
tagger.stop.assert_called()
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
class TestLibraryTable(tests.util.TestCase):
|
|
|
|
"""Tests our library table."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""Set up common variables."""
|
|
|
|
tests.util.TestCase.setUp(self)
|
|
|
|
self.table = self.sql.libraries
|
|
|
|
|
2022-10-03 16:43:36 -04:00
|
|
|
self.album = self.sql.albums.create("Test Album", "Test Artist", "123")
|
|
|
|
self.medium = self.sql.media.create(self.album, "", number=1)
|
|
|
|
self.year = self.sql.years.create(2023)
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
def test_init(self):
|
|
|
|
"""Test that the library model is configured correctly."""
|
|
|
|
self.assertIsInstance(self.table, emmental.db.playlist.Table)
|
|
|
|
self.assertEqual(len(self.table), 0)
|
2022-10-03 16:43:36 -04:00
|
|
|
self.assertFalse(self.table.autodelete)
|
|
|
|
self.assertFalse(self.table.system_tracks)
|
|
|
|
|
|
|
|
def test_add_track(self):
|
|
|
|
"""Test adding a Track to a Library playlist."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b"))
|
|
|
|
track = self.sql.tracks.create(library, pathlib.Path("/a/b/c.ogg"),
|
|
|
|
self.medium, self.year)
|
|
|
|
self.assertTrue(self.table.add_track(library, track))
|
|
|
|
library2 = self.table.create(pathlib.Path("/a/d"))
|
|
|
|
self.assertFalse(self.table.add_track(library2, track))
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
def test_construct(self):
|
|
|
|
"""Test constructing a new library."""
|
|
|
|
library = self.table.construct(propertyid=1, libraryid=1,
|
|
|
|
path=pathlib.Path("/a/b/c"),
|
|
|
|
name="/a/b/c")
|
|
|
|
self.assertIsInstance(library, emmental.db.libraries.Library)
|
|
|
|
self.assertEqual(library.table, self.table)
|
|
|
|
self.assertEqual(library.propertyid, 1)
|
|
|
|
self.assertEqual(library.libraryid, 1)
|
|
|
|
self.assertEqual(library.path, pathlib.Path("/a/b/c"))
|
|
|
|
self.assertEqual(library.name, "/a/b/c")
|
|
|
|
self.assertFalse(library.active)
|
2022-10-03 16:43:36 -04:00
|
|
|
self.assertFalse(library.tracks_movable)
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
def test_create(self):
|
|
|
|
"""Test creating a library."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
self.assertIsInstance(library, emmental.db.libraries.Library)
|
|
|
|
self.assertEqual(library.path, pathlib.Path("/a/b/c"))
|
2022-10-03 16:43:36 -04:00
|
|
|
self.assertEqual(library.sort_order, "filepath")
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
cur = self.sql("SELECT COUNT(path) FROM libraries")
|
|
|
|
self.assertEqual(cur.fetchone()["COUNT(path)"], 1)
|
|
|
|
self.assertEqual(len(self.table.store), 1)
|
|
|
|
self.assertEqual(self.table.store.get_item(0), library)
|
|
|
|
|
|
|
|
cur = self.sql("""SELECT COUNT(*) FROM playlist_properties
|
|
|
|
WHERE propertyid=?""", library.propertyid)
|
|
|
|
self.assertEqual(cur.fetchone()["COUNT(*)"], 1)
|
|
|
|
|
|
|
|
self.assertIsNone(self.table.create("/a/b/c"))
|
|
|
|
|
|
|
|
def test_delete(self):
|
|
|
|
"""Test deleting a library."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
self.assertTrue(self.table.delete(library))
|
|
|
|
self.assertIsNone(self.table.index(library))
|
|
|
|
|
|
|
|
cur = self.sql("SELECT COUNT(path) FROM libraries")
|
|
|
|
self.assertEqual(cur.fetchone()["COUNT(path)"], 0)
|
|
|
|
self.assertEqual(len(self.table), 0)
|
|
|
|
self.assertIsNone(self.table.get_item(0))
|
|
|
|
|
|
|
|
cur = self.sql("""SELECT COUNT(*) FROM playlist_properties
|
|
|
|
WHERE propertyid=?""", library.propertyid)
|
|
|
|
self.assertEqual(cur.fetchone()["COUNT(*)"], 0)
|
|
|
|
|
|
|
|
self.assertFalse(self.table.delete(library))
|
|
|
|
|
|
|
|
def test_filter(self):
|
|
|
|
"""Test filtering the library model."""
|
|
|
|
self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
self.table.create(pathlib.Path("/a/b/d"))
|
|
|
|
|
|
|
|
self.table.filter("*c", now=True)
|
|
|
|
self.assertSetEqual(self.table.get_filter().keys, {1})
|
|
|
|
self.table.filter("*a/b*", now=True)
|
|
|
|
self.assertSetEqual(self.table.get_filter().keys, {1, 2})
|
|
|
|
|
2022-10-03 16:43:36 -04:00
|
|
|
def test_get_trackids(self):
|
|
|
|
"""Test loading library tracks from the database."""
|
|
|
|
library = self.table.create("/a/b/")
|
|
|
|
track1 = self.sql.tracks.create(library, pathlib.Path("/a/b/1.ogg"),
|
|
|
|
self.medium, self.year)
|
|
|
|
track2 = self.sql.tracks.create(library, pathlib.Path("/a/b/2.ogg"),
|
|
|
|
self.medium, self.year)
|
|
|
|
self.assertSetEqual(self.table.get_trackids(library),
|
|
|
|
{track1.trackid, track2.trackid})
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
def test_load(self):
|
|
|
|
"""Test loading libraries from the database."""
|
|
|
|
self.table.create("/a/b/c")
|
|
|
|
self.table.create("/a/b/d").enabled = False
|
|
|
|
|
|
|
|
libraries2 = emmental.db.libraries.Table(self.sql)
|
|
|
|
self.assertEqual(len(libraries2), 0)
|
|
|
|
|
|
|
|
libraries2.load(now=True)
|
|
|
|
self.assertEqual(len(libraries2), 2)
|
|
|
|
|
|
|
|
self.assertEqual(libraries2.get_item(0).libraryid, 1)
|
|
|
|
self.assertEqual(libraries2.get_item(0).path, pathlib.Path("/a/b/c"))
|
|
|
|
self.assertTrue(libraries2.get_item(0).enabled)
|
|
|
|
|
|
|
|
self.assertEqual(libraries2.get_item(1).libraryid, 2)
|
|
|
|
self.assertEqual(libraries2.get_item(1).path, pathlib.Path("/a/b/d"))
|
|
|
|
self.assertFalse(libraries2.get_item(1).enabled)
|
|
|
|
|
|
|
|
def test_lookup(self):
|
|
|
|
"""Test looking up a library."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
self.assertEqual(self.table.lookup(pathlib.Path("/a/b/c/")), library)
|
|
|
|
self.assertIsNone(self.table.lookup(pathlib.Path("/no/library/path")))
|
|
|
|
|
2022-10-03 16:43:36 -04:00
|
|
|
def test_remove_track(self):
|
|
|
|
"""Test removing a Track from the Library."""
|
|
|
|
library = self.table.create("/a/b/")
|
|
|
|
self.assertTrue(self.table.remove_track(library, unittest.mock.Mock()))
|
|
|
|
|
2023-03-10 17:03:19 -05:00
|
|
|
def test_stop(self):
|
|
|
|
"""Test stopping the library table."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
library.queue.running = True
|
|
|
|
|
|
|
|
self.table.stop()
|
|
|
|
self.assertFalse(self.table.queue.running)
|
|
|
|
self.assertFalse(library.queue.running)
|
|
|
|
|
2022-09-06 14:13:51 -04:00
|
|
|
def test_update(self):
|
|
|
|
"""Test updating genre attributes."""
|
|
|
|
library = self.table.create("/a/b/c")
|
|
|
|
library.active = True
|
|
|
|
library.enabled = False
|
2022-10-03 16:43:36 -04:00
|
|
|
library.loop = "Track"
|
|
|
|
library.shuffle = True
|
|
|
|
library.sort_order = "trackid"
|
|
|
|
|
|
|
|
row = self.sql("""SELECT active, enabled, loop, shuffle,
|
|
|
|
sort_order, current_trackid
|
|
|
|
FROM libraries_view WHERE libraryid=?""",
|
|
|
|
library.libraryid).fetchone()
|
2022-09-06 14:13:51 -04:00
|
|
|
self.assertTrue(row["active"])
|
|
|
|
self.assertFalse(row["enabled"])
|
2022-10-03 16:43:36 -04:00
|
|
|
self.assertEqual(row["loop"], "Track")
|
|
|
|
self.assertTrue(row["shuffle"])
|
|
|
|
self.assertEqual(row["sort_order"], "trackid")
|
|
|
|
self.assertIsNone(row["current_trackid"])
|
2022-09-06 14:13:51 -04:00
|
|
|
|
|
|
|
def test_library_online(self):
|
|
|
|
"""Test the library-online signal."""
|
|
|
|
library = self.table.create(pathlib.Path("/a/b/c"))
|
|
|
|
callback = unittest.mock.Mock()
|
|
|
|
self.table.connect("library-online", callback)
|
|
|
|
|
|
|
|
library.online = True
|
|
|
|
callback.assert_not_called()
|
|
|
|
library.online = False
|
|
|
|
callback.assert_called_with(self.table, library)
|
|
|
|
|
|
|
|
callback.reset_mock()
|
|
|
|
self.table.loaded = True
|
|
|
|
library.online = True
|
|
|
|
callback.assert_called_with(self.table, library)
|
|
|
|
|
|
|
|
callback.reset_mock()
|
|
|
|
library.online = False
|
|
|
|
callback.assert_called_with(self.table, library)
|