Beispiel #1
0
class TestDownloads(MyReportsTestCase):
    """Tests the reports view."""
    def setUp(self):
        super(TestDownloads, self).setUp()
        self.client = TestClient(path=reverse('downloads'),
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_column_order(self):
        """Tests that column order is preserved"""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(path=reverse('reports',
                                                 kwargs={
                                                     'app': 'mypartners',
                                                     'model': 'contactrecord'
                                                 }))

        report_name = response.content
        report = Report.objects.get(name=report_name)
        report.values = json.dumps(['partner', 'contact name', 'contact_type'])
        report.save()

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context['columns'].items()[:3],
                         [('Partner', True), ('Contact Name', True),
                          ('Communication Type', True)])

    def test_blacklisted_columns(self):
        """Test that blacklisted columns aren't visible."""
        blacklist = ['pk', 'approval_status']
        response = self.client.post(
            path=reverse('reports',
                         kwargs={
                             'app': 'mypartners',
                             'model': 'contactrecord'
                         }),
            data={'values': ['partner', 'contact__name', 'contact_type']})

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.id})
        self.assertFalse(
            set(response.context['columns']).intersection(blacklist))
class MyJobsHelpersTests(MyJobsBase):
    def setUp(self):
        super(MyJobsHelpersTests, self).setUp()
        self.user = UserFactory()
        self.client = TestClient()

        self.login_params = {'username': '******',
                             'password': '******',
                             'action': 'login'}

    def test_login_dont_remember_me(self):
        self.assertEqual(Session.objects.count(), 0)
        response = self.client.post(reverse('home'),
                                    data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        # session.expire_date is tz aware; datetime.datetime.now is naive
        # It probably isn't worth it to bring in pytz just for tests
        now = datetime.datetime.now(session.expire_date.tzinfo)
        diff = session.expire_date - now

        # Due to the delay between the post at the top of this test
        # and reaching this line, this can't be an assertEquals;
        self.assertTrue(880 <= diff.total_seconds() <= 900)

    def test_login_remember_me(self):
        self.assertEqual(Session.objects.count(), 0)
        self.login_params['remember_me'] = True
        response = self.client.post(reverse('home'),
                                    data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        weeks = (datetime.datetime.now() + datetime.timedelta(days=14))
        # Session expiration should be two weeks from now - comparing number
        # of days should be good enough
        self.assertEqual(session.expire_date.toordinal(), weeks.toordinal())
Beispiel #3
0
class TestDownloads(MyReportsTestCase):
    """Tests the reports view."""

    def setUp(self):
        super(TestDownloads, self).setUp()
        self.client = TestClient(path=reverse('downloads'),
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_column_order(self):
        """Tests that column order is preserved"""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}),
            data={'values': ['partner', 'contact__name', 'contact_type']})

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context['columns'], {
            'Partner': True, 'Contact Name': True, 'Contact Type': True})
Beispiel #4
0
class TestDownloadReport(MyReportsTestCase):
    """Tests that reports can be downloaded."""

    def setUp(self):
        super(TestDownloadReport, self).setUp()
        self.client = TestClient(path=reverse("download_report"))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner__owner=self.company)
        ContactRecordFactory.create_batch(5, contact_type="job", job_applications=1, partner__owner=self.company)
        ContactRecordFactory.create_batch(5, contact_type="job", job_hires=1, partner__owner=self.company)

    def test_download_csv(self):
        """Test that a report can be downloaded in CSV format."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(path=reverse("reports", kwargs={"app": "mypartners", "model": "contactrecord"}))
        report_name = response.content
        report = Report.objects.get(name=report_name)
        python = report.python

        # download the report
        response = self.client.get(data={"id": report.pk, "values": ["contact", "contact_email", "contact_phone"]})

        self.assertEqual(response["Content-Type"], "text/csv")

        # specifying export values shouldn't modify the underlying report
        self.assertEqual(len(python[0].keys()), len(report.python[0].keys()))
Beispiel #5
0
class TestDownloadReport(MyReportsTestCase):
    """Tests that reports can be downloaded."""

    def setUp(self):
        super(TestDownloadReport, self).setUp()
        self.client = TestClient(path=reverse('download_report'))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner__owner=self.company)
        ContactRecordFactory.create_batch(
            5, contact_type='job', job_applications=1,
            partner__owner=self.company)
        ContactRecordFactory.create_batch(
            5, contact_type='job',
            job_hires=1, partner__owner=self.company)

    def test_download_csv(self):
        """Test that a report can be downloaded in CSV format."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(path=reverse('reports', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'}))
        report_name = response.content
        report = Report.objects.get(name=report_name)

        # download the report
        response = self.client.get(data={'id': report.pk})

        self.assertEqual(response['Content-Type'], 'text/csv')
Beispiel #6
0
class TestDownloads(MyReportsTestCase):
    """Tests the reports view."""

    def setUp(self):
        super(TestDownloads, self).setUp()
        self.client = TestClient(path=reverse('downloads'),
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_column_order(self):
        """Tests that column order is preserved"""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}))

        report_name = response.content
        report = Report.objects.get(name=report_name)
        report.values = json.dumps(['partner', 'contact name', 'contact_type'])
        report.save()

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context['columns'].items()[:3],
                         [('Partner', True), ('Contact Name', True),
                          ('Communication Type', True)])

    def test_blacklisted_columns(self):
        """Test that blacklisted columns aren't visible."""
        blacklist = ['pk', 'approval_status']
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}),
            data={'values': ['partner', 'contact__name', 'contact_type']})

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.id})
        self.assertFalse(
            set(response.context['columns']).intersection(blacklist))
Beispiel #7
0
class TestDownloads(MyReportsTestCase):
    """Tests the reports view."""

    def setUp(self):
        super(TestDownloads, self).setUp()
        self.client = TestClient(path=reverse("downloads"), HTTP_X_REQUESTED_WITH="XMLHttpRequest")
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_column_order(self):
        """Tests that column order is preserved"""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(path=reverse("reports", kwargs={"app": "mypartners", "model": "contactrecord"}))

        report_name = response.content
        report = Report.objects.get(name=report_name)
        report.values = json.dumps(["partner", "contact name", "contact_type"])
        report.save()

        response = self.client.get(data={"id": report.id})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.context["columns"].items()[:3],
            [("Partner", True), ("Contact Name", True), ("Communication Type", True)],
        )

    def test_blacklisted_columns(self):
        """Test that blacklisted columns aren't visible."""
        blacklist = ["pk", "approval_status"]
        response = self.client.post(
            path=reverse("reports", kwargs={"app": "mypartners", "model": "contactrecord"}),
            data={"values": ["partner", "contact__name", "contact_type"]},
        )

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={"id": report.id})
        self.assertFalse(set(response.context["columns"]).intersection(blacklist))
Beispiel #8
0
class TestReportView(MyReportsTestCase):
    """
    Tests the ReportView class, which is used to create and retrieve
    reports.
    """
    def setUp(self):
        super(TestReportView, self).setUp()
        self.client = TestClient(path=reverse('reports', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'}))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner__owner=self.company)
        ContactRecordFactory.create_batch(
            5, contact_type='job', job_applications=1,
            partner__owner=self.company)
        ContactRecordFactory.create_batch(
            5, contact_type='job',
            job_hires=1, partner__owner=self.company)

    def test_create_report(self):
        """Test that a report model instance is properly created."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post()
        report_name = response.content
        report = Report.objects.get(name=report_name)

        self.assertEqual(len(report.python), 15)

        # we use this in other tests

        return report_name

    def test_get_report(self):
        """Test that chart data is retreived from record results."""

        report_name = self.test_create_report()
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.pk})
        data = json.loads(response.content)

        # check contact record stats
        for key in ['applications', 'hires', 'communications', 'emails']:
            self.assertEqual(data[key], 5)

        # check contact stats
        self.assertEqual(data['contacts'][0]['records'], 1)
        self.assertEqual(data['contacts'][0]['referrals'], 10)
Beispiel #9
0
class TestDownloadReport(MyReportsTestCase):
    """Tests that reports can be downloaded."""
    def setUp(self):
        super(TestDownloadReport, self).setUp()
        self.client = TestClient(path=reverse('download_report'))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner__owner=self.company)
        ContactRecordFactory.create_batch(5,
                                          contact_type='job',
                                          job_applications=1,
                                          partner__owner=self.company)
        ContactRecordFactory.create_batch(5,
                                          contact_type='job',
                                          job_hires=1,
                                          partner__owner=self.company)

    def test_download_csv(self):
        """Test that a report can be downloaded in CSV format."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(path=reverse('reports',
                                                 kwargs={
                                                     'app': 'mypartners',
                                                     'model': 'contactrecord'
                                                 }))
        report_name = response.content
        report = Report.objects.get(name=report_name)
        python = report.python

        # download the report
        response = self.client.get(
            data={
                'id': report.pk,
                'values': ['contact', 'contact_email', 'contact_phone']
            })

        self.assertEqual(response['Content-Type'], 'text/csv')

        # specifying export values shouldn't modify the underlying report
        self.assertEqual(len(python[0].keys()), len(report.python[0].keys()))
Beispiel #10
0
class TestRegenerate(MyReportsTestCase):
    """Tests the reports can be regenerated."""

    def setUp(self):
        super(TestRegenerate, self).setUp()
        self.client = TestClient(path=reverse('reports', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'}))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_regenerate(self):
        # create a report whose results is for all contact records in the
        # company
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}),
            data={'values': ['partner', 'contact__name', 'contact_type']})

        report_name = response.content
        report = Report.objects.get(name=report_name)
        results = report.results

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # remove report results and ensure we can still get a resonable
        # response
        report.results.delete()
        report.save()
        self.assertFalse(report.results)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # regenerate results and ensure they are the same as the original
        response = self.client.get(path=reverse('regenerate'), data={
            'id': report.pk})
        report = Report.objects.get(name=report_name)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(report.results)
