Skip to content
Snippets Groups Projects
Commit 1ffa81f7 authored by Renzo Lucioni's avatar Renzo Lucioni
Browse files

Retrofit programs data mixin with factories

This should make it easier to test programs-related features. Preface to ECOM-3200.
parent f8f5e703
No related merge requests found
......@@ -4,67 +4,16 @@ Tools to create programs-related data for use in bok choy tests.
from collections import namedtuple
import json
import factory
import requests
from . import PROGRAMS_STUB_URL
from .config import ConfigModelFixture
from openedx.core.djangoapps.programs.tests import factories
FakeProgram = namedtuple('FakeProgram', ['name', 'status', 'org_key', 'course_id'])
class Program(factory.Factory):
"""
Factory for stubbing program resources from the Programs API (v1).
"""
class Meta(object):
model = dict
id = factory.Sequence(lambda n: n) # pylint: disable=invalid-name
name = 'dummy-program-name'
subtitle = 'dummy-program-subtitle'
category = 'xseries'
status = 'unpublished'
marketing_slug = factory.Sequence(lambda n: 'slug-{}'.format(n)) # pylint: disable=unnecessary-lambda
organizations = []
course_codes = []
banner_image_urls = {}
class Organization(factory.Factory):
"""
Factory for stubbing nested organization resources from the Programs API (v1).
"""
class Meta(object):
model = dict
key = 'dummyX'
display_name = 'dummy-org-display-name'
class CourseCode(factory.Factory):
"""
Factory for stubbing nested course code resources from the Programs API (v1).
"""
class Meta(object):
model = dict
display_name = 'dummy-org-display-name'
run_modes = []
class RunMode(factory.Factory):
"""
Factory for stubbing nested run mode resources from the Programs API (v1).
"""
class Meta(object):
model = dict
course_key = 'org/course/run'
mode_slug = 'verified'
class ProgramsFixture(object):
"""
Interface to set up mock responses from the Programs stub server.
......@@ -78,11 +27,11 @@ class ProgramsFixture(object):
"""
programs = []
for program in fake_programs:
run_mode = RunMode(course_key=program.course_id)
course_code = CourseCode(run_modes=[run_mode])
org = Organization(key=program.org_key)
run_mode = factories.RunMode(course_key=program.course_id)
course_code = factories.CourseCode(run_modes=[run_mode])
org = factories.Organization(key=program.org_key)
program = Program(
program = factories.Program(
name=program.name,
status=program.status,
organizations=[org],
......
......@@ -8,7 +8,6 @@ from urlparse import urljoin
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.test import override_settings
from edx_oauth2_provider.tests.factories import ClientFactory
from opaque_keys.edx import locator
......@@ -39,6 +38,7 @@ class TestProgramListing(
Unit tests for getting the list of programs enrolled by a logged in user
"""
PASSWORD = 'test'
url = reverse('program_listing_view')
def setUp(self):
"""
......@@ -81,10 +81,9 @@ class TestProgramListing(
"""
self.mock_programs_api()
self.client.login(username=self.student.username, password=self.PASSWORD)
response = self.client.get(reverse("program_listing_view"))
self.assertEqual(response.status_code, 200)
response = self.client.get(self.url)
x_series_url = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries')
self.assertIn(x_series_url, response.content)
self.assertContains(response, x_series_url)
return response
def _get_program_checklist(self, program_id):
......@@ -101,18 +100,18 @@ class TestProgramListing(
def test_get_program_with_no_enrollment(self):
response = self._setup_and_get_program()
for program_element in self._get_program_checklist(0):
self.assertNotIn(program_element, response.content)
self.assertNotContains(response, program_element)
for program_element in self._get_program_checklist(1):
self.assertNotIn(program_element, response.content)
self.assertNotContains(response, program_element)
@httpretty.activate
def test_get_one_program(self):
self._create_course_and_enroll(self.student, *self.COURSE_KEYS[0].split('/'))
response = self._setup_and_get_program()
for program_element in self._get_program_checklist(0):
self.assertIn(program_element, response.content)
self.assertContains(response, program_element)
for program_element in self._get_program_checklist(1):
self.assertNotIn(program_element, response.content)
self.assertNotContains(response, program_element)
@httpretty.activate
def test_get_both_program(self):
......@@ -120,32 +119,34 @@ class TestProgramListing(
self._create_course_and_enroll(self.student, *self.COURSE_KEYS[5].split('/'))
response = self._setup_and_get_program()
for program_element in self._get_program_checklist(0):
self.assertIn(program_element, response.content)
self.assertContains(response, program_element)
for program_element in self._get_program_checklist(1):
self.assertIn(program_element, response.content)
self.assertContains(response, program_element)
def test_get_programs_dashboard_not_enabled(self):
self.create_programs_config(program_listing_enabled=False)
self.client.login(username=self.student.username, password=self.PASSWORD)
response = self.client.get(reverse("program_listing_view"))
response = self.client.get(self.url)
self.assertEqual(response.status_code, 404)
def test_xseries_advertise_disabled(self):
self.create_programs_config(program_listing_enabled=True, xseries_ad_enabled=False)
self.client.login(username=self.student.username, password=self.PASSWORD)
response = self.client.get(reverse("program_listing_view"))
self.assertEqual(response.status_code, 200)
response = self.client.get(self.url)
x_series_url = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries')
self.assertNotIn(x_series_url, response.content)
self.assertNotContains(response, x_series_url)
def test_get_programs_not_logged_in(self):
self.create_programs_config()
response = self.client.get(reverse("program_listing_view"))
self.assertEqual(response.status_code, 302)
self.assertIsInstance(response, HttpResponseRedirect)
self.assertIn('login', response.url) # pylint: disable=no-member
response = self.client.get(self.url)
def _expected_credetials_data(self):
self.assertRedirects(
response,
'{}?next={}'.format(reverse('signin_user'), self.url)
)
# TODO: Use a factory to generate this data.
def _expected_credentials_data(self):
""" Dry method for getting expected credentials."""
return [
......@@ -172,13 +173,11 @@ class TestProgramListing(
self.mock_credentials_api(self.student, data=self.CREDENTIALS_API_RESPONSE, reset_url=False)
response = self.client.get(reverse("program_listing_view"))
self.assertEqual(response.status_code, 200)
for certificate in self._expected_credentials_data():
self.assertContains(response, certificate['display_name'])
self.assertContains(response, certificate['credential_url'])
for certificate in self._expected_credetials_data():
self.assertIn(certificate['display_name'], response.content)
self.assertIn(certificate['credential_url'], response.content)
self.assertIn('images/xseries-certificate-visual.png', response.content)
self.assertContains(response, 'images/xseries-certificate-visual.png')
@httpretty.activate
def test_get_xseries_certificates_without_data(self):
......@@ -193,8 +192,6 @@ class TestProgramListing(
self.mock_credentials_api(self.student, data={"results": []}, reset_url=False)
response = self.client.get(reverse("program_listing_view"))
self.assertEqual(response.status_code, 200)
for certificate in self._expected_credetials_data():
self.assertNotIn(certificate['display_name'], response.content)
self.assertNotIn(certificate['credential_url'], response.content)
for certificate in self._expected_credentials_data():
self.assertNotContains(response, certificate['display_name'])
self.assertNotContains(response, certificate['credential_url'])
"""Factories for generating fake program-related data."""
import factory
from factory.fuzzy import FuzzyText
class Program(factory.Factory):
"""
Factory for stubbing program resources from the Programs API (v1).
"""
class Meta(object):
model = dict
id = factory.Sequence(lambda n: n) # pylint: disable=invalid-name
name = FuzzyText(prefix='Program ')
subtitle = FuzzyText(prefix='Subtitle ')
category = 'xseries'
status = 'unpublished'
marketing_slug = FuzzyText(prefix='slug_')
organizations = []
course_codes = []
banner_image_urls = {}
class Organization(factory.Factory):
"""
Factory for stubbing nested organization resources from the Programs API (v1).
"""
class Meta(object):
model = dict
key = FuzzyText(prefix='org_')
display_name = FuzzyText(prefix='Display Name ')
class CourseCode(factory.Factory):
"""
Factory for stubbing nested course code resources from the Programs API (v1).
"""
class Meta(object):
model = dict
display_name = FuzzyText(prefix='Display Name ')
run_modes = []
class RunMode(factory.Factory):
"""
Factory for stubbing nested run mode resources from the Programs API (v1).
"""
class Meta(object):
model = dict
course_key = FuzzyText(prefix='org/', suffix='/run')
mode_slug = 'verified'
......@@ -4,6 +4,7 @@ import json
import httpretty
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests import factories
class ProgramsApiConfigMixin(object):
......@@ -50,176 +51,48 @@ class ProgramsDataMixin(object):
'organization-b/course-d/winter',
]
# TODO: Use factory-boy.
PROGRAMS_API_RESPONSE = {
'results': [
{
'id': 1,
'name': PROGRAM_NAMES[0],
'subtitle': 'A program used for testing purposes',
'category': 'xseries',
'status': 'unpublished',
'marketing_slug': '{}_test_url'.format(PROGRAM_NAMES[0].replace(' ', '_')),
'organizations': [
{
'display_name': 'Test Organization A',
'key': 'organization-a'
}
],
'course_codes': [
{
'display_name': 'Test Course A',
'key': 'course-a',
'organization': {
'display_name': 'Test Organization A',
'key': 'organization-a'
},
'run_modes': [
{
'course_key': COURSE_KEYS[0],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'fall'
},
{
'course_key': COURSE_KEYS[1],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'winter'
}
]
},
{
'display_name': 'Test Course B',
'key': 'course-b',
'organization': {
'display_name': 'Test Organization A',
'key': 'organization-a'
},
'run_modes': [
{
'course_key': COURSE_KEYS[2],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'fall'
},
{
'course_key': COURSE_KEYS[3],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'winter'
}
]
}
],
'created': '2015-10-26T17:52:32.861000Z',
'modified': '2015-11-18T22:21:30.826365Z'
},
{
'id': 2,
'name': PROGRAM_NAMES[1],
'subtitle': 'Another program used for testing purposes',
'category': 'xseries',
'status': 'unpublished',
'marketing_slug': '{}_test_url'.format(PROGRAM_NAMES[1].replace(' ', '_')),
'organizations': [
{
'display_name': 'Test Organization B',
'key': 'organization-b'
}
],
'course_codes': [
{
'display_name': 'Test Course C',
'key': 'course-c',
'organization': {
'display_name': 'Test Organization B',
'key': 'organization-b'
},
'run_modes': [
{
'course_key': COURSE_KEYS[4],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'fall'
},
{
'course_key': COURSE_KEYS[5],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'winter'
}
]
},
{
'display_name': 'Test Course D',
'key': 'course-d',
'organization': {
'display_name': 'Test Organization B',
'key': 'organization-b'
},
'run_modes': [
{
'course_key': COURSE_KEYS[6],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'fall'
},
{
'course_key': COURSE_KEYS[7],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'winter'
}
]
}
],
'created': '2015-10-26T19:59:03.064000Z',
'modified': '2015-10-26T19:59:18.536000Z'
},
{
'id': 3,
'name': PROGRAM_NAMES[2],
'subtitle': 'A third program used for testing purposes',
'category': 'xseries',
'status': 'unpublished',
'marketing_slug': '{}_test_url'.format(PROGRAM_NAMES[2].replace(' ', '_')),
'organizations': [
{
'display_name': 'Test Organization B',
'key': 'organization-b'
}
],
'course_codes': [
{
'display_name': 'Test Course D',
'key': 'course-d',
'organization': {
'display_name': 'Test Organization B',
'key': 'organization-b'
},
'run_modes': [
{
'course_key': COURSE_KEYS[7],
'mode_slug': 'verified',
'sku': '',
'start_date': '2015-11-05T07:39:02.791741Z',
'run_key': 'winter'
}
]
}
],
'created': '2015-10-26T19:59:03.064000Z',
'modified': '2015-10-26T19:59:18.536000Z'
}
factories.Program(
id=1,
name=PROGRAM_NAMES[0],
organizations=[factories.Organization()],
course_codes=[
factories.CourseCode(run_modes=[
factories.RunMode(course_key=COURSE_KEYS[0]),
factories.RunMode(course_key=COURSE_KEYS[1]),
]),
factories.CourseCode(run_modes=[
factories.RunMode(course_key=COURSE_KEYS[2]),
factories.RunMode(course_key=COURSE_KEYS[3]),
]),
]
),
factories.Program(
id=2,
name=PROGRAM_NAMES[1],
organizations=[factories.Organization()],
course_codes=[
factories.CourseCode(run_modes=[
factories.RunMode(course_key=COURSE_KEYS[4]),
factories.RunMode(course_key=COURSE_KEYS[5]),
]),
factories.CourseCode(run_modes=[
factories.RunMode(course_key=COURSE_KEYS[6]),
factories.RunMode(course_key=COURSE_KEYS[7]),
]),
]
),
factories.Program(
id=3,
name=PROGRAM_NAMES[2],
organizations=[factories.Organization()],
course_codes=[
factories.CourseCode(run_modes=[
factories.RunMode(course_key=COURSE_KEYS[7]),
]),
]
),
]
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment