Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -123,34 +123,9 @@ required-attributes=
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input

# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$

# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$

# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$

# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,50}$

# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$

# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$

# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$

# Regular expression which should only match correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$

# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$

# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_

Expand Down
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ before_install:
- "sh -e /etc/init.d/xvfb start"

install:
- pip install -r requirements.txt
- "pip install -r requirements.txt"
- "pip uninstall -y xblock-google-drive && python setup.py sdist && pip install dist/xblock-google-drive-0.1.tar.gz"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added uninstall line like suggested


script:
- DJANGO_SETTINGS_MODULE="settings" nosetests --with-coverage --cover-package="google_drive" --with-django
Expand Down
9 changes: 7 additions & 2 deletions google_drive/google_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,15 @@ def check_url(self, data, suffix=''): # pylint: disable=unused-argument,no-self
"""
Checks that the given document url is accessible, and therefore assumed to be valid
"""
test_url = data['url']
try:
test_url = data['url']
url_response = requests.head(test_url)
# Catch wide range of errors
except KeyError as ex:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catch KeyError exception, means url wasn't provided

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but I would put the two lines in two different try/except blocks, since you're catching different exceptions for each. This way you don't risk to inadvertently catch a KeyError that would be thrown for a different reason from requests.head() for example.

LOG.debug("URL not provided - %s", unicode(ex))
return {
'status_code': 400,
}
# Catch wide range of request exceptions
except requests.exceptions.RequestException as ex:
LOG.debug("Unable to connect to %s - %s", test_url, unicode(ex))
return {
Expand Down
8 changes: 4 additions & 4 deletions google_drive/templates/html/google_calendar_edit.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% load i18n %}

<!-- TODO: Replace by default edit view once available in Studio -->
<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="settings-tab">
<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="calendar-settings-tab">
<div class="user-inputs-and-validation">
<div class="validation_alert covered">
<i class="alert_icon"></i>
Expand All @@ -17,7 +17,7 @@ <h2 class="alert_title">{% trans "Invalid Google Calendar" %}</h2>
<label class="label setting-label" for="edit_display_name">{% trans "Display Name" %}</label>
<input class="input setting-input edit-display-name" id="edit_display_name" value="{{ self.display_name }}" type="text" data-default-value="{{defaultName}}">
<button class="action setting-clear clear-display-name" type="button" name="setting-clear">
<i class="icon-undo"></i>
<i class="icon fa fa-undo"></i>
<span class="sr">"<%= gettext("Clear Value") %>"</span>
</button>
</div>
Expand All @@ -28,7 +28,7 @@ <h2 class="alert_title">{% trans "Invalid Google Calendar" %}</h2>
<label class="label setting-label" for="edit_calendar_id">{% trans "Public Calendar ID" %}</label>
<input class="input setting-input edit-calendar-id" id="edit_calendar_id" value="{{ self.calendar_id }}" type="text" data-default-value="{{defaultID}}">
<button class="action setting-clear clear-calendar-id" type="button" name="setting-clear">
<i class="icon-undo"></i>
<i class="icon fa fa-undo"></i>
<span class="sr">"<%= gettext("Clear Value") %>"</span>
</button>
</div>
Expand Down Expand Up @@ -57,7 +57,7 @@ <h2 class="alert_title">{% trans "Invalid Google Calendar" %}</h2>
<span class="xblock-editor-error-message"></span>
<ul>
<li class="action-item">
<a href="#" class="button action-primary save-button">{% trans "Save" %}</a>
<a href="#" id="calendar-submit-options" class="button action-primary save-button">{% trans "Save" %}</a>
</li>

<li class="action-item">
Expand Down
6 changes: 3 additions & 3 deletions google_drive/templates/html/google_docs_edit.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% load i18n %}

<!-- TODO: Replace by default edit view once available in Studio -->
<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="settings-tab">
<div class="wrapper-comp-settings is-active editor-with-buttons google-edit-wrapper" id="document-settings-tab">
<div class="user-inputs-and-validation">
<div class="validation_alert covered">
<i class="alert_icon"></i>
Expand All @@ -17,7 +17,7 @@ <h2 class="alert_title">{% trans "Invalid Google Document" %}</h2>
<label class="label setting-label" for="edit_display_name">{% trans "Display Name" %}</label>
<input class="input setting-input edit-display-name" id="edit_display_name" value="{{ self.display_name }}" type="text" data-default-value="{{defaultName}}">
<button class="action setting-clear clear-display-name" type="button" name="setting-clear">
<i class="icon-undo"></i>
<i class="icon fa fa-undo"></i>
<span class="sr">"<%= gettext("Clear Value") %>"</span>
</button>
</div>
Expand All @@ -44,7 +44,7 @@ <h2 class="alert_title">{% trans "Invalid Google Document" %}</h2>
<span class="xblock-editor-error-message"></span>
<ul>
<li class="action-item">
<a href="#" class="button action-primary save-button">{% trans "Save" %}</a>
<a href="#" id="document-submit-options" class="button action-primary save-button">{% trans "Save" %}</a>
</li>

