- ## Translators: this message is displayed when a user tries to link their account with a third-party authentication provider (for example, Google or LinkedIn) with a given edX account, but their third-party account is already associated with another edX account. provider_name is the name of the third-party authentication provider, and platform_name is the name of the edX deployment.
-
${_("The {provider_name} account you selected is already linked to another {platform_name} account.").format(provider_name=duplicate_provider, platform_name=platform_name)}
-
-
-
-
diff --git a/lms/templates/header/user_dropdown.html b/lms/templates/header/user_dropdown.html
index 2e7e168a6937..5cb2b5f5b840 100644
--- a/lms/templates/header/user_dropdown.html
+++ b/lms/templates/header/user_dropdown.html
@@ -4,13 +4,14 @@
<%!
import json
+from urllib.parse import urljoin
from django.conf import settings
from django.urls import reverse
from django.utils.translation import gettext as _
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_urls_for_user
-from openedx.core.djangoapps.user_api.accounts.toggles import should_redirect_to_order_history_microfrontend
+from openedx.core.djangoapps.user_api.accounts.utils import retrieve_last_sitewide_block_completed
from openedx.features.enterprise_support.utils import get_enterprise_learner_generic_name, get_enterprise_learner_portal
%>
@@ -23,7 +24,7 @@
enterprise_customer_portal = get_enterprise_learner_portal(request)
## Enterprises with the learner portal enabled should not show order history, as it does
## not apply to the learner's method of purchasing content.
-should_show_order_history = should_redirect_to_order_history_microfrontend() and not enterprise_customer_portal
+should_show_order_history = not enterprise_customer_portal
%>
% else:
diff --git a/lms/urls.py b/lms/urls.py
index 8b314f9f1ea2..a82d134afe7a 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -669,12 +669,6 @@
include('openedx.features.calendar_sync.urls'),
),
- # Learner profile
- path(
- 'u/',
- include('openedx.features.learner_profile.urls'),
- ),
-
# Survey Report
re_path(
fr'^survey_report/',
diff --git a/openedx/core/djangoapps/theming/tests/test_theme_style_overrides.py b/openedx/core/djangoapps/theming/tests/test_theme_style_overrides.py
index d7578f25eb87..41f91c7d1eb5 100644
--- a/openedx/core/djangoapps/theming/tests/test_theme_style_overrides.py
+++ b/openedx/core/djangoapps/theming/tests/test_theme_style_overrides.py
@@ -44,21 +44,6 @@ def test_footer(self):
# This string comes from header.html of test-theme
self.assertContains(resp, "This is a footer for test-theme.")
- @with_comprehensive_theme("edx.org")
- def test_account_settings_hide_nav(self):
- """
- Test that theme header doesn't show marketing site links for Account Settings page.
- """
- self._login()
-
- account_settings_url = reverse('account_settings')
- response = self.client.get(account_settings_url)
-
- # Verify that the header navigation links are hidden for the edx.org version
- self.assertNotContains(response, "How it Works")
- self.assertNotContains(response, "Find courses")
- self.assertNotContains(response, "Schools & Partners")
-
@with_comprehensive_theme("test-theme")
def test_logo_image(self):
"""
diff --git a/openedx/core/djangoapps/user_api/accounts/settings_views.py b/openedx/core/djangoapps/user_api/accounts/settings_views.py
deleted file mode 100644
index 002695d4e33f..000000000000
--- a/openedx/core/djangoapps/user_api/accounts/settings_views.py
+++ /dev/null
@@ -1,299 +0,0 @@
-""" Views related to Account Settings. """
-
-
-import logging
-import urllib
-from datetime import datetime
-
-from django.conf import settings
-from django.contrib import messages
-from django.contrib.auth.decorators import login_required
-from django.http import HttpResponseRedirect
-from django.shortcuts import redirect
-from django.urls import reverse
-from django.utils.translation import gettext as _
-from django.views.decorators.http import require_http_methods
-from django_countries import countries
-
-from openedx_filters.learning.filters import AccountSettingsRenderStarted
-from common.djangoapps import third_party_auth
-from common.djangoapps.edxmako.shortcuts import render_to_response
-from common.djangoapps.student.models import UserProfile
-from common.djangoapps.third_party_auth import pipeline
-from common.djangoapps.util.date_utils import strftime_localized
-from lms.djangoapps.commerce.models import CommerceConfiguration
-from lms.djangoapps.commerce.utils import EcommerceService
-from openedx.core.djangoapps.commerce.utils import get_ecommerce_api_base_url, get_ecommerce_api_client
-from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
-from openedx.core.djangoapps.lang_pref.api import all_languages, released_languages
-from openedx.core.djangoapps.programs.models import ProgramsApiConfig
-from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
-from openedx.core.djangoapps.user_api.accounts.toggles import (
- should_redirect_to_account_microfrontend,
- should_redirect_to_order_history_microfrontend
-)
-from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
-from openedx.core.lib.edx_api_utils import get_api_data
-from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES
-from openedx.features.enterprise_support.api import enterprise_customer_for_request
-from openedx.features.enterprise_support.utils import update_account_settings_context_for_enterprise
-
-log = logging.getLogger(__name__)
-
-
-@login_required
-@require_http_methods(['GET'])
-def account_settings(request):
- """Render the current user's account settings page.
-
- Args:
- request (HttpRequest)
-
- Returns:
- HttpResponse: 200 if the page was sent successfully
- HttpResponse: 302 if not logged in (redirect to login page)
- HttpResponse: 405 if using an unsupported HTTP method
-
- Example usage:
-
- GET /account/settings
-
- """
- if should_redirect_to_account_microfrontend():
- url = settings.ACCOUNT_MICROFRONTEND_URL
-
- duplicate_provider = pipeline.get_duplicate_provider(messages.get_messages(request))
- if duplicate_provider:
- url = '{url}?{params}'.format(
- url=url,
- params=urllib.parse.urlencode({
- 'duplicate_provider': duplicate_provider,
- }),
- )
-
- return redirect(url)
-
- context = account_settings_context(request)
-
- account_settings_template = 'student_account/account_settings.html'
-
- try:
- # .. filter_implemented_name: AccountSettingsRenderStarted
- # .. filter_type: org.openedx.learning.student.settings.render.started.v1
- context, account_settings_template = AccountSettingsRenderStarted.run_filter(
- context=context, template_name=account_settings_template,
- )
- except AccountSettingsRenderStarted.RenderInvalidAccountSettings as exc:
- response = render_to_response(exc.account_settings_template, exc.template_context)
- except AccountSettingsRenderStarted.RedirectToPage as exc:
- response = HttpResponseRedirect(exc.redirect_to or reverse('dashboard'))
- except AccountSettingsRenderStarted.RenderCustomResponse as exc:
- response = exc.response
- else:
- response = render_to_response(account_settings_template, context)
-
- return response
-
-
-def account_settings_context(request):
- """ Context for the account settings page.
-
- Args:
- request: The request object.
-
- Returns:
- dict
-
- """
- user = request.user
-
- year_of_birth_options = [(str(year), str(year)) for year in UserProfile.VALID_YEARS]
- try:
- user_orders = get_user_orders(user)
- except: # pylint: disable=bare-except
- log.exception('Error fetching order history from Otto.')
- # Return empty order list as account settings page expect a list and
- # it will be broken if exception raised
- user_orders = []
-
- beta_language = {}
- dark_lang_config = DarkLangConfig.current()
- if dark_lang_config.enable_beta_languages:
- user_preferences = get_user_preferences(user)
- pref_language = user_preferences.get('pref-lang')
- if pref_language in dark_lang_config.beta_languages_list:
- beta_language['code'] = pref_language
- beta_language['name'] = settings.LANGUAGE_DICT.get(pref_language)
-
- context = {
- 'auth': {},
- 'duplicate_provider': None,
- 'nav_hidden': True,
- 'fields': {
- 'country': {
- 'options': list(countries),
- }, 'gender': {
- 'options': [(choice[0], _(choice[1])) for choice in UserProfile.GENDER_CHOICES], # lint-amnesty, pylint: disable=translation-of-non-string
- }, 'language': {
- 'options': released_languages(),
- }, 'level_of_education': {
- 'options': [(choice[0], _(choice[1])) for choice in UserProfile.LEVEL_OF_EDUCATION_CHOICES], # lint-amnesty, pylint: disable=translation-of-non-string
- }, 'password': {
- 'url': reverse('password_reset'),
- }, 'year_of_birth': {
- 'options': year_of_birth_options,
- }, 'preferred_language': {
- 'options': all_languages(),
- }, 'time_zone': {
- 'options': TIME_ZONE_CHOICES,
- }
- },
- 'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
- 'password_reset_support_link': configuration_helpers.get_value(
- 'PASSWORD_RESET_SUPPORT_LINK', settings.PASSWORD_RESET_SUPPORT_LINK
- ) or settings.SUPPORT_SITE_LINK,
- 'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}),
- 'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}),
- 'disable_courseware_js': True,
- 'show_program_listing': ProgramsApiConfig.is_enabled(),
- 'show_dashboard_tabs': True,
- 'order_history': user_orders,
- 'disable_order_history_tab': should_redirect_to_order_history_microfrontend(),
- 'enable_account_deletion': configuration_helpers.get_value(
- 'ENABLE_ACCOUNT_DELETION', settings.FEATURES.get('ENABLE_ACCOUNT_DELETION', False)
- ),
- 'extended_profile_fields': _get_extended_profile_fields(),
- 'beta_language': beta_language,
- 'enable_coppa_compliance': settings.ENABLE_COPPA_COMPLIANCE,
- }
-
- enterprise_customer = enterprise_customer_for_request(request)
- update_account_settings_context_for_enterprise(context, enterprise_customer, user)
-
- if third_party_auth.is_enabled():
- # If the account on the third party provider is already connected with another edX account,
- # we display a message to the user.
- context['duplicate_provider'] = pipeline.get_duplicate_provider(messages.get_messages(request))
-
- auth_states = pipeline.get_provider_user_states(user)
-
- context['auth']['providers'] = [{
- 'id': state.provider.provider_id,
- 'name': state.provider.name, # The name of the provider e.g. Facebook
- 'connected': state.has_account, # Whether the user's edX account is connected with the provider.
- # If the user is not connected, they should be directed to this page to authenticate
- # with the particular provider, as long as the provider supports initiating a login.
- 'connect_url': pipeline.get_login_url(
- state.provider.provider_id,
- pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS,
- # The url the user should be directed to after the auth process has completed.
- redirect_url=reverse('account_settings'),
- ),
- 'accepts_logins': state.provider.accepts_logins,
- # If the user is connected, sending a POST request to this url removes the connection
- # information for this provider from their edX account.
- 'disconnect_url': pipeline.get_disconnect_url(state.provider.provider_id, state.association_id),
- # We only want to include providers if they are either currently available to be logged
- # in with, or if the user is already authenticated with them.
- } for state in auth_states if state.provider.display_for_login or state.has_account]
-
- return context
-
-
-def get_user_orders(user):
- """Given a user, get the detail of all the orders from the Ecommerce service.
-
- Args:
- user (User): The user to authenticate as when requesting ecommerce.
-
- Returns:
- list of dict, representing orders returned by the Ecommerce service.
- """
- user_orders = []
- commerce_configuration = CommerceConfiguration.current()
- user_query = {'username': user.username}
-
- use_cache = commerce_configuration.is_cache_enabled
- cache_key = commerce_configuration.CACHE_KEY + '.' + str(user.id) if use_cache else None
- commerce_user_orders = get_api_data(
- commerce_configuration,
- 'orders',
- api_client=get_ecommerce_api_client(user),
- base_api_url=get_ecommerce_api_base_url(),
- querystring=user_query,
- cache_key=cache_key
- )
-
- for order in commerce_user_orders:
- if order['status'].lower() == 'complete':
- date_placed = datetime.strptime(order['date_placed'], "%Y-%m-%dT%H:%M:%SZ")
- order_data = {
- 'number': order['number'],
- 'price': order['total_excl_tax'],
- 'order_date': strftime_localized(date_placed, 'SHORT_DATE'),
- 'receipt_url': EcommerceService().get_receipt_page_url(order['number']),
- 'lines': order['lines'],
- }
- user_orders.append(order_data)
-
- return user_orders
-
-
-def _get_extended_profile_fields():
- """Retrieve the extended profile fields from site configuration to be shown on the
- Account Settings page
-
- Returns:
- A list of dicts. Each dict corresponds to a single field. The keys per field are:
- "field_name" : name of the field stored in user_profile.meta
- "field_label" : The label of the field.
- "field_type" : TextField or ListField
- "field_options": a list of tuples for options in the dropdown in case of ListField
- """
-
- extended_profile_fields = []
- fields_already_showing = ['username', 'name', 'email', 'pref-lang', 'country', 'time_zone', 'level_of_education',
- 'gender', 'year_of_birth', 'language_proficiencies', 'social_links']
-
- field_labels_map = {
- "first_name": _("First Name"),
- "last_name": _("Last Name"),
- "city": _("City"),
- "state": _("State/Province/Region"),
- "company": _("Company"),
- "title": _("Title"),
- "job_title": _("Job Title"),
- "mailing_address": _("Mailing address"),
- "goals": _("Tell us why you're interested in {platform_name}").format(
- platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME)
- ),
- "profession": _("Profession"),
- "specialty": _("Specialty")
- }
-
- extended_profile_field_names = configuration_helpers.get_value('extended_profile_fields', [])
- for field_to_exclude in fields_already_showing:
- if field_to_exclude in extended_profile_field_names:
- extended_profile_field_names.remove(field_to_exclude)
-
- extended_profile_field_options = configuration_helpers.get_value('EXTRA_FIELD_OPTIONS', [])
- extended_profile_field_option_tuples = {}
- for field in extended_profile_field_options.keys():
- field_options = extended_profile_field_options[field]
- extended_profile_field_option_tuples[field] = [(option.lower(), option) for option in field_options]
-
- for field in extended_profile_field_names:
- field_dict = {
- "field_name": field,
- "field_label": field_labels_map.get(field, field),
- }
-
- field_options = extended_profile_field_option_tuples.get(field)
- if field_options:
- field_dict["field_type"] = "ListField"
- field_dict["field_options"] = field_options
- else:
- field_dict["field_type"] = "TextField"
- extended_profile_fields.append(field_dict)
-
- return extended_profile_fields
diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_filters.py b/openedx/core/djangoapps/user_api/accounts/tests/test_filters.py
deleted file mode 100644
index 782549aea0b5..000000000000
--- a/openedx/core/djangoapps/user_api/accounts/tests/test_filters.py
+++ /dev/null
@@ -1,241 +0,0 @@
-"""
-Test that various filters are fired for views in the certificates app.
-"""
-from django.http import HttpResponse
-from django.test import override_settings
-from django.urls import reverse
-from openedx_filters import PipelineStep
-from openedx_filters.learning.filters import AccountSettingsRenderStarted
-from rest_framework import status
-from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
-
-from openedx.core.djangolib.testing.utils import skip_unless_lms
-from common.djangoapps.student.tests.factories import UserFactory
-
-
-class TestRenderInvalidAccountSettings(PipelineStep):
- """
- Utility class used when getting steps for pipeline.
- """
-
- def run_filter(self, context, template_name): # pylint: disable=arguments-differ
- """
- Pipeline step that stops the course about render process.
- """
- raise AccountSettingsRenderStarted.RenderInvalidAccountSettings(
- "You can't access the account settings page.",
- account_settings_template="static_templates/server-error.html",
- )
-
-
-class TestRedirectToPage(PipelineStep):
- """
- Utility class used when getting steps for pipeline.
- """
-
- def run_filter(self, context, template_name): # pylint: disable=arguments-differ
- """
- Pipeline step that redirects to dashboard before rendering the account settings page.
-
- When raising RedirectToPage, this filter uses a redirect_to field handled by
- the course about view that redirects to that URL.
- """
- raise AccountSettingsRenderStarted.RedirectToPage(
- "You can't access this page, redirecting to dashboard.",
- redirect_to="/courses",
- )
-
-
-class TestRedirectToDefaultPage(PipelineStep):
- """
- Utility class used when getting steps for pipeline.
- """
-
- def run_filter(self, context, template_name): # pylint: disable=arguments-differ
- """
- Pipeline step that redirects to dashboard before rendering the account settings page.
-
- When raising RedirectToPage, this filter uses a redirect_to field handled by
- the course about view that redirects to that URL.
- """
- raise AccountSettingsRenderStarted.RedirectToPage(
- "You can't access this page, redirecting to dashboard."
- )
-
-
-class TestRenderCustomResponse(PipelineStep):
- """
- Utility class used when getting steps for pipeline.
- """
-
- def run_filter(self, context, template_name): # pylint: disable=arguments-differ
- """Pipeline step that returns a custom response when rendering the account settings page."""
- response = HttpResponse("Here's the text of the web page.")
- raise AccountSettingsRenderStarted.RenderCustomResponse(
- "You can't access this page.",
- response=response,
- )
-
-
-class TestAccountSettingsRender(PipelineStep):
- """
- Utility class used when getting steps for pipeline.
- """
-
- def run_filter(self, context, template_name): # pylint: disable=arguments-differ
- """Pipeline step that returns a custom response when rendering the account settings page."""
- template_name = 'static_templates/about.html'
- return {
- "context": context, "template_name": template_name,
- }
-
-
-@skip_unless_lms
-class TestAccountSettingsFilters(SharedModuleStoreTestCase):
- """
- Tests for the Open edX Filters associated with the account settings proccess.
-
- This class guarantees that the following filters are triggered during the user's account settings rendering:
-
- - AccountSettingsRenderStarted
- """
- def setUp(self): # pylint: disable=arguments-differ
- super().setUp()
- self.user = UserFactory.create(
- username="somestudent",
- first_name="Student",
- last_name="Person",
- email="robot@robot.org",
- is_active=True,
- password="password",
- )
- self.client.login(username=self.user.username, password="password")
- self.account_settings_url = '/account/settings'
-
- @override_settings(
- OPEN_EDX_FILTERS_CONFIG={
- "org.openedx.learning.student.settings.render.started.v1": {
- "pipeline": [
- "openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestAccountSettingsRender",
- ],
- "fail_silently": False,
- },
- },
- )
- def test_account_settings_render_filter_executed(self):
- """
- Test whether the account settings filter is triggered before the user's
- account settings page is rendered.
-
- Expected result:
- - AccountSettingsRenderStarted is triggered and executes TestAccountSettingsRender
- """
- response = self.client.get(self.account_settings_url)
- self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertContains(response, "This page left intentionally blank. Feel free to add your own content.")
-
- @override_settings(
- OPEN_EDX_FILTERS_CONFIG={
- "org.openedx.learning.student.settings.render.started.v1": {
- "pipeline": [
- "openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRenderInvalidAccountSettings", # pylint: disable=line-too-long
- ],
- "fail_silently": False,
- },
- },
- PLATFORM_NAME="My site",
- )
- def test_account_settings_render_alternative(self):
- """
- Test whether the account settings filter is triggered before the user's
- account settings page is rendered.
-
- Expected result:
- - AccountSettingsRenderStarted is triggered and executes TestRenderInvalidAccountSettings # pylint: disable=line-too-long
- """
- response = self.client.get(self.account_settings_url)
-
- self.assertContains(response, "There has been a 500 error on the My site servers")
-
- @override_settings(
- OPEN_EDX_FILTERS_CONFIG={
- "org.openedx.learning.student.settings.render.started.v1": {
- "pipeline": [
- "openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRenderCustomResponse",
- ],
- "fail_silently": False,
- },
- },
- )
- def test_account_settings_render_custom_response(self):
- """
- Test whether the account settings filter is triggered before the user's
- account settings page is rendered.
-
- Expected result:
- - AccountSettingsRenderStarted is triggered and executes TestRenderCustomResponse
- """
- response = self.client.get(self.account_settings_url)
-
- self.assertEqual(response.content, b"Here's the text of the web page.")
-
- @override_settings(
- OPEN_EDX_FILTERS_CONFIG={
- "org.openedx.learning.student.settings.render.started.v1": {
- "pipeline": [
- "openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRedirectToPage",
- ],
- "fail_silently": False,
- },
- },
- )
- def test_account_settings_redirect_to_page(self):
- """
- Test whether the account settings filter is triggered before the user's
- account settings page is rendered.
-
- Expected result:
- - AccountSettingsRenderStarted is triggered and executes TestRedirectToPage
- """
- response = self.client.get(self.account_settings_url)
-
- self.assertEqual(response.status_code, status.HTTP_302_FOUND)
- self.assertEqual('/courses', response.url)
-
- @override_settings(
- OPEN_EDX_FILTERS_CONFIG={
- "org.openedx.learning.student.settings.render.started.v1": {
- "pipeline": [
- "openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRedirectToDefaultPage",
- ],
- "fail_silently": False,
- },
- },
- )
- def test_account_settings_redirect_default(self):
- """
- Test whether the account settings filter is triggered before the user's
- account settings page is rendered.
-
- Expected result:
- - AccountSettingsRenderStarted is triggered and executes TestRedirectToDefaultPage
- """
- response = self.client.get(self.account_settings_url)
-
- self.assertEqual(response.status_code, status.HTTP_302_FOUND)
- self.assertEqual(f"{reverse('dashboard')}", response.url)
-
- @override_settings(OPEN_EDX_FILTERS_CONFIG={})
- def test_account_settings_render_without_filter_config(self):
- """
- Test whether the course about filter is triggered before the course about
- render without affecting its execution flow.
-
- Expected result:
- - AccountSettingsRenderStarted executes a noop (empty pipeline). Without any
- modification comparing it with the effects of TestAccountSettingsRender.
- - The view response is HTTP_200_OK.
- """
- response = self.client.get(self.account_settings_url)
-
- self.assertNotContains(response, "This page left intentionally blank. Feel free to add your own content.")
diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py
deleted file mode 100644
index b49be866ff4c..000000000000
--- a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py
+++ /dev/null
@@ -1,271 +0,0 @@
-""" Tests for views related to account settings. """
-
-
-from unittest import mock
-from django.conf import settings
-from django.contrib import messages
-from django.contrib.messages.middleware import MessageMiddleware
-from django.http import HttpRequest
-from django.test import TestCase
-from django.test.utils import override_settings
-from django.urls import reverse
-from edx_rest_api_client import exceptions
-
-from edx_toggles.toggles.testutils import override_waffle_flag
-from lms.djangoapps.commerce.models import CommerceConfiguration
-from lms.djangoapps.commerce.tests import factories
-from lms.djangoapps.commerce.tests.mocks import mock_get_orders
-from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
-from openedx.core.djangoapps.lang_pref.tests.test_api import EN, LT_LT
-from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
-from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
-from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
-from openedx.core.djangoapps.user_api.accounts.settings_views import account_settings_context, get_user_orders
-from openedx.core.djangoapps.user_api.accounts.toggles import REDIRECT_TO_ACCOUNT_MICROFRONTEND
-from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory
-from openedx.core.djangolib.testing.utils import skip_unless_lms
-from openedx.features.enterprise_support.utils import get_enterprise_readonly_account_fields
-from common.djangoapps.student.tests.factories import UserFactory
-from common.djangoapps.third_party_auth.tests.testutil import ThirdPartyAuthTestMixin
-
-
-@skip_unless_lms
-class AccountSettingsViewTest(ThirdPartyAuthTestMixin, SiteMixin, ProgramsApiConfigMixin, TestCase):
- """ Tests for the account settings view. """
-
- USERNAME = 'student'
- PASSWORD = 'password'
- FIELDS = [
- 'country',
- 'gender',
- 'language',
- 'level_of_education',
- 'password',
- 'year_of_birth',
- 'preferred_language',
- 'time_zone',
- ]
-
- @mock.patch("django.conf.settings.MESSAGE_STORAGE", 'django.contrib.messages.storage.cookie.CookieStorage')
- def setUp(self): # pylint: disable=arguments-differ
- super().setUp()
- self.user = UserFactory.create(username=self.USERNAME, password=self.PASSWORD)
- CommerceConfiguration.objects.create(cache_ttl=10, enabled=True)
- self.client.login(username=self.USERNAME, password=self.PASSWORD)
-
- self.request = HttpRequest()
- self.request.user = self.user
-
- # For these tests, two third party auth providers are enabled by default:
- self.configure_google_provider(enabled=True, visible=True)
- self.configure_facebook_provider(enabled=True, visible=True)
-
- # Python-social saves auth failure notifcations in Django messages.
- # See pipeline.get_duplicate_provider() for details.
- self.request.COOKIES = {}
- MessageMiddleware(get_response=lambda request: None).process_request(self.request)
- messages.error(self.request, 'Facebook is already in use.', extra_tags='Auth facebook')
-
- @mock.patch('openedx.features.enterprise_support.api.enterprise_customer_for_request')
- def test_context(self, mock_enterprise_customer_for_request):
- self.request.site = SiteFactory.create()
- UserPreferenceFactory(user=self.user, key='pref-lang', value='lt-lt')
- DarkLangConfig(
- released_languages='en',
- changed_by=self.user,
- enabled=True,
- beta_languages='lt-lt',
- enable_beta_languages=True
- ).save()
- mock_enterprise_customer_for_request.return_value = {}
-
- with override_settings(LANGUAGES=[EN, LT_LT], LANGUAGE_CODE='en'):
- context = account_settings_context(self.request)
-
- user_accounts_api_url = reverse("accounts_api", kwargs={'username': self.user.username})
- assert context['user_accounts_api_url'] == user_accounts_api_url
-
- user_preferences_api_url = reverse('preferences_api', kwargs={'username': self.user.username})
- assert context['user_preferences_api_url'] == user_preferences_api_url
-
- for attribute in self.FIELDS:
- assert attribute in context['fields']
-
- assert context['user_accounts_api_url'] == reverse('accounts_api', kwargs={'username': self.user.username})
- assert context['user_preferences_api_url'] ==\
- reverse('preferences_api', kwargs={'username': self.user.username})
-
- assert context['duplicate_provider'] == 'facebook'
- assert context['auth']['providers'][0]['name'] == 'Facebook'
- assert context['auth']['providers'][1]['name'] == 'Google'
-
- assert context['sync_learner_profile_data'] is False
- assert context['edx_support_url'] == settings.SUPPORT_SITE_LINK
- assert context['enterprise_name'] is None
- assert context['enterprise_readonly_account_fields'] ==\
- {'fields': list(get_enterprise_readonly_account_fields(self.user))}
-
- expected_beta_language = {'code': 'lt-lt', 'name': settings.LANGUAGE_DICT.get('lt-lt')}
- assert context['beta_language'] == expected_beta_language
-
- @mock.patch('openedx.core.djangoapps.user_api.accounts.settings_views.enterprise_customer_for_request')
- @mock.patch('openedx.features.enterprise_support.utils.third_party_auth.provider.Registry.get')
- def test_context_for_enterprise_learner(
- self, mock_get_auth_provider, mock_enterprise_customer_for_request
- ):
- dummy_enterprise_customer = {
- 'uuid': 'real-ent-uuid',
- 'name': 'Dummy Enterprise',
- 'identity_provider': 'saml-ubc'
- }
- mock_enterprise_customer_for_request.return_value = dummy_enterprise_customer
- self.request.site = SiteFactory.create()
- mock_get_auth_provider.return_value.sync_learner_profile_data = True
- context = account_settings_context(self.request)
-
- user_accounts_api_url = reverse("accounts_api", kwargs={'username': self.user.username})
- assert context['user_accounts_api_url'] == user_accounts_api_url
-
- user_preferences_api_url = reverse('preferences_api', kwargs={'username': self.user.username})
- assert context['user_preferences_api_url'] == user_preferences_api_url
-
- for attribute in self.FIELDS:
- assert attribute in context['fields']
-
- assert context['user_accounts_api_url'] == reverse('accounts_api', kwargs={'username': self.user.username})
- assert context['user_preferences_api_url'] ==\
- reverse('preferences_api', kwargs={'username': self.user.username})
-
- assert context['duplicate_provider'] == 'facebook'
- assert context['auth']['providers'][0]['name'] == 'Facebook'
- assert context['auth']['providers'][1]['name'] == 'Google'
-
- assert context['sync_learner_profile_data'] == mock_get_auth_provider.return_value.sync_learner_profile_data
- assert context['edx_support_url'] == settings.SUPPORT_SITE_LINK
- assert context['enterprise_name'] == dummy_enterprise_customer['name']
- assert context['enterprise_readonly_account_fields'] ==\
- {'fields': list(get_enterprise_readonly_account_fields(self.user))}
-
- def test_view(self):
- """
- Test that all fields are visible
- """
- view_path = reverse('account_settings')
- response = self.client.get(path=view_path)
-
- for attribute in self.FIELDS:
- self.assertContains(response, attribute)
-
- def test_header_with_programs_listing_enabled(self):
- """
- Verify that tabs header will be shown while program listing is enabled.
- """
- self.create_programs_config()
- view_path = reverse('account_settings')
- response = self.client.get(path=view_path)
-
- self.assertContains(response, 'global-header')
-
- def test_header_with_programs_listing_disabled(self):
- """
- Verify that nav header will be shown while program listing is disabled.
- """
- self.create_programs_config(enabled=False)
- view_path = reverse('account_settings')
- response = self.client.get(path=view_path)
-
- self.assertContains(response, 'global-header')
-
- def test_commerce_order_detail(self):
- """
- Verify that get_user_orders returns the correct order data.
- """
- with mock_get_orders():
- order_detail = get_user_orders(self.user)
-
- for i, order in enumerate(mock_get_orders.default_response['results']):
- expected = {
- 'number': order['number'],
- 'price': order['total_excl_tax'],
- 'order_date': 'Jan 01, 2016',
- 'receipt_url': '/checkout/receipt/?order_number=' + order['number'],
- 'lines': order['lines'],
- }
- assert order_detail[i] == expected
-
- def test_commerce_order_detail_exception(self):
- with mock_get_orders(exception=exceptions.HttpNotFoundError):
- order_detail = get_user_orders(self.user)
-
- assert not order_detail
-
- def test_incomplete_order_detail(self):
- response = {
- 'results': [
- factories.OrderFactory(
- status='Incomplete',
- lines=[
- factories.OrderLineFactory(
- product=factories.ProductFactory(attribute_values=[factories.ProductAttributeFactory()])
- )
- ]
- )
- ]
- }
- with mock_get_orders(response=response):
- order_detail = get_user_orders(self.user)
-
- assert not order_detail
-
- def test_order_history_with_no_product(self):
- response = {
- 'results': [
- factories.OrderFactory(
- lines=[
- factories.OrderLineFactory(
- product=None
- ),
- factories.OrderLineFactory(
- product=factories.ProductFactory(attribute_values=[factories.ProductAttributeFactory(
- name='certificate_type',
- value='verified'
- )])
- )
- ]
- )
- ]
- }
- with mock_get_orders(response=response):
- order_detail = get_user_orders(self.user)
-
- assert len(order_detail) == 1
-
- def test_redirect_view(self):
- old_url_path = reverse('account_settings')
- with override_waffle_flag(REDIRECT_TO_ACCOUNT_MICROFRONTEND, active=True):
- # Test with waffle flag active and none site setting, redirects to microfrontend
- response = self.client.get(path=old_url_path)
- self.assertRedirects(response, settings.ACCOUNT_MICROFRONTEND_URL, fetch_redirect_response=False)
-
- # Test with waffle flag disabled and site setting disabled, does not redirect
- response = self.client.get(path=old_url_path)
- for attribute in self.FIELDS:
- self.assertContains(response, attribute)
-
- # Test with site setting disabled, does not redirect
- site_domain = 'othersite.example.com'
- site = self.set_up_site(site_domain, {
- 'SITE_NAME': site_domain,
- 'ENABLE_ACCOUNT_MICROFRONTEND': False
- })
- self.client.login(username=self.USERNAME, password=self.PASSWORD)
- response = self.client.get(path=old_url_path)
- for attribute in self.FIELDS:
- self.assertContains(response, attribute)
-
- # Test with site setting enabled, redirects to microfrontend
- site.configuration.site_values['ENABLE_ACCOUNT_MICROFRONTEND'] = True
- site.configuration.save()
- site.__class__.objects.clear_cache()
- response = self.client.get(path=old_url_path)
- self.assertRedirects(response, settings.ACCOUNT_MICROFRONTEND_URL, fetch_redirect_response=False)
diff --git a/openedx/core/djangoapps/user_api/accounts/toggles.py b/openedx/core/djangoapps/user_api/accounts/toggles.py
deleted file mode 100644
index 80de4fa75692..000000000000
--- a/openedx/core/djangoapps/user_api/accounts/toggles.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Toggles for accounts related code.
-"""
-
-from edx_toggles.toggles import WaffleFlag
-
-from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
-
-# .. toggle_name: order_history.redirect_to_microfrontend
-# .. toggle_implementation: WaffleFlag
-# .. toggle_default: False
-# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the order history page.
-# .. toggle_use_cases: temporary, open_edx
-# .. toggle_creation_date: 2019-04-11
-# .. toggle_target_removal_date: 2020-12-31
-# .. toggle_warning: Also set settings.ORDER_HISTORY_MICROFRONTEND_URL and site's
-# ENABLE_ORDER_HISTORY_MICROFRONTEND.
-# .. toggle_tickets: DEPR-17
-REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND = WaffleFlag('order_history.redirect_to_microfrontend', __name__)
-
-
-def should_redirect_to_order_history_microfrontend():
- return (
- configuration_helpers.get_value('ENABLE_ORDER_HISTORY_MICROFRONTEND') and
- REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND.is_enabled()
- )
-
-
-# .. toggle_name: account.redirect_to_microfrontend
-# .. toggle_implementation: WaffleFlag
-# .. toggle_default: False
-# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the account page.
-# Its action can be overridden using site's ENABLE_ACCOUNT_MICROFRONTEND setting.
-# .. toggle_use_cases: temporary, open_edx
-# .. toggle_creation_date: 2019-04-30
-# .. toggle_target_removal_date: 2021-12-31
-# .. toggle_warning: Also set settings.ACCOUNT_MICROFRONTEND_URL.
-# .. toggle_tickets: DEPR-17
-REDIRECT_TO_ACCOUNT_MICROFRONTEND = WaffleFlag('account.redirect_to_microfrontend', __name__)
-
-
-def should_redirect_to_account_microfrontend():
- return configuration_helpers.get_value('ENABLE_ACCOUNT_MICROFRONTEND',
- REDIRECT_TO_ACCOUNT_MICROFRONTEND.is_enabled())
diff --git a/openedx/core/djangoapps/user_api/legacy_urls.py b/openedx/core/djangoapps/user_api/legacy_urls.py
index b3f707f64b50..ad02f7f19ce8 100644
--- a/openedx/core/djangoapps/user_api/legacy_urls.py
+++ b/openedx/core/djangoapps/user_api/legacy_urls.py
@@ -5,7 +5,6 @@
from rest_framework import routers
from . import views as user_api_views
-from .accounts.settings_views import account_settings
from .models import UserPreference
USER_API_ROUTER = routers.DefaultRouter()
@@ -13,7 +12,6 @@
USER_API_ROUTER.register(r'user_prefs', user_api_views.UserPreferenceViewSet)
urlpatterns = [
- path('account/settings', account_settings, name='account_settings'),
path('user_api/v1/', include(USER_API_ROUTER.urls)),
re_path(
fr'^user_api/v1/preferences/(?P{UserPreference.KEY_REGEX})/users/$',
diff --git a/openedx/core/djangoapps/user_authn/cookies.py b/openedx/core/djangoapps/user_authn/cookies.py
index 24f929698fa7..036baf2125b2 100644
--- a/openedx/core/djangoapps/user_authn/cookies.py
+++ b/openedx/core/djangoapps/user_authn/cookies.py
@@ -6,6 +6,7 @@
import json
import logging
import time
+from urllib.parse import urljoin
from django.conf import settings
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
@@ -244,8 +245,8 @@ def _get_user_info_cookie_data(request, user):
# External sites will need to have fallback mechanisms to handle this case
# (most likely just hiding the links).
try:
- header_urls['account_settings'] = reverse('account_settings')
- header_urls['learner_profile'] = reverse('learner_profile', kwargs={'username': user.username})
+ header_urls['account_settings'] = settings.ACCOUNT_MICROFRONTEND_URL
+ header_urls['learner_profile'] = urljoin(settings.PROFILE_MICROFRONTEND_URL, f'/u/{user.username}')
except NoReverseMatch:
pass
diff --git a/openedx/core/djangoapps/user_authn/tests/test_cookies.py b/openedx/core/djangoapps/user_authn/tests/test_cookies.py
index a90f20f19469..826ef1e1209a 100644
--- a/openedx/core/djangoapps/user_authn/tests/test_cookies.py
+++ b/openedx/core/djangoapps/user_authn/tests/test_cookies.py
@@ -4,6 +4,7 @@
from datetime import date
import json
from unittest.mock import MagicMock, patch
+from urllib.parse import urljoin
from django.conf import settings
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
@@ -57,8 +58,8 @@ def _get_expected_image_urls(self):
def _get_expected_header_urls(self):
expected_header_urls = {
'logout': reverse('logout'),
- 'account_settings': reverse('account_settings'),
- 'learner_profile': reverse('learner_profile', kwargs={'username': self.user.username}),
+ 'account_settings': settings.ACCOUNT_MICROFRONTEND_URL,
+ 'learner_profile': urljoin(settings.PROFILE_MICROFRONTEND_URL, f'/u/{self.user.username}'),
}
block_url = retrieve_last_sitewide_block_completed(self.user)
if block_url:
diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
index 1e8a4c3ed510..a8a591083fae 100644
--- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py
+++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
@@ -496,7 +496,7 @@ def test_login_user_info_cookie(self):
# Check that the URLs are absolute
for url in user_info["header_urls"].values():
- assert 'http://testserver/' in url
+ assert 'http://' in url
def test_logout_deletes_mktg_cookies(self):
response, _ = self._login_response(self.user_email, self.password)
diff --git a/openedx/features/learner_profile/README.rst b/openedx/features/learner_profile/README.rst
deleted file mode 100644
index 0dce8e10ccdc..000000000000
--- a/openedx/features/learner_profile/README.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-Learner Profile
----------------
-
-This directory contains a Django application that provides a view to render
-a profile for any Open edX learner. See `Exploring Your Dashboard and Profile`_
-for more details.
-
-.. _Exploring Your Dashboard and Profile: https://edx.readthedocs.io/projects/open-edx-learner-guide/en/latest/SFD_dashboard_profile_SectionHead.html?highlight=profile
diff --git a/openedx/features/learner_profile/__init__.py b/openedx/features/learner_profile/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/openedx/features/learner_profile/static/learner_profile/fixtures/learner_profile.html b/openedx/features/learner_profile/static/learner_profile/fixtures/learner_profile.html
deleted file mode 100644
index 61c139210a20..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/fixtures/learner_profile.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- An error occurred. Try loading the page again.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Loading
-
-
-
-
-
-
- An error occurred. Please reload the page.
-
-
-
diff --git a/openedx/features/learner_profile/static/learner_profile/js/learner_profile_factory.js b/openedx/features/learner_profile/static/learner_profile/js/learner_profile_factory.js
deleted file mode 100644
index 6419dd17703a..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/learner_profile_factory.js
+++ /dev/null
@@ -1,246 +0,0 @@
-(function(define) {
- 'use strict';
-
- define([
- 'gettext',
- 'jquery',
- 'underscore',
- 'backbone',
- 'logger',
- 'edx-ui-toolkit/js/utils/string-utils',
- 'edx-ui-toolkit/js/pagination/paging-collection',
- 'js/student_account/models/user_account_model',
- 'js/student_account/models/user_preferences_model',
- 'js/views/fields',
- 'learner_profile/js/views/learner_profile_fields',
- 'learner_profile/js/views/learner_profile_view',
- 'learner_profile/js/models/badges_model',
- 'learner_profile/js/views/badge_list_container',
- 'js/student_account/views/account_settings_fields',
- 'js/views/message_banner',
- 'string_utils'
- ], function(gettext, $, _, Backbone, Logger, StringUtils, PagingCollection, AccountSettingsModel,
- AccountPreferencesModel, FieldsView, LearnerProfileFieldsView, LearnerProfileView, BadgeModel,
- BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
- return function(options) {
- var $learnerProfileElement = $('.wrapper-profile');
-
- var accountSettingsModel = new AccountSettingsModel(
- _.extend(
- options.account_settings_data,
- {
- default_public_account_fields: options.default_public_account_fields,
- parental_consent_age_limit: options.parental_consent_age_limit,
- enable_coppa_compliance: options.enable_coppa_compliance
- }
- ),
- {parse: true}
- );
- var AccountPreferencesModelWithDefaults = AccountPreferencesModel.extend({
- defaults: {
- account_privacy: options.default_visibility
- }
- });
- var accountPreferencesModel = new AccountPreferencesModelWithDefaults(options.preferences_data);
-
- var editable = options.own_profile ? 'toggle' : 'never';
-
- var messageView = new MessageBannerView({
- el: $('.message-banner')
- });
-
- var accountPrivacyFieldView,
- profileImageFieldView,
- usernameFieldView,
- nameFieldView,
- sectionOneFieldViews,
- sectionTwoFieldViews,
- BadgeCollection,
- badgeCollection,
- badgeListContainer,
- learnerProfileView,
- getProfileVisibility,
- showLearnerProfileView;
-
- accountSettingsModel.url = options.accounts_api_url;
- accountPreferencesModel.url = options.preferences_api_url;
-
- accountPrivacyFieldView = new LearnerProfileFieldsView.AccountPrivacyFieldView({
- model: accountPreferencesModel,
- required: true,
- editable: 'always',
- showMessages: false,
- title: gettext('Profile Visibility:'),
- valueAttribute: 'account_privacy',
- options: [
- ['private', gettext('Limited Profile')],
- ['all_users', gettext('Full Profile')]
- ],
- helpMessage: '',
- accountSettingsPageUrl: options.account_settings_page_url,
- persistChanges: true
- });
-
- profileImageFieldView = new LearnerProfileFieldsView.ProfileImageFieldView({
- model: accountSettingsModel,
- valueAttribute: 'profile_image',
- editable: editable === 'toggle',
- messageView: messageView,
- imageMaxBytes: options.profile_image_max_bytes,
- imageMinBytes: options.profile_image_min_bytes,
- imageUploadUrl: options.profile_image_upload_url,
- imageRemoveUrl: options.profile_image_remove_url
- });
-
- usernameFieldView = new FieldsView.ReadonlyFieldView({
- model: accountSettingsModel,
- screenReaderTitle: gettext('Username'),
- valueAttribute: 'username',
- helpMessage: ''
- });
-
- nameFieldView = new FieldsView.ReadonlyFieldView({
- model: accountSettingsModel,
- screenReaderTitle: gettext('Full Name'),
- valueAttribute: 'name',
- helpMessage: ''
- });
-
- sectionOneFieldViews = [
- new LearnerProfileFieldsView.SocialLinkIconsView({
- model: accountSettingsModel,
- socialPlatforms: options.social_platforms,
- ownProfile: options.own_profile
- }),
-
- new FieldsView.DateFieldView({
- title: gettext('Joined'),
- titleVisible: true,
- model: accountSettingsModel,
- screenReaderTitle: gettext('Joined Date'),
- valueAttribute: 'date_joined',
- helpMessage: '',
- userLanguage: accountSettingsModel.get('language'),
- userTimezone: accountPreferencesModel.get('time_zone'),
- dateFormat: 'MMMM YYYY' // not localized, but hopefully ok.
- }),
-
- new FieldsView.DropdownFieldView({
- title: gettext('Location'),
- titleVisible: true,
- model: accountSettingsModel,
- screenReaderTitle: gettext('Country'),
- required: true,
- editable: editable,
- showMessages: false,
- placeholderValue: gettext('Add Country'),
- valueAttribute: 'country',
- options: options.country_options,
- helpMessage: '',
- persistChanges: true
- }),
-
- new AccountSettingsFieldViews.LanguageProficienciesFieldView({
- title: gettext('Language'),
- titleVisible: true,
- model: accountSettingsModel,
- screenReaderTitle: gettext('Preferred Language'),
- required: false,
- editable: editable,
- showMessages: false,
- placeholderValue: gettext('Add language'),
- valueAttribute: 'language_proficiencies',
- options: options.language_options,
- helpMessage: '',
- persistChanges: true
- })
- ];
-
- sectionTwoFieldViews = [
- new FieldsView.TextareaFieldView({
- model: accountSettingsModel,
- editable: editable,
- showMessages: false,
- title: gettext('About me'),
- // eslint-disable-next-line max-len
- placeholderValue: gettext("Tell other learners a little about yourself: where you live, what your interests are, why you're taking courses, or what you hope to learn."),
- valueAttribute: 'bio',
- helpMessage: '',
- persistChanges: true,
- messagePosition: 'header',
- maxCharacters: 300
- })
- ];
-
- BadgeCollection = PagingCollection.extend({
- queryParams: {
- currentPage: 'current_page'
- }
- });
- badgeCollection = new BadgeCollection();
- badgeCollection.url = options.badges_api_url;
-
- badgeListContainer = new BadgeListContainer({
- attributes: {class: 'badge-set-display'},
- collection: badgeCollection,
- find_courses_url: options.find_courses_url,
- ownProfile: options.own_profile,
- badgeMeta: {
- badges_logo: options.badges_logo,
- backpack_ui_img: options.backpack_ui_img,
- badges_icon: options.badges_icon
- }
- });
-
- learnerProfileView = new LearnerProfileView({
- el: $learnerProfileElement,
- ownProfile: options.own_profile,
- has_preferences_access: options.has_preferences_access,
- accountSettingsModel: accountSettingsModel,
- preferencesModel: accountPreferencesModel,
- accountPrivacyFieldView: accountPrivacyFieldView,
- profileImageFieldView: profileImageFieldView,
- usernameFieldView: usernameFieldView,
- nameFieldView: nameFieldView,
- sectionOneFieldViews: sectionOneFieldViews,
- sectionTwoFieldViews: sectionTwoFieldViews,
- badgeListContainer: badgeListContainer,
- platformName: options.platform_name
- });
-
- getProfileVisibility = function() {
- if (options.has_preferences_access) {
- return accountPreferencesModel.get('account_privacy');
- } else {
- return accountSettingsModel.get('profile_is_public') ? 'all_users' : 'private';
- }
- };
-
- 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();
- };
-
- if (options.has_preferences_access) {
- if (accountSettingsModel.get('requires_parental_consent')) {
- accountPreferencesModel.set('account_privacy', 'private');
- }
- }
- showLearnerProfileView();
-
- return {
- accountSettingsModel: accountSettingsModel,
- accountPreferencesModel: accountPreferencesModel,
- learnerProfileView: learnerProfileView,
- badgeListContainer: badgeListContainer
- };
- };
- });
-}).call(this, define || RequireJS.define);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/models/badges_model.js b/openedx/features/learner_profile/static/learner_profile/js/models/badges_model.js
deleted file mode 100644
index 42da19ef7677..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/models/badges_model.js
+++ /dev/null
@@ -1,8 +0,0 @@
-(function(define) {
- 'use strict';
-
- define(['backbone'], function(Backbone) {
- var BadgesModel = Backbone.Model.extend({});
- return BadgesModel;
- });
-}).call(this, define || RequireJS.define);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/learner_profile_factory_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/learner_profile_factory_spec.js
deleted file mode 100644
index f5b8f4bec6b5..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/learner_profile_factory_spec.js
+++ /dev/null
@@ -1,222 +0,0 @@
-define(
- [
- 'backbone', 'jquery', 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
- 'common/js/spec_helpers/template_helpers',
- 'js/spec/student_account/helpers',
- 'learner_profile/js/spec_helpers/helpers',
- 'js/views/fields',
- 'js/student_account/models/user_account_model',
- 'js/student_account/models/user_preferences_model',
- 'learner_profile/js/views/learner_profile_view',
- 'learner_profile/js/views/learner_profile_fields',
- 'learner_profile/js/learner_profile_factory',
- 'js/views/message_banner'
- ],
- function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers, FieldViews,
- UserAccountModel, UserPreferencesModel, LearnerProfileView, LearnerProfileFields, LearnerProfilePage) {
- 'use strict';
-
- describe('edx.user.LearnerProfileFactory', function() {
- var createProfilePage;
-
- beforeEach(function() {
- loadFixtures('learner_profile/fixtures/learner_profile.html');
- });
-
- afterEach(function() {
- Backbone.history.stop();
- });
-
- createProfilePage = function(ownProfile, options) {
- return new LearnerProfilePage({
- accounts_api_url: Helpers.USER_ACCOUNTS_API_URL,
- preferences_api_url: Helpers.USER_PREFERENCES_API_URL,
- badges_api_url: Helpers.BADGES_API_URL,
- own_profile: ownProfile,
- account_settings_page_url: Helpers.USER_ACCOUNTS_API_URL,
- country_options: Helpers.FIELD_OPTIONS,
- language_options: Helpers.FIELD_OPTIONS,
- has_preferences_access: true,
- profile_image_max_bytes: Helpers.IMAGE_MAX_BYTES,
- profile_image_min_bytes: Helpers.IMAGE_MIN_BYTES,
- profile_image_upload_url: Helpers.IMAGE_UPLOAD_API_URL,
- profile_image_remove_url: Helpers.IMAGE_REMOVE_API_URL,
- default_visibility: 'all_users',
- platform_name: 'edX',
- find_courses_url: '/courses/',
- account_settings_data: Helpers.createAccountSettingsData(options),
- preferences_data: Helpers.createUserPreferencesData()
- });
- };
-
- it('renders the full profile for a user', function() {
- var context,
- learnerProfileView;
- AjaxHelpers.requests(this);
- context = createProfilePage(true);
- learnerProfileView = context.learnerProfileView;
-
- // sets the profile for full view.
- context.accountPreferencesModel.set({account_privacy: 'all_users'});
- LearnerProfileHelpers.expectProfileSectionsAndFieldsToBeRendered(learnerProfileView, false);
- });
-
- it("renders the limited profile for undefined 'year_of_birth'", function() {
- var context = createProfilePage(true, {year_of_birth: '', requires_parental_consent: true}),
- learnerProfileView = context.learnerProfileView;
-
- LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView);
- });
-
- it("doesn't show the mode toggle if badges are disabled", function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: false}),
- tabbedView = context.learnerProfileView.tabbedView,
- learnerProfileView = context.learnerProfileView;
-
- LearnerProfileHelpers.expectTabbedViewToBeUndefined(requests, tabbedView);
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- });
-
- it("doesn't show the mode toggle if badges fail to fetch", function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: false}),
- tabbedView = context.learnerProfileView.tabbedView,
- learnerProfileView = context.learnerProfileView;
-
- LearnerProfileHelpers.expectTabbedViewToBeUndefined(requests, tabbedView);
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- });
-
- it('renders the mode toggle if there are badges', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- tabbedView = context.learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
-
- LearnerProfileHelpers.expectTabbedViewToBeShown(tabbedView);
- });
-
- it('renders the mode toggle if badges enabled but none exist', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- tabbedView = context.learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.emptyBadges);
-
- LearnerProfileHelpers.expectTabbedViewToBeShown(tabbedView);
- });
-
- it('displays the badges when the accomplishments toggle is selected', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- learnerProfileView = context.learnerProfileView,
- tabbedView = learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
-
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- tabbedView.$el.find('[data-url="accomplishments"]').click();
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
- tabbedView.$el.find('[data-url="about_me"]').click();
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- });
-
- it('displays a placeholder on the last page of badges', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- learnerProfileView = context.learnerProfileView,
- tabbedView = learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.thirdPageBadges);
-
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- tabbedView.$el.find('[data-url="accomplishments"]').click();
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, true);
- tabbedView.$el.find('[data-url="about_me"]').click();
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- });
-
- it('displays a placeholder when the accomplishments toggle is selected and no badges exist', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- learnerProfileView = context.learnerProfileView,
- tabbedView = learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.emptyBadges);
-
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- tabbedView.$el.find('[data-url="accomplishments"]').click();
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 0, true);
- tabbedView.$el.find('[data-url="about_me"]').click();
- LearnerProfileHelpers.expectBadgesHidden(learnerProfileView);
- });
-
- it('shows a paginated list of badges', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- learnerProfileView = context.learnerProfileView,
- tabbedView = learnerProfileView.tabbedView;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
-
- tabbedView.$el.find('[data-url="accomplishments"]').click();
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
- LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.firstPageBadges);
- });
-
- it('allows forward and backward navigation of badges', function() {
- var requests = AjaxHelpers.requests(this),
- context = createProfilePage(true, {accomplishments_shared: true}),
- learnerProfileView = context.learnerProfileView,
- tabbedView = learnerProfileView.tabbedView,
- badgeListContainer = context.badgeListContainer;
-
- AjaxHelpers.expectRequest(requests, 'POST', '/event');
- AjaxHelpers.respondWithError(requests, 404);
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
-
- tabbedView.$el.find('[data-url="accomplishments"]').click();
-
- badgeListContainer.$el.find('.next-page-link').click();
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
- LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.secondPageBadges);
-
- badgeListContainer.$el.find('.next-page-link').click();
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.thirdPageBadges);
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, true);
- LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.thirdPageBadges);
-
- badgeListContainer.$el.find('.previous-page-link').click();
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.secondPageBadges);
- LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.secondPageBadges);
- LearnerProfileHelpers.expectBadgesDisplayed(learnerProfileView, 10, false);
-
- badgeListContainer.$el.find('.previous-page-link').click();
- AjaxHelpers.respondWithJson(requests, LearnerProfileHelpers.firstPageBadges);
- LearnerProfileHelpers.expectPage(learnerProfileView, LearnerProfileHelpers.firstPageBadges);
- });
-
- it('renders the limited profile for under 13 users', function() {
- var context = createProfilePage(
- true,
- {year_of_birth: new Date().getFullYear() - 10, requires_parental_consent: true}
- );
- var learnerProfileView = context.learnerProfileView;
- LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView);
- });
- });
- });
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_container_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_container_spec.js
deleted file mode 100644
index 20342c4a6709..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_container_spec.js
+++ /dev/null
@@ -1,99 +0,0 @@
-define([
- 'backbone',
- 'jquery',
- 'underscore',
- 'URI',
- 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
- 'edx-ui-toolkit/js/pagination/paging-collection',
- 'learner_profile/js/spec_helpers/helpers',
- 'learner_profile/js/views/badge_list_container'
-],
-function(Backbone, $, _, URI, AjaxHelpers, PagingCollection, LearnerProfileHelpers, BadgeListContainer) {
- 'use strict';
-
- describe('edx.user.BadgeListContainer', function() {
- var view;
-
- var createView = function(requests, pageNum, badgeListObject) {
- var BadgeCollection = PagingCollection.extend({
- queryParams: {
- currentPage: 'current_page'
- }
- });
- var badgeCollection = new BadgeCollection();
- var models = [];
- var badgeListContainer;
- var request;
- var path;
- badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
- _.each(_.range(badgeListObject.count), function(idx) {
- models.push(LearnerProfileHelpers.makeBadge(idx));
- });
- badgeListObject.results = models; // eslint-disable-line no-param-reassign
- badgeCollection.setPage(pageNum);
- request = AjaxHelpers.currentRequest(requests);
- path = new URI(request.url).path();
- expect(path).toBe('/api/badges/v1/assertions/user/staff/');
- AjaxHelpers.respondWithJson(requests, badgeListObject);
- badgeListContainer = new BadgeListContainer({
- collection: badgeCollection
-
- });
- badgeListContainer.render();
- return badgeListContainer;
- };
-
- afterEach(function() {
- view.$el.remove();
- });
-
- it('displays all badges', function() {
- var requests = AjaxHelpers.requests(this),
- badges;
- view = createView(requests, 1, {
- count: 30,
- previous: '/arbitrary/url',
- num_pages: 3,
- next: null,
- start: 20,
- current_page: 1,
- results: []
- });
- badges = view.$el.find('div.badge-display');
- expect(badges.length).toBe(30);
- });
-
- it('displays placeholder on last page', function() {
- var requests = AjaxHelpers.requests(this),
- placeholder;
- view = createView(requests, 3, {
- count: 30,
- previous: '/arbitrary/url',
- num_pages: 3,
- next: null,
- start: 20,
- current_page: 3,
- results: []
- });
- placeholder = view.$el.find('span.accomplishment-placeholder');
- expect(placeholder.length).toBe(1);
- });
-
- it('does not display placeholder on first page', function() {
- var requests = AjaxHelpers.requests(this),
- placeholder;
- view = createView(requests, 1, {
- count: 30,
- previous: '/arbitrary/url',
- num_pages: 3,
- next: null,
- start: 0,
- current_page: 1,
- results: []
- });
- placeholder = view.$el.find('span.accomplishment-placeholder');
- expect(placeholder.length).toBe(0);
- });
- });
-}
-);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_view_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_view_spec.js
deleted file mode 100644
index e8cfd32d4c38..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_list_view_spec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-define([
- 'backbone',
- 'jquery',
- 'underscore',
- 'edx-ui-toolkit/js/pagination/paging-collection',
- 'learner_profile/js/spec_helpers/helpers',
- 'learner_profile/js/views/badge_list_view'
-],
-function(Backbone, $, _, PagingCollection, LearnerProfileHelpers, BadgeListView) {
- 'use strict';
-
- describe('edx.user.BadgeListView', function() {
- var view;
-
- var createView = function(badges, pages, page, hasNextPage) {
- var badgeCollection = new PagingCollection();
- var models = [];
- var badgeList;
- badgeCollection.url = '/api/badges/v1/assertions/user/staff/';
- _.each(badges, function(element) {
- models.push(new Backbone.Model(element));
- });
- badgeCollection.models = models;
- badgeCollection.length = badges.length;
- badgeCollection.currentPage = page;
- badgeCollection.totalPages = pages;
- badgeCollection.hasNextPage = function() {
- return hasNextPage;
- };
- badgeList = new BadgeListView({
- collection: badgeCollection
-
- });
- return badgeList;
- };
-
- afterEach(function() {
- view.$el.remove();
- });
-
- it('there is a single row if there is only one badge', function() {
- var rows;
- view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 1, false);
- view.render();
- rows = view.$el.find('div.row');
- expect(rows.length).toBe(1);
- });
-
- it('accomplishments placeholder is visible on a last page', function() {
- var placeholder;
- view = createView([LearnerProfileHelpers.makeBadge(1)], 2, 2, false);
- view.render();
- placeholder = view.$el.find('span.accomplishment-placeholder');
- expect(placeholder.length).toBe(1);
- });
-
- it('accomplishments placeholder to be not visible on a first page', function() {
- var placeholder;
- view = createView([LearnerProfileHelpers.makeBadge(1)], 1, 2, true);
- view.render();
- placeholder = view.$el.find('span.accomplishment-placeholder');
- expect(placeholder.length).toBe(0);
- });
-
- it('badges are in two columns (checked by counting rows for a known number of badges)', function() {
- var badges = [];
- var placeholder;
- var rows;
- _.each(_.range(4), function(item) {
- badges.push(LearnerProfileHelpers.makeBadge(item));
- });
- view = createView(badges, 1, 2, true);
- view.render();
- placeholder = view.$el.find('span.accomplishment-placeholder');
- expect(placeholder.length).toBe(0);
- rows = view.$el.find('div.row');
- expect(rows.length).toBe(2);
- });
- });
-}
-);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_view_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_view_spec.js
deleted file mode 100644
index 8ac88ae0b17e..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/badge_view_spec.js
+++ /dev/null
@@ -1,114 +0,0 @@
-define([
- 'backbone', 'jquery', 'underscore',
- 'learner_profile/js/spec_helpers/helpers',
- 'learner_profile/js/views/badge_view'
-],
-function(Backbone, $, _, LearnerProfileHelpers, BadgeView) {
- 'use strict';
-
- describe('edx.user.BadgeView', function() {
- var view,
- badge,
- testBadgeNameIsDisplayed,
- testBadgeIconIsDisplayed;
-
- var createView = function(ownProfile) {
- var options,
- testView;
- badge = LearnerProfileHelpers.makeBadge(1);
- options = {
- model: new Backbone.Model(badge),
- ownProfile: ownProfile,
- badgeMeta: {}
- };
- testView = new BadgeView(options);
- testView.render();
- $('body').append(testView.$el);
- testView.$el.show();
- expect(testView.$el.is(':visible')).toBe(true);
- return testView;
- };
-
- afterEach(function() {
- view.$el.remove();
- $('.badges-modal').remove();
- });
-
- it('profile of other has no share button', function() {
- view = createView(false);
- expect(view.context.ownProfile).toBeFalsy();
- expect(view.$el.find('button.share-button').length).toBe(0);
- });
-
- it('own profile has share button', function() {
- view = createView(true);
- expect(view.context.ownProfile).toBeTruthy();
- expect(view.$el.find('button.share-button').length).toBe(1);
- });
-
- it('click on share button calls createModal function', function() {
- var shareButton;
- view = createView(true);
- spyOn(view, 'createModal');
- view.delegateEvents();
- expect(view.context.ownProfile).toBeTruthy();
- shareButton = view.$el.find('button.share-button');
- expect(shareButton.length).toBe(1);
- expect(view.createModal).not.toHaveBeenCalled();
- shareButton.click();
- expect(view.createModal).toHaveBeenCalled();
- });
-
- it('click on share button calls shows the dialog', function(done) {
- var shareButton,
- $modalElement;
- view = createView(true);
- expect(view.context.ownProfile).toBeTruthy();
- shareButton = view.$el.find('button.share-button');
- expect(shareButton.length).toBe(1);
- $modalElement = $('.badges-modal');
- expect($modalElement.length).toBe(0);
- expect($modalElement.is(':visible')).toBeFalsy();
- shareButton.click();
- // Note: this element should have appeared in the dom during: shareButton.click();
- $modalElement = $('.badges-modal');
- jasmine.waitUntil(function() {
- return $modalElement.is(':visible');
- }).always(done);
- });
-
- testBadgeNameIsDisplayed = function(ownProfile) {
- var badgeDiv;
- view = createView(ownProfile);
- badgeDiv = view.$el.find('.badge-name');
- expect(badgeDiv.length).toBeTruthy();
- expect(badgeDiv.is(':visible')).toBe(true);
- expect(_.count(badgeDiv.html(), badge.badge_class.display_name)).toBeTruthy();
- };
-
- it('test badge name is displayed for own profile', function() {
- testBadgeNameIsDisplayed(true);
- });
-
- it('test badge name is displayed for other profile', function() {
- testBadgeNameIsDisplayed(false);
- });
-
- testBadgeIconIsDisplayed = function(ownProfile) {
- var badgeImg;
- view = createView(ownProfile);
- badgeImg = view.$el.find('img.badge');
- expect(badgeImg.length).toBe(1);
- expect(badgeImg.attr('src')).toEqual(badge.image_url);
- };
-
- it('test badge icon is displayed for own profile', function() {
- testBadgeIconIsDisplayed(true);
- });
-
- it('test badge icon is displayed for other profile', function() {
- testBadgeIconIsDisplayed(false);
- });
- });
-}
-);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_fields_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_fields_spec.js
deleted file mode 100644
index 49b3dbc630df..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_fields_spec.js
+++ /dev/null
@@ -1,381 +0,0 @@
-define(
- [
- 'backbone',
- 'jquery',
- 'underscore',
- 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
- 'common/js/spec_helpers/template_helpers',
- 'js/spec/student_account/helpers',
- 'js/student_account/models/user_account_model',
- 'learner_profile/js/views/learner_profile_fields',
- 'js/views/message_banner'
- ],
- function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, UserAccountModel, LearnerProfileFields,
- MessageBannerView) {
- 'use strict';
-
- describe('edx.user.LearnerProfileFields', function() {
- var MOCK_YEAR_OF_BIRTH = 1989;
- var MOCK_IMAGE_MAX_BYTES = 64;
- var MOCK_IMAGE_MIN_BYTES = 16;
-
- var createImageView = function(options) {
- var yearOfBirth = _.isUndefined(options.yearOfBirth) ? MOCK_YEAR_OF_BIRTH : options.yearOfBirth;
- var imageMaxBytes = _.isUndefined(options.imageMaxBytes) ? MOCK_IMAGE_MAX_BYTES : options.imageMaxBytes;
- var imageMinBytes = _.isUndefined(options.imageMinBytes) ? MOCK_IMAGE_MIN_BYTES : options.imageMinBytes;
- var messageView;
-
- var imageData = {
- image_url_large: '/media/profile-images/default.jpg',
- has_image: !!options.hasImage
- };
-
- var accountSettingsModel = new UserAccountModel();
- accountSettingsModel.set({profile_image: imageData});
- accountSettingsModel.set({year_of_birth: yearOfBirth});
- accountSettingsModel.set({requires_parental_consent: !!_.isEmpty(yearOfBirth)});
-
- accountSettingsModel.url = Helpers.USER_ACCOUNTS_API_URL;
-
- messageView = new MessageBannerView({
- el: $('.message-banner')
- });
-
- return new LearnerProfileFields.ProfileImageFieldView({
- model: accountSettingsModel,
- valueAttribute: 'profile_image',
- editable: options.ownProfile,
- messageView: messageView,
- imageMaxBytes: imageMaxBytes,
- imageMinBytes: imageMinBytes,
- imageUploadUrl: Helpers.IMAGE_UPLOAD_API_URL,
- imageRemoveUrl: Helpers.IMAGE_REMOVE_API_URL
- });
- };
-
- var createSocialLinksView = function(ownProfile, socialPlatformLinks) {
- var accountSettingsModel = new UserAccountModel();
- accountSettingsModel.set({social_platforms: socialPlatformLinks});
-
- return new LearnerProfileFields.SocialLinkIconsView({
- model: accountSettingsModel,
- socialPlatforms: ['twitter', 'facebook', 'linkedin'],
- ownProfile: ownProfile
- });
- };
-
- var createFakeImageFile = function(size) {
- var fileFakeData = 'i63ljc6giwoskyb9x5sw0169bdcmcxr3cdz8boqv0lik971972cmd6yknvcxr5sw0nvc169bdcmcxsdf';
- return new Blob(
- [fileFakeData.substr(0, size)],
- {type: 'image/jpg'}
- );
- };
-
- var initializeUploader = function(view) {
- view.$('.upload-button-input').fileupload({
- url: Helpers.IMAGE_UPLOAD_API_URL,
- type: 'POST',
- add: view.fileSelected,
- done: view.imageChangeSucceeded,
- fail: view.imageChangeFailed
- });
- };
-
- beforeEach(function() {
- loadFixtures('learner_profile/fixtures/learner_profile.html');
- TemplateHelpers.installTemplate('templates/fields/field_image');
- TemplateHelpers.installTemplate('templates/fields/message_banner');
- TemplateHelpers.installTemplate('learner_profile/templates/social_icons');
- });
-
- afterEach(function() {
- // image_field.js's window.onBeforeUnload breaks Karma in Chrome, clean it up after each test
- $(window).off('beforeunload');
- });
-
- describe('ProfileImageFieldView', function() {
- var verifyImageUploadButtonMessage = function(view, inProgress) {
- var iconName = inProgress ? 'fa-spinner' : 'fa-camera';
- var message = inProgress ? view.titleUploading : view.uploadButtonTitle();
- expect(view.$('.upload-button-icon span').attr('class')).toContain(iconName);
- expect(view.$('.upload-button-title').text().trim()).toBe(message);
- };
-
- var verifyImageRemoveButtonMessage = function(view, inProgress) {
- var iconName = inProgress ? 'fa-spinner' : 'fa-remove';
- var message = inProgress ? view.titleRemoving : view.removeButtonTitle();
- expect(view.$('.remove-button-icon span').attr('class')).toContain(iconName);
- expect(view.$('.remove-button-title').text().trim()).toBe(message);
- };
-
- it('can upload profile image', function() {
- var requests = AjaxHelpers.requests(this);
- var imageName = 'profile_image.jpg';
- var imageView = createImageView({ownProfile: true, hasImage: false});
- var data;
- imageView.render();
-
- initializeUploader(imageView);
-
- // Remove button should not be present for default image
- expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
-
- // For default image, image title should be `Upload an image`
- verifyImageUploadButtonMessage(imageView, false);
-
- // Add image to upload queue. Validate the image size and send POST request to upload image
- imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(60)]});
-
- // Verify image upload progress message
- verifyImageUploadButtonMessage(imageView, true);
-
- // Verify if POST request received for image upload
- AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_UPLOAD_API_URL, new FormData());
-
- // Send 204 NO CONTENT to confirm the image upload success
- AjaxHelpers.respondWithNoContent(requests);
-
- // Upon successful image upload, account settings model will be fetched to
- // get the url for newly uploaded image, So we need to send the response for that GET
- data = {
- profile_image: {
- image_url_large: '/media/profile-images/' + imageName,
- has_image: true
- }
- };
- AjaxHelpers.respondWithJson(requests, data);
-
- // Verify uploaded image name
- expect(imageView.$('.image-frame').attr('src')).toContain(imageName);
-
- // Remove button should be present after successful image upload
- expect(imageView.$('.u-field-remove-button').css('display') !== 'none').toBeTruthy();
-
- // After image upload, image title should be `Change image`
- verifyImageUploadButtonMessage(imageView, false);
- });
-
- it('can remove profile image', function() {
- var requests = AjaxHelpers.requests(this);
- var imageView = createImageView({ownProfile: true, hasImage: false});
- var data;
- imageView.render();
-
- // Verify image remove title
- verifyImageRemoveButtonMessage(imageView, false);
-
- imageView.$('.u-field-remove-button').click();
-
- // Verify image remove progress message
- verifyImageRemoveButtonMessage(imageView, true);
-
- // Verify if POST request received for image remove
- AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_REMOVE_API_URL, null);
-
- // Send 204 NO CONTENT to confirm the image removal success
- AjaxHelpers.respondWithNoContent(requests);
-
- // Upon successful image removal, account settings model will be fetched to get default image url
- // So we need to send the response for that GET
- data = {
- profile_image: {
- image_url_large: '/media/profile-images/default.jpg',
- has_image: false
- }
- };
- AjaxHelpers.respondWithJson(requests, data);
-
- // Remove button should not be present for default image
- expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
- });
-
- it("can't remove default profile image", function() {
- var imageView = createImageView({ownProfile: true, hasImage: false});
- imageView.render();
-
- spyOn(imageView, 'clickedRemoveButton');
-
- // Remove button should not be present for default image
- expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
-
- imageView.$('.u-field-remove-button').click();
-
- // Remove button click handler should not be called
- expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
- });
-
- it("can't upload image having size greater than max size", function() {
- var imageView = createImageView({ownProfile: true, hasImage: false});
- imageView.render();
-
- initializeUploader(imageView);
-
- // Add image to upload queue, this will validate the image size
- imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(70)]});
-
- // Verify error message
- expect($('.message-banner').text().trim())
- .toBe('The file must be smaller than 64 bytes in size.');
- });
-
- it("can't upload image having size less than min size", function() {
- var imageView = createImageView({ownProfile: true, hasImage: false});
- imageView.render();
-
- initializeUploader(imageView);
-
- // Add image to upload queue, this will validate the image size
- imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(10)]});
-
- // Verify error message
- expect($('.message-banner').text().trim()).toBe('The file must be at least 16 bytes in size.');
- });
-
- it("can't upload and remove image if parental consent required", function() {
- var imageView = createImageView({ownProfile: true, hasImage: false, yearOfBirth: ''});
- imageView.render();
-
- spyOn(imageView, 'clickedUploadButton');
- spyOn(imageView, 'clickedRemoveButton');
-
- expect(imageView.$('.u-field-upload-button').css('display') === 'none').toBeTruthy();
- expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
-
- imageView.$('.u-field-upload-button').click();
- imageView.$('.u-field-remove-button').click();
-
- expect(imageView.clickedUploadButton).not.toHaveBeenCalled();
- expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
- });
-
- it("can't upload and remove image on others profile", function() {
- var imageView = createImageView({ownProfile: false});
- imageView.render();
-
- spyOn(imageView, 'clickedUploadButton');
- spyOn(imageView, 'clickedRemoveButton');
-
- expect(imageView.$('.u-field-upload-button').css('display') === 'none').toBeTruthy();
- expect(imageView.$('.u-field-remove-button').css('display') === 'none').toBeTruthy();
-
- imageView.$('.u-field-upload-button').click();
- imageView.$('.u-field-remove-button').click();
-
- expect(imageView.clickedUploadButton).not.toHaveBeenCalled();
- expect(imageView.clickedRemoveButton).not.toHaveBeenCalled();
- });
-
- it('shows message if we try to navigate away during image upload/remove', function() {
- var imageView = createImageView({ownProfile: true, hasImage: false});
- spyOn(imageView, 'onBeforeUnload');
- imageView.render();
-
- initializeUploader(imageView);
-
- // Add image to upload queue, this will validate image size and send POST request to upload image
- imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(60)]});
-
- // Verify image upload progress message
- verifyImageUploadButtonMessage(imageView, true);
-
- window.onbeforeunload = null;
- $(window).trigger('beforeunload');
- expect(imageView.onBeforeUnload).toHaveBeenCalled();
- });
-
- it('shows error message for HTTP 500', function() {
- var requests = AjaxHelpers.requests(this);
- var imageView = createImageView({ownProfile: true, hasImage: false});
- imageView.render();
-
- initializeUploader(imageView);
-
- // Add image to upload queue. Validate the image size and send POST request to upload image
- imageView.$('.upload-button-input').fileupload('add', {files: [createFakeImageFile(60)]});
-
- // Verify image upload progress message
- verifyImageUploadButtonMessage(imageView, true);
-
- // Verify if POST request received for image upload
- AjaxHelpers.expectRequest(requests, 'POST', Helpers.IMAGE_UPLOAD_API_URL, new FormData());
-
- // Send HTTP 500
- AjaxHelpers.respondWithError(requests);
-
- expect($('.message-banner').text().trim()).toBe(imageView.errorMessage);
- });
- });
-
- describe('SocialLinkIconsView', function() {
- var socialPlatformLinks,
- socialLinkData,
- socialLinksView,
- socialPlatform,
- $icon;
-
- it('icons are visible and links to social profile if added in account settings', function() {
- socialPlatformLinks = {
- twitter: {
- platform: 'twitter',
- social_link: 'https://www.twitter.com/edX'
- },
- facebook: {
- platform: 'facebook',
- social_link: 'https://www.facebook.com/edX'
- },
- linkedin: {
- platform: 'linkedin',
- social_link: ''
- }
- };
-
- socialLinksView = createSocialLinksView(true, socialPlatformLinks);
-
- // Icons should be present and contain links if defined
- for (var i = 0; i < Object.keys(socialPlatformLinks); i++) { // eslint-disable-line vars-on-top
- socialPlatform = Object.keys(socialPlatformLinks)[i];
- socialLinkData = socialPlatformLinks[socialPlatform];
- if (socialLinkData.social_link) {
- // Icons with a social_link value should be displayed with a surrounding link
- $icon = socialLinksView.$('span.fa-' + socialPlatform + '-square');
- expect($icon).toExist();
- expect($icon.parent().is('a'));
- } else {
- // Icons without a social_link value should be displayed without a surrounding link
- $icon = socialLinksView.$('span.fa-' + socialPlatform + '-square');
- expect($icon).toExist();
- expect(!$icon.parent().is('a'));
- }
- }
- });
-
- it('icons are not visible on a profile with no links', function() {
- socialPlatformLinks = {
- twitter: {
- platform: 'twitter',
- social_link: ''
- },
- facebook: {
- platform: 'facebook',
- social_link: ''
- },
- linkedin: {
- platform: 'linkedin',
- social_link: ''
- }
- };
-
- socialLinksView = createSocialLinksView(false, socialPlatformLinks);
-
- // Icons should not be present if not defined on another user's profile
- for (var i = 0; i < Object.keys(socialPlatformLinks); i++) { // eslint-disable-line vars-on-top
- socialPlatform = Object.keys(socialPlatformLinks)[i];
- socialLinkData = socialPlatformLinks[socialPlatform];
- $icon = socialLinksView.$('span.fa-' + socialPlatform + '-square');
- expect($icon).toBe(null);
- }
- });
- });
- });
- });
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_view_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_view_spec.js
deleted file mode 100644
index 1797b0de05e7..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/learner_profile_view_spec.js
+++ /dev/null
@@ -1,240 +0,0 @@
-/* eslint-disable vars-on-top */
-define(
- [
- 'gettext',
- 'backbone',
- 'jquery',
- 'underscore',
- 'edx-ui-toolkit/js/pagination/paging-collection',
- 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
- 'common/js/spec_helpers/template_helpers',
- 'js/spec/student_account/helpers',
- 'learner_profile/js/spec_helpers/helpers',
- 'js/views/fields',
- 'js/student_account/models/user_account_model',
- 'js/student_account/models/user_preferences_model',
- 'learner_profile/js/views/learner_profile_fields',
- 'learner_profile/js/views/learner_profile_view',
- 'learner_profile/js/views/badge_list_container',
- 'js/student_account/views/account_settings_fields',
- 'js/views/message_banner'
- ],
- function(gettext, Backbone, $, _, PagingCollection, AjaxHelpers, TemplateHelpers, Helpers, LearnerProfileHelpers,
- FieldViews, UserAccountModel, AccountPreferencesModel, LearnerProfileFields, LearnerProfileView,
- BadgeListContainer, AccountSettingsFieldViews, MessageBannerView) {
- 'use strict';
-
- describe('edx.user.LearnerProfileView', function() {
- var createLearnerProfileView = function(ownProfile, accountPrivacy, profileIsPublic) {
- var accountSettingsModel = new UserAccountModel();
- accountSettingsModel.set(Helpers.createAccountSettingsData());
- accountSettingsModel.set({profile_is_public: profileIsPublic});
- accountSettingsModel.set({profile_image: Helpers.PROFILE_IMAGE});
-
- var accountPreferencesModel = new AccountPreferencesModel();
- accountPreferencesModel.set({account_privacy: accountPrivacy});
-
- accountPreferencesModel.url = Helpers.USER_PREFERENCES_API_URL;
-
- var editable = ownProfile ? 'toggle' : 'never';
-
- var accountPrivacyFieldView = new LearnerProfileFields.AccountPrivacyFieldView({
- model: accountPreferencesModel,
- required: true,
- editable: 'always',
- showMessages: false,
- title: 'edX learners can see my:',
- valueAttribute: 'account_privacy',
- options: [
- ['all_users', 'Full Profile'],
- ['private', 'Limited Profile']
- ],
- helpMessage: '',
- accountSettingsPageUrl: '/account/settings/'
- });
-
- var messageView = new MessageBannerView({
- el: $('.message-banner')
- });
-
- var profileImageFieldView = new LearnerProfileFields.ProfileImageFieldView({
- model: accountSettingsModel,
- valueAttribute: 'profile_image',
- editable: editable,
- messageView: messageView,
- imageMaxBytes: Helpers.IMAGE_MAX_BYTES,
- imageMinBytes: Helpers.IMAGE_MIN_BYTES,
- imageUploadUrl: Helpers.IMAGE_UPLOAD_API_URL,
- imageRemoveUrl: Helpers.IMAGE_REMOVE_API_URL
- });
-
- var usernameFieldView = new FieldViews.ReadonlyFieldView({
- model: accountSettingsModel,
- valueAttribute: 'username',
- helpMessage: ''
- });
-
- var nameFieldView = new FieldViews.ReadonlyFieldView({
- model: accountSettingsModel,
- valueAttribute: 'name',
- helpMessage: ''
- });
-
- var sectionOneFieldViews = [
- new LearnerProfileFields.SocialLinkIconsView({
- model: accountSettingsModel,
- socialPlatforms: Helpers.SOCIAL_PLATFORMS,
- ownProfile: true
- }),
-
- new FieldViews.DropdownFieldView({
- title: gettext('Location'),
- model: accountSettingsModel,
- required: false,
- editable: editable,
- showMessages: false,
- placeholderValue: '',
- valueAttribute: 'country',
- options: Helpers.FIELD_OPTIONS,
- helpMessage: ''
- }),
-
- new AccountSettingsFieldViews.LanguageProficienciesFieldView({
- title: gettext('Language'),
- model: accountSettingsModel,
- required: false,
- editable: editable,
- showMessages: false,
- placeholderValue: 'Add language',
- valueAttribute: 'language_proficiencies',
- options: Helpers.FIELD_OPTIONS,
- helpMessage: ''
- }),
-
- new FieldViews.DateFieldView({
- model: accountSettingsModel,
- valueAttribute: 'date_joined',
- helpMessage: ''
- })
- ];
-
- var sectionTwoFieldViews = [
- new FieldViews.TextareaFieldView({
- model: accountSettingsModel,
- editable: editable,
- showMessages: false,
- title: 'About me',
- placeholderValue: 'Tell other edX learners a little about yourself: where you live, '
- + "what your interests are, why you're taking courses on edX, or what you hope to learn.",
- valueAttribute: 'bio',
- helpMessage: '',
- messagePosition: 'header'
- })
- ];
-
- var badgeCollection = new PagingCollection();
- badgeCollection.url = Helpers.BADGES_API_URL;
-
- var badgeListContainer = new BadgeListContainer({
- attributes: {class: 'badge-set-display'},
- collection: badgeCollection,
- find_courses_url: Helpers.FIND_COURSES_URL
- });
-
- return new LearnerProfileView(
- {
- el: $('.wrapper-profile'),
- ownProfile: ownProfile,
- hasPreferencesAccess: true,
- accountSettingsModel: accountSettingsModel,
- preferencesModel: accountPreferencesModel,
- accountPrivacyFieldView: accountPrivacyFieldView,
- usernameFieldView: usernameFieldView,
- nameFieldView: nameFieldView,
- profileImageFieldView: profileImageFieldView,
- sectionOneFieldViews: sectionOneFieldViews,
- sectionTwoFieldViews: sectionTwoFieldViews,
- badgeListContainer: badgeListContainer
- });
- };
-
- beforeEach(function() {
- loadFixtures('learner_profile/fixtures/learner_profile.html');
- });
-
- afterEach(function() {
- Backbone.history.stop();
- });
-
- it('shows loading error correctly', function() {
- var learnerProfileView = createLearnerProfileView(false, 'all_users');
-
- Helpers.expectLoadingIndicatorIsVisible(learnerProfileView, true);
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
-
- learnerProfileView.render();
- learnerProfileView.showLoadingError();
-
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, true);
- });
-
- it('renders all fields as expected for self with full access', function() {
- var learnerProfileView = createLearnerProfileView(true, 'all_users', true);
-
- Helpers.expectLoadingIndicatorIsVisible(learnerProfileView, true);
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
-
- learnerProfileView.render();
-
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
- LearnerProfileHelpers.expectProfileSectionsAndFieldsToBeRendered(learnerProfileView);
- });
-
- it('renders all fields as expected for self with limited access', function() {
- var learnerProfileView = createLearnerProfileView(true, 'private', false);
-
- Helpers.expectLoadingIndicatorIsVisible(learnerProfileView, true);
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
-
- learnerProfileView.render();
-
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
- LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView);
- });
-
- it('renders the fields as expected for others with full access', function() {
- var learnerProfileView = createLearnerProfileView(false, 'all_users', true);
-
- Helpers.expectLoadingIndicatorIsVisible(learnerProfileView, true);
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
-
- learnerProfileView.render();
-
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
- LearnerProfileHelpers.expectProfileSectionsAndFieldsToBeRendered(learnerProfileView, true);
- });
-
- it('renders the fields as expected for others with limited access', function() {
- var learnerProfileView = createLearnerProfileView(false, 'private', false);
-
- Helpers.expectLoadingIndicatorIsVisible(learnerProfileView, true);
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
-
- learnerProfileView.render();
-
- Helpers.expectLoadingErrorIsVisible(learnerProfileView, false);
- LearnerProfileHelpers.expectLimitedProfileSectionsAndFieldsToBeRendered(learnerProfileView, true);
- });
-
- it("renders an error if the badges can't be fetched", function() {
- var learnerProfileView = createLearnerProfileView(false, 'all_users', true);
- learnerProfileView.options.accountSettingsModel.set({accomplishments_shared: true});
- var requests = AjaxHelpers.requests(this);
-
- learnerProfileView.render();
-
- LearnerProfileHelpers.breakBadgeLoading(learnerProfileView, requests);
- LearnerProfileHelpers.expectBadgeLoadingErrorIsRendered(learnerProfileView);
- });
- });
- });
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/section_two_tab_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/section_two_tab_spec.js
deleted file mode 100644
index d0e22d670beb..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/section_two_tab_spec.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/* eslint-disable vars-on-top */
-define(
- [
- 'backbone', 'jquery', 'underscore',
- 'js/spec/student_account/helpers',
- 'learner_profile/js/views/section_two_tab',
- 'js/views/fields',
- 'js/student_account/models/user_account_model'
- ],
- function(Backbone, $, _, Helpers, SectionTwoTabView, FieldViews, UserAccountModel) {
- 'use strict';
-
- describe('edx.user.SectionTwoTab', function() {
- var createSectionTwoView = function(ownProfile, profileIsPublic) {
- var accountSettingsModel = new UserAccountModel();
- accountSettingsModel.set(Helpers.createAccountSettingsData());
- accountSettingsModel.set({profile_is_public: profileIsPublic});
- accountSettingsModel.set({profile_image: Helpers.PROFILE_IMAGE});
-
- var editable = ownProfile ? 'toggle' : 'never';
-
- var sectionTwoFieldViews = [
- new FieldViews.TextareaFieldView({
- model: accountSettingsModel,
- editable: editable,
- showMessages: false,
- title: 'About me',
- placeholderValue: 'Tell other edX learners a little about yourself: where you live, '
- + "what your interests are, why you're taking courses on edX, or what you hope to learn.",
- valueAttribute: 'bio',
- helpMessage: '',
- messagePosition: 'header'
- })
- ];
-
- return new SectionTwoTabView({
- viewList: sectionTwoFieldViews,
- showFullProfile: function() {
- return profileIsPublic;
- },
- ownProfile: ownProfile
- });
- };
-
- it('full profile displayed for public profile', function() {
- var view = createSectionTwoView(false, true);
- view.render();
- var bio = view.$el.find('.u-field-bio');
- expect(bio.length).toBe(1);
- });
-
- it('profile field parts are actually rendered for public profile', function() {
- var view = createSectionTwoView(false, true);
- _.each(view.options.viewList, function(fieldView) {
- spyOn(fieldView, 'render').and.callThrough();
- });
- view.render();
- _.each(view.options.viewList, function(fieldView) {
- expect(fieldView.render).toHaveBeenCalled();
- });
- });
-
- var testPrivateProfile = function(ownProfile, messageString) {
- var view = createSectionTwoView(ownProfile, false);
- view.render();
- var bio = view.$el.find('.u-field-bio');
- expect(bio.length).toBe(0);
- var msg = view.$el.find('span.profile-private-message');
- expect(msg.length).toBe(1);
- expect(_.count(msg.html(), messageString)).toBeTruthy();
- };
-
- it('no profile when profile is private for other people', function() {
- testPrivateProfile(false, 'This learner is currently sharing a limited profile');
- });
-
- it('no profile when profile is private for the user herself', function() {
- testPrivateProfile(true, 'You are currently sharing a limited profile');
- });
-
- var testProfilePrivatePartsDoNotRender = function(ownProfile) {
- var view = createSectionTwoView(ownProfile, false);
- _.each(view.options.viewList, function(fieldView) {
- spyOn(fieldView, 'render');
- });
- view.render();
- _.each(view.options.viewList, function(fieldView) {
- expect(fieldView.render).not.toHaveBeenCalled();
- });
- };
-
- it('profile field parts are not rendered for private profile for owner', function() {
- testProfilePrivatePartsDoNotRender(true);
- });
-
- it('profile field parts are not rendered for private profile for other people', function() {
- testProfilePrivatePartsDoNotRender(false);
- });
-
- it('does not allow fields to be edited when visiting a profile for other people', function() {
- var view = createSectionTwoView(false, true);
- var bio = view.options.viewList[0];
- expect(bio.editable).toBe('never');
- });
-
- it("allows fields to be edited when visiting one's own profile", function() {
- var view = createSectionTwoView(true, true);
- var bio = view.options.viewList[0];
- expect(bio.editable).toBe('toggle');
- });
- });
- }
-);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec/views/share_modal_view_spec.js b/openedx/features/learner_profile/static/learner_profile/js/spec/views/share_modal_view_spec.js
deleted file mode 100644
index e3d15659ffa6..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec/views/share_modal_view_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-define(
- [
- 'backbone', 'jquery', 'underscore', 'moment',
- 'js/spec/student_account/helpers',
- 'learner_profile/js/spec_helpers/helpers',
- 'learner_profile/js/views/share_modal_view',
- 'jquery.simulate'
- ],
- function(Backbone, $, _, Moment, Helpers, LearnerProfileHelpers, ShareModalView) {
- 'use strict';
-
- describe('edx.user.ShareModalView', function() {
- var keys = $.simulate.keyCode;
-
- var view;
-
- var createModalView = function() {
- var badge = LearnerProfileHelpers.makeBadge(1);
- var context = _.extend(badge, {
- created: new Moment(badge.created),
- ownProfile: true,
- badgeMeta: {}
- });
- return new ShareModalView({
- model: new Backbone.Model(context),
- shareButton: $('')
- });
- };
-
- beforeEach(function() {
- view = createModalView();
- // Attach view to document, otherwise click won't work
- view.render();
- $('body').append(view.$el);
- view.$el.show();
- expect(view.$el.is(':visible')).toBe(true);
- });
-
- afterEach(function() {
- view.$el.remove();
- });
-
- it('modal view closes on escape', function() {
- spyOn(view, 'close');
- view.delegateEvents();
- expect(view.close).not.toHaveBeenCalled();
- $(view.$el).simulate('keydown', {keyCode: keys.ESCAPE});
- expect(view.close).toHaveBeenCalled();
- });
-
- it('modal view closes click on close', function() {
- var $closeButton;
- spyOn(view, 'close');
- view.delegateEvents();
- $closeButton = view.$el.find('button.close');
- expect($closeButton.length).toBe(1);
- expect(view.close).not.toHaveBeenCalled();
- $closeButton.trigger('click');
- expect(view.close).toHaveBeenCalled();
- });
- });
- }
-);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/spec_helpers/helpers.js b/openedx/features/learner_profile/static/learner_profile/js/spec_helpers/helpers.js
deleted file mode 100644
index 5d4a278907ca..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/spec_helpers/helpers.js
+++ /dev/null
@@ -1,259 +0,0 @@
-define(['underscore', 'URI', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'], function(_, URI, AjaxHelpers) {
- 'use strict';
-
- var expectProfileElementContainsField = function(element, view) {
- var titleElement, fieldTitle;
- var $element = $(element);
-
- // Avoid testing for elements without titles
- titleElement = $element.find('.u-field-title');
- if (titleElement.length === 0) {
- return;
- }
-
- fieldTitle = titleElement.text().trim();
- if (!_.isUndefined(view.options.title) && !_.isUndefined(fieldTitle)) {
- expect(fieldTitle).toBe(view.options.title);
- }
-
- if ('fieldValue' in view || 'imageUrl' in view) {
- if ('imageUrl' in view) {
- expect($($element.find('.image-frame')[0]).attr('src')).toBe(view.imageUrl());
- } else if (view.fieldType === 'date') {
- expect(view.fieldValue()).toBe(view.timezoneFormattedDate());
- } else if (view.fieldValue()) {
- expect(view.fieldValue()).toBe(view.modelValue());
- } else if ('optionForValue' in view) {
- expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(
- view.displayValue(view.modelValue())
- );
- } else {
- expect($($element.find('.u-field-value .u-field-value-readonly')[0]).text()).toBe(view.modelValue());
- }
- } else {
- throw new Error('Unexpected field type: ' + view.fieldType);
- }
- };
-
- var expectProfilePrivacyFieldTobeRendered = function(learnerProfileView, othersProfile) {
- var $accountPrivacyElement = $('.wrapper-profile-field-account-privacy');
- var $privacyFieldElement = $($accountPrivacyElement).find('.u-field');
-
- if (othersProfile) {
- expect($privacyFieldElement.length).toBe(0);
- } else {
- expect($privacyFieldElement.length).toBe(1);
- expectProfileElementContainsField($privacyFieldElement, learnerProfileView.options.accountPrivacyFieldView);
- }
- };
-
- var expectSectionOneTobeRendered = function(learnerProfileView) {
- var sectionOneFieldElements = $(learnerProfileView.$('.wrapper-profile-section-one'))
- .find('.u-field, .social-links');
-
- expect(sectionOneFieldElements.length).toBe(7);
- expectProfileElementContainsField(sectionOneFieldElements[0], learnerProfileView.options.profileImageFieldView);
- expectProfileElementContainsField(sectionOneFieldElements[1], learnerProfileView.options.usernameFieldView);
- expectProfileElementContainsField(sectionOneFieldElements[2], learnerProfileView.options.nameFieldView);
-
- _.each(_.rest(sectionOneFieldElements, 3), function(sectionFieldElement, fieldIndex) {
- expectProfileElementContainsField(
- sectionFieldElement,
- learnerProfileView.options.sectionOneFieldViews[fieldIndex]
- );
- });
- };
-
- var expectSectionTwoTobeRendered = function(learnerProfileView) {
- var $sectionTwoElement = $('.wrapper-profile-section-two');
- var $sectionTwoFieldElements = $($sectionTwoElement).find('.u-field');
-
- expect($sectionTwoFieldElements.length).toBe(learnerProfileView.options.sectionTwoFieldViews.length);
-
- _.each($sectionTwoFieldElements, function(sectionFieldElement, fieldIndex) {
- expectProfileElementContainsField(
- sectionFieldElement,
- learnerProfileView.options.sectionTwoFieldViews[fieldIndex]
- );
- });
- };
-
- var expectProfileSectionsAndFieldsToBeRendered = function(learnerProfileView, othersProfile) {
- expectProfilePrivacyFieldTobeRendered(learnerProfileView, othersProfile);
- expectSectionOneTobeRendered(learnerProfileView);
- expectSectionTwoTobeRendered(learnerProfileView);
- };
-
- var expectLimitedProfileSectionsAndFieldsToBeRendered = function(learnerProfileView, othersProfile) {
- var sectionOneFieldElements = $('.wrapper-profile-section-one').find('.u-field');
-
- expectProfilePrivacyFieldTobeRendered(learnerProfileView, othersProfile);
-
- expect(sectionOneFieldElements.length).toBe(2);
- expectProfileElementContainsField(
- sectionOneFieldElements[0],
- learnerProfileView.options.profileImageFieldView
- );
- expectProfileElementContainsField(
- sectionOneFieldElements[1],
- learnerProfileView.options.usernameFieldView
- );
-
- if (othersProfile) {
- expect($('.profile-private-message').text())
- .toBe('This learner is currently sharing a limited profile.');
- } else {
- expect($('.profile-private-message').text()).toBe('You are currently sharing a limited profile.');
- }
- };
-
- var expectProfileSectionsNotToBeRendered = function() {
- expect($('.wrapper-profile-field-account-privacy').length).toBe(0);
- expect($('.wrapper-profile-section-one').length).toBe(0);
- expect($('.wrapper-profile-section-two').length).toBe(0);
- };
-
- var expectTabbedViewToBeUndefined = function(requests, tabbedViewView) {
- // Unrelated initial request, no badge request
- expect(requests.length).toBe(1);
- expect(tabbedViewView).toBe(undefined);
- };
-
- var expectTabbedViewToBeShown = function(tabbedViewView) {
- expect(tabbedViewView.$el.find('.page-content-nav').is(':visible')).toBe(true);
- };
-
- var expectBadgesDisplayed = function(learnerProfileView, length, lastPage) {
- var $badgeListingView = $('#tabpanel-accomplishments'),
- updatedLength = length,
- placeholder;
- expect($('#tabpanel-about_me').hasClass('is-hidden')).toBe(true);
- expect($badgeListingView.hasClass('is-hidden')).toBe(false);
- if (lastPage) {
- updatedLength += 1;
- placeholder = $badgeListingView.find('.find-course');
- expect(placeholder.length).toBe(1);
- expect(placeholder.attr('href')).toBe('/courses/');
- }
- expect($badgeListingView.find('.badge-display').length).toBe(updatedLength);
- };
-
- var expectBadgesHidden = function() {
- var $accomplishmentsTab = $('#tabpanel-accomplishments');
- if ($accomplishmentsTab.length) {
- // Nonexistence counts as hidden.
- expect($('#tabpanel-accomplishments').hasClass('is-hidden')).toBe(true);
- }
- expect($('#tabpanel-about_me').hasClass('is-hidden')).toBe(false);
- };
-
- var expectPage = function(learnerProfileView, pageData) {
- var $badgeListContainer = $('#tabpanel-accomplishments');
- var index = $badgeListContainer.find('span.search-count').text().trim();
- expect(index).toBe('Showing ' + (pageData.start + 1) + '-' + (pageData.start + pageData.results.length)
- + ' out of ' + pageData.count + ' total');
- expect($badgeListContainer.find('.current-page').text()).toBe('' + pageData.current_page);
- _.each(pageData.results, function(badge) {
- expect($('.badge-display:contains(' + badge.badge_class.display_name + ')').length).toBe(1);
- });
- };
-
- var expectBadgeLoadingErrorIsRendered = function() {
- var errorMessage = $('.badge-set-display').text();
- expect(errorMessage).toBe(
- 'Your request could not be completed. Reload the page and try again. If the issue persists, click the '
- + 'Help tab to report the problem.'
- );
- };
-
- var breakBadgeLoading = function(learnerProfileView, requests) {
- var request = AjaxHelpers.currentRequest(requests);
- var path = new URI(request.url).path();
- expect(path).toBe('/api/badges/v1/assertions/user/student/');
- AjaxHelpers.respondWithError(requests, 500);
- };
-
- var firstPageBadges = {
- count: 30,
- previous: null,
- next: '/arbitrary/url',
- num_pages: 3,
- start: 0,
- current_page: 1,
- results: []
- };
-
- var secondPageBadges = {
- count: 30,
- previous: '/arbitrary/url',
- next: '/arbitrary/url',
- num_pages: 3,
- start: 10,
- current_page: 2,
- results: []
- };
-
- var thirdPageBadges = {
- count: 30,
- previous: '/arbitrary/url',
- num_pages: 3,
- next: null,
- start: 20,
- current_page: 3,
- results: []
- };
-
- var emptyBadges = {
- count: 0,
- previous: null,
- num_pages: 1,
- results: []
- };
-
- function makeBadge(num) {
- return {
- badge_class: {
- slug: 'test_slug_' + num,
- issuing_component: 'test_component',
- display_name: 'Test Badge ' + num,
- course_id: null,
- description: "Yay! It's a test badge.",
- criteria: 'https://example.com/syllabus',
- image_url: 'http://localhost:8000/media/badge_classes/test_lMB9bRw.png'
- },
- image_url: 'http://example.com/image.png',
- assertion_url: 'http://example.com/example.json',
- created_at: '2015-12-03T16:25:57.676113Z'
- };
- }
-
- _.each(_.range(0, 10), function(i) {
- firstPageBadges.results.push(makeBadge(i));
- });
-
- _.each(_.range(10, 20), function(i) {
- secondPageBadges.results.push(makeBadge(i));
- });
-
- _.each(_.range(20, 30), function(i) {
- thirdPageBadges.results.push(makeBadge(i));
- });
-
- return {
- expectLimitedProfileSectionsAndFieldsToBeRendered: expectLimitedProfileSectionsAndFieldsToBeRendered,
- expectProfileSectionsAndFieldsToBeRendered: expectProfileSectionsAndFieldsToBeRendered,
- expectProfileSectionsNotToBeRendered: expectProfileSectionsNotToBeRendered,
- expectTabbedViewToBeUndefined: expectTabbedViewToBeUndefined,
- expectTabbedViewToBeShown: expectTabbedViewToBeShown,
- expectBadgesDisplayed: expectBadgesDisplayed,
- expectBadgesHidden: expectBadgesHidden,
- expectBadgeLoadingErrorIsRendered: expectBadgeLoadingErrorIsRendered,
- breakBadgeLoading: breakBadgeLoading,
- firstPageBadges: firstPageBadges,
- secondPageBadges: secondPageBadges,
- thirdPageBadges: thirdPageBadges,
- emptyBadges: emptyBadges,
- expectPage: expectPage,
- makeBadge: makeBadge
- };
-});
diff --git a/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_container.js b/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_container.js
deleted file mode 100644
index ca68ca8fa9e8..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_container.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* eslint-disable no-underscore-dangle */
-(function(define) {
- 'use strict';
-
- define(
- [
- 'gettext', 'jquery', 'underscore', 'common/js/components/views/paginated_view',
- 'learner_profile/js/views/badge_view', 'learner_profile/js/views/badge_list_view',
- 'text!learner_profile/templates/badge_list.underscore'
- ],
- function(gettext, $, _, PaginatedView, BadgeView, BadgeListView, BadgeListTemplate) {
- var BadgeListContainer = PaginatedView.extend({
- type: 'badge',
-
- itemViewClass: BadgeView,
-
- listViewClass: BadgeListView,
-
- viewTemplate: BadgeListTemplate,
-
- isZeroIndexed: true,
-
- paginationLabel: gettext('Accomplishments Pagination'),
-
- initialize: function(options) {
- BadgeListContainer.__super__.initialize.call(this, options);
- this.listView.find_courses_url = options.find_courses_url;
- this.listView.badgeMeta = options.badgeMeta;
- this.listView.ownProfile = options.ownProfile;
- }
- });
-
- return BadgeListContainer;
- });
-}).call(this, define || RequireJS.define);
diff --git a/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_view.js b/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_view.js
deleted file mode 100644
index c30ab9c94ad9..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/js/views/badge_list_view.js
+++ /dev/null
@@ -1,65 +0,0 @@
-(function(define) {
- 'use strict';
-
- define([
- 'gettext',
- 'jquery',
- 'underscore',
- 'edx-ui-toolkit/js/utils/html-utils',
- 'common/js/components/views/list',
- 'learner_profile/js/views/badge_view',
- 'text!learner_profile/templates/badge_placeholder.underscore'
- ],
- function(gettext, $, _, HtmlUtils, ListView, BadgeView, badgePlaceholder) {
- var BadgeListView = ListView.extend({
- tagName: 'div',
-
- template: HtmlUtils.template(badgePlaceholder),
-
- renderCollection: function() {
- var self = this,
- $row;
-
- this.$el.empty();
-
- // Split into two columns.
- this.collection.each(function(badge, index) {
- var $item;
- if (index % 2 === 0) {
- $row = $('
');
- this.$el.append($row);
- }
- $item = new BadgeView({
- model: badge,
- badgeMeta: this.badgeMeta,
- ownProfile: this.ownProfile
- }).render().el;
-
- if ($row) {
- $row.append($item);
- }
-
- this.itemViews.push($item);
- }, this);
- // Placeholder must always be at the end, and may need a new row.
- if (!this.collection.hasNextPage()) {
- // find_courses_url set by BadgeListContainer during initialization.
- if (this.collection.length % 2 === 0) {
- $row = $('
-
- <% if (!showFullProfile) { %>
- <% if(ownProfile) { %>
- <%- gettext("You are currently sharing a limited profile.") %>
- <% } else { %>
- <%- gettext("This learner is currently sharing a limited profile.") %>
- <% } %>
- <% } %>
-
\ No newline at end of file
diff --git a/openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore b/openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore
deleted file mode 100644
index b71e89823bad..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
<%- gettext("Share on Mozilla Backpack") %>
-
<%- gettext("To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.") %>
-
-
-
-
-
- <%= edx.HtmlUtils.interpolateHtml(
- gettext("Create a {link_start}Mozilla Backpack{link_end} account, or log in to your existing account"),
- {
- link_start: edx.HtmlUtils.HTML(''),
- link_end: edx.HtmlUtils.HTML('')
- }
- )
- %>
-
-
-
- <%= edx.HtmlUtils.interpolateHtml(
- gettext("{download_link_start}Download this image (right-click or option-click, save as){link_end} and then {upload_link_start}upload{link_end} it to your backpack."),
- {
- download_link_start: edx.HtmlUtils.joinHtml(
- edx.HtmlUtils.HTML(''),
- ),
- link_end: edx.HtmlUtils.HTML(''),
- upload_link_start: edx.HtmlUtils.HTML('')
- }
- )
- %>
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/openedx/features/learner_profile/static/learner_profile/templates/social_icons.underscore b/openedx/features/learner_profile/static/learner_profile/templates/social_icons.underscore
deleted file mode 100644
index 52b864cfb669..000000000000
--- a/openedx/features/learner_profile/static/learner_profile/templates/social_icons.underscore
+++ /dev/null
@@ -1,9 +0,0 @@
-
- <% for (var platform in socialLinks) { %>
- <% if (socialLinks[platform]) { %>
- >
- aria-hidden="true">
-
- <% } %>
- <% } %>
-
-
- ## Translators: this section lists all the third-party authentication providers (for example, Google and LinkedIn) the user can link with or unlink from their edX account.
- ${_("Connected Accounts")}
-
-
-
- % for state in provider_user_states:
-