Beispiel #1
0
    def test_update(self):
        """ Test topics/update.
        """
        # Create a dummy user for testing, log in, and create a topic.

        username = utils.random_username()
        password = utils.random_password()

        user    = users.create(username=username, password=password)
        session = users.login(username=username, password=password)
        topic   = topics.create(session)

        # Try updating the topic.

        updated_topic = topics.update(session, topic['id'],
                                      name="bike", active=False)

        self.assertEqual(updated_topic['name'],    "bike")
        self.assertEqual(updated_topic['active'],  False)

        # Finally, log in as a second user and make sure we can't update the
        # topic for the first user.

        username = utils.random_username()
        password = utils.random_password()

        user    = users.create(username=username, password=password)
        session = users.login(username=username, password=password)

        with self.assertRaises(UnauthorizedException):
            updated_topic = topics.update(session, topic['id'], name="car")
Beispiel #2
0
    def test_create(self):
        """ Test topics/create.
        """
        # Create a dummy user for testing, and log in.

        username = utils.random_username()
        password = utils.random_password()

        user    = users.create(username=username, password=password)
        session = users.login(username=username, password=password)

        # Create a new topic without a name.  The topic API should allocate a
        # random name for this topic.

        topic = topics.create(session)

        self.assertTrue(topic['user_id'] == user['id'])
        self.assertTrue(topic['name'] not in [None, ""])
        self.assertTrue(topic['active'] == True)
        self.assertTrue(topic['default'] == False)
        self.assertTrue(topic['num_views'] == 0)
        self.assertTrue(topic['num_conversations'] == 0)

        # Create a named topic.

        topic = topics.create(session, topic_name="bike")

        self.assertTrue(topic['name'] == "bike")

        # Finally, make sure we can't create a second topic with the same name.

        with self.assertRaises(DuplicateTopicNameException):
            topic = topics.create(session, topic_name="bike")
Beispiel #3
0
    def test_update(self):
        """ Test users/update.
        """
        # Create an ad hoc user, and log in as that user.

        user          = users.create()
        session_token = users.login(user_id=user['id'])

        # Update the ad hoc user, and make sure the user is no longer ad hoc.

        updated_user = users.update(session_token,
                                    username=utils.random_username(),
                                    password=utils.random_password())
        self.assertFalse(updated_user['ad_hoc'])

        # Create a random user with a username and password, and log in as that
        # user.

        username_1 = utils.random_username()
        password_1 = utils.random_password()

        user          = users.create(username=username_1, password=password_1)
        session_token = users.login(username=username_1, password=password_1)

        # Now try updating this user's details.

        username_2 = utils.random_username()
        password_2 = utils.random_password()

        updated_user = users.update(session_token,
                                    username=username_2,
                                    password=password_2,
                                    phone_number=PHONE_NUMBER)

        # Finally, check that the update worked.

        self.assertItemsEqual(updated_user.keys(),
                              ["id", "ad_hoc", "username", "phone_number",
                               "verified", "created_at", "updated_at"])
        self.assertEqual(updated_user['username'], username_2)
Beispiel #4
0
    def test_profiles(self):
        """ Test the various api.profiles functions.
        """
        # Create a dummy user with a random username and password.  This should
        # also create a dummy identity within the 3taps identity API.

        username = utils.random_username()
        password = utils.random_password()

        user = users.create(username=username, password=password)

        # Attempt to log in as this user.

        session_token = users.login(username=username,
                                    password=password)

        sessionHandler.validate(session_token)

        # Retrieve the new user's profile, and make sure that it is empty.

        profile = profiles.get(session_token)
        self.assertItemsEqual(profile.keys(), [])

        # Set the user's profile, including uploading a photo.

        photo_file = file(os.path.join(os.path.dirname(__file__),
                                       "data", "photo.jpg"), "rb")

        ignore = profiles.update(session_token,
                                 photo=photo_file,
                                 name="Test User",
                                 email="*****@*****.**")

        # Check that the profile has been updated.

        profile = profiles.get(session_token)
        self.assertItemsEqual(profile.keys(), ["photo_url_48x48",
                                               "photo_url_72x72",
                                               "photo_url_128x128",
                                               "name",
                                               "email"])

        # Finally, log out again.

        users.logout(session_token)
Beispiel #5
0
    def test_increment_num_views(self):
        """ Test topics/increment_num_views.
        """
        # Create a dummy user for testing, log in, and create a topic.

        username = utils.random_username()
        password = utils.random_password()

        user     = users.create(username=username, password=password)
        session  = users.login(username=username, password=password)
        topic_id = topics.create(session)['id']

        topic = Topic.objects.get(id=topic_id)
        self.assertEqual(topic.num_views, 0)

        topics.increment_num_views(topic_id)

        topic = Topic.objects.get(id=topic_id)
        self.assertEqual(topic.num_views, 1)
Beispiel #6
0
    def test_phone_number_exists(self):
        """ Test users/phone_number_exists.
        """
        # Create a user with a phone number.

        username = utils.random_username()
        password = utils.random_password()

        formatted_number = utils.format_phone_number(PHONE_NUMBER)

        User.objects.filter(phone_number=formatted_number).delete()

        user = users.create(phone_number=PHONE_NUMBER)

        # Check that the phone number can be found.

        self.assertTrue(users.phone_number_exists(PHONE_NUMBER))

        # Check that a different phone number can't be found.

        self.assertFalse(users.phone_number_exists(PHONE_NUMBER+"123"))
Beispiel #7
0
    def test_list(self):
        """ Test topics/list.
        """
        # Create a dummy user for testing, log in, and create a randomly-named
        # topic for that user.

        username = utils.random_username()
        password = utils.random_password()

        user    = users.create(username=username, password=password)
        session = users.login(username=username, password=password)
        topic   = topics.create(session)

        # Get the list of topics for this user.

        topic_list = topics.list(session)

        # Finally, check that we have two topics: the default one, and the one
        # we created.

        self.assertTrue(len(topic_list) == 2)
Beispiel #8
0
    def test_get(self):
        """ Test users/get.
        """
        # Create a random user, and log in.

        username = utils.random_username()
        password = utils.random_password()

        user          = users.create(username=username, password=password)
        session_token = users.login(username=username, password=password)

        # Make sure we can get the details of the logged-in user.

        user_2 = users.get(session=session_token)

        self.assertEqual(user, user_2)

        # Log out, and make sure we can't get the user's details any more.

        users.logout(session_token)

        with self.assertRaises(InvalidSessionException):
            user_2 = users.get(session=session_token)
Beispiel #9
0
    def test_logout(self):
        """ Test users/logout.
        """
        # Create a random user, and log in.

        username = utils.random_username()
        password = utils.random_password()

        user          = users.create(username=username, password=password)
        session_token = users.login(username=username, password=password)

        # Check that we are indeed logged in.

        sessionHandler.validate(session_token)

        # Now log out.

        users.logout(session_token)

        # Finally, check that we are indeed logged out.

        with self.assertRaises(InvalidSessionException):
            sessionHandler.validate(session_token)
Beispiel #10
0
    def test_delete(self):
        """ Test users/delete.
        """
        # Create a test user, and log in as that user.

        username = utils.random_username()
        password = utils.random_password()

        user    = users.create(username=username, password=password)
        session = users.login(username=username, password=password)

        # Delete that user.

        users.delete(session)

        # Finally, check that the user has been deleted from our local
        # database.

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = None

        self.assertEqual(user, None)
