Source

hgbb / test_hgbb.py

The default branch has multiple heads

import py
from mock import Mock, MagicMock

import getpass
import urllib

import hgbb
from hgbb import parse_repopath

from mercurial import extensions, commands, hg, util


def pytest_funcarg__ui(request):
    mock_ui = Mock(name='ui')
    def printstatus(status, **kw):
        print status[:-1], kw # strip hg ui newlines, evil
    mock_ui.status.side_effect = printstatus
    return mock_ui


def pytest_generate_tests(metafunc):
    if 'path' in metafunc.funcargnames:
        for id, path, expected_name in parse_repopath_cases:
            metafunc.addcall(id=id,
                             funcargs={
                                 'path': path,
                                 'expected_name': expected_name,
                             })


def test_get_username(monkeypatch, ui):
    getuser = Mock(return_value='fromgetpass')
    monkeypatch.setattr(getpass, 'getuser',  getuser)

    ui.config.return_value = 'fromconfig'
    assert hgbb.get_username(ui) == 'fromconfig'

    ui.reset_mock()
    ui.config.return_value = None
    assert hgbb.get_username(ui) == 'fromgetpass'


parse_repopath_cases = [
    # some valid cases
    ('bb http url', 'http://bitbucket.org/the/repo', 'the/repo'),
    ('bb ssh url', 'ssh://bitbucket.org/the/repo', 'the/repo'),
    ('bb colon', 'bb:test', 'test'),
    ('bb plus colon', 'bb+something:test', 'test'),  # kinda evil
    # some invalid cases
    ('stray bb prefix', 'bbfoo', None),
    ('stray bb plus prefix', 'bb+foo', None),
    ('some name', 'some/name', None),
]


def test_parse_repopath(path, expected_name):
    reponame = parse_repopath(path)
    assert reponame == expected_name


def test_get_reponame(monkeypatch, ui):
    monkeypatch.setattr(hgbb, 'get_username', Mock(return_value='test'))
    monkeypatch.setattr(hgbb, 'parse_repopath', Mock(return_value='test/path'))
    repo = Mock()
    repo.root = 'the/basename'
    # guessed from repo root
    ui.configitems.return_value = []
    name = hgbb.get_bbreponame(ui, repo, {})
    assert name == 'test/basename'
    assert ui.status.called  # warned cause of construction

    ui.reset_mock()
    # grab from url
    ui.configitems.return_value = [('default', None)]
    name = hgbb.get_bbreponame(ui, repo, {})
    assert name == 'test/path'
    assert ui.status.called

    ui.reset_mock()
    # given short name
    name = hgbb.get_bbreponame(ui, repo, {'reponame': 'given'})
    assert name == 'test/given'
    assert ui.status.called

    ui.reset_mock()
    # given full name
    name = hgbb.get_bbreponame(ui, repo, {'reponame': 'full/given'})
    assert name == 'full/given'
    assert not ui.status.called


def test_clone_wrapper_path_mapping(ui):
    mock = Mock()
    hgbb.clone(mock, ui, 'bb:test')
    #                       ui,   source,      dest
    mock.assert_called_with(ui, 'bb://test', None)

    mock.reset_mock()
    hgbb.clone(mock, ui, 'bb://test')
    #                       ui,   source,      dest
    mock.assert_called_with(ui, 'bb://test', None)
    
    mock.reset_mock()
    hgbb.clone(mock, ui, 'bb+something:test')
    #                       ui,   source,      dest
    mock.assert_called_with(ui, 'bb+something://test', None)


def test_uisetup(monkeypatch, ui):
    mock = Mock()
    monkeypatch.setattr(extensions, 'wrapcommand', mock)
    hgbb.uisetup(ui)
    mock.assert_called_with(commands.table, 'clone', hgbb.clone)


def test_auto_bbrepo(monkeypatch, ui):
    schemes = MagicMock(name='schemes')
    monkeypatch.setattr(hg, 'schemes', schemes)
    ui.config.return_value = 'ssh'

    auto = hgbb.auto_bbrepo()

    auto.instance(ui, 'test', False)
    schemes['bb+ssh'].instance.assert_called_with(ui, 'test', False)

    ui.config.return_value = 'unknown'

    py.test.raises(util.Abort, auto.instance, ui, 'test', False)


