Commit 0a839436 by Martyn James

Changes as a result of feedback

parent 90399e79
...@@ -17,9 +17,18 @@ from xblockutils.resources import ResourceLoader ...@@ -17,9 +17,18 @@ from xblockutils.resources import ResourceLoader
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
RESOURCE_LOADER = ResourceLoader(__name__) RESOURCE_LOADER = ResourceLoader(__name__)
# Classes ###########################################################
# Constants ###########################################################
DEFAULT_CALENDAR_ID = "edx.org_lom804qe3ttspplj1bgeu1l3ak@group.calendar.google.com"
CALENDAR_TEMPLATE = "/templates/html/google_calendar.html"
CALENDAR_EDIT_TEMPLATE = "/templates/html/google_calendar_edit.html"
CALENDAR_IFRAME = (
'<iframe src="https://www.google.com/calendar/embed'
'?mode={}&amp;src={}&amp;showCalendars=0" title="{}"></iframe>'
)
# Classes ###########################################################
class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-many-ancestors class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-many-ancestors
""" """
XBlock providing a google calendar view for a specific calendar XBlock providing a google calendar view for a specific calendar
...@@ -38,7 +47,7 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -38,7 +47,7 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
"open Settings and copy the ID from the Calendar Address section into this field." "open Settings and copy the ID from the Calendar Address section into this field."
), ),
scope=Scope.settings, scope=Scope.settings,
default="edx.org_lom804qe3ttspplj1bgeu1l3ak@group.calendar.google.com" default=DEFAULT_CALENDAR_ID
) )
default_view = Integer( default_view = Integer(
...@@ -55,19 +64,12 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -55,19 +64,12 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
""" """
Player view, displayed to the student Player view, displayed to the student
""" """
fragment = Fragment() fragment = Fragment()
view = self.views[self.default_view][1] view = self.views[self.default_view][1]
iframe = CALENDAR_IFRAME.format(view, self.calendar_id, self.display_name)
iframe = ( fragment.add_content(RESOURCE_LOADER.render_template(CALENDAR_TEMPLATE, {
'<iframe src="https://www.google.com/calendar/embed'
'?mode={}&amp;src={}&amp;showCalendars=0" title="{}"></iframe>'
).format(
view, self.calendar_id, self.display_name
)
fragment.add_content(RESOURCE_LOADER.render_template('/templates/html/google_calendar.html', {
"self": self, "self": self,
"iframe": iframe "iframe": iframe
})) }))
...@@ -85,7 +87,7 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -85,7 +87,7 @@ class GoogleCalendarBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
""" """
fragment = Fragment() fragment = Fragment()
# Need to access protected members of fields to get their default value # Need to access protected members of fields to get their default value
fragment.add_content(RESOURCE_LOADER.render_template('/templates/html/google_calendar_edit.html', { fragment.add_content(RESOURCE_LOADER.render_template(CALENDAR_EDIT_TEMPLATE, {
'self': self, 'self': self,
'defaultName': self.fields['display_name']._default, # pylint: disable=protected-access 'defaultName': self.fields['display_name']._default, # pylint: disable=protected-access
'defaultID': self.fields['calendar_id']._default # pylint: disable=protected-access 'defaultID': self.fields['calendar_id']._default # pylint: disable=protected-access
......
...@@ -19,9 +19,23 @@ from xblockutils.resources import ResourceLoader ...@@ -19,9 +19,23 @@ from xblockutils.resources import ResourceLoader
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
RESOURCE_LOADER = ResourceLoader(__name__) RESOURCE_LOADER = ResourceLoader(__name__)
# Classes ########################################################### # Constants ###########################################################
DEFAULT_EMBED_CODE = textwrap.dedent("""
<iframe
src="https://docs.google.com/presentation/d/1x2ZuzqHsMoh1epK8VsGAlanSo7r9z55ualwQlj-ofBQ/embed?start=true&loop=true&delayms=10000"
frameborder="0"
width="960"
height="569"
allowfullscreen="true"
mozallowfullscreen="true"
webkitallowfullscreen="true">
</iframe>
""")
DOCUMENT_TEMPLATE = "/templates/html/google_docs.html"
DOCUMENT_EDIT_TEMPLATE = "/templates/html/google_docs_edit.html"
# Classes ###########################################################
class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-many-ancestors class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-many-ancestors
""" """
XBlock providing a google document embed link XBlock providing a google document embed link
...@@ -41,17 +55,8 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -41,17 +55,8 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
"Publish, and copy the embed code into this field." "Publish, and copy the embed code into this field."
), ),
scope=Scope.settings, scope=Scope.settings,
default=textwrap.dedent(""" default=DEFAULT_EMBED_CODE
<iframe )
src="https://docs.google.com/presentation/d/1x2ZuzqHsMoh1epK8VsGAlanSo7r9z55ualwQlj-ofBQ/embed?start=true&loop=true&delayms=10000"
frameborder="0"
width="960"
height="569"
allowfullscreen="true"
mozallowfullscreen="true"
webkitallowfullscreen="true">
</iframe>
"""))
alt_text = String( alt_text = String(
display_name="Alternative Text", display_name="Alternative Text",
...@@ -68,10 +73,9 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -68,10 +73,9 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
""" """
Player view, displayed to the student Player view, displayed to the student
""" """
fragment = Fragment() fragment = Fragment()
fragment.add_content(RESOURCE_LOADER.render_template('/templates/html/google_docs.html', {"self": self})) fragment.add_content(RESOURCE_LOADER.render_template(DOCUMENT_TEMPLATE, {"self": self}))
fragment.add_css(RESOURCE_LOADER.load_unicode('public/css/google_docs.css')) fragment.add_css(RESOURCE_LOADER.load_unicode('public/css/google_docs.css'))
fragment.add_javascript(RESOURCE_LOADER.load_unicode('public/js/google_docs.js')) fragment.add_javascript(RESOURCE_LOADER.load_unicode('public/js/google_docs.js'))
...@@ -86,7 +90,7 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man ...@@ -86,7 +90,7 @@ class GoogleDocumentBlock(XBlock, PublishEventMixin): # pylint: disable=too-man
""" """
fragment = Fragment() fragment = Fragment()
# Need to access protected members of fields to get their default value # Need to access protected members of fields to get their default value
fragment.add_content(RESOURCE_LOADER.render_template('/templates/html/google_docs_edit.html', { fragment.add_content(RESOURCE_LOADER.render_template(DOCUMENT_EDIT_TEMPLATE, {
'self': self, 'self': self,
'defaultName': self.fields['display_name']._default # pylint: disable=protected-access 'defaultName': self.fields['display_name']._default # pylint: disable=protected-access
})) }))
......
/* Javascript for GoogleDocumentBlock. */ /* Javascript for GoogleDocumentBlock. */
function GoogleCalendarBlock(runtime, element) { function GoogleCalendarBlock(runtime, element) {
$('iframe', element).load(function(){ $('iframe', element).load(function(){
var iframe_url = $(this).attr('src'); var iframe_url = $(this).attr('src');
$.ajax({ $.ajax({
......
/* Javascript for GoogleDocumentBlock. */ /* Javascript for GoogleDocumentBlock. */
function GoogleDocumentBlock(runtime, element) { function GoogleDocumentBlock(runtime, element) {
var iframe = $('iframe', element); var iframe = $('iframe', element);
var image = $('img', element); var image = $('img', element);
var xblock_wrapper = $('.google-docs-xblock-wrapper', element); var xblock_wrapper = $('.google-docs-xblock-wrapper', element);
......
function GoogleDocumentEditBlock(runtime, element) { function GoogleDocumentEditBlock(runtime, element) {
var clear_name_button = $('.clear-display-name', element); var clear_name_button = $('.clear-display-name', element);
var save_button = $('.save-button', element); var save_button = $('.save-button', element);
var validation_alert = $('.validation_alert', element); var validation_alert = $('.validation_alert', element);
......
""" Put tests here """ """ Unit and integration tests for google drive components """
""" Unit tests for google drive components """ """ Integration tests for google drive components """
""" Unit tests for google document components """
import json
import unittest
from mock import Mock
from nose.tools import assert_equals, assert_in
from workbench.runtime import WorkbenchRuntime
from xblock.runtime import KvsFieldData, DictKeyValueStore
from google_drive import GoogleCalendarBlock
from google_drive.tests.unit.test_utils import generate_scope_ids, make_request
class TestGoogleCalendarBlock(unittest.TestCase):
""" Tests for GoogleCalendarBlock """
@classmethod
def make_calendar_block(cls):
""" helper to construct a GoogleCalendarBlock """
runtime = WorkbenchRuntime()
key_store = DictKeyValueStore()
db_model = KvsFieldData(key_store)
ids = generate_scope_ids(runtime, 'google_calendar')
return GoogleCalendarBlock(runtime, db_model, scope_ids=ids)
def test_calendar_template_content(self): # pylint: disable=no-self-use
""" Test content of GoogleCalendarBlock's rendered views """
block = TestGoogleCalendarBlock.make_calendar_block()
block.usage_id = Mock()
student_fragment = block.render('student_view', Mock())
# pylint: disable=no-value-for-parameter
assert_in('<div class="google-calendar-xblock-wrapper">', student_fragment.content)
assert_in(
(
'https://www.google.com/calendar/embed?mode=Month&amp;src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&amp;showCalendars=0'
),
student_fragment.content
)
assert_in('Google Calendar', student_fragment.content)
studio_fragment = block.render('studio_view', Mock())
assert_in(
'<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="settings-tab">',
studio_fragment.content
)
assert_in('<div class="user-inputs-and-validation">', studio_fragment.content)
assert_in('<div class="xblock-inputs editor_content_wrapper">', studio_fragment.content)
assert_in('<div class="xblock-actions">', studio_fragment.content)
def test_calendar_document_submit(self): # pylint: disable=no-self-use
""" Test studio submission of GoogleCalendarBlock """
block = TestGoogleCalendarBlock.make_calendar_block()
body = json.dumps({
'display_name': "Google Calendar",
'calendar_id': "google1234",
'default_view': 1
})
res = block.handle('studio_submit', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equals(json.loads(res.body), {'result': 'success'})
assert_equals(block.display_name, "Google Calendar")
assert_equals(block.calendar_id, "google1234")
assert_equals(block.default_view, 1)
def test_calendar_publish_event(self): # pylint: disable=no-self-use
""" Test event publishing in GoogleCalendarBlock"""
block = TestGoogleCalendarBlock.make_calendar_block()
body = json.dumps({
'url': (
'https://www.google.com/calendar/embed?mode=Month&src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&showCalendars=0'
),
'displayed_in': 'iframe',
'event_type': 'edx.googlecomponent.calendar.displayed'
})
res = block.handle('publish_event', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equals(json.loads(res.body), {'result': 'success'})
body = json.dumps({
'url': (
'https://www.google.com/calendar/embed?mode=Month&src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&showCalendars=0'
),
'displayed_in': 'iframe',
})
res = block.handle('publish_event', make_request(body))
assert_equals(json.loads(res.body), {'result': 'error', 'message': 'Missing event_type in JSON data'})
""" Tests for google drive components """ """ Unit tests for google document components """
import json import json
import unittest import unittest
from webob import Request
from mock import Mock from mock import Mock
from nose.tools import assert_equals, assert_in
from workbench.runtime import WorkbenchRuntime from workbench.runtime import WorkbenchRuntime
from xblock.runtime import KvsFieldData, DictKeyValueStore from xblock.runtime import KvsFieldData, DictKeyValueStore
from xblock.fields import ScopeIds
from google_drive import GoogleDocumentBlock, GoogleCalendarBlock
from nose.tools import assert_equals, assert_in
def generate_scope_ids(runtime, block_type):
""" helper to generate scope IDs for an XBlock """
def_id = runtime.id_generator.create_definition(block_type)
usage_id = runtime.id_generator.create_usage(def_id)
return ScopeIds('user', block_type, def_id, usage_id)
def make_request(body, method='POST'): from google_drive import GoogleDocumentBlock
""" helper to make a request """ from google_drive.tests.unit.test_utils import generate_scope_ids, make_request
request = Request.blank('/')
request.method = 'POST'
request.body = body.encode('utf-8')
request.method = method
return request
class TestGoogleDocumentBlock(unittest.TestCase): class TestGoogleDocumentBlock(unittest.TestCase):
...@@ -155,86 +136,3 @@ class TestGoogleDocumentBlock(unittest.TestCase): ...@@ -155,86 +136,3 @@ class TestGoogleDocumentBlock(unittest.TestCase):
res = block.handle('publish_event', make_request(body)) res = block.handle('publish_event', make_request(body))
assert_equals(json.loads(res.body), {'result': 'error', 'message': 'Missing event_type in JSON data'}) assert_equals(json.loads(res.body), {'result': 'error', 'message': 'Missing event_type in JSON data'})
class TestGoogleCalendarBlock(unittest.TestCase):
""" Tests for GoogleCalendarBlock """
@classmethod
def make_calendar_block(cls):
""" helper to construct a GoogleCalendarBlock """
runtime = WorkbenchRuntime()
key_store = DictKeyValueStore()
db_model = KvsFieldData(key_store)
ids = generate_scope_ids(runtime, 'google_calendar')
return GoogleCalendarBlock(runtime, db_model, scope_ids=ids)
def test_calendar_template_content(self): # pylint: disable=no-self-use
""" Test content of GoogleCalendarBlock's rendered views """
block = TestGoogleCalendarBlock.make_calendar_block()
block.usage_id = Mock()
student_fragment = block.render('student_view', Mock())
# pylint: disable=no-value-for-parameter
assert_in('<div class="google-calendar-xblock-wrapper">', student_fragment.content)
assert_in(
(
'https://www.google.com/calendar/embed?mode=Month&amp;src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&amp;showCalendars=0'
),
student_fragment.content
)
assert_in('Google Calendar', student_fragment.content)
studio_fragment = block.render('studio_view', Mock())
assert_in(
'<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="settings-tab">',
studio_fragment.content
)
assert_in('<div class="user-inputs-and-validation">', studio_fragment.content)
assert_in('<div class="xblock-inputs editor_content_wrapper">', studio_fragment.content)
assert_in('<div class="xblock-actions">', studio_fragment.content)
def test_calendar_document_submit(self): # pylint: disable=no-self-use
""" Test studio submission of GoogleCalendarBlock """
block = TestGoogleCalendarBlock.make_calendar_block()
body = json.dumps({
'display_name': "Google Calendar",
'calendar_id': "google1234",
'default_view': 1
})
res = block.handle('studio_submit', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equals(json.loads(res.body), {'result': 'success'})
assert_equals(block.display_name, "Google Calendar")
assert_equals(block.calendar_id, "google1234")
assert_equals(block.default_view, 1)
def test_calendar_publish_event(self): # pylint: disable=no-self-use
""" Test event publishing in GoogleCalendarBlock"""
block = TestGoogleCalendarBlock.make_calendar_block()
body = json.dumps({
'url': (
'https://www.google.com/calendar/embed?mode=Month&src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&showCalendars=0'
),
'displayed_in': 'iframe',
'event_type': 'edx.googlecomponent.calendar.displayed'
})
res = block.handle('publish_event', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equals(json.loads(res.body), {'result': 'success'})
body = json.dumps({
'url': (
'https://www.google.com/calendar/embed?mode=Month&src=edx.org_lom804qe3ttspplj1bgeu1l3ak'
'@group.calendar.google.com&showCalendars=0'
),
'displayed_in': 'iframe',
})
res = block.handle('publish_event', make_request(body))
assert_equals(json.loads(res.body), {'result': 'error', 'message': 'Missing event_type in JSON data'})
""" Utility functions used within unit tests """
from webob import Request
from xblock.fields import ScopeIds
def generate_scope_ids(runtime, block_type):
""" helper to generate scope IDs for an XBlock """
def_id = runtime.id_generator.create_definition(block_type)
usage_id = runtime.id_generator.create_usage(def_id)
return ScopeIds('user', block_type, def_id, usage_id)
def make_request(body, method='POST'):
""" helper to make a request """
request = Request.blank('/')
request.method = 'POST'
request.body = body.encode('utf-8')
request.method = method
return request
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment