def _ensure_logged_in(browser):
    """Ensure that password dialog is answered and we can interact."""
    url = functional.base_url + '/deluge'

    def service_is_available():
        if browser.is_element_present_by_xpath(
                '//h1[text()="Service Unavailable"]'):
            functional.access_url(browser, 'deluge')
            return False

        return True

    if browser.url != url:
        browser.visit(url)
        # After a backup restore, service may not be available immediately
        functional.eventually(service_is_available)

        time.sleep(1)  # Wait for Ext.js application in initialize

    if _get_active_window_title(browser) != 'Login':
        return

    browser.find_by_id('_password').first.fill('deluge')
    _click_active_window_button(browser, 'Login')

    assert functional.eventually(
        lambda: _get_active_window_title(browser) != 'Login')
    functional.eventually(browser.is_element_not_present_by_css,
                          args=['#add.x-item-disabled'],
                          timeout=0.3)
def _open_connection_manager(browser):
    """Open the connection manager dialog if not already open."""
    title = 'Connection Manager'
    if _get_active_window_title(browser) == title:
        return

    browser.find_by_css('button.x-deluge-connection-manager').first.click()
    functional.eventually(lambda: _get_active_window_title(browser) == title)
예제 #3
0
def _load_site(browser):
    """Visit WordPress site and wait until becomes available."""
    functional.visit(browser, '/wordpress/wp-admin/')

    def loaded():
        browser.reload()
        title_node = browser.find_by_css('title')
        return (not title_node or '404' not in title_node[0].text)

    functional.eventually(loaded)
예제 #4
0
def _configure_domain(browser, domain):
    functional.nav_to_module(browser, 'dynamicdns')
    browser.find_link_by_href(
        '/plinth/sys/dynamicdns/configure/').first.click()
    browser.find_by_id('id_dynamicdns_domain').fill(domain)
    functional.submit(browser)

    # After a domain name change, Let's Encrypt will restart the web
    # server and could cause a connection failure.
    time.sleep(1)
    functional.eventually(functional.nav_to_module, [browser, 'dynamicdns'])
예제 #5
0
def _get_number_of_ed2k_files(browser):
    """Return the number of ed2k files currently in mldonkey."""
    functional.visit(browser, '/mldonkey/')

    with browser.get_iframe('commands') as commands_frame:
        commands_frame.find_by_xpath(
            '//tr//td[contains(text(), "Transfers")]').click()

    with browser.get_iframe('output') as output_frame:
        functional.eventually(output_frame.find_by_css, ['.downloaded'])
        return len(output_frame.find_by_css('.dl-1')) + len(
            output_frame.find_by_css('.dl-2'))
예제 #6
0
def _upload_sample_torrent(browser):
    """Upload a sample torrent into transmission."""
    functional.visit(browser, '/transmission')
    file_path = os.path.join(os.path.dirname(__file__), 'data',
                             'sample.torrent')
    browser.click_link_by_id('toolbar-open')
    functional.eventually(browser.is_element_not_present_by_css,
                          args=['#upload-container[style="display: none;"]'])
    browser.attach_file('torrent_files[]', [file_path])
    browser.click_link_by_id('upload_confirm_button')
    functional.eventually(browser.is_element_present_by_css,
                          args=['#torrent_list .torrent'])
예제 #7
0
def _jsxc_add_contact(browser):
    """Add a contact to JSXC user's roster."""
    functional.set_domain_name(browser, 'localhost')
    functional.install(browser, 'jsxc')
    _jsxc_login(browser)
    functional.eventually(_is_jsxc_buddy_list_loaded, args=[browser])
    new = browser.find_by_text('new contact')
    if new:  # roster is empty
        new.first.click()
        browser.find_by_id('jsxc_username').fill('alice@localhost')
        browser.find_by_text('Add').first.click()
        assert functional.eventually(browser.find_by_text, ['alice@localhost'])
