|
1 | 1 | import os |
2 | 2 | import random |
3 | 3 | from unittest import TestCase |
4 | | -from unittest.mock import call, patch |
| 4 | +from unittest.mock import call, patch, MagicMock |
5 | 5 |
|
6 | 6 | from src.controller import PhonebookController, CommandNotFound, FieldRequired |
7 | | -from src.model import JsonStorage |
| 7 | +from src.model import Contact, JsonStorage |
8 | 8 | from src.view import Commands |
9 | 9 | from tests.utils import ( |
10 | 10 | generate_random_id, |
11 | 11 | generate_random_string, |
| 12 | + generate_random_phone, |
12 | 13 | generate_contact, |
13 | 14 | generate_contacts, |
| 15 | + generate_contacts_storage, |
14 | 16 | ) |
15 | 17 |
|
16 | 18 |
|
@@ -180,14 +182,12 @@ def test_entered_integer_value(self): |
180 | 182 | self.assertEqual(result, expected) |
181 | 183 |
|
182 | 184 | def test_entered_not_integer_value(self): |
183 | | - with patch( |
184 | | - "src.view.InputView.ask_required_field", |
185 | | - return_value=generate_random_string() |
186 | | - ): |
| 185 | + value = generate_random_string() |
| 186 | + with patch("src.view.InputView.ask_required_field", return_value=value): |
187 | 187 | self.assertRaises( |
188 | 188 | ValueError, |
189 | 189 | self.controller._get_required_integer_field, |
190 | | - generate_random_id(), |
| 190 | + value, |
191 | 191 | ) |
192 | 192 |
|
193 | 193 |
|
@@ -217,40 +217,220 @@ def test_get_contact_called(self, get_contact, update_fields): |
217 | 217 | self.controller._edit_contact() |
218 | 218 | get_contact.assert_called_with(contact_id) |
219 | 219 |
|
220 | | - # @patch("src.view.InputView.update_field") |
| 220 | + @patch("src.view.InputView.update_field") |
221 | 221 | @patch("src.model.PhonebookModel.get") |
222 | 222 | @patch("src.controller.PhonebookController._get_required_integer_field") |
223 | | - def test_new_name_asked(self, ask_id, get_contact): |
224 | | - with patch("src.view.InputView.update_field") as ask_new_values: |
225 | | - self.controller._edit_contact() |
226 | | - calls = [call("name"), call("phone"), call("comment")] |
227 | | - ask_new_values.assert_has_calls(calls, any_order=True) |
228 | | - self.assertEqual(3, ask_new_values.call_count) |
| 223 | + def test_new_values_asked(self, ask_id, get_contact, ask_new_values): |
| 224 | + self.controller._edit_contact() |
| 225 | + calls = [call("name"), call("phone"), call("comment")] |
| 226 | + ask_new_values.assert_has_calls(calls, any_order=True) |
| 227 | + self.assertEqual(len(calls), ask_new_values.call_count) |
229 | 228 |
|
| 229 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 230 | + def test_update_name_called(self, ask_id): |
| 231 | + contact = generate_contact() |
| 232 | + contact.update_name = MagicMock() |
230 | 233 |
|
231 | | - def test_update_name_called(self): |
232 | | - pass |
| 234 | + new_name = generate_random_string() |
| 235 | + with patch("src.view.InputView.update_field", side_effect=[new_name, "", ""]): |
| 236 | + with patch("src.model.PhonebookModel.get", return_value=contact): |
| 237 | + self.controller._edit_contact() |
| 238 | + contact.update_name.assert_called_with(new_name) |
233 | 239 |
|
234 | | - def test_try_clear_name(self): |
235 | | - pass |
| 240 | + @patch("src.view.InputView.update_field", side_effect=["<", "", ""]) |
| 241 | + @patch("src.model.PhonebookModel.get") |
| 242 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 243 | + def test_try_clear_name(self, ask_id, get_contact, ask_new_values): |
| 244 | + self.assertRaises(ValueError, self.controller._edit_contact) |
236 | 245 |
|
237 | | - def test_new_phone_asked(self): |
238 | | - pass |
| 246 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 247 | + def test_update_phone_called(self, ask_id): |
| 248 | + contact = generate_contact() |
| 249 | + contact.update_phone = MagicMock() |
239 | 250 |
|
240 | | - def test_update_phone_called(self): |
241 | | - pass |
| 251 | + new_phone = generate_random_phone() |
| 252 | + with patch("src.view.InputView.update_field", side_effect=["", new_phone, ""]): |
| 253 | + with patch("src.model.PhonebookModel.get", return_value=contact): |
| 254 | + self.controller._edit_contact() |
| 255 | + contact.update_phone.assert_called_with(new_phone) |
242 | 256 |
|
243 | | - def test_try_clear_phone(self): |
244 | | - pass |
| 257 | + @patch("src.view.InputView.update_field", side_effect=["", "<", ""]) |
| 258 | + @patch("src.model.PhonebookModel.get") |
| 259 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 260 | + def test_try_clear_phone(self, ask_id, get_contact, ask_new_values): |
| 261 | + self.assertRaises(ValueError, self.controller._edit_contact) |
245 | 262 |
|
246 | | - def test_new_comment_asked(self): |
247 | | - pass |
| 263 | + @patch("src.view.InputView.update_field", side_effect=["", "", "<"]) |
| 264 | + @patch("src.model.PhonebookModel.get") |
| 265 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 266 | + def test_clear_comment_called(self, ask_id, get_contact, ask_new_values): |
| 267 | + contact = generate_contact() |
| 268 | + contact.clear_comment = MagicMock() |
248 | 269 |
|
249 | | - def test_clear_comment_called(self): |
250 | | - pass |
| 270 | + with patch("src.view.InputView.update_field", side_effect=["", "", "<"]): |
| 271 | + with patch("src.model.PhonebookModel.get", return_value=contact): |
| 272 | + self.controller._edit_contact() |
| 273 | + contact.clear_comment.assert_called() |
251 | 274 |
|
252 | | - def test_update_comment_called(self): |
253 | | - pass |
| 275 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 276 | + def test_update_comment_called(self, ask_id): |
| 277 | + contact = generate_contact() |
| 278 | + contact.update_comment = MagicMock() |
| 279 | + |
| 280 | + new_comment = generate_random_phone() |
| 281 | + with patch( |
| 282 | + "src.view.InputView.update_field", side_effect=["", "", new_comment] |
| 283 | + ): |
| 284 | + with patch("src.model.PhonebookModel.get", return_value=contact): |
| 285 | + self.controller._edit_contact() |
| 286 | + contact.update_comment.assert_called_with(new_comment) |
254 | 287 |
|
255 | | - def test_return_contact(self): |
256 | | - pass |
| 288 | + @patch("src.view.InputView.update_field", side_effect=["", "", ""]) |
| 289 | + @patch("src.model.PhonebookModel.get") |
| 290 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 291 | + def test_return_contact(self, ask_id, get_contact, ask_new_values): |
| 292 | + contact = generate_contact() |
| 293 | + with patch("src.model.PhonebookModel.get", return_value=contact): |
| 294 | + result = self.controller._edit_contact() |
| 295 | + self.assertIsInstance(result, Contact) |
| 296 | + |
| 297 | + |
| 298 | +class TestDeleteContact(TestCase): |
| 299 | + def setUp(self): |
| 300 | + self.controller = PhonebookController() |
| 301 | + |
| 302 | + def tearDown(self): |
| 303 | + if os.path.isfile(JsonStorage.STORAGE): |
| 304 | + os.remove(JsonStorage.STORAGE) |
| 305 | + |
| 306 | + @patch("src.controller.PhonebookController._get_required_integer_field") |
| 307 | + def test_id_asked(self, ask_id): |
| 308 | + self.controller._delete_contact() |
| 309 | + ask_id.assert_called_with("Contact ID") |
| 310 | + |
| 311 | + @patch("src.model.PhonebookModel.delete_contact") |
| 312 | + def test_delete_contact_called(self, delete_contact): |
| 313 | + id_ = generate_random_id() |
| 314 | + with patch( |
| 315 | + "src.controller.PhonebookController._get_required_integer_field", |
| 316 | + return_value=id_, |
| 317 | + ): |
| 318 | + self.controller._delete_contact() |
| 319 | + delete_contact.assert_called_with(id_) |
| 320 | + |
| 321 | + |
| 322 | +class TestShowStorage(TestCase): |
| 323 | + def setUp(self): |
| 324 | + self.controller = PhonebookController() |
| 325 | + |
| 326 | + def tearDown(self): |
| 327 | + if os.path.isfile(JsonStorage.STORAGE): |
| 328 | + os.remove(JsonStorage.STORAGE) |
| 329 | + |
| 330 | + @patch("src.view.OutputView.print_raw") |
| 331 | + @patch("src.model.PhonebookModel.raw_storage") |
| 332 | + def test_raw_storage_asked(self, raw_storage, output): |
| 333 | + self.controller._show_storage() |
| 334 | + raw_storage.assert_called() |
| 335 | + |
| 336 | + @patch("src.view.OutputView.print_raw") |
| 337 | + def test_storage_showed_in_view(self, output_view): |
| 338 | + storage = generate_contacts_storage() |
| 339 | + with patch("src.model.PhonebookModel.raw_storage", return_value=storage): |
| 340 | + self.controller._show_storage() |
| 341 | + output_view.assert_called_with(storage) |
| 342 | + |
| 343 | + |
| 344 | +class TestPrintContacts(TestCase): |
| 345 | + def setUp(self): |
| 346 | + self.controller = PhonebookController() |
| 347 | + |
| 348 | + def tearDown(self): |
| 349 | + if os.path.isfile(JsonStorage.STORAGE): |
| 350 | + os.remove(JsonStorage.STORAGE) |
| 351 | + |
| 352 | + @patch("src.view.OutputView.contact_info") |
| 353 | + def test_print_all_contacts(self, contact_info): |
| 354 | + contacts = list(generate_contacts()) |
| 355 | + calls = [ |
| 356 | + call(contact_id=c.id, name=c.name, phone=c.phone, comment=c.comment) |
| 357 | + for c in contacts |
| 358 | + ] |
| 359 | + with patch( |
| 360 | + "src.model.PhonebookModel.contacts", return_value=iter(contacts) |
| 361 | + ) as mock_contacts: |
| 362 | + self.controller._print_contacts() |
| 363 | + contact_info.assert_has_calls(calls) |
| 364 | + |
| 365 | + |
| 366 | +class TestRun(TestCase): |
| 367 | + def setUp(self): |
| 368 | + self.controller = PhonebookController() |
| 369 | + |
| 370 | + def tearDown(self): |
| 371 | + if os.path.isfile(JsonStorage.STORAGE): |
| 372 | + os.remove(JsonStorage.STORAGE) |
| 373 | + |
| 374 | + @patch( |
| 375 | + "src.controller.PhonebookController._get_command_or_raise", return_value="exit" |
| 376 | + ) |
| 377 | + def test_ask_command(self, ask_command): |
| 378 | + self.controller.run() |
| 379 | + ask_command.asserc_called_once() |
| 380 | + |
| 381 | + @patch("src.view.ErrorView.unknown_command") |
| 382 | + def test_unknown_command(self, view_mock): |
| 383 | + command = generate_random_string(length=100) |
| 384 | + error_message = f"Command {command} not found" |
| 385 | + with patch( |
| 386 | + "src.controller.PhonebookController._get_command_or_raise", |
| 387 | + side_effect=[CommandNotFound(error_message), "exit"], |
| 388 | + ): |
| 389 | + self.controller.run() |
| 390 | + view_mock.assert_called_with(error_message) |
| 391 | + |
| 392 | + @patch("src.controller.PhonebookController._add_contact") |
| 393 | + def test_add_command(self, add_contact): |
| 394 | + with patch( |
| 395 | + "src.controller.PhonebookController._get_command_or_raise", |
| 396 | + side_effect=["add", "exit"], |
| 397 | + ): |
| 398 | + self.controller.run() |
| 399 | + add_contact.assert_called_once() |
| 400 | + |
| 401 | + @patch("src.view.ErrorView.required_field") |
| 402 | + def test_add_command_error(self, view): |
| 403 | + field_name = generate_random_string() |
| 404 | + with patch( |
| 405 | + "src.controller.PhonebookController._add_contact", |
| 406 | + side_effect=FieldRequired(field_name), |
| 407 | + ): |
| 408 | + with patch( |
| 409 | + "src.controller.PhonebookController._get_command_or_raise", |
| 410 | + side_effect=["add", "exit"], |
| 411 | + ): |
| 412 | + self.controller.run() |
| 413 | + view.assert_called_with(field_name) |
| 414 | + |
| 415 | + @patch("src.controller.PhonebookController._find_contact") |
| 416 | + def test_find_contact(self, find_contact): |
| 417 | + with patch( |
| 418 | + "src.controller.PhonebookController._get_command_or_raise", |
| 419 | + side_effect=["find", "exit"], |
| 420 | + ): |
| 421 | + self.controller.run() |
| 422 | + find_contact.assert_called_once() |
| 423 | + |
| 424 | + @patch("src.view.ErrorView.required_field") |
| 425 | + def test_find_contact_error(self, view): |
| 426 | + field_name = generate_random_string() |
| 427 | + with patch( |
| 428 | + "src.controller.PhonebookController._find_contact", |
| 429 | + side_effect=FieldRequired(field_name), |
| 430 | + ): |
| 431 | + with patch( |
| 432 | + "src.controller.PhonebookController._get_command_or_raise", |
| 433 | + side_effect=["find", "exit"], |
| 434 | + ): |
| 435 | + self.controller.run() |
| 436 | + view.assert_called_with(field_name) |
0 commit comments