Django unit tests for courses, move around test files
authorCharles Connell <charles@connells.org>
Tue, 17 Dec 2013 04:27:18 +0000 (23:27 -0500)
committerCharles Connell <charles@connells.org>
Tue, 17 Dec 2013 04:27:37 +0000 (23:27 -0500)
karmaworld/apps/ajaxuploader/tests/__init__.py [deleted file]
karmaworld/apps/ajaxuploader/tests/default_storage_backend.py [deleted file]
karmaworld/apps/ajaxuploader/tests/urls.py [deleted file]
karmaworld/apps/courses/models.py
karmaworld/apps/courses/test/selenium.py [new file with mode: 0644]
karmaworld/apps/courses/test/test.py [new file with mode: 0644]
karmaworld/apps/courses/views.py
test/selenium/add_course.py [deleted file]

diff --git a/karmaworld/apps/ajaxuploader/tests/__init__.py b/karmaworld/apps/ajaxuploader/tests/__init__.py
deleted file mode 100644 (file)
index f215d53..0000000
+++ /dev/null
@@ -1 +0,0 @@
-from ajaxuploader.tests.default_storage_backend import *
diff --git a/karmaworld/apps/ajaxuploader/tests/default_storage_backend.py b/karmaworld/apps/ajaxuploader/tests/default_storage_backend.py
deleted file mode 100644 (file)
index 495a070..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-import os
-import hashlib
-from shutil import rmtree
-
-from django.conf import settings
-from django.test import TestCase
-from django.test.client import Client
-from django.core.urlresolvers import reverse
-
-
-class AjaxUploadTest(TestCase):
-    urls = 'ajaxuploader.tests.urls'
-
-    def setUp(self):
-        super(AjaxUploadTest, self).setUp()
-        
-        self.test_dir = os.path.dirname(__file__)
-        test_file = open(os.path.join(self.test_dir, '../fixtures/pony.png'),
-                         'rb')
-
-        self.test_file_1 = test_file
-
-        # generate sha1 hash of the file
-        self.test_file_1_hash = hashlib.sha1(self.test_file_1.read())\
-                                       .hexdigest()
-
-        # reset position to beginning of the file
-        self.test_file_1.seek(0)
-        
-        
-    def tearDown(self):
-        # remove created uploads/tests directory
-        rmtree(os.path.join(settings.MEDIA_ROOT, 'uploads/tests'))
-        
-    def test_upload_raw_post_local_backend(self):
-        """
-        tests uploading a file to DefaultStorageUploadBackend
-        """
-
-        # there is a bug in Django 1.3.1 with raw_post_data in the django test client
-        # it's fixed in trunk
-        # https://code.djangoproject.com/changeset/16479
-
-        uploaded_file_name = 'tests/foo.png'
-
-        file_data = self.test_file_1.read()
-        # post raw self.test_file_1 data to AjaxFileUploader as Ajax request
-        response = self.client.post(reverse('ajax-upload-default-storage')+'?qqfile=%s' % \
-                                    uploaded_file_name, file_data,
-                                    content_type='application/octet-stream',
-                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
-
-        uploaded_file_path = os.path.join(settings.MEDIA_ROOT, 'uploads',
-                                          uploaded_file_name)
-        uploaded_file = open(uploaded_file_path, 'rb')
-
-        # uploaded file must exist in MEDIA_DIR
-        self.assertTrue(os.path.exists(uploaded_file_path))
-
-        # sha1 hash of original file and uploaded file must match
-        self.assertEquals(hashlib.sha1(uploaded_file.read()).hexdigest(),
-                          self.test_file_1_hash)
diff --git a/karmaworld/apps/ajaxuploader/tests/urls.py b/karmaworld/apps/ajaxuploader/tests/urls.py
deleted file mode 100644 (file)
index 19299d3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-from django.conf.urls.defaults import *
-
-from ajaxuploader.views import AjaxFileUploader
-from ajaxuploader.backends.default_storage import DefaultStorageUploadBackend
-
-
-default_storage_uploader = AjaxFileUploader(backend=DefaultStorageUploadBackend)
-
-urlpatterns = patterns('',
-    url(r'^upload$', default_storage_uploader, name="ajax-upload-default-storage"),                
-)
index 0c70727c0444588cd2dcde7ace3d7d4f4a717d3d..273dc69fc936620b473b715b6caa8a7866c8a1af 100644 (file)
@@ -97,7 +97,7 @@ class Course(models.Model):
         super(Course, self).save(*args, **kwargs) # generate a self.id
         if not self.slug:
             self.slug = defaultfilters.slugify("%s %s" % (self.name, self.id))
-            super(Course, self).save(*args, **kwargs) # Save the slug
+            self.save() # Save the slug
 
     def get_updated_at_string(self):
         """ return the formatted style for datetime strings """
diff --git a/karmaworld/apps/courses/test/selenium.py b/karmaworld/apps/courses/test/selenium.py
new file mode 100644 (file)
index 0000000..55c320b
--- /dev/null
@@ -0,0 +1,161 @@
+from selenium import webdriver
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.common.keys import Keys
+from selenium.webdriver.support import expected_conditions as EC
+import uuid
+import unittest
+
+
+class AddCourseTest(unittest.TestCase):
+    """Tests the Add Course form. Requires a copy of KarmaNotes
+    be available at localhost:8000. This will modify your database."""
+
+    def setUp(self):
+        self.driver = webdriver.Firefox()
+        self.driver.implicitly_wait(3)
+        self.wait = WebDriverWait(self.driver, 10)
+
+    def tearDown(self):
+        self.driver.close()
+
+    def selectAutocomplete(self, inputId, keys, fieldIndex):
+        input = self.driver.find_element_by_id(inputId)
+        input.send_keys(keys)
+        self.wait.until(EC.element_to_be_clickable((By.XPATH, "//ul[contains(@class,'ui-autocomplete')][" + str(fieldIndex) + "]/li")))
+        input.send_keys(Keys.DOWN)
+        autocompleteMenuItem = self.driver.find_element_by_id("ui-active-menuitem")
+        autocompleteMenuItem.click()
+
+    def testSchoolName(self):
+        self.driver.get("http://localhost:8000/")
+
+        # Click "Add Course"
+        addCourseButton = self.driver.find_element_by_id("add-course-btn")
+        addCourseButton.click()
+
+        # Scroll down so the autocomplete menu is in view
+        # This works around some weird failures
+        self.driver.execute_script("javascript:window.scrollBy(0,200)")
+
+        # Type in part of a school name
+        schoolInput = self.driver.find_element_by_id("str_school")
+        schoolInput.send_keys("harvard u")
+
+        # Wait for autocomplete menu to appear
+        self.wait.until(EC.element_to_be_clickable((By.XPATH, "//ul[contains(@class,'ui-autocomplete')][1]/li")))
+
+        # Choose the first suggestion
+        schoolInput.send_keys(Keys.DOWN)
+        activeItem = self.driver.find_element_by_id("ui-active-menuitem")
+        activeItem.click()
+
+        self.assertEqual(schoolInput.get_attribute("value"), "Harvard University")
+
+        schoolId = self.driver.find_element_by_id("id_school")
+        self.assertEqual(schoolId.get_attribute("value"), "1817")
+
+    def testCreateCourse(self):
+        self.driver.get("http://localhost:8000/")
+
+        # Click "Add Course"
+        addCourseButton = self.driver.find_element_by_id("add-course-btn")
+        addCourseButton.click()
+        self.driver.execute_script("javascript:window.scrollBy(0,200)")
+
+        # We shouldn't be able to save it yet
+        saveButton = self.driver.find_element_by_id("save-btn")
+        self.assertIn("disabled", saveButton.get_attribute("class"))
+
+        # Choose a school
+        self.selectAutocomplete("str_school", "northeastern u", 1)
+
+        # Check that save button is now enabled
+        self.assertNotIn("disabled", saveButton.get_attribute("class"))
+
+        # Course name
+        newCourseName = "SELENIUM TEST COURSE " + uuid.uuid4().hex
+        courseNameInput = self.driver.find_element_by_id("id_name")
+        courseNameInput.send_keys(newCourseName)
+
+        # Instructor name
+        newInstructorName = "SELENIUM TEST INSTRUCTOR " + uuid.uuid4().hex
+        instructorNameInput = self.driver.find_element_by_id("id_instructor_name")
+        instructorNameInput.send_keys(newInstructorName)
+
+        # Click "Save"
+        saveButton = self.driver.find_element_by_id("save-btn")
+        saveButton.click()
+
+        # See if we are taken to the new course page
+        self.wait.until(EC.title_contains(newCourseName))
+
+
+    def testCreateExistingCourse(self):
+        self.driver.get("http://localhost:8000/")
+
+        # Click "Add Course"
+        addCourseButton = self.driver.find_element_by_id("add-course-btn")
+        addCourseButton.click()
+        self.driver.execute_script("javascript:window.scrollBy(0,200)")
+
+        # We shouldn't be able to save it yet
+        saveButton = self.driver.find_element_by_id("save-btn")
+        self.assertIn("disabled", saveButton.get_attribute("class"))
+
+        # Choose a school
+        self.selectAutocomplete("str_school", "northeastern u", 1)
+
+        # Check that save button is now enabled
+        self.assertNotIn("disabled", saveButton.get_attribute("class"))
+
+        # Course name
+        newCourseName = "SELENIUM TEST COURSE " + uuid.uuid4().hex
+        courseNameInput = self.driver.find_element_by_id("id_name")
+        courseNameInput.send_keys(newCourseName)
+
+        # Instructor name
+        newInstructorName = "SELENIUM TEST INSTRUCTOR " + uuid.uuid4().hex
+        instructorNameInput = self.driver.find_element_by_id("id_instructor_name")
+        instructorNameInput.send_keys(newInstructorName)
+
+        # Click "Save"
+        saveButton = self.driver.find_element_by_id("save-btn")
+        saveButton.click()
+
+        # See if we are taken to the new course page
+        self.wait.until(EC.title_contains(newCourseName))
+
+        # Now go back to the home page
+        self.driver.get("http://localhost:8000/")
+
+        # Click "Add Course"
+        addCourseButton = self.driver.find_element_by_id("add-course-btn")
+        addCourseButton.click()
+        self.driver.execute_script("javascript:window.scrollBy(0,200)")
+
+        # Choose the SAME school
+        self.selectAutocomplete("str_school", "northeastern u", 1)
+
+        # The SAME course name
+        self.selectAutocomplete("id_name", newCourseName, 2)
+
+        # The SAME instructor name
+        self.selectAutocomplete("id_instructor_name", newInstructorName, 3)
+
+        # Make sure Save button is disabled and hidden
+        saveButton = self.driver.find_element_by_id("save-btn")
+        self.assertIn("disabled", saveButton.get_attribute("class"))
+        self.wait.until_not(EC.visibility_of(saveButton))
+
+        # Make sure Existing Course link is shown
+        existingCourse = self.driver.find_element_by_id("existing-course-btn")
+        self.wait.until(EC.visibility_of(existingCourse))
+        existingCourse.click()
+
+        # See if we are taken to the new course page
+        self.wait.until(EC.title_contains(newCourseName))
+
+if __name__ == "__main__":
+    unittest.main()
+
diff --git a/karmaworld/apps/courses/test/test.py b/karmaworld/apps/courses/test/test.py
new file mode 100644 (file)
index 0000000..36d7f0f
--- /dev/null
@@ -0,0 +1,148 @@
+from django.test import TestCase
+from karmaworld.apps.courses.models import *
+from django.test.client import Client
+from django.core.urlresolvers import reverse
+import unittest
+import json
+
+class CoursesTests(TestCase):
+
+    def setUp(self):
+        self.harvard = School.objects.create(name="Harvard University")
+        self.harvard.save()
+        self.course1 = Course.objects.create(name="Underwater Basketweaving", instructor_name="Alice Janney", school=self.harvard)
+        self.client = Client()
+
+    def testCourseUniqueness(self):
+        """Make sure we can't create multiple courses with the same
+        school + course name + instructor name combination."""
+        #with self.assertRaises(Exception):
+        #    Course.objects.create(name="Underwater Basketweaving", instructor_name="Alice", school=self.harvard)
+
+    def testSearchForSchool(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_list'),
+                                    {"q": "harvard u"},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertIn('schools', responseContent)
+
+        # Is the correct school in the list?
+        self.assertEqual(responseContent['schools'][0]['name'], 'Harvard University')
+
+
+    def testSearchForBadSchool(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_list'),
+                                    {"q": "A FAKE SCHOOL"},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertEqual(len(responseContent['schools']), 0)
+
+
+    def testSearchForCourseName(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_list'),
+                                    {"q": "under", 'school_id': self.harvard.id},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertIn('courses', responseContent)
+
+        # Is the correct school in the list?
+        self.assertEqual(responseContent['courses'][0]['name'], 'Underwater Basketweaving')
+
+
+    def testSearchForBadCourseName(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_list'),
+                                    {"q": "A FAKE COURSE NAME", 'school_id': self.harvard.id},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertIn('courses', responseContent)
+
+        # Is the correct school in the list?
+        self.assertEqual(len(responseContent['courses']), 0)
+
+
+    def testSearchForCourseNameWithBadRequest(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_list'),
+                                    {"q": "under", 'school_id': '3737373737'},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 400)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'fail')
+
+    def testSearchForInstructorName(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_instructor_list'),
+                                    {"q": "alice", 'course_name': self.course1.name, 'school_id': self.harvard.id},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertIn('instructors', responseContent)
+
+        # Is the correct school in the list?
+        self.assertEqual(responseContent['instructors'][0]['name'], 'Alice Janney')
+
+
+    def testSearchForBadInstructorName(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_instructor_list'),
+                                   {"q": "bob", 'course_name': self.course1.name, 'school_id': self.harvard.id},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 200)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'success')
+        self.assertIn('instructors', responseContent)
+
+        # Is the correct school in the list?
+        self.assertEqual(len(responseContent['instructors']), 0)
+
+
+    def testSearchForInstructorNameWithBadRequest(self):
+        """Test searching for a school by partial name"""
+        response = self.client.post(reverse('karmaworld.apps.courses.views.school_course_instructor_list'),
+                                    {"q": "alice", 'course_name': self.course1.name, 'school_id': '3737373737'},
+                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+        self.assertEqual(response.status_code, 400)
+        responseContent = json.loads(response.content)
+
+        # Did we get a good response back?
+        self.assertIn('status', responseContent)
+        self.assertEqual(responseContent['status'], 'fail')
+
+
+
+if __name__ == "__main__":
+    unittest.main()
+
index 18f27fee60368147ac430e3f0b10eae85c05fa75..39c32ad09c0b35ba2e85a69c89031092646817d7 100644 (file)
@@ -8,7 +8,7 @@ import json
 from django.core.exceptions import MultipleObjectsReturned
 from django.core.exceptions import ObjectDoesNotExist
 
-from django.http import HttpResponse, HttpResponseNotFound
+from django.http import HttpResponse, HttpResponseBadRequest
 from django.views.generic import DetailView
 from django.views.generic import TemplateView
 from django.views.generic.edit import ProcessFormView
@@ -103,7 +103,7 @@ def school_list(request):
         return HttpResponse(json.dumps({'status':'success', 'schools': schools}), mimetype="application/json")
     else:
         # else return that the api call failed
-        return HttpResponse(json.dumps({'status':'fail'}), mimetype="application/json")
+        return HttpResponseBadRequest(json.dumps({'status':'fail'}), mimetype="application/json")
 
 
 def school_course_list(request):
@@ -117,7 +117,7 @@ def school_course_list(request):
         try:
           _school_id = int(request.POST['school_id'])
         except:
-          return HttpResponseNotFound(json.dumps({'status': 'fail',
+          return HttpResponseBadRequest(json.dumps({'status': 'fail',
                                                   'message': 'could not convert school id to integer'}),
                                       mimetype="application/json")
 
@@ -125,7 +125,7 @@ def school_course_list(request):
         try:
             school = School.objects.get(id__exact=_school_id)
         except (MultipleObjectsReturned, ObjectDoesNotExist):
-            return HttpResponseNotFound(json.dumps({'status': 'fail',
+            return HttpResponseBadRequest(json.dumps({'status': 'fail',
                                                     'message': 'school id did not match exactly one school'}),
                                         mimetype="application/json")
 
@@ -138,7 +138,7 @@ def school_course_list(request):
                             mimetype="application/json")
     else:
         # else return that the api call failed
-        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': 'query parameters missing'}),
+        return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'query parameters missing'}),
                                     mimetype="application/json")
 
 def school_course_instructor_list(request):
@@ -155,7 +155,7 @@ def school_course_instructor_list(request):
         try:
           _school_id = int(request.POST['school_id'])
         except:
-          return HttpResponseNotFound(json.dumps({'status': 'fail',
+          return HttpResponseBadRequest(json.dumps({'status': 'fail',
                                                   'message':'could not convert school id to integer'}),
                                       mimetype="application/json")
 
@@ -163,7 +163,7 @@ def school_course_instructor_list(request):
         try:
             school = School.objects.get(id__exact=_school_id)
         except (MultipleObjectsReturned, ObjectDoesNotExist):
-            return HttpResponseNotFound(json.dumps({'status': 'fail',
+            return HttpResponseBadRequest(json.dumps({'status': 'fail',
                                                     'message': 'school id did not match exactly one school'}),
                                         mimetype="application/json")
 
@@ -178,5 +178,6 @@ def school_course_instructor_list(request):
                             mimetype="application/json")
     else:
         # else return that the api call failed
-        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': 'query parameters missing'}),
+        return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'query parameters missing'}),
                                     mimetype="application/json")
+
diff --git a/test/selenium/add_course.py b/test/selenium/add_course.py
deleted file mode 100644 (file)
index 679edee..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-from selenium import webdriver
-from selenium.webdriver.support.wait import WebDriverWait
-from selenium.webdriver.common.by import By
-from selenium.webdriver.common.keys import Keys
-from selenium.webdriver.support import expected_conditions as EC
-import uuid
-import unittest
-
-
-class AddCourseTest(unittest.TestCase):
-    """Tests the Add Course form. Requires a copy of KarmaNotes
-    be available at localhost:8000. This will modify your database."""
-    
-    def setUp(self):
-        self.driver = webdriver.Firefox()
-        self.driver.implicitly_wait(3)
-        self.wait = WebDriverWait(self.driver, 10)
-
-    def tearDown(self):
-        self.driver.close()
-
-    def selectAutocomplete(self, inputId, keys, fieldIndex):
-        input = self.driver.find_element_by_id(inputId)
-        input.send_keys(keys)
-        self.wait.until(EC.element_to_be_clickable((By.XPATH, "//ul[contains(@class,'ui-autocomplete')][" + str(fieldIndex) + "]/li")))
-        input.send_keys(Keys.DOWN)
-        autocompleteMenuItem = self.driver.find_element_by_id("ui-active-menuitem")
-        autocompleteMenuItem.click()
-
-    def testSchoolName(self):
-        self.driver.get("http://localhost:8000/")
-
-        # Click "Add Course"
-        addCourseButton = self.driver.find_element_by_id("add-course-btn")
-        addCourseButton.click()
-
-        # Scroll down so the autocomplete menu is in view
-        # This works around some weird failures
-        self.driver.execute_script("javascript:window.scrollBy(0,200)")
-
-        # Type in part of a school name
-        schoolInput = self.driver.find_element_by_id("str_school")
-        schoolInput.send_keys("harvard u")
-
-        # Wait for autocomplete menu to appear
-        self.wait.until(EC.element_to_be_clickable((By.XPATH, "//ul[contains(@class,'ui-autocomplete')][1]/li")))
-
-        # Choose the first suggestion
-        schoolInput.send_keys(Keys.DOWN)
-        activeItem = self.driver.find_element_by_id("ui-active-menuitem")
-        activeItem.click()
-
-        self.assertEqual(schoolInput.get_attribute("value"), "Harvard University")
-
-        schoolId = self.driver.find_element_by_id("id_school")
-        self.assertEqual(schoolId.get_attribute("value"), "1817")
-
-    def testCreateCourse(self):
-        self.driver.get("http://localhost:8000/")
-
-        # Click "Add Course"
-        addCourseButton = self.driver.find_element_by_id("add-course-btn")
-        addCourseButton.click()
-        self.driver.execute_script("javascript:window.scrollBy(0,200)")
-
-        # We shouldn't be able to save it yet
-        saveButton = self.driver.find_element_by_id("save-btn")
-        self.assertIn("disabled", saveButton.get_attribute("class"))
-
-        # Choose a school
-        self.selectAutocomplete("str_school", "northeastern u", 1)
-
-        # Check that save button is now enabled
-        self.assertNotIn("disabled", saveButton.get_attribute("class"))
-
-        # Course name
-        newCourseName = "SELENIUM TEST COURSE " + uuid.uuid4().hex
-        courseNameInput = self.driver.find_element_by_id("id_name")
-        courseNameInput.send_keys(newCourseName)
-
-        # Instructor name
-        newInstructorName = "SELENIUM TEST INSTRUCTOR " + uuid.uuid4().hex
-        instructorNameInput = self.driver.find_element_by_id("id_instructor_name")
-        instructorNameInput.send_keys(newInstructorName)
-
-        # Click "Save"
-        saveButton = self.driver.find_element_by_id("save-btn")
-        saveButton.click()
-
-        # See if we are taken to the new course page
-        self.wait.until(EC.title_contains(newCourseName))
-
-
-    def testCreateExistingCourse(self):
-        self.driver.get("http://localhost:8000/")
-
-        # Click "Add Course"
-        addCourseButton = self.driver.find_element_by_id("add-course-btn")
-        addCourseButton.click()
-        self.driver.execute_script("javascript:window.scrollBy(0,200)")
-
-        # We shouldn't be able to save it yet
-        saveButton = self.driver.find_element_by_id("save-btn")
-        self.assertIn("disabled", saveButton.get_attribute("class"))
-
-        # Choose a school
-        self.selectAutocomplete("str_school", "northeastern u", 1)
-
-        # Check that save button is now enabled
-        self.assertNotIn("disabled", saveButton.get_attribute("class"))
-
-        # Course name
-        newCourseName = "SELENIUM TEST COURSE " + uuid.uuid4().hex
-        courseNameInput = self.driver.find_element_by_id("id_name")
-        courseNameInput.send_keys(newCourseName)
-
-        # Instructor name
-        newInstructorName = "SELENIUM TEST INSTRUCTOR " + uuid.uuid4().hex
-        instructorNameInput = self.driver.find_element_by_id("id_instructor_name")
-        instructorNameInput.send_keys(newInstructorName)
-
-        # Click "Save"
-        saveButton = self.driver.find_element_by_id("save-btn")
-        saveButton.click()
-
-        # See if we are taken to the new course page
-        self.wait.until(EC.title_contains(newCourseName))
-
-        # Now go back to the home page
-        self.driver.get("http://localhost:8000/")
-
-        # Click "Add Course"
-        addCourseButton = self.driver.find_element_by_id("add-course-btn")
-        addCourseButton.click()
-        self.driver.execute_script("javascript:window.scrollBy(0,200)")
-
-        # Choose the SAME school
-        self.selectAutocomplete("str_school", "northeastern u", 1)
-
-        # The SAME course name
-        self.selectAutocomplete("id_name", newCourseName, 2)
-
-        # The SAME instructor name
-        self.selectAutocomplete("id_instructor_name", newInstructorName, 3)
-
-        # Make sure Save button is disabled and hidden
-        saveButton = self.driver.find_element_by_id("save-btn")
-        self.assertIn("disabled", saveButton.get_attribute("class"))
-        self.wait.until_not(EC.visibility_of(saveButton))
-
-        # Make sure Existing Course link is shown
-        existingCourse = self.driver.find_element_by_id("existing-course-btn")
-        self.wait.until(EC.visibility_of(existingCourse))
-        existingCourse.click()
-
-        # See if we are taken to the new course page
-        self.wait.until(EC.title_contains(newCourseName))
-
-if __name__ == "__main__":
-    unittest.main()
-