예제 #8
0
def _add_folder(browser, folder_name, folder_path):
    """Add a new folder to Synthing."""
    _load_main_interface(browser)
    add_folder_xpath = '//button[contains(@ng-click, "addFolder")]'
    browser.find_by_xpath(add_folder_xpath).click()

    folder_dialog = browser.find_by_id('editFolder').first
    functional.eventually(lambda: folder_dialog.visible)
    browser.find_by_id('folderLabel').fill(folder_name)
    browser.find_by_id('folderPath').fill(folder_path)
    save_folder_xpath = './/button[contains(@ng-click, "saveFolder")]'
    folder_dialog.find_by_xpath(save_folder_xpath).first.click()
    functional.eventually(lambda: not folder_dialog.visible)
예제 #9
0
def test_private_mode(session_browser):
    """Test that site is not available without login in public mode."""
    functional.app_enable(session_browser, 'wordpress')
    _enable_public_mode(session_browser, False)

    def login_prompt():
        _load_site(session_browser)
        return functional.is_login_prompt(session_browser)

    try:
        functional.logout(session_browser)
        functional.eventually(login_prompt)
    finally:
        functional.login(session_browser)
예제 #10
0
def _write_post(browser, title):
    """Create a blog post in WordPress site."""
    post = _get_post(browser, title)
    if post:
        _delete_post(browser, title)

    functional.visit(browser, '/wordpress/wp-admin/post-new.php')
    if browser.find_by_css('.edit-post-welcome-guide'):
        browser.find_by_css('.components-modal__header button')[0].click()

    browser.find_by_id('post-title-0').fill(title)
    browser.find_by_css('.editor-post-publish-button__button')[0].click()
    functional.eventually(browser.find_by_css, ['.editor-post-publish-button'])
    browser.find_by_css('.editor-post-publish-button')[0].click()
예제 #11
0
def _remove_folder(browser, folder_name):
    """Remove a folder from Synthing."""
    _load_main_interface(browser)

    # Find folder
    folder = None
    for current_folder in browser.find_by_css('#folders > .panel'):
        name = current_folder.find_by_css('.panel-title-text span').first.text
        if name == folder_name:
            folder = current_folder
            break

    # Edit folder button
    folder.find_by_css('button.panel-heading').first.click()
    functional.eventually(lambda: folder.find_by_css('div.collapse.in'))
    edit_folder_xpath = './/button[contains(@ng-click, "editFolder")]'
    edit_folder_button = folder.find_by_xpath(edit_folder_xpath).first
    edit_folder_button.click()

    # Edit folder dialog
    folder_dialog = browser.find_by_id('editFolder').first
    functional.eventually(lambda: folder_dialog.visible)
    remove_button_xpath = './/button[contains(@data-target, "remove-folder")]'
    folder_dialog.find_by_xpath(remove_button_xpath).first.click()

    # Remove confirmation dialog
    remove_folder_dialog = browser.find_by_id('remove-folder-confirmation')
    functional.eventually(lambda: remove_folder_dialog.visible)
    remove_button_xpath = './/button[contains(@ng-click, "deleteFolder")]'
    remove_folder_dialog.find_by_xpath(remove_button_xpath).first.click()

    functional.eventually(lambda: not folder_dialog.visible)
예제 #12
0
def _jsxc_login(browser):
    """Login to JSXC."""
    username = functional.config['DEFAULT']['username']
    password = functional.config['DEFAULT']['password']
    functional.visit(browser, '/plinth/apps/jsxc/jsxc/')
    assert functional.eventually(browser.find_by_text,
                                 ['BOSH Server reachable.'])
    if browser.find_by_text('relogin'):
        browser.reload()

    browser.find_by_id('jsxc-username').fill(username)
    browser.find_by_id('jsxc-password').fill(password)
    browser.find_by_id('jsxc-submit').click()
    assert functional.eventually(browser.find_by_css,
                                 ['#jsxc_roster.jsxc_state_shown'])
