diff --git a/tests/test_message.py b/tests/test_message.py index 220fef2..48004b1 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,5 +1,9 @@ +import pathlib +import tempfile +from typing import cast from .test_main import CmmTestCase -from chatmastermind.message import source_code, MessageError, Question, Answer +from chatmastermind.message import source_code, Message, MessageError, Question, Answer +from chatmastermind.tags import Tag, TagLine class SourceCodeTestCase(CmmTestCase): @@ -76,3 +80,213 @@ class AnswerTestCase(CmmTestCase): answer = Answer("No") self.assertIsInstance(answer, Answer) self.assertEqual(answer, "No") + + +class MessageToFileTxtTestCase(CmmTestCase): + def setUp(self) -> None: + self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.txt') + self.file_path = pathlib.Path(self.file.name) + self.message = Message(Question('This is a question.'), + Answer('This is an answer.'), + {Tag('tag1'), Tag('tag2')}, + self.file_path) + + def tearDown(self) -> None: + self.file.close() + self.file_path.unlink() + + def test_to_file_txt(self) -> None: + self.message.to_file(self.file_path) + + with open(self.file_path, "r") as fd: + content = fd.read() + expected_content = f"""{TagLine.prefix} tag1 tag2 +{Question.txt_header} +This is a question. +{Answer.txt_header} +This is an answer. +""" + self.assertEqual(content, expected_content) + + def test_to_file_unsupported_file_type(self) -> None: + unsupported_file_path = pathlib.Path("example.doc") + with self.assertRaises(MessageError) as cm: + self.message.to_file(unsupported_file_path) + self.assertEqual(str(cm.exception), "File type '.doc' is not supported") + + def test_to_file_no_file_path(self) -> None: + """ + Provoke an exception using an empty path. + """ + with self.assertRaises(MessageError) as cm: + # clear the internal file_path + self.message.file_path = None + self.message.to_file(None) + self.assertEqual(str(cm.exception), "Got no valid path to write message") + # reset the internal file_path + self.message.file_path = self.file_path + + +class MessageToFileYamlTestCase(CmmTestCase): + def setUp(self) -> None: + self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.yaml') + self.file_path = pathlib.Path(self.file.name) + self.message = Message(Question('This is a question.'), + Answer('This is an answer.'), + {Tag('tag1'), Tag('tag2')}, + self.file_path) + self.message_multiline = Message(Question('This is a\nmultiline question.'), + Answer('This is a\nmultiline answer.'), + {Tag('tag1'), Tag('tag2')}, + self.file_path) + + def tearDown(self) -> None: + self.file.close() + self.file_path.unlink() + + def test_to_file_yaml(self) -> None: + self.message.to_file(self.file_path) + + with open(self.file_path, "r") as fd: + content = fd.read() + expected_content = "answer: This is an answer.\nquestion: This is a question.\ntags:\n- tag1\n- tag2\n" + self.assertEqual(content, expected_content) + + def test_to_file_yaml_multiline(self) -> None: + self.message_multiline.to_file(self.file_path) + + with open(self.file_path, "r") as fd: + content = fd.read() + expected_content = f"""{Answer.yaml_key}: |- + This is a + multiline answer. +{Question.yaml_key}: |- + This is a + multiline question. +{Message.tags_yaml_key}: +- tag1 +- tag2 +""" + self.assertEqual(content, expected_content) + + +class MessageFromFileTxtTestCase(CmmTestCase): + def setUp(self) -> None: + self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.txt') + self.file_path = pathlib.Path(self.file.name) + with open(self.file_path, "w") as fd: + fd.write(f"""{TagLine.prefix} tag1 tag2 +{Question.txt_header} +This is a question. +{Answer.txt_header} +This is an answer. +""") + self.file_no_tags = tempfile.NamedTemporaryFile(delete=False, suffix='.txt') + self.file_path_no_tags = pathlib.Path(self.file_no_tags.name) + with open(self.file_path_no_tags, "w") as fd: + fd.write(f"""{Question.txt_header} +This is a question. +{Answer.txt_header} +This is an answer. +""") + + def tearDown(self) -> None: + self.file.close() + self.file_no_tags.close() + self.file_path.unlink() + self.file_path_no_tags.unlink() + + def test_from_file_txt(self) -> None: + message = Message.from_file(self.file_path) + self.assertIsNotNone(message) + self.assertIsInstance(message, Message) + if message: + self.assertEqual(message.question, 'This is a question.') + self.assertEqual(message.answer, 'This is an answer.') + self.assertSetEqual(cast(set[Tag], message.tags), {Tag('tag1'), Tag('tag2')}) + self.assertEqual(message.file_path, self.file_path) + + def test_from_file_txt_no_tags(self) -> None: + message = Message.from_file(self.file_path_no_tags) + self.assertIsNotNone(message) + self.assertIsInstance(message, Message) + if message: + self.assertEqual(message.question, 'This is a question.') + self.assertEqual(message.answer, 'This is an answer.') + self.assertSetEqual(cast(set[Tag], message.tags), set()) + self.assertEqual(message.file_path, self.file_path_no_tags) + + def test_from_file_txt_tags_match(self) -> None: + message = Message.from_file(self.file_path, tags_or={Tag('tag1')}) + self.assertIsNotNone(message) + self.assertIsInstance(message, Message) + if message: + self.assertEqual(message.question, 'This is a question.') + self.assertEqual(message.answer, 'This is an answer.') + self.assertSetEqual(cast(set[Tag], message.tags), {Tag('tag1'), Tag('tag2')}) + self.assertEqual(message.file_path, self.file_path) + + def test_from_file_txt_tags_dont_match(self) -> None: + message = Message.from_file(self.file_path, tags_or={Tag('tag3')}) + self.assertIsNone(message) + + def test_from_file_not_exists(self) -> None: + file_not_exists = pathlib.Path("example.txt") + with self.assertRaises(MessageError) as cm: + Message.from_file(file_not_exists) + self.assertEqual(str(cm.exception), f"Message file '{file_not_exists}' does not exist") + + +class MessageFromFileYamlTestCase(CmmTestCase): + def setUp(self) -> None: + self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.yaml') + self.file_path = pathlib.Path(self.file.name) + with open(self.file_path, "w") as fd: + fd.write(f""" +{Question.yaml_key}: |- + This is a question. +{Answer.yaml_key}: |- + This is an answer. +{Message.tags_yaml_key}: + - tag1 + - tag2 +""") + self.file_no_tags = tempfile.NamedTemporaryFile(delete=False, suffix='.yaml') + self.file_path_no_tags = pathlib.Path(self.file_no_tags.name) + with open(self.file_path_no_tags, "w") as fd: + fd.write(f""" +{Question.yaml_key}: |- + This is a question. +{Answer.yaml_key}: |- + This is an answer. +""") + + def tearDown(self) -> None: + self.file.close() + self.file_path.unlink() + + def test_from_file_yaml(self) -> None: + message = Message.from_file(self.file_path) + self.assertIsInstance(message, Message) + self.assertIsNotNone(message) + if message: + self.assertEqual(message.question, 'This is a question.') + self.assertEqual(message.answer, 'This is an answer.') + self.assertSetEqual(cast(set[Tag], message.tags), {Tag('tag1'), Tag('tag2')}) + self.assertEqual(message.file_path, self.file_path) + + def test_from_file_yaml_no_tags(self) -> None: + message = Message.from_file(self.file_path_no_tags) + self.assertIsInstance(message, Message) + self.assertIsNotNone(message) + if message: + self.assertEqual(message.question, 'This is a question.') + self.assertEqual(message.answer, 'This is an answer.') + self.assertSetEqual(cast(set[Tag], message.tags), set()) + self.assertEqual(message.file_path, self.file_path_no_tags) + + def test_from_file_not_exists(self) -> None: + file_not_exists = pathlib.Path("example.yaml") + with self.assertRaises(MessageError) as cm: + Message.from_file(file_not_exists) + self.assertEqual(str(cm.exception), f"Message file '{file_not_exists}' does not exist")