1
0
Fork 0
gita/tests/test_main.py
Daniel Baumann bb3b60775d
Merging upstream version 0.11.9.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-02-11 18:39:54 +01:00

325 lines
11 KiB
Python

import pytest
from unittest.mock import patch, mock_open
from pathlib import Path
import argparse
import shlex
from gita import __main__
from gita import utils, info
from conftest import (
PATH_FNAME, PATH_FNAME_EMPTY, PATH_FNAME_CLASH, GROUP_FNAME,
async_mock, TEST_DIR,
)
class TestLsLl:
@patch('gita.common.get_config_fname')
def testLl(self, mock_path_fname, capfd, tmp_path):
"""
functional test
"""
# avoid modifying the local configuration
def side_effect(input):
return tmp_path / f'{input}.txt'
#mock_path_fname.return_value = tmp_path / 'path_config.txt'
mock_path_fname.side_effect = side_effect
__main__.main(['add', '.'])
out, err = capfd.readouterr()
assert err == ''
assert 'Found 1 new repo(s).\n' == out
# in production this is not needed
utils.get_repos.cache_clear()
__main__.main(['ls'])
out, err = capfd.readouterr()
assert err == ''
assert 'gita\n' == out
__main__.main(['ll'])
out, err = capfd.readouterr()
assert err == ''
assert 'gita' in out
assert info.Color.end in out
# no color on branch name
__main__.main(['ll', '-n'])
out, err = capfd.readouterr()
assert err == ''
assert 'gita' in out
assert info.Color.end not in out
__main__.main(['ls', 'gita'])
out, err = capfd.readouterr()
assert err == ''
assert out.strip() == utils.get_repos()['gita']
def testLs(self, monkeypatch, capfd):
monkeypatch.setattr(utils, 'get_repos',
lambda: {'repo1': '/a/', 'repo2': '/b/'})
monkeypatch.setattr(utils, 'describe', lambda x: x)
__main__.main(['ls'])
out, err = capfd.readouterr()
assert err == ''
assert out == "repo1 repo2\n"
__main__.main(['ls', 'repo1'])
out, err = capfd.readouterr()
assert err == ''
assert out == '/a/\n'
@pytest.mark.parametrize('path_fname, expected', [
(PATH_FNAME,
"repo1 cmaster dsu\x1b[0m msg\nrepo2 cmaster dsu\x1b[0m msg\nxxx cmaster dsu\x1b[0m msg\n"),
(PATH_FNAME_EMPTY, ""),
(PATH_FNAME_CLASH,
"repo1 cmaster dsu\x1b[0m msg\nrepo2 cmaster dsu\x1b[0m msg\nx/repo1 cmaster dsu\x1b[0m msg\n"
),
])
@patch('gita.utils.is_git', return_value=True)
@patch('gita.info.get_head', return_value="master")
@patch('gita.info._get_repo_status', return_value=("d", "s", "u", "c"))
@patch('gita.info.get_commit_msg', return_value="msg")
@patch('gita.common.get_config_fname')
def testWithPathFiles(self, mock_path_fname, _0, _1, _2, _3, path_fname,
expected, capfd):
def side_effect(input):
if input == 'repo_path':
return path_fname
return f'/{input}'
mock_path_fname.side_effect = side_effect
utils.get_repos.cache_clear()
__main__.main(['ll'])
out, err = capfd.readouterr()
print(out)
assert err == ''
assert out == expected
@patch('os.path.isfile', return_value=True)
@patch('gita.common.get_config_fname', return_value='some path')
@patch('gita.utils.get_repos', return_value={'repo1': '/a/', 'repo2': '/b/'})
@patch('gita.utils.write_to_repo_file')
def test_rm(mock_write, *_):
args = argparse.Namespace()
args.repo = ['repo1']
__main__.f_rm(args)
mock_write.assert_called_once_with({'repo2': '/b/'}, 'w')
def test_not_add():
# this won't write to disk because the repo is not valid
__main__.main(['add', '/home/some/repo/'])
@patch('gita.utils.get_repos', return_value={'repo2': '/d/efg'})
@patch('subprocess.run')
def test_fetch(mock_run, *_):
__main__.main(['fetch'])
mock_run.assert_called_once_with(['git', 'fetch'], cwd='/d/efg')
@patch(
'gita.utils.get_repos', return_value={
'repo1': '/a/bc',
'repo2': '/d/efg'
})
@patch('gita.utils.run_async', new=async_mock())
@patch('subprocess.run')
def test_async_fetch(*_):
__main__.main(['fetch'])
mock_run = utils.run_async.mock
assert mock_run.call_count == 2
cmds = ['git', 'fetch']
# print(mock_run.call_args_list)
mock_run.assert_any_call('repo1', '/a/bc', cmds)
mock_run.assert_any_call('repo2', '/d/efg', cmds)
@pytest.mark.parametrize('input', [
'diff --name-only --staged',
"commit -am 'lala kaka'",
])
@patch('gita.utils.get_repos', return_value={'repo7': 'path7'})
@patch('subprocess.run')
def test_superman(mock_run, _, input):
mock_run.reset_mock()
args = ['super', 'repo7'] + shlex.split(input)
__main__.main(args)
expected_cmds = ['git'] + shlex.split(input)
mock_run.assert_called_once_with(expected_cmds, cwd='path7')
class TestContext:
@patch('gita.utils.get_context', return_value=None)
def testDisplayNoContext(self, _, capfd):
__main__.main(['context'])
out, err = capfd.readouterr()
assert err == ''
assert 'Context is not set\n' == out
@patch('gita.utils.get_context', return_value=Path('gname.context'))
@patch('gita.utils.get_groups', return_value={'gname': ['a', 'b']})
def testDisplayContext(self, _, __, capfd):
__main__.main(['context'])
out, err = capfd.readouterr()
assert err == ''
assert 'gname: a b\n' == out
@patch('gita.utils.get_context')
def testReset(self, mock_ctx):
__main__.main(['context', 'none'])
mock_ctx.return_value.unlink.assert_called()
@patch('gita.utils.get_context', return_value=None)
@patch('gita.common.get_config_dir', return_value=TEST_DIR)
@patch('gita.utils.get_groups', return_value={'lala': ['b'], 'kaka': []})
def testSetFirstTime(self, *_):
ctx = TEST_DIR / 'lala.context'
assert not ctx.is_file()
__main__.main(['context', 'lala'])
assert ctx.is_file()
ctx.unlink()
@patch('gita.common.get_config_dir', return_value=TEST_DIR)
@patch('gita.utils.get_groups', return_value={'lala': ['b'], 'kaka': []})
@patch('gita.utils.get_context')
def testSetSecondTime(self, mock_ctx, *_):
__main__.main(['context', 'kaka'])
mock_ctx.return_value.rename.assert_called()
class TestGroupCmd:
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
def testLs(self, _, capfd):
args = argparse.Namespace()
args.to_group = None
args.group_cmd = 'ls'
utils.get_groups.cache_clear()
__main__.f_group(args)
out, err = capfd.readouterr()
assert err == ''
assert 'xx yy\n' == out
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
def testLl(self, _, capfd):
args = argparse.Namespace()
args.to_group = None
args.group_cmd = None
utils.get_groups.cache_clear()
__main__.f_group(args)
out, err = capfd.readouterr()
assert err == ''
assert 'xx: a b\nyy: a c d\n' == out
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
def testRename(self, mock_write, _):
args = argparse.Namespace()
args.gname = 'xx'
args.new_name = 'zz'
args.group_cmd = 'rename'
utils.get_groups.cache_clear()
__main__.f_group(args)
expected = {'yy': ['a', 'c', 'd'], 'zz': ['a', 'b']}
mock_write.assert_called_once_with(expected, 'w')
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
def testRenameError(self, *_):
args = argparse.Namespace()
args.gname = 'xx'
args.new_name = 'yy'
args.group_cmd = 'rename'
utils.get_groups.cache_clear()
with pytest.raises(SystemExit, match='yy already exists.'):
__main__.f_group(args)
@pytest.mark.parametrize('input, expected', [
('xx', {'yy': ['a', 'c', 'd']}),
("xx yy", {}),
])
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
def testRm(self, mock_write, _, __, input, expected):
utils.get_groups.cache_clear()
args = ['group', 'rm'] + shlex.split(input)
__main__.main(args)
mock_write.assert_called_once_with(expected, 'w')
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
def testAdd(self, mock_write, *_):
args = argparse.Namespace()
args.to_group = ['a', 'c']
args.group_cmd = 'add'
args.gname = 'zz'
utils.get_groups.cache_clear()
__main__.f_group(args)
mock_write.assert_called_once_with({'zz': ['a', 'c']}, 'a+')
@patch('gita.utils.get_repos', return_value={'a': '', 'b': '', 'c': '', 'd': ''})
@patch('gita.common.get_config_fname', return_value=GROUP_FNAME)
@patch('gita.utils.write_to_groups_file')
def testAddToExisting(self, mock_write, *_):
args = argparse.Namespace()
args.to_group = ['a', 'c']
args.group_cmd = 'add'
args.gname = 'xx'
utils.get_groups.cache_clear()
__main__.f_group(args)
mock_write.assert_called_once_with(
{'xx': ['a', 'b', 'c'], 'yy': ['a', 'c', 'd']}, 'w')
@patch('gita.utils.is_git', return_value=True)
@patch('gita.common.get_config_fname', return_value=PATH_FNAME)
@patch('gita.utils.rename_repo')
def test_rename(mock_rename, _, __):
utils.get_repos.cache_clear()
args = ['rename', 'repo1', 'abc']
__main__.main(args)
mock_rename.assert_called_once_with(
{'repo1': '/a/bcd/repo1', 'repo2': '/e/fgh/repo2',
'xxx': '/a/b/c/repo3'},
'repo1', 'abc')
class TestInfo:
@patch('gita.common.get_config_fname', return_value='')
def testLl(self, _, capfd):
args = argparse.Namespace()
args.info_cmd = None
__main__.f_info(args)
out, err = capfd.readouterr()
assert 'In use: branch,commit_msg\nUnused: path\n' == out
assert err == ''
@patch('gita.common.get_config_fname', return_value='')
@patch('yaml.dump')
def testAdd(self, mock_dump, _):
args = argparse.Namespace()
args.info_cmd = 'add'
args.info_item = 'path'
with patch('builtins.open', mock_open(), create=True):
__main__.f_info(args)
mock_dump.assert_called_once()
args, kwargs = mock_dump.call_args
assert args[0] == ['branch', 'commit_msg', 'path']
assert kwargs == {'default_flow_style': None}
@patch('gita.common.get_config_fname', return_value='')
@patch('yaml.dump')
def testRm(self, mock_dump, _):
args = argparse.Namespace()
args.info_cmd = 'rm'
args.info_item = 'commit_msg'
with patch('builtins.open', mock_open(), create=True):
__main__.f_info(args)
mock_dump.assert_called_once()
args, kwargs = mock_dump.call_args
assert args[0] == ['branch']
assert kwargs == {'default_flow_style': None}