Exemplo n.º 1
0
    def test_not_disabled(self):
        """
        An anonymous user who provides the :verify-email: query string or
        user with is_disabled set to True should be redirected to the home
        page. An anonymous user who does not should see a 404. A user with
        is_active set to False should proceed to their destination.
        """
        client = TestClient()
        user = UserFactory()

        #Anonymous user
        resp = client.get(reverse('view_profile'))
        path = resp.request.get('PATH_INFO')
        self.assertRedirects(resp, reverse('home') + '?next=' + path)

        # This is ugly, but it is an artifact of the way Django redirects
        # users who fail the `user_passes_test` decorator.
        qs = '?verify-email=%s' % user.email
        next_qs = '?next=' + urlquote('/profile/view/%s' % qs)

        # Anonymous user navigates to url with :verify-email: in query string
        resp = client.get(reverse('view_profile') + qs)
        # Old path + qs is urlquoted and added to the url as the :next: param
        self.assertRedirects(resp, "http://testserver/" + next_qs)

        # Active user
        client.login_user(user)
        resp = client.get(reverse('view_profile'))
        self.assertTrue(resp.status_code, 200)

        #Disabled user
        user.is_disabled = True
        user.save()
        resp = client.get(reverse('view_profile'))
        self.assertRedirects(resp, "http://testserver/?next=/profile/view/")
Exemplo n.º 2
0
    def test_not_disabled(self):
        """
        An anonymous user who provides the :verify-email: query string or
        user with is_disabled set to True should be redirected to the home
        page. An anonymous user who does not should see a 404. A user with
        is_active set to False should proceed to their destination.
        """
        client = TestClient()
        user = UserFactory()

        #Anonymous user
        resp = client.get(reverse('view_profile'))
        path = resp.request.get('PATH_INFO')
        self.assertRedirects(resp, reverse('home')+'?next='+path)

        # This is ugly, but it is an artifact of the way Django redirects
        # users who fail the `user_passes_test` decorator.
        qs = '?verify-email=%s' % user.email
        next_qs = '?next=' + urlquote('/profile/view/%s' % qs)

        # Anonymous user navigates to url with :verify-email: in query string
        resp = client.get(reverse('view_profile') + qs)
        # Old path + qs is urlquoted and added to the url as the :next: param
        self.assertRedirects(resp, "http://testserver/" + next_qs)

        # Active user
        client.login_user(user)
        resp = client.get(reverse('view_profile'))
        self.assertTrue(resp.status_code, 200)

        #Disabled user
        user.is_disabled = True
        user.save()
        resp = client.get(reverse('view_profile'))
        self.assertRedirects(resp, "http://testserver/?next=/profile/view/")
Exemplo n.º 3
0
class MessageViewTests(TestCase):
    def setUp(self):
        self.user = UserFactory()
        self.message = Message(subject='subject',
                               body='body',
                               message_type='success')
        self.message.save()
        for group in Group.objects.all():
            self.message.group.add(group.pk)
        self.message.save()
        self.messageInfo = MessageInfo(user=User.objects.get(id=1),
                                       message=self.message)
        self.messageInfo.save()
        self.client = TestClient()
        self.client.login_user(self.user)

    def test_user_post_mark_message_read(self):
        resp = self.client.post(reverse('read'),
                                data={
                                    'name':
                                    'message-' + str(self.message.id) + '-' +
                                    str(self.user.id)
                                },
                                follow=True)
        m = MessageInfo.objects.get(user=self.user, message=self.message)
        self.assertTrue(m.read)
        self.assertTrue(m.read_at)
Exemplo n.º 4
0
    def test_is_active(self):
        """
        A user with is_active set to False should be redirected to the home
        page, while a user with is_active set to True should proceed to their
        destination.
        """
        client = TestClient()
        user = UserFactory()
        quoted_email = urllib.quote(user.email)

        # Active user
        client.login_user(user)
        resp = client.get(reverse('saved_search_main'))
        self.assertTrue(resp.status_code, 200)

        # Inactive user
        user.is_active = False
        user.save()
        resp = client.get(reverse('saved_search_main'))
        self.assertRedirects(resp, "http://testserver/?next=/saved-search/view/")