Beispiel #11
0
    def test_merge(self):
        """ Test users/merge.
        """
        # Create a user who will be the recipient of our test conversation.

        username = utils.random_username()
        password = utils.random_password()

        user_1    = users.create(username=username, password=password)
        session_1 = users.login(username=username, password=password)

        # Get the default topic for this user.

        topic = topics.list(session_1)[0]

        # Create a second, ad hoc user.

        user_2    = users.create()
        session_2 = users.login(user_id=user_2['id'])

        # Create a third, non-ad hoc user.  This will be the user we merge the
        # ad hoc user into.

        username = utils.random_username()
        password = utils.random_password()

        user_3    = users.create(username=username, password=password)
        session_3 = users.login(username=username, password=password)

        # Send a test message from the 'user_2' to 'user_1's default topic.
        # This will create a conversation between these two users.

        messages.send(session_2, topic_id=topic['id'],
                      message="Test Message 1")

        # Get the conversation we've created.

        try:
            conversation_2_to_1 = \
                Conversation.objects.get(user_1=user_1['id'],
                                         user_2=user_2['id'])
        except Conversation.DoesNotExist:
            conversation_2_to_1 = \
                Conversation.objects.get(user_1=user_2['id'],
                                         user_2=user_1['id'])

        # Get the message for this conversation.

        message_2_to_1 = Message.objects.get(conversation=conversation_2_to_1)

        # Send a test message from 'user_3' to 'user_1's default topic.  This
        # will create a conversation between these two users.

        messages.send(session_3, topic_id=topic['id'],
                      message="Test Message 2")

        # Get the conversation we've created.

        try:
            conversation_3_to_1 = \
                Conversation.objects.get(user_1=user_1['id'],
                                         user_2=user_3['id'])
        except Conversation.DoesNotExist:
            conversation_3_to_1 = \
                Conversation.objects.get(user_1=user_3['id'],
                                         user_2=user_1['id'])

        # Get the message for this conversation.

        message_3_to_1 = Message.objects.get(conversation=conversation_3_to_1)

        # It's now time to pretend that the ad hoc user has identified
        # themselves as actually being the third user.  We merge 'user_2' into
        # 'user_3'.

        users.merge(session_2, session_3)

        # Check that the conversation between user_2 and user_1 no longer
        # exists.

        n = Conversation.objects.filter(user_1=user_1['id'],
                                        user_2=user_2['id']).count()
        n = n + Conversation.objects.filter(user_1=user_2['id'],
                                            user_2=user_1['id']).count()

        self.assertEqual(n, 0)

        # Check that we have exactly one conversation between user_3 and
        # user_1.

        n = Conversation.objects.filter(user_1=user_1['id'],
                                        user_2=user_3['id']).count()
        n = n + Conversation.objects.filter(user_1=user_3['id'],
                                            user_2=user_1['id']).count()

        self.assertEqual(n, 1)

        # Get the conversation between user_3 and user_1.  Note that this might
        # have changed due to the merge -- we don't assume that the same
        # conversation record is used.

        try:
            conversation_3_to_1 = \
                Conversation.objects.get(user_1=user_1['id'],
                                         user_2=user_3['id'])
        except Conversation.DoesNotExist:
            conversation_3_to_1 = \
                Conversation.objects.get(user_1=user_3['id'],
                                         user_2=user_1['id'])

        # Finally, check that the message that was part of conversation_2_to_1
        # is now part of conversation_3_to_1.

        updated_message = Message.objects.get(id=message_2_to_1.id)
        self.assertEqual(updated_message.conversation, conversation_3_to_1)
Beispiel #12
0
    def test_create(self):
        """ Test users/create.
        """
        # Test the process of creating a user without any details.

        user = users.create()
        self.assertItemsEqual(user.keys(),
                              ["id", "ad_hoc", "verified", "created_at",
                               "updated_at"])
        self.assertTrue(user['ad_hoc'])

        # Test the process of creating a user with a username and password.

        user = users.create(username=utils.random_username(),
                            password=utils.random_password())
        self.assertItemsEqual(user.keys(),
                              ["id", "ad_hoc", "username", "verified",
                               "created_at", "updated_at"])
        self.assertFalse(user['ad_hoc'])

        # Check that a default topic has been created for the new user.

        has_default_topic = False

        for topic in Topic.objects.filter(user_id=user['id']):
            if topic.default:
                has_default_topic = True
                break

        self.assertTrue(has_default_topic)

        # Check that we can't create a user with an invalid username.

        with self.assertRaises(InvalidUsernameException):
            user = users.create(username="******", password="******")

        # Check that we can't create a user with an invalid password.

        with self.assertRaises(InvalidPasswordException):
            user = users.create(username=utils.random_username(),
                                password="******")

        # Check that we can't create a user with a username but no password.

        with self.assertRaises(InvalidParametersException):
            user = users.create(username=utils.random_username(),
                                password=None)

        # Check that we can't create a user with a password but not username.

        with self.assertRaises(InvalidParametersException):
            user = users.create(username=None,
                                password=utils.random_password())

        # Check that we can create a user with a valid phone number, and that
        # the phone number is converted to E.164 standard.

        formatted_number = utils.format_phone_number(PHONE_NUMBER)

        User.objects.filter(phone_number=formatted_number).delete()

        user = users.create(phone_number=PHONE_NUMBER)

        self.assertEqual(user['phone_number'], formatted_number)

        # Check that we can't create a second user with the same number.

        with self.assertRaises(DuplicatePhoneNumberException):
            user = users.create(phone_number=PHONE_NUMBER)

        # Check that we can't create a user with an invalid phone number.

        with self.assertRaises(InvalidPhoneNumberException):
            user = users.create(phone_number="INVALID")

        # Check that we can't create two users with the same username.

        username = utils.random_username()
        password = utils.random_password()

        user1 = users.create(username=username, password=password)
        with self.assertRaises(DuplicateUsernameException):
            user2 = users.create(username=username, password=password)
Beispiel #13
0
    def test_receive(self):
        """ Test messages/receive.
        """
        # Create the two users we'll need for our test.

        user_1_username = utils.random_username()
        user_1_password = utils.random_password()

        user_1_id = users.create(username=user_1_username,
                                 password=user_1_password,
                                 phone_number=PHONE_NUMBER)['id']

        user_2_id = users.create(phone_number=PHONE_NUMBER_2)['id']

        user_1 = User.objects.get(id=user_1_id)
        user_2 = User.objects.get(id=user_2_id)

        # Verify user 1's phone number, so that replies will be forwarded to
        # that number.

        user_1.verified = True
        user_1.save()

        # Log in as user 1, and create a topic for this user.  We'll need this
        # topic for our pseudo-conversation.

        session = users.login(username=user_1_username,
                              password=user_1_password)

        topic_id = topics.create(session, topic_name=None)['id']

        topic = Topic.objects.get(id=topic_id)

        # Create our pseudo-conversation.

        conversation = Conversation()
        conversation.user_1 = user_1
        conversation.user_2 = user_2
        conversation.topic  = topic
        conversation.save()

        # Ask the twilio gateway to calculate the phone number to use for
        # sending SMS messages to user 2.  This opens up an SMS channel for the
        # conversation we're pretending to have.

        sending_phone_number = \
            twilio_gateway.calc_sending_phone_number(conversation, user_2)

        # Set up a signal listener to check that the reply was forwarded via
        # Twilio.

        self.twilio_messages = []

        def twilio_signal_handler(sender, **kwargs):
            self.twilio_messages.append(kwargs.get("message"))

        signals.twilio_sms_sent.connect(twilio_signal_handler)

        # Set up a signal listener to check that the reply was forwarded via
        # PubNub.

        self.pubnub_notification_sent = False # initially.
        self.pubnub_message           = None  # ditto.

        def pubnub_signal_handler(sender, **kwargs):
            self.pubnub_notification_sent = True
            self.pubnub_message           = kwargs.get("message")

        signals.pubnub_notification_sent.connect(pubnub_signal_handler)

        # Simulate an incoming SMS reply being received from user 2.  Note that
        # we disable Twilio and PubNub so that the SMS reply isn't actually
        # sent out to the original sender.

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            response = messages.receive(To=sending_phone_number,
                                        From=user_2.phone_number,
                                        Body=REPLY_BODY)

        # Check that the response is what we expect.

        self.assertEqual(response.status_code, 201)
        self.assertEqual(response['Content-Type'], "text/xml")

        # Check that the Twilio gateway sent the message.

        if len(self.twilio_messages) == 0:
            # Whoops!  The reply wasn't forwarded, which means that something
            # went seriously wrong.  Print out the response so we can see the
            # XML message sent back to Twilio.
            print "Error response sent to Twilio:"
            print response.content
            self.fail("Reply not forwarded -> something went wrong.")

        # Check that the PubNub gateway sent the notification.

        self.assertTrue(self.pubnub_notification_sent)
        self.assertEqual(self.pubnub_message.body, REPLY_BODY)
        self.assertEqual(self.pubnub_message.conversation.topic.id, topic_id)

        # Finally, clean everything up.

        signals.twilio_sms_sent.disconnect(twilio_signal_handler)
        signals.pubnub_notification_sent.disconnect(pubnub_signal_handler)