Beispiel #11
0
class MyProfileViewsTests(MyJobsBase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.client = TestClient()
        self.client.login_user(self.user)
        self.name = PrimaryNameFactory(user=self.user)

    def test_edit_profile(self):
        """
        Going to the edit_profile view generates a list of existing profile
        items in the main content section and a list of profile sections that
        don't have data filled out in the sidebar.
        """
        resp = self.client.get(reverse('view_profile'))

        soup = BeautifulSoup(resp.content)
        item = soup.find('div', id='profileTitleBar')

        # Page should have fake user's email as title
        self.assertIsNotNone(soup.find_all('h3', text="*****@*****.**"))

        # The only module that is complete at this point is 'Name'. So there
        # should only be one module displayed in the moduleColumn div
        self.assertEquals(1, len(soup.findAll("div",
                                              {"class": "card-wrapper"})))

        # The 'Add a New Section' section should have many items
        # Check for each one
        self.assertEquals(
            10, len(soup.findAll("tr", {"class": "profile-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Education-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Address-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Telephone-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a",
                                {"id": "Employment History-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Secondary Email-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Military Service-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Website-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "License-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Summary-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Volunteer History-new-section"})))
        self.assertEquals(
            1, len(soup.findAll("a", {"id": "Summary-new-section"})))

    def test_handle_form_post_new_valid(self):
        """
        Invoking the handle_form view as a POST request for a new item
        creates that object in the database and returns the item snippet
        to be rendered on the page.
        """

        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': 'new',
                                    'given_name': 'Susy',
                                    'family_name': 'Smith'
                                })
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(
            Name.objects.filter(given_name='Susy',
                                family_name='Smith').count(), 1)

    def test_delete_item(self):
        """
        Invoking the delete_item view deletes the item and returns
        the 'Deleted!' HttpResponse
        """

        resp = self.client.post(
            reverse('delete_item') + '?item=' + str(self.name.id))

        self.assertEqual(resp.content, '')
        self.assertEqual(Name.objects.filter(id=self.name.id).count(), 0)

    def test_edit_summary(self):
        """
        See test_edit_profile
        """
        summary = SummaryFactory(user=self.user)
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)

        item = soup.find('div', id='summary-' + str(summary.id) + '-item')
        self.assertIsNotNone(item)

        link = item.find('a').attrs['href']
        resp = self.client.get(link)
        self.assertEqual(resp.status_code, 200)

    def test_handle_form_post_invalid(self):
        """
        Invoking the handle_form view as a POST request with an invalid
        form returns the list of form errors.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': 'new',
                                    'given_name': 'Susy'
                                },
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'family_name': [u'This field is required.']})

        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': 'new',
                                    'family_name': 'Smithers'
                                },
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'given_name': [u'This field is required.']})

    def test_handle_form_post_existing_valid(self):
        """
        Invoking the handle_form view as a POST request for an existing
        item updates that item and returns the update item snippet.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': self.name.id,
                                    'given_name': 'Susy',
                                    'family_name': 'Smith'
                                })

        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(
            Name.objects.filter(given_name='Susy',
                                family_name='Smith').count(), 1)

    def test_handle_form_json_serialize_get(self):
        """When an ajax requests wants to GET json, serialize the form."""
        resp = self.client.get(reverse('handle_form'),
                               HTTP_ACCEPT='application/json',
                               data={'module': 'Name'})
        self.assertEquals(200, resp.status_code)
        self.assertIn('application/json', resp['content-type'])
        data = json.loads(resp.content)
        self.assertEquals(3, len(data['ordered_fields']))
        self.assertIsInstance(data['ordered_fields'], list)
        self.assertEquals(3, len(data['fields']))
        self.assertIsInstance(data['fields'], dict)
        self.assertIsInstance(data['fields']['family_name'], dict)
        self.assertIsInstance(data['fields']['given_name'], dict)
        self.assertIsInstance(data['fields']['primary'], dict)
        self.assertEquals(3, len(data['data']))
        self.assertIsInstance(data['data'], dict)

    def test_add_duplicate_primary_email(self):
        """
        Attempting to add a secondary email with a value equal to the user's
        current primary email results in an error.

        Due to how the instance is constructed, this validation is form-level
        rather than model-level.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'SecondaryEmail',
                                    'id': 'new',
                                    'email': self.user.email
                                },
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'email': [u'This email is already registered.']})
Beispiel #12
0
class MySignOn(MyJobsBase):
    def setUp(self):
        super(MySignOn, self).setUp()
        self.user = UserFactory()
        self.auth_callback_url = 'https://secure.my.jobs/account'
        self.auth_callback = '?auth_callback=%s' % self.auth_callback_url
        self.key_qs = '%s&key=%s'

        self.client = TestClient()
        self.client.login_user(self.user)

    def test_anonymous_auth(self):
        """
        Anonymous users must first login before being redirected.

        This redirection happens automatically if JavaScript is disabled. JSON
        is returned and the redirect takes place via JavaScript otherwise.
        """
        login_data = {'username': self.user.email,
                      'password': '******',
                      'auth_callback': self.auth_callback_url,
                      'action': 'login'}

        self.client.logout()
        self.assertEqual(AuthorizedClient.objects.count(), 0)
        self.assertTrue(self.client.session.get('key') is None)

        response = self.client.post(reverse('sso_authorize'),
                                    login_data)

        self.assertEqual(AuthorizedClient.objects.count(), 1)
        self.assertTrue(self.client.session.get('key') is not None)
        self.assertEqual(response.get('Location'),
                         self.auth_callback_url + '?key=%s' %
                         self.client.session.get('key'))

        self.client.logout()
        response = self.client.post(reverse('sso_authorize'),
                                    login_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        content = json.loads(response.content)
        self.assertEqual(content['url'], self.auth_callback_url +
                         '?key=%s' % self.client.session['key'])

    def test_authenticated_auth(self):
        """
        Users who are already logged in can simply click a button to authorize
        a given site and are then redirected to the given callback url.

        If a given user has already authorized a given site and that site
        provides the key that it was given, this redirect is automatic.
        """
        self.assertEqual(AuthorizedClient.objects.count(), 0)
        self.assertTrue(self.client.session.get('key') is None)

        response = self.client.post(reverse('sso_authorize'),
                                    {'auth_callback': self.auth_callback_url,
                                     'action': 'authorize'})

        self.assertEqual(self.user.authorizedclient_set.count(), 1)
        self.assertTrue(self.client.session.get('key') is not None)
        self.assertEqual(response.get('Location'),
                         self.auth_callback_url + '?key=%s' %
                         self.client.session.get('key'))

        good_qs = self.key_qs % (self.auth_callback,
                                 self.client.session.get('key'))
        response = self.client.get(reverse('sso_authorize') + good_qs)
        self.assertEqual(response.get('Location'),
                         self.auth_callback_url + '?key=%s' %
                         self.client.session.get('key'))

    def test_bad_key(self):
        """
        Providing a bad key will always cause the user to have to
        log back into their account.

        Bad keys are defined as providing a key that doesn't match the
        user's current key or providing a key when the user doesn't currently
        have a key defined.
        """
        # no key
        no_key = self.key_qs % (self.auth_callback,
                                AuthorizedClient.create_key(self.user))
        response = self.client.get(reverse('sso_authorize') + no_key)
        self.assertEqual(AuthorizedClient.objects.count(), 0)

        # Ensure that user was logged out
        response = self.client.get(reverse('view_profile'))
        path = response.request.get('PATH_INFO')
        self.assertRedirects(response, reverse('home')+'?next='+path)

        # wrong key
        self.client.login_user(self.user)
        session = self.client.session
        session['key'] = AuthorizedClient.create_key(self.user)
        session.save()

        # key is a hex string; we can invalidate it by taking a substring
        wrong_key = self.key_qs % (self.auth_callback,
                                   AuthorizedClient.create_key(self.user)[:-1])

        AuthorizedClientFactory(user=self.user)

        response = self.client.get(reverse('sso_authorize') + wrong_key)
        # Ensure that user was logged out again
        response = self.client.get(reverse('view_profile'))
        path = response.request.get('PATH_INFO')
        self.assertRedirects(response, reverse('home')+'?next='+path)
Beispiel #13
0
class MyProfileViewsTests(MyJobsBase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.client = TestClient()
        self.client.login_user(self.user)
        self.name = PrimaryNameFactory(user=self.user)

    def test_edit_profile(self):
        """
        Going to the edit_profile view generates a list of existing profile
        items in the main content section and a list of profile sections that
        don't have data filled out in the sidebar.
        """
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)
        item_id = self.name.id

        # The existing name object should be rendered on the main content
        # section
        self.assertIsNotNone(
            soup.find('div', id='name-' + str(item_id) + '-item'))
        # profile-section contains the name of a profile section that has no
        # information filled out yet and shows up in the sidebar
        self.assertTrue(soup.findAll('tr', {'class': 'profile-section'}))

    def test_edit_summary(self):
        """
        See test_edit_profile
        """
        summary = SummaryFactory(user=self.user)
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)

        item = soup.find('div', id='summary-' + str(summary.id) + '-item')
        self.assertIsNotNone(item)

        link = item.find('a').attrs['href']
        resp = self.client.get(link)
        self.assertEqual(resp.status_code, 200)

    def test_handle_form_get_new(self):
        """
        Invoking the handle_form view without an id parameter returns an
        empty form with the correct form id
        """

        resp = self.client.get(reverse('handle_form'), data={'module': 'Name'})
        self.assertTemplateUsed(resp, 'myprofile/profile_form.html')
        soup = BeautifulSoup(resp.content)
        self.assertEquals(soup.form.attrs['id'], 'profile-unit-form')
        with self.assertRaises(KeyError):
            soup.find('input', id='id_name-given_name').attrs['value']

    def test_handle_form_get_existing(self):
        """
        Invoking the handle_form view with and id paraemeter returns
        a form filled out with the corresponding profile/ID combination
        """

        resp = self.client.get(reverse('handle_form'),
                               data={
                                   'module': 'Name',
                                   'id': self.name.id
                               })
        self.assertTemplateUsed(resp, 'myprofile/profile_form.html')
        soup = BeautifulSoup(resp.content)
        self.assertEquals(soup.form.attrs['id'], 'profile-unit-form')
        self.assertEquals(
            soup.find('input', id='id_name-given_name').attrs['value'],
            'Alice')
        self.assertEquals(
            soup.find('input', id='id_name-family_name').attrs['value'],
            'Smith')
        self.assertEquals(
            soup.find('input', id='id_name-primary').attrs['checked'],
            'checked')

    def test_handle_form_post_new_valid(self):
        """
        Invoking the handle_form view as a POST request for a new item
        creates that object in the database and returns the item snippet
        to be rendered on the page.
        """

        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': 'new',
                                    'given_name': 'Susy',
                                    'family_name': 'Smith'
                                })
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(
            Name.objects.filter(given_name='Susy',
                                family_name='Smith').count(), 1)

    def test_handle_form_post_invalid(self):
        """
        Invoking the handle_form view as a POST request with an invalid
        form returns the list of form errors.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': 'new',
                                    'given_name': 'Susy'
                                },
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'family_name': [u'This field is required.']})

    def test_handle_form_post_existing_valid(self):
        """
        Invoking the handle_form view as a POST request for an existing
        item updates that item and returns the update item snippet.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'Name',
                                    'id': self.name.id,
                                    'given_name': 'Susy',
                                    'family_name': 'Smith'
                                })
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(
            Name.objects.filter(given_name='Susy',
                                family_name='Smith').count(), 1)

    def test_handle_form_redirect_summary(self):
        """
        When a user has a summary already if they try to make a new summary
        handle form should redirect the user to edit the summary they already
        have. User is only allowed one summary per account.
        """
        summary_instance = SummaryFactory(user=self.user)
        summary_instance.save()
        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Summary'})
        self.assertRedirects(
            resp,
            reverse('handle_form') +
            '?id=%s&module=Summary' % summary_instance.id)

    def test_delete_item(self):
        """
        Invoking the delete_item view deletes the item and returns
        the 'Deleted!' HttpResponse
        """

        resp = self.client.post(
            reverse('delete_item') + '?item=' + str(self.name.id))

        self.assertEqual(resp.content, '')
        self.assertEqual(Name.objects.filter(id=self.name.id).count(), 0)

    def test_add_duplicate_primary_email(self):
        """
        Attempting to add a secondary email with a value equal to the user's
        current primary email results in an error.

        Due to how the instance is constructed, this validation is form-level
        rather than model-level.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={
                                    'module': 'SecondaryEmail',
                                    'id': 'new',
                                    'email': self.user.email
                                },
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(json.loads(resp.content),
                         {u'email': [u'This email is already registered.']})

    def test_default_country_changes(self):
        """
        The displayed country when editing an address should update to reflect
        the chosen country.
        """
        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Address'})
        content = BeautifulSoup(resp.content)

        selected = content.find('option', attrs={'selected': True})
        self.assertEqual(selected.attrs['value'], 'USA')

        address = AddressFactory(user=self.user, country_code='AFG')

        resp = self.client.get(reverse('handle_form'),
                               data={
                                   'module': 'Address',
                                   'id': address.id
                               })
        content = BeautifulSoup(resp.content)
        selected = content.find('option', attrs={'selected': True})
        self.assertEqual(selected.attrs['value'], 'AFG')
