Exemple #1
0
async def test_upload_finds_error_message(message, exp_error, tmp_path, mocker,
                                          httpserver):
    html_dump_mock = mocker.patch('upsies.utils.html.dump')

    httpserver.expect_request(
        uri='/upload.php',
        method='POST',
    ).respond_with_data(f'''
        <html>
            <div id="messagebar">{message}</div>
        </html>
    ''')

    torrent_file = tmp_path / 'foo.torrent'
    torrent_file.write_bytes(b'mocked torrent metainfo')
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': httpserver.url_for(''),
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    tracker._logout_url = 'logout.php'
    tracker._auth_key = 'mocked auth key'
    tracker_jobs_mock = Mock(
        create_torrent_job=Mock(output=(str(torrent_file), )),
        mediainfo_job=Mock(output=('mocked mediainfo', )),
        tvmaze_job=Mock(output=('12345', )),
        category_job=Mock(output=('Season', )),
    )
    with pytest.raises(errors.RequestError,
                       match=rf'^{re.escape(exp_error)}$'):
        await tracker.upload(tracker_jobs_mock)
    assert html_dump_mock.call_args_list == []
Exemple #2
0
async def test_upload_fails_to_find_error_message(tmp_path, mocker,
                                                  httpserver):
    html_dump_mock = mocker.patch('upsies.utils.html.dump')
    response = 'unexpected html'
    httpserver.expect_request(
        uri='/upload.php',
        method='POST',
    ).respond_with_data(response)

    torrent_file = tmp_path / 'foo.torrent'
    torrent_file.write_bytes(b'mocked torrent metainfo')
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': httpserver.url_for(''),
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    tracker._logout_url = 'logout.php'
    tracker._auth_key = 'mocked auth key'
    tracker_jobs_mock = Mock(
        create_torrent_job=Mock(output=(str(torrent_file), )),
        mediainfo_job=Mock(output=('mocked mediainfo', )),
        tvmaze_job=Mock(output=('12345', )),
        category_job=Mock(output=('Season', )),
    )
    with pytest.raises(RuntimeError,
                       match=(r'^Failed to find error message. '
                              r'See upload.html for more information.$')):
        await tracker.upload(tracker_jobs_mock)
    assert html_dump_mock.call_args_list == [call(response, 'upload.html')]
Exemple #3
0
def test_report_login_error(page, exp_message, get_html_page):
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    html = bs4.BeautifulSoup(
        markup=get_html_page('nbl', page),
        features='html.parser',
    )
    with pytest.raises(errors.RequestError,
                       match=rf'^Login failed: {exp_message}$'):
        tracker._report_login_error(html)
Exemple #4
0
async def test_get_announce_url_fails(mocker):
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )

    mocks = AsyncMock(
        get=mocker.patch('upsies.utils.http.get',
                         AsyncMock(return_value='<html>foo</html>', )),
        post=mocker.patch('upsies.utils.http.post', AsyncMock()),
        login=AsyncMock(),
        logout=AsyncMock(),
    )
    mocker.patch.object(tracker, 'login', mocks.login)
    mocker.patch.object(tracker, 'logout', mocks.logout)

    exp_cmd = f'{__project_name__} set trackers.{tracker.name}.announce_url <YOUR URL>'
    with pytest.raises(
            errors.RequestError,
            match=rf'^Failed to find announce URL - set it manually: {exp_cmd}$'
    ):
        await tracker.get_announce_url()
    assert mocks.mock_calls == [
        call.login(),
        call.get('http://nbl.local' + NblTracker._url_path['upload'],
                 cache=False,
                 user_agent=True),
        call.logout(),
    ]
Exemple #5
0
async def test_get_announce_url_succeeds(mocker):
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )

    mocks = AsyncMock(
        get=mocker.patch(
            'upsies.utils.http.get',
            AsyncMock(return_value='''
            <html>
                <input type="text" value="https://nbl.local:123/l33tb34f/announce">
            </html>
            ''', )),
        post=mocker.patch('upsies.utils.http.post', AsyncMock()),
        login=AsyncMock(),
        logout=AsyncMock(),
    )
    mocker.patch.object(tracker, 'login', mocks.login)
    mocker.patch.object(tracker, 'logout', mocks.logout)

    announce_url = await tracker.get_announce_url()
    assert announce_url == 'https://nbl.local:123/l33tb34f/announce'
    assert mocks.mock_calls == [
        call.login(),
        call.get('http://nbl.local' + NblTracker._url_path['upload'],
                 cache=False,
                 user_agent=True),
        call.logout(),
    ]