Beispiel #14
0
    def test_send(self):
        """ Test messages/send.
        """
        # Create the sender and recipient users, giving the recipient a phone
        # number so it can receive messages.

        sender_username = utils.random_username()
        sender_password = utils.random_password()

        sender = users.create(username=sender_username,
                              password=sender_password)

        recipient_username = utils.random_username()
        recipient_password = utils.random_password()

        recipient = users.create(username=recipient_username,
                                 password=recipient_password,
                                 phone_number=PHONE_NUMBER)

        # Verify the recipient's phone number.

        recipient_obj = User.objects.get(id=recipient['id'])
        recipient_obj.verified = True
        recipient_obj.save()

        # Log in as the recipient, and create a dummy topic for this user.

        session = users.login(username=recipient_username,
                              password=recipient_password)

        topic = topics.create(session, topic_name=None)

        # Set up a signal listener to check that the message is being sent via
        # Twilio.

        self.twilio_messages = []

        def twilio_signal_handler(sender, **kwargs):
            self.twilio_messages.append(kwargs.get("message"))

        signals.twilio_sms_sent.connect(twilio_signal_handler)

        # Set up a signal listener to check that the message is being sent via
        # PubNub.

        self.pubnub_notification_sent = False # initially.
        self.pubnub_message           = None  # ditto.

        def pubnub_signal_handler(sender, **kwargs):
            self.pubnub_notification_sent = True
            self.pubnub_message           = kwargs.get("message")

        signals.pubnub_notification_sent.connect(pubnub_signal_handler)

        # Log in as the sender, and send a test message to the topic.  Note
        # that we disable Twilio and PubNub so no actual notifications will get
        # sent out.

        session = users.login(username=sender_username,
                              password=sender_password)

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            message = messages.send(session, topic_id=topic['id'],
                                    sender_name="SENDER",
                                    message=MESSAGE_BODY)

        # Check that the Twilio gateway sent the message.

        self.assertEqual(len(self.twilio_messages), 1)

        # Check that the PubNub gateway sent the notification.

        self.assertTrue(self.pubnub_notification_sent)
        self.assertEqual(self.pubnub_message.body, MESSAGE_BODY)
        self.assertEqual(self.pubnub_message.conversation.topic.id,
                         topic['id'])

        # Finally, clean everything up.

        signals.twilio_sms_sent.disconnect(twilio_signal_handler)
        signals.pubnub_notification_sent.disconnect(pubnub_signal_handler)
Beispiel #15
0
    def test_stop_via_sms(self):
        """ Test the stopping of a conversation via sms message.
        """
        # Create two users, giving them a phone number so they can receive
        # messages.

        username_1 = utils.random_username()
        password_1 = utils.random_password()

        username_2 = utils.random_username()
        password_2 = utils.random_password()

        user_1 = users.create(username=username_1,
                              password=password_2,
                              phone_number=PHONE_NUMBER)

        user_2 = users.create(username=username_2,
                              password=password_2,
                              phone_number=PHONE_NUMBER_2)

        # Verify both phone numbers.

        user = User.objects.get(id=user_1['id'])
        user.verified = True
        user.save()

        user = User.objects.get(id=user_2['id'])
        user.verified = True
        user.save()

        # Log in as user 2, and create a dummy topic for this user.

        session = users.login(username=username_2,
                              password=password_2)

        topic = topics.create(session, topic_name=None)

        # Log in as user 1, and send a test message to the topic.  This
        # creates a conversation between the two users.

        session = users.login(username=username_1,
                              password=password_1)

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            message = messages.send(session, topic_id=topic['id'],
                                    message=MESSAGE_BODY)

        # Get the created conversation.

        conversation = conversationHandler.get(user_1['id'],
                                               user_2['id'],
                                               topic['id'])

        # Set up a signal listener to check that the "conversation has stopped"
        # messages were sent out.

        self.twilio_sms_messages = []

        def twilio_signal_handler(sender, **kwargs):
            self.twilio_sms_messages.append(kwargs.get("message"))

        signals.twilio_sms_sent.connect(twilio_signal_handler)

        # Ask the twilio gateway to calculate the phone number to use for
        # sending SMS messages to user 2.  This opens up an SMS channel for the
        # conversation we're pretending to have.

        sending_phone_number = \
            twilio_gateway.calc_sending_phone_number(conversation, user_2)

        # Simulate an incoming SMS reply being received from user 2, containing
        # the word "stop".  Note that we disable Twilio and PubNub so that
        # nothing will actually get sent out.

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            response = messages.receive(To=sending_phone_number,
                                        From=user_2.phone_number,
                                        Body="stop")

        # Check that the Twilio gateway sent the "conversation has been
        # stopped" message to both parties.

        self.assertEqual(len(twilio_sms_messages), 2)

        # Finally, clean everything up.

        signals.twilio_sms_sent.disconnect(twilio_signal_handler)