<li class="action-item">
Expand Down
14 changes: 14 additions & 0 deletions google_drive/tests/integration/base_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
""" Base classes for integration tests """
from xblockutils.base_test import SeleniumBaseTest


class GoogleCalendarBaseTest(SeleniumBaseTest): # pylint: disable=too-many-ancestors, too-few-public-methods
""" Base class for Google Calendar integration tests """
module_name = __name__
default_css_selector = 'div.google-calendar-xblock-wrapper'


class GoogleDocumentBaseTest(SeleniumBaseTest): # pylint: disable=too-many-ancestors, too-few-public-methods
""" Base class for Google Document integration tests """
module_name = __name__
default_css_selector = 'div.google-docs-xblock-wrapper'
17 changes: 0 additions & 17 deletions google_drive/tests/integration/calendar_base_test.py

This file was deleted.

26 changes: 0 additions & 26 deletions google_drive/tests/integration/document_base_test.py

This file was deleted.

20 changes: 20 additions & 0 deletions google_drive/tests/integration/studio_scenarios.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
Contains a list of lists that will be used as the DDT arguments for the studio test.
"""
CALENDAR_SCENARIOS = [
[
'Calendar',
],
]

DOCUMENT_SCENARIOS = [
[
'Document',
],
]

IMAGE_SCENARIOS = [
[
'Image',
],
]
41 changes: 41 additions & 0 deletions google_drive/tests/integration/test_publish.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
""" Runs tests for publish event functionality """
from .base_test import GoogleCalendarBaseTest, GoogleDocumentBaseTest


class GoogleCalendarPublishTestCase(GoogleCalendarBaseTest): # pylint: disable=too-few-public-methods, too-many-ancestors
"""
Tests for Google Calendar event publishing functionality.
"""

def test_calendar_publish_event(self):
""" Tests whether the publish event for calendar was triggered """
calendar = self.go_to_page('Calendar')
load_event_complete = calendar.find_element_by_css_selector('.load_event_complete')
self.assertEqual(
load_event_complete.get_attribute('value'),
"I've published the event that indicates that the load has completed"
)


class GoogleDocumentPublishTestCase(GoogleDocumentBaseTest): # pylint: disable=too-many-ancestors
"""
Tests for Google Document event publishing functionality.
"""

def test_document_publish_event(self):
""" Tests whether the publish event for document was triggered """
document = self.go_to_page('Document')
load_event_complete = document.find_element_by_css_selector('.load_event_complete')
self.assertEqual(
load_event_complete.get_attribute('value'),
"I've published the event that indicates that the load has completed"
)

def test_image_publish_event(self):
""" Tests whether the publish event for image was triggered """
image = self.go_to_page('Image')
load_event_complete = image.find_element_by_css_selector('.load_event_complete')
self.assertEqual(
load_event_complete.get_attribute('value'),
"I've published the event that indicates that the load has completed"
)
135 changes: 135 additions & 0 deletions google_drive/tests/integration/test_studio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
""" Runs tests for the studio views """

from ddt import ddt, unpack, data
from .base_test import GoogleCalendarBaseTest, GoogleDocumentBaseTest
from .studio_scenarios import CALENDAR_SCENARIOS, DOCUMENT_SCENARIOS, IMAGE_SCENARIOS

DEFAULT_CALENDAR_SRC = (
'https://www.google.com/calendar/embed?'
'mode=Month&'
'src=edx.org_lom804qe3ttspplj1bgeu1l3ak@group.calendar.google.com&'
'showCalendars=0'
)

DEFAULT_DOCUMENT_SRC = (
'https://docs.google.com/presentation/d/1x2ZuzqHsMoh1epK8VsGAlanSo7r9z55ualwQlj-ofBQ/embed?'
'start=true&loop=true&delayms=10000'
)

TEST_IMAGE_SRC = 'https://docs.google.com/drawings/d/1lmmxboBM5c_0WCTjhAxBdkpqQb3T8VSwtuG0TRR1ODQ/pub?w=960&h=720'


@ddt # pylint: disable=too-many-ancestors
class GoogleCalendarStudioTest(GoogleCalendarBaseTest):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@antoviaque Thanks for providing an example of studio testing. Here are integration tests which include studio views.

"""
Tests for Google Calendar studio view.
"""
default_css_selector = '#calendar-settings-tab'

def studio_save(self):
""" Save changes made in studio for Google Calendar """
self.browser.find_element_by_css_selector('#calendar-submit-options').click()

@data(*CALENDAR_SCENARIOS) # pylint: disable=star-args
@unpack
def test_save_calendar(self, page_name):
"""
Verify that option changes in Google Calendar studio view
are appropriately saved and visible immediately after
"""
self.go_to_page(page_name, view_name='studio_view')
# Expecting every input value to be valid
self.assertTrue(self.browser.find_element_by_css_selector('.validation_alert.covered'))
display_name_input = self.browser.find_element_by_css_selector('#edit_display_name')
# Change display name
display_name_input.clear()
display_name_input.send_keys('My Meetings')
calendar_id_input = self.browser.find_element_by_css_selector('#edit_calendar_id')
# Change calendar ID
calendar_id_input.clear()
calendar_id_input.send_keys('a')
self.wait_until_exists('#edit_calendar_id.error')
# Expects validation error due to calendar ID being invalid
self.assertTrue(self.browser.find_element_by_css_selector('.validation_alert:not(covered)'))
# Check to see that calendar ID input element is marked as invalid
self.assertTrue(self.browser.find_element_by_css_selector('#edit_calendar_id.error'))
# Save button should be disabled
self.assertTrue(self.browser.find_element_by_css_selector('#calendar-submit-options.disabled'))
clean_calendar_id_button = self.browser.find_element_by_css_selector('button.clear-calendar-id')
# Reset calendar ID value to default one
clean_calendar_id_button.click()
# Expecting every input value to be valid again
self.assertTrue(self.browser.find_element_by_css_selector('.validation_alert.covered'))

self.studio_save()
self.go_to_page(page_name, css_selector='div.google-calendar-xblock-wrapper')
calendar_iframe = self.browser.find_element_by_css_selector('iframe')
# Expecting that default calendar is the one loaded in the IFrame
self.assertEqual(calendar_iframe.get_attribute("src"), DEFAULT_CALENDAR_SRC)
# Expecting that the new display name is the title of the IFrame
self.assertEqual(calendar_iframe.get_attribute("title"), 'My Meetings')


@ddt # pylint: disable=too-many-ancestors
class GoogleDocumentStudioTest(GoogleDocumentBaseTest):
"""
Tests for Google Document studio view.
"""
default_css_selector = '#document-settings-tab'

def studio_save(self):
""" Save changes made in studio for Google Document """
self.browser.find_element_by_css_selector('#document-submit-options').click()

@data(*DOCUMENT_SCENARIOS) # pylint: disable=star-args
@unpack
def test_save_document(self, page_name):
"""
Verify that option changes in Google Document studio view
are appropriately saved and visible immediately after
"""
self.go_to_page(page_name, view_name='studio_view')
# Expecting every input value to be valid
self.assertTrue(self.browser.find_element_by_css_selector('.validation_alert.covered'))
display_name_input = self.browser.find_element_by_css_selector('#edit_display_name')
# Change display name
display_name_input.clear()
display_name_input.send_keys('My Document')
# Expecting list item that contains input element for alternative text to be hidden
self.assertTrue(self.browser.find_element_by_css_selector('li#alt_text_item.covered'))

self.studio_save()
self.go_to_page(page_name, css_selector='div.google-docs-xblock-wrapper')
document_iframe = self.browser.find_element_by_css_selector('iframe')
# Expecting that default calendar is the one loaded in the IFrame
self.assertEqual(document_iframe.get_attribute("src"), DEFAULT_DOCUMENT_SRC)
# Expecting that the new display name is the title of the IFrame
self.assertEqual(document_iframe.get_attribute("title"), 'My Document')

@data(*IMAGE_SCENARIOS) # pylint: disable=star-args
@unpack
def test_save_image(self, page_name):
"""
Verify that option changes in Google Image studio view
are appropriately saved and visible immediately after
"""
self.go_to_page(page_name, view_name='studio_view')
# Expecting every input value to be valid
self.assertTrue(self.browser.find_element_by_css_selector('.validation_alert.covered'))
display_name_input = self.browser.find_element_by_css_selector('#edit_display_name')
# Change display name
display_name_input.clear()
display_name_input.send_keys('My Image')
# Expecting list item that contains input element for alternative text to be shown
self.assertTrue(self.browser.find_element_by_css_selector('li#alt_text_item:not(covered)'))
alt_text_input = self.browser.find_element_by_css_selector('#edit_alt_text')
# Add alternative text for image
alt_text_input.send_keys('Alternative text for my image')

self.studio_save()
self.go_to_page(page_name, css_selector='div.google-docs-xblock-wrapper')
image_iframe = self.browser.find_element_by_css_selector('img')
# Expecting that default calendar is the one loaded in the IFrame
self.assertEqual(image_iframe.get_attribute("src"), TEST_IMAGE_SRC)
# Expecting that the new display name is the title of the IFrame
self.assertEqual(image_iframe.get_attribute("alt"), 'Alternative text for my image')
4 changes: 1 addition & 3 deletions google_drive/tests/integration/xml/calendar.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<vertical_demo>
<google-calendar/>
</vertical_demo>
<google-calendar/>
4 changes: 1 addition & 3 deletions google_drive/tests/integration/xml/document.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<vertical_demo>
<google-document/>
</vertical_demo>
<google-document/>
4 changes: 1 addition & 3 deletions google_drive/tests/integration/xml/image.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<vertical_demo>
<google-document embed_code="&lt;img src='https://docs.google.com/drawings/d/1lmmxboBM5c_0WCTjhAxBdkpqQb3T8VSwtuG0TRR1ODQ/pub?w=960&amp;h=720'&gt;"/>
</vertical_demo>
<google-document embed_code="&lt;img src='https://docs.google.com/drawings/d/1lmmxboBM5c_0WCTjhAxBdkpqQb3T8VSwtuG0TRR1ODQ/pub?w=960&amp;h=720'&gt;"/>
Loading