Exemple #6
0
async def test_login_succeeds(mocker):
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch(
        'upsies.utils.http.post',
        AsyncMock(return_value='''
            <html>
                <input name="auth" value="12345" />
                <a href="logout.php?asdfasdf">logout</a>
            </html>
        ''', ))
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    await tracker.login()
    assert get_mock.call_args_list == []
    assert post_mock.call_args_list == [
        call(
            url='http://nbl.local' + tracker._url_path['login'],
            user_agent=True,
            data={
                'username': '******',
                'password': '******',
                'twofa': '',
                'login': '******',
            },
        )
    ]
    assert tracker.is_logged_in
    assert tracker._logout_url == 'http://nbl.local/logout.php?asdfasdf'
    assert tracker._auth_key == '12345'
Exemple #7
0
async def test_login_does_nothing_if_already_logged_in(mocker):
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch('upsies.utils.http.post', AsyncMock())
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    tracker._logout_url = 'anything'
    tracker._auth_key = 'something'
    assert tracker.is_logged_in
    await tracker.login()
    assert tracker.is_logged_in
    assert get_mock.call_args_list == []
    assert post_mock.call_args_list == []
    assert tracker._logout_url == 'anything'
    assert tracker._auth_key == 'something'
Exemple #8
0
def test_is_logged_in():
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    # tracker.logged_in must be True if "_logout_url" and "_auth_key" are set
    assert tracker.is_logged_in is False
    tracker._logout_url = 'asdf'
    assert tracker.is_logged_in is False
    tracker._auth_key = 'asdf'
    assert tracker.is_logged_in is True
    delattr(tracker, '_logout_url')
    assert tracker.is_logged_in is False
    tracker._logout_url = 'asdf'
    assert tracker.is_logged_in is True
    delattr(tracker, '_auth_key')
    assert tracker.is_logged_in is False
Exemple #9
0
async def test_logout(logout_url, auth_key, mocker):
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch('upsies.utils.http.post', AsyncMock())
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    if logout_url is not None:
        tracker._logout_url = logout_url
    if auth_key is not None:
        tracker._auth_key = auth_key
    await tracker.logout()
    if logout_url is not None:
        assert get_mock.call_args_list == [
            call(logout_url, user_agent=True),
        ]
    else:
        assert get_mock.call_args_list == []
    assert post_mock.call_args_list == []
    assert not hasattr(tracker, '_logout_url')
    assert not hasattr(tracker, '_auth_key')
Exemple #10
0
async def test_upload_without_being_logged_in(mocker):
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch('upsies.utils.http.post', AsyncMock())
    metadata_mock = {'torrent': '/path/to/torrent'}
    with pytest.raises(RuntimeError,
                       match=r'^upload\(\) called before login\(\)$'):
        await tracker.upload(metadata_mock)
    assert get_mock.call_args_list == []
    assert post_mock.call_args_list == []
Exemple #11
0
async def test_login_with_incomplete_login_credentials(credentials, exp_error,
                                                       mocker):
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch('upsies.utils.http.post', AsyncMock())
    tracker = NblTracker(options={
        **{
            'base_url': 'http://nbl.local',
            'announce': 'http://nbl.local/announce',
            'exclude': 'some files',
        },
        **credentials,
    }, )
    assert not tracker.is_logged_in
    with pytest.raises(errors.RequestError,
                       match=rf'^Login failed: {exp_error}$'):
        await tracker.login()
    assert not tracker.is_logged_in
    assert get_mock.call_args_list == []
    assert post_mock.call_args_list == []
    assert not hasattr(tracker, '_logout_url')
    assert not hasattr(tracker, '_auth_key')
