"Fossies" - the Fresh Open Source Software Archive

Member "buku-4.3/tests/test_buku.py" (31 Jan 2020, 24829 Bytes) of package /linux/privat/buku-4.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_buku.py": 4.2.2_vs_4.3.

    1 """test module."""
    2 from itertools import product
    3 from unittest import mock
    4 from urllib.parse import urlparse
    5 import json
    6 import logging
    7 import os
    8 import signal
    9 import sys
   10 import unittest
   11 
   12 import pytest
   13 
   14 from buku import is_int, parse_tags, prep_tag_search
   15 
   16 only_python_3_5 = pytest.mark.skipif(
   17     sys.version_info < (3, 5), reason="requires Python 3.5 or later")
   18 
   19 
   20 @pytest.mark.parametrize(
   21     'url, exp_res',
   22     [
   23         ['http://example.com', False],
   24         ['ftp://ftp.somedomain.org', False],
   25         ['http://examplecom.', True],
   26         ['http://.example.com', True],
   27         ['http://example.com.', True],
   28         ['about:newtab', True],
   29         ['chrome://version/', True],
   30     ]
   31 )
   32 def test_is_bad_url(url, exp_res):
   33     """test func."""
   34     import buku
   35     res = buku.is_bad_url(url)
   36     assert res == exp_res
   37 
   38 
   39 @pytest.mark.parametrize(
   40     'url, exp_res',
   41     [
   42         ('http://example.com/file.pdf', True),
   43         ('http://example.com/file.txt', True),
   44         ('http://example.com/file.jpg', False),
   45     ]
   46 )
   47 def test_is_ignored_mime(url, exp_res):
   48     """test func."""
   49     import buku
   50     assert exp_res == buku.is_ignored_mime(url)
   51 
   52 
   53 def test_gen_headers():
   54     """test func."""
   55     import buku
   56     exp_myheaders = {
   57         'Accept-Encoding': 'gzip,deflate',
   58         'User-Agent': buku.USER_AGENT,
   59         'Accept': '*/*',
   60         'Cookie': '',
   61         'DNT': '1'
   62     }
   63     buku.gen_headers()
   64     assert buku.MYPROXY is None
   65     assert buku.MYHEADERS == exp_myheaders
   66 
   67 
   68 @pytest.mark.parametrize('m_myproxy', [None, mock.Mock()])
   69 def test_get_PoolManager(m_myproxy):
   70     """test func."""
   71     with mock.patch('buku.urllib3'):
   72         import buku
   73         buku.myproxy = m_myproxy
   74         assert buku.get_PoolManager()
   75 
   76 
   77 @pytest.mark.parametrize(
   78     'keywords, exp_res',
   79     [
   80         (None, None),
   81         ([], None),
   82         (['tag1', 'tag2'], ',tag1 tag2,'),
   83         (['tag1,tag2', 'tag3'], ',tag1,tag2 tag3,'),
   84     ]
   85 )
   86 def test_parse_tags(keywords, exp_res):
   87     """test func."""
   88     import buku
   89     if keywords is None:
   90         pass
   91     elif not keywords:
   92         exp_res = buku.DELIM
   93     res = buku.parse_tags(keywords)
   94     assert res == exp_res
   95 
   96 
   97 @pytest.mark.parametrize(
   98     'records, field_filter, exp_res',
   99     [
  100         [
  101             [(1, 'http://url1.com', 'title1', ',tag1,'),
  102              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  103             1,
  104             ['1\thttp://url1.com', '2\thttp://url2.com']
  105         ],
  106         [
  107             [(1, 'http://url1.com', 'title1', ',tag1,'),
  108              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  109             2,
  110             ['1\thttp://url1.com\ttag1', '2\thttp://url2.com\ttag1,tag2']
  111         ],
  112         [
  113             [(1, 'http://url1.com', 'title1', ',tag1,'),
  114              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  115             3,
  116             ['1\ttitle1', '2\ttitle2']
  117         ],
  118         [
  119             [(1, 'http://url1.com', 'title1', ',tag1,'),
  120              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  121             4,
  122             ['1\thttp://url1.com\ttitle1\ttag1', '2\thttp://url2.com\ttitle2\ttag1,tag2']
  123         ],
  124         [
  125             [(1, 'http://url1.com', 'title1', ',tag1,'),
  126              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  127             10,
  128             ['http://url1.com', 'http://url2.com']
  129         ],
  130         [
  131             [(1, 'http://url1.com', 'title1', ',tag1,'),
  132              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  133             20,
  134             ['http://url1.com\ttag1', 'http://url2.com\ttag1,tag2']
  135         ],
  136         [
  137             [(1, 'http://url1.com', 'title1', ',tag1,'),
  138              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  139             30,
  140             ['title1', 'title2']
  141         ],
  142         [
  143             [(1, 'http://url1.com', 'title1', ',tag1,'),
  144              (2, 'http://url2.com', 'title2', ',tag1,tag2,')],
  145             40,
  146             ['http://url1.com\ttitle1\ttag1', 'http://url2.com\ttitle2\ttag1,tag2']
  147         ]
  148     ]
  149 )
  150 def test_print_rec_with_filter(records, field_filter, exp_res):
  151     """test func."""
  152     with mock.patch('buku.print', create=True) as m_print:
  153         import buku
  154         buku.print_rec_with_filter(records, field_filter)
  155         for res in exp_res:
  156             m_print.assert_any_call(res)
  157 
  158 
  159 @pytest.mark.parametrize(
  160     'taglist, exp_res',
  161     [
  162         [
  163             'tag1, tag2+3',
  164             ([',tag1,', ',tag2+3,'], 'OR', None)
  165         ],
  166         [
  167             'tag1 + tag2-3 + tag4',
  168             ([',tag1,', ',tag2-3,', ',tag4,'], 'AND', None)
  169         ],
  170         [
  171             'tag1, tag2-3 - tag4, tag5',
  172             ([',tag1,', ',tag2-3,'], 'OR', ',tag4,|,tag5,')
  173         ]
  174     ]
  175 )
  176 def test_prep_tag_search(taglist, exp_res):
  177     """test prep_tag_search helper function"""
  178 
  179     results = prep_tag_search(taglist)
  180     assert results == exp_res
  181 
  182 
  183 @pytest.mark.parametrize(
  184     'nav, is_editor_valid_retval, edit_rec_retval',
  185     product(
  186         ['w', [None, None, 1], [None, None, 'string']],
  187         [True, False],
  188         [[mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock()], None]
  189     )
  190 )
  191 def test_edit_at_prompt(nav, is_editor_valid_retval, edit_rec_retval):
  192     """test func."""
  193     obj = mock.Mock()
  194     editor = mock.Mock()
  195     with mock.patch('buku.get_system_editor', return_value=editor), \
  196             mock.patch('buku.is_editor_valid', return_value=is_editor_valid_retval), \
  197             mock.patch('buku.edit_rec', return_value=edit_rec_retval) as m_edit_rec:
  198         import buku
  199         buku.edit_at_prompt(obj, nav)
  200         # test
  201         if nav == 'w' and not is_editor_valid_retval:
  202             return
  203         if nav == 'w':
  204             m_edit_rec.assert_called_once_with(editor, '', None, buku.DELIM, None)
  205         elif buku.is_int(nav[2:]):
  206             obj.edit_update_rec.assert_called_once_with(int(nav[2:]))
  207             return
  208         else:
  209             editor = nav[2:]
  210         m_edit_rec.assert_called_once_with(editor, '', None, buku.DELIM, None)
  211         if edit_rec_retval is not None:
  212             obj.add_rec(*edit_rec_retval)
  213 
  214 
  215 @pytest.mark.parametrize(
  216     'field_filter, single_record',
  217     product(list(range(4)), [True, False])
  218 )
  219 def test_format_json(field_filter, single_record):
  220     """test func."""
  221     resultset = [['row{}'.format(x) for x in range(5)]]
  222     if field_filter == 1:
  223         marks = {'uri': 'row1'}
  224     elif field_filter == 2:
  225         marks = {'uri': 'row1', 'tags': 'row3'[1:-1]}
  226     elif field_filter == 3:
  227         marks = {'title': 'row2'}
  228     else:
  229         marks = {
  230             'index': 'row0',
  231             'uri': 'row1',
  232             'title': 'row2',
  233             'description': 'row4',
  234             'tags': 'row3'[1:-1]
  235         }
  236     if not single_record:
  237         marks = [marks]
  238 
  239     with mock.patch('buku.json') as m_json:
  240         import buku
  241         res = buku.format_json(resultset, single_record, field_filter)
  242         m_json.dumps.assert_called_once_with(marks, sort_keys=True, indent=4)
  243         assert res == m_json.dumps.return_value
  244 
  245 
  246 @pytest.mark.parametrize(
  247     'string, exp_res',
  248     [
  249         ('string', False),
  250         ('12', True),
  251         ('12.1', False),
  252     ]
  253 )
  254 def test_is_int(string, exp_res):
  255     """test func."""
  256     import buku
  257     assert exp_res == buku.is_int(string)
  258 
  259 
  260 @pytest.mark.parametrize(
  261     'url, opened_url, platform',
  262     [
  263         ['http://example.com', 'http://example.com', 'linux'],
  264         ['example.com', 'http://example.com', 'linux'],
  265         ['http://example.com', 'http://example.com', 'win32'],
  266     ]
  267 )
  268 def test_browse(url, opened_url, platform):
  269     """test func."""
  270     with mock.patch('buku.webbrowser') as m_webbrowser, \
  271             mock.patch('buku.sys') as m_sys, \
  272             mock.patch('buku.os'):
  273         m_sys.platform = platform
  274         get_func_retval = mock.Mock()
  275         m_webbrowser.get.return_value = get_func_retval
  276         import buku
  277         buku.browse.suppress_browser_output = True
  278         buku.browse.override_text_browser = False
  279         buku.browse(url)
  280         if platform == 'win32':
  281             m_webbrowser.open.assert_called_once_with(opened_url, new=2)
  282         else:
  283             get_func_retval.open.assert_called_once_with(opened_url, new=2)
  284 
  285 
  286 @only_python_3_5
  287 @pytest.mark.parametrize(
  288     'status_code, latest_release',
  289     product([200, 404], [True, False])
  290 )
  291 def test_check_upstream_release(status_code, latest_release):
  292     """test func."""
  293     resp = mock.Mock()
  294     resp.status = status_code
  295     m_manager = mock.Mock()
  296     m_manager.request.return_value = resp
  297     with mock.patch('buku.urllib3') as m_urllib3, \
  298             mock.patch('buku.print') as m_print:
  299         import buku
  300         if latest_release:
  301             latest_version = 'v{}'.format(buku.__version__)
  302         else:
  303             latest_version = 'v0'
  304         m_urllib3.PoolManager.return_value = m_manager
  305         resp.data.decode.return_value = json.dumps([{'tag_name': latest_version}])
  306         buku.check_upstream_release()
  307         if status_code != 200:
  308             return
  309         len(m_print.mock_calls) == 1
  310 
  311 
  312 @pytest.mark.parametrize(
  313     'exp, item, exp_res',
  314     [
  315         ('cat.y', 'catty', True),
  316         ('cat.y', 'caty', False),
  317     ]
  318 )
  319 def test_regexp(exp, item, exp_res):
  320     """test func."""
  321     import buku
  322     res = buku.regexp(exp, item)
  323     assert res == exp_res
  324 
  325 
  326 @pytest.mark.parametrize('token, exp_res', [('text', ',text,')])
  327 def test_delim_wrap(token, exp_res):
  328     """test func."""
  329     import buku
  330     res = buku.delim_wrap(token)
  331     assert res == exp_res
  332 
  333 
  334 @only_python_3_5
  335 def test_read_in():
  336     """test func."""
  337     message = mock.Mock()
  338     with mock.patch('buku.disable_sigint_handler'), \
  339             mock.patch('buku.enable_sigint_handler'), \
  340             mock.patch('buku.input', return_value=message):
  341         import buku
  342         res = buku.read_in(msg=mock.Mock())
  343         assert res == message
  344 
  345 
  346 def test_sigint_handler_with_mock():
  347     """test func."""
  348     with mock.patch('buku.os') as m_os:
  349         import buku
  350         buku.sigint_handler(mock.Mock(), mock.Mock())
  351         m_os._exit.assert_called_once_with(1)
  352 
  353 
  354 def test_get_system_editor():
  355     """test func."""
  356     with mock.patch('buku.os') as m_os:
  357         import buku
  358         res = buku.get_system_editor()
  359         assert res == m_os.environ.get.return_value
  360         m_os.environ.get.assert_called_once_with('EDITOR', 'none')
  361 
  362 
  363 @pytest.mark.parametrize(
  364     'editor, exp_res',
  365     [
  366         ('none', False),
  367         ('0', False),
  368         ('random_editor', True),
  369     ]
  370 )
  371 def test_is_editor_valid(editor, exp_res):
  372     """test func."""
  373     import buku
  374     assert buku.is_editor_valid(editor) == exp_res
  375 
  376 
  377 @pytest.mark.parametrize(
  378     'url, title_in, tags_in, desc',
  379     product(
  380         [None, 'example.com'],
  381         [None, '', 'title'],
  382         [None, '', '-', 'tag1,tag2', ',tag1,tag2,', ',,,,,'],
  383         [None, '', '-', 'description'],
  384     )
  385 )
  386 def test_to_temp_file_content(url, title_in, tags_in, desc):
  387     """test func."""
  388     import buku
  389     if desc is None:
  390         desc_text = '\n'
  391     elif desc == '':
  392         desc_text = '-'
  393     else:
  394         desc_text = desc
  395     if title_in is None:
  396         title_text = ''
  397     elif title_in == '':
  398         title_text = '-'
  399     else:
  400         title_text = title_in
  401     if tags_in is None:
  402         with pytest.raises(AttributeError):
  403             res = buku.to_temp_file_content(url, title_in, tags_in, desc)
  404         return
  405     res = buku.to_temp_file_content(url, title_in, tags_in, desc)
  406     lines = """# Lines beginning with "#" will be stripped.
  407 # Add URL in next line (single line).{}
  408 # Add TITLE in next line (single line). Leave blank to web fetch, "-" for no title.{}
  409 # Add comma-separated TAGS in next line (single line).{}
  410 # Add COMMENTS in next line(s). Leave blank to web fetch, "-" for no comments.{}""".format(
  411         ''.join(['\n', url]) if url is not None else '',
  412         ''.join(['\n', title_text]),
  413         ''.join(['\n', ','.join([x for x in tags_in.split(',') if x])]) if tags_in else '\n',
  414         ''.join(['\n', desc_text])
  415     )
  416     assert res == lines
  417 
  418 
  419 @pytest.mark.parametrize(
  420     'content, exp_res',
  421     [
  422         ('', None),
  423         ('#line1\n#line2', None),
  424         (
  425             '\n'.join([
  426                 'example.com',
  427                 'title',
  428                 'tags',
  429                 'desc',
  430             ]),
  431             ('example.com', 'title', ',tags,', 'desc')
  432         )
  433     ]
  434 )
  435 def test_parse_temp_file_content(content, exp_res):
  436     """test func."""
  437     import buku
  438     res = buku.parse_temp_file_content(content)
  439     assert res == exp_res
  440 
  441 
  442 @only_python_3_5
  443 @pytest.mark.skip(reason="can't patch subprocess")
  444 def test_edit_rec():
  445     """test func."""
  446     editor = 'nanoe'
  447     args = ('url', 'title_in', 'tags_in', 'desc')
  448     with mock.patch('buku.to_temp_file_content'), \
  449             mock.patch('buku.os'), \
  450             mock.patch('buku.open'), \
  451             mock.patch('buku.parse_temp_file_content') as m_ptfc:
  452         import buku
  453         res = buku.edit_rec(editor, *args)
  454         assert res == m_ptfc.return_value
  455 
  456 
  457 @pytest.mark.parametrize('argv, pipeargs, isatty', product(['argv'], [None, []], [True, False]))
  458 def test_piped_input(argv, pipeargs, isatty):
  459     """test func."""
  460     with mock.patch('buku.sys') as m_sys:
  461         m_sys.stdin.isatty.return_value = isatty
  462         m_sys.stdin.readlines.return_value = 'arg1\narg2'
  463         import buku
  464         if pipeargs is None and not isatty:
  465             with pytest.raises(TypeError):
  466                 buku.piped_input(argv, pipeargs)
  467             return
  468         buku.piped_input(argv, pipeargs)
  469 
  470 
  471 class TestHelpers(unittest.TestCase):
  472 
  473     # @unittest.skip('skipping')
  474     def test_parse_tags(self):
  475         # call with None
  476         parsed = parse_tags(None)
  477         self.assertIsNone(parsed)
  478         # call with empty list
  479         parsed = parse_tags([])
  480         self.assertEqual(parsed, ",")
  481         # empty tags
  482         parsed = parse_tags([",,,,,"])
  483         self.assertEqual(parsed, ",")
  484         # sorting tags
  485         parsed = parse_tags(["z_tag,a_tag,n_tag"])
  486         self.assertEqual(parsed, ",a_tag,n_tag,z_tag,")
  487         # whitespaces
  488         parsed = parse_tags([" a tag , ,   ,  ,\t,\n,\r,\x0b,\x0c"])
  489         self.assertEqual(parsed, ",a tag,")
  490         # duplicates, excessive spaces
  491         parsed = parse_tags(["tag,tag, tag,  tag,tag , tag "])
  492         self.assertEqual(parsed, ",tag,")
  493         # escaping quotes
  494         parsed = parse_tags(["\"tag\",\'tag\',tag"])
  495         self.assertEqual(parsed, ",\"tag\",\'tag\',tag,")
  496         # combo
  497         parsed = parse_tags([",,z_tag, a tag ,\t,,,  ,n_tag ,n_tag, a_tag, \na tag  ,\r, \"a_tag\""])
  498         self.assertEqual(parsed, ",\"a_tag\",a tag,a_tag,n_tag,z_tag,")
  499 
  500     # @unittest.skip('skipping')
  501     def test_is_int(self):
  502         self.assertTrue(is_int('0'))
  503         self.assertTrue(is_int('1'))
  504         self.assertTrue(is_int('-1'))
  505         self.assertFalse(is_int(''))
  506         self.assertFalse(is_int('one'))
  507 
  508 # This test fails because we use os._exit() now
  509 @unittest.skip('skipping')
  510 def test_sigint_handler(capsys):
  511     try:
  512         # sending SIGINT to self
  513         os.kill(os.getpid(), signal.SIGINT)
  514     except SystemExit as error:
  515         out, err = capsys.readouterr()
  516         # assert exited with 1
  517         assert error.args[0] == 1
  518         # assert proper error message
  519         assert out == ''
  520         assert err == "\nInterrupted.\n"
  521 
  522 
  523 @pytest.mark.parametrize(
  524     'url, exp_res',
  525     [
  526         ['http://example.com.', (None, None, None, 0, 1)],
  527         ['http://example.com', ('Example Domain', None, None, 0, 0)],
  528         ['http://example.com/page1.txt', (('', '', '', 1, 0))],
  529         ['about:new_page', ((None, None, None, 0, 1))],
  530         ['chrome://version/', ((None, None, None, 0, 1))],
  531         ['chrome://version/', ((None, None, None, 0, 1))],
  532         # [
  533         #     'http://4pda.ru/forum/index.php?showtopic=182463&st=1640#entry6044923',
  534         #     (
  535         #         'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA',
  536         #         'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA',
  537         #         None,
  538         #         0, 0
  539         #     )
  540         # ],
  541         [
  542             'https://www.google.ru/search?'
  543             'newwindow=1&safe=off&q=xkbcomp+alt+gr&'
  544             'oq=xkbcomp+alt+gr&'
  545             'gs_l=serp.3..33i21.28976559.28977886.0.'
  546             '28978017.6.6.0.0.0.0.167.668.0j5.5.0....0...1c.1.64.'
  547             'serp..1.2.311.06cSKPTLo18',
  548             ('xkbcomp alt gr', None, None, 0, 0)
  549         ],
  550         [
  551             'http://www.vim.org/scripts/script.php?script_id=4641',
  552             (
  553                 'mlessnau_case - "in-case" selection, deletion and substitution '
  554                 'for underscore, camel, mixed case : vim online',
  555                 None, None, 0, 0
  556             )
  557         ],
  558     ]
  559 )
  560 def test_network_handler_with_url(url, exp_res):
  561     """test func."""
  562     import buku
  563     import urllib3
  564     buku.urllib3 = urllib3
  565     buku.myproxy = None
  566     res = buku.network_handler(url)
  567     if urlparse(url).netloc == 'www.google.ru':
  568         temp_res = [res[0].split(" - ")[0], ]
  569         temp_res.extend(res[1:])
  570         res = tuple(temp_res)
  571     assert res == exp_res
  572 
  573 
  574 @pytest.mark.parametrize(
  575     'url, exp_res',
  576     [
  577         ('http://example.com', False),
  578         ('apt:package1,package2,package3', True),
  579         ('apt://firefox', True),
  580         ('file:///tmp/vim-markdown-preview.html', True),
  581         ('place:sort=8&maxResults=10', True),
  582     ]
  583 )
  584 def test_is_nongeneric_url(url, exp_res):
  585     import buku
  586     res = buku.is_nongeneric_url(url)
  587     assert res == exp_res
  588 
  589 
  590 @pytest.mark.parametrize(
  591     'newtag, exp_res',
  592     [
  593         (None, ('http://example.com', 'text1', None, None, 0, True)),
  594         ('tag1', ('http://example.com', 'text1', ',tag1,', None, 0, True)),
  595     ]
  596 )
  597 def test_import_md(tmpdir, newtag, exp_res):
  598     from buku import import_md
  599     p = tmpdir.mkdir("importmd").join("test.md")
  600     p.write("[text1](http://example.com)")
  601     res = list(import_md(p.strpath, newtag))
  602     assert res[0] == exp_res
  603 
  604 @pytest.mark.parametrize(
  605     'newtag, exp_res',
  606     [
  607         (None, ('http://example.com', 'text1', None, None, 0, True)),
  608         ('tag0', ('http://example.com', 'text1', ',tag0,tag1,:tag2,tag:3,tag4:,tag::5,tag:6:,', None, 0, True)),
  609     ]
  610 )
  611 def test_import_org(tmpdir, newtag, exp_res):
  612     from buku import import_org
  613     p = tmpdir.mkdir("importorg").join("test.org")
  614     p.write("[[http://example.com][text1]] :tag1: ::tag2:tag::3:tag4:: :tag:::5:tag::6:: :")
  615     res = list(import_org(p.strpath, newtag))
  616     assert res[0] == exp_res
  617 
  618 
  619 @pytest.mark.parametrize(
  620     'html_text, exp_res',
  621     [
  622         (
  623             """<DT><A HREF="https://github.com/j" ADD_DATE="1360951967" PRIVATE="1" TAGS="tag1,tag2">GitHub</A>
  624 <DD>comment for the bookmark here
  625 <a> </a>""",
  626             ((
  627                 'https://github.com/j', 'GitHub', ',tag1,tag2,',
  628                 'comment for the bookmark here', 0, True, False
  629             ),)
  630         ),
  631         (
  632             """DT><A HREF="https://github.com/j" ADD_DATE="1360951967" PRIVATE="1" TAGS="tag1,tag2">GitHub</A>
  633             <DD>comment for the bookmark here
  634             <a>second line of the comment here</a>""",
  635             ((
  636                 'https://github.com/j', 'GitHub', ',tag1,tag2,',
  637                 'comment for the bookmark here', 0, True, False
  638             ),)
  639         ),
  640         (
  641             """DT><A HREF="https://github.com/j" ADD_DATE="1360951967" PRIVATE="1" TAGS="tag1,tag2">GitHub</A>
  642             <DD>comment for the bookmark here
  643             second line of the comment here
  644             third line of the comment here
  645             <DT><A HREF="https://news.com/" ADD_DATE="1360951967" PRIVATE="1" TAGS="tag1,tag2,tag3">News</A>""",
  646             (
  647                 (
  648                     'https://github.com/j', 'GitHub', ',tag1,tag2,',
  649                     'comment for the bookmark here\n            '
  650                     'second line of the comment here\n            '
  651                     'third line of the comment here',
  652                     0, True, False
  653                 ),
  654                 ('https://news.com/', 'News', ',tag1,tag2,tag3,', None, 0, True, False)
  655             )
  656         ),
  657         (
  658 
  659             """DT><A HREF="https://github.com/j" ADD_DATE="1360951967" PRIVATE="1" TAGS="tag1,tag2">GitHub</A>
  660             <DD>comment for the bookmark here""",
  661             ((
  662                 'https://github.com/j', 'GitHub', ',tag1,tag2,',
  663                 'comment for the bookmark here', 0, True, False
  664             ),)
  665         )
  666 
  667     ]
  668 )
  669 def test_import_html(html_text, exp_res):
  670     """test method."""
  671     from buku import import_html
  672     from bs4 import BeautifulSoup
  673     html_soup = BeautifulSoup(html_text, 'html.parser')
  674     res = list(import_html(html_soup, False, None))
  675     for item, exp_item in zip(res, exp_res):
  676         assert item == exp_item, 'Actual item:\n{}'.format(item)
  677 
  678 
  679 def test_import_html_and_add_parent():
  680     from buku import import_html
  681     from bs4 import BeautifulSoup
  682     html_text = """<DT><H3>1s</H3>
  683 <DL><p>
  684 <DT><A HREF="http://example.com/"></A>"""
  685     exp_res = ('http://example.com/', None, ',1s,', None, 0, True, False)
  686     html_soup = BeautifulSoup(html_text, 'html.parser')
  687     res = list(import_html(html_soup, True, None))
  688     assert res[0] == exp_res
  689 
  690 
  691 def test_import_html_and_new_tag():
  692     from buku import import_html
  693     from bs4 import BeautifulSoup
  694     html_text = """<DT><A HREF="https://github.com/j" TAGS="tag1,tag2">GitHub</A>
  695 <DD>comment for the bookmark here"""
  696     exp_res = (
  697         'https://github.com/j', 'GitHub', ',tag1,tag2,tag3,',
  698         'comment for the bookmark here', 0, True, False
  699     )
  700     html_soup = BeautifulSoup(html_text, 'html.parser')
  701     res = list(import_html(html_soup, False, 'tag3'))
  702     assert res[0] == exp_res
  703 
  704 
  705 @pytest.mark.parametrize(
  706     'platform, params',
  707     [
  708         ['linux', ['xsel', '-b', '-i']],
  709         ['freebsd', ['xsel', '-b', '-i']],
  710         ['openbsd', ['xsel', '-b', '-i']],
  711         ['darwin', ['pbcopy']],
  712         ['win32', ['clip']],
  713         ['random', None],
  714     ],
  715 )
  716 def test_copy_to_clipboard(platform, params):
  717     # m_popen = mock.Mock()
  718     content = mock.Mock()
  719     m_popen_retval = mock.Mock()
  720     platform_recognized = \
  721         platform.startswith(('linux', 'freebsd', 'openbsd')) \
  722         or platform in ('darwin', 'win32')
  723     with mock.patch('buku.sys') as m_sys, \
  724             mock.patch('buku.Popen', return_value=m_popen_retval) as m_popen, \
  725             mock.patch('buku.shutil.which', return_value=True):
  726         m_sys.platform = platform
  727         from buku import copy_to_clipboard
  728         import subprocess
  729         copy_to_clipboard(content)
  730         if platform_recognized:
  731             m_popen.assert_called_once_with(
  732                 params, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
  733             m_popen_retval.communicate.assert_called_once_with(content)
  734         else:
  735             logging.info('popen is called {} on unrecognized platform'.format(m_popen.call_count))
  736 
  737 
  738 @pytest.mark.parametrize('export_type, exp_res', [
  739     [
  740         'html',
  741         '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n\n'
  742         '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n'
  743         '<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks</H1>\n\n<DL><p>\n'
  744         '    <DT><H3 ADD_DATE="1556430615" LAST_MODIFIED="1556430615" PERSONAL_TOOLBAR_FOLDER="true">buku bookmarks</H3>\n'
  745         '    <DL><p>\n'
  746         '        <DT><A HREF="htttp://example.com" ADD_DATE="1556430615" LAST_MODIFIED="1556430615"></A>\n'
  747         '        <DT><A HREF="htttp://example.org" ADD_DATE="1556430615" LAST_MODIFIED="1556430615"></A>\n'
  748         '        <DT><A HREF="http://google.com" ADD_DATE="1556430615" LAST_MODIFIED="1556430615">Google</A>\n'
  749         '    </DL><p>\n</DL><p>'
  750     ],
  751     ['org', '* [[htttp://example.com][Untitled]]\n* [[htttp://example.org][Untitled]]\n* [[http://google.com][Google]]\n'],
  752     ['markdown', '- [Untitled](htttp://example.com)\n- [Untitled](htttp://example.org)\n- [Google](http://google.com)\n'],
  753     ['random', None],
  754 ])
  755 def test_convert_bookmark_set(export_type, exp_res, monkeypatch):
  756     from buku import convert_bookmark_set
  757     import buku
  758     bms = [
  759         (1, 'htttp://example.com', '', ',', '', 0),
  760         (1, 'htttp://example.org', None, ',', '', 0),
  761         (2, 'http://google.com', 'Google', ',', '', 0)]
  762     if export_type == 'random':
  763         with pytest.raises(AssertionError):
  764             convert_bookmark_set(bms, export_type=export_type)
  765     else:
  766 
  767         def return_fixed_number():
  768             return 1556430615
  769         monkeypatch.setattr(buku.time, 'time', return_fixed_number)
  770         res = convert_bookmark_set(bms, export_type=export_type)
  771         assert res['count'] == 3
  772         assert exp_res == res['data']