Commit f03841a6 by Andy Armstrong

Add client-side events for viewing pages

TNL-1504
parent c3a39934
......@@ -277,8 +277,7 @@ class EventsTestMixin(object):
def setUp(self):
super(EventsTestMixin, self).setUp()
self.event_collection = MongoClient()["test"]["events"]
self.event_collection.drop()
self.start_time = datetime.now()
self.reset_event_tracking()
def assert_event_emitted_num_times(self, event_name, event_time, event_user_id, num_times_emitted):
"""
......@@ -298,6 +297,43 @@ class EventsTestMixin(object):
).count(), num_times_emitted
)
def reset_event_tracking(self):
"""
Resets all event tracking so that previously captured events are removed.
"""
self.event_collection.drop()
self.start_time = datetime.now()
def get_matching_events(self, event_type):
"""
Returns a cursor for the matching browser events.
"""
return self.event_collection.find({
"event_type": event_type,
"time": {"$gt": self.start_time},
})
def verify_events_of_type(self, event_type, expected_events):
"""Verify that the expected events of a given type were logged.
Args:
event_type (str): The type of event to be verified.
expected_events (list): A list of dicts representing the events that should
have been fired.
"""
EmptyPromise(
lambda: self.get_matching_events(event_type).count() >= len(expected_events),
"Waiting for the minimum number of events of type {type} to have been recorded".format(type=event_type)
).fulfill()
# Verify that the correct events were fired
cursor = self.get_matching_events(event_type)
actual_events = []
for i in range(0, cursor.count()):
raw_event = cursor.next()
actual_events.append(json.loads(raw_event["event"]))
self.assertEqual(expected_events, actual_events)
class UniqueCourseTest(WebAppTest):
"""
......
......@@ -10,13 +10,14 @@ from ...pages.lms.account_settings import AccountSettingsPage
from ...pages.lms.auto_auth import AutoAuthPage
from ...pages.lms.dashboard import DashboardPage
from ..helpers import EventsTestMixin
class AccountSettingsPageTest(WebAppTest):
class AccountSettingsTestMixin(EventsTestMixin, WebAppTest):
"""
Tests that verify behaviour of the Account Settings page.
Mixin with helper methods to test the account settings page.
"""
SUCCESS_MESSAGE = 'Your changes have been saved.'
USERNAME = "test"
PASSWORD = "testpass"
EMAIL = "test@example.com"
......@@ -25,17 +26,26 @@ class AccountSettingsPageTest(WebAppTest):
"""
Initialize account and pages.
"""
super(AccountSettingsPageTest, self).setUp()
super(AccountSettingsTestMixin, self).setUp()
AutoAuthPage(self.browser, username=self.USERNAME, password=self.PASSWORD, email=self.EMAIL).visit()
self.user_id = AutoAuthPage(
self.browser, username=self.USERNAME, password=self.PASSWORD, email=self.EMAIL
).visit().get_user_id()
self.account_settings_page = AccountSettingsPage(self.browser)
self.account_settings_page.visit()
class DashboardMenuTest(AccountSettingsTestMixin, WebAppTest):
"""
Tests that the dashboard menu works correctly with the account settings page.
"""
def test_link_on_dashboard_works(self):
"""
Scenario: Verify that account settings link is present in dashboard
page and we can use it to navigate to the page.
Scenario: Verify that the "Account Settings" link works from the dashboard.
Given that I am a registered user
And I visit my dashboard
And I click on "Account Settings" in the top drop down
Then I should see my account settings page
"""
dashboard_page = DashboardPage(self.browser)
dashboard_page.visit()
......@@ -43,6 +53,41 @@ class AccountSettingsPageTest(WebAppTest):
self.assertIn('Account Settings', dashboard_page.username_dropdown_link_text)
dashboard_page.click_account_settings_link()
class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
"""
Tests that verify behaviour of the Account Settings page.
"""
SUCCESS_MESSAGE = 'Your changes have been saved.'
def setUp(self):
"""
Initialize account and pages.
"""
super(AccountSettingsPageTest, self).setUp()
# Visit the account settings page for the current user.
self.account_settings_page = AccountSettingsPage(self.browser)
self.account_settings_page.visit()
def test_page_view_event(self):
"""
Scenario: An event should be recorded when the "Account Settings"
page is viewed.
Given that I am a registered user
And I visit my account settings page
Then a page view analytics event should be recorded
"""
self.verify_events_of_type(
u"edx.user.settings.viewed",
[{
u"user_id": int(self.user_id),
u"page": u"account",
u"visibility": None,
}]
)
def test_all_sections_and_fields_are_present(self):
"""
Scenario: Verify that all sections and fields are present on the page.
......@@ -245,7 +290,7 @@ class AccountSettingsPageTest(WebAppTest):
[u'Pakistan', u''],
)
def test_prefered_language_field(self):
def test_preferred_language_field(self):
"""
Test behaviour of "Preferred Language" field.
"""
......
......@@ -2,28 +2,23 @@
"""
End-to-end tests for Student's Profile Page.
"""
from datetime import datetime
from bok_choy.web_app_test import WebAppTest
from ...pages.common.logout import LogoutPage
from ...pages.lms.account_settings import AccountSettingsPage
from ...pages.lms.auto_auth import AutoAuthPage
from ...pages.lms.learner_profile import LearnerProfilePage
from ...pages.lms.dashboard import DashboardPage
from bok_choy.web_app_test import WebAppTest
from ..helpers import EventsTestMixin
class LearnerProfilePageTest(WebAppTest):
class LearnerProfileTestMixin(EventsTestMixin):
"""
Tests that verify Student's Profile Page.
Mixin with helper methods for testing learner profile pages.
"""
USER_1_NAME = 'user1'
USER_1_EMAIL = 'user1@edx.org'
USER_2_NAME = 'user2'
USER_2_EMAIL = 'user2@edx.org'
MY_USER = 1
OTHER_USER = 2
PRIVACY_PUBLIC = 'all_users'
PRIVACY_PRIVATE = 'private'
......@@ -32,39 +27,16 @@ class LearnerProfilePageTest(WebAppTest):
PUBLIC_PROFILE_EDITABLE_FIELDS = ['country', 'language_proficiencies', 'bio']
def setUp(self):
def log_in_as_unique_user(self):
"""
Initialize pages.
Create a unique user and return the account's username and id.
"""
super(LearnerProfilePageTest, self).setUp()
self.account_settings_page = AccountSettingsPage(self.browser)
self.dashboard_page = DashboardPage(self.browser)
username = "test_{uuid}".format(uuid=self.unique_id[0:6])
auto_auth_page = AutoAuthPage(self.browser, username=username).visit()
user_id = auto_auth_page.get_user_id()
return username, user_id
self.my_auto_auth_page = AutoAuthPage(self.browser, username=self.USER_1_NAME, email=self.USER_1_EMAIL).visit()
self.my_profile_page = LearnerProfilePage(self.browser, self.USER_1_NAME)
self.other_auto_auth_page = AutoAuthPage(
self.browser,
username=self.USER_2_NAME,
email=self.USER_2_EMAIL
).visit()
self.other_profile_page = LearnerProfilePage(self.browser, self.USER_2_NAME)
self.set_birth_year(self.MY_USER, birth_year='1990')
self.set_birth_year(self.OTHER_USER, birth_year='1990')
def authenticate_as_user(self, user):
"""
Auto authenticate a user.
"""
if user == self.MY_USER:
self.my_auto_auth_page.visit()
elif user == self.OTHER_USER:
self.other_auto_auth_page.visit()
def set_pubilc_profile_fields_data(self, profile_page):
def set_public_profile_fields_data(self, profile_page):
"""
Fill in the public profile fields of a user.
"""
......@@ -72,56 +44,72 @@ class LearnerProfilePageTest(WebAppTest):
profile_page.value_for_dropdown_field('country', 'United Kingdom')
profile_page.value_for_textarea_field('bio', 'Nothing Special')
def visit_my_profile_page(self, user, privacy=None, authenticate=True):
def visit_profile_page(self, username, privacy=None):
"""
Visits a users profile page.
Visits a user's profile page.
"""
if authenticate:
self.authenticate_as_user(user)
self.my_profile_page.visit()
self.my_profile_page.wait_for_page()
profile_page = LearnerProfilePage(self.browser, username)
if user is self.MY_USER and privacy is not None:
self.my_profile_page.privacy = privacy
# Change the privacy if requested by loading the page and
# changing the drop down
if privacy is not None:
profile_page.visit()
profile_page.wait_for_page()
profile_page.privacy = privacy
if privacy == self.PRIVACY_PUBLIC:
self.set_pubilc_profile_fields_data(self.my_profile_page)
self.set_public_profile_fields_data(profile_page)
def visit_other_profile_page(self, user, privacy=None):
"""
Visits a users profile page.
"""
self.authenticate_as_user(user)
self.other_profile_page.visit()
self.other_profile_page.wait_for_page()
# Reset event tracking so that the tests only see events from
# loading the profile page.
self.reset_event_tracking()
if user is self.OTHER_USER and privacy is not None:
self.other_profile_page.visit()
self.other_profile_page.wait_for_page()
self.other_profile_page.privacy = privacy
# Load the page
profile_page.visit()
profile_page.wait_for_page()
if privacy == self.PRIVACY_PUBLIC:
self.set_pubilc_profile_fields_data(self.other_profile_page)
return profile_page
def set_birth_year(self, birth_year):
"""
Set birth year for the current user to the specified value.
"""
account_settings_page = AccountSettingsPage(self.browser)
account_settings_page.visit()
account_settings_page.wait_for_page()
self.assertEqual(
account_settings_page.value_for_dropdown_field('year_of_birth', str(birth_year)),
str(birth_year)
)
def set_birth_year(self, user, birth_year):
def verify_profile_page_view_event(self, profile_user_id, visibility=None):
"""
Set birth year for `user` to the specified value.
Verifies that the correct view event was captured for the profile page.
"""
self.authenticate_as_user(user)
self.account_settings_page.visit()
self.account_settings_page.wait_for_page()
self.assertEqual(self.account_settings_page.value_for_dropdown_field('year_of_birth', birth_year), birth_year)
self.verify_events_of_type(
u"edx.user.settings.viewed",
[{
u"user_id": int(profile_user_id),
u"page": u"profile",
u"visibility": unicode(visibility),
}]
)
class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
"""
Tests that verify a student's own profile page.
"""
def verify_profile_forced_private_message(self, birth_year, message=None):
def verify_profile_forced_private_message(self, username, birth_year, message=None):
"""
Verify age limit messages for a user.
"""
self.set_birth_year(self.MY_USER, birth_year=birth_year)
self.visit_my_profile_page(self.MY_USER, authenticate=False)
self.assertTrue(self.my_profile_page.privacy_field_visible)
self.assertEqual(self.my_profile_page.age_limit_message_present, message is not None)
self.assertIn(message, self.my_profile_page.profile_forced_private_message)
self.set_birth_year(birth_year=birth_year if birth_year is not None else "")
profile_page = self.visit_profile_page(username)
self.assertTrue(profile_page.privacy_field_visible)
self.assertEqual(profile_page.age_limit_message_present, message is not None)
self.assertIn(message, profile_page.profile_forced_private_message)
def test_dashboard_learner_profile_link(self):
"""
......@@ -134,11 +122,14 @@ class LearnerProfilePageTest(WebAppTest):
When I click on My Profile link.
Then I will be navigated to My Profile page.
"""
self.dashboard_page.visit()
self.dashboard_page.click_username_dropdown()
self.assertTrue('My Profile' in self.dashboard_page.username_dropdown_link_text)
self.dashboard_page.click_my_profile_link()
self.my_profile_page.wait_for_page()
username, user_id = self.log_in_as_unique_user()
dashboard_page = DashboardPage(self.browser)
dashboard_page.visit()
dashboard_page.click_username_dropdown()
self.assertTrue('My Profile' in dashboard_page.username_dropdown_link_text)
dashboard_page.click_my_profile_link()
my_profile_page = LearnerProfilePage(self.browser, username)
my_profile_page.wait_for_page()
def test_fields_on_my_private_profile(self):
"""
......@@ -151,10 +142,13 @@ class LearnerProfilePageTest(WebAppTest):
Then I should see the profile visibility selector dropdown.
Then I see some of the profile fields are shown.
"""
self.visit_my_profile_page(self.MY_USER, privacy=self.PRIVACY_PRIVATE)
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PRIVATE)
self.assertTrue(profile_page.privacy_field_visible)
self.assertEqual(profile_page.visible_fields, self.PRIVATE_PROFILE_FIELDS)
self.assertTrue(self.my_profile_page.privacy_field_visible)
self.assertEqual(self.my_profile_page.visible_fields, self.PRIVATE_PROFILE_FIELDS)
self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PRIVATE)
def test_fields_on_my_public_profile(self):
"""
......@@ -168,81 +162,43 @@ class LearnerProfilePageTest(WebAppTest):
Then I see all the profile fields are shown.
And `location`, `language` and `about me` fields are editable.
"""
self.visit_my_profile_page(self.MY_USER, privacy=self.PRIVACY_PUBLIC)
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self.assertTrue(self.my_profile_page.privacy_field_visible)
self.assertEqual(self.my_profile_page.visible_fields, self.PUBLIC_PROFILE_FIELDS)
self.assertTrue(profile_page.privacy_field_visible)
self.assertEqual(profile_page.visible_fields, self.PUBLIC_PROFILE_FIELDS)
self.assertEqual(self.my_profile_page.editable_fields, self.PUBLIC_PROFILE_EDITABLE_FIELDS)
self.assertEqual(profile_page.editable_fields, self.PUBLIC_PROFILE_EDITABLE_FIELDS)
def test_fields_on_others_private_profile(self):
"""
Scenario: Verify that desired fields are shown when looking at her own private profile.
self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PUBLIC)
Given that I am a registered user.
And I visit others private profile page.
Then I shouldn't see the profile visibility selector dropdown.
Then I see some of the profile fields are shown.
"""
self.visit_other_profile_page(self.OTHER_USER, privacy=self.PRIVACY_PRIVATE)
self.visit_other_profile_page(self.MY_USER)
self.assertFalse(self.other_profile_page.privacy_field_visible)
self.assertEqual(self.other_profile_page.visible_fields, self.PRIVATE_PROFILE_FIELDS)
def test_fields_on_others_public_profile(self):
"""
Scenario: Verify that desired fields are shown when looking at her own public profile.
Given that I am a registered user.
And I visit others public profile page.
Then I shouldn't see the profile visibility selector dropdown.
Then all the profile fields are shown.
Then I shouldn't see the profile visibility selector dropdown.
Also `location`, `language` and `about me` fields are not editable.
"""
self.visit_other_profile_page(self.OTHER_USER, privacy=self.PRIVACY_PUBLIC)
self.visit_other_profile_page(self.MY_USER)
self.other_profile_page.wait_for_public_fields()
self.assertFalse(self.other_profile_page.privacy_field_visible)
fields_to_check = self.PUBLIC_PROFILE_FIELDS
self.assertEqual(self.other_profile_page.visible_fields, fields_to_check)
self.assertEqual(self.my_profile_page.editable_fields, [])
def _test_dropdown_field(self, field_id, new_value, displayed_value, mode):
def _test_dropdown_field(self, profile_page, field_id, new_value, displayed_value, mode):
"""
Test behaviour of a dropdown field.
"""
self.visit_my_profile_page(self.MY_USER, privacy=self.PRIVACY_PUBLIC)
self.my_profile_page.value_for_dropdown_field(field_id, new_value)
self.assertEqual(self.my_profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(self.my_profile_page.mode_for_field(field_id), mode)
profile_page.value_for_dropdown_field(field_id, new_value)
self.assertEqual(profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(profile_page.mode_for_field(field_id), mode)
self.browser.refresh()
self.my_profile_page.wait_for_page()
profile_page.wait_for_page()
self.assertEqual(self.my_profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(self.my_profile_page.mode_for_field(field_id), mode)
self.assertEqual(profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(profile_page.mode_for_field(field_id), mode)
def _test_textarea_field(self, field_id, new_value, displayed_value, mode):
def _test_textarea_field(self, profile_page, field_id, new_value, displayed_value, mode):
"""
Test behaviour of a textarea field.
"""
self.visit_my_profile_page(self.MY_USER, privacy=self.PRIVACY_PUBLIC, )
self.my_profile_page.value_for_textarea_field(field_id, new_value)
self.assertEqual(self.my_profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(self.my_profile_page.mode_for_field(field_id), mode)
profile_page.value_for_textarea_field(field_id, new_value)
self.assertEqual(profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(profile_page.mode_for_field(field_id), mode)
self.browser.refresh()
self.my_profile_page.wait_for_page()
profile_page.wait_for_page()
self.assertEqual(self.my_profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(self.my_profile_page.mode_for_field(field_id), mode)
self.assertEqual(profile_page.get_non_editable_mode_value(field_id), displayed_value)
self.assertTrue(profile_page.mode_for_field(field_id), mode)
def test_country_field(self):
"""
......@@ -259,12 +215,14 @@ class LearnerProfilePageTest(WebAppTest):
Then `country` field mode should be `edit`
And `country` field icon should be visible.
"""
self._test_dropdown_field('country', 'Pakistan', 'Pakistan', 'display')
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self._test_dropdown_field(profile_page, 'country', 'Pakistan', 'Pakistan', 'display')
self.my_profile_page.make_field_editable('country')
self.assertTrue(self.my_profile_page.mode_for_field('country'), 'edit')
profile_page.make_field_editable('country')
self.assertTrue(profile_page.mode_for_field('country'), 'edit')
self.assertTrue(self.my_profile_page.field_icon_present('country'))
self.assertTrue(profile_page.field_icon_present('country'))
def test_language_field(self):
"""
......@@ -285,13 +243,15 @@ class LearnerProfilePageTest(WebAppTest):
Then `language` field mode should be `edit`
And `language` field icon should be visible.
"""
self._test_dropdown_field('language_proficiencies', 'Urdu', 'Urdu', 'display')
self._test_dropdown_field('language_proficiencies', '', 'Add language', 'placeholder')
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self._test_dropdown_field(profile_page, 'language_proficiencies', 'Urdu', 'Urdu', 'display')
self._test_dropdown_field(profile_page, 'language_proficiencies', '', 'Add language', 'placeholder')
self.my_profile_page.make_field_editable('language_proficiencies')
self.assertTrue(self.my_profile_page.mode_for_field('language_proficiencies'), 'edit')
profile_page.make_field_editable('language_proficiencies')
self.assertTrue(profile_page.mode_for_field('language_proficiencies'), 'edit')
self.assertTrue(self.my_profile_page.field_icon_present('language_proficiencies'))
self.assertTrue(profile_page.field_icon_present('language_proficiencies'))
def test_about_me_field(self):
"""
......@@ -320,11 +280,13 @@ class LearnerProfilePageTest(WebAppTest):
"why you're taking courses on edX, or what you hope to learn."
)
self._test_textarea_field('bio', 'Eat Sleep Code', 'Eat Sleep Code', 'display')
self._test_textarea_field('bio', '', placeholder_value, 'placeholder')
username, user_id = self.log_in_as_unique_user()
profile_page = self.visit_profile_page(username, privacy=self.PRIVACY_PUBLIC)
self._test_textarea_field(profile_page, 'bio', 'Eat Sleep Code', 'Eat Sleep Code', 'display')
self._test_textarea_field(profile_page, 'bio', '', placeholder_value, 'placeholder')
self.my_profile_page.make_field_editable('bio')
self.assertTrue(self.my_profile_page.mode_for_field('bio'), 'edit')
profile_page.make_field_editable('bio')
self.assertTrue(profile_page.mode_for_field('bio'), 'edit')
def test_birth_year_not_set(self):
"""
......@@ -332,11 +294,13 @@ class LearnerProfilePageTest(WebAppTest):
Given that I am a registered user.
And birth year is not set for the user.
And i visit my profile page.
Then i should see message `Your profile is disabled because you haven't filled in your Year of Birth.`
And I visit my profile page.
Then I should see a message that the profile is private until the year of birth is set.
"""
username, user_id = self.log_in_as_unique_user()
message = "You must specify your birth year before you can share your full profile."
self.verify_profile_forced_private_message('', message=message)
self.verify_profile_forced_private_message(username, birth_year=None, message=message)
self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PRIVATE)
def test_user_is_under_age(self):
"""
......@@ -344,7 +308,72 @@ class LearnerProfilePageTest(WebAppTest):
Given that I am a registered user.
And birth year is set so that age is less than 13.
And i visit my profile page.
Then i should see message `You must be over 13 to share a full profile.`
And I visit my profile page.
Then I should see a message that the profile is private as I am under thirteen.
"""
username, user_id = self.log_in_as_unique_user()
under_age_birth_year = datetime.now().year - 10
self.verify_profile_forced_private_message(
username,
birth_year=under_age_birth_year,
message='You must be over 13 to share a full profile.'
)
self.verify_profile_page_view_event(user_id, visibility=self.PRIVACY_PRIVATE)
class DifferentUserLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
"""
Tests that verify viewing the profile page of a different user.
"""
def test_different_user_private_profile(self):
"""
self.verify_profile_forced_private_message('2010', message='You must be over 13 to share a full profile.')
Scenario: Verify that desired fields are shown when looking at a different user's private profile.
Given that I am a registered user.
And I visit a different user's private profile page.
Then I shouldn't see the profile visibility selector dropdown.
Then I see some of the profile fields are shown.
"""
different_username, different_user_id = self._initialize_different_user(privacy=self.PRIVACY_PRIVATE)
self.log_in_as_unique_user()
profile_page = self.visit_profile_page(different_username)
self.assertFalse(profile_page.privacy_field_visible)
self.assertEqual(profile_page.visible_fields, self.PRIVATE_PROFILE_FIELDS)
self.verify_profile_page_view_event(different_user_id, visibility=self.PRIVACY_PRIVATE)
def test_different_user_public_profile(self):
"""
Scenario: Verify that desired fields are shown when looking at a different user's public profile.
Given that I am a registered user.
And I visit a different user's public profile page.
Then I shouldn't see the profile visibility selector dropdown.
Then all the profile fields are shown.
Then I shouldn't see the profile visibility selector dropdown.
Also `location`, `language` and `about me` fields are not editable.
"""
different_username, different_user_id = self._initialize_different_user(privacy=self.PRIVACY_PUBLIC)
self.log_in_as_unique_user()
profile_page = self.visit_profile_page(different_username)
profile_page.wait_for_public_fields()
self.assertFalse(profile_page.privacy_field_visible)
self.assertEqual(profile_page.visible_fields, self.PUBLIC_PROFILE_FIELDS)
self.assertEqual(profile_page.editable_fields, [])
self.verify_profile_page_view_event(different_user_id, visibility=self.PRIVACY_PUBLIC)
def _initialize_different_user(self, privacy=None):
"""
Initialize the profile page for a different test user
"""
username, user_id = self.log_in_as_unique_user()
# Set the privacy for the new user
if privacy is None:
privacy = self.PRIVACY_PUBLIC
self.visit_profile_page(username, privacy=privacy)
# Log the user out
LogoutPage(self.browser).visit()
return username, user_id
......@@ -67,3 +67,11 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase):
for attribute in self.CONTEXT_DATA:
self.assertIn(attribute, response.content)
def test_undefined_profile_page(self):
"""
Verify that a 404 is returned for a non-existent profile page.
"""
profile_path = reverse('learner_profile', kwargs={'username': "no_such_user"})
response = self.client.get(path=profile_path)
self.assertEqual(404, response.status_code)
""" Views for a student's profile information. """
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django_countries import countries
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.views.decorators.http import require_http_methods
from edxmako.shortcuts import render_to_response
from student.models import User
@login_required
@require_http_methods(['GET'])
def learner_profile(request, username):
"""
Render the students profile page.
"""Render the profile page for the specified username.
Args:
request (HttpRequest)
......@@ -23,20 +25,23 @@ def learner_profile(request, username):
Returns:
HttpResponse: 200 if the page was sent successfully
HttpResponse: 302 if not logged in (redirect to login page)
HttpResponse: 404 if the specified username does not exist
HttpResponse: 405 if using an unsupported HTTP method
Example usage:
GET /account/profile
"""
return render_to_response(
'student_profile/learner_profile.html',
learner_profile_context(request.user.username, username, request.user.is_staff)
)
try:
return render_to_response(
'student_profile/learner_profile.html',
learner_profile_context(request.user.username, username, request.user.is_staff)
)
except ObjectDoesNotExist:
return HttpResponse(status=404)
def learner_profile_context(logged_in_username, profile_username, user_is_staff):
"""
Context for the learner profile page.
"""Context for the learner profile page.
Args:
logged_in_username (str): Username of user logged In user.
......@@ -45,7 +50,11 @@ def learner_profile_context(logged_in_username, profile_username, user_is_staff)
Returns:
dict
Raises:
ObjectDoesNotExist: the specified profile_username does not exist.
"""
profile_user = User.objects.get(username=profile_username)
language_options = [language for language in settings.ALL_LANGUAGES]
country_options = [
......@@ -57,6 +66,7 @@ def learner_profile_context(logged_in_username, profile_username, user_is_staff)
context = {
'data': {
'profile_user_id': profile_user.id,
'default_public_account_fields': settings.ACCOUNT_VISIBILITY_CONFIGURATION['public_fields'],
'accounts_api_url': reverse("accounts_api", kwargs={'username': profile_username}),
'preferences_api_url': reverse('preferences_api', kwargs={'username': profile_username}),
......
......@@ -49,6 +49,15 @@
],
"port": 27017
},
"TRACKING_BACKENDS": {
"mongo": {
"ENGINE": "track.backends.mongodb.MongoBackend",
"OPTIONS": {
"database": "test",
"collection": "events"
}
}
},
"EVENT_TRACKING_BACKENDS": {
"mongo": {
"ENGINE": "eventtracking.backends.mongodb.MongoBackend",
......
......@@ -93,8 +93,8 @@ define(['backbone', 'jquery', 'underscore', 'js/common_helpers/ajax_helpers', 'j
return new LearnerProfileView(
{
el: $('.wrapper-profile'),
own_profile: ownProfile,
has_preferences_access: true,
ownProfile: ownProfile,
hasPreferencesAccess: true,
accountSettingsModel: accountSettingsModel,
preferencesModel: accountPreferencesModel,
accountPrivacyFieldView: accountPrivacyFieldView,
......
;(function (define, undefined) {
'use strict';
define([
'gettext', 'jquery', 'underscore', 'backbone',
'gettext', 'jquery', 'underscore', 'backbone', 'logger',
'js/views/fields',
'js/student_account/models/user_account_model',
'js/student_account/models/user_preferences_model',
'js/student_account/views/account_settings_fields',
'js/student_account/views/account_settings_view'
], function (gettext, $, _, Backbone, FieldViews, UserAccountModel, UserPreferencesModel,
], function (gettext, $, _, Backbone, Logger, FieldViews, UserAccountModel, UserPreferencesModel,
AccountSettingsFieldViews, AccountSettingsView) {
return function (fieldsData, authData, userAccountsApiUrl, userPreferencesApiUrl) {
return function (fieldsData, authData, userAccountsApiUrl, userPreferencesApiUrl, accountUserId) {
var accountSettingsElement = $('.wrapper-account-settings');
......@@ -29,7 +29,7 @@
model: userAccountModel,
title: gettext('Username'),
valueAttribute: 'username',
helpMessage: 'The name that identifies you on the edX site. You cannot change your username.'
helpMessage: gettext('The name that identifies you on the edX site. You cannot change your username.')
})
},
{
......@@ -55,7 +55,7 @@
valueAttribute: 'password',
emailAttribute: 'email',
linkTitle: gettext('Reset Password'),
linkHref: fieldsData['password']['url'],
linkHref: fieldsData.password.url,
helpMessage: gettext('When you click "Reset Password", a message will be sent to your email address. Click the link in the message to reset your password.')
})
},
......@@ -67,7 +67,7 @@
required: true,
refreshPageOnSave: true,
helpMessage: gettext('The language used for the edX site. The site is currently available in a limited number of languages.'),
options: fieldsData['language']['options']
options: fieldsData.language.options
})
}
]
......@@ -80,7 +80,7 @@
model: userAccountModel,
title: gettext('Education Completed'),
valueAttribute: 'level_of_education',
options: fieldsData['level_of_education']['options']
options: fieldsData.level_of_education.options
})
},
{
......@@ -88,7 +88,7 @@
model: userAccountModel,
title: gettext('Gender'),
valueAttribute: 'gender',
options: fieldsData['gender']['options']
options: fieldsData.gender.options
})
},
{
......@@ -96,7 +96,7 @@
model: userAccountModel,
title: gettext('Year of Birth'),
valueAttribute: 'year_of_birth',
options: fieldsData['year_of_birth']['options']
options: fieldsData.year_of_birth.options
})
},
{
......@@ -104,7 +104,7 @@
model: userAccountModel,
title: gettext('Country or Region'),
valueAttribute: 'country',
options: fieldsData['country']['options']
options: fieldsData.country.options
})
},
{
......@@ -112,7 +112,7 @@
model: userAccountModel,
title: gettext('Preferred Language'),
valueAttribute: 'language_proficiencies',
options: fieldsData['preferred_language']['options']
options: fieldsData.preferred_language.options
})
}
]
......@@ -125,20 +125,22 @@
fields: _.map(authData.providers, function(provider) {
return {
'view': new AccountSettingsFieldViews.AuthFieldView({
title: provider['name'],
valueAttribute: 'auth-' + provider['name'].toLowerCase(),
title: provider.name,
valueAttribute: 'auth-' + provider.name.toLowerCase(),
helpMessage: '',
connected: provider['connected'],
connectUrl: provider['connect_url'],
disconnectUrl: provider['disconnect_url']
connected: provider.connected,
connectUrl: provider.connect_url,
disconnectUrl: provider.disconnect_url
})
}
};
})
};
sectionsData.push(accountsSectionData);
}
var accountSettingsView = new AccountSettingsView({
model: userAccountModel,
accountUserId: accountUserId,
el: accountSettingsElement,
sectionsData: sectionsData
});
......@@ -149,14 +151,25 @@
accountSettingsView.showLoadingError();
};
var showAccountFields = function () {
// Record that the account settings page was viewed.
Logger.log('edx.user.settings.viewed', {
page: "account",
visibility: null,
user_id: accountUserId
});
// Render the fields
accountSettingsView.renderFields();
};
userAccountModel.fetch({
success: function () {
// Fetch the user preferences model
userPreferencesModel.fetch({
success: function () {
accountSettingsView.renderFields();
},
success: showAccountFields,
error: showLoadingError
})
});
},
error: showLoadingError
});
......@@ -167,5 +180,5 @@
accountSettingsView: accountSettingsView
};
};
})
});
}).call(this, define || RequireJS.define);
......@@ -23,7 +23,7 @@
var view = this;
_.each(this.$('.account-settings-section-body'), function (sectionEl, index) {
_.each(view.options.sectionsData[index].fields, function (field, index) {
_.each(view.options.sectionsData[index].fields, function (field) {
$(sectionEl).append(field.view.render().el);
});
});
......@@ -37,5 +37,5 @@
});
return AccountSettingsView;
})
});
}).call(this, define || RequireJS.define);
;(function (define, undefined) {
'use strict';
define([
'gettext', 'jquery', 'underscore', 'backbone',
'gettext', 'jquery', 'underscore', 'backbone', 'logger',
'js/student_account/models/user_account_model',
'js/student_account/models/user_preferences_model',
'js/views/fields',
'js/student_profile/views/learner_profile_fields',
'js/student_profile/views/learner_profile_view',
'js/student_account/views/account_settings_fields'
], function (gettext, $, _, Backbone, AccountSettingsModel, AccountPreferencesModel, FieldsView,
], function (gettext, $, _, Backbone, Logger, AccountSettingsModel, AccountPreferencesModel, FieldsView,
LearnerProfileFieldsView, LearnerProfileView, AccountSettingsFieldViews) {
return function (options) {
......@@ -18,14 +16,14 @@
var learnerProfileElement = $('.wrapper-profile');
var accountPreferencesModel = new AccountPreferencesModel();
accountPreferencesModel.url = options['preferences_api_url'];
accountPreferencesModel.url = options.preferences_api_url;
var accountSettingsModel = new AccountSettingsModel({
'default_public_account_fields': options['default_public_account_fields']
'default_public_account_fields': options.default_public_account_fields
});
accountSettingsModel.url = options['accounts_api_url'];
accountSettingsModel.url = options.accounts_api_url;
var editable = options['own_profile'] ? 'toggle' : 'never';
var editable = options.own_profile ? 'toggle' : 'never';
var accountPrivacyFieldView = new LearnerProfileFieldsView.AccountPrivacyFieldView({
model: accountPreferencesModel,
......@@ -39,7 +37,7 @@
['all_users', gettext('Full Profile')]
],
helpMessage: '',
accountSettingsPageUrl: options['account_settings_page_url']
accountSettingsPageUrl: options.account_settings_page_url
});
var usernameFieldView = new FieldsView.ReadonlyFieldView({
......@@ -58,7 +56,7 @@
iconName: 'fa-map-marker',
placeholderValue: gettext('Add country'),
valueAttribute: "country",
options: options['country_options'],
options: options.country_options,
helpMessage: ''
}),
new AccountSettingsFieldViews.LanguageProficienciesFieldView({
......@@ -69,7 +67,7 @@
iconName: 'fa-comment',
placeholderValue: gettext('Add language'),
valueAttribute: "language_proficiencies",
options: options['language_options'],
options: options.language_options,
helpMessage: ''
})
];
......@@ -88,8 +86,8 @@
var learnerProfileView = new LearnerProfileView({
el: learnerProfileElement,
own_profile: options['own_profile'],
has_preferences_access: options['has_preferences_access'],
ownProfile: options.own_profile,
has_preferences_access: options.has_preferences_access,
accountSettingsModel: accountSettingsModel,
preferencesModel: accountPreferencesModel,
accountPrivacyFieldView: accountPrivacyFieldView,
......@@ -102,20 +100,37 @@
learnerProfileView.showLoadingError();
};
var renderLearnerProfileView = function() {
var getProfileVisibility = function() {
if (options.has_preferences_access) {
return accountPreferencesModel.get('account_privacy');
} else {
return accountSettingsModel.get('profile_is_public') ? 'all_users' : 'private';
}
};
var showLearnerProfileView = function() {
// Record that the profile page was viewed
Logger.log('edx.user.settings.viewed', {
page: "profile",
visibility: getProfileVisibility(),
user_id: options.profile_user_id
});
// Render the view for the first time
learnerProfileView.render();
};
accountSettingsModel.fetch({
success: function () {
if (options['has_preferences_access']) {
// Fetch the preferences model if the user has access
if (options.has_preferences_access) {
accountPreferencesModel.fetch({
success: renderLearnerProfileView,
success: showLearnerProfileView,
error: showLoadingError
});
}
else {
renderLearnerProfileView();
showLearnerProfileView();
}
},
error: showLoadingError
......@@ -127,5 +142,5 @@
learnerProfileView: learnerProfileView
};
};
})
});
}).call(this, define || RequireJS.define);
......@@ -14,7 +14,7 @@
showFullProfile: function () {
var isAboveMinimumAge = this.options.accountSettingsModel.isAboveMinimumAge();
if (this.options.own_profile) {
if (this.options.ownProfile) {
return isAboveMinimumAge && this.options.preferencesModel.get('account_privacy') === 'all_users';
} else {
return this.options.accountSettingsModel.get('profile_is_public');
......@@ -25,7 +25,7 @@
this.$el.html(this.template({
username: this.options.accountSettingsModel.get('username'),
profilePhoto: 'http://www.teachthought.com/wp-content/uploads/2012/07/edX-120x120.jpg',
ownProfile: this.options.own_profile,
ownProfile: this.options.ownProfile,
showFullProfile: this.showFullProfile()
}));
this.renderFields();
......@@ -35,11 +35,12 @@
renderFields: function() {
var view = this;
if (this.options.own_profile) {
var fieldView = this.options.accountPrivacyFieldView;
fieldView.profileIsPrivate = (!this.options.accountSettingsModel.get('year_of_birth'));
fieldView.requiresParentalConsent = (this.options.accountSettingsModel.get('requires_parental_consent'));
fieldView.isAboveMinimumAge = this.options.accountSettingsModel.isAboveMinimumAge();
if (this.options.ownProfile) {
var fieldView = this.options.accountPrivacyFieldView,
settings = this.options.accountSettingsModel;
fieldView.profileIsPrivate = !settings.get('year_of_birth');
fieldView.requiresParentalConsent = settings.get('requires_parental_consent');
fieldView.isAboveMinimumAge = settings.isAboveMinimumAge();
fieldView.undelegateEvents();
this.$('.wrapper-profile-field-account-privacy').append(fieldView.render().el);
fieldView.delegateEvents();
......@@ -48,13 +49,13 @@
this.$('.profile-section-one-fields').append(this.options.usernameFieldView.render().el);
if (this.showFullProfile()) {
_.each(this.options.sectionOneFieldViews, function (fieldView, index) {
_.each(this.options.sectionOneFieldViews, function (fieldView) {
fieldView.undelegateEvents();
view.$('.profile-section-one-fields').append(fieldView.render().el);
fieldView.delegateEvents();
});
_.each(this.options.sectionTwoFieldViews, function (fieldView, index) {
_.each(this.options.sectionTwoFieldViews, function (fieldView) {
fieldView.undelegateEvents();
view.$('.profile-section-two-fields').append(fieldView.render().el);
fieldView.delegateEvents();
......@@ -69,5 +70,5 @@
});
return LearnerProfileView;
})
});
}).call(this, define || RequireJS.define);
......@@ -41,7 +41,7 @@
var authData = ${ json.dumps(auth) };
setupAccountSettingsSection(
fieldsData, authData, '${user_accounts_api_url}', '${user_preferences_api_url}'
fieldsData, authData, '${user_accounts_api_url}', '${user_preferences_api_url}', ${user.id}
);
});
}).call(this, require || RequireJS.require);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment