diff --git a/.travis.yml b/.travis.yml index 130bf4b5..4437b826 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,28 @@ sudo: false + language: python + python: - "2.7" + branches: only: - master cache: directories: - $HOME/.cache/pip + before_install: - "export DISPLAY=:99" - "sh -e /etc/init.d/xvfb start" + install: - "make install" - "pip install coveralls" + script: - "make quality" - "make cover" + after_success: - "coveralls" diff --git a/Makefile b/Makefile index edd588bd..5388cd4d 100755 --- a/Makefile +++ b/Makefile @@ -36,3 +36,10 @@ quality: cover: coverage run manage.py test coverage report + +clean: + rm -f workbench.log* workbench.test.* + rm -rf workbench/static/djpyfs + rm -rf *.egg-info + rm -f .coverage + find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \; diff --git a/requirements/base.txt b/requirements/base.txt index 553daac8..a2bc1b6e 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ cookiecutter==0.9.0 -Django >= 1.4, < 1.5 +Django>=1.8,<1.9 lxml requests webob diff --git a/requirements/test.txt b/requirements/test.txt index 9f9592a5..63f22381 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,9 +1,10 @@ coverage +ddt mock pylint==0.28 pep8 rednose -bok_choy==0.3.3 +bok_choy==0.4.3 # Acid xblock -e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock diff --git a/setup.py b/setup.py index b4fa75f8..3932a427 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def load_requirements(*requirements_paths): setup( name='xblock-sdk', - version='0.1a0', + version='0.1.1', description='XBlock SDK', packages=[ 'sample_xblocks', diff --git a/workbench/scenarios.py b/workbench/scenarios.py index 4537b959..b02b6e95 100644 --- a/workbench/scenarios.py +++ b/workbench/scenarios.py @@ -74,3 +74,5 @@ def init_scenarios(): # Get all the XBlock classes, and add their scenarios. for class_name, cls in sorted(XBlock.load_classes(fail_silently=False)): add_class_scenarios(class_name, cls, fail_silently=False) + +init_scenarios() diff --git a/workbench/templates/workbench/block.html b/workbench/templates/workbench/block.html index d209cbff..0406e0d3 100644 --- a/workbench/templates/workbench/block.html +++ b/workbench/templates/workbench/block.html @@ -1,6 +1,5 @@ {% load staticfiles %} -{% load url from future %} diff --git a/workbench/templates/workbench/index.html b/workbench/templates/workbench/index.html index 956a27d0..e128d216 100644 --- a/workbench/templates/workbench/index.html +++ b/workbench/templates/workbench/index.html @@ -1,5 +1,4 @@ {% load staticfiles %} -{% load url from future %} diff --git a/workbench/test/selenium_test.py b/workbench/test/selenium_test.py index ba0bb560..ad9246a8 100644 --- a/workbench/test/selenium_test.py +++ b/workbench/test/selenium_test.py @@ -1,6 +1,6 @@ """Helpers for Selenium tests.""" -from django.test import LiveServerTestCase +from django.contrib.staticfiles.testing import StaticLiveServerTestCase from bok_choy.web_app_test import WebAppTest from nose.plugins.attrib import attr @@ -9,7 +9,7 @@ @attr('selenium') -class SeleniumTest(WebAppTest, LiveServerTestCase): +class SeleniumTest(WebAppTest, StaticLiveServerTestCase): """Base test class that provides setUpClass and tearDownClass methods necessary for selenium testing.""" diff --git a/workbench/test/test_scenarios.py b/workbench/test/test_scenarios.py index 71e33088..38d71d8c 100644 --- a/workbench/test/test_scenarios.py +++ b/workbench/test/test_scenarios.py @@ -1,60 +1,68 @@ """Test that all scenarios render successfully.""" -import lxml.html +import unittest +import ddt from django.test.client import Client +import lxml.html +from django.core.urlresolvers import reverse from xblock.test.tools import assert_equals + from workbench import scenarios +from workbench.runtime import reset_global_state + + +@ddt.ddt +class ScenarioTest(unittest.TestCase): + """Test the scenario support.""" + def setUp(self): + super(ScenarioTest, self).setUp() + reset_global_state() + + def test_all_scenarios(self): + """Load the home page, examine the scenarios displayed.""" + client = Client() + response = client.get("/") + assert response.status_code == 200 + html = lxml.html.fromstring(response.content) + a_tags = list(html.xpath('//a')) + + # Load the loaded_scenarios from the classes. + loaded_scenarios = scenarios.SCENARIOS.values() + + # We should have an tag for each scenario. + assert_equals(len(a_tags), len(loaded_scenarios)) + + # We should have at least one scenario with a vertical tag, since we use + # empty verticals as our canary in the coal mine that something has gone + # horribly wrong with loading the loaded_scenarios. + assert any("" in scen.xml for scen in loaded_scenarios) + + # Since we are claiming in try_scenario that no vertical is empty, let's + # eliminate the possibility that a scenario has an actual empty vertical. + assert all("" not in scen.xml for scen in loaded_scenarios) + assert all("" not in scen.xml for scen in loaded_scenarios) + + @ddt.data(*scenarios.SCENARIOS.keys()) + def test_scenario(self, scenario_id): + """A very shallow test, just to see if the scenario loads all its blocks. + + We don't know enough about each scenario to know what each should do. + So we load the scenario to see that the workbench could successfully + serve it. + """ + url = reverse('workbench_show_scenario', kwargs={'scenario_id': scenario_id}) + client = Client() + response = client.get(url, follow=True) + assert response.status_code == 200, scenario_id -def test_all_scenarios(): - """Load the home page, get every URL, make a test from it.""" - client = Client() - response = client.get("/") - assert response.status_code == 200 - html = lxml.html.fromstring(response.content) - a_tags = list(html.xpath('//a')) - for a_tag in a_tags: - yield try_scenario, a_tag.get('href'), a_tag.text - - # Load the loaded_scenarios from the classes. - loaded_scenarios = scenarios.SCENARIOS.values() - - # We should have an tag for each scenario. - assert_equals(len(a_tags), len(loaded_scenarios)) - - # We should have at least one scenario with a vertical tag, since we use - # empty verticals as our canary in the coal mine that something has gone - # horribly wrong with loading the loaded_scenarios. - assert any("" in scen.xml for scen in loaded_scenarios) - - # Since we are claiming in try_scenario that no vertical is empty, let's - # eliminate the possibility that a scenario has an actual empty vertical. - assert all("" not in scen.xml for scen in loaded_scenarios) - assert all("" not in scen.xml for scen in loaded_scenarios) - - -def try_scenario(url, name): - """Check that a scenario renders without error. - - `url`: the URL to the scenario to test. - - `name`: the name of the scenario, used in error messages. - - """ - # This is a very shallow test. We don't know enough about each scenario to - # know what each should do. So we load the scenario to see that the - # workbench could successfully serve it. - client = Client() - response = client.get(url, follow=True) - assert response.status_code == 200, name - - # Be sure we got the whole scenario. Again, we can't know what to expect - # here, but at the very least, if there are verticals, they should not be - # empty. That would be a sign that some data wasn't loaded properly while - # rendering the scenario. - html = lxml.html.fromstring(response.content) - for vertical_tag in html.xpath('//div[@class="vertical"]'): - # No vertical tag should be empty. - assert list(vertical_tag), "Empty shouldn't happen!" + # Be sure we got the whole scenario. Again, we can't know what to expect + # here, but at the very least, if there are verticals, they should not be + # empty. That would be a sign that some data wasn't loaded properly while + # rendering the scenario. + html = lxml.html.fromstring(response.content) + for vertical_tag in html.xpath('//div[@class="vertical"]'): + # No vertical tag should be empty. + assert list(vertical_tag), "Empty shouldn't happen!" diff --git a/workbench/urls.py b/workbench/urls.py index b3f88eee..b8e1c6a4 100644 --- a/workbench/urls.py +++ b/workbench/urls.py @@ -4,12 +4,9 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin -from workbench.scenarios import init_scenarios admin.autodiscover() -init_scenarios() - urlpatterns = patterns( 'workbench.views', url(r'^$', 'index', name='workbench_index'), diff --git a/workbench/views.py b/workbench/views.py index e801fd2c..f07b6269 100644 --- a/workbench/views.py +++ b/workbench/views.py @@ -160,7 +160,7 @@ def package_resource(_request, block_type, resource): except Exception: # pylint: disable-msg=broad-except raise Http404 mimetype, _ = mimetypes.guess_type(resource) - return HttpResponse(content, mimetype=mimetype) + return HttpResponse(content, content_type=mimetype) @csrf_exempt