mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
Merge branch 'master' of salsa.debian.org:freedombox-team/plinth
This commit is contained in:
commit
cb43d5ad09
36
actions/i2p
36
actions/i2p
@ -23,7 +23,7 @@ import argparse
|
||||
import os
|
||||
|
||||
from plinth import action_utils, cfg
|
||||
from plinth.modules.i2p.helpers import TunnelEditor
|
||||
from plinth.modules.i2p.helpers import RouterEditor, TunnelEditor
|
||||
|
||||
cfg.read()
|
||||
module_config_path = os.path.join(cfg.config_dir, 'modules-enabled')
|
||||
@ -43,6 +43,9 @@ def parse_arguments():
|
||||
'add-favorite', help='Add an eepsite to the list of favorites')
|
||||
subparser.add_argument('--name', help='Name of the entry', required=True)
|
||||
subparser.add_argument('--url', help='URL of the entry', required=True)
|
||||
subparser.add_argument('--description', help='Short description',
|
||||
required=False)
|
||||
subparser.add_argument('--icon', help='URL to icon', required=False)
|
||||
|
||||
subparser = subparsers.add_parser('set-tunnel-property',
|
||||
help='Modify configuration of a tunnel')
|
||||
@ -87,36 +90,11 @@ def subcommand_add_favorite(arguments):
|
||||
:param arguments:
|
||||
:type arguments:
|
||||
"""
|
||||
router_config_path = os.path.join(I2P_CONF_DIR, 'router.config')
|
||||
# Read config
|
||||
with open(router_config_path) as config_file:
|
||||
config_lines = config_file.readlines()
|
||||
|
||||
found_favorites = False
|
||||
url = arguments.url
|
||||
new_favorite = '{name},{description},{url},{icon},'.format(
|
||||
name=arguments.name, description='', url=arguments.url,
|
||||
icon='/themes/console/images/eepsite.png')
|
||||
for i in range(len(config_lines)):
|
||||
line = config_lines[i]
|
||||
|
||||
# Find favorites line
|
||||
if line.startswith('routerconsole.favorites'):
|
||||
found_favorites = True
|
||||
if url in line:
|
||||
print('URL already in favorites')
|
||||
exit(0)
|
||||
|
||||
# Append favorite
|
||||
config_lines[i] = line.strip() + new_favorite + '\n'
|
||||
break
|
||||
|
||||
if not found_favorites:
|
||||
config_lines.append('routerconsole.favorites=' + new_favorite + '\n')
|
||||
|
||||
# Update config
|
||||
with open(router_config_path, mode='w') as config_file:
|
||||
config_file.writelines(config_lines)
|
||||
editor = RouterEditor()
|
||||
editor.read_conf().add_favorite(arguments.name, url, arguments.description,
|
||||
arguments.icon).write_conf()
|
||||
|
||||
print('Added {} to favorites'.format(url))
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from plinth import action_utils, actions, frontpage
|
||||
from plinth import service as service_module
|
||||
from plinth.menu import main_menu
|
||||
from plinth.modules.i2p.resources import FAVORITES
|
||||
from plinth.modules.users import register_group
|
||||
|
||||
from .manifest import backup, clients
|
||||
@ -59,13 +60,6 @@ proxies_service = None
|
||||
|
||||
manual_page = 'I2P'
|
||||
|
||||
additional_favorites = [
|
||||
('Searx instance', 'http://ransack.i2p'),
|
||||
('Torrent tracker', 'http://tracker2.postman.i2p'),
|
||||
('YaCy Legwork', 'http://legwork.i2p'),
|
||||
('YaCy Seeker', 'http://seeker.i2p'),
|
||||
]
|
||||
|
||||
tunnels_to_manage = {
|
||||
'I2P HTTP Proxy': 'i2p-http-proxy-freedombox',
|
||||
'I2P HTTPS Proxy': 'i2p-https-proxy-freedombox',
|
||||
@ -101,14 +95,22 @@ def setup(helper, old_version=None):
|
||||
|
||||
helper.call('post', disable)
|
||||
# Add favorites to the configuration
|
||||
for fav_name, fav_url in additional_favorites:
|
||||
helper.call('post', actions.superuser_run, 'i2p', [
|
||||
for fav in FAVORITES:
|
||||
args = [
|
||||
'add-favorite',
|
||||
'--name',
|
||||
fav_name,
|
||||
fav.get('name'),
|
||||
'--url',
|
||||
fav_url,
|
||||
])
|
||||
fav.get('url'),
|
||||
]
|
||||
if 'icon' in fav:
|
||||
args.extend(['--icon', fav.get('icon')])
|
||||
|
||||
if 'description' in fav:
|
||||
args.extend(['--description', fav.get('description')])
|
||||
|
||||
helper.call('post', actions.superuser_run, 'i2p', args)
|
||||
|
||||
|
||||
# Tunnels to all interfaces
|
||||
for tunnel in tunnels_to_manage:
|
||||
|
||||
@ -19,12 +19,14 @@ Various helpers for the I2P app.
|
||||
|
||||
import os
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
import augeas
|
||||
|
||||
I2P_CONF_DIR = '/var/lib/i2p/i2p-config'
|
||||
FILE_TUNNEL_CONF = os.path.join(I2P_CONF_DIR, 'i2ptunnel.config')
|
||||
TUNNEL_IDX_REGEX = re.compile(r'tunnel.(\d+).name$')
|
||||
I2P_ROUTER_CONF = os.path.join(I2P_CONF_DIR, 'router.config')
|
||||
|
||||
|
||||
class TunnelEditor():
|
||||
@ -133,3 +135,110 @@ class TunnelEditor():
|
||||
|
||||
def __setitem__(self, tunnel_prop, value):
|
||||
self.aug.set(self.calc_prop_path(tunnel_prop), value)
|
||||
|
||||
|
||||
class RouterEditor():
|
||||
"""Helper to edit I2P router configuration file using augeas.
|
||||
|
||||
:type aug: augeas.Augeas
|
||||
|
||||
"""
|
||||
|
||||
FAVORITE_PROP = 'routerconsole.favorites'
|
||||
FAVORITE_TUPLE_SIZE = 4
|
||||
|
||||
def __init__(self, filename=None):
|
||||
self.conf_filename = filename or I2P_ROUTER_CONF
|
||||
self.aug = None
|
||||
|
||||
def read_conf(self):
|
||||
"""Load an instance of Augeaus for processing APT configuration.
|
||||
|
||||
Chainable method.
|
||||
|
||||
"""
|
||||
self.aug = augeas.Augeas(
|
||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
|
||||
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
|
||||
self.conf_filename)
|
||||
self.aug.load()
|
||||
return self
|
||||
|
||||
def write_conf(self):
|
||||
"""Write changes to the configuration file to disk.
|
||||
|
||||
Chainable method.
|
||||
|
||||
"""
|
||||
self.aug.save()
|
||||
return self
|
||||
|
||||
@property
|
||||
def favorite_property(self):
|
||||
"""Return the favourites property from configuration file."""
|
||||
return '/files{filename}/{prop}'.format(filename=self.conf_filename,
|
||||
prop=self.FAVORITE_PROP)
|
||||
|
||||
def add_favorite(self, name, url, description=None, icon=None):
|
||||
"""Add a favorite to the router configuration file.
|
||||
|
||||
Favorites are in a single string and separated by ','. none of the
|
||||
incoming params can therefore use commas. I2P replaces the commas by
|
||||
dots.
|
||||
|
||||
That's ok for the name and description, but not for the url and icon.
|
||||
|
||||
:type name: basestring
|
||||
:type url: basestring
|
||||
:type description: basestring
|
||||
:type icon: basestring
|
||||
|
||||
"""
|
||||
if not description:
|
||||
description = ''
|
||||
|
||||
if not icon:
|
||||
icon = '/themes/console/images/eepsite.png'
|
||||
|
||||
if ',' in url:
|
||||
raise ValueError('URL cannot contain commas')
|
||||
|
||||
if ',' in icon:
|
||||
raise ValueError('Icon cannot contain commas')
|
||||
|
||||
name = name.replace(',', '.')
|
||||
description = description.replace(',', '.')
|
||||
|
||||
prop = self.favorite_property
|
||||
favorites = self.aug.get(prop) or ''
|
||||
new_favorite = '{name},{description},{url},{icon},'.format(
|
||||
name=name, description=description, url=url, icon=icon)
|
||||
self.aug.set(prop, favorites + new_favorite)
|
||||
return self
|
||||
|
||||
def get_favorites(self):
|
||||
"""Return list of favorites."""
|
||||
favs_string = self.aug.get(self.favorite_property) or ''
|
||||
favs_split = favs_string.split(',')
|
||||
|
||||
# There's a trailing comma --> 1 extra
|
||||
favs_len = len(favs_split)
|
||||
if favs_len > 0:
|
||||
favs_split = favs_split[:-1]
|
||||
favs_len = len(favs_split)
|
||||
|
||||
if favs_len % self.FAVORITE_TUPLE_SIZE:
|
||||
raise SyntaxError("Invalid number of fields in favorite line")
|
||||
|
||||
favs = OrderedDict()
|
||||
for index in range(0, favs_len, self.FAVORITE_TUPLE_SIZE):
|
||||
next_index = index + self.FAVORITE_TUPLE_SIZE
|
||||
name, description, url, icon = favs_split[index:next_index]
|
||||
favs[url] = {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'icon': icon
|
||||
}
|
||||
|
||||
return favs
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Application manifest for I2P.
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
144
plinth/modules/i2p/resources.py
Normal file
144
plinth/modules/i2p/resources.py
Normal file
@ -0,0 +1,144 @@
|
||||
#
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Pre-defined list of favorites for I2P and some additional favorites.
|
||||
"""
|
||||
|
||||
DEFAULT_FAVORITES = [
|
||||
{
|
||||
'name': 'anoncoin.i2p',
|
||||
'description': 'The Anoncoin project',
|
||||
'icon': '/themes/console/images/anoncoin_32.png',
|
||||
'url': 'http://anoncoin.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'Dev Builds',
|
||||
'description': 'Development builds of I2P',
|
||||
'icon': '/themes/console/images/script_gear.png',
|
||||
'url': 'http://bobthebuilder.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'Dev Forum',
|
||||
'description': 'Development forum',
|
||||
'icon': '/themes/console/images/group_gear.png',
|
||||
'url': 'http://zzz.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'echelon.i2p',
|
||||
'description': 'I2P Applications',
|
||||
'icon': '/themes/console/images/box_open.png',
|
||||
'url': 'http://echelon.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'exchanged.i2p',
|
||||
'description': 'Anonymous cryptocurrency exchange',
|
||||
'icon': '/themes/console/images/exchanged.png',
|
||||
'url': 'http://exchanged.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'I2P Bug Reports',
|
||||
'description': 'Bug tracker',
|
||||
'icon': '/themes/console/images/bug.png',
|
||||
'url': 'http://trac.i2p2.i2p/report/1'
|
||||
},
|
||||
{
|
||||
'name': 'I2P FAQ',
|
||||
'description': 'Frequently Asked Questions',
|
||||
'icon': '/themes/console/images/question.png',
|
||||
'url': 'http://i2p-projekt.i2p/faq'
|
||||
},
|
||||
{
|
||||
'name': 'I2P Forum',
|
||||
'description': 'Community forum',
|
||||
'icon': '/themes/console/images/group.png',
|
||||
'url': 'http://i2pforum.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'I2P Plugins',
|
||||
'description': 'Add-on directory',
|
||||
'icon': '/themes/console/images/info/plugin_link.png',
|
||||
'url': 'http://i2pwiki.i2p/index.php?title=Plugins'
|
||||
},
|
||||
{
|
||||
'name': 'I2P Technical Docs',
|
||||
'description': 'Technical documentation',
|
||||
'icon': '/themes/console/images/education.png',
|
||||
'url': 'http://i2p-projekt.i2p/how'
|
||||
},
|
||||
{
|
||||
'name': 'I2P Wiki',
|
||||
'description': 'Anonymous wiki - share the knowledge',
|
||||
'icon': '/themes/console/images/i2pwiki_logo.png',
|
||||
'url': 'http://i2pwiki.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'Planet I2P',
|
||||
'description': 'I2P News',
|
||||
'icon': '/themes/console/images/world.png',
|
||||
'url': 'http://planet.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'PrivateBin',
|
||||
'description': 'Encrypted I2P Pastebin',
|
||||
'icon': '/themes/console/images/paste_plain.png',
|
||||
'url': 'http://paste.crypthost.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'Project Website',
|
||||
'description': 'I2P home page',
|
||||
'icon': '/themes/console/images/info_rhombus.png',
|
||||
'url': 'http://i2p-projekt.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'stats.i2p',
|
||||
'description': 'I2P Network Statistics',
|
||||
'icon': '/themes/console/images/chart_line.png',
|
||||
'url': 'http://stats.i2p/cgi-bin/dashboard.cgi'
|
||||
},
|
||||
{
|
||||
'name': 'The Tin Hat',
|
||||
'description': 'Privacy guides and tutorials',
|
||||
'icon': '/themes/console/images/thetinhat.png',
|
||||
'url': 'http://secure.thetinhat.i2p/'
|
||||
},
|
||||
{
|
||||
'name': 'Trac Wiki',
|
||||
'description': '',
|
||||
'icon': '/themes/console/images/billiard_marker.png',
|
||||
'url': 'http://trac.i2p2.i2p/'
|
||||
}
|
||||
]
|
||||
ADDITIONAL_FAVORITES = [
|
||||
{
|
||||
'name': 'Searx instance',
|
||||
'url': 'http://ransack.i2p'
|
||||
},
|
||||
{
|
||||
'name': 'Torrent tracker',
|
||||
'url': 'http://tracker2.postman.i2p'
|
||||
},
|
||||
{
|
||||
'name': 'YaCy Legwork',
|
||||
'url': 'http://legwork.i2p'
|
||||
},
|
||||
{
|
||||
'name': 'YaCy Seeker',
|
||||
'url': 'http://seeker.i2p'
|
||||
},
|
||||
]
|
||||
|
||||
FAVORITES = DEFAULT_FAVORITES + ADDITIONAL_FAVORITES
|
||||
@ -0,0 +1,23 @@
|
||||
#
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Common parts for all I2P tests.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
DATA_DIR = Path(__file__).parent / 'data'
|
||||
23
plinth/modules/i2p/tests/data/router.config
Normal file
23
plinth/modules/i2p/tests/data/router.config
Normal file
@ -0,0 +1,23 @@
|
||||
# NOTE: This I2P config file must use UTF-8 encoding
|
||||
i2np.lastIPChange=1555091394049
|
||||
i2np.ntcp2.iv=i3yLM2tPW6QH5h4YYZ8EWQ==
|
||||
i2np.ntcp2.sp=j1K18jMDa5SPH23R2cHMJ-dUyPdo~uooZp6Uz06qP0k=
|
||||
i2np.udp.internalPort=18778
|
||||
i2np.udp.port=18778
|
||||
jbigi.lastProcessor=Haswell Celeron/Pentium w/ AVX model 60/64
|
||||
router.blocklistVersion=1523108115000
|
||||
router.firstInstalled=1555091372597
|
||||
router.firstVersion=0.9.38
|
||||
router.inboundPool.randomKey=c1BGKzCBpxYfsH0AiEMIS39zYWzyBuWO9lYTqeA91dk=
|
||||
router.outboundPool.randomKey=Of0jkHuGeUAHr~NoIAQbY930fbYacb4NyX3CjbVKKFI=
|
||||
router.passwordManager.migrated=true
|
||||
router.previousVersion=0.9.38
|
||||
router.startup.jetty9.migrated=true
|
||||
router.updateDisabled=true
|
||||
router.updateLastInstalled=1555091372597
|
||||
routerconsole.country=
|
||||
routerconsole.favorites=anoncoin.i2p,The Anoncoin project,http://anoncoin.i2p/,/themes/console/images/anoncoin_32.png,Dev Builds,Development builds of I2P,http://bobthebuilder.i2p/,/themes/console/images/script_gear.png,Dev Forum,Development forum,http://zzz.i2p/,/themes/console/images/group_gear.png,echelon.i2p,I2P Applications,http://echelon.i2p/,/themes/console/images/box_open.png,exchanged.i2p,Anonymous cryptocurrency exchange,http://exchanged.i2p/,/themes/console/images/exchanged.png,I2P Bug Reports,Bug tracker,http://trac.i2p2.i2p/report/1,/themes/console/images/bug.png,I2P FAQ,Frequently Asked Questions,http://i2p-projekt.i2p/faq,/themes/console/images/question.png,I2P Forum,Community forum,http://i2pforum.i2p/,/themes/console/images/group.png,I2P Plugins,Add-on directory,http://i2pwiki.i2p/index.php?title=Plugins,/themes/console/images/info/plugin_link.png,I2P Technical Docs,Technical documentation,http://i2p-projekt.i2p/how,/themes/console/images/education.png,I2P Wiki,Anonymous wiki - share the knowledge,http://i2pwiki.i2p/,/themes/console/images/i2pwiki_logo.png,Planet I2P,I2P News,http://planet.i2p/,/themes/console/images/world.png,PrivateBin,Encrypted I2P Pastebin,http://paste.crypthost.i2p/,/themes/console/images/paste_plain.png,Project Website,I2P home page,http://i2p-projekt.i2p/,/themes/console/images/info_rhombus.png,stats.i2p,I2P Network Statistics,http://stats.i2p/cgi-bin/dashboard.cgi,/themes/console/images/chart_line.png,The Tin Hat,Privacy guides and tutorials,http://secure.thetinhat.i2p/,/themes/console/images/thetinhat.png,Trac Wiki,,http://trac.i2p2.i2p/,/themes/console/images/billiard_marker.png,
|
||||
routerconsole.lang=en
|
||||
routerconsole.newsLastChecked=1555093599462
|
||||
routerconsole.newsLastUpdated=1553195540000
|
||||
routerconsole.welcomeWizardComplete=true
|
||||
@ -1,17 +1,18 @@
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program 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 Affero General Public License for more details.
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# This program 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Unit tests for helpers of I2P application.
|
||||
|
||||
88
plinth/modules/i2p/tests/test_router_editor.py
Normal file
88
plinth/modules/i2p/tests/test_router_editor.py
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# This file is part of FreedomBox.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Test I2P router configuration editing helper.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from plinth.modules.i2p.helpers import RouterEditor
|
||||
from plinth.modules.i2p.tests import DATA_DIR
|
||||
|
||||
ROUTER_CONF_PATH = str(DATA_DIR / 'router.config')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def editor():
|
||||
"""Return editor instance object for each test."""
|
||||
return RouterEditor(ROUTER_CONF_PATH)
|
||||
|
||||
|
||||
def test_count_favorites(editor):
|
||||
"""Test counting favorites."""
|
||||
editor.read_conf()
|
||||
favorites = editor.get_favorites()
|
||||
assert len(favorites.keys()) == 17
|
||||
|
||||
|
||||
def test_add_normal_favorite(editor):
|
||||
"""Test adding a normal favorite."""
|
||||
editor.read_conf()
|
||||
name = 'Somewhere'
|
||||
url = 'http://somewhere-again.i2p'
|
||||
description = "Just somewhere else"
|
||||
editor.add_favorite(name, url, description)
|
||||
|
||||
favorites = editor.get_favorites()
|
||||
assert url in favorites
|
||||
favorite = favorites[url]
|
||||
assert favorite['name'] == name
|
||||
assert favorite['description'] == description
|
||||
|
||||
assert len(favorites) == 18
|
||||
|
||||
|
||||
def test_add_favorite_with_comma(editor):
|
||||
"""Test adding a favorite with common in its name."""
|
||||
editor.read_conf()
|
||||
name = 'Name,with,comma'
|
||||
expected_name = name.replace(',', '.')
|
||||
url = 'http://url-without-comma.i2p'
|
||||
description = "Another,comma,to,play,with"
|
||||
expected_description = description.replace(',', '.')
|
||||
|
||||
editor.add_favorite(name, url, description)
|
||||
|
||||
favorites = editor.get_favorites()
|
||||
assert url in favorites
|
||||
favorite = favorites[url]
|
||||
assert favorite['name'] == expected_name
|
||||
assert favorite['description'] == expected_description
|
||||
|
||||
assert len(favorites) == 18
|
||||
|
||||
|
||||
def test_add_fav_to_empty_config(editor):
|
||||
"""Test adding favorite to empty configuration."""
|
||||
editor.conf_filename = '/tmp/inexistent.conf'
|
||||
editor.read_conf()
|
||||
assert not editor.get_favorites()
|
||||
|
||||
name = 'Test Favorite'
|
||||
url = 'http://test-fav.i2p'
|
||||
editor.add_favorite(name, url)
|
||||
assert len(editor.get_favorites()) == 1
|
||||
Loading…
x
Reference in New Issue
Block a user