buku/tests/test_bukuDb.py

396 lines
16 KiB
Python
Raw Normal View History

2016-05-31 17:06:17 -05:00
#!/usr/bin/env python3
2016-06-23 08:44:09 -05:00
# Unit test cases for buku
2016-05-25 03:59:40 -05:00
# -*- coding: utf-8 -*-
2016-05-25 07:57:33 -05:00
from genericpath import exists
2016-05-25 03:59:40 -05:00
import imp
2016-05-25 07:57:33 -05:00
import os
import re
2016-05-25 07:57:33 -05:00
from tempfile import TemporaryDirectory
2016-06-23 16:59:55 -05:00
import unittest, pytest
from unittest import mock
2016-05-25 07:57:33 -05:00
from os.path import join, expanduser
import sqlite3
2016-05-25 03:59:40 -05:00
2016-05-25 07:57:33 -05:00
buku = imp.load_source('buku', '../buku')
TEST_TEMP_DIR_OBJ = TemporaryDirectory(prefix='bukutest_')
TEST_TEMP_DIR_PATH = TEST_TEMP_DIR_OBJ.name
TEST_TEMP_DBDIR_PATH = join(TEST_TEMP_DIR_PATH, 'buku')
TEST_TEMP_DBFILE_PATH = join(TEST_TEMP_DBDIR_PATH, 'bookmarks.db')
from buku import BukuDb, parse_tags
2016-05-25 03:59:40 -05:00
2016-06-25 13:59:33 -05:00
TEST_BOOKMARKS = [ ['http://slashdot.org',
'SLASHDOT',
parse_tags(['old,news']),
"News for old nerds, stuff that doesn't matter",
],
['http://www.zażółćgęśląjaźń.pl/',
'ZAŻÓŁĆ',
parse_tags(['zażółć,gęślą,jaźń']),
"Testing UTF-8, zażółć gęślą jaźń.",
],
['https://test.com:8080',
'test',
parse_tags(['test,tes,est,es']),
"a case for replace_tag test",
],
]
2016-06-23 16:59:55 -05:00
@pytest.fixture()
def setup():
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
# start every test from a clean state
if exists(TEST_TEMP_DBFILE_PATH):
os.remove(TEST_TEMP_DBFILE_PATH)
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
class TestBukuDb(unittest.TestCase):
2016-05-25 03:59:40 -05:00
2016-05-25 07:57:33 -05:00
def setUp(self):
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
2016-05-25 03:59:40 -05:00
# start every test from a clean state
if exists(TEST_TEMP_DBFILE_PATH):
os.remove(TEST_TEMP_DBFILE_PATH)
2016-06-25 13:59:33 -05:00
self.bookmarks = TEST_BOOKMARKS
self.bdb = BukuDb()
2016-05-25 07:57:33 -05:00
def tearDown(self):
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# @unittest.skip('skipping')
2016-05-25 07:57:33 -05:00
def test_get_dbdir_path(self):
dbdir_expected = TEST_TEMP_DBDIR_PATH
dbdir_local_expected = join(expanduser('~'), '.local', 'share', 'buku')
dbdir_relative_expected = join('.', 'buku')
2016-05-25 03:59:40 -05:00
2016-05-25 07:57:33 -05:00
# desktop linux
self.assertEqual(dbdir_expected, BukuDb.get_dbdir_path())
# desktop generic
os.environ.pop('XDG_DATA_HOME')
self.assertEqual(dbdir_local_expected, BukuDb.get_dbdir_path())
# no desktop
# -- home is defined differently on various platforms.
# -- keep a copy and set it back once done
originals = {}
for env_var in ['HOME', 'HOMEPATH', 'HOMEDIR']:
try:
originals[env_var] = os.environ.pop(env_var)
except KeyError:
pass
self.assertEqual(dbdir_relative_expected, BukuDb.get_dbdir_path())
for key, value in originals.items():
os.environ[key] = value
# # not sure how to test this in nondestructive manner
# def test_move_legacy_dbfile(self):
# self.fail()
2016-05-31 17:06:17 -05:00
# @unittest.skip('skipping')
2016-05-25 07:57:33 -05:00
def test_initdb(self):
if exists(TEST_TEMP_DBFILE_PATH):
os.remove(TEST_TEMP_DBFILE_PATH)
self.assertIs(False, exists(TEST_TEMP_DBFILE_PATH))
conn, curr = BukuDb.initdb()
self.assertIsInstance(conn, sqlite3.Connection)
self.assertIsInstance(curr, sqlite3.Cursor)
self.assertIs(True, exists(TEST_TEMP_DBFILE_PATH))
curr.close()
conn.close()
2016-08-21 22:14:46 -05:00
# @unittest.skip('skipping')
def test_get_bookmark_by_index(self):
for bookmark in self.bookmarks:
# adding bookmark from self.bookmarks
self.bdb.add_bookmark(*bookmark)
2016-08-21 22:14:46 -05:00
2016-08-23 01:10:14 -05:00
# the expected bookmark
2016-08-21 22:14:46 -05:00
expected = (1, 'http://slashdot.org', 'SLASHDOT', ',news,old,',
"News for old nerds, stuff that doesn't matter")
bookmark_from_db = self.bdb.get_bookmark_by_index(1)
2016-08-21 22:14:46 -05:00
# asserting bookmark matches expected
self.assertEqual(expected, bookmark_from_db)
# asserting None returned if index out of range
self.assertIsNone(self.bdb.get_bookmark_by_index( len(self.bookmarks[0]) + 1 ))
2016-08-21 22:14:46 -05:00
2016-06-13 16:54:22 -05:00
# @unittest.skip('skipping')
def test_get_bookmark_index(self):
for idx, bookmark in enumerate(self.bookmarks):
# adding bookmark from self.bookmarks to database
self.bdb.add_bookmark(*bookmark)
2016-06-13 16:54:22 -05:00
# asserting index is in order
idx_from_db = self.bdb.get_bookmark_index(bookmark[0])
2016-06-13 16:54:22 -05:00
self.assertEqual(idx + 1, idx_from_db)
# asserting -1 is returned for nonexistent url
idx_from_db = self.bdb.get_bookmark_index("http://nonexistent.url")
2016-06-13 16:54:22 -05:00
self.assertEqual(-1, idx_from_db)
2016-05-25 07:57:33 -05:00
2016-05-31 17:06:17 -05:00
# @unittest.skip('skipping')
2016-06-13 16:54:22 -05:00
def test_add_bookmark(self):
for bookmark in self.bookmarks:
# adding bookmark from self.bookmarks to database
self.bdb.add_bookmark(*bookmark)
# retrieving bookmark from database
index = self.bdb.get_bookmark_index(bookmark[0])
from_db = self.bdb.get_bookmark_by_index(index)
self.assertIsNotNone(from_db)
# comparing data
for pair in zip(from_db[1:], bookmark):
self.assertEqual(*pair)
2016-05-25 07:57:33 -05:00
# TODO: tags should be passed to the api as a sequence...
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# @unittest.skip('skipping')
2016-06-03 18:18:54 -05:00
def test_update_bookmark(self):
old_values = self.bookmarks[0]
new_values = self.bookmarks[1]
# adding bookmark and getting index
self.bdb.add_bookmark(*old_values)
index = self.bdb.get_bookmark_index(old_values[0])
2016-06-03 18:18:54 -05:00
# updating with new values
self.bdb.update_bookmark(index, *new_values)
2016-06-03 18:18:54 -05:00
# retrieving bookmark from database
from_db = self.bdb.get_bookmark_by_index(index)
2016-06-03 18:18:54 -05:00
self.assertIsNotNone(from_db)
# checking if values are updated
for pair in zip(from_db[1:], new_values):
self.assertEqual(*pair)
2016-05-25 03:59:40 -05:00
2016-08-23 01:10:14 -05:00
# @unittest.skip('skipping')
def test_append_tag_at_index(self):
for bookmark in self.bookmarks:
self.bdb.add_bookmark(*bookmark)
2016-08-23 01:10:14 -05:00
# tags to add
old_tags = self.bdb.get_bookmark_by_index(1)[3]
2016-08-23 01:10:14 -05:00
new_tags = ",foo,bar,baz"
self.bdb.append_tag_at_index(1, new_tags)
# updated list of tags
from_db = self.bdb.get_bookmark_by_index(1)[3]
2016-08-23 01:10:14 -05:00
# checking if new tags were added to the bookmark
self.assertTrue(all( x in from_db.split(',') for x in new_tags.split(',') ))
# checking if old tags still exist
self.assertTrue(all( x in from_db.split(',') for x in old_tags.split(',') ))
2016-08-23 01:10:14 -05:00
# @unittest.skip('skipping')
def test_append_tag_at_all_indices(self):
for bookmark in self.bookmarks:
self.bdb.add_bookmark(*bookmark)
inclusive_range = lambda start, end: range(start, end + 1)
# tags to add
new_tags = ",foo,bar,baz"
# record of original tags for each bookmark
old_tagsets = { i: self.bdb.get_bookmark_by_index(i)[3] for i in inclusive_range(1, len(self.bookmarks)) }
with mock.patch('builtins.input', return_value='y'):
self.bdb.append_tag_at_index(0, new_tags)
# updated tags for each bookmark
from_db = [ (i, self.bdb.get_bookmark_by_index(i)[3]) for i in inclusive_range(1, len(self.bookmarks)) ]
for index, tagset in from_db:
# checking if new tags added to bookmark
self.assertTrue(all( x in tagset.split(',') for x in new_tags.split(',') ))
# checking if old tags still exist for boomark
self.assertTrue(all( x in tagset.split(',') for x in old_tagsets[index].split(',') ))
# @unittest.skip('skipping')
def test_delete_tag_at_index(self):
# adding bookmarks
for bookmark in self.bookmarks:
self.bdb.add_bookmark(*bookmark)
inclusive_range = lambda start, end: range(start, end + 1)
# dictionary of db bookmark index: tags
tags_by_index = { i: self.bdb.get_bookmark_by_index(i)[3] for i in inclusive_range(1, len(self.bookmarks)) }
for i, tags in tags_by_index.items():
# get the first tag from the bookmark
to_delete = re.match(',.*?,', tags).group(0)
self.bdb.delete_tag_at_index(i, to_delete)
# get updated tags from db
from_db = self.bdb.get_bookmark_by_index(i)[3]
self.assertNotIn(to_delete, from_db)
# @unittest.skip('skipping')
2016-06-05 15:41:01 -05:00
def test_refreshdb(self):
self.bdb.add_bookmark("https://www.google.com/ncr", "?")
self.bdb.refreshdb(1)
from_db = self.bdb.get_bookmark_by_index(1)
2016-06-08 03:16:09 -05:00
self.assertEqual(from_db[2], "Google")
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# def test_searchdb(self):
# self.fail()
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# def test_search_by_tag(self):
# self.fail()
2016-05-25 03:59:40 -05:00
2016-06-05 15:41:01 -05:00
# @unittest.skip('skipping')
2016-06-03 18:18:54 -05:00
def test_delete_bookmark(self):
# adding bookmark and getting index
self.bdb.add_bookmark(*self.bookmarks[0])
index = self.bdb.get_bookmark_index(self.bookmarks[0][0])
2016-06-03 18:18:54 -05:00
# deleting bookmark
self.bdb.delete_bookmark(index)
2016-06-03 18:18:54 -05:00
# asserting it doesn't exist
from_db = self.bdb.get_bookmark_by_index(index)
2016-06-03 18:18:54 -05:00
self.assertIsNone(from_db)
# @unittest.skip('skipping')
def test_delete_bookmark_yes(self):
# checking that "y" response causes delete_bookmark to return True
with mock.patch('builtins.input', return_value='y'):
self.assertTrue(self.bdb.delete_bookmark(0))
# @unittest.skip('skipping')
def test_delete_bookmark_no(self):
# checking that non-"y" response causes delete_bookmark to return None
with mock.patch('builtins.input', return_value='n'):
self.assertIsNone(self.bdb.delete_bookmark(0))
2016-08-21 18:09:07 -05:00
# @unittest.skip('skipping')
def test_delete_all_bookmarks(self):
# adding bookmarks
self.bdb.add_bookmark(*self.bookmarks[0])
2016-08-21 18:09:07 -05:00
# deleting all bookmarks
self.bdb.delete_all_bookmarks()
2016-08-21 18:09:07 -05:00
# assert table has been dropped
2016-08-31 23:22:28 -05:00
with self.assertRaises(sqlite3.OperationalError) as ctx_man:
self.bdb.get_bookmark_by_index(0)
2016-05-25 03:59:40 -05:00
2016-08-31 23:22:28 -05:00
err_msg = str(ctx_man.exception)
self.assertEqual(err_msg, 'no such table: bookmarks')
2016-06-06 23:22:38 -05:00
# @unittest.skip('skipping')
def test_replace_tag(self):
indices = []
for bookmark in self.bookmarks:
# adding bookmark, getting index
self.bdb.add_bookmark(*bookmark)
index = self.bdb.get_bookmark_index(bookmark[0])
2016-06-06 23:22:38 -05:00
indices += [index]
# replacing tags
self.bdb.replace_tag("news", ["__01"])
self.bdb.replace_tag("zażółć", ["__02,__03"])
2016-06-06 23:22:38 -05:00
# replacing tag which is also a substring of other tag
self.bdb.replace_tag("es", ["__04"])
2016-06-06 23:22:38 -05:00
# removing tags
self.bdb.replace_tag("gęślą")
self.bdb.replace_tag("old")
2016-06-06 23:22:38 -05:00
# removing nonexistent tag
self.bdb.replace_tag("_")
2016-06-06 23:22:38 -05:00
# removing nonexistent tag which is also a substring of other tag
self.bdb.replace_tag("e")
2016-06-06 23:22:38 -05:00
for url, title, _, _ in self.bookmarks:
# retrieving from db
index = self.bdb.get_bookmark_index(url)
from_db = self.bdb.get_bookmark_by_index(index)
2016-06-06 23:22:38 -05:00
# asserting tags were replaced
if title == "SLASHDOT":
self.assertEqual(from_db[3], parse_tags(["__01"]))
elif title == "ZAŻÓŁĆ":
2016-06-08 03:16:09 -05:00
self.assertEqual(from_db[3], parse_tags(["__02,__03,jaźń"]))
2016-06-06 23:22:38 -05:00
elif title == "test":
2016-06-08 03:16:09 -05:00
self.assertEqual(from_db[3], parse_tags(["test,tes,est,__04"]))
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# def test_browse_by_index(self):
# self.fail()
2016-05-25 03:59:40 -05:00
# @unittest.skip('skipping')
def test_close_quit(self):
# quitting with no args
try:
self.bdb.close_quit()
except SystemExit as err:
self.assertEqual(err.args[0], 0)
# quitting with custom arg
try:
self.bdb.close_quit(1)
except SystemExit as err:
self.assertEqual(err.args[0], 1)
2016-05-25 03:59:40 -05:00
2016-05-31 17:06:17 -05:00
# def test_import_bookmark(self):
# self.fail()
2016-06-30 16:53:04 -05:00
def test_print_bookmark(capsys, caplog, setup):
2016-06-23 16:59:55 -05:00
bdb = BukuDb()
out, err = capsys.readouterr()
# calling with nonexistent index
bdb.print_bookmark(1)
out, err = capsys.readouterr()
2016-06-30 16:53:04 -05:00
for record in caplog.records():
2016-06-30 16:53:04 -05:00
assert record.levelname == "ERROR"
assert record.getMessage() == "No matching index"
assert (out, err) == ('', '')
2016-06-23 16:59:55 -05:00
# adding bookmarks
bdb.add_bookmark("http://full-bookmark.com", "full", parse_tags(['full,bookmark']), "full bookmark")
bdb.add_bookmark("http://blank-title.com", "", parse_tags(['blank,title']), "blank title")
bdb.add_bookmark("http://empty-tags.com", "empty tags", parse_tags(['']), "empty tags")
bdb.add_bookmark("http://all-empty.com", "", parse_tags(['']), "all empty")
out, err = capsys.readouterr()
# printing first bookmark
bdb.print_bookmark(1)
out, err = capsys.readouterr()
assert out == "\x1b[1m\x1b[93m1. \x1b[0m\x1b[92mhttp://full-bookmark.com\x1b[0m\n \x1b[91m>\x1b[0m full\n \x1b[91m+\x1b[0m full bookmark\n \x1b[91m#\x1b[0m bookmark,full\n\n"
assert err == ''
# printing all bookmarks
bdb.print_bookmark(0)
out, err = capsys.readouterr()
assert out == "\x1b[1m\x1b[93m1. \x1b[0m\x1b[92mhttp://full-bookmark.com\x1b[0m\n \x1b[91m>\x1b[0m full\n \x1b[91m+\x1b[0m full bookmark\n \x1b[91m#\x1b[0m bookmark,full\n\n\x1b[1m\x1b[93m2. \x1b[0m\x1b[92mhttp://blank-title.com\x1b[0m\n \x1b[91m+\x1b[0m blank title\n \x1b[91m#\x1b[0m blank,title\n\n\x1b[1m\x1b[93m3. \x1b[0m\x1b[92mhttp://empty-tags.com\x1b[0m\n \x1b[91m>\x1b[0m empty tags\n \x1b[91m+\x1b[0m empty tags\n\n\x1b[1m\x1b[93m4. \x1b[0m\x1b[92mhttp://all-empty.com\x1b[0m\n \x1b[91m+\x1b[0m all empty\n\n"
assert err == ''
# printing all bookmarks with empty fields
bdb.print_bookmark(0, empty=True)
out, err = capsys.readouterr()
assert out == "\x1b[1m3 records found\x1b[21m\n\n\x1b[1m\x1b[93m2. \x1b[0m\x1b[92mhttp://blank-title.com\x1b[0m\n \x1b[91m+\x1b[0m blank title\n \x1b[91m#\x1b[0m blank,title\n\n\x1b[1m\x1b[93m3. \x1b[0m\x1b[92mhttp://empty-tags.com\x1b[0m\n \x1b[91m>\x1b[0m empty tags\n \x1b[91m+\x1b[0m empty tags\n\n\x1b[1m\x1b[93m4. \x1b[0m\x1b[92mhttp://all-empty.com\x1b[0m\n \x1b[91m+\x1b[0m all empty\n\n"
assert err == ''
2016-06-24 16:56:18 -05:00
def test_list_tags(capsys, setup):
bdb = BukuDb()
# adding bookmarks
bdb.add_bookmark("http://one.com", "", parse_tags(['cat,ant,bee,1']), "")
bdb.add_bookmark("http://two.com", "", parse_tags(['Cat,Ant,bee,1']), "")
bdb.add_bookmark("http://three.com", "", parse_tags(['Cat,Ant,3,Bee,2']), "")
# listing tags, asserting output
2016-06-25 13:59:33 -05:00
out, err = capsys.readouterr()
2016-06-24 16:56:18 -05:00
bdb.list_tags()
out, err = capsys.readouterr()
assert out == " 1. 1\n 2. 2\n 3. 3\n 4. Ant\n 5. ant\n 6. bee\n 7. Bee\n 8. Cat\n 9. cat\n"
assert err == ''
2016-05-31 17:06:17 -05:00
2016-06-25 13:59:33 -05:00
def test_compactdb(setup):
bdb = BukuDb()
# adding bookmarks
for bookmark in TEST_BOOKMARKS:
bdb.add_bookmark(*bookmark)
# manually deleting 2nd index from db, calling compactdb
bdb.cur.execute('DELETE FROM bookmarks WHERE id = ?', (2,))
bdb.compactdb(2)
# asserting bookmarks have correct indices
assert bdb.get_bookmark_by_index(1) == (1, 'http://slashdot.org', 'SLASHDOT', ',news,old,', "News for old nerds, stuff that doesn't matter")
assert bdb.get_bookmark_by_index(2) == (2, 'https://test.com:8080', 'test', ',es,est,tes,test,', 'a case for replace_tag test')
assert bdb.get_bookmark_by_index(3) is None
2016-05-31 17:06:17 -05:00
if __name__ == "__main__":
unittest.main()