def testStrictRules(self): step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) # modify setUp() ScriptStep 2 to be LENIENT step.rule = ScriptStep.STRICT_MOVEON step.num_tries = 2 step.retry_offset = 60 step.giveup_offset = 0 step.save() # dummy progress, the question for step two has been sent out, now we check # that any response (even erroneous) advances progress connection = Connection.objects.all()[0] script = Script.objects.get(slug="test_autoreg") step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) prog = ScriptProgress.objects.create(connection=connection, script=script, step=step, status='P') # create a dummy session session = ScriptSession.objects.create(connection=connection, script=script) incomingmessage = self.fakeIncoming('Jack cheese is a cheese that I like') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "We didn't understand your response and it's very important to know about your cheese desires. Please resend.") self.assertEquals(Response.objects.count(), 1) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this erroneous poll response DID update the progress, # since the rule is now lenient r = Response.objects.order_by('-date')[0] self.failUnless(r.has_errors) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'P') self.assertEquals(prog.num_tries, 1) incomingmessage = self.fakeIncoming('Well, I also like cheddar') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "We didn't understand your response and it's very important to know about your cheese desires. Please resend.") self.assertEquals(Response.objects.count(), 2) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this erroneous poll response DID update the progress, # since the rule is now lenient r = Response.objects.order_by('-date')[0] self.failUnless(r.has_errors) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'P') self.assertEquals(prog.num_tries, 2) check_progress(self.script) # refresh progress prog = ScriptProgress.objects.get(connection=connection) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'C')
def testIncomingProgress(self): connection = Connection.objects.all()[0] script = Script.objects.get(slug="test_autoreg") step = ScriptStep.objects.get(script__slug='test_autoreg', order=1) prog = ScriptProgress.objects.create(connection=connection, script=script, step=step, status='P') # create a dummy session session = ScriptSession.objects.create(connection=connection, script=script) incomingmessage = self.fakeIncoming('I like all forms of spam, but typically Nigerian email spam is the best.') incoming_progress(incomingmessage) self.assertEquals(Response.objects.count(), 1) self.assertEquals(ScriptSession.objects.count(), 1) self.assertEquals(ScriptSession.objects.all()[0].responses.count(), 1) # refresh progress prog = ScriptProgress.objects.get(connection=connection) self.assertEquals(prog.step.order, 1) self.assertEquals(prog.status, 'C') # manually move to next step, check_progress would do this prog.step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) prog.status = 'P' prog.save() incomingmessage = self.fakeIncoming('Jack cheese is a cheese that I like') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "We didn't understand your response and it's very important to know about your cheese desires. Please resend.") self.assertEquals(Response.objects.count(), 2) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this erroneous poll response didn't update the progress r = Response.objects.order_by('-date')[0] self.failUnless(r.has_errors) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'P') incomingmessage = self.fakeIncoming('YES I like jack cheese you silly poll!!!eleventyone') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "It's very good to know that you like cheese!") r = Response.objects.order_by('-date')[0] self.failIf(r.has_errors) self.assertEquals(Response.objects.count(), 3) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this correct poll response updated the progress self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'C')
def handle (self, message): reg = re.compile('COMPLETE|DAMAGED') waybills = filter(None, reg.split(message.db_message.text.upper())) if len(waybills) > 0: for waybill in waybills: # waybill=waybill_match.group('waybill') delivery=Delivery.objects.get(waybill=waybill.strip()) #check if message is from consignee if delivery.consignee.default_connection.identity == message.connection.identity: delivery.status = Delivery.DELIVERED delivery.date_delivered = datetime.datetime.now() delivery.save() #if it is in the backlog, delete it if DeliveryBackLog.objects.filter(delivery__waybill=waybill.strip()).exists(): DeliveryBackLog.objects.get(delivery=delivery).delete() #in case consignee has sent delivery report, send it out to supply admins if delivery.consignee.default_connection.identity == message.connection.identity: supply_admins = Contact.objects.filter(groups__name__in=['supply_admin']) recipients = list(supply_admins.values_list('user__email',flat=True).distinct()) sender = '*****@*****.**' subject = 'SupplyTracking: Delivery Report' message = message.db_message.text if message.strip(): send_mail(subject, message, sender, recipients, fail_silently=False) #process and send out response to message sender response = incoming_progress(message) if response: message.respond(response) return True else: return False
def testLenient(self): step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) # modify setUp() ScriptStep 2 to be LENIENT step.rule = ScriptStep.LENIENT step.save() # dummy progress, the question for step two has been sent out, now we check # that any response (even erroneous) advances progress connection = Connection.objects.all()[0] script = Script.objects.get(slug="test_autoreg") step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) prog = ScriptProgress.objects.create(connection=connection, script=script, step=step, status='P') # create a dummy session session = ScriptSession.objects.create(connection=connection, script=script) incomingmessage = self.fakeIncoming( 'Jack cheese is a cheese that I like') response_message = incoming_progress(incomingmessage) self.assertEquals( response_message, "We didn't understand your response and it's very important to know about your cheese desires. Please resend." ) self.assertEquals(Response.objects.count(), 1) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this erroneous poll response DID update the progress, # since the rule is now lenient r = Response.objects.order_by('-date')[0] self.failUnless(r.has_errors) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'C')
def testTransporterScript(self): #upload excel, this should result into creation of a delivery upload_file = open(os.path.join(os.path.join(os.path.realpath(os.path.dirname(__file__)),'fixtures'),'excel.xls'), 'rb') file_dict = {'excel_file': SimpleUploadedFile(upload_file.name, upload_file.read())} form = UploadForm({},file_dict) self.assertTrue(form.is_valid()) msg = handle_excel_file(form.cleaned_data['excel_file']) #wait one day and upload another excel progress = ScriptProgress.objects.get(connection=Contact.objects.get(name='3ways shipping').default_connection) self.elapseTime(progress, 86401) upload_file = open(os.path.join(os.path.join(os.path.realpath(os.path.dirname(__file__)),'fixtures'),'excel2.xls'), 'rb') file_dict = {'excel_file': SimpleUploadedFile(upload_file.name, upload_file.read())} form = UploadForm({},file_dict) self.assertTrue(form.is_valid()) msg = handle_excel_file(form.cleaned_data['excel_file']) #transporter has different shipments in shipped status self.assertEquals(Delivery.objects.filter(transporter=Contact.objects.get(name='3ways shipping'),status='S').count(), 4) #transporter does not advance to step 0 before the start_offset time has expired transporter_script=Script.objects.get(slug='transporter') default_connection = Contact.objects.get(name='3ways shipping').default_connection transporter_connection = default_connection.pk response = check_progress(transporter_connection) self.assertEquals(progress.step, None) self.assertEquals(response, None) #elapse 3 days self.elapseTime(progress, 259201) #transporter should advance to step 0 of transporter script for deliveries uploaded 3 or more days ago response = check_progress(transporter_connection) progress = ScriptProgress.objects.get(connection=transporter_connection, script=transporter_script) self.assertEquals(progress.step.order, 0) response_msg = Template(response) self.assertEquals(response_msg.render(Context(transporter_connection)), 'Has the consignment been delivered?') self.assertEquals(Delivery.objects.filter(transporter=Contact.objects.get(name='3ways shipping'), status='S').count(), 4) self.assertEquals(DeliveryBackLog.objects.get(delivery__waybill='kp/wb11/00037'), Delivery.objects.get(waybill='kp/wb11/00037')) #transporter sending delivery message does not affect delivery status incomingmessage = self.fakeIncoming('kp/wb11/00034 Delivered') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "Thanks for your response") progress = ScriptProgress.objects.get(connection=transporter_connection, script=transporter_script) self.assertEquals(Delivery.objects.get(waybill='kp/wb11/00034').status, 'S') #new delivery objects are thrown into backlog since there is already an active script progression for admins self.assertEquals(DeliveryBackLog.objects.get(delivery__waybill='kp/wb11/00037'), Delivery.objects.get(waybill='kb/wb11/00037'))
def handle (self, message): try: progress = ScriptProgress.objects.filter(connection=message.connection, time__lte=datetime.datetime.now()).order_by('-time') if progress.count(): progress = progress[0] script_last_step = ScriptStep.objects.filter(script=progress.script).order_by('-order')[0] if progress.step and progress.step.order == script_last_step.order and progress.status == 'C': return False else: response = incoming_progress(message) if response: message.respond(gettext_db(response,progress.language)) return True except ScriptProgress.DoesNotExist: pass return False
def testConsigneeScript(self): #upload excel, this should result into creation of a delivery upload_file = open(os.path.join(os.path.join(os.path.realpath(os.path.dirname(__file__)),'fixtures'),'excel.xls'), 'rb') file_dict = {'excel_file': SimpleUploadedFile(upload_file.name, upload_file.read())} form = UploadForm({},file_dict) self.assertTrue(form.is_valid()) msg = handle_excel_file(form.cleaned_data['excel_file']) #wait one day and upload another excel self.elapseTime(progress[0], 86401) upload_file = open(os.path.join(os.path.join(os.path.realpath(os.path.dirname(__file__)),'fixtures'),'excel2.xls'), 'rb') file_dict = {'excel_file': SimpleUploadedFile(upload_file.name, upload_file.read())} form = UploadForm({},file_dict) self.assertTrue(form.is_valid()) msg = handle_excel_file(form.cleaned_data['excel_file']) #consignee has different shipments in shipped status self.assertEquals(Delivery.objects.filter(consignee=Contact.objects.get(name='action against hunger', status='S')).count(), 2) #consignee has not yet advanced into the script (step 0) consignee_script=Script.objects.get(slug='consignee') consignee_connection = Contact.objects.get(name='action against hunger').default_connection progress = ScriptProgress.objects.create(connection=consignee_connection, script=consignee_script) response = check_progress(consignee_connection) self.assertEquals(progress.step, None) self.assertEquals(response, None) #elapse 3 days self.elapseTime(progress, 259201) #consignee should advance to step 0 of consignee script for deliveries uploaded 3 more days ago response = check_progress(consignee_connection) progress = ScriptProgress.objects.get(connection=consignee_connection, script=consignee_script) self.assertEquals(progress.step.order, 0) self.assertEquals(response, 'Has the consignment been delivered?') self.assertEquals(Delivery.objects.filter(consignee=Contact.objects.get(name='action against hunger', status='S')).count(), 2) self.assertEquals(DeliveryBackLog.objects.get(delivery__waybill='kp/wb11/00037'), Delivery.objects.get(waybill='kp/wb11/00037')) #consignee sending in a delivery message should complete the script for transporter and consignee and mark orders as delivered incomingmessage = self.fakeIncoming('kp/wb11/00034 COMPLETE kb/wb11/00037 COMPLETE') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "Thanks for your response") progress = ScriptProgress.objects.get(connection=consignee_connection, script=consignee_script) self.assertEquals(Delivery.objects.filter(consignee=Contact.objects.get(name='action against hunger', status='D')).count(), 2) self.assertEquals(DeliveryBackLog.objects.filter(delivery__consignee=Contact.objects.get(name='action against hunger')), None)
def handle(self, message): try: progress = ScriptProgress.objects.filter( connection=message.connection, time__lte=datetime.datetime.now()).order_by('-time') if progress.count(): progress = progress[0] script_last_step = ScriptStep.objects.filter( script=progress.script).order_by('-order')[0] if progress.step and progress.step.order == script_last_step.order and progress.status == 'C': return False else: response = incoming_progress(message) if response: message.respond(gettext_db(response, progress.language)) return True except ScriptProgress.DoesNotExist: pass return False
def handle (self, message): if handle_dongle_sms(message): return True if message.text.strip().lower() in [i.lower() for i in getattr(settings, 'OPT_OUT_WORDS', ['quit'])]: if Blacklist.objects.filter(connection=message.connection).exists(): message.respond('You cannot send Quit to 6200 (EduTrac) more than once.') return True else: if ScriptProgress.objects.filter(connection=message.connection, script__slug='edtrac_autoreg').exists(): # user is attempting to quit before completing registration message.respond('Your registration is not complete. You cannot quit at this point.') return True Blacklist.objects.create(connection=message.connection) ScriptProgress.objects.filter(connection=message.connection).delete() # delete all script progress since the user has quit ScriptSession.objects.filter(connection=message.connection, end_time=None).delete() # the non closed out sessions need to be expunged as well if (message.connection.contact): message.connection.contact.active = False message.connection.contact.save() message.respond(getattr(settings, 'OPT_OUT_CONFIRMATION', 'Thank you for your contribution to EduTrac. To rejoin the system, send join to 6200')) return True elif message.text.strip().lower() in [i.lower() for i in getattr(settings, 'OPT_IN_WORDS', ['join'])]: if not message.connection.contact: if ScriptProgress.objects.filter(script__slug='edtrac_autoreg', connection=message.connection).count() == 0: ScriptProgress.objects.create(script=Script.objects.get(slug="edtrac_autoreg"),\ connection=message.connection) else: message.respond("Your registration is not complete yet, you do not need to 'Join' again.") elif Blacklist.objects.filter(connection=message.connection).exists(): Blacklist.objects.filter(connection=message.connection).delete() if not ScriptProgress.objects.filter(script__slug='edtrac_autoreg', connection=message.connection).count(): ScriptProgress.objects.create(script=Script.objects.get(slug="edtrac_autoreg"),\ connection=message.connection) else: message.respond("You are already in the system and do not need to 'Join' again.") return True elif Blacklist.objects.filter(connection=message.connection).count(): return True # when all else fails, quit! else: try: progress = ScriptProgress.objects.filter(connection=message.connection, time__lte=datetime.datetime.now()).order_by('-time') response_message_string = {"n":"The answer you have provided is not in the correct format. Use figures like 3 to answer the question", "t":"The answer you have provided is not in the correct format. Please follow instructions that were given to you"} if progress.count(): progress = progress[0] script_last_step = ScriptStep.objects.filter(script=progress.script).order_by('-order')[0] if progress.step and progress.step.order == script_last_step.order and progress.status == 'C': return False else: response = incoming_progress(message) if not progress.script.slug == 'edtrac_autoreg': r = Response.objects.filter(contact__connection=message.connection,date__lte=datetime.datetime.now(),message__text=message.text).latest('date') if r is not None: if r.has_errors: progress.status = ScriptProgress.PENDING progress.save() Message.mass_text(response_message_string[r.poll.type], [message.connection]) Message.mass_text(r.poll.question , [message.connection]) if response: message.respond(gettext_db(response,progress.language)) return True except ScriptProgress.DoesNotExist: logger.debug("\nScript Progress object not found for message %s with connection %s" % (message,message.connection)) return False
def handle (self, message): if handle_dongle_sms(message): return True if message.text.strip().lower() in [i.lower() for i in getattr(settings, 'OPT_OUT_WORDS', ['quit'])]: if Blacklist.objects.filter(connection=message.connection).exists(): message.respond('You cannot send Quit to 6200 (EduTrac) more than once.') return True else: if ScriptProgress.objects.filter(connection=message.connection, script__slug='edtrac_autoreg').exists(): # user is attempting to quit before completing registration message.respond('Your registration is not complete, you can not quit at this point') return True Blacklist.objects.create(connection=message.connection) ScriptProgress.objects.filter(connection=message.connection).delete() # delete all script progress since the user has quit ScriptSession.objects.filter(connection=message.connection, end_time=None).delete() # the non closed out sessions need to be expunged as well if (message.connection.contact): message.connection.contact.active = False message.connection.contact.save() message.respond(getattr(settings, 'OPT_OUT_CONFIRMATION', 'Thank you for your contribution to EduTrac. To rejoin the system, send join to 6200')) return True elif message.text.strip().lower() in [i.lower() for i in getattr(settings, 'OPT_IN_WORDS', ['join'])]: if not message.connection.contact: if ScriptProgress.objects.filter(script__slug='edtrac_autoreg', connection=message.connection).count() == 0: ScriptProgress.objects.create(script=Script.objects.get(slug="edtrac_autoreg"),\ connection=message.connection) else: message.respond("Your registration is not complete yet, you do not need to 'Join' again.") elif Blacklist.objects.filter(connection=message.connection).exists(): Blacklist.objects.filter(connection=message.connection).delete() if not ScriptProgress.objects.filter(script__slug='edtrac_autoreg', connection=message.connection).count(): ScriptProgress.objects.create(script=Script.objects.get(slug="edtrac_autoreg"),\ connection=message.connection) else: message.respond("You are already in the system and do not need to 'Join' again.") return True elif Blacklist.objects.filter(connection=message.connection).count(): return True # when all else fails, quit! else: try: progress = ScriptProgress.objects.filter(connection=message.connection, time__lte=datetime.datetime.now()).order_by('-time') response_message_string = {"n":"The answer you have provided is not in the correct format. Use figures like 3 to answer the question", "t":"The answer you have provided is not in the correct format. Please follow instructions that were given to you"} if progress.count(): progress = progress[0] script_last_step = ScriptStep.objects.filter(script=progress.script).order_by('-order')[0] if progress.step and progress.step.order == script_last_step.order and progress.status == 'C': return False else: response = incoming_progress(message) if not progress.script.slug == 'edtrac_autoreg': r = Response.objects.filter(contact__connection=message.connection,date__lte=datetime.datetime.now(),message__text=message.text).latest('date') if r is not None: if r.has_errors: progress.status = ScriptProgress.PENDING progress.save() Message.mass_text(response_message_string[r.poll.type], [message.connection]) Message.mass_text(r.poll.question , [message.connection]) if response: message.respond(gettext_db(response,progress.language)) return True except ScriptProgress.DoesNotExist: logger.debug("\nScript Progress object not found for message %s with connection %s" % (message,message.connection)) return False
def testFullScriptFlow(self): script = Script.objects.get(slug="test_autoreg") connection = Connection.objects.all()[0] progress = ScriptProgress.objects.create(connection=connection, script=script) # test that an incoming message from a user freshly added to the script # (i.e., no call to check_progress yet) doesn't fail incomingmessage = self.fakeIncoming('Im in the script, but nothings happened yet. What next?') response_message = incoming_progress(incomingmessage) # no response message self.assertEquals(response_message, None) # refresh progress, no updates to progress should be made # no ScriptSession should be created, that's up to check_progress progress = self.assertProgress(connection, None, '', 0, 0) # modify step 1, check_progress should wait a full minute before sending out # the first message step0 = script.steps.get(order=0) step0.start_offset = 60 step0.save() res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # we're still waiting to send the first message, for a full minute self.assertEquals(response, None) self.elapseTime(progress, 60) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # we're ready for the first message to go out self.assertEquals(response, step0.message) # refresh progress # we should now be advanced to step 0, in 'P'ending status # because it's a WAIT_MOVEON step, so we have to wait for one # hour before advancing to the next step # there should be a scriptsession at this point # but there shouldn't be any responses progress = self.assertProgress(connection, 0, 'P', 1, 0) # test that an incoming message from a user in this portion # of the script doesn't affect the progress incomingmessage = self.fakeIncoming('Im in the script, but Im waiting to be asked a question. Why do I have to wait for an hour?') response_message = incoming_progress(incomingmessage) # no response message self.assertEquals(response_message, None) # refresh progress # no updates to progress # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 0, 'P', 1, 0) # now let's wait a full hour self.elapseTime(progress, 3600) step1 = script.steps.get(order=1) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, step1.poll.question) # refresh progress # check that the step is now step 1, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 1, 'P', 1, 0) # check that an additional call to check_progress doesn't re-send the # question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, None) # check that the step is still step 1, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 1, 'P', 1, 0) # test the moveon scenario, wait a full day with no response self.elapseTime(progress, 86400) # make sure that incoming_progress respects the giveup time of # the previous step and drops any messages (otherwise it's a # potential race contidion incomingmessage = self.fakeIncoming('I like spam, Im just a little late to mention anything about it') response_message = incoming_progress(incomingmessage) self.assertEquals(response, None) progress = self.assertProgress(connection, 1, 'P', 1, 0) # check that this call to check_progress sends out the # next question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None step2 = script.steps.get(order=2) # the first poll question should go out now self.assertEquals(response, step2.poll.question) # check that the step is now step 2, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 2, 'P', 1, 0) # test the scenario where a response is received progress.step = step1 progress.status = 'P' progress.save() session = ScriptSession.objects.all()[0] session.start_time = datetime.datetime.now() session.end_time = None for r in session.responses.all(): r.delete() for r in Response.objects.all(): r.delete() session.save() # test that an incoming message from a user in this portion # of the script affects the progress step1response = 'My favorite form of spam is an overabundance of test cases ;-)' incomingmessage = self.fakeIncoming(step1response) response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') # we should move the status of step 1 to complete, and there should # be one response in the ScriptSession progress = self.assertProgress(connection, 1, 'C', 1, 1) # test that the response was processed correctly self.assertEquals(Response.objects.all()[0].pk, ScriptSession.objects.all()[0].responses.all()[0].response.pk) self.assertEquals(Response.objects.all()[0].eav.poll_text_value, step1response) # check that this call to check_progress sends out the # next question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, step2.poll.question) # check that the step is now step 2, with status 'P' # there should still be a scriptsession, but only one # and there still should be one response progress = self.assertProgress(connection, 2, 'P', 1, 1) # no movement until we get a response this time res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'P', 1, 1) step2errorResponse = 'I like cheese' incomingmessage = self.fakeIncoming(step2errorResponse) response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, step2.poll.categories.get(name='unknown').response) # we should be in the same step, with one additional response progress = self.assertProgress(connection, 2, 'P', 1, 2) res_count = Message.objects.filter(direction='O', connection=connection).count() # no movement until we get a response this time check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'P', 1, 2) step2yesResponse = 'YES I like cheese' incomingmessage = self.fakeIncoming(step2yesResponse) response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, step2.poll.categories.get(name='yes').response) # we should be in the same step, with one additional response and 'C'omplete status progress = self.assertProgress(connection, 2, 'C', 1, 3) # no movement until for a full hour res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'C', 1, 3) # incoming messages shouldn't do anything here # (in fact, the shouldn't be added even as responses to the poll, since # the status of this step is complete) incomingmessage = self.fakeIncoming('still just waiting around for another message') response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') progress = self.assertProgress(connection, 2, 'C', 1, 3) # wait an hour self.elapseTime(progress, 3601) step3 = script.steps.get(order=3) res_count = Message.objects.filter(direction='O', connection=connection).count() # this should complete the script check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, step3.message) progress = self.assertProgress(connection, 3, 'P', 1, 3) # incoming messages shouldn't do anything here # (in fact, the shouldn't be added even as responses to the poll, since # the status of this step is complete) incomingmessage = self.fakeIncoming('im done with the script, just sending random stuff') response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') progress = self.assertProgress(connection, 3, 'P', 1, 3) # wait a few more seconds, then check that the script is closed out self.elapseTime(progress, 10) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) self.assertEquals(ScriptProgress.objects.count(), 0) self.assertEquals(ScriptSession.objects.all()[0].responses.count(), 3) self.failIf(ScriptSession.objects.all()[0].end_time is None)
def testFullScriptFlow(self): script = Script.objects.get(slug="test_autoreg") connection = Connection.objects.all()[0] progress = ScriptProgress.objects.create(connection=connection, script=script) # test that an incoming message from a user freshly added to the script # (i.e., no call to check_progress yet) doesn't fail incomingmessage = self.fakeIncoming( 'Im in the script, but nothings happened yet. What next?') response_message = incoming_progress(incomingmessage) # no response message self.assertEquals(response_message, None) # refresh progress, no updates to progress should be made # no ScriptSession should be created, that's up to check_progress progress = self.assertProgress(connection, None, '', 0, 0) # modify step 1, check_progress should wait a full minute before sending out # the first message step0 = script.steps.get(order=0) step0.start_offset = 60 step0.save() res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # we're still waiting to send the first message, for a full minute self.assertEquals(response, None) self.elapseTime(progress, 60) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # we're ready for the first message to go out self.assertEquals(response, step0.message) # refresh progress # we should now be advanced to step 0, in 'P'ending status # because it's a WAIT_MOVEON step, so we have to wait for one # hour before advancing to the next step # there should be a scriptsession at this point # but there shouldn't be any responses progress = self.assertProgress(connection, 0, 'P', 1, 0) # test that an incoming message from a user in this portion # of the script doesn't affect the progress incomingmessage = self.fakeIncoming( 'Im in the script, but Im waiting to be asked a question. Why do I have to wait for an hour?' ) response_message = incoming_progress(incomingmessage) # no response message self.assertEquals(response_message, None) # refresh progress # no updates to progress # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 0, 'P', 1, 0) # now let's wait a full hour self.elapseTime(progress, 3600) step1 = script.steps.get(order=1) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, step1.poll.question) # refresh progress # check that the step is now step 1, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 1, 'P', 1, 0) # check that an additional call to check_progress doesn't re-send the # question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, None) # check that the step is still step 1, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 1, 'P', 1, 0) # test the moveon scenario, wait a full day with no response self.elapseTime(progress, 86400) # make sure that incoming_progress respects the giveup time of # the previous step and drops any messages (otherwise it's a # potential race contidion incomingmessage = self.fakeIncoming( 'I like spam, Im just a little late to mention anything about it') response_message = incoming_progress(incomingmessage) self.assertEquals(response, None) progress = self.assertProgress(connection, 1, 'P', 1, 0) # check that this call to check_progress sends out the # next question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None step2 = script.steps.get(order=2) # the first poll question should go out now self.assertEquals(response, step2.poll.question) # check that the step is now step 2, with status 'P' # there should still be a scriptsession, but only one # and there still shouldn't be any responses progress = self.assertProgress(connection, 2, 'P', 1, 0) # test the scenario where a response is received progress.step = step1 progress.status = 'P' progress.save() session = ScriptSession.objects.all()[0] session.start_time = datetime.datetime.now() session.end_time = None for r in session.responses.all(): r.delete() for r in Response.objects.all(): r.delete() session.save() # test that an incoming message from a user in this portion # of the script affects the progress step1response = 'My favorite form of spam is an overabundance of test cases ;-)' incomingmessage = self.fakeIncoming(step1response) response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') # we should move the status of step 1 to complete, and there should # be one response in the ScriptSession progress = self.assertProgress(connection, 1, 'C', 1, 1) # test that the response was processed correctly self.assertEquals( Response.objects.all()[0].pk, ScriptSession.objects.all()[0].responses.all()[0].response.pk) self.assertEquals(Response.objects.all()[0].eav.poll_text_value, step1response) # check that this call to check_progress sends out the # next question res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None # the first poll question should go out now self.assertEquals(response, step2.poll.question) # check that the step is now step 2, with status 'P' # there should still be a scriptsession, but only one # and there still should be one response progress = self.assertProgress(connection, 2, 'P', 1, 1) # no movement until we get a response this time res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'P', 1, 1) step2errorResponse = 'I like cheese' incomingmessage = self.fakeIncoming(step2errorResponse) response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, step2.poll.categories.get(name='unknown').response) # we should be in the same step, with one additional response progress = self.assertProgress(connection, 2, 'P', 1, 2) res_count = Message.objects.filter(direction='O', connection=connection).count() # no movement until we get a response this time check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'P', 1, 2) step2yesResponse = 'YES I like cheese' incomingmessage = self.fakeIncoming(step2yesResponse) response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, step2.poll.categories.get(name='yes').response) # we should be in the same step, with one additional response and 'C'omplete status progress = self.assertProgress(connection, 2, 'C', 1, 3) # no movement until for a full hour res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) progress = self.assertProgress(connection, 2, 'C', 1, 3) # incoming messages shouldn't do anything here # (in fact, the shouldn't be added even as responses to the poll, since # the status of this step is complete) incomingmessage = self.fakeIncoming( 'still just waiting around for another message') response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') progress = self.assertProgress(connection, 2, 'C', 1, 3) # wait an hour self.elapseTime(progress, 3601) step3 = script.steps.get(order=3) res_count = Message.objects.filter(direction='O', connection=connection).count() # this should complete the script check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, step3.message) progress = self.assertProgress(connection, 3, 'P', 1, 3) # incoming messages shouldn't do anything here # (in fact, the shouldn't be added even as responses to the poll, since # the status of this step is complete) incomingmessage = self.fakeIncoming( 'im done with the script, just sending random stuff') response_message = incoming_progress(incomingmessage) self.failUnless(response_message == None or response_message == '') progress = self.assertProgress(connection, 3, 'P', 1, 3) # wait a few more seconds, then check that the script is closed out self.elapseTime(progress, 10) res_count = Message.objects.filter(direction='O', connection=connection).count() check_progress(self.script) response = Message.objects.filter(direction='O', connection=connection) if response.exists() and not response.count() == res_count: response = response.latest('date').text else: response = None self.assertEquals(response, None) self.assertEquals(ScriptProgress.objects.count(), 0) self.assertEquals(ScriptSession.objects.all()[0].responses.count(), 3) self.failIf(ScriptSession.objects.all()[0].end_time is None)
def testIncomingProgress(self): connection = Connection.objects.all()[0] script = Script.objects.get(slug="test_autoreg") step = ScriptStep.objects.get(script__slug='test_autoreg', order=1) prog = ScriptProgress.objects.create(connection=connection, script=script, step=step, status='P') # create a dummy session session = ScriptSession.objects.create(connection=connection, script=script) incomingmessage = self.fakeIncoming( 'I like all forms of spam, but typically Nigerian email spam is the best.' ) incoming_progress(incomingmessage) self.assertEquals(Response.objects.count(), 1) self.assertEquals(ScriptSession.objects.count(), 1) self.assertEquals(ScriptSession.objects.all()[0].responses.count(), 1) # refresh progress prog = ScriptProgress.objects.get(connection=connection) self.assertEquals(prog.step.order, 1) self.assertEquals(prog.status, 'C') # manually move to next step, check_progress would do this prog.step = ScriptStep.objects.get(script__slug='test_autoreg', order=2) prog.status = 'P' prog.save() incomingmessage = self.fakeIncoming( 'Jack cheese is a cheese that I like') response_message = incoming_progress(incomingmessage) self.assertEquals( response_message, "We didn't understand your response and it's very important to know about your cheese desires. Please resend." ) self.assertEquals(Response.objects.count(), 2) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this erroneous poll response didn't update the progress r = Response.objects.order_by('-date')[0] self.failUnless(r.has_errors) self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'P') incomingmessage = self.fakeIncoming( 'YES I like jack cheese you silly poll!!!eleventyone') response_message = incoming_progress(incomingmessage) self.assertEquals(response_message, "It's very good to know that you like cheese!") r = Response.objects.order_by('-date')[0] self.failIf(r.has_errors) self.assertEquals(Response.objects.count(), 3) # refresh progress prog = ScriptProgress.objects.get(connection=connection) # check that this correct poll response updated the progress self.assertEquals(prog.step.order, 2) self.assertEquals(prog.status, 'C')