예제 #13
0
def _add_book(browser, library_name, book_name):
    """Add a book to the library through Calibre interface."""
    _visit_library(browser, library_name)
    add_button = browser.find_by_css('a[data-button-icon="plus"]')
    add_button.first.click()

    functional.eventually(browser.find_by_xpath,
                          ['//span[contains(text(), "Add books")]'])
    browser.execute_script(
        '''document.querySelector('input[type="file"]').setAttribute(
        'name', 'test-book-upload');''')

    file_path = pathlib.Path(__file__).parent / f'data/{book_name}'
    browser.attach_file('test-book-upload', [str(file_path)])
    functional.eventually(browser.find_by_xpath,
                          ['//span[contains(text(), "Added successfully")]'])
예제 #14
0
def _subscribe(browser):
    """Subscribe to a feed in TT-RSS."""
    def _already_subscribed_message():
        return browser.is_text_present(
            'You are already subscribed to this feed.')

    _ttrss_load_main_interface(browser)

    _click_main_menu_item(browser, 'Subscribe to feed...')
    browser.find_by_id('feedDlg_feedUrl').fill(
        'https://planet.debian.org/atom.xml')
    browser.find_by_text('Subscribe').click()
    add_dialog = browser.find_by_css('#feedAddDlg')
    functional.eventually(
        lambda: not add_dialog.visible or _already_subscribed_message())
    if _already_subscribed_message():
        browser.find_by_text('Cancel').click()
        functional.eventually(lambda: not add_dialog.visible)
예제 #15
0
def _upload_file(browser, file_path, password):
    """Upload a local file from disk to coquelicot."""
    _verify_upload_password(browser, password)
    browser.attach_file('file', file_path)
    functional.submit(browser)
    assert functional.eventually(browser.is_element_present_by_css,
                                 args=['#content .url'])
    url_textarea = browser.find_by_css('#content .url textarea').first
    return url_textarea.value
예제 #16
0
def _change_config(browser):
    functional.nav_to_module(browser, 'dynamicdns')
    browser.find_link_by_href(
        '/plinth/sys/dynamicdns/configure/').first.click()
    browser.find_by_id('id_enabled').check()
    browser.find_by_id('id_service_type').select('GnuDIP')
    browser.find_by_id('id_dynamicdns_server').fill('2.example.com')
    browser.find_by_id('id_dynamicdns_domain').fill('freedombox2.example.com')
    browser.find_by_id('id_dynamicdns_user').fill('tester2')
    browser.find_by_id('id_dynamicdns_secret').fill('testingtesting2')
    browser.find_by_id('id_dynamicdns_ipurl').fill(
        'http://myip2.datasystems24.de')
    functional.submit(browser)

    # After a domain name change, Let's Encrypt will restart the web
    # server and could cause a connection failure.
    time.sleep(1)
    functional.eventually(functional.nav_to_module, [browser, 'dynamicdns'])
def _remove_all_torrents(browser):
    """Remove all torrents from deluge."""
    _ensure_connected(browser)

    while browser.find_by_css('#torrentGrid .torrent-name'):
        browser.find_by_css('#torrentGrid .torrent-name').first.click()

        # Click remove toolbar button
        browser.find_by_id('remove').first.click()

        # Remove window shows up
        assert functional.eventually(
            lambda: _get_active_window_title(browser) == 'Remove Torrent')

        _click_active_window_button(browser, 'Remove With Data')

        # Remove window disappears
        assert functional.eventually(
            lambda: not _get_active_window_title(browser))
def _ensure_connected(browser):
    """Type the connection password if required and start Deluge daemon."""
    _ensure_logged_in(browser)

    # Change Default Password window appears once.
    if _get_active_window_title(browser) == 'Change Default Password':
        _click_active_window_button(browser, 'No')

    assert functional.eventually(browser.is_element_not_present_by_css,
                                 args=['#add.x-item-disabled'])
예제 #19
0
def _verify_upload_password(browser, password):
    functional.visit(browser, '/coquelicot')
    # ensure the password form is scrolled into view
    browser.execute_script('window.scrollTo(100, 0)')
    browser.find_by_id('upload_password').fill(password)
    actions = ActionChains(browser.driver)
    actions.send_keys(Keys.RETURN)
    actions.perform()
    assert functional.eventually(browser.is_element_present_by_css,
                                 args=['div[style*="display: none;"]'])
예제 #20
0
def _delete_book(browser, library_name, book_name, ignore_missing=False):
    """Delete a book from the library through Calibre interface."""
    _visit_library(browser, library_name)
    book_name = book_name.partition('.')[0]
    book = browser.find_by_xpath(f'//a[contains(@title, "{book_name}")]')
    if not book:
        if ignore_missing:
            return

        raise Exception('Book not found')

    book.first.click()
    delete_button = browser.find_by_css('a[data-button-icon="trash"]')
    delete_button.first.click()

    dialog = browser.find_by_id('modal-container').first
    functional.eventually(lambda: dialog.visible)
    ok_button = browser.find_by_xpath('//span[contains(text(), "OK")]')
    ok_button.first.click()
예제 #21
0
def _backup_schedule_set(browser, enable, daily, weekly, monthly, run_at,
                         without_app):
    """Set the schedule for root repository."""
    functional.nav_to_module(browser, 'backups')
    browser.find_link_by_href(
        '/plinth/sys/backups/root/schedule/').first.click()
    if enable:
        browser.find_by_name('backups_schedule-enabled').check()
    else:
        browser.find_by_name('backups_schedule-enabled').uncheck()

    browser.fill('backups_schedule-daily_to_keep', daily)
    browser.fill('backups_schedule-weekly_to_keep', weekly)
    browser.fill('backups_schedule-monthly_to_keep', monthly)
    browser.fill('backups_schedule-run_at_hour', run_at)
    functional.eventually(browser.find_by_css, args=['.select-all'])
    browser.find_by_css('.select-all').first.check()
    browser.find_by_css(f'input[value="{without_app}"]').first.uncheck()
    functional.submit(browser)
예제 #22
0
def _visit_library(browser, name):
    """Open the page for the library."""
    functional.visit(browser, '/calibre/')

    # Calibre interface will be available a short time after restarting the
    # service.
    def _service_available():
        unavailable_xpath = '//h1[contains(text(), "Service Unavailable")]'
        available = not browser.find_by_xpath(unavailable_xpath)
        if not available:
            time.sleep(0.5)
            functional.visit(browser, '/calibre/')

        return available

    functional.eventually(_service_available)

    functional.eventually(browser.find_by_css,
                          args=[f'.calibre-push-button[data-lid="{name}"]'])
    link = browser.find_by_css(f'.calibre-push-button[data-lid="{name}"]')
    if not link:
        raise ValueError('Library not found')

    link.first.click()
    functional.eventually(browser.find_by_css, ['.book-list-cover-grid'])
예제 #23
0
def _load_main_interface(browser):
    """Close the dialog boxes that many popup after visiting the URL."""
    functional.access_url(browser, 'syncthing')

    def service_is_available():
        if browser.is_element_present_by_xpath(
                '//h1[text()="Service Unavailable"]'):
            functional.access_url(browser, 'syncthing')
            return False

        return True

    # After a backup restore, service may not be available immediately
    functional.eventually(service_is_available)

    # Wait for javascript loading process to complete
    functional.eventually(lambda: browser.evaluate_script(
        'angular.element("[ng-controller=SyncthingController]").scope()'
        '.thisDevice().name'))

    # Give browser additional time to setup site
    time.sleep(1)
예제 #24
0
def _load_main_interface(browser):
    """Close the dialog boxes that many popup after visiting the URL."""
    functional.access_url(browser, 'syncthing')

    def service_is_available():
        if browser.is_element_present_by_xpath(
                '//h1[text()="Service Unavailable"]'):
            functional.access_url(browser, 'syncthing')
            return False

        return True

    # After a backup restore, service may not be available immediately
    functional.eventually(service_is_available)

    # Wait for javascript loading process to complete
    browser.execute_script('''
        document.is_ui_online = false;
        var old_console_log = console.log;
        console.log = function(message) {
            old_console_log.apply(null, arguments);
            if (message == 'UIOnline') {
                document.is_ui_online = true;
                console.log = old_console_log;
            }
        };
    ''')
    functional.eventually(
        lambda: browser.evaluate_script('document.is_ui_online'), timeout=5)

    # Dismiss the Usage Reporting consent dialog
    functional.eventually(browser.find_by_id, ['ur'])
    usage_reporting = browser.find_by_id('ur').first
    functional.eventually(lambda: usage_reporting.visible, timeout=2)
    if usage_reporting.visible:
        yes_xpath = './/button[contains(@ng-click, "declineUR")]'
        usage_reporting.find_by_xpath(yes_xpath).first.click()
        functional.eventually(lambda: not usage_reporting.visible)
