various fixes found during review
This commit is contained in:
@@ -722,6 +722,9 @@ def watched(monkeypatch, tmp_path, all_mode):
|
||||
st.files = [change("a.py"), change("b.py")]
|
||||
st.change, st.all_mode = st.files[0], all_mode
|
||||
st.fingerprint = commands.render.fingerprint(st)
|
||||
# git status lists what the view lists, unless a test says otherwise
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: done(work()))
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: list(st.files))
|
||||
return st, refreshes
|
||||
|
||||
|
||||
@@ -750,6 +753,27 @@ def test_refresh_if_changed_watches_the_shown_file_and_the_index(monkeypatch, tm
|
||||
assert refreshes == [st]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("all_mode", [False, True])
|
||||
def test_refresh_if_changed_sees_a_file_changed_outside_the_list(monkeypatch, tmp_path, all_mode):
|
||||
st, refreshes = watched(monkeypatch, tmp_path, all_mode=all_mode)
|
||||
# no listed file and not the index moved, but git status now lists c.py too
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: st.files + [change("c.py")])
|
||||
commands.refresh_if_changed(sublime.View(), st)
|
||||
assert refreshes == [st]
|
||||
|
||||
|
||||
def test_a_stale_git_status_does_not_refresh(monkeypatch, tmp_path):
|
||||
st, refreshes = watched(monkeypatch, tmp_path, all_mode=False)
|
||||
pending = []
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: pending.append(done))
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: [])
|
||||
commands.refresh_if_changed(sublime.View(), st)
|
||||
# the user moved on to another file before git status answered
|
||||
st.token += 1
|
||||
pending[0]([change("c.py")])
|
||||
assert refreshes == []
|
||||
|
||||
|
||||
def test_staging_the_only_file_leaves_an_empty_listing(monkeypatch):
|
||||
messages = []
|
||||
monkeypatch.setattr(commands.render, "render_message", lambda view, st, text: messages.append(text))
|
||||
@@ -882,3 +906,101 @@ def test_all_files_context_zero_shows_only_changed_lines(monkeypatch):
|
||||
view, st = all_files_view()
|
||||
shown = [line for _, line, _ in st.all_rows if line is not None]
|
||||
assert shown and all(line.kind != " " for line in shown)
|
||||
|
||||
|
||||
def test_refresh_in_the_all_files_view_relists_the_working_tree(monkeypatch):
|
||||
view, st = all_files_view()
|
||||
st.change = st.files[0]
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: done(work()))
|
||||
# b.py was reverted and c.py is new since the view was drawn
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: [change("a.py"), change("c.py")])
|
||||
shown = []
|
||||
monkeypatch.setattr(commands, "show_all", lambda view, st, focus=None: shown.append(focus))
|
||||
commands.ACTIONS["refresh"](view, None, st)
|
||||
assert shown == ["a.py"] and [c.path for c in st.files] == ["a.py", "c.py"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("all_mode, expected", [(False, ("file", "b.py")), (True, ("all", "b.py"))])
|
||||
def test_restore_falls_back_to_the_first_changed_file(monkeypatch, tmp_path, all_mode, expected):
|
||||
view = sublime.View()
|
||||
view.settings().set(state.VIEW_DATA, {"repo": str(tmp_path), "sha": None, "path": "gone.py", "all_mode": all_mode})
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: done(work()))
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: [change("b.py"), change("c.py")])
|
||||
shown = []
|
||||
monkeypatch.setattr(commands, "show_all", lambda view, st, focus=None: shown.append(("all", st.change.path)))
|
||||
monkeypatch.setattr(commands, "show_file", lambda view, st, c: shown.append(("file", c.path)))
|
||||
commands.restore_view(view)
|
||||
assert shown == [expected]
|
||||
|
||||
|
||||
def test_restore_with_no_changes_left_says_so(monkeypatch, tmp_path):
|
||||
view = sublime.View()
|
||||
view.settings().set(state.VIEW_DATA, {"repo": str(tmp_path), "sha": None, "path": "gone.py"})
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: done(work()))
|
||||
monkeypatch.setattr(commands.git, "changed_files", lambda repo: [])
|
||||
messages = []
|
||||
monkeypatch.setattr(commands.render, "render_message", lambda view, st, text: messages.append(text))
|
||||
commands.restore_view(view)
|
||||
assert messages == [f"No uncommitted changes in {tmp_path}"]
|
||||
|
||||
|
||||
def test_open_in_the_all_files_view_maps_a_deleted_row_like_the_single_file_view(tmp_path):
|
||||
from vdiff import parse
|
||||
view, st = all_files_view()
|
||||
st.repo = str(tmp_path)
|
||||
(tmp_path / "a.py").write_text("")
|
||||
(tmp_path / "b.py").write_text("")
|
||||
lines_b = [parse.Line(" ", i, i, f"b{i}") for i in range(1, 5)] + [parse.Line("-", 5, None, "old b5"),
|
||||
parse.Line(" ", 6, 5, "b6")]
|
||||
st.all_diffs["b.py"] = (lines_b, parse.change_blocks(lines_b), False)
|
||||
commands.render.render_all(view, st)
|
||||
opened = []
|
||||
|
||||
class Window:
|
||||
def open_file(self, name, flags=0):
|
||||
opened.append(name)
|
||||
|
||||
def open_at(match):
|
||||
put_caret(view, next(i for i, (_, line, _) in enumerate(st.all_rows) if line is not None and match(line)))
|
||||
commands.ACTIONS["open"](view, Window(), st)
|
||||
|
||||
# the deleted row opens at the line that took its place, as in the single-file view, not at line 1
|
||||
open_at(lambda line: line.kind == "-")
|
||||
# a surviving row keeps its own number
|
||||
open_at(lambda line: line.new_no == 26)
|
||||
assert opened == [f"{tmp_path}/b.py:5", f"{tmp_path}/a.py:26"]
|
||||
|
||||
|
||||
def test_a_blank_row_in_the_all_files_view_is_no_file(monkeypatch):
|
||||
view, st = all_files_view()
|
||||
messages, ran = [], []
|
||||
monkeypatch.setattr(commands, "status", messages.append)
|
||||
monkeypatch.setattr(commands, "run_async", lambda work, done: ran.append(work))
|
||||
# the caret was on a.py, then moved to the blank row above b.py: git actions and open act on nothing
|
||||
put_caret(view, heading_row(st, "a.py") + 1)
|
||||
commands.render.follow_caret(view, st)
|
||||
put_caret(view, heading_row(st, "b.py") - 1)
|
||||
commands.ACTIONS["discard"](view, None, st)
|
||||
commands.ACTIONS["stage"](view, None, st)
|
||||
commands.ACTIONS["open"](view, None, st)
|
||||
assert ran == [] and messages == ["no file under the caret"] * 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize("action, path", [("next_file", "b.py"), ("prev_file", "a.py")])
|
||||
def test_a_blank_row_steps_files_as_the_gap_above_the_file_below(action, path):
|
||||
view, st = all_files_view()
|
||||
st.change = st.files[0]
|
||||
put_caret(view, heading_row(st, "b.py") - 1)
|
||||
commands.ACTIONS[action](view, None, st)
|
||||
assert st.change.path == path
|
||||
|
||||
|
||||
def test_a_blank_row_steps_changes_as_the_gap_above_the_file_below():
|
||||
view, st = all_files_view()
|
||||
put_caret(view, heading_row(st, "b.py") - 1)
|
||||
commands.ACTIONS["next_change"](view, None, st)
|
||||
assert st.change.path == "b.py"
|
||||
put_caret(view, heading_row(st, "b.py") - 1)
|
||||
commands.ACTIONS["prev_change"](view, None, st)
|
||||
# a.py's last hunk, not the first or last of the whole list from nowhere
|
||||
assert st.change.path == "a.py" and commands.render.caret_index(view) == st.all_change_rows[1]
|
||||
|
||||
Reference in New Issue
Block a user