Beispiel #14
0
class TestReportView(MyReportsTestCase):
    """
    Tests the ReportView class, which is used to create and retrieve
    reports.
    """
    def setUp(self):
        super(TestReportView, self).setUp()
        self.client = TestClient(path=reverse('reports', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'}))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner=self.partner)
        ContactRecordFactory.create_batch(
            5, contact_type='job',
            job_applications="1", job_interviews="0", job_hires="0",
            partner=self.partner)
        ContactRecordFactory.create_batch(
            5, contact_type='job',
            job_applications="0", job_interviews="0", job_hires="1",
            partner=self.partner)

    def test_create_report(self):
        """Test that a report model instance is properly created."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post()
        report_name = response.content
        report = Report.objects.get(name=report_name)

        self.assertEqual(len(report.python), 15)

        # we use this in other tests
        return report_name

    def test_get_report(self):
        """Test that chart data is retreived from record results."""

        report_name = self.test_create_report()
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.pk})
        data = json.loads(response.content)

        # check contact record stats
        for key in ['applications', 'hires', 'communications', 'emails']:
            self.assertEqual(data[key], 5)

        # check contact stats
        self.assertEqual(data['contacts'][0]['records'], 5)
        self.assertEqual(data['contacts'][0]['referrals'], 10)

    def test_reports_exclude_archived(self):
        """
        Test that reports exclude archived records as appropriate. This
        includes non-archived records associated with archived records.
        """
        self.client.path = reverse('view_records', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'})

        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 15)

        ContactRecord.objects.last().archive()

        # Archiving one communication record should result in one fewer entry
        # in the returned json.
        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 14)

        Partner.objects.last().archive()

        # Archiving the partner governing these communication records should
        # exclude all of them from the returned json even if they aren't
        # archived.
        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 0)
Beispiel #15
0
class TestViewRecords(MyReportsTestCase):
    """
    Tests the `view_records` view which is used to query various models.
    """

    def setUp(self):
        super(TestViewRecords, self).setUp()
        self.client = TestClient(path="/reports/ajax/mypartners", HTTP_X_REQUESTED_WITH="XMLHttpRequest")
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner=self.partner, contact__name="Joe Shmoe")

    def test_restricted_to_ajax(self):
        """View should only be reachable through AJAX."""

        self.client.path += "/partner"
        self.client.defaults.pop("HTTP_X_REQUESTED_WITH")
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_restricted_to_get(self):
        """POST requests should raise a 404."""

        self.client.path += "/partner"
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_json_output(self):
        """Test that filtering contact records through ajax works properly."""

        # records to be filtered out
        ContactRecordFactory.create_batch(10, contact__name="John Doe")

        self.client.path += "/contactrecord"
        response = self.client.get(data={"contact__name": "Joe Shmoe"})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_only_user_results_returned(self):
        """Results should only contain records user has access to."""

        # records not owned by user
        partner = PartnerFactory(name="Wrong Partner")
        ContactRecordFactory.create_batch(10, partner=partner)

        self.client.path += "/contactrecord"
        response = self.client.get()
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_partner(self):
        """Test the ability to filter by partner."""

        # we already have one because of self.partner
        PartnerFactory.create_batch(9, name="Test Partner", owner=self.company)

        self.client.path += "/partner"
        response = self.client.get(data={"name": "Test Partner"})
        output = json.loads(response.content)

        # ContactRecordFactory creates 10 partners in setUp
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_list_query_params(self):
        """Test that query parameters that are lists are parsed correctly."""

        contacts = ContactFactory.create_batch(10, partner__owner=self.company)
        pks = [contact.pk for contact in contacts[:5]]

        self.client.path += "/partner"
        response = self.client.get(data={"contact": pks})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 5)

    def test_filtering_on_contact(self):
        """Test the ability to filter by contact."""

        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner)

        # contacts with the wrong name
        ContactFactory.create_batch(10, name="Jen Smith", partner=self.partner)

        self.client.path += "/contact"
        response = self.client.get(data={"name": "Jen Doe"})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filter_by_state(self):
        """Tests that filtering by state works."""

        indiana = LocationFactory(state="IN")
        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner, locations=[indiana])

        self.client.path += "/contact"
        response = self.client.get(data={"state": "IN"})
        output = json.loads(response.content)

        self.assertEqual(len(output), 10)

    def test_filter_by_city(self):
        """Tests that filtering by city works."""

        indianapolis = LocationFactory(city="Indianapolis")
        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner, locations=[indianapolis])

        self.client.path += "/contact"
        response = self.client.get(data={"city": "indianapolis"})
        output = json.loads(response.content)

        self.assertEqual(len(output), 10)

    def test_filter_by_tag(self):
        """Tests that records can be found by tag."""

        tag = TagFactory(name="Test", company=self.company)
        ContactRecord.objects.first().tags.add(tag)

        # explicitly add tag to partner to make sure that a tag associated wiht
        # multiple models doesn't cause issues
        self.partner.tags.add(tag)

        self.client.path += "/tag"
        # make a call that mimicks static/reporting:721 (as of 7/1/15)
        response = self.client.get(
            data={"name": "Test", "contactrecord__isnull": "false", "values": ["name"], "order_by": "name"}
        )
        output = json.loads(response.content)

        self.assertEqual(len(output), 1)
Beispiel #16
0
class MySearchViewTests(MyJobsBase):
    def setUp(self):
        super(MySearchViewTests, self).setUp()
        self.client = TestClient()
        self.user = UserFactory()
        self.client.login_user(self.user)
        self.new_form_data = {
            'url': 'www.my.jobs/jobs',
            'feed': 'http://www.my.jobs/jobsfeed/rss?',
            'label': 'Jobs Label',
            'email': self.user.email,
            'frequency': 'D',
            'is_active': 'True',
            'jobs_per_email': 5,
            'sort_by': 'Relevance',
        }
        self.new_digest_data = {
            'is_active': 'True',
            'user': self.user,
            'email': self.user.email,
            'frequency': 'M',
            'day_of_month': 1,
        }
        self.new_form = forms.SavedSearchForm(user=self.user,
                                              data=self.new_form_data)

        self.patcher = patch('urllib2.urlopen', return_file())
        self.patcher.start()

    def tearDown(self):
        super(MySearchViewTests, self).tearDown()
        try:
            self.patcher.stop()
        except RuntimeError:
            # patcher was stopped in a test
            pass

    def test_search_main(self):
        response = self.client.get(reverse('saved_search_main'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'mysearches/saved_search_main.html')
        self.failUnless(isinstance(response.context['form'], forms.DigestForm))
        self.failUnless(isinstance(response.context['add_form'],
                                   forms.SavedSearchForm))

    def test_saved_search_digest_options(self):
        response = self.client.get(reverse('saved_search_main'))
        self.assertTrue('Digest Options' in response.content)
        self.assertFalse('digest-option' in response.content)

        self.assertTrue(self.new_form.is_valid())
        self.new_form.save()
        response = self.client.get(reverse('saved_search_main'))
        self.assertTrue('Digest Options' in response.content)
        self.assertTrue('digest-option' in response.content)

    def test_save_new_search_form(self):
        response = self.client.post(reverse('save_search_form'),
                                    data=self.new_form_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '')

    def test_save_new_search_invalid(self):
        del self.new_form_data['frequency']
        response = self.client.post(reverse('save_search_form'),
                                    data=self.new_form_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content).keys(),
                         ['frequency'])

    def test_get_edit_page(self):
        self.assertTrue(self.new_form.is_valid())
        self.new_form.save()
        search_id = self.new_form.instance.id
        response = self.client.get(
            reverse('edit_search')+'?id=%s' % search_id)
        self.assertEqual(response.status_code, 200)

        self.assertEqual(self.new_form.instance,
                         response.context['form'].instance)
        self.assertTemplateUsed(response, 'mysearches/saved_search_edit.html')

        search_id += 1
        response = self.client.get(
            reverse('edit_search')+'?id=%s' % search_id)
        self.assertEqual(response.status_code, 404)

    def test_save_edit_form(self):
        self.assertTrue(self.new_form.is_valid())
        self.new_form.save()
        search_id = self.new_form.instance.id

        self.new_form_data['frequency'] = 'W'
        self.new_form_data['day_of_week'] = 1
        self.new_form_data['url'] = 'www.my.jobs/search?'
        self.new_form_data['search_id'] = search_id

        new_form = forms.SavedSearchForm(user=self.user,
                                         data=self.new_form_data)
        response = self.client.post(reverse('save_search_form'),
                                    data=self.new_form_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '')

        del self.new_form_data['frequency']

        response = self.client.post(reverse('save_search_form'),
                                    data=self.new_form_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content).keys(), ['frequency'])

    def test_validate_url(self):
        response = self.client.post(reverse('validate_url'),
                                    data={'url': self.new_form_data['url']},
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        data = {u'rss_url': u'http://www.my.jobs/jobs/feed/rss',
                u'feed_title': u'My.jobs - Jobs',
                u'url_status': u'valid'}

        content = json.loads(response.content)
        self.assertEqual(content['rss_url'], data['rss_url'])
        self.assertEqual(content['url_status'], data['url_status'])

        response = self.client.post(reverse('validate_url'),
                                    data={'url': 'google.com'},
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content),
                         {'url_status': 'not valid'})

    def test_save_digest_form(self):
        response = self.client.post(reverse('save_digest_form'),
                                    self.new_digest_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '')

        del self.new_digest_data['email']
        response = self.client.post(reverse('save_digest_form'),
                                    self.new_digest_data,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content,
                         '{"email": ["This field is required."]}')

    def test_unsubscribe_owned_search(self):
        """
        Unsubscribing an owned saved search should result in
        that search being deactivated
        """
        search = SavedSearchFactory(user=self.user)
        self.assertTrue(search.is_active)

        response = self.client.get(reverse('unsubscribe')+'?id=%s' % search.id)
        search = models.SavedSearch.objects.get(id=search.id)
        self.assertFalse(search.is_active)
        self.assertTemplateUsed(response,
                                'mysearches/saved_search_disable.html')

    def test_unsubscribe_unowned_search(self):
        """
        Attempting to unsubscribe using a search that isn't yours
        should result in nothing happening to the search
        """
        user = UserFactory(email='*****@*****.**')
        search = SavedSearchFactory(user=user)

        response = self.client.get(reverse('unsubscribe')+'?id=%s' % search.id)
        search = models.SavedSearch.objects.get(id=search.id)
        self.assertTrue(search.is_active)
        self.assertEqual(response.status_code, 404)

    def test_unsubscribe_digest(self):
        """
        Unsubscribing a saved search digest should result in all
        of the owner's saved searches being disabled
        """
        digest = SavedSearchDigestFactory(user=self.user)
        searches = []
        for url in ['www.my.jobs/search?q=python', 'jobs.jobs/search?q=django']:
            searches.append(SavedSearchFactory(url=url, user=self.user))

        for search in searches:
            self.assertTrue(search.is_active)

        response = self.client.get(reverse('unsubscribe')+'?id=digest')
        searches = list(models.SavedSearch.objects.all())
        for search in searches:
            self.assertFalse(search.is_active)
        self.assertTemplateUsed(response,
                                'mysearches/saved_search_disable.html')
        self.assertEqual(response.status_code, 200)

    def test_anonymous_unsubscribe(self):
        search = SavedSearchFactory(user=self.user)
        Session.objects.all().delete()

        # Navigating to the 'unsubscribe' page while logged out...
        response = self.client.get(
            reverse('unsubscribe')+'?id='+str(search.id))
        path = response.request.get('PATH_INFO') + "?id=" + str(search.id)
        self.assertRedirects(response, reverse('home')+'?next='+path)
        # or with the wrong email address...
        response = self.client.get(
            reverse('unsubscribe') + '?id='+str(
                search.id)+'&[email protected]')
        # results in being redirected to the login page and the searches
        # remaining unchanged
        self.assertRedirects(response, reverse('home'))
        search = models.SavedSearch.objects.get(id=search.id)
        self.assertTrue(search.is_active)

        response = self.client.get(
            reverse('unsubscribe') + '?id=%s&verify=%s' % (
                search.id, self.user.user_guid))
        search = models.SavedSearch.objects.get(id=search.id)
        self.assertFalse(search.is_active)

    def test_delete_owned_search(self):
        search = SavedSearchFactory(user=self.user)
        self.assertEqual(models.SavedSearch.objects.count(), 1)

        response = self.client.get(
            reverse('delete_saved_search')+'?id=%s' % search.id)
        self.assertEqual(models.SavedSearch.objects.count(), 0)
        self.assertRedirects(response, reverse(
            'saved_search_main_query')+'?d='+str(urllib2.quote(
                                                 search.label)))

    def test_delete_all_searches(self):
        """
        Deleting all searches should only remove regular saved searches if the
        partner saved searches weren't created by the user trying to use it.
        """
        
        user = UserFactory(email='*****@*****.**')
        company = CompanyFactory(id=2423, name="Bacon Factory",
                                 user_created=False)
        SavedSearchFactory(user=self.user)
        pss = PartnerSavedSearchFactory(user=self.user, created_by=user,
                                        provider=company)

        response = self.client.get(reverse('delete_saved_search') +
            '?id=ALL')
        
        self.assertEqual(response.status_code, 302)
        # partner saved search should still exist...
        self.assertTrue(models.PartnerSavedSearch.objects.filter(
            pk=pss.pk).exists())
        # ... but the regular saved search shouldn't
        self.assertFalse(models.SavedSearch.objects.filter(
            partnersavedsearch__isnull=True).exists())

    def test_delete_unowned_search(self):
        """
        Attempting to delete a search that isn't yours should
        result in nothing happening to the search
        """
        user = UserFactory(email='*****@*****.**')
        search = SavedSearchFactory(user=user)

        response = self.client.get(
            reverse('delete_saved_search') + '?id=%s' % search.id)
        self.assertEqual(models.SavedSearch.objects.count(), 1)
        self.assertEqual(response.status_code, 404)

    def test_delete_owned_searches_by_digest(self):
        """
        Deleting with a saved search digest should result in
        all of the user's saved searches being deleted
        """
        digest = SavedSearchDigestFactory(user=self.user)
        searches = []
        for url in ['www.my.jobs/search?q=python', 'jobs.jobs/search?q=django']:
            searches.append(SavedSearchFactory(url=url, user=self.user))

        self.assertEqual(models.SavedSearch.objects.count(), 2)

        response = self.client.get(reverse(
            'delete_saved_search') + '?id=digest')
        self.assertEqual(models.SavedSearch.objects.count(), 0)
        self.assertRedirects(response, reverse(
            'saved_search_main_query') + '?d=all')

    def test_anonymous_delete_searches(self):
        search = SavedSearchFactory(user=self.user)
        Session.objects.all().delete()

        # Navigating to the 'delete saved search' page while logged out...
        response = self.client.get(
            reverse('delete_saved_search') + '?id=' + str(search.id))
        path = response.request.get('PATH_INFO') + "?id=" + str(search.id)
        self.assertRedirects(response, reverse('home') + '?next=' + path)
        self.assertEqual(models.SavedSearch.objects.count(), 1)
        # or with the wrong email address...
        response = self.client.get(
            reverse('delete_saved_search') + '?id=' + str(
                search.id) + '&[email protected]')
        # results in being redirected to the login page and no searches being
        # deleted
        self.assertRedirects(response, reverse('home'))
        self.assertEqual(models.SavedSearch.objects.count(), 1)

        response = self.client.get(
            reverse('delete_saved_search') + '?id=%s&verify=%s' % (
                search.id, self.user.user_guid))
        self.assertEqual(models.SavedSearch.objects.count(), 0)

        # assertRedirects follows any redirect and waits for a 200 status code;
        # anonymous users will always redirect, never returning a 200.
        self.client.login_user(self.user)
        self.assertRedirects(response, reverse(
            'saved_search_main_query') + '?d=' + str(urllib2.quote(
                search.label)))

    def test_widget_with_saved_search(self):
        search = SavedSearchFactory(user=self.user)
        response = self.client.get(reverse('saved_search_widget') +
                                   '?url=%s&callback=callback' % (
                                       search.url, ))
        edit_url = '\\"https://secure.my.jobs%s?id=%s\\"' % (
            reverse('edit_search'), search.pk)
        self.assertTrue(edit_url in response.content)

    def test_widget_with_partner_saved_search(self):
        company = CompanyFactory()
        partner = PartnerFactory(owner=company)
        ContactFactory(user=self.user, partner=partner)
        search = PartnerSavedSearchFactory(user=self.user,
                                           created_by=self.user,
                                           provider=company,
                                           partner=partner)

        response = self.client.get(reverse('saved_search_widget') +
                                   '?url=%s&callback=callback' % (
                                       search.url, ))
        edit_url = '\\"https://secure.my.jobs%s?id=%s&pss=True\\"' % (
            reverse('edit_search'), search.pk)
        self.assertTrue(edit_url in response.content)

    def test_viewing_feed_on_bad_search(self):
        search = SavedSearchFactory(user=self.user, url='http://404.com',
                                    feed='http://404.com/feed/json')
        response = self.client.get(reverse(
            'view_full_feed') + '?id=%s' % search.id)
        self.assertIn('The domain for this saved search is no longer valid.',
                      response.content)

    def test_send_link_appearance(self):
        """
        The button to manually send a saved search should not be displayed
        when DEBUG=False. If the url is guessed, nothing bad should happen.
        """
        self.user.is_superuser = True
        self.user.save()
        saved_search = SavedSearchFactory(user=self.user)
        partner_search = PartnerSavedSearchFactory(user=self.user,
                                                   created_by=self.user)
        ContactFactory(partner=partner_search.partner, user=self.user)

        for search in [saved_search, partner_search]:
            full_feed = reverse('view_full_feed') + '?id=%s' % search.id
            send_url = reverse('send_saved_search') + '?id=%s' % search.id
            if hasattr(search, 'partnersavedsearch'):
                send_url += '&is_pss=True'

            self.client.login_user(self.user)
            response = self.client.get(full_feed)
            self.assertNotIn('>Send</a>', response.content)
            send = self.client.get(send_url)
            self.assertEqual(send.status_code, 404)
            self.assertEqual(len(mail.outbox), 0)

            settings.DEBUG = True
            self.client.login_user(self.user)
            response = self.client.get(full_feed)
            self.assertIn('>Send</a>', response.content)
            send = self.client.get(send_url)
            self.assertEqual(send.status_code, 302)
            self.assertEqual(len(mail.outbox), 1)
            mail.outbox = []

            settings.DEBUG = False

    def test_send_link_respects_permissions(self):
        # The send_saved_search view requires that DEBUG be enabled.
        settings.DEBUG = True
        self.user.is_superuser = True
        self.user.save()
        search = SavedSearchFactory(user=self.user)
        search_2 = SavedSearchFactory(user=UserFactory(email='*****@*****.**'))
        send_url = reverse('send_saved_search') + '?id=%s'

        self.assertEqual(len(mail.outbox), 0)
        response = self.client.get(send_url % search.pk)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(len(mail.outbox), 1)
        response = self.client.get(send_url % search_2.pk)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(len(mail.outbox), 2)
        settings.DEBUG = False
Beispiel #17
0
class TestReportView(MyReportsTestCase):
    """
    Tests the ReportView class, which is used to create and retrieve
    reports.
    """
    def setUp(self):
        super(TestReportView, self).setUp()
        self.client = TestClient(path=reverse('reports',
                                              kwargs={
                                                  'app': 'mypartners',
                                                  'model': 'contactrecord'
                                              }))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(5, partner=self.partner)
        ContactRecordFactory.create_batch(5,
                                          contact_type='job',
                                          job_applications="1",
                                          job_interviews="0",
                                          job_hires="0",
                                          partner=self.partner)
        ContactRecordFactory.create_batch(5,
                                          contact_type='job',
                                          job_applications="0",
                                          job_interviews="0",
                                          job_hires="1",
                                          partner=self.partner)

    def test_create_report(self):
        """Test that a report model instance is properly created."""

        # create a report whose results is for all contact records in the
        # company
        response = self.client.post()
        report_name = response.content
        report = Report.objects.get(name=report_name)

        self.assertEqual(len(report.python), 15)

        # we use this in other tests
        return report_name

    def test_get_report(self):
        """Test that chart data is retreived from record results."""

        report_name = self.test_create_report()
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.pk})
        data = json.loads(response.content)

        # check contact record stats
        for key in ['applications', 'hires', 'communications', 'emails']:
            self.assertEqual(data[key], 5)

        for contact in data['contacts']:
            self.assertTrue(contact['records'] < 2)
            self.assertTrue(contact['referrals'] < 2)
            total = contact['records'] + contact['referrals']
            self.assertEqual(total, 1)

    def test_reports_exclude_archived(self):
        """
        Test that reports exclude archived records as appropriate. This
        includes non-archived records associated with archived records.
        """
        self.client.path = reverse('view_records',
                                   kwargs={
                                       'app': 'mypartners',
                                       'model': 'contactrecord'
                                   })

        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 15)

        ContactRecord.objects.last().archive()

        # Archiving one communication record should result in one fewer entry
        # in the returned json.
        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 14)

        Partner.objects.last().archive()

        # Archiving the partner governing these communication records should
        # exclude all of them from the returned json even if they aren't
        # archived.
        response = self.client.post(HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        content = json.loads(response.content)
        self.assertEqual(len(content), 0)
Beispiel #18
0
class MyDashboardViewsTests(MyJobsBase):
    def setUp(self):
        super(MyDashboardViewsTests, self).setUp()
        self.staff_user = UserFactory()
        group = Group.objects.get(name=CompanyUser.GROUP_NAME)
        self.staff_user.groups.add(group)

        self.business_unit = BusinessUnitFactory()

        self.company = CompanyFactory(id=1)
        self.company.job_source_ids.add(self.business_unit)
        self.admin = CompanyUserFactory(user=self.staff_user,
                                        company=self.company)
        self.microsite = SeoSiteFactory()
        self.microsite.business_units.add(self.business_unit)

        self.client = TestClient()
        self.client.login_user(self.staff_user)

        self.candidate_user = UserFactory(email="*****@*****.**")
        SavedSearchFactory(user=self.candidate_user,
                           feed='http://test.jobs/jobs/feed/rss?',
                           url='http://test.jobs/search?q=django',
                           label='test Jobs')

        for i in range(5):
            # Create 5 new users
            user = UserFactory(email='*****@*****.**' % i)
            for search in SEARCH_OPTS:
                # Create 15 new searches and assign three per user
                SavedSearchFactory(user=user,
                                   url='http://test.jobs/search?q=%s' % search,
                                   feed='http://test.jobs/jobs/feed/rss?',
                                   label='%s Jobs' % search)
        update_solr_task(settings.TEST_SOLR_INSTANCE)

    def tearDown(self):
        super(MyDashboardViewsTests, self).tearDown()
        for location in settings.TEST_SOLR_INSTANCE.values():
            solr = pysolr.Solr(location)
            solr.delete(q='*:*')

    def add_analytics_data(self, type_, num_to_add=2):
        """
        Adds testing analytics data to Solr.

        Adds two entries per page category, one for unauthenticated and one for
        authenticated hits.
        """
        dicts = []
        base_dict = {
            'domain': self.microsite.domain,
            'view_date': datetime.now(),
            'company_id': self.company.pk,
        }
        home_dict = {
            'page_category': 'home'
        }
        view_dict = {
            'job_view_guid': '1'*32,
            'job_view_buid': self.business_unit.pk,
            'page_category': 'listing'
        }
        search_dict = {
            'page_category': 'results'
        }
        apply_dict = {
            'job_view_guid': '2'*32,
            'job_view_buid': self.business_unit.pk,
            'page_category': 'redirect'
        }

        if type_ == 'home':
            analytics_dict = home_dict
        elif type_ == 'listing':
            analytics_dict = view_dict
        elif type_ == 'results':
            analytics_dict = search_dict
        else:
            analytics_dict = apply_dict

        analytics_dict.update(base_dict)
        for _ in range(num_to_add):
            dicts.append(analytics_dict.copy())

        for analytics_dict in dicts:
            analytics_dict['aguid'] = uuid.uuid4().hex
            analytics_dict['uid'] = 'analytics##%s#%s' % (
                analytics_dict['view_date'],
                analytics_dict['aguid']
            )

        for location in settings.TEST_SOLR_INSTANCE.values():
            solr = pysolr.Solr(location)
            solr.add(dicts)

    @unittest.skip("Correct behavior undefined with respect to duplicates.")
    def test_number_of_searches_and_users_is_correct(self):
        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id))
        # 6 users total
        self.assertEqual(response.context['total_candidates'], 6)

        old_search = SavedSearch.objects.all()[0]
        old_search.created_on -= timedelta(days=31)
        old_search.save()

        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id),
            {'microsite': 'test.jobs'})

        self.assertEqual(response.context['total_candidates'], 6)

    def test_facets(self):
        education = EducationFactory(user=self.candidate_user)
        adr = AddressFactory(user=self.candidate_user)
        license = LicenseFactory(user=self.candidate_user)
        self.candidate_user.save()
        update_solr_task(settings.TEST_SOLR_INSTANCE)

        country_str = 'http://testserver/candidates/view?company=1&location={country}'
        education_str = 'http://testserver/candidates/view?company=1&education={education}'
        license_str = 'http://testserver/candidates/view?company=1&license={license_name}'

        country_str = country_str.format(country=adr.country_code)
        education_str = education_str.format(education=education.education_level_code)
        license_str = license_str.format(license_name=license.license_name)

        q = '?company={company}'
        q = q.format(company=str(self.company.id))
        response = self.client.post(reverse('dashboard')+q)
        soup = BeautifulSoup(response.content)

        types = ['Country', 'Education', 'License']
        hrefs = []
        for facet_type in types:
            container = soup.select('#%s-details-table' % facet_type)[0]
            href = container.select('a')[0].attrs['href']
            hrefs.append(href)

        self.assertIn(country_str, hrefs)
        self.assertIn(education_str, hrefs)
        self.assertIn(license_str, hrefs)

    def test_filters(self):
        adr = AddressFactory(user=self.candidate_user)
        self.candidate_user.save()
        update_solr_task(settings.TEST_SOLR_INSTANCE)

        country_str = 'http://testserver/candidates/view?company=1&amp;location={country}'
        country_filter_str = '<a class="applied-filter" href="http://testserver/candidates/view?company=1"><span>&#10006;</span> {country_long}</a><br>'
        region_str = 'http://testserver/candidates/view?company=1&amp;location={country}-{region}'
        region_filter_str = '<a class="applied-filter" href="http://testserver/candidates/view?company=1&amp;location={country}"><span>&#10006;</span> {region}, {country}</a>'
        city_str = 'http://testserver/candidates/view?company=1&amp;location={country}-{region}-{city}'
        city_filter_str = '<a class="applied-filter" href="http://testserver/candidates/view?company=1&amp;location={country}-{region}"><span>&#10006;</span> {city}, {region}, {country}</a>'

        country_str = country_str.format(country=adr.country_code)
        country_filter_str = country_filter_str.format(country=adr.country_code,
                                                       country_long=country_codes[adr.country_code])
        region_str = region_str.format(country=adr.country_code,
                                       region=adr.country_sub_division_code)
        region_filter_str = region_filter_str.format(region=adr.country_sub_division_code,
                                                     country=adr.country_code,
                                                     country_long=country_codes[adr.country_code])
        city_str = city_str.format(country=adr.country_code,
                                   region=adr.country_sub_division_code,
                                   city=adr.city_name)
        city_filter_str = city_filter_str.format(country=adr.country_code,
                                                 region=adr.country_sub_division_code,
                                                 city=adr.city_name,
                                                 country_long=country_codes[adr.country_code])

        q = '?company={company}'
        q = q.format(company=str(self.company.id))
        response = self.client.post(reverse('dashboard')+q)
        self.assertIn(country_str, response.content)

        q = '?company={company}&location={country}'
        q = q.format(company=str(self.company.id), country=adr.country_code)
        response = self.client.post(reverse('dashboard')+q)
        self.assertIn(country_filter_str, response.content)
        self.assertIn(region_str, response.content)

        q = '?company={company}&location={country}-{region}'
        q = q.format(company=str(self.company.id), country=adr.country_code,
                     region=adr.country_sub_division_code)
        response = self.client.post(reverse('dashboard')+q)
        self.assertIn(region_filter_str, response.content)
        self.assertIn(city_str, response.content)

        q = '?company={company}&location={country}-{region}-{city}'
        q = q.format(company=str(self.company.id), country=adr.country_code,
                     region=adr.country_sub_division_code,
                     city=adr.city_name)
        response = self.client.post(reverse('dashboard')+q)
        self.assertIn(city_filter_str, response.content)

    @unittest.skip("Correct behavior undefined with respect to duplicates.")
    def test_search_field(self):
        # Build url
        def build_url(search):
            q = '?company={company}&search={search}'
            q = q.format(company=str(self.company.id), search=search)
            return reverse('dashboard') + q

        # assert it finds all 5 searches.
        response = self.client.post(build_url('python'))
        soup = BeautifulSoup(response.content)
        count_box = soup.select('.count-box-left')
        count = int(count_box[0].text)
        self.assertEqual(count, 5)

        # 6 users total
        response = self.client.post(build_url('example'))
        soup = BeautifulSoup(response.content)
        count_box = soup.select('.count-box-left')
        count = int(count_box[0].text)
        self.assertIn(count, [6, 7])

    def test_search_email(self):
        """We should be able to search for an exact email."""
        user = UserFactory(email="*****@*****.**")
        SavedSearchFactory(user=user,
                           url='http://test.jobs/search?q=python',
                           feed='http://test.jobs/jobs/feed/rss?',
                           label='Python Jobs')
        user.save()
        update_solr_task(settings.TEST_SOLR_INSTANCE)

        q = '?company={company}&search={search}'
        q = q.format(company=str(self.company.id), search='*****@*****.**')
        url = reverse('dashboard') + q

        response = self.client.post(url)
        soup = BeautifulSoup(response.content)
        self.assertEqual(len(soup.select('#row-link-table tr')), 1)

    def test_search_domain(self):
        """We should be able to search for domain."""
        user = UserFactory(email="*****@*****.**")
        SavedSearchFactory(user=user,
                           url='http://test.jobs/search?q=python',
                           feed='http://test.jobs/jobs/feed/rss?',
                           label='Python Jobs')
        user.save()
        update_solr_task(settings.TEST_SOLR_INSTANCE)

        q = '?company={company}&search={search}'
        q = q.format(company=str(self.company.id), search='shouldWork.com')
        url = reverse('dashboard') + q

        response = self.client.post(url)
        soup = BeautifulSoup(response.content)
        self.assertEqual(len(soup.select('#row-link-table tr')), 1)

    def test_search_updates_facet_counts(self):
        # Add ProfileData to the candidate_user
        EducationFactory(user=self.candidate_user)
        AddressFactory(user=self.candidate_user)
        LicenseFactory(user=self.candidate_user)
        self.candidate_user.save()

        # Create a new user with ProfileData
        user = UserFactory(email="*****@*****.**")
        SavedSearchFactory(user=user,
                           url='http://test.jobs/search?q=python',
                           feed='http://test.jobs/jobs/feed/rss?',
                           label='Python Jobs')
        EducationFactory(user=user)
        AddressFactory(user=user)
        LicenseFactory(user=user)
        user.save()

        update_solr_task(settings.TEST_SOLR_INSTANCE)

        # Assert there are two users with country codes
        country_tag = '#Country-details-table .facet-count'
        q = '?company={company}'
        q = q.format(company=str(self.company.id))
        response = self.client.post(reverse('dashboard') + q)
        soup = BeautifulSoup(response.content)
        self.assertEqual(int(soup.select(country_tag)[0].text), 2)

        # When we search, the facet count updates.
        q = '?company={company}&search={search}'
        q = q.format(company=str(self.company.id), search='find')
        response = self.client.post(reverse('dashboard') + q)
        soup = BeautifulSoup(response.content)
        self.assertEqual(int(soup.select(country_tag)[0].text), 1)

    # Tests to see if redirect from /candidates/ goes to candidates/view/
    def test_redirect_to_candidates_views_default_page(self):
        response = self.client.post('/candidates/')

        # response returns HttpResponsePermanentRedirect which returns a 301
        # status code instead of the normal 302 redirect status code
        self.assertRedirects(response, '/candidates/view/', status_code=301,
                             target_status_code=200)

        response = self.client.post(reverse('dashboard'))

        self.assertEqual(response.status_code, 200)

        soup = BeautifulSoup(response.content)
        company_name = soup.find('h1')
        company_name = company_name.next

        self.assertEqual(company_name, self.company.name)

    # Eventually these opted-in/out will be changed to
    # track if user is part of company's activity feed
    def test_candidate_has_opted_in(self):
        response = self.client.post(
            reverse('candidate_information',
                    )+'?company='+str(self.company.id)+'&user='******'candidate_information',
                    )+'?company='+str(self.company.id)+'&user='******'candidate_information',
                    )+'?company='+str(self.company.id)+'&user='******'div', {'id': 'candidate-content'}).findAll(
            'a', {'class': 'accordion-toggle'})
        info = soup.find('div', {'id': 'candidate-content'}).findAll('li')

        self.assertEqual(len(titles), 6)
        self.assertEqual(len(info), 16)
        self.assertEqual(response.status_code, 200)

    def test_candidate_page_load_without_profileunits_with_activites(self):
        response = self.client.post(
            reverse('candidate_information',
                    )+'?company='+str(self.company.id)+'&user='******'div', {'id': 'candidate-content'}).findAll(
            'a', {'class': 'accordion-toggle'})
        info = soup.find('div', {'id': 'candidate-content'}).findAll('li')

        self.assertEqual(len(titles), 1)
        self.assertEqual(len(info), 3)
        self.assertEqual(response.status_code, 200)

    def test_candidate_page_load_without_profileunits_and_activites(self):
        saved_search = SavedSearch.objects.get(user=self.candidate_user)
        saved_search.delete()
        response = self.client.post(
            reverse('candidate_information',
                    )+'?company='+str(self.company.id)+'&user='******'div', {'id': 'candidate-content'})

        self.assertFalse(info)
        self.assertEqual(response.status_code, 404)

    def test_export_csv(self):
        response = self.client.post(
            reverse('export_candidates')+'?company=' +
            str(self.company.id)+'&ex-t=csv')
        self.assertTrue(response.content)
        self.assertEqual(response.status_code, 200)

    def test_export_xml(self):
        response = self.client.post(
            reverse('export_candidates')+'?company=' +
            str(self.company.id)+'&ex-t=xml')
        self.assertTrue(response.content.index('candidates'))
        self.assertEqual(response.status_code, 200)

    def test_export_json(self):
        response = self.client.post(
            reverse('export_candidates')+'?company=' +
            str(self.company.id)+'&ex-t=json')
        self.assertTrue(response.content.index('candidates'))
        self.assertEqual(response.status_code, 200)

    def test_dashboard_analytics_no_data(self):
        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id),
            {'microsite': 'test.jobs'})

        soup = BeautifulSoup(response.content)

        for selector in ['#total-clicks',
                         '#total-home',
                         '#total-job-views',
                         '#total-search']:

            container = soup.select(selector)
            # Empty list means no elements were found.
            self.assertEqual(container, [])

    def test_dashboard_analytics_with_data(self):
        for type_ in ['home', 'listing', 'results']:
            self.add_analytics_data(type_)
        num_clicks = 1234
        self.add_analytics_data('redirect', num_to_add=num_clicks)

        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id))

        soup = BeautifulSoup(response.content)

        for selector in ['#total-clicks',
                         '#total-home',
                         '#total-job-views',
                         '#total-search']:

            # This should be the parent container for all analytics data
            # of this type
            container = soup.select(selector)[0]

            # All hits, humanized
            all_hits = container.select('span')[0]
            if selector == '#total-clicks':
                expected = '1.2k'
            else:
                expected = '2'
            self.assertEqual(all_hits.text.strip(), expected)

            # All hits, raw number
            if selector == '#total-clicks':
                full = container.attrs['data-original-title']
                self.assertEqual(full.strip(),
                                 '1,234')
            else:
                with self.assertRaises(KeyError):
                    # This is marked as having no effect, which is intended
                    container.attrs['data-original-title']

    def test_dashboard_with_no_microsites(self):
        """
        Trying to access the dashboard of a company that has no microsites
        associated with it should not create malformed solr queries.
        """
        self.microsite.delete()
        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id))
        self.assertEqual(response.status_code, 200)
Beispiel #19
0
class TestViewRecords(MyReportsTestCase):
    """
    Tests the `view_records` view which is used to query various models.
    """

    def setUp(self):
        super(TestViewRecords, self).setUp()
        self.client = TestClient(path='/reports/ajax/mypartners',
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(
            10, partner=self.partner, contact__name='Joe Shmoe')

    def test_restricted_to_ajax(self):
        """View should only be reachable through AJAX."""

        self.client.path += '/partner'
        self.client.defaults.pop('HTTP_X_REQUESTED_WITH')
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_restricted_to_get(self):
        """POST requests should raise a 404."""

        self.client.path += '/partner'
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_json_output(self):
        """Test that filtering contact records through ajax works properly."""

        # records to be filtered out
        ContactRecordFactory.create_batch(10, contact__name='John Doe')

        self.client.path += '/contactrecord'
        response = self.client.get(data={'contact__name': 'Joe Shmoe'})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_only_user_results_returned(self):
        """Results should only contain records user has access to."""

        # records not owned by user
        partner = PartnerFactory(name="Wrong Partner")
        ContactRecordFactory.create_batch(10, partner=partner)

        self.client.path += '/contactrecord'
        response = self.client.get()
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_partner(self):
        """Test the ability to filter by partner."""

        # we already have one because of self.partner
        PartnerFactory.create_batch(9, name="Test Partner", owner=self.company)

        self.client.path += '/partner'
        response = self.client.get(data={'name': 'Test Partner'})
        output = json.loads(response.content)

        # ContactRecordFactory creates 10 partners in setUp
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_list_query_params(self):
        """Test that query parameters that are lists are parsed correctly."""

        contacts = ContactFactory.create_batch(10, partner__owner=self.company)
        pks = [contact.pk for contact in contacts[:5]]

        self.client.path += '/partner'
        response = self.client.get(data={'contact': pks})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 5)

    def test_filtering_on_contact(self):
        """Test the ability to filter by contact."""

        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner)

        # contacts with the wrong name
        ContactFactory.create_batch(10, name="Jen Smith", partner=self.partner)

        self.client.path += '/contact'
        response = self.client.get(data={'name': 'Jen Doe'})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filter_by_state(self):
        """Tests that filtering by state works."""

        indiana = LocationFactory(state="IN")
        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner,
                                    locations=[indiana])

        self.client.path += '/contact'
        response = self.client.get(data={'state': 'IN'})
        output = json.loads(response.content)

        self.assertEqual(len(output), 10)

    def test_filter_by_city(self):
        """Tests that filtering by city works."""

        indianapolis = LocationFactory(city="Indianapolis")
        ContactFactory.create_batch(10, name="Jen Doe", partner=self.partner,
                                    locations=[indianapolis])

        self.client.path += '/contact'
        response = self.client.get(data={'city': 'indianapolis'})
        output = json.loads(response.content)

        self.assertEqual(len(output), 10)
Beispiel #20
0
class TestRegenerate(MyReportsTestCase):
    """Tests the reports can be regenerated."""

    def setUp(self):
        super(TestRegenerate, self).setUp()
        self.client = TestClient(path=reverse('reports', kwargs={
            'app': 'mypartners', 'model': 'contactrecord'}))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_regenerate(self):
        # create a new report
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}))

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # remove report results and ensure we can still get a reasonable
        # response
        report.results.delete()
        report.save()
        self.assertFalse(report.results)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # regenerate results and ensure they are the same as the original
        response = self.client.get(path=reverse('regenerate'), data={
            'id': report.pk})
        report = Report.objects.get(name=report_name)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(report.results)

        # regenerate report without deleting the report prior
        # see if it overwrites other report.
        results = report.results
        response = self.client.get(path=reverse('regenerate'), data={
            'id': report.pk})
        report = Report.objects.get(name=report_name)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(results.name, report.results.name)

    def test_regenerating_missing_file(self):
        """Tests that a report can be regenerated when file is missing."""

        # create a new report
        response = self.client.post(
            path=reverse('reports', kwargs={
                'app': 'mypartners', 'model': 'contactrecord'}))

        report_name = response.content
        report = Report.objects.get(name=report_name)

        # report should have results
        self.assertTrue(report.results)

        # delete physical file and ensure that json reflects the missing link
        os.remove(report.results.file.name)
        report = Report.objects.get(pk=report.pk)
        self.assertEqual(report.json, u'{}')
        self.assertEqual(report.python, {})
    
        # regenerate the report even though the file is physically missing
        report.regenerate()
        self.assertTrue(report.results)
Beispiel #21
0
class TestViewRecords(MyReportsTestCase):
    """
    Tests the `view_records` view which is used to query various models.
    """
    def setUp(self):
        super(TestViewRecords, self).setUp()
        self.client = TestClient(path='/reports/ajax/mypartners',
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10,
                                          partner=self.partner,
                                          contact__name='Joe Shmoe')

    def test_restricted_to_ajax(self):
        """View should only be reachable through AJAX."""

        self.client.path += '/partner'
        self.client.defaults.pop('HTTP_X_REQUESTED_WITH')
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_restricted_to_post(self):
        """POST requests should raise a 404."""

        self.client.path += '/partner'
        response = self.client.get()

        self.assertEqual(response.status_code, 404)

    def test_json_output(self):
        """Test that filtering contact records through ajax works properly."""

        # records to be filtered out
        ContactRecordFactory.create_batch(10, contact__name='John Doe')

        self.client.path += '/contactrecord'
        filters = json.dumps({'contact': {'name': {'icontains': 'Joe Shmoe'}}})
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_only_user_results_returned(self):
        """Results should only contain records user has access to."""

        # records not owned by user
        partner = PartnerFactory(name="Wrong Partner")
        ContactRecordFactory.create_batch(10, partner=partner)

        self.client.path += '/contactrecord'
        response = self.client.post()
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_model(self):
        """Test the ability to filter on a model's field's."""

        # we already have one because of self.partner
        PartnerFactory.create_batch(9, name='Test Partner', owner=self.company)

        self.client.path += '/partner'
        filters = json.dumps({'name': {'icontains': 'Test Partner'}})
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        # ContactRecordFactory creates 10 partners in setUp
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_foreign_key(self):
        """Test the ability to filter on a model's foreign key fields."""

        PartnerFactory.create_batch(5, name='Test Partner', owner=self.company)

        ContactRecordFactory.create_batch(5,
                                          partner=self.partner,
                                          contact__name='Jane Doe')

        self.client.path += '/partner'
        filters = json.dumps({
            'name': {
                'icontains': 'Test Partner',
            },
            'contactrecord': {
                'contact': {
                    'name': {
                        'icontains': 'Jane Doe'
                    }
                }
            }
        })
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        # We look for distinct records
        self.assertEqual(len(output), 1)

    def test_list_query_params(self):
        """Test that query parameters that are lists are parsed correctly."""

        contacts = ContactFactory.create_batch(10, partner__owner=self.company)
        pks = [contact.pk for contact in contacts[:5]]

        self.client.path += '/partner'
        filters = json.dumps({'contact': {'in': pks}})
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 5)
Beispiel #22
0
class MyJobsHelpersTests(MyJobsBase):
    def setUp(self):
        super(MyJobsHelpersTests, self).setUp()
        self.client = TestClient()

        self.login_params = {'username': '******',
                             'password': '******',
                             'action': 'login'}

    def test_login_dont_remember_me(self):
        # MyJobsBase logs in a user, so we're clearing that session first
        self.client.logout()
        Session.objects.all().delete()
        self.assertEqual(Session.objects.count(), 0)
        self.client.post(reverse('home'),
                         data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        # session.expire_date is tz aware; datetime.datetime.now is naive
        # It probably isn't worth it to bring in pytz just for tests
        now = datetime.datetime.now(session.expire_date.tzinfo)
        diff = session.expire_date - now

        # Due to the delay between the post at the top of this test
        # and reaching this line, this can't be an assertEquals;
        self.assertTrue(880 <= diff.total_seconds() <= 900)

    def test_login_remember_me(self):
        # MyJobsBase logs in a user, so we're clearing that session first
        self.client.logout()
        Session.objects.all().delete()
        self.assertEqual(Session.objects.count(), 0)
        self.login_params['remember_me'] = True
        self.client.post(reverse('home'),
                         data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        weeks = (datetime.datetime.now() + datetime.timedelta(days=14))
        # Session expiration should be two weeks from now - comparing number
        # of days should be good enough
        self.assertEqual(session.expire_date.toordinal(), weeks.toordinal())

    def test_extract_value(self):
        """Tests that the proper values are extracted from an object."""

        class Foo(object):
            value = 'foo'


        class Bar(object):
            value = 'bar'
            foo = Foo()

        foo = Foo()
        bar = Bar()

        # single-level object traversal
        self.assertEqual(extract_value(foo, 'value'), 'foo')
        self.assertEqual(extract_value(foo, 'bar'), None)

        # default values
        self.assertEqual(extract_value(foo, 'bar', default='bar'), 'bar')
        self.assertEqual(extract_value(foo, 'value', default='bar'), 'foo')

        # multiple-level object traversal
        self.assertEqual(extract_value(bar, 'foo', 'value'), 'foo')
        self.assertEqual(extract_value(bar, 'foo', 'buz'), None)
Beispiel #23
0
class MyProfileViewsTests(MyJobsBase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.client = TestClient()
        self.client.login_user(self.user)
        self.name = PrimaryNameFactory(user=self.user)

    def test_edit_profile(self):
        """
        Going to the edit_profile view generates a list of existing profile
        items in the main content section and a list of profile sections that
        don't have data filled out in the sidebar.
        """
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)
        item_id = self.name.id

        # The existing name object should be rendered on the main content
        # section
        self.assertIsNotNone(soup.find('div',
                                       id='name-' + str(item_id) + '-item'))
        # profile-section contains the name of a profile section that has no
        # information filled out yet and shows up in the sidebar
        self.assertTrue(soup.findAll('tr', {'class': 'profile-section'}))

    def test_edit_summary(self):
        """
        See test_edit_profile
        """
        summary = SummaryFactory(user=self.user)
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)

        item = soup.find('div', id='summary-' + str(summary.id) + '-item')
        self.assertIsNotNone(item)

        link = item.find('a').attrs['href']
        resp = self.client.get(link)
        self.assertEqual(resp.status_code, 200)

    def test_handle_form_get_new(self):
        """
        Invoking the handle_form view without an id parameter returns an
        empty form with the correct form id
        """

        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Name'})
        self.assertTemplateUsed(resp, 'myprofile/profile_form.html')
        soup = BeautifulSoup(resp.content)
        self.assertEquals(soup.form.attrs['id'], 'profile-unit-form')
        with self.assertRaises(KeyError):
            soup.find('input', id='id_name-given_name').attrs['value']

    def test_handle_form_get_existing(self):
        """
        Invoking the handle_form view with and id paraemeter returns
        a form filled out with the corresponding profile/ID combination
        """

        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Name', 'id': self.name.id})
        self.assertTemplateUsed(resp, 'myprofile/profile_form.html')
        soup = BeautifulSoup(resp.content)
        self.assertEquals(soup.form.attrs['id'], 'profile-unit-form')
        self.assertEquals(soup.find('input', id='id_name-given_name')
                          .attrs['value'], 'Alice')
        self.assertEquals(soup.find('input', id='id_name-family_name')
                          .attrs['value'], 'Smith')
        self.assertEquals(soup.find('input', id='id_name-primary')
                          .attrs['checked'], 'checked')

    def test_handle_form_post_new_valid(self):
        """
        Invoking the handle_form view as a POST request for a new item
        creates that object in the database and returns the item snippet
        to be rendered on the page.
        """

        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': 'new',
                                      'given_name': 'Susy',
                                      'family_name': 'Smith'})
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(Name.objects.filter(given_name='Susy',
                                             family_name='Smith').count(), 1)

    def test_handle_form_post_invalid(self):
        """
        Invoking the handle_form view as a POST request with an invalid
        form returns the list of form errors.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': 'new',
                                      'given_name': 'Susy'},
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'family_name': [u'This field is required.']})

    def test_handle_form_post_existing_valid(self):
        """
        Invoking the handle_form view as a POST request for an existing
        item updates that item and returns the update item snippet.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': self.name.id,
                                      'given_name': 'Susy',
                                      'family_name': 'Smith'})
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(Name.objects.filter(given_name='Susy',
                                             family_name='Smith').count(), 1)

    def test_handle_form_json_serialize_get(self):
        """When an ajax requests wants to GET json, serialize the form."""
        resp = self.client.get(reverse('handle_form'),
                               HTTP_ACCEPT='application/json',
                               data={'module': 'Name'})
        self.assertEquals(200, resp.status_code)
        self.assertIn('application/json', resp['content-type'])
        data = json.loads(resp.content)
        self.assertEquals(3, len(data['ordered_fields']))
        self.assertIsInstance(data['ordered_fields'], list)
        self.assertEquals(3, len(data['fields']))
        self.assertIsInstance(data['fields'], dict)
        self.assertIsInstance(data['fields']['family_name'], dict)
        self.assertIsInstance(data['fields']['given_name'], dict)
        self.assertIsInstance(data['fields']['primary'], dict)
        self.assertEquals(3, len(data['data']))
        self.assertIsInstance(data['data'], dict)

    def test_handle_form_redirect_summary(self):
        """
        When a user has a summary already if they try to make a new summary
        handle form should redirect the user to edit the summary they already
        have. User is only allowed one summary per account.
        """
        summary_instance = SummaryFactory(user=self.user)
        summary_instance.save()
        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Summary'})
        self.assertRedirects(resp, reverse(
            'handle_form')+'?id=%s&module=Summary' % summary_instance.id)

    def test_delete_item(self):
        """
        Invoking the delete_item view deletes the item and returns
        the 'Deleted!' HttpResponse
        """

        resp = self.client.post(reverse('delete_item')+'?item='+str(self.name.id))

        self.assertEqual(resp.content, '')
        self.assertEqual(Name.objects.filter(id=self.name.id).count(), 0)

    def test_add_duplicate_primary_email(self):
        """
        Attempting to add a secondary email with a value equal to the user's
        current primary email results in an error.

        Due to how the instance is constructed, this validation is form-level
        rather than model-level.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'SecondaryEmail',
                                      'id': 'new',
                                      'email': self.user.email},
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertEqual(json.loads(resp.content),
                         {u'email': [u'This email is already registered.']})

    def test_default_country_changes(self):
        """
        The displayed country when editing an address should update to reflect
        the chosen country.
        """
        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Address'})
        content = BeautifulSoup(resp.content)

        selected = content.find('option', attrs={'selected': True})
        self.assertEqual(selected.attrs['value'], 'USA')

        address = AddressFactory(user=self.user, country_code='AFG')

        resp = self.client.get(reverse('handle_form'),
                               data={'module': 'Address',
                                     'id': address.id})
        content = BeautifulSoup(resp.content)
        selected = content.find('option', attrs={'selected': True})
        self.assertEqual(selected.attrs['value'], 'AFG')
Beispiel #24
0
class RegistrationViewTests(MyJobsBase):
    """
    Test the registration views.

    """

    def setUp(self):
        """
        These tests use the default backend, since we know it's
        available; that needs to have ``ACCOUNT_ACTIVATION_DAYS`` set.

        """
        super(RegistrationViewTests, self).setUp()
        self.client = TestClient()
        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
        if self.old_activation is None:
            settings.ACCOUNT_ACTIVATION_DAYS = 7  # pragma: no cover

        self.data = {'email': '*****@*****.**',
                     'password1': 'swordfish',
                     'send_email': True}
        self.user, _ = User.objects.create_user(**self.data)

        # Update the only existing site so we're working with
        # my.jobs for historical/aesthetic purposes.
        site = SeoSite.objects.get()
        site.domain = 'my.jobs'
        site.save()

    def test_valid_activation(self):
        """
        Test that the ``activate`` view properly handles a valid
        activation (in this case, based on the default backend's
        activation window).

        """
        self.client.login_user(self.user)
        profile = ActivationProfile.objects.get(user__email=self.user.email)
        response = self.client.get(reverse('registration_activate',
                                           args=[profile.activation_key]))
        self.assertEqual(response.status_code, 200)
        self.failUnless(User.objects.get(email=self.user.email).is_active)

    def test_anonymous_activation(self):
        """
        Test that the ``activate`` view properly handles activation
        when the user to be activated is not currently logged in. The
        page should also contain a login link.
        """
        self.client.post(reverse('auth_logout'))
        profile = ActivationProfile.objects.get(user__email=self.user.email)
        response = self.client.get(reverse('registration_activate',
                                           args=[profile.activation_key]) +
                                   '?verify=%s' % self.user.user_guid)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, self.data['email'])

        contents = BeautifulSoup(response.content)
        bank = contents.find(id='moduleBank')
        anchors = bank.findAll('a')
        self.assertEqual(len(anchors), 1)
        self.assertEqual(anchors[0].attrs['href'], '/')
        self.assertEqual(anchors[0].text, 'Log In')

    def test_invalid_activation(self):
        """
        Test that the ``activate`` view properly handles an invalid
        activation (in this case, based on the default backend's
        activation window).

        """
        self.client.login_user(self.user)
        expired_profile = ActivationProfile.objects.get(user=self.user)
        expired_profile.sent -= datetime.timedelta(
            days=settings.ACCOUNT_ACTIVATION_DAYS)
        expired_profile.save()
        response = self.client.get(reverse('registration_activate',
                                           args=[expired_profile.activation_key]))
        self.assertEqual(response.status_code, 200)
        self.assertNotEqual(response.context['activated'],
                            expired_profile.activation_key_expired())
        self.failIf(User.objects.get(email=self.user.email).is_verified)

    def test_resend_activation(self):
        x, created = User.objects.create_user(
            **{'email': '*****@*****.**', 'password1': '5UuYquA@'})
        self.client.login_user(x)
        self.assertEqual(len(mail.outbox), 1)
        resp = self.client.get(reverse('resend_activation'))
        self.assertEqual(resp.status_code, 200)
        # one email sent for creating a user, another one for resend
        self.assertEqual(len(mail.outbox), 2)

    def test_resend_activation_with_secondary_emails(self):
        user, _ = User.objects.create_user(
            email='*****@*****.**', password1='5UuYquA@',
            create_user=True)
        self.assertEqual(ActivationProfile.objects.count(), 1)

        self.client.login_user(user)
        self.client.get(reverse('resend_activation'))
        self.assertEqual(len(mail.outbox), 2)

        SecondaryEmail.objects.create(user=user, email='*****@*****.**')
        self.assertEqual(len(mail.outbox), 3)
        self.assertEqual(ActivationProfile.objects.count(), 2)
        self.client.get(reverse('resend_activation'))
        self.assertEqual(len(mail.outbox), 4)

    def test_site_name_in_password_reset_email(self):
        domain = settings.SITE.domain.lower()
        mail.outbox = []
        self.user.is_active = True
        self.user.save()
        self.client.post(reverse('password_reset'),
                         data={'email': self.user.email})
        self.assertEqual(len(mail.outbox), 1,
                         [msg.subject for msg in mail.outbox])
        msg = mail.outbox[0]
        self.assertEqual(msg.subject, "Password Reset on {0}".format(domain))
        self.assertIn("The {0} Team".format(domain.lower()), msg.body)
        self.assertIn("user account at {0}.".format(domain.lower()), msg.body)

    def test_inactive_user_requesting_password_reset(self):
        """
        Requesting a password reset as an inactive user should activate the
        account, allowing the password reset to proceed.
        """
        self.user.is_active = False
        self.user.save()

        mail.outbox = []
        self.client.post(reverse('password_reset'), {'email': self.user.email})
        self.assertEqual(len(mail.outbox), 1)

        user = User.objects.get(pk=self.user.pk)
        self.assertFalse(user.is_active)

    def test_invitation_asks_for_password_change(self):
        """
        When activating an account via an invitation, the user should still be
        prompted to change their password.
        """
        invitation = InvitationFactory(inviting_user=self.user)
        key = invitation.invitee.activationprofile_set.first().activation_key
        response = self.client.get(
            reverse('invitation_activate', kwargs={'activation_key': key}),
            data={'verify-email': invitation.invitee_email})

        invitee = User.objects.get(pk=invitation.invitee.pk)

        self.assertTrue(invitee.password_change)

    def test_accept_invitation_already_activated(self):
        """
        Since invitations use the same keys as activations, we should ensure
        that invitation acceptance doesn't show an error message when the link
        has already been used.
        """
        invitation = InvitationFactory(invitee_email=self.user.email)
        self.assertFalse(invitation.accepted)
        profile = self.user.activationprofile_set.all()[0]
        key = profile.activation_key
        self.user.in_reserve = True
        self.user.save()

        # Quickly activate and ensure that activation was successful
        self.assertEqual(ActivationProfile.objects.activate_user(key),
                         self.user)

        self.client.login_user(self.user)
        response = self.client.get(reverse('invitation_activate', args=[key]))
        self.assertTrue('Thanks for registering!' in response.content)
        invitation = Invitation.objects.get()
        self.assertTrue(invitation.accepted)
        user = User.objects.get(pk=self.user.pk)
        self.assertFalse(user.in_reserve)
Beispiel #25
0
class TestRegenerate(MyReportsTestCase):
    """Tests the reports can be regenerated."""
    def setUp(self):
        super(TestRegenerate, self).setUp()
        self.client = TestClient(path=reverse('reports',
                                              kwargs={
                                                  'app': 'mypartners',
                                                  'model': 'contactrecord'
                                              }))
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(10, partner__owner=self.company)

    def test_regenerate(self):
        # create a new report
        response = self.client.post(path=reverse('reports',
                                                 kwargs={
                                                     'app': 'mypartners',
                                                     'model': 'contactrecord'
                                                 }))

        report_name = response.content
        report = Report.objects.get(name=report_name)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # remove report results and ensure we can still get a reasonable
        # response
        report.results.delete()
        report.save()
        self.assertFalse(report.results)

        response = self.client.get(data={'id': report.id})
        self.assertEqual(response.status_code, 200)

        # regenerate results and ensure they are the same as the original
        response = self.client.get(path=reverse('regenerate'),
                                   data={'id': report.pk})
        report = Report.objects.get(name=report_name)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(report.results)

        # regenerate report without deleting the report prior
        # see if it overwrites other report.
        results = report.results
        response = self.client.get(path=reverse('regenerate'),
                                   data={'id': report.pk})
        report = Report.objects.get(name=report_name)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(results.name, report.results.name)

    def test_regenerating_missing_file(self):
        """Tests that a report can be regenerated when file is missing."""

        # create a new report
        response = self.client.post(path=reverse('reports',
                                                 kwargs={
                                                     'app': 'mypartners',
                                                     'model': 'contactrecord'
                                                 }))

        report_name = response.content
        report = Report.objects.get(name=report_name)

        # report should have results
        self.assertTrue(report.results)

        # delete physical file and ensure that json reflects the missing link
        os.remove(report.results.file.name)
        report = Report.objects.get(pk=report.pk)
        self.assertEqual(report.json, u'{}')
        self.assertEqual(report.python, {})

        # regenerate the report even though the file is physically missing
        report.regenerate()
        self.assertTrue(report.results)
Beispiel #26
0
class MyJobsHelpersTests(MyJobsBase):
    def setUp(self):
        super(MyJobsHelpersTests, self).setUp()
        self.client = TestClient()

        self.login_params = {
            'username': '******',
            'password': '******',
            'action': 'login'
        }

    def test_login_dont_remember_me(self):
        # MyJobsBase logs in a user, so we're clearing that session first
        self.client.logout()
        Session.objects.all().delete()
        self.assertEqual(Session.objects.count(), 0)
        self.client.post(reverse('home'), data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        # session.expire_date is tz aware; datetime.datetime.now is naive
        # It probably isn't worth it to bring in pytz just for tests
        now = datetime.datetime.now(session.expire_date.tzinfo)
        diff = session.expire_date - now

        # Due to the delay between the post at the top of this test
        # and reaching this line, this can't be an assertEquals;
        self.assertTrue(880 <= diff.total_seconds() <= 900)

    def test_login_remember_me(self):
        # MyJobsBase logs in a user, so we're clearing that session first
        self.client.logout()
        Session.objects.all().delete()
        self.assertEqual(Session.objects.count(), 0)
        self.login_params['remember_me'] = True
        self.client.post(reverse('home'), data=self.login_params)
        self.assertEqual(Session.objects.count(), 1)

        session = Session.objects.all()[0]

        session_dict = session.get_decoded()
        user_id = session_dict['_auth_user_id']
        self.assertEqual(user_id, self.user.id)

        weeks = (datetime.datetime.now() + datetime.timedelta(days=14))
        # Session expiration should be two weeks from now - comparing number
        # of days should be good enough
        self.assertEqual(session.expire_date.toordinal(), weeks.toordinal())

    def test_extract_value(self):
        """Tests that the proper values are extracted from an object."""
        class Foo(object):
            value = 'foo'

        class Bar(object):
            value = 'bar'
            foo = Foo()

        foo = Foo()
        bar = Bar()

        # single-level object traversal
        self.assertEqual(extract_value(foo, 'value'), 'foo')
        self.assertEqual(extract_value(foo, 'bar'), None)

        # default values
        self.assertEqual(extract_value(foo, 'bar', default='bar'), 'bar')
        self.assertEqual(extract_value(foo, 'value', default='bar'), 'foo')

        # multiple-level object traversal
        self.assertEqual(extract_value(bar, 'foo', 'value'), 'foo')
        self.assertEqual(extract_value(bar, 'foo', 'buz'), None)
Beispiel #27
0
class TestViewRecords(MyReportsTestCase):
    """
    Tests the `view_records` view which is used to query various models.
    """

    def setUp(self):
        super(TestViewRecords, self).setUp()
        self.client = TestClient(path='/reports/ajax/mypartners',
                                 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.client.login_user(self.user)

        ContactRecordFactory.create_batch(
            10, partner=self.partner, contact__name='Joe Shmoe')

    def test_restricted_to_ajax(self):
        """View should only be reachable through AJAX."""

        self.client.path += '/partner'
        self.client.defaults.pop('HTTP_X_REQUESTED_WITH')
        response = self.client.post()

        self.assertEqual(response.status_code, 404)

    def test_restricted_to_post(self):
        """POST requests should raise a 404."""

        self.client.path += '/partner'
        response = self.client.get()

        self.assertEqual(response.status_code, 404)

    def test_json_output(self):
        """Test that filtering contact records through ajax works properly."""

        # records to be filtered out
        ContactRecordFactory.create_batch(10, contact__name='John Doe')

        self.client.path += '/contactrecord'
        filters = json.dumps({
            'contact': {
                'name': {
                    'icontains': 'Joe Shmoe'
                }
            }
        })
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_only_user_results_returned(self):
        """Results should only contain records user has access to."""

        # records not owned by user
        partner = PartnerFactory(name="Wrong Partner")
        ContactRecordFactory.create_batch(10, partner=partner)

        self.client.path += '/contactrecord'
        response = self.client.post()
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_model(self):
        """Test the ability to filter on a model's field's."""

        # we already have one because of self.partner
        PartnerFactory.create_batch(9, name='Test Partner', owner=self.company)

        self.client.path += '/partner'
        filters = json.dumps({
            'name': {
                'icontains': 'Test Partner'
            }
        })
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        # ContactRecordFactory creates 10 partners in setUp
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 10)

    def test_filtering_on_foreign_key(self):
        """Test the ability to filter on a model's foreign key fields."""

        PartnerFactory.create_batch(5, name='Test Partner', owner=self.company)

        ContactRecordFactory.create_batch(
            5, partner=self.partner, contact__name='Jane Doe')


        self.client.path += '/partner'
        filters = json.dumps({
            'name': {
                'icontains': 'Test Partner',
            },
            'contactrecord': {
                'contact': {
                    'name': {
                        'icontains': 'Jane Doe'
                    }
                }
            }
        })
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        # We look for distinct records
        self.assertEqual(len(output), 1)


    def test_list_query_params(self):
        """Test that query parameters that are lists are parsed correctly."""

        contacts = ContactFactory.create_batch(10, partner__owner=self.company)
        pks = [contact.pk for contact in contacts[:5]]

        self.client.path += '/partner'
        filters = json.dumps({
            'contact': {
                'in': pks
            }
        })
        response = self.client.post(data={'filters': filters})
        output = json.loads(response.content)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(output), 5)
