class UploadedFileManagerTest(unittest.TestCase): def setUp(self): self.mgr = UploadedFileManager() self.filemgr_events = [] self.mgr.on_files_added.connect(self._on_files_added) def _on_files_added(self, file_list, **kwargs): self.filemgr_events.append(file_list) def test_add_file(self): self.assertIsNone(self.mgr.get_files("non-report", "non-widget")) event1 = UploadedFileList("session", "widget", [file1]) event2 = UploadedFileList("session", "widget", [file2]) self.mgr.add_files("session", "widget", [file1]) self.assertEqual([file1], self.mgr.get_files("session", "widget")) self.assertEqual([event1], self.filemgr_events) # Add another file with the same ID self.mgr.add_files("session", "widget", [file2]) self.assertEqual([file2], self.mgr.get_files("session", "widget")) self.assertEqual([event1, event2], self.filemgr_events) def test_remove_file(self): # This should not error. self.mgr.remove_files("non-report", "non-widget") self.mgr.add_files("session", "widget", [file1]) self.assertEqual([file1], self.mgr.get_files("session", "widget")) self.mgr.remove_files("session", "widget") self.assertIsNone(self.mgr.get_files("session", "widget")) def test_remove_all_files(self): # This should not error. self.mgr.remove_session_files("non-report") # Add two files with different session IDs, but the same widget ID. self.mgr.add_files("session1", "widget", [file1]) self.mgr.add_files("session2", "widget", [file1]) event1 = UploadedFileList("session1", "widget", [file1]) event2 = UploadedFileList("session2", "widget", [file1]) self.mgr.remove_session_files("session1") self.assertIsNone(self.mgr.get_files("session1", "widget")) self.assertEqual([file1], self.mgr.get_files("session2", "widget")) self.assertEqual([event1, event2], self.filemgr_events)
class UploadFileRequestHandlerTest(tornado.testing.AsyncHTTPTestCase): """Tests the /upload_file endpoint.""" def get_app(self): self.file_mgr = UploadedFileManager() return tornado.web.Application([("/upload_file", UploadFileRequestHandler, dict(file_mgr=self.file_mgr))]) def _upload_files(self, params): # We use requests.Request to construct our multipart/form-data request # here, because they are absurdly fiddly to compose, and Tornado # doesn't include a utility for building them. We then use self.fetch() # to actually send the request to the test server. req = requests.Request(method="POST", url=self.get_url("/upload_file"), files=params).prepare() return self.fetch("/upload_file", method=req.method, headers=req.headers, body=req.body) def test_upload_one_file(self): """Uploading a file should populate our file_mgr.""" file = UploadedFile("image.png", b"123") params = { file.name: file, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual([file], self.file_mgr.get_files("fooReport", "barWidget")) def test_upload_multiple_files(self): file1 = UploadedFile("image1.png", b"123") file2 = UploadedFile("image2.png", b"456") file3 = UploadedFile("image3.png", b"789") params = { file1.name: file1, file2.name: file2, file3.name: file3, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual( sorted([file1, file2, file3], key=_get_filename), sorted(self.file_mgr.get_files("fooReport", "barWidget"), key=_get_filename), ) def test_missing_params(self): """Missing params in the body should fail with 400 status.""" params = { "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), # "widgetId": (None, 'barWidget'), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Missing 'widgetId'", response.reason) def test_missing_file(self): """Missing file should fail with 400 status.""" params = { # "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Expected at least 1 file, but got 0", response.reason)