Exemplo n.º 5
0
    def test_is_active(self):
        """
        A user with is_active set to False should be redirected to the home
        page, while a user with is_active set to True should proceed to their
        destination.
        """
        client = TestClient()
        user = UserFactory()
        quoted_email = urllib.quote(user.email)

        # Active user
        client.login_user(user)
        resp = client.get(reverse('saved_search_main'))
        self.assertTrue(resp.status_code, 200)

        # Inactive user
        user.is_active = False
        user.save()
        resp = client.get(reverse('saved_search_main'))
        self.assertRedirects(resp,
                             "http://testserver/?next=/saved-search/view/")
Exemplo n.º 6
0
class MessageViewTests(TestCase):
    def setUp(self):
        self.user = UserFactory()
        self.message = Message(subject='subject',
                               body='body',
                               message_type='success')
        self.message.save()
        for group in Group.objects.all():
            self.message.group.add(group.pk)
        self.message.save()
        self.messageInfo = MessageInfo(user=User.objects.get(id=1),
                                       message=self.message)
        self.messageInfo.save()
        self.client = TestClient()
        self.client.login_user(self.user)

    def test_user_post_mark_message_read(self):
        resp = self.client.post(reverse('read'),
                                data={'name': 'message-'+str(self.message.id)
                                              + '-'+str(self.user.id)},
                                follow=True)
        m = MessageInfo.objects.get(user=self.user, message=self.message)
        self.assertTrue(m.read)
        self.assertTrue(m.read_at)
Exemplo n.º 7
0
class MyProfileViewsTests(TestCase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.user = UserFactory()
        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 = Name.objects.all()[0].id

        # The existing name object should be rendered on the main content
        # section
        self.assertIsNotNone(soup.find('tr',
                                       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_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.']})
Exemplo n.º 8
0
class AccountFormTests(TestCase):
    def setUp(self):
        self.user = UserFactory()
        self.name = PrimaryNameFactory(user=self.user)
        self.client = TestClient()
        
    def test_password_form(self):
        invalid_data = [
            { 'data': {'password': '******',
                       'new_password1': 'newpassword',
                       'new_password2': 'newpassword'},
              u'errors': [['password', [u"Wrong password."]]]},
            { 'data': {'password': '******',
                       'new_password1': 'newpassword',
                       'new_password2': 'notnewpassword'},
                u'errors':
                    [[u'new_password2', [u'The new password fields did not match.']],
                    [u'new_password1', [u'The new password fields did not match.']]],
            
            },
        ]

        for item in invalid_data:
            form = ChangePasswordForm(user=self.user, data=item['data'])
            self.failIf(form.is_valid())
            self.assertEqual(form.errors[item[u'errors'][0][0]],
                             item[u'errors'][0][1])

        form = ChangePasswordForm(user=self.user,data={'password': '******',
                                                       'new_password1': 'anothersecret',
                                                       'new_password2': 'anothersecret'})
        
        self.failUnless(form.is_valid())
        form.save()
        self.failUnless(self.user.check_password('anothersecret'))

    def test_no_name_account_form(self):
        """
        Leaving both the first and last name fields blank produces a valid save.
        It also deletes the primary name object from the Name model.
        """
        data = {"gravatar": "*****@*****.**", "user": self.user}
        form = EditAccountForm(data, **{'user':self.user})
        self.assertTrue(form.is_valid())
        form.save(self.user)
        self.assertEqual(Name.objects.count(), 0) 

    def test_both_names_account_form(self):
        """
        Filling out both name fields produces a valid save.
        """
        
        data = {"given_name": "Alicia", "family_name": "Smith",
                "gravatar": "*****@*****.**"}
        form = EditAccountForm(data, **{'user':self.user})
        self.assertTrue(form.is_valid())

    def test_partial_name_account_form(self):
        """
        Filling out only the first name or only the last name produces an error.
        """
        data = {"given_name": "Alicia", "gravatar": "*****@*****.**",
                "user": self.user}
        form = EditAccountForm(data, **{'user':self.user})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.errors['family_name'][0],
                         "Both a first and last name required.")

    def test_gravatar_email_list(self):
        """
        Dropdowns for selecting the user's preferred Gravatar email should be
        the only dropdowns that include "Do not use Gravatar" as an option -
        others should default to the user's primary email address.
        """
        self.client.login_user(self.user)
        response = self.client.get(reverse('edit_communication'))
        soup = BeautifulSoup(response.content)
        options = soup.select('#id_digest_email option')
        self.assertEqual(len(options), 1)
        self.assertTrue(self.user.gravatar in options[0])

        response = self.client.get(reverse('edit_basic'))
        soup = BeautifulSoup(response.content)
        options = soup.select('#id_gravatar option')
        self.assertEqual(len(options), 2)
        self.assertTrue('Do not use Gravatar' in options[0])
        self.assertTrue(self.user.gravatar in options[1])
Exemplo n.º 9
0
class RegistrationViewTests(TestCase):
    """
    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',
                     'password2': 'swordfish',
                     'action': 'register'}
        self.client.post(reverse('home'), data=self.data)
        self.user = User.objects.get(email=self.data['email'])

    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).

        """
        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.
        """
        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-email=%s' % self.user.email)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, self.data['email'])

    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).

        """
        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_active)

    def test_resend_activation(self):
        x, created = User.objects.create_inactive_user(
            **{'email': '*****@*****.**', 'password1': 'secret'})
        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 an inactive user, another one for resend
        self.assertEqual(len(mail.outbox), 2)

    def test_resend_activation_with_secondary_emails(self):
        user, created = User.objects.create_inactive_user(
            **{'email': '*****@*****.**', 'password1': 'secret'})
        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)