Beispiel #16
0
    def test_login(self):
        """ Test users/login.
        """
        # Try logging in without any parameters.  This should create a new ad
        # hoc user on-the-fly.

        session_token = users.login()
        self.assertTrue(users.get(session_token)['ad_hoc'])

        # Create an ad-hoc user, and log in using the user ID.

        user_id = users.create()['id']
        session_token = users.login(user_id=user_id)

        # Create a user with a username, password and phone number, for testing.

        username = utils.random_username()
        password = utils.random_password()

        formatted_number = utils.format_phone_number(PHONE_NUMBER)

        User.objects.filter(phone_number=formatted_number).delete()

        user_id = users.create(username=username,
                               password=password,
                               phone_number=PHONE_NUMBER)['id']

        # Create two random verification codes, making sure they're different.

        while True:
            code_1 = utils.random_letters(min_length=4, max_length=4)
            code_2 = utils.random_letters(min_length=4, max_length=4)

            if code_1 != code_2:
                break
            else:
                continue

        # Store the first verification code into the User object.

        user = User.objects.get(id=user_id)
        user.verification_code = code_1
        user.verified          = False
        user.save()

        # Attempt to log in using the supplied phone number and verification
        # code, deliberately using the wrong code.  This should fail.

        with self.assertRaises(LoginRejectedException):
            session_token = users.login(phone_number=PHONE_NUMBER,
                                        verification_code=code_2)

        # Attempt to log in using the username and an incorrect password.  Once
        # again, this should fail.

        with self.assertRaises(LoginRejectedException):
            session_token = users.login(username=username,
                                        password=password+"X")

        # Now try logging in with the correct username and password.  This
        # should succeed.

        session_token = users.login(username=username,
                                    password=password)

        sessionHandler.validate(session_token)

        # Finally, try logging in again using the phone number and verification
        # code.  This should not only log the user it, but also verify the
        # phone number.

        session_token = users.login(phone_number=PHONE_NUMBER,
                                    verification_code=code_1)

        sessionHandler.validate(session_token)

        user = User.objects.get(id=user_id)

        self.assertEqual(user.verified, True)
    def test_close_old_conversations(self):
        """ Test the "close_old_conversations" management command.
        """
        # Create three random users for testing.

        username_1 = utils.random_username()
        password_1 = utils.random_password()
        user_1     = users.create(username=username_1, password=password_1)

        username_2 = utils.random_username()
        password_2 = utils.random_password()
        user_2     = users.create(username=username_2, password=password_2)

        username_3 = utils.random_username()
        password_3 = utils.random_password()
        user_3     = users.create(username=username_3, password=password_3)

        # Create a dummy topic for user 1.

        session = users.login(username=username_1, password=password_1)
        topic = topics.create(session)

        # Create a conversation between user 2 and user 1, about the dummy
        # topic.  This conversation will have a message twelve days old, and a
        # second message just two days old.

        conversation_1 = Conversation()
        conversation_1.user_1_id = user_1['id']
        conversation_1.user_2_id = user_2['id']
        conversation_1.stopped   = False
        conversation_1.topic_id  = topic['id']
        conversation_1.save()

        message = Message()
        message.conversation = conversation_1
        message.sender_id    = user_2['id']
        message.body         = "The quick brown fox"
        message.created_at   = datetime.datetime.utcnow() \
                             - datetime.timedelta(days=12)
        message.updated_at   = message.created_at
        message.save()

        message = Message()
        message.conversation = conversation_1
        message.sender_id    = user_1['id']
        message.body         = "jumps over the lazy dog"
        message.created_at   = datetime.datetime.utcnow() \
                             - datetime.timedelta(days=2)
        message.updated_at   = message.created_at
        message.save()

        # Create a second conversation between user 3 and user 1.  This
        # conversation will have a message five days old.

        conversation_2 = Conversation()
        conversation_2.user_1_id = user_1['id']
        conversation_2.user_2_id = user_3['id']
        conversation_2.stopped   = False
        conversation_2.topic_id  = topic['id']
        conversation_2.save()

        message = Message()
        message.conversation = conversation_2
        message.sender_id    = user_3['id']
        message.body         = "Hello world"
        message.created_at   = datetime.datetime.utcnow() \
                             - datetime.timedelta(days=5)
        message.updated_at   = message.created_at
        message.save()

        # We've now set up the data.  Call our management command to close all
        # conversations older than ten days.

        call_command("close_old_conversations", 10, silent=True)

        # Finally, check that the first conversation has been closed, but the
        # second has not.

        conversation_1 = Conversation.objects.get(id=conversation_1.id)
        conversation_2 = Conversation.objects.get(id=conversation_2.id)

        self.assertEqual(conversation_1.stopped, True)
        self.assertEqual(conversation_2.stopped, False)
    def test_stop_and_restart(self):
        """ Test conversations/stop and conversations/restart.

            Note that this is combined into a single unit test because most of
            the complexity is in setting up the conversation -- it makes sense
            to test both at once so we don't have to set up the conversation
            twice.
        """
        # Create two random users for testing.

        username_1 = utils.random_username()
        password_1 = utils.random_password()

        username_2 = utils.random_username()
        password_2 = utils.random_password()

        user_1_id = users.create(username=username_1,
                                 password=password_1,
                                 phone_number=PHONE_NUMBER)['id']
        user_2_id = users.create(username=username_2,
                                 password=password_2,
                                 phone_number=PHONE_NUMBER_2)['id']

        # Calculate a verification code for the two users.

        with self.settings(ENABLE_TWILIO=False):
            users.send_verification_code(phone_number=PHONE_NUMBER)
            users.send_verification_code(phone_number=PHONE_NUMBER_2)

        # Get the underlying User objects.

        user_1 = User.objects.get(id=user_1_id)
        user_2 = User.objects.get(id=user_2_id)

        # Open up two sessions, one for each user.  Note that this also
        # verifies the users' phone numbers.

        session_1 = users.login(phone_number=PHONE_NUMBER,
                                verification_code=user_1.verification_code)

        session_2 = users.login(phone_number=PHONE_NUMBER_2,
                                verification_code=user_2.verification_code)

        # Get the default topic for user 1.  We'll use this as the topic for
        # our conversation.

        topic_id = topics.list(session_1)[0]['id']
        topic    = Topic.objects.get(id=topic_id)

        # Send a message from user_2 to user_1 about the topic.  This creates a
        # conversation between the two users.

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            messages.send(session_2, topic_id=topic.id, message="Hello")

        # Find the Conversation and make sure it isn't stopped.

        conversation = conversationHandler.get(user_1.id, user_2.id, topic.id)
        self.assertFalse(conversation.stopped)

        # Set up a signal listener to check that the "stopped" message is being
        # sent out via Twilio to both users.

        self.twilio_messages = []

        def twilio_signal_handler(sender, **kwargs):
            self.twilio_messages.append(kwargs.get("message"))

        signals.twilio_sms_sent.connect(twilio_signal_handler)

        # Now try stopping the conversation.  This should send an SMS to each
        # party.

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            conversations.stop(session_1,
                               topic_id=topic.id,
                               other_user_id=user_2.id)

        # Check that the conversation was stopped.

        conversation = conversationHandler.get(user_1.id, user_2.id, topic.id)
        self.assertTrue(conversation.stopped)

        # Check that the two SMS messages were sent.

        self.assertEqual(len(self.twilio_messages), 2)

        # Now try restarting the conversation.  Once again, this should send
        # out an SMS message to each party.

        self.twilio_messages = []

        with self.settings(ENABLE_TWILIO=False, ENABLE_PUBNUB=False):
            conversations.restart(session_1,
                                  topic_id=topic.id,
                                  other_user_id=user_2.id)

        # Check that the conversation was restarted.

        conversation = conversationHandler.get(user_1.id, user_2.id, topic.id)
        self.assertFalse(conversation.stopped)

        # Check that the two SMS messages were sent.

        self.assertEqual(len(self.twilio_messages), 2)

        # Finally, clean up.

        signals.twilio_sms_sent.disconnect(twilio_signal_handler)