diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 5fbfe5f8..99eda4a4 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -16,6 +16,7 @@ services: command: - --development - --port=14000 + - --dont-delete-pdfs snmp-collector: build: context: . diff --git a/printer/server.py b/printer/server.py index 4741a386..3f07bd12 100644 --- a/printer/server.py +++ b/printer/server.py @@ -56,6 +56,13 @@ def get_args() -> argparse.Namespace: default=False, help="specify if server should run in development. this means requests won't get sent to a printer but logger instead", ) + parser.add_argument( + "--dont-delete-pdfs", + action="store_true", + default=False, + help="specify if server should delete pdfs after printing" + ) + return parser.parse_args() @@ -138,6 +145,9 @@ async def read_item(file: UploadFile = File(...), copies: str = Form(...), sides copies, sides=sides, ) + if args.dont_delete_pdfs: + logging.info(f'--dont-delete-pdfs is set, skipping deletion of file {file_path}') + return "worked!" pathlib.Path(file_path).unlink() return "worked!" except Exception: diff --git a/printer/test_server.py b/printer/test_server.py index cc99527e..33d5e16c 100644 --- a/printer/test_server.py +++ b/printer/test_server.py @@ -1,19 +1,29 @@ +import importlib import io import os import unittest from unittest import mock from fastapi.testclient import TestClient -from server import app + +import server class TestFastAPI(unittest.TestCase): - def setUp(self): + def load_server_with_args(self, argv=[]): + argv_to_use = ["server.py"] + argv_to_use.extend(argv) + os.environ["RIGHT_PRINTER_NAME"] = "HP_P2015_DN" - self.client = TestClient(app) + + with mock.patch("sys.argv", argv_to_use): + importlib.reload(server) + + return TestClient(server.app) def test_health_check(self): - response = self.client.get("/healthcheck/printer") + client = self.load_server_with_args() + response = client.get("/healthcheck/printer") self.assertEqual(response.status_code, 200) self.assertEqual(response.text, '"printer is up!"') @@ -22,8 +32,9 @@ def test_health_check(self): @mock.patch("builtins.open", new_callable=mock.mock_open) @mock.patch("pathlib.Path.unlink") def test_print_endpoint(self, mock_pathlib_unlink, mock_open_func, mock_popen, _): + client = self.load_server_with_args() test_file = io.BytesIO(b"dummy file content") - response = self.client.post( + response = client.post( "/print", files={"file": ("test.txt", test_file, "text/plain")}, data={"copies": "1", "sides": "one-sided"}, @@ -51,12 +62,50 @@ def test_print_endpoint(self, mock_pathlib_unlink, mock_open_func, mock_popen, _ mock_pathlib_unlink.assert_called_once() + @mock.patch("server.uuid.uuid4", return_value="test-id") + @mock.patch("server.subprocess.Popen") + @mock.patch("builtins.open", new_callable=mock.mock_open) + @mock.patch("pathlib.Path.unlink") + def test_print_endpoint_dont_delete_pdf( + self, mock_pathlib_unlink, mock_open_func, mock_popen, _ + ): + client = self.load_server_with_args(["--dont-delete-pdfs"]) + test_file = io.BytesIO(b"dummy file content") + response = client.post( + "/print", + files={"file": ("test.txt", test_file, "text/plain")}, + data={"copies": "1", "sides": "one-sided"}, + ) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.text, '"worked!"') + + mock_open_func.assert_called_once_with("/tmp/test-id", "wb") + + mock_open_func().write.assert_called_once() + self.assertEqual( + mock_open_func().write.call_args_list[0], mock.call(b"dummy file content") + ) + + mock_popen.assert_called_once() + + self.assertEqual( + mock_popen.call_args_list[0], + mock.call( + "lp -n 1 -o sides=one-sided -o media=na_letter_8.5x11in -d HP_P2015_DN /tmp/test-id", + shell=True, + ), + ) + + mock_pathlib_unlink.assert_not_called() + @mock.patch("server.subprocess.Popen") @mock.patch("builtins.open", side_effect=FileNotFoundError("sorry!")) @mock.patch("pathlib.Path.unlink") - def test_print_endpoint(self, mock_pathlib_unlink, _, mock_popen): + def test_print_endpoint_error(self, mock_pathlib_unlink, _, mock_popen): + client = self.load_server_with_args() test_file = io.BytesIO(b"dummy file content") - response = self.client.post( + response = client.post( "/print", files={"file": ("test.txt", test_file, "text/plain")}, data={"copies": "1", "sides": "one-sided"},