Exemple #12
0
async def test_get_announce_url_from_options(mocker):
    tracker = NblTracker(
        options={
            'base_url': 'http://nbl.local',
            'announce_url': 'https://nbl.local:123/d34db33f/announce'
        })

    mocks = AsyncMock(
        get=mocker.patch(
            'upsies.utils.http.get',
            AsyncMock(return_value='you should never get this response', )),
        post=mocker.patch('upsies.utils.http.post', AsyncMock()),
        login=AsyncMock(),
        logout=AsyncMock(),
    )
    mocker.patch.object(tracker, 'login', mocks.login)
    mocker.patch.object(tracker, 'logout', mocks.logout)

    announce_url = await tracker.get_announce_url()
    assert announce_url == 'https://nbl.local:123/d34db33f/announce'
    assert mocks.mock_calls == []
Exemple #13
0
async def test_login_dumps_html_if_handling_response_fails(
        method_name, mocker):
    response = '''
    <html>
        <input name="auth" value="12345" />
        <a href="logout.php?asdfasdf">logout</a>
    </html>
    '''
    html_dump_mock = mocker.patch('upsies.utils.html.dump')
    get_mock = mocker.patch('upsies.utils.http.get', AsyncMock())
    post_mock = mocker.patch('upsies.utils.http.post',
                             AsyncMock(return_value=response))
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': 'http://nbl.local',
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
    }, )
    with patch.object(tracker, method_name) as method_mock:
        method_mock.side_effect = Exception('Oooph!')
        with pytest.raises(Exception, match=r'^Oooph!$'):
            await tracker.login()
    assert not tracker.is_logged_in
    assert get_mock.call_args_list == []
    assert post_mock.call_args_list == [
        call(url='http://nbl.local' + tracker._url_path['login'],
             user_agent=True,
             data={
                 'username': '******',
                 'password': '******',
                 'twofa': '',
                 'login': '******',
             })
    ]
    assert not tracker.is_logged_in
    assert html_dump_mock.call_args_list == [
        call(response, 'login.html'),
    ]
Exemple #14
0
async def test_upload_succeeds(category, exp_category_code, ignore_dupes,
                               exp_data, tmp_path, mocker, httpserver):
    class Handler(RequestHandler):
        def handle(self, request):
            request_seen = {
                'method': request.method,
                'User-Agent': request.headers.get('User-Agent', ''),
                'multipart/form-data': dict(request.form),
            }
            # werkzeug.Request stores files in the `files` property
            for field, filestorage in request.files.items():
                request_seen['multipart/form-data'][field] = filestorage.read()
            self.requests_seen.append(request_seen)
            # Upload form redirects to torrent page
            return Response(
                status=307,
                headers={'Location': '/torrents.php?id=123'},
            )

    handler = Handler()
    httpserver.expect_request(
        uri='/upload.php',
        method='POST',
    ).respond_with_handler(handler, )

    torrent_file = tmp_path / 'foo.torrent'
    torrent_file.write_bytes(b'mocked torrent metainfo')
    tracker = NblTracker(options={
        'username': '******',
        'password': '******',
        'base_url': httpserver.url_for(''),
        'announce': 'http://nbl.local/announce',
        'exclude': 'some files',
        'ignore_dupes': ignore_dupes,
    }, )
    tracker._logout_url = 'logout.php'
    tracker._auth_key = 'mocked auth key'
    tracker_jobs_mock = Mock(
        create_torrent_job=Mock(output=(str(torrent_file), )),
        mediainfo_job=Mock(output=('mocked mediainfo', )),
        tvmaze_job=Mock(output=('12345', )),
        category_job=Mock(output=(category, )),
    )
    torrent_page_url = await tracker.upload(tracker_jobs_mock)
    assert torrent_page_url == httpserver.url_for('/torrents.php?id=123')
    exp_form_data = {
        'MAX_FILE_SIZE': '1048576',
        'auth': 'mocked auth key',
        'category': exp_category_code,
        'desc': 'mocked mediainfo',
        'file_input': b'mocked torrent metainfo',
        'fontfont': '-1',
        'fontsize': '-1',
        'genre_tags': '',
        'image': '',
        'media': 'mocked mediainfo',
        'mediaclean': '[mediainfo]mocked mediainfo[/mediainfo]',
        'submit': 'true',
        'tags': '',
        'title': '',
        'tvmazeid': '12345',
    }
    exp_form_data.update(exp_data)
    assert handler.requests_seen == [{
        'method': 'POST',
        'User-Agent': f'{__project_name__}/{__version__}',
        'multipart/form-data': exp_form_data,
    }]