From 5c8635570da85d368465aea23989e8d0530d7ba8 Mon Sep 17 00:00:00 2001 From: mattie ruth backman Date: Tue, 21 Oct 2025 15:04:34 -0400 Subject: [PATCH] test fixes --- .../35-pattern-pair-voice-switching.py | 1 + src/pipecat/extensions/ivr/ivr_navigator.py | 10 +++++-- tests/test_pattern_pair_aggregator.py | 29 +++++++++++++------ tests/test_skip_tags_aggregator.py | 24 ++++++++------- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/examples/foundational/35-pattern-pair-voice-switching.py b/examples/foundational/35-pattern-pair-voice-switching.py index 7ed9eb268..013c3eecd 100644 --- a/examples/foundational/35-pattern-pair-voice-switching.py +++ b/examples/foundational/35-pattern-pair-voice-switching.py @@ -110,6 +110,7 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): pattern_id="voice_tag", start_pattern="", end_pattern="", + type="voice", remove_match=True, ) diff --git a/src/pipecat/extensions/ivr/ivr_navigator.py b/src/pipecat/extensions/ivr/ivr_navigator.py index 05748d94f..c4e31e12a 100644 --- a/src/pipecat/extensions/ivr/ivr_navigator.py +++ b/src/pipecat/extensions/ivr/ivr_navigator.py @@ -114,15 +114,19 @@ class IVRProcessor(FrameProcessor): def _setup_xml_patterns(self): """Set up XML pattern detection and handlers.""" # Register DTMF pattern - self._aggregator.add_pattern_pair("dtmf", "", "", remove_match=True) + self._aggregator.add_pattern_pair( + "dtmf", "", "", type="dtmf", remove_match=True + ) self._aggregator.on_pattern_match("dtmf", self._handle_dtmf_action) # Register mode pattern - self._aggregator.add_pattern_pair("mode", "", "", remove_match=True) + self._aggregator.add_pattern_pair( + "mode", "", "", type="mode", remove_match=True + ) self._aggregator.on_pattern_match("mode", self._handle_mode_action) # Register IVR pattern - self._aggregator.add_pattern_pair("ivr", "", "", remove_match=True) + self._aggregator.add_pattern_pair("ivr", "", "", type="ivr", remove_match=True) self._aggregator.on_pattern_match("ivr", self._handle_ivr_action) async def process_frame(self, frame: Frame, direction: FrameDirection): diff --git a/tests/test_pattern_pair_aggregator.py b/tests/test_pattern_pair_aggregator.py index 8426dcf39..d0e13ffc6 100644 --- a/tests/test_pattern_pair_aggregator.py +++ b/tests/test_pattern_pair_aggregator.py @@ -20,8 +20,16 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): pattern_id="test_pattern", start_pattern="", end_pattern="", + type="test", remove_match=True, ) + self.aggregator.add_pattern_pair( + pattern_id="code_pattern", + start_pattern="", + end_pattern="", + type="code", + remove_match=False, + ) # Register the mock handler self.aggregator.on_pattern_match("test_pattern", self.test_handler) @@ -30,7 +38,8 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): # First part doesn't complete the pattern result = await self.aggregator.aggregate("Hello pattern") self.assertIsNone(result) - self.assertEqual(self.aggregator.text, "Hello pattern") + self.assertEqual(self.aggregator.text.text, "Hello pattern") + self.assertEqual(self.aggregator.text.type, "test") # Second part completes the pattern and includes an exclamation point result = await self.aggregator.aggregate(" content!") @@ -45,14 +54,15 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): # The exclamation point should be treated as a sentence boundary, # so the result should include just text up to and including "!" - self.assertEqual(result, "Hello !") + self.assertEqual(result.text, "Hello !") + self.assertEqual(result.type, "sentence") # Next sentence should be processed separately result = await self.aggregator.aggregate(" This is another sentence.") - self.assertEqual(result, " This is another sentence.") + self.assertEqual(result.text, " This is another sentence.") # Buffer should be empty after returning a complete sentence - self.assertEqual(self.aggregator.text, "") + self.assertEqual(self.aggregator.text.text, "") async def test_incomplete_pattern(self): # Add text with incomplete pattern @@ -65,11 +75,12 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): self.test_handler.assert_not_called() # Buffer should contain the incomplete text - self.assertEqual(self.aggregator.text, "Hello pattern content") + self.assertEqual(self.aggregator.text.text, "Hello pattern content") + self.assertEqual(self.aggregator.text.type, "test") # Reset and confirm buffer is cleared await self.aggregator.reset() - self.assertEqual(self.aggregator.text, "") + self.assertEqual(self.aggregator.text.text, "") async def test_multiple_patterns(self): # Set up multiple patterns and handlers @@ -109,7 +120,7 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): self.assertEqual(result, "Hello I am very excited to meet you!") # Buffer should be empty - self.assertEqual(self.aggregator.text, "") + self.assertEqual(self.aggregator.text.text, "") async def test_handle_interruption(self): # Start with incomplete pattern @@ -120,7 +131,7 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): await self.aggregator.handle_interruption() # Buffer should be cleared - self.assertEqual(self.aggregator.text, "") + self.assertEqual(self.aggregator.text.text, "") # Handler should not have been called self.test_handler.assert_not_called() @@ -144,4 +155,4 @@ class TestPatternPairAggregator(unittest.IsolatedAsyncioTestCase): self.assertEqual(result, "Hello Final sentence.") # Buffer should be empty - self.assertEqual(self.aggregator.text, "") + self.assertEqual(self.aggregator.text.text, "") diff --git a/tests/test_skip_tags_aggregator.py b/tests/test_skip_tags_aggregator.py index f6cbb7b93..702b991ce 100644 --- a/tests/test_skip_tags_aggregator.py +++ b/tests/test_skip_tags_aggregator.py @@ -18,16 +18,18 @@ class TestSkipTagsAggregator(unittest.IsolatedAsyncioTestCase): # No tags involved, aggregate at end of sentence. result = await self.aggregator.aggregate("Hello Pipecat!") - self.assertEqual(result, "Hello Pipecat!") - self.assertEqual(self.aggregator.text, "") + self.assertEqual(result.text, "Hello Pipecat!") + self.assertEqual(result.type, "sentence") + self.assertEqual(self.aggregator.text.text, "") async def test_basic_tags(self): await self.aggregator.reset() # Tags involved, avoid aggregation during tags. result = await self.aggregator.aggregate("My email is foo@pipecat.ai.") - self.assertEqual(result, "My email is foo@pipecat.ai.") - self.assertEqual(self.aggregator.text, "") + self.assertEqual(result.text, "My email is foo@pipecat.ai.") + self.assertEqual(result.type, "sentence") + self.assertEqual(self.aggregator.text.text, "") async def test_streaming_tags(self): await self.aggregator.reset() @@ -35,20 +37,22 @@ class TestSkipTagsAggregator(unittest.IsolatedAsyncioTestCase): # Tags involved, stream small chunk of texts. result = await self.aggregator.aggregate("My email is foo.") self.assertIsNone(result) - self.assertEqual(self.aggregator.text, "My email is foo.") + self.assertEqual(self.aggregator.text.text, "My email is foo.") result = await self.aggregator.aggregate("bar@pipecat.") self.assertIsNone(result) - self.assertEqual(self.aggregator.text, "My email is foo.bar@pipecat.") + self.assertEqual(self.aggregator.text.text, "My email is foo.bar@pipecat.") result = await self.aggregator.aggregate("aifoo.bar@pipecat.aifoo.bar@pipecat.ai.") - self.assertEqual(result, "My email is foo.bar@pipecat.ai.") - self.assertEqual(self.aggregator.text, "") + self.assertEqual(result.text, "My email is foo.bar@pipecat.ai.") + self.assertEqual(self.aggregator.text.text, "") + self.assertEqual(self.aggregator.text.type, "sentence")