Exemplo n.º 10
0
class MyProfileViewsTests(TestCase):
    def setUp(self):
        super(MyProfileViewsTests, self).setUp()
        self.user = UserFactory()
        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 = Name.objects.all()[0].id

        # The existing name object should be rendered on the main content
        # section
        self.assertIsNotNone(
            soup.find('tr', 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_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.']})
Exemplo n.º 11
0
class MySignOn(TestCase):
    def setUp(self):
        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)
Exemplo n.º 12
0
class RegistrationViewTests(TestCase):
    """
    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',
            'password2': 'swordfish',
            'action': 'register'
        }
        self.client.post(reverse('home'), data=self.data)
        self.user = User.objects.get(email=self.data['email'])

    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).

        """
        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.
        """
        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-email=%s' % self.user.email)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, self.data['email'])

    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).

        """
        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_active)

    def test_resend_activation(self):
        x, created = User.objects.create_inactive_user(**{
            'email': '*****@*****.**',
            'password1': 'secret'
        })
        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 an inactive user, another one for resend
        self.assertEqual(len(mail.outbox), 2)

    def test_resend_activation_with_secondary_emails(self):
        user, created = User.objects.create_inactive_user(**{
            'email': '*****@*****.**',
            'password1': 'secret'
        })
        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)
Exemplo n.º 13
0
class MyDashboardViewsTests(TestCase):
    def setUp(self):
        self.staff_user = UserFactory()
        group = Group.objects.get(name=CompanyUser.GROUP_NAME)
        self.staff_user.groups.add(group)
        self.staff_user.save()

        self.company = CompanyFactory()
        self.company.save()
        self.admin = CompanyUserFactory(user=self.staff_user,
                                        company=self.company)
        self.admin.save()
        self.microsite = MicrositeFactory(company=self.company)
        self.microsite.save()

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

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

        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,
                                   label='%s Jobs' % search)

    def test_number_of_searches_and_users_is_correct(self):
        response = self.client.post(
            reverse('dashboard')+'?company='+str(self.company.id),
            {'microsite': 'test.jobs'})
        soup = BeautifulSoup(response.content)
        # 10 searches total, two rows per search
        self.assertEqual(len(soup.select('#row-link-table tr')), 20)

        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'})
        soup = BeautifulSoup(response.content)
        self.assertEqual(len(soup.select('#row-link-table tr')), 20)

    # 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_pdf(self):
        response = self.client.post(
            reverse('export_candidates')+'?company=' +
            str(self.company.id)+'&ex-t=pdf')
        self.assertTrue(response.content.index('PDF'))
        self.assertEqual(response.templates[0].name,
                         'mydashboard/export/candidate_listing.html')
        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)
Exemplo n.º 14
0
class MySearchViewTests(TestCase):
    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',
            '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.r = Replacer()
        self.r.replace('urllib2.urlopen', return_file)

    def tearDown(self):
        self.r.restore()

    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_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.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.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 = {'rss_url': 'http://www.my.jobs/jobs/feed/rss',
                'feed_title': 'Jobs',
                'url_status': 'valid'}
        self.assertEqual(json.loads(response.content), data)

        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-email=%s' % (
                search.id, self.user.email))
        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.title())))

    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-email=%s' % (
                search.id, self.user.email))
        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.title())))