예제 #25
0
def _jsxc_delete_contact(browser):
    """Delete the contact from JSXC user's roster."""
    _jsxc_login(browser)

    # noqa, pylint: disable=unnecessary-lambda
    functional.eventually(browser.find_by_css, ['div.jsxc_more'])
    browser.find_by_css('div.jsxc_more').first.click()
    functional.eventually(browser.find_by_text, ['delete contact'])
    browser.find_by_text('delete contact').first.click()
    functional.eventually(browser.find_by_text, ['Remove'])
    browser.find_by_text('Remove').first.click()
def _unsubscribe(browser):
    """Unsubscribe from a feed in TT-RSS."""
    _ttrss_load_main_interface(browser)
    expand = browser.find_by_css('span.dijitTreeExpandoClosed')
    if expand:
        expand.first.click()

    browser.find_by_text('Planet Debian').click()
    _click_main_menu_item(browser, 'Unsubscribe')

    prompt = browser.get_alert()
    prompt.accept()

    # Reload as sometimes the feed does not disappear immediately
    _ttrss_load_main_interface(browser)

    assert functional.eventually(_is_feed_shown, [browser, True])
def _upload_sample_torrent(browser):
    """Upload a sample torrent into deluge."""
    _ensure_connected(browser)

    number_of_torrents = _get_number_of_torrents(browser)

    # Click add toolbar button
    browser.find_by_id('add').first.click()

    # Add window appears
    functional.eventually(
        lambda: _get_active_window_title(browser) == 'Add Torrents')

    file_path = os.path.join(os.path.dirname(__file__), 'data',
                             'sample.torrent')

    if browser.find_by_id('fileUploadForm'):  # deluge-web 2.x
        browser.attach_file('file', file_path)
    else:  # deluge-web 1.x
        browser.find_by_css('button.x-deluge-add-file').first.click()

        # Add from file window appears
        functional.eventually(
            lambda: _get_active_window_title(browser) == 'Add from File')

        # Attach file
        browser.attach_file('file', file_path)

        # Click Add
        _click_active_window_button(browser, 'Add')

        functional.eventually(
            lambda: _get_active_window_title(browser) == 'Add Torrents')

    # Click Add
    time.sleep(1)
    _click_active_window_button(browser, 'Add')

    functional.eventually(
        lambda: _get_number_of_torrents(browser) > number_of_torrents)
예제 #28
0
def _remove_all_torrents(browser):
    """Remove all torrents from transmission."""
    functional.visit(browser, '/transmission')
    while True:
        torrents = browser.find_by_css('#torrent_list .torrent')
        if not torrents:
            break

        torrents.first.click()
        functional.eventually(browser.is_element_not_present_by_css,
                              args=['#toolbar-remove.disabled'])
        browser.click_link_by_id('toolbar-remove')
        functional.eventually(
            browser.is_element_not_present_by_css,
            args=['#dialog-container[style="display: none;"]'])
        browser.click_link_by_id('dialog_confirm_button')
        functional.eventually(browser.is_element_present_by_css,
                              args=['#toolbar-remove.disabled'])
예제 #29
0
def _cannot_list_all(browser):
    functional.visit(browser, '/bepasty/+list')
    return functional.eventually(browser.is_text_present, ['Forbidden'], 5)
예제 #30
0
def _can_list_all(browser):
    functional.visit(browser, '/bepasty')
    return functional.eventually(browser.links.find_by_href,
                                 ['/bepasty/+list'], 5)