def test_updating_profile_with_photo_file(self):
        attr = self.mobile_user_to_post.copy()
        attr['email'] = '*****@*****.**'
        attr['phone'] = '+256775019511'
        attr['user'] = User(username='******', password='******').save()
        profile = UserProfile(**attr)
        user_photo = open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg',
                          'rb')
        profile.photo.put(user_photo, content_type='image/content_type')
        profile.save()

        with open(settings.PROJECT_ROOT + '/../dms/tests/test2.jpg',
                  'rb') as test_image:
            attr['file'] = test_image
            response = self.client.post(
                self.API_ENDPOINT + str(profile.id) + '/', attr)
            self.assertEqual(200, response.status_code)

        retrieved_user = User.objects(username='******').first()
        reloaded_profile = UserProfile.objects(user=retrieved_user).first()
        self.assertEqual(
            reloaded_profile.photo.read(),
            open(settings.PROJECT_ROOT + '/../dms/tests/test2.jpg',
                 'rb').read())
        self.assertEqual(reloaded_profile.photo.content_type, 'image/jpeg')
        self.assertEqual(reloaded_profile.photo_uri(),
                         '/api/v1/photo/' + str(reloaded_profile.id))
示例#2
0
 def test_should_save_photo_of_user(self):
     user_profile_attr = dict(name='timothy', phone='+256775019449', location=self.district, email=None)
     profile = UserProfile(**user_profile_attr)
     user_photo = open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb')
     profile.photo.put(user_photo, content_type='image/content_type')
     profile.save()
     reloaded_profile = UserProfile.objects(id=profile.id).first()
     self.assertEqual(reloaded_profile.photo.read(),
                      open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb').read())
     self.assertEqual(reloaded_profile.photo.content_type, 'image/content_type')
     self.assertEqual(reloaded_profile.photo_uri(), '/api/v1/photo/' + str(reloaded_profile.id))
    def test_allow_user_to_see_their_own(self):
        self.client.logout()
        attr = self.user_profile_attr.copy()
        attr['phone'] = '+2555837295789'
        user = User(username='******', email='*****@*****.**')
        user.group = None
        user.set_password('weak_password')
        attr['user'] = user
        profile = UserProfile(**attr)
        profile.photo.put(open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb'), content_type='image/content_type')
        profile.save()
        self.client.login(username='******', password='******')

        response = self.client.get(self.PROFILE_IMAGE_ENDPOINT + str(profile.id) + '/')
        self.assertEquals(response.status_code, 200)
    def test_handling_photo_update_exception(self):
        attr = self.mobile_user_to_post.copy()
        attr['email'] = '*****@*****.**'
        attr['phone'] = '+256775019511'
        attr['user'] = User(username='******', password='******').save()
        profile = UserProfile(**attr)
        user_photo = open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb')
        profile.photo.put(user_photo, content_type='image/content_type')
        profile.save()

        with open(settings.PROJECT_ROOT + '/../dms/tests/test2.jpg', 'rb') as test_image:
            attr['file'] = test_image
            response = self.client.post(self.API_ENDPOINT + str(profile.id) + '/', attr)
            self.assertEqual(200, response.status_code)

        retrieved_user = User.objects(username='******').first()
        reloaded_profile = UserProfile.objects(user=retrieved_user).first()
        self.assertEqual(reloaded_profile.photo.read(), None)
示例#5
0
 def test_should_save_photo_of_user(self):
     user_profile_attr = dict(name='timothy',
                              phone='+256775019449',
                              location=self.district,
                              email=None)
     profile = UserProfile(**user_profile_attr)
     user_photo = open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg',
                       'rb')
     profile.photo.put(user_photo, content_type='image/content_type')
     profile.save()
     reloaded_profile = UserProfile.objects(id=profile.id).first()
     self.assertEqual(
         reloaded_profile.photo.read(),
         open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg',
              'rb').read())
     self.assertEqual(reloaded_profile.photo.content_type,
                      'image/content_type')
     self.assertEqual(reloaded_profile.photo_uri(),
                      '/api/v1/photo/' + str(reloaded_profile.id))
