2015-08-08 20:10:27 +02:00
|
|
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
|
|
|
|
2017-05-09 21:37:03 +02:00
|
|
|
# Copyright 2015-2017 Antoni Boucher (antoyo) <bouanto@zoho.com>
|
2015-08-08 20:10:27 +02:00
|
|
|
#
|
|
|
|
# This file is part of qutebrowser.
|
|
|
|
#
|
|
|
|
# qutebrowser is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# qutebrowser is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
2017-09-19 22:18:02 +02:00
|
|
|
import attr
|
2015-08-09 01:32:47 +02:00
|
|
|
import pytest
|
2015-08-13 21:55:25 +02:00
|
|
|
import bs4
|
|
|
|
from PyQt5.QtCore import QUrl
|
|
|
|
from PyQt5.QtNetwork import QNetworkRequest
|
2015-08-08 20:10:27 +02:00
|
|
|
|
2016-06-13 10:49:58 +02:00
|
|
|
from qutebrowser.browser.webkit.network import filescheme
|
2017-09-20 10:39:39 +02:00
|
|
|
from qutebrowser.utils import urlutils, utils
|
2015-08-08 20:10:27 +02:00
|
|
|
|
|
|
|
|
2015-08-09 01:32:47 +02:00
|
|
|
@pytest.mark.parametrize('create_file, create_dir, filterfunc, expected', [
|
|
|
|
(True, False, os.path.isfile, True),
|
|
|
|
(True, False, os.path.isdir, False),
|
2015-08-08 20:10:27 +02:00
|
|
|
|
2015-08-09 01:32:47 +02:00
|
|
|
(False, True, os.path.isfile, False),
|
|
|
|
(False, True, os.path.isdir, True),
|
2015-08-08 20:10:27 +02:00
|
|
|
|
2015-08-09 01:32:47 +02:00
|
|
|
(False, False, os.path.isfile, False),
|
|
|
|
(False, False, os.path.isdir, False),
|
|
|
|
])
|
|
|
|
def test_get_file_list(tmpdir, create_file, create_dir, filterfunc, expected):
|
|
|
|
"""Test get_file_list."""
|
|
|
|
path = tmpdir / 'foo'
|
|
|
|
if create_file or create_dir:
|
|
|
|
path.ensure(dir=create_dir)
|
2015-08-08 20:10:27 +02:00
|
|
|
|
2015-08-09 01:32:47 +02:00
|
|
|
all_files = os.listdir(str(tmpdir))
|
2015-08-08 20:10:27 +02:00
|
|
|
|
2015-08-13 21:55:25 +02:00
|
|
|
result = filescheme.get_file_list(str(tmpdir), all_files, filterfunc)
|
2015-08-09 01:32:47 +02:00
|
|
|
item = {'name': 'foo', 'absname': str(path)}
|
|
|
|
assert (item in result) == expected
|
2015-08-13 21:55:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TestIsRoot:
|
|
|
|
|
|
|
|
@pytest.mark.windows
|
|
|
|
@pytest.mark.parametrize('directory, is_root', [
|
2016-03-23 23:56:23 +01:00
|
|
|
('C:\\foo\\bar', False),
|
|
|
|
('C:\\foo\\', False),
|
2015-08-13 21:55:25 +02:00
|
|
|
('C:\\foo', False),
|
|
|
|
('C:\\', True)
|
|
|
|
])
|
|
|
|
def test_windows(self, directory, is_root):
|
|
|
|
assert filescheme.is_root(directory) == is_root
|
|
|
|
|
|
|
|
@pytest.mark.posix
|
|
|
|
@pytest.mark.parametrize('directory, is_root', [
|
2016-03-23 23:56:23 +01:00
|
|
|
('/foo/bar', False),
|
|
|
|
('/foo/', False),
|
2015-08-13 21:55:25 +02:00
|
|
|
('/foo', False),
|
|
|
|
('/', True)
|
|
|
|
])
|
|
|
|
def test_posix(self, directory, is_root):
|
|
|
|
assert filescheme.is_root(directory) == is_root
|
|
|
|
|
|
|
|
|
2016-03-24 18:52:49 +01:00
|
|
|
class TestParentDir:
|
|
|
|
|
|
|
|
@pytest.mark.windows
|
|
|
|
@pytest.mark.parametrize('directory, parent', [
|
|
|
|
('C:\\foo\\bar', 'C:\\foo'),
|
|
|
|
('C:\\foo', 'C:\\'),
|
|
|
|
('C:\\foo\\', 'C:\\'),
|
|
|
|
('C:\\', 'C:\\'),
|
|
|
|
])
|
|
|
|
def test_windows(self, directory, parent):
|
|
|
|
assert filescheme.parent_dir(directory) == parent
|
|
|
|
|
|
|
|
@pytest.mark.posix
|
|
|
|
@pytest.mark.parametrize('directory, parent', [
|
|
|
|
('/home/foo', '/home'),
|
|
|
|
('/home', '/'),
|
|
|
|
('/home/', '/'),
|
|
|
|
('/', '/'),
|
|
|
|
])
|
|
|
|
def test_posix(self, directory, parent):
|
|
|
|
assert filescheme.parent_dir(directory) == parent
|
|
|
|
|
|
|
|
|
2016-03-24 00:53:23 +01:00
|
|
|
def _file_url(path):
|
|
|
|
"""Return a file:// url (as string) for the given LocalPath.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
path: The filepath as LocalPath (as handled by py.path)
|
|
|
|
"""
|
2016-05-29 22:44:40 +02:00
|
|
|
return urlutils.file_url(str(path))
|
2016-03-24 00:53:23 +01:00
|
|
|
|
|
|
|
|
2015-08-13 21:55:25 +02:00
|
|
|
class TestDirbrowserHtml:
|
|
|
|
|
2017-09-19 22:18:02 +02:00
|
|
|
@attr.s
|
|
|
|
class Parsed:
|
|
|
|
|
|
|
|
parent = attr.ib()
|
|
|
|
folders = attr.ib()
|
|
|
|
files = attr.ib()
|
|
|
|
|
|
|
|
@attr.s
|
|
|
|
class Item:
|
|
|
|
|
|
|
|
link = attr.ib()
|
|
|
|
text = attr.ib()
|
2015-08-13 21:55:25 +02:00
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def parser(self):
|
|
|
|
"""Provide a function to get a parsed dirbrowser document."""
|
|
|
|
def parse(path):
|
2016-07-28 07:19:09 +02:00
|
|
|
html = filescheme.dirbrowser_html(path).decode('utf-8')
|
2015-08-13 21:55:25 +02:00
|
|
|
soup = bs4.BeautifulSoup(html, 'html.parser')
|
|
|
|
print(soup.prettify())
|
|
|
|
container = soup('div', id='dirbrowserContainer')[0]
|
|
|
|
|
2015-08-14 01:54:23 +02:00
|
|
|
parent_elem = container('ul', class_='parent')
|
2016-03-29 12:36:43 +02:00
|
|
|
if not parent_elem:
|
2015-08-13 21:55:25 +02:00
|
|
|
parent = None
|
|
|
|
else:
|
2015-08-14 01:54:23 +02:00
|
|
|
parent = parent_elem[0].li.a.string
|
2015-08-13 21:55:25 +02:00
|
|
|
|
|
|
|
folders = []
|
|
|
|
files = []
|
|
|
|
|
|
|
|
for li in container('ul', class_='folders')[0]('li'):
|
|
|
|
item = self.Item(link=li.a['href'], text=str(li.a.string))
|
|
|
|
folders.append(item)
|
|
|
|
|
|
|
|
for li in container('ul', class_='files')[0]('li'):
|
|
|
|
item = self.Item(link=li.a['href'], text=str(li.a.string))
|
|
|
|
files.append(item)
|
|
|
|
|
|
|
|
return self.Parsed(parent=parent, folders=folders, files=files)
|
|
|
|
|
|
|
|
return parse
|
|
|
|
|
|
|
|
def test_basic(self):
|
2016-07-28 07:19:09 +02:00
|
|
|
html = filescheme.dirbrowser_html(os.getcwd()).decode('utf-8')
|
2015-08-13 21:55:25 +02:00
|
|
|
soup = bs4.BeautifulSoup(html, 'html.parser')
|
|
|
|
print(soup.prettify())
|
|
|
|
container = soup.div
|
|
|
|
assert container['id'] == 'dirbrowserContainer'
|
|
|
|
title_elem = container('div', id='dirbrowserTitle')[0]
|
|
|
|
title_text = title_elem('p', id='dirbrowserTitleText')[0].text
|
|
|
|
assert title_text == 'Browse directory: {}'.format(os.getcwd())
|
|
|
|
|
2015-08-16 19:03:20 +02:00
|
|
|
def test_icons(self, monkeypatch):
|
|
|
|
"""Make sure icon paths are correct file:// URLs."""
|
2017-03-01 11:33:41 +01:00
|
|
|
monkeypatch.setattr(filescheme.jinja.utils, 'resource_filename',
|
2016-04-27 18:30:54 +02:00
|
|
|
lambda name: '/test path/foo.svg')
|
2015-08-16 19:03:20 +02:00
|
|
|
|
2016-07-28 07:19:09 +02:00
|
|
|
html = filescheme.dirbrowser_html(os.getcwd()).decode('utf-8')
|
2015-08-16 19:03:20 +02:00
|
|
|
soup = bs4.BeautifulSoup(html, 'html.parser')
|
|
|
|
print(soup.prettify())
|
|
|
|
|
|
|
|
css = soup.html.head.style.string
|
|
|
|
assert "background-image: url('file:///test%20path/foo.svg');" in css
|
|
|
|
|
2015-08-13 21:55:25 +02:00
|
|
|
def test_empty(self, tmpdir, parser):
|
|
|
|
parsed = parser(str(tmpdir))
|
|
|
|
assert parsed.parent
|
|
|
|
assert not parsed.folders
|
|
|
|
assert not parsed.files
|
|
|
|
|
|
|
|
def test_files(self, tmpdir, parser):
|
|
|
|
foo_file = tmpdir / 'foo'
|
|
|
|
bar_file = tmpdir / 'bar'
|
|
|
|
foo_file.ensure()
|
|
|
|
bar_file.ensure()
|
|
|
|
|
|
|
|
parsed = parser(str(tmpdir))
|
|
|
|
assert parsed.parent
|
|
|
|
assert not parsed.folders
|
2016-03-24 00:53:23 +01:00
|
|
|
foo_item = self.Item(_file_url(foo_file), foo_file.relto(tmpdir))
|
|
|
|
bar_item = self.Item(_file_url(bar_file), bar_file.relto(tmpdir))
|
2015-08-13 21:55:25 +02:00
|
|
|
assert parsed.files == [bar_item, foo_item]
|
|
|
|
|
2015-09-24 06:45:33 +02:00
|
|
|
def test_html_special_chars(self, tmpdir, parser):
|
|
|
|
special_file = tmpdir / 'foo&bar'
|
|
|
|
special_file.ensure()
|
|
|
|
|
|
|
|
parsed = parser(str(tmpdir))
|
2016-03-24 00:53:23 +01:00
|
|
|
item = self.Item(_file_url(special_file), special_file.relto(tmpdir))
|
2015-09-24 06:45:33 +02:00
|
|
|
assert parsed.files == [item]
|
|
|
|
|
2015-08-13 21:55:25 +02:00
|
|
|
def test_dirs(self, tmpdir, parser):
|
|
|
|
foo_dir = tmpdir / 'foo'
|
|
|
|
bar_dir = tmpdir / 'bar'
|
|
|
|
foo_dir.ensure(dir=True)
|
|
|
|
bar_dir.ensure(dir=True)
|
|
|
|
|
|
|
|
parsed = parser(str(tmpdir))
|
|
|
|
assert parsed.parent
|
|
|
|
assert not parsed.files
|
2016-03-24 00:53:23 +01:00
|
|
|
foo_item = self.Item(_file_url(foo_dir), foo_dir.relto(tmpdir))
|
|
|
|
bar_item = self.Item(_file_url(bar_dir), bar_dir.relto(tmpdir))
|
2015-08-13 21:55:25 +02:00
|
|
|
assert parsed.folders == [bar_item, foo_item]
|
|
|
|
|
|
|
|
def test_mixed(self, tmpdir, parser):
|
|
|
|
foo_file = tmpdir / 'foo'
|
|
|
|
bar_dir = tmpdir / 'bar'
|
|
|
|
foo_file.ensure()
|
|
|
|
bar_dir.ensure(dir=True)
|
|
|
|
|
|
|
|
parsed = parser(str(tmpdir))
|
2016-03-24 00:53:23 +01:00
|
|
|
foo_item = self.Item(_file_url(foo_file), foo_file.relto(tmpdir))
|
|
|
|
bar_item = self.Item(_file_url(bar_dir), bar_dir.relto(tmpdir))
|
2015-08-13 21:55:25 +02:00
|
|
|
assert parsed.parent
|
|
|
|
assert parsed.files == [foo_item]
|
|
|
|
assert parsed.folders == [bar_item]
|
|
|
|
|
|
|
|
def test_root_dir(self, tmpdir, parser):
|
2017-09-20 10:39:39 +02:00
|
|
|
root_dir = 'C:\\' if utils.is_windows else '/'
|
2015-08-13 21:55:25 +02:00
|
|
|
parsed = parser(root_dir)
|
|
|
|
assert not parsed.parent
|
|
|
|
|
|
|
|
def test_oserror(self, mocker):
|
2016-06-13 10:49:58 +02:00
|
|
|
m = mocker.patch('qutebrowser.browser.webkit.network.filescheme.'
|
|
|
|
'os.listdir')
|
2015-08-13 21:55:25 +02:00
|
|
|
m.side_effect = OSError('Error message')
|
2016-07-28 07:19:09 +02:00
|
|
|
html = filescheme.dirbrowser_html('').decode('utf-8')
|
2015-08-13 21:55:25 +02:00
|
|
|
soup = bs4.BeautifulSoup(html, 'html.parser')
|
|
|
|
print(soup.prettify())
|
2015-10-17 18:29:13 +02:00
|
|
|
error_msg = soup('p', id='error-message-text')[0].string
|
2015-08-13 21:55:25 +02:00
|
|
|
assert error_msg == 'Error message'
|
|
|
|
|
|
|
|
|
|
|
|
class TestFileSchemeHandler:
|
|
|
|
|
|
|
|
def test_dir(self, tmpdir):
|
|
|
|
url = QUrl.fromLocalFile(str(tmpdir))
|
|
|
|
req = QNetworkRequest(url)
|
|
|
|
handler = filescheme.FileSchemeHandler(win_id=0)
|
|
|
|
reply = handler.createRequest(None, req, None)
|
2015-08-16 18:28:46 +02:00
|
|
|
# The URL will always use /, even on Windows - so we force this here
|
|
|
|
# too.
|
|
|
|
tmpdir_path = str(tmpdir).replace(os.sep, '/')
|
|
|
|
assert reply.readAll() == filescheme.dirbrowser_html(tmpdir_path)
|
2015-08-13 21:55:25 +02:00
|
|
|
|
|
|
|
def test_file(self, tmpdir):
|
|
|
|
filename = tmpdir / 'foo'
|
|
|
|
filename.ensure()
|
|
|
|
url = QUrl.fromLocalFile(str(filename))
|
|
|
|
req = QNetworkRequest(url)
|
|
|
|
handler = filescheme.FileSchemeHandler(win_id=0)
|
|
|
|
reply = handler.createRequest(None, req, None)
|
|
|
|
assert reply is None
|