def test_bbrepo(ui):
    password = None
    def ui_config(section, name, default):
        if name == 'username':
            return 'testuser'
        return password

    ui.config.side_effect = ui_config


    maker = hgbb.bbrepo(ui, '%(auth)s%(path)s')

    maker.instance(ui, 'bb:test', False)
    ui.assert_called_with(ui, 'testuser@testuser/test/', False)

    maker.instance(ui, 'bb+something:other/test', False)
    ui.assert_called_with(ui, 'testuser@other/test/', False)
    
    password = 'evil'
    maker.instance(ui, 'bb:test', False)
    ui.assert_called_with(ui, 'testuser:evil@testuser/test/', False)


# bb will have a single link to the repo overview in case of lack of forks
example_bbforks_page_no_forks = """
<div class="forks pane">
    <h2>Forks</h2>
    <p>No forks of <a href="testrepo">testrepo</a> yet.</p>
    <h2>Patch queues</h2>
    <p>No patch queues of <a href="testrepo">testrepo</a> yet.</p>
</div>
"""


def test_list_forks_no_forks(monkeypatch):
    import lxml.html
    parse = Mock()
    io = py.io.BytesIO(example_bbforks_page_no_forks)
    parse.return_value = lxml.html.parse(io)
    monkeypatch.setattr(lxml.etree, 'parse', parse)
    repos = hgbb.list_forks('testrepo')
    assert not repos

example_bbforks_page_with_forks = """
<body>
    <div class="forks pane">
        <h2>Forks</h2>
        <ol class="detailed iterable">
            <li>
                <dd class="name"><a href="/special">special</a> / <a href="/special/testrepo">ow</a></dd><br />
            </li>
            <li>
                <dd class="name"><a href="/special">special</a> / <a href="/special/testrepo2">ow2</a></dd><br />
            </li>
        </ol>
        <h2>Patch queues</h2>
        <ol class="detailed iterable">
            <li>
                <dd class="name"><a href="/special-patches">special-patches</a> / <a href="/special/testrepo-patches">ow</a></dd><br />
            </li>
        </ol>
    </div>
</body>
"""


def test_list_forks_with_forks(monkeypatch):
    import lxml.html
    parse = Mock()
    io = py.io.BytesIO(example_bbforks_page_with_forks)
    parse.return_value = lxml.html.parse(io)
    monkeypatch.setattr(lxml.html, 'parse', parse)
    repos = hgbb.list_forks('testrepo')
    print repos
    assert repos == ['special/testrepo', 'special/testrepo2']


def test_list_forks_failes(monkeypatch):
    import lxml.html
    parse = Mock()
    parse.side_effect = IOError('example failure')
    monkeypatch.setattr(lxml.html, 'parse', parse)
    py.test.raises(util.Abort, hgbb.list_forks, 'testrepo')


def test_bbforks_no_forks(monkeypatch, ui):
    list_forks = Mock(return_value=None)
    incoming = Mock(name='incoming', spec=commands.incoming)
    reponame = Mock(return_value = [])
    monkeypatch.setattr(hgbb, 'list_forks', list_forks)
    monkeypatch.setattr(hgbb, 'get_bbreponame', reponame)
    monkeypatch.setattr(commands, 'incoming', incoming)
    hgbb.bb_forks(ui, None)
    hgbb.bb_forks(ui, None, incoming=True)

    assert not incoming.called

def test_bbforks_some_forks(monkeypatch, ui):
    def configlist(section, key):
        if key=='ignore_forks':
            return ['some']
    ui.configlist.side_effect = configlist
    ui.popbuffer.return_value = '\xff'

    list_forks = Mock(return_value=['some', 'other', 'moar'])
    incoming = Mock(name='incoming', spec=commands.incoming)
    reponame = Mock(return_value=[])
    monkeypatch.setattr(hgbb, 'list_forks', list_forks)
    monkeypatch.setattr(hgbb, 'get_bbreponame', reponame)
    monkeypatch.setattr(commands, 'incoming', incoming)

    hgbb.bb_forks(ui, None)
    hgbb.bb_forks(ui, None, incoming=True)

    assert incoming.call_count==2
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.