class ProfileImageViewTest(MongoAPITestCase):

    PROFILE_IMAGE_ENDPOINT = '/api/v1/photo/'

    def setUp(self):
        self.district = Location(**dict(name='Kampala', type='district', parent=None))
        self.district.save()
        self.user_profile_attr = dict(name='timothy', phone='+256775019449', location=self.district, email=None)
        self.profile = UserProfile(**self.user_profile_attr)
        self.profile.photo.put(open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb'), content_type='image/content_type')
        self.profile.save()
        self.client = Client()
        self.login_user()

    def test_successfully_retrieve_profile_image(self):
        response = self.client.get(self.PROFILE_IMAGE_ENDPOINT + str(self.profile.id) + '/')
        self.assertEqual(200, response.status_code)
        self.assertEqual(open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb').read(), response.content)

    def test_not_permitted_to_view_profile(self):
        self.assert_permission_required_for_get(self.PROFILE_IMAGE_ENDPOINT + str(self.profile.id) + '/')

    def test_no_image_found(self):
        response = self.client.get(self.PROFILE_IMAGE_ENDPOINT + 'j34ks34344df234/')
        self.assertEqual(200, response.status_code)
        self.assertEqual(open(settings.PROJECT_ROOT + '/../dms/client/app/img/default_profile.jpg', 'rb').read(), response.content)

    def test_allow_user_to_see_their_own(self):
        self.client.logout()
        attr = self.user_profile_attr.copy()
        attr['phone'] = '+2555837295789'
        user = User(username='******', email='*****@*****.**')
        user.group = None
        user.set_password('weak_password')
        attr['user'] = user
        profile = UserProfile(**attr)
        profile.photo.put(open(settings.PROJECT_ROOT + '/../dms/tests/test.jpg', 'rb'), content_type='image/content_type')
        profile.save()
        self.client.login(username='******', password='******')

        response = self.client.get(self.PROFILE_IMAGE_ENDPOINT + str(profile.id) + '/')
        self.assertEquals(response.status_code, 200)
class RapidProEndPointTest(MongoAPITestCase):
    API_ENDPOINT = '/api/v1/rapid-pro/'
    CSV_ENDPOINT = '/api/v1/csv-messages/'

    def setUp(self):
        self.date_time = datetime.datetime(2014, 9, 17, 16, 0, 49, 807000)
        self.date_time = self.date_time.replace(tzinfo=pytz.utc)
        self.district = Location(**dict(name='Kampala', parent=None, type='district')).save()
        self.village = Location(**dict(name='Bukoto', parent=self.district, type='village')).save()
        self.mobile_user = UserProfile(**dict(name='timothy', phone="+256775019449",
                                             location=self.village, email=None)).save()

        self.fire_type = DisasterType(**dict(name="Fire", description="Fire")).save()
        disaster_attributes = dict(name=self.fire_type, locations=[self.district],
                                   description="Big Fire", date="2014-12-01 00:00:00", status="Assessment")
        self.disaster = Disaster(**disaster_attributes).save()

        self.text_format = "NECOC.%s. There is a fire"
        text = self.text_format % self.village.name
        self.expected_message = dict(phone="+256775019449", text=text, time=self.date_time, relayer=234,
                                     run=23243)
        self.message = dict(phone_no="+256775019449", text=text, received_at=self.date_time,
                            relayer_id=234, run_id=23243)

        self.api_user, created = User.objects.get_or_create(**dict(username='******'))
        self.auto_message_response = dict(phone_numbers=[u'+256775019449'], text=settings.AUTO_RESPONSE_MESSAGE)

        self.cao_group, created = Group.objects.get_or_create(name='CAO')
        self.cao_user = User.objects.create(username='******', group=self.cao_group, email='*****@*****.**')
        self.cao_user.set_password('password')
        self.login_url = '/login/'
        self.login_data = {
            'username': '******',
            'password': '******'
        }

        AdminSetting(**dict(name='enable_automatic_response')).save()
        AdminSetting(**dict(name='enable_volunteer_profiles')).save()

    def _api_url(self, id):
        return "%s%s/" % (self.API_ENDPOINT, str(id))

    def test_should_create_rapid_pro_message(self):
        self.expected_message['time'] = self.date_time.strftime(RAPID_PRO_TIME_FORMAT)
        response = self.client.post(self.API_ENDPOINT, data=self.expected_message)
        self.assertEqual(201, response.status_code)

        del self.message['received_at']
        retrieved_message = RapidProMessage.objects(**self.message)
        self.assertEqual(1, retrieved_message.count())

    def test_should_create_rapid_pro_message_from_wacky_format(self):
        normal_time = self.date_time.strftime(RAPID_PRO_TIME_FORMAT)
        rapid_pro_time = normal_time + ".234567Z"
        self.expected_message['time'] = rapid_pro_time
        response = self.client.post(self.API_ENDPOINT, data=self.expected_message)
        self.assertEqual(201, response.status_code)

        del self.message['received_at']
        retrieved_message = RapidProMessage.objects(**self.message)
        self.assertEqual(1, retrieved_message.count())

    def test_should_get_rapid_pro_message(self):
        RapidProMessage(**self.message).save()
        response = self.client.get(self.API_ENDPOINT, format='json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertDictContainsSubset(self.expected_message, response.data[0])
        self.assertEqual(self.mobile_user.name, response.data[0]['source'])
        self.assertEqual('Kampala >> Bukoto', response.data[0]['location'])
        self.assertIsNotNone(response.data[0]['id'])

    def test_should_filter_messages_by_location(self):
        RapidProMessage(**self.message).save()
        wakiso = Location(**(dict(name='Wakiso', type='village'))).save()

        response = self.client.get(self.API_ENDPOINT, {"location": wakiso.id, "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(0, len(response.data))

        other_phone_number = '1234'
        other_message_options = dict(phone_no=other_phone_number, text=self.text_format % wakiso.name, received_at=self.date_time,
                                     relayer_id=234, run_id=23243)
        RapidProMessage(**other_message_options).save()

        response = self.client.get(self.API_ENDPOINT, {"location": wakiso.id, "format": "json"})

        expected_message = {'phone': other_phone_number, 'time': self.date_time, 'relayer': 234, 'run': 23243,
                            'text': self.text_format % wakiso.name}

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertDictContainsSubset(expected_message, response.data[0])
        self.assertEqual('NECOC Volunteer', response.data[0]['source'])
        self.assertEqual(wakiso.name, response.data[0]['location'])

    def test_location_filter_should_return_messages_in_all_children_location_and_in_order(self):
        Disaster.objects.delete() #Remove all disasters to avoid interference with this test
        bukoto_message = RapidProMessage(**self.message).save()
        wakiso = Location(**(dict(name='Wakiso', type='village', parent=self.district))).save()
        other_phone_number = '1234'
        one_hour_later_date = self.date_time + datetime.timedelta(hours=1)
        one_hour_later_date = one_hour_later_date.replace(tzinfo=pytz.utc)
        other_message_options = dict(phone_no=other_phone_number, text=self.text_format % wakiso.name, received_at=one_hour_later_date,
                                     relayer_id=234, run_id=23243)
        user_profile = UserProfile(**dict(name='timothy', phone=other_phone_number, location=wakiso)).save()
        wakiso_message = RapidProMessage(**other_message_options).save()

        response = self.client.get(self.API_ENDPOINT, {"location": self.district.id, "format": "json"})

        wakiso_expected_message = {'phone': other_phone_number, 'time': one_hour_later_date, 'relayer': 234, 'run': 23243,
                                   'text': self.text_format % wakiso.name, 'disaster': None}
        wakiso_expected_message = dict(wakiso_expected_message.items() + {
            'source': user_profile.name,
            'id': str(wakiso_message.id),
            'location': str(wakiso),
            'profile_id': str(user_profile.id),
            'auto_associated': False}.items())

        bukoto_expected_message = dict(self.expected_message.items() + {
            'source': self.mobile_user.name,
            'id': str(bukoto_message.id),
            'disaster': None,
            'location': str(self.village),
            'profile_id': str(self.mobile_user.id),
            'auto_associated': False}.items())

        self.assertEqual(200, response.status_code)
        self.assertEqual(2, len(response.data))
        self.assertEqual(wakiso_expected_message, response.data[0])
        self.assertEqual(bukoto_expected_message, response.data[1])

    @override_settings(REST_FRAMEWORK={})
    def test_should_update_disaster_field_with_put(self):
        message = RapidProMessage(**self.message).save()

        self.expected_message['time'] = self.date_time.replace(tzinfo=None)
        data = self.expected_message.copy()
        data['disaster'] = self.disaster.id

        response = self.client.put(self._api_url(message.id), data=data)
        self.assertEqual(200, response.status_code)

        retrieved_message = RapidProMessage.objects(**self.message)
        self.assertEqual(1, retrieved_message.count())
        self.assertEqual(self.disaster, retrieved_message[0].disaster)

    @override_settings(REST_FRAMEWORK={})
    def test_should_update_disaster_field_using_a_patch(self):
        message = RapidProMessage(**self.message).save()

        response = self.client.patch(self._api_url(message.id), data=dict(disaster=self.disaster.id))
        self.assertEqual(200, response.status_code)

        retrieved_message = RapidProMessage.objects(**self.message)
        self.assertEqual(1, retrieved_message.count())
        self.assertEqual(self.disaster, retrieved_message[0].disaster)

    @override_settings(REST_FRAMEWORK={})
    def test_should_update_disaster_field_with_post_is_also_supported_for_phantomjs_sake(self):
        message = RapidProMessage(**self.message).save()

        response = self.client.post(self._api_url(message.id), data=dict(disaster=self.disaster.id))
        self.assertEqual(200, response.status_code)

        retrieved_message = RapidProMessage.objects(**self.message)
        self.assertEqual(1, retrieved_message.count())
        self.assertEqual(self.disaster, retrieved_message[0].disaster)

    def test_should_filter_messages_by_disaster_association(self):
        self.message['text'] = 'unassociate-able disaster text text' #short circuit auto disaster association
        self.expected_message['text'] = 'unassociate-able disaster text text'
        uncategorized_message = RapidProMessage(**self.message).save()
        message_2 = self.message.copy()
        message_2['text'] = 'some other text'
        message_2['disaster'] = self.disaster

        categorized_message = RapidProMessage(**message_2).save()

        response = self.client.get(self.API_ENDPOINT, {"disaster": "", "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(str(uncategorized_message.id), response.data[0]['id'])
        self.assertDictContainsSubset(self.expected_message, response.data[0])

        response = self.client.get(self.API_ENDPOINT, {"disaster": str(self.disaster.id), "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(str(categorized_message.id), response.data[0]['id'])
        expected_message2= self.expected_message.copy()
        expected_message2['text'] = message_2['text']
        self.assertDictContainsSubset(expected_message2, response.data[0])

    def test_should_filter_messages_by_disaster_type(self):
        message_attr = self.message.copy()
        message_attr['disaster'] = self.disaster
        fire_message = RapidProMessage(**message_attr).save()
        flood_type = DisasterType(**dict(name="Flood", description="Flood")).save()

        response = self.client.get(self.API_ENDPOINT, {"disaster_type": str(self.fire_type.id), "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(str(fire_message.id), response.data[0]['id'])
        self.assertDictContainsSubset(self.expected_message, response.data[0])

        response = self.client.get(self.API_ENDPOINT, {"disaster_type": str(flood_type.id), "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(0, len(response.data))

    def test_should_filter_messages_by_date_range(self):
        message_attr = self.message.copy()
        date_1_jan = datetime.datetime(2014, 01, 01)
        message_attr['received_at'] = date_1_jan
        message_now = RapidProMessage(**message_attr).save()

        message_attr2 = self.message.copy()
        date_3_jan = datetime.datetime(2014, 01, 03)
        message_attr2['received_at'] = date_3_jan
        message_2days_later = RapidProMessage(**message_attr2).save()

        response = self.client.get(self.API_ENDPOINT, {"to": "2014-01-02", "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(str(message_now.id), response.data[0]['id'])
        expected_message = self.expected_message.copy()
        expected_message['time'] = date_1_jan.replace(tzinfo=pytz.utc)
        self.assertDictContainsSubset(expected_message, response.data[0])

        response = self.client.get(self.API_ENDPOINT, {"from": "2014-01-02", "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(str(message_2days_later.id), response.data[0]['id'])
        expected_message2 = self.expected_message.copy()
        expected_message2['time'] = date_3_jan.replace(tzinfo=pytz.utc)
        self.assertDictContainsSubset(expected_message2, response.data[0])

        response = self.client.get(self.API_ENDPOINT, {"from": "2014-01-02", "to": "2014-01-02",  "format": "json"})

        self.assertEqual(200, response.status_code)
        self.assertEqual(0, len(response.data))

    def test_should_auto_associate_message_to_disaster(self):
        disaster_type = DisasterType(**dict(name='Flood', description="Some flood")).save()
        disaster_attr = dict(name=disaster_type, locations=[self.district], description="Big Flood",
                                  date=self.date_time,
                                  status="Assessment")
        kampala_disaster = Disaster(**disaster_attr).save()
        text = "NECOC.%s. flood here and allover the place!" % self.district.name
        self.message['text'] = text
        saved_message = RapidProMessage(**self.message).save()
        self.assertEqual(saved_message.disaster, kampala_disaster)

    def test_should_auto_associate_message_to_disaster_when_posted_from_subcounty(self):
        disaster_type = DisasterType(**dict(name='Flood', description="Some flood")).save()
        disaster_attr = dict(name=disaster_type, locations=[self.district], description="Big Flood",
                                  date=self.date_time,
                                  status="Assessment")
        kampala_disaster = Disaster(**disaster_attr).save()
        text = "NECOC.%s. flood here and allover the place!" % self.village.name
        self.message['text'] = text
        saved_message = RapidProMessage(**self.message).save()
        self.assertEqual(saved_message.disaster, kampala_disaster)

    def test_should_save_post_message_and_associate_to_disaster(self):
        disaster_type = DisasterType(**dict(name='Flood', description="Some flood")).save()
        disaster_attr = dict(name=disaster_type, locations=[self.district], description="Big Flood",
                                  date=self.date_time,
                                  status="Assessment")
        kampala_disaster = Disaster(**disaster_attr).save()
        text = "NECOC.%s. flood here and allover the place!" % self.district.name
        self.expected_message['text'] = text
        self.expected_message['time'] = self.date_time.strftime(RAPID_PRO_TIME_FORMAT)

        response = self.client.post(self.API_ENDPOINT, data=self.expected_message)
        self.assertEqual(201, response.status_code)
        self.assertEqual(response.data['disaster']['id'], str(kampala_disaster.id))

    @override_settings(REST_FRAMEWORK={
        'DEFAULT_RENDERER_CLASSES': (
            'rest_framework_csv.renderers.CSVRenderer'
        ),
        "TEST_REQUEST_RENDERER_CLASSES": (
            'rest_framework_csv.renderers.CSVRenderer'
        )
    })
    def test_should_return_csv_when_csv_endpoint_is_called(self):
        disaster_type = DisasterType(**dict(name='Fire', description="Some fire")).save()
        disaster_attr = dict(name=disaster_type, locations=[self.district], description="Big Fire",
                                  date=self.date_time,
                                  status="Assessment")
        kampala_disaster = Disaster(**disaster_attr).save()

        msg = RapidProMessage(**self.message).save()
        expected_response = "phone,text,source,location,time,disaster\n" \
                            "+256775019449,NECOC.Bukoto. There is a fire,timothy,Kampala >> Bukoto,%s,Fire" % msg.received_at
        response = self.client.get(self.CSV_ENDPOINT, {'format': 'csv'})
        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        # self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

    def test_should_filter_csv_when_date_range_is_specified(self):
        new_date_time = datetime.datetime(2015, 9, 17, 16, 0, 49, 807000)
        new_date_time = new_date_time.replace(tzinfo=pytz.utc)
        disaster_type = DisasterType(**dict(name='Fire', description="Some fire")).save()
        disaster_attr = dict(name=disaster_type, locations=[self.district], description="Big Fire",
                                  date=self.date_time,
                                  status="Assessment")
        kampala_disaster = Disaster(**disaster_attr).save()

        RapidProMessage(**self.message).save()
        self.message['received_at'] = new_date_time
        RapidProMessage(**self.message).save()
        expected_response = "phone,text,source,location,time\n" \
                            "+256775019449,NECOC.Bukoto. There is a fire,timothy,Kampala >> Bukoto,%s,Fire" % self.date_time

        response = self.client.get(self.CSV_ENDPOINT, {'dfrom' : 'undefined', 'dto': '2014-11-26', 'format': 'csv'})
        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))

        response = self.client.get(self.CSV_ENDPOINT, {'dfrom' : '2015-01-01', 'dto': 'undefined', 'format': 'csv'})
        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))

        response = self.client.get(self.CSV_ENDPOINT, {'dfrom' : '2014-01-01', 'dto': '2014-11-26', 'format': 'csv'})
        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))

        response = self.client.get(self.CSV_ENDPOINT, {'dfrom' : '2014-01-01', 'dto': '2015-11-26', 'format': 'csv'})
        self.assertEqual(200, response.status_code)
        self.assertEqual(2, len(response.data))

        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        # self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

    def test_should_return_only_district_messages_for_CAO(self):
        self.mobile_user.user = self.cao_user
        self.mobile_user.save()

        masaka_district = Location(**dict(name='Masaka', parent=None, type='district')).save()
        masaka_village = Location(**dict(name='Bukasa', parent=masaka_district, type='village')).save()
        masaka_message = self.message.copy()
        masaka_message['location'] = masaka_village
        masaka_message['phone_no'] = "+256775019441"
        msk_msg = RapidProMessage(**masaka_message).save()
        kla_msg = RapidProMessage(**self.message).save()

        login_response = self.client.post(self.login_url, self.login_data)
        self.assertRedirects(login_response, '/')
        self.assertTrue('sessionid' in login_response.cookies)

        response = self.client.get(self.API_ENDPOINT, format='json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertDictContainsSubset(self.expected_message, response.data[0])
        self.assertEqual(self.mobile_user.name, response.data[0]['source'])
        self.assertEqual('Kampala >> Bukoto', response.data[0]['location'])
        self.assertIsNotNone(response.data[0]['id'])
class TestDisasterEndpoint(MongoAPITestCase):

    API_ENDPOINT = '/api/v1/disasters/'
    CSV_ENDPOINT = '/api/v1/csv-disasters/'

    def setUp(self):
        self.user = self.login_user()
        self.district = Location(**dict(name='Kampala', type='district', parent=None))
        self.district.save()
        self.disaster_type = DisasterType(**dict(name="Fire", description="Fire"))
        self.disaster_type.save()
        self.disaster_type2 = DisasterType(**dict(name="Flood", description="Flood"))
        self.disaster_type2.save()
        self.disaster_to_post = dict(name=str(self.disaster_type.id), locations=[str(self.district.id)],
                                     description="Big Flood", date="2014-12-01 00:00:00", status="Assessment")
        self.disaster = dict(name=self.disaster_type, locations=[self.district],
                             description="Big Flood", date="2014-12-01 00:00:00", status="Assessment")

        self.mobile_user = UserProfile(**dict(name='timothy', phone="+256775019449",
                                             location=self.district, email=None)).save()
        self.cao_group, created = Group.objects.get_or_create(name='CAO')

    def test_should_post_a_disaster(self):
        response = self.client.post(self.API_ENDPOINT, data=json.dumps(self.disaster_to_post), content_type="application/json")
        self.assertEqual(201, response.status_code)

        retrieved_disaster = Disaster.objects(description="Big Flood")
        self.assertEqual(1, retrieved_disaster.count())

    def test_should_get_a_list_of_disasters(self):
        Disaster(**self.disaster).save()
        response = self.client.get(self.API_ENDPOINT, format='json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(self.disaster_to_post['status'], response.data[0]['status'])
        self.assertEqual(self.disaster_to_post['date'], str(response.data[0]['date']))
        self.assertEqual(self.disaster_to_post['description'], response.data[0]['description'])

    def test_can_get_a_list_of_disasters_with_no_permissions(self):
        self.login_without_permissions()
        response = self.client.get(self.API_ENDPOINT)
        self.assertEquals(response.status_code, 200)

    def test_cant_post_to_disasters_without_permission(self):
        self.assert_permission_required_for_post(self.API_ENDPOINT)

    def test_can_post_to_disasters_with_permission(self):
        self.login_with_permission('can_manage_disasters')
        response = self.client.get(self.API_ENDPOINT)
        self.assertEquals(response.status_code, 200)
        response = self.client.post(self.API_ENDPOINT, data=json.dumps(self.disaster_to_post), content_type="application/json")
        self.assertEqual(201, response.status_code)

    def test_should_get_a_single_disaster(self):
        disaster = Disaster(**self.disaster).save()
        response = self.client.get(self.API_ENDPOINT + str(disaster.id) + '/', format='json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(self.disaster_to_post['status'], response.data['status'])
        self.assertEqual(self.disaster_to_post['date'], str(response.data['date']))
        self.assertEqual(self.disaster_to_post['description'], response.data['description'])

    def test_cant_get_or_post_single_disaster_without_permission(self):
        disaster = Disaster(**self.disaster).save()
        self.assert_permission_required_for_get(self.API_ENDPOINT + str(disaster.id) + '/')
        self.assert_permission_required_for_post(self.API_ENDPOINT + str(disaster.id) + '/')

    def test_should_post_a_single_disaster(self):
        disaster = Disaster(**self.disaster_to_post).save()
        self.disaster_to_post['description'] = "Giant Flood"
        response = self.client.post(self.API_ENDPOINT + str(disaster.id) + '/',
                                    data=json.dumps(self.disaster_to_post),
                                    content_type="application/json")
        self.assertEqual(200, response.status_code)

        retrieved_disaster = Disaster.objects(description="Giant Flood")
        self.assertEqual(1, retrieved_disaster.count())

    def test_filter_disaster_by_status(self):
        Disaster(**self.disaster).save()
        disaster_attr2 = self.disaster.copy()
        disaster_attr2['status'] = "Closed"
        Disaster(**disaster_attr2).save()

        response = self.client.get(self.API_ENDPOINT+'?status=Closed&format=json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual('Closed', response.data[0]['status'])
        self.assertEqual(self.disaster_to_post['date'], str(response.data[0]['date']))
        self.assertEqual(self.disaster_to_post['description'], response.data[0]['description'])

    def test_filter_disaster_by_date(self):
        disaster_attr = self.disaster.copy()
        date_1_jan = "2014-01-01"
        disaster_attr['date'] = date_1_jan

        disaster_attr2 = self.disaster.copy()
        date_3_jan = "2014-01-03"
        disaster_attr2['date'] = date_3_jan

        Disaster(**disaster_attr).save()
        Disaster(**disaster_attr2).save()

        response = self.client.get(self.API_ENDPOINT+'?from=%s&to=%s&format=json' % (date_1_jan, date_3_jan))

        self.assertEqual(200, response.status_code)
        self.assertEqual(2, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_1_jan, "%Y-%m-%d"), response.data[0]['date'])
        self.assertEqual(datetime.datetime.strptime(date_3_jan, "%Y-%m-%d"), response.data[1]['date'])

        response = self.client.get(self.API_ENDPOINT+'?from=%s&format=json' % date_3_jan)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_3_jan, "%Y-%m-%d"), response.data[0]['date'])

        response = self.client.get(self.API_ENDPOINT+'?to=%s&format=json' % date_1_jan)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_1_jan, "%Y-%m-%d"), response.data[0]['date'])

    def test_filter_disaster_by_date_and_date(self):
        disaster_attr = self.disaster.copy()
        date_1_jan = "2014-01-01"
        disaster_attr['date'] = date_1_jan

        disaster_attr2 = self.disaster.copy()
        date_3_jan = "2014-01-03"
        disaster_attr2['status'] = "Closed"
        disaster_attr2['date'] = date_3_jan

        Disaster(**disaster_attr).save()
        Disaster(**disaster_attr2).save()

        response = self.client.get(self.API_ENDPOINT+'?from=%s&to=%s&status=Closed&format=json' % (date_1_jan, date_3_jan))

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_3_jan, "%Y-%m-%d"), response.data[0]['date'])

        response = self.client.get(self.API_ENDPOINT+'?from=%s&status=closed&format=json' % date_3_jan)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_3_jan, "%Y-%m-%d"), response.data[0]['date'])

        response = self.client.get(self.API_ENDPOINT+'?to=%s&status=assessment&format=json' % date_1_jan)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(datetime.datetime.strptime(date_1_jan, "%Y-%m-%d"), response.data[0]['date'])

    def test_should_return_only_district_disasters_for_CAO(self):
        self.user.group = self.cao_group
        self.user.save()
        self.mobile_user.user = self.user
        self.mobile_user.save()

        masaka_district = Location(**dict(name='Masaka', parent=None, type='district')).save()

        masaka_disaster = dict(name=self.disaster_type, locations=[masaka_district],
                             description="Big Flood", date="2014-12-01 00:00:00", status="Assessment")

        Disaster(**self.disaster).save()
        Disaster(**masaka_disaster).save()
        response = self.client.get(self.API_ENDPOINT, format='json')

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertEqual(self.disaster_to_post['status'], response.data[0]['status'])
        self.assertEqual(self.disaster_to_post['date'], str(response.data[0]['date']))
        self.assertEqual(self.disaster_to_post['description'], response.data[0]['description'])
        self.assertEqual('Kampala', response.data[0]['locations'][0]['name'])

    def test_should_return_csv_when_csv_endpoint_is_called(self):
        Disaster(**self.disaster).save()
        disaster_attr2 = self.disaster.copy()
        disaster_attr2['status'] = "Closed"
        Disaster(**disaster_attr2).save()
        disaster2 = self.disaster.copy()
        disaster2['name'] = self.disaster_type2
        Disaster(**disaster2).save()

        response = self.client.get(self.CSV_ENDPOINT, format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Fire,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name,)
        expected_response = expected_response + "\r\nFire,Big Flood,%s,Closed,2014-12-01 00:00:00" % (self.district.name)
        expected_response = expected_response + "\r\nFlood,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(3, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

    def test_should_return_filtered_csv_when_csv_endpoint_is_called(self):
        Disaster(**self.disaster).save()
        disaster_attr2 = self.disaster.copy()
        disaster_attr2['status'] = "Closed"
        Disaster(**disaster_attr2).save()
        disaster2 = self.disaster.copy()
        disaster2['name'] = self.disaster_type2
        sdisaster = Disaster(**disaster2).save()

        response = self.client.get(self.CSV_ENDPOINT, format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Fire,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name,)
        expected_response = expected_response + "\r\nFire,Big Flood,%s,Closed,2014-12-01 00:00:00" % (self.district.name)
        expected_response = expected_response + "\r\nFlood,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(3, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

        response = self.client.get(self.CSV_ENDPOINT + '?status=Assessment&from=undefined', format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Fire,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name,)
        expected_response = expected_response + "\r\nFlood,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(2, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

        sdisaster.date = "2014-12-02 00:00:00"
        sdisaster.save()

        response = self.client.get(self.CSV_ENDPOINT + '?status=Assessment&from=2014-12-02 00:00:00', format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Flood,Big Flood,%s,Assessment,2014-12-02 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(1, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

        response = self.client.get(self.CSV_ENDPOINT + '?to=2014-12-01 00:00:00', format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Fire,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name,)
        expected_response = expected_response + "\r\nFire,Big Flood,%s,Closed,2014-12-01 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(2, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

    def test_should_return_csv_with_all_records_when_empty_filters_are_used_on_csv_endpoint(self):
        Disaster(**self.disaster).save()
        disaster_attr2 = self.disaster.copy()
        disaster_attr2['status'] = "Closed"
        Disaster(**disaster_attr2).save()
        disaster2 = self.disaster.copy()
        disaster2['name'] = self.disaster_type2
        sdisaster = Disaster(**disaster2).save()

        response = self.client.get(self.CSV_ENDPOINT + '?status=undefined&from=undefined&to=undefined', format='csv')

        expected_response = "name,description,location,status,date\r\n" \
                            "Fire,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name,)
        expected_response = expected_response + "\r\nFire,Big Flood,%s,Closed,2014-12-01 00:00:00" % (self.district.name)
        expected_response = expected_response + "\r\nFlood,Big Flood,%s,Assessment,2014-12-01 00:00:00" % (self.district.name)

        self.assertEqual(200, response.status_code)
        self.assertEqual(3, len(response.data))
        self.assertTrue(isinstance(response.accepted_renderer, CSVRenderer))
        self.assertEqual(collections.Counter(split_text(expected_response)), collections.Counter(split_text(response.content)))

    @mock.patch('dms.tasks.send_email.delay')
    def test_changing_disaster_status_sends_email_to_stakeholders(self, mock_send_email):
        disaster = Disaster(**self.disaster).save()
        disaster.status = 'Closed'
        disaster.save()
        mock_send_email.assert_called_with('Status of Disaster Risk has changed',
                                           mock.ANY,
                                           settings.DEFAULT_FROM_EMAIL,
                                           settings.DISASTER_NOTIFY_STATUS)