Beispiel #28
0
class MyProfileViewsTests(MyJobsBase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.client = TestClient()
        self.client.login_user(self.user)
        self.name = PrimaryNameFactory(user=self.user)


    def test_edit_profile(self):
        """
        Going to the edit_profile view generates a list of existing profile
        items in the main content section and a list of profile sections that
        don't have data filled out in the sidebar.
        """
        resp = self.client.get(reverse('view_profile'))

        soup = BeautifulSoup(resp.content)
        item = soup.find('div', id='profileTitleBar')

        # Page should have fake user's email as title
        self.assertIsNotNone(soup.find_all('h3', text="*****@*****.**"))

        # The only module that is complete at this point is 'Name'. So there
        # should only be one module displayed in the moduleColumn div
        self.assertEquals(1, len(soup.findAll("div", { "class" : "card-wrapper" })))

        # The 'Add a New Section' section should have many items
        # Check for each one
        self.assertEquals(10, len(soup.findAll("tr", { "class" : "profile-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Education-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Address-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Telephone-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Employment History-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Secondary Email-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Military Service-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Website-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "License-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Summary-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Volunteer History-new-section" })))
        self.assertEquals(1, len(soup.findAll("a", { "id" : "Summary-new-section" })))


    def test_handle_form_post_new_valid(self):
        """
        Invoking the handle_form view as a POST request for a new item
        creates that object in the database and returns the item snippet
        to be rendered on the page.
        """

        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': 'new',
                                      'given_name': 'Susy',
                                      'family_name': 'Smith'})
        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(Name.objects.filter(given_name='Susy',
                                             family_name='Smith').count(), 1)


    def test_delete_item(self):
        """
        Invoking the delete_item view deletes the item and returns
        the 'Deleted!' HttpResponse
        """

        resp = self.client.post(reverse('delete_item')+'?item='+str(self.name.id))

        self.assertEqual(resp.content, '')
        self.assertEqual(Name.objects.filter(id=self.name.id).count(), 0)


    def test_edit_summary(self):
        """
        See test_edit_profile
        """
        summary = SummaryFactory(user=self.user)
        resp = self.client.get(reverse('view_profile'))
        soup = BeautifulSoup(resp.content)

        item = soup.find('div', id='summary-' + str(summary.id) + '-item')
        self.assertIsNotNone(item)

        link = item.find('a').attrs['href']
        resp = self.client.get(link)
        self.assertEqual(resp.status_code, 200)


    def test_handle_form_post_invalid(self):
        """
        Invoking the handle_form view as a POST request with an invalid
        form returns the list of form errors.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': 'new',
                                      'given_name': 'Susy'},
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'family_name': [u'This field is required.']})

        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': 'new',
                                      'family_name': 'Smithers'},
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'given_name': [u'This field is required.']})


    def test_handle_form_post_existing_valid(self):
        """
        Invoking the handle_form view as a POST request for an existing
        item updates that item and returns the update item snippet.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'Name', 'id': self.name.id,
                                      'given_name': 'Susy',
                                      'family_name': 'Smith'})

        self.assertRedirects(resp, reverse('view_profile'))
        self.assertEqual(Name.objects.filter(given_name='Susy',
                                             family_name='Smith').count(), 1)


    def test_handle_form_json_serialize_get(self):
        """When an ajax requests wants to GET json, serialize the form."""
        resp = self.client.get(reverse('handle_form'),
                               HTTP_ACCEPT='application/json',
                               data={'module': 'Name'})
        self.assertEquals(200, resp.status_code)
        self.assertIn('application/json', resp['content-type'])
        data = json.loads(resp.content)
        self.assertEquals(3, len(data['ordered_fields']))
        self.assertIsInstance(data['ordered_fields'], list)
        self.assertEquals(3, len(data['fields']))
        self.assertIsInstance(data['fields'], dict)
        self.assertIsInstance(data['fields']['family_name'], dict)
        self.assertIsInstance(data['fields']['given_name'], dict)
        self.assertIsInstance(data['fields']['primary'], dict)
        self.assertEquals(3, len(data['data']))
        self.assertIsInstance(data['data'], dict)


    def test_add_duplicate_primary_email(self):
        """
        Attempting to add a secondary email with a value equal to the user's
        current primary email results in an error.

        Due to how the instance is constructed, this validation is form-level
        rather than model-level.
        """
        resp = self.client.post(reverse('handle_form'),
                                data={'module': 'SecondaryEmail',
                                      'id': 'new',
                                      'email': self.user.email},
                                HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        self.assertEqual(json.loads(resp.content),
                         {u'email': [u'This email is already registered.']})