Exemplo n.º 15
0
class AccountFormTests(TestCase):
    def setUp(self):
        self.user = UserFactory()
        self.name = PrimaryNameFactory(user=self.user)
        self.client = TestClient()

    def test_password_form(self):
        invalid_data = [
            {
                'data': {
                    'password': '******',
                    'new_password1': 'newpassword',
                    'new_password2': 'newpassword'
                },
                u'errors': [['password', [u"Wrong password."]]]
            },
            {
                'data': {
                    'password': '******',
                    'new_password1': 'newpassword',
                    'new_password2': 'notnewpassword'
                },
                u'errors': [[
                    u'new_password2',
                    [u'The new password fields did not match.']
                ],
                            [
                                u'new_password1',
                                [u'The new password fields did not match.']
                            ]],
            },
        ]

        for item in invalid_data:
            form = ChangePasswordForm(user=self.user, data=item['data'])
            self.failIf(form.is_valid())
            self.assertEqual(form.errors[item[u'errors'][0][0]],
                             item[u'errors'][0][1])

        form = ChangePasswordForm(user=self.user,
                                  data={
                                      'password': '******',
                                      'new_password1': 'anothersecret',
                                      'new_password2': 'anothersecret'
                                  })

        self.failUnless(form.is_valid())
        form.save()
        self.failUnless(self.user.check_password('anothersecret'))

    def test_no_name_account_form(self):
        """
        Leaving both the first and last name fields blank produces a valid save.
        It also deletes the primary name object from the Name model.
        """
        data = {"gravatar": "*****@*****.**", "user": self.user}
        form = EditAccountForm(data, **{'user': self.user})
        self.assertTrue(form.is_valid())
        form.save(self.user)
        self.assertEqual(Name.objects.count(), 0)

    def test_both_names_account_form(self):
        """
        Filling out both name fields produces a valid save.
        """

        data = {
            "given_name": "Alicia",
            "family_name": "Smith",
            "gravatar": "*****@*****.**"
        }
        form = EditAccountForm(data, **{'user': self.user})
        self.assertTrue(form.is_valid())

    def test_partial_name_account_form(self):
        """
        Filling out only the first name or only the last name produces an error.
        """
        data = {
            "given_name": "Alicia",
            "gravatar": "*****@*****.**",
            "user": self.user
        }
        form = EditAccountForm(data, **{'user': self.user})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.errors['family_name'][0],
                         "Both a first and last name required.")

    def test_gravatar_email_list(self):
        """
        Dropdowns for selecting the user's preferred Gravatar email should be
        the only dropdowns that include "Do not use Gravatar" as an option -
        others should default to the user's primary email address.
        """
        self.client.login_user(self.user)
        response = self.client.get(reverse('edit_communication'))
        soup = BeautifulSoup(response.content)
        options = soup.select('#id_digest_email option')
        self.assertEqual(len(options), 1)
        self.assertTrue(self.user.gravatar in options[0])

        response = self.client.get(reverse('edit_basic'))
        soup = BeautifulSoup(response.content)
        options = soup.select('#id_gravatar option')
        self.assertEqual(len(options), 2)
        self.assertTrue('Do not use Gravatar' in options[0])
        self.assertTrue(self.user.gravatar in options[1])
Exemplo n.º 16
0
class MyDashboardViewsTests(TestCase):
    def setUp(self):
        self.staff_user = UserFactory()
        group = Group.objects.get(name=CompanyUser.GROUP_NAME)
        self.staff_user.groups.add(group)
        self.staff_user.save()

        self.company = CompanyFactory()
        self.company.save()
        self.admin = CompanyUserFactory(user=self.staff_user,
                                        company=self.company)
        self.admin.save()
        self.microsite = MicrositeFactory(company=self.company)
        self.microsite.save()

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

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

        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,
                                   label='%s Jobs' % search)

    def test_number_of_searches_and_users_is_correct(self):
        response = self.client.post(
            reverse('dashboard') + '?company=' + str(self.company.id),
            {'microsite': 'test.jobs'})
        soup = BeautifulSoup(response.content)
        # 10 searches total, two rows per search
        self.assertEqual(len(soup.select('#row-link-table tr')), 20)

        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'})
        soup = BeautifulSoup(response.content)
        self.assertEqual(len(soup.select('#row-link-table tr')), 20)

    # 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_pdf(self):
        response = self.client.post(
            reverse('export_candidates') + '?company=' + str(self.company.id) +
            '&ex-t=pdf')
        self.assertTrue(response.content.index('PDF'))
        self.assertEqual(response.templates[0].name,
                         'mydashboard/export/candidate_listing.html')
        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)