Skip to content

Commit fd37173

Browse files
Frederic Collonvaltelamonian
authored andcommitted
Add endpoint tests
1 parent f56b4ed commit fd37173

File tree

5 files changed

+430
-33
lines changed

5 files changed

+430
-33
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,4 @@ MANIFEST
110110
jupyterlab_git/labextension/*.tgz
111111
.pytest_cache/
112112
*.tsbuildinfo
113+
.pytest_cache/

jupyterlab_git/git.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self, command, cwd, env, username, password):
2424
self.env = env
2525
self.username = username
2626
self.password = password
27+
2728
def communicate(self):
2829
try:
2930
p = pexpect.spawn(
@@ -896,7 +897,7 @@ def _get_tag(self, current_path, commit_sha):
896897

897898
def show(self, filename, ref, top_repo_path):
898899
"""
899-
Execute git show<ref:filename> command & return the result.
900+
Execute git show <ref:filename> command & return the result.
900901
"""
901902
command = ["git", "show", '{}:{}'.format(ref, filename)]
902903
p = subprocess.Popen(
@@ -917,7 +918,7 @@ def show(self, filename, ref, top_repo_path):
917918
elif any([msg in lower_error for msg in error_messages]):
918919
return ""
919920
else:
920-
raise Exception('Error [{}] occurred while executing [{}] command to retrieve plaintext diff.'.format(
921+
raise HTTPError(log_message='Error [{}] occurred while executing [{}] command to retrieve plaintext diff.'.format(
921922
error.decode('utf-8'),
922923
' '.join(command)
923924
))
@@ -934,17 +935,14 @@ def diff_content(self, filename, prev_ref, curr_ref, top_repo_path):
934935
"""
935936
Collect get content of prev and curr and return.
936937
"""
937-
try:
938-
prev_content = self.show(filename, prev_ref["git"], top_repo_path)
939-
if "special" in curr_ref:
940-
if curr_ref["special"] == "WORKING":
941-
curr_content = self.get_content(filename, top_repo_path)
942-
elif curr_ref["special"] == "INDEX":
943-
curr_content = self.show(filename, "", top_repo_path)
944-
else:
945-
raise Exception("Error while retrieving plaintext diff, unknown special ref '{}'.".format(curr_ref["specialref"]))
938+
prev_content = self.show(filename, prev_ref["git"], top_repo_path)
939+
if "special" in curr_ref:
940+
if curr_ref["special"] == "WORKING":
941+
curr_content = self.get_content(filename, top_repo_path)
942+
elif curr_ref["special"] == "INDEX":
943+
curr_content = self.show(filename, "", top_repo_path)
946944
else:
947-
curr_content = self.show(filename, curr_ref["git"], top_repo_path)
948-
return {"prev_content": prev_content, "curr_content": curr_content}
949-
except:
950-
raise
945+
raise HTTPError(log_message="Error while retrieving plaintext diff, unknown special ref '{}'.".format(curr_ref["special"]))
946+
else:
947+
curr_content = self.show(filename, curr_ref["git"], top_repo_path)
948+
return {"prev_content": prev_content, "curr_content": curr_content}

jupyterlab_git/tests/test_handlers.py

Lines changed: 286 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import json
2-
from unittest.mock import Mock, ANY, patch
2+
import os
3+
import subprocess
4+
from unittest.mock import ANY, call, Mock, patch
35

46
from jupyterlab_git.handlers import (
57
GitAllHistoryHandler,
@@ -10,6 +12,8 @@
1012
setup_handlers
1113
)
1214

15+
from .testutils import assert_http_error, ServerTest
16+
1317
def test_mapping_added():
1418
mock_web_app = Mock()
1519
mock_web_app.settings = {
@@ -231,3 +235,284 @@ def test_upstream_handler_localbranch(mock_finish, mock_git):
231235
mock_git.get_current_branch.assert_called_with('test_path')
232236
mock_git.get_upstream_branch.assert_called_with('test_path', 'foo')
233237
mock_finish.assert_called_with('{"upstream": "bar"}')
238+
239+
class TestDiffContent(ServerTest):
240+
241+
@patch("subprocess.Popen")
242+
def test_diffcontent(self, popen):
243+
# Given
244+
top_repo_path = "path/to/repo"
245+
filename = "my/file"
246+
content = "dummy content file\nwith multiplelines"
247+
248+
process_mock = Mock()
249+
attrs = {
250+
"communicate": Mock(
251+
return_value=(
252+
bytes(content, encoding="utf-8"),
253+
b"",
254+
)
255+
),
256+
"returncode": 0,
257+
}
258+
process_mock.configure_mock(**attrs)
259+
popen.return_value = process_mock
260+
261+
# When
262+
body = {
263+
"filename": filename,
264+
"prev_ref": {"git": "previous"},
265+
"curr_ref": {"git": "current"},
266+
"top_repo_path" : top_repo_path
267+
}
268+
response = self.tester.post(["diffcontent"], body=body)
269+
270+
# Then
271+
assert response.status_code == 200
272+
payload = response.json()
273+
assert payload["prev_content"] == content
274+
assert payload["curr_content"] == content
275+
popen.assert_has_calls([
276+
call(
277+
["git", "show", '{}:{}'.format("previous", filename)],
278+
stdout=subprocess.PIPE,
279+
stderr=subprocess.PIPE,
280+
cwd=os.path.join(self.notebook_dir, top_repo_path)
281+
),
282+
call().communicate(),
283+
call(
284+
["git", "show", '{}:{}'.format("current", filename)],
285+
stdout=subprocess.PIPE,
286+
stderr=subprocess.PIPE,
287+
cwd=os.path.join(self.notebook_dir, top_repo_path)
288+
),
289+
call().communicate()
290+
])
291+
292+
@patch("subprocess.Popen")
293+
def test_diffcontent_working(self, popen):
294+
# Given
295+
top_repo_path = "path/to/repo"
296+
filename = "my/file"
297+
content = "dummy content file\nwith multiplelines"
298+
299+
process_mock = Mock()
300+
attrs = {
301+
"communicate": Mock(
302+
return_value=(
303+
bytes(content, encoding="utf-8"),
304+
b"",
305+
)
306+
),
307+
"returncode": 0,
308+
}
309+
process_mock.configure_mock(**attrs)
310+
popen.return_value = process_mock
311+
312+
dummy_file = os.path.join(self.notebook_dir, top_repo_path, filename)
313+
os.makedirs(os.path.dirname(dummy_file))
314+
with open(dummy_file, 'w') as f:
315+
f.write(content)
316+
317+
# When
318+
body = {
319+
"filename": filename,
320+
"prev_ref": {"git": "previous"},
321+
"curr_ref": {"special": "WORKING"},
322+
"top_repo_path" : top_repo_path
323+
}
324+
response = self.tester.post(["diffcontent"], body=body)
325+
326+
# Then
327+
assert response.status_code == 200
328+
payload = response.json()
329+
assert payload["prev_content"] == content
330+
assert payload["curr_content"] == content
331+
popen.assert_has_calls([
332+
call(
333+
["git", "show", '{}:{}'.format("previous", filename)],
334+
stdout=subprocess.PIPE,
335+
stderr=subprocess.PIPE,
336+
cwd=os.path.join(self.notebook_dir, top_repo_path)
337+
),
338+
call().communicate()
339+
])
340+
341+
@patch("subprocess.Popen")
342+
def test_diffcontent_index(self, popen):
343+
# Given
344+
top_repo_path = "path/to/repo"
345+
filename = "my/file"
346+
content = "dummy content file\nwith multiplelines"
347+
348+
process_mock = Mock()
349+
attrs = {
350+
"communicate": Mock(
351+
return_value=(
352+
bytes(content, encoding="utf-8"),
353+
b"",
354+
)
355+
),
356+
"returncode": 0,
357+
}
358+
process_mock.configure_mock(**attrs)
359+
popen.return_value = process_mock
360+
361+
# When
362+
body = {
363+
"filename": filename,
364+
"prev_ref": {"git": "previous"},
365+
"curr_ref": {"special": "INDEX"},
366+
"top_repo_path" : top_repo_path
367+
}
368+
response = self.tester.post(["diffcontent"], body=body)
369+
370+
# Then
371+
assert response.status_code == 200
372+
payload = response.json()
373+
assert payload["prev_content"] == content
374+
assert payload["curr_content"] == content
375+
popen.assert_has_calls([
376+
call(
377+
["git", "show", '{}:{}'.format("previous", filename)],
378+
stdout=subprocess.PIPE,
379+
stderr=subprocess.PIPE,
380+
cwd=os.path.join(self.notebook_dir, top_repo_path)
381+
),
382+
call().communicate(),
383+
call(
384+
["git", "show", '{}:{}'.format("", filename)],
385+
stdout=subprocess.PIPE,
386+
stderr=subprocess.PIPE,
387+
cwd=os.path.join(self.notebook_dir, top_repo_path)
388+
),
389+
call().communicate()
390+
])
391+
392+
@patch("subprocess.Popen")
393+
def test_diffcontent_unknown_special(self, popen):
394+
# Given
395+
top_repo_path = "path/to/repo"
396+
filename = "my/file"
397+
content = "dummy content file\nwith multiplelines"
398+
399+
process_mock = Mock()
400+
attrs = {
401+
"communicate": Mock(
402+
return_value=(
403+
bytes(content, encoding="utf-8"),
404+
b"",
405+
)
406+
),
407+
"returncode": 0,
408+
}
409+
process_mock.configure_mock(**attrs)
410+
popen.return_value = process_mock
411+
412+
# When
413+
body = {
414+
"filename": filename,
415+
"prev_ref": {"git": "previous"},
416+
"curr_ref": {"special": "unknown"},
417+
"top_repo_path" : top_repo_path
418+
}
419+
420+
with assert_http_error(500, msg="unknown special ref"):
421+
self.tester.post(["diffcontent"], body=body)
422+
423+
@patch("subprocess.Popen")
424+
def test_diffcontent_show_handled_error(self, popen):
425+
# Given
426+
top_repo_path = "path/to/repo"
427+
filename = "my/file"
428+
429+
process_mock = Mock()
430+
attrs = {
431+
"communicate": Mock(
432+
return_value=(
433+
b"",
434+
bytes("fatal: Path '{}' does not exist (neither on disk nor in the index)".format(filename), encoding="utf-8"),
435+
)
436+
),
437+
"returncode": -1,
438+
}
439+
process_mock.configure_mock(**attrs)
440+
popen.return_value = process_mock
441+
442+
# When
443+
body = {
444+
"filename": filename,
445+
"prev_ref": {"git": "previous"},
446+
"curr_ref": {"git": "current"},
447+
"top_repo_path" : top_repo_path
448+
}
449+
response = self.tester.post(["diffcontent"], body=body)
450+
451+
# Then
452+
assert response.status_code == 200
453+
payload = response.json()
454+
assert payload["prev_content"] == ""
455+
assert payload["curr_content"] == ""
456+
457+
@patch("subprocess.Popen")
458+
def test_diffcontent_show_unhandled_error(self, popen):
459+
# Given
460+
top_repo_path = "path/to/repo"
461+
filename = "my/file"
462+
463+
process_mock = Mock()
464+
attrs = {
465+
"communicate": Mock(
466+
return_value=(
467+
b"",
468+
b"Dummy error",
469+
)
470+
),
471+
"returncode": -1,
472+
}
473+
process_mock.configure_mock(**attrs)
474+
popen.return_value = process_mock
475+
476+
# When
477+
body = {
478+
"filename": filename,
479+
"prev_ref": {"git": "previous"},
480+
"curr_ref": {"git": "current"},
481+
"top_repo_path" : top_repo_path
482+
}
483+
484+
# Then
485+
with assert_http_error(500, msg="command to retrieve plaintext diff"):
486+
self.tester.post(["diffcontent"], body=body)
487+
488+
@patch("subprocess.Popen")
489+
def test_diffcontent_getcontent_error(self, popen):
490+
# Given
491+
top_repo_path = "path/to/repo"
492+
filename = "my/absent_file"
493+
content = "dummy content file\nwith multiplelines"
494+
495+
process_mock = Mock()
496+
attrs = {
497+
"communicate": Mock(
498+
return_value=(
499+
bytes(content, encoding="utf-8"),
500+
b"",
501+
)
502+
),
503+
"returncode": 0,
504+
}
505+
process_mock.configure_mock(**attrs)
506+
popen.return_value = process_mock
507+
508+
# When
509+
body = {
510+
"filename": filename,
511+
"prev_ref": {"git": "previous"},
512+
"curr_ref": {"special": "WORKING"},
513+
"top_repo_path" : top_repo_path
514+
}
515+
# Then
516+
with assert_http_error(404, msg="No such file or directory"):
517+
r = self.tester.post(["diffcontent"], body=body)
518+
print(r.json())

0 commit comments

Comments
 (0)