def test_that_it_first_sends_messages_from_a_batch_with_higher_priority(self):
        batch2 = MessageBatch(status="Q", name="batch2", priority=2)
        batch2.save()
        outgoing_message_with_low_priority_batch = self.create_message("1234", "test_backend")
        outgoing_message_with_high_priority_batch = self.create_message("3331", "test_backend", batch2)

        self.command.process_messages_for_db(10, "default", self.router_url)

        self.assertEquals((Message.objects.get(pk=outgoing_message_with_low_priority_batch.pk)).status, 'Q')
        self.assertEquals((Message.objects.get(pk=outgoing_message_with_high_priority_batch.pk)).status, 'S')
    def setUp(self):
        self.batch1 = MessageBatch(status="Q", name="batch1", priority=1)
        self.batch1.save()

        self.command = Command()
        self.router_url = "text=%(text)s&to=%(recipient)s&smsc=%(backend)s&%(priority)s"
        self.command.fetch_url = self.fake_get_url
class SendMessagesCommandTestCase(TestCase):
    def setUp(self):
        self.batch1 = MessageBatch(status="Q", name="batch1", priority=1)
        self.batch1.save()

        self.command = Command()
        self.router_url = "text=%(text)s&to=%(recipient)s&smsc=%(backend)s&%(priority)s"
        self.command.fetch_url = self.fake_get_url

    def tearDown(self):
        settings.SUPPORTED_BACKENDS = None

    def fake_get_url(self, url):
        if "400" in url:
            return 403
        return 200

    def create_message(self, id, backend, batch=None):
        fake_connection = Connection(identity=str(id))
        fake_connection.backend, created = Backend.objects.get_or_create(name=backend)
        fake_connection.save()
        message = Message(status='Q', direction="O")
        message.connection = fake_connection

        message.batch = self.batch1 if batch is None else batch
        message.save()
        return message

    def create_message_without_batch(self, id, backend):
        fake_connection = Connection(identity=str(id))
        fake_connection.backend, created = Backend.objects.get_or_create(name=backend)
        fake_connection.save()
        message = Message(status='Q', direction="O")
        message.text = "this is an important message"
        message.connection = fake_connection
        message.batch = None
        message.save()
        return message

    def test_that_build_send_url_replace_special_characters_for_text(self):
        backend = "aggregator"
        recipients = ["2561245678"]
        text = "çà çó ê"
        settings.SPECIAL_CHARS_MAPPING = {"ç": "Ç", "ê": "e"}

        url = self.command.build_send_url(self.router_url, backend, recipients, text)

        expected_text = quote_plus("Çà Çó e")
        expected_url = self.router_url % ({"backend":backend, "recipient": recipients[0], "text": expected_text, "priority": 1})
        self.assertEquals(expected_url, url)

    def test_build_send_url_fixes_incompatible_utf_8_message_text(self):
        backend = "aggregator"
        recipients = ["2561245678"]
        text = u'Hello Emanuele: ù ê é è Ç à @ ç'
        settings.SPECIAL_CHARS_MAPPING = {'ç': 'Ç', 'ê': 'e'}

        connection = Connection.objects.create(identity=recipients[0], backend=Backend.objects.create(name=backend))
        message = Message.objects.create(text=text, connection=connection)

        url = self.command.build_send_url(self.router_url, backend, recipients, message.text)

        expected_text = quote_plus('Hello Emanuele: ù e é è Ç à @ Ç')
        expected_url = self.router_url % ({"backend":backend, "recipient": recipients[0], "text": expected_text, "priority": 1})
        self.assertEquals(expected_url, url)

    def test_that_build_send_url_do_not_change_NON_special_characters(self):
        backend = "aggregator"
        recipients = ["2561245678"]
        text = "ha he ho"
        settings.SPECIAL_CHARS_MAPPING = {"ç": "Ç", "ê": "e"}

        url = self.command.build_send_url(self.router_url, backend, recipients, text)

        expected_text = quote_plus(text)
        expected_url = self.router_url % ({"backend":backend, "recipient": recipients[0], "text": expected_text, "priority": 1})
        self.assertEquals(expected_url, url)

    def test_send_all_updates_status_to_sent_if_fetch_returns_200(self):
        self.command.db_key = "default"
        self.message = self.create_message(129, "fake")
        self.command.send_all(self.router_url, [self.message], 1)
        self.assertEquals((Message.objects.get(pk=self.message.pk)).status, 'S')


    def test_process_messages_for_db_processes_all_first_chunk_of_the_messages(self):
        msg1 = self.create_message(3, "fake")
        msg2 = self.create_message(2, "fake")
        self.command.process_messages_for_db(3, "default", self.router_url)
        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')

    def test_process_messages_can_handle_a_non_routable_backend(self):
        msg1 = self.create_message(1, "fake")
        msg2 = self.create_message(2, "fake")
        msg3 = self.create_message(400, "warid")
        msg4 = self.create_message(4, "fake")
        self.command.process_messages_for_db(5, "default", self.router_url)
        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg3.pk)).status, 'K')
        self.assertEquals((Message.objects.get(pk=msg4.pk)).status, 'S')

    def test_process_messages_only_for_valid_backends(self):
        settings.SUPPORTED_BACKENDS = {"fake": {}, "valid_backend": {}}
        msg1 = self.create_message(1, "fake")
        msg2 = self.create_message(2, "fake")
        msg3 = self.create_message(3, "invalid")
        msg4 = self.create_message(4, "invalid")
        msg5 = self.create_message(5, "fake")
        self.command.process_messages_for_db(10, "default", self.router_url)
        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg3.pk)).status, 'B')
        self.assertEquals((Message.objects.get(pk=msg4.pk)).status, 'B')
        self.assertEquals((Message.objects.get(pk=msg5.pk)).status, 'S')

    def test_batch_is_mark_as_sent_after_marked_messages_with_invalid_backends(self):
        settings.SUPPORTED_BACKENDS = {"fake": {}, "valid_backend": {}}
        msg1 = self.create_message(1, "fake")
        msg2 = self.create_message(3, "invalid")
        msg3 = self.create_message(5, "fake")
        self.command.process_messages_for_db(10, "default", self.router_url)
        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'B')
        self.assertEquals((Message.objects.get(pk=msg3.pk)).status, 'S')
        self.command.process_messages_for_db(10, "default", self.router_url)
        self.assertEquals(MessageBatch.objects.get(pk=self.batch1.pk).status, 'C')

    def test_that_invalid_numbers_are_marked_as_blocked(self):
        settings.SUPPORTED_BACKENDS = {"valid_backend": {"identity_validation_regex": "[a-c]+"},
                                       "sms_backend": {"identity_validation_regex": "[0-9]+"}}
        msg1 = self.create_message("x", "valid_backend")
        msg2 = self.create_message("ab", "valid_backend")
        msg3 = self.create_message(4, "sms_backend")
        msg4 = self.create_message("invalid", "sms_backend")

        self.command.process_messages_for_db(10, "default", self.router_url)

        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'C')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg3.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=msg4.pk)).status, 'C')

    def test_that_message_is_not_sent_when_connection_identity_has_letters_without_valid_backends_configuration(self):
        msg1 = self.create_message("invalid", "sms_backend")
        msg2 = self.create_message(4, "sms_backend")
        self.command.process_messages_for_db(10, "default", self.router_url)
        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'Q')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')

    def test_that_message_is_not_sent_when_connection_identity_has_letters_and_no_validation_regex(self):
        settings.SUPPORTED_BACKENDS = {"valid_backend": {}}
        msg1 = self.create_message("x", "valid_backend")
        msg2 = self.create_message(2, "valid_backend")

        self.command.process_messages_for_db(10, "default", self.router_url)

        self.assertEquals((Message.objects.get(pk=msg1.pk)).status, 'Q')
        self.assertEquals((Message.objects.get(pk=msg2.pk)).status, 'S')

    def test_that_if_single_message_with_out_batch_is_present_it_is_sent_alongside_the_batched_messages(self):
        settings.SUPPORTED_BACKENDS = {"valid_backend": {}}
        outgoing_message_without_batch = self.create_message_without_batch("123", "valid_backend")
        outgoing_message_with_batch = self.create_message("1234", "valid_backend")
        self.command.process_messages_for_db(10, "default", self.router_url)

        self.assertEquals((Message.objects.get(pk=outgoing_message_without_batch.pk)).status, 'S')
        self.assertEquals((Message.objects.get(pk=outgoing_message_with_batch.pk)).status, 'S')

    def test_that_it_first_sends_messages_from_a_batch_with_higher_priority(self):
        batch2 = MessageBatch(status="Q", name="batch2", priority=2)
        batch2.save()
        outgoing_message_with_low_priority_batch = self.create_message("1234", "test_backend")
        outgoing_message_with_high_priority_batch = self.create_message("3331", "test_backend", batch2)

        self.command.process_messages_for_db(10, "default", self.router_url)

        self.assertEquals((Message.objects.get(pk=outgoing_message_with_low_priority_batch.pk)).status, 'Q')
        self.assertEquals((Message.objects.get(pk=outgoing_message_with_high_priority_batch.pk)).status, 'S')