diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 85ef300..320533f 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -2,7 +2,7 @@ name: Create release draft on: push: - branches: [dev] + branches: [main] jobs: draft: diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 5bdfa43..b36f24c 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -17,10 +17,12 @@ jobs: env: DOTENV: '${{ secrets.DOTENV }}' run: echo "$DOTENV" >> .env - - name: Setup python + - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.10' + - name: Setup Chrome + uses: nanasess/setup-chromedriver@v1.0.8 - name: Install dependencies run: python -m pip install -r requirements.txt - name: Test build diff --git a/.gitignore b/.gitignore index 82ad58d..1204c03 100644 --- a/.gitignore +++ b/.gitignore @@ -260,14 +260,6 @@ cython_debug/ ### venv ### # Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ -[Bb]in -[Ii]nclude -[Ll]ib -[Ll]ib64 -[Ll]ocal -[Ss]cripts -pyvenv.cfg -pip-selfcheck.json +venv # End of https://www.toptal.com/developers/gitignore/api/django,python,pydev,venv - diff --git a/housewars/forms/UserEntryForm.py b/housewars/forms/UserEntryForm.py index b4c3533..4405fe7 100644 --- a/housewars/forms/UserEntryForm.py +++ b/housewars/forms/UserEntryForm.py @@ -36,7 +36,7 @@ class UserEntryForm(Form): # Verify that email domain matches if ('@slps.org' not in email): - raise ValidationError("Please use your school email") + raise ValidationError("Please use your school email.") # Verify that the email is unique if UserEntry.objects.filter(email=email).exists(): raise ValidationError( diff --git a/housewars/migrations/0005_activity_room_number_alter_teacher_grade.py b/housewars/migrations/0005_activity_room_number_alter_teacher_grade.py new file mode 100644 index 0000000..a0cea31 --- /dev/null +++ b/housewars/migrations/0005_activity_room_number_alter_teacher_grade.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.4 on 2022-09-07 12:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('housewars', '0004_alter_pointsentry_unique_together'), + ] + + operations = [ + migrations.AddField( + model_name='activity', + name='room_number', + field=models.IntegerField(blank=True, default=None, null=True), + ), + migrations.AlterField( + model_name='teacher', + name='grade', + field=models.IntegerField(blank=True, choices=[(9, '9th/Freshman'), (10, '10th/Sophomore'), (11, '11th/Junior'), (12, '12th/Senior')], default=None, null=True), + ), + ] diff --git a/housewars/migrations/0005_alter_teacher_grade.py b/housewars/migrations/0005_alter_teacher_grade.py new file mode 100644 index 0000000..f5f61a8 --- /dev/null +++ b/housewars/migrations/0005_alter_teacher_grade.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.4 on 2022-09-06 13:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('housewars', '0004_alter_pointsentry_unique_together'), + ] + + operations = [ + migrations.AlterField( + model_name='teacher', + name='grade', + field=models.IntegerField(blank=True, choices=[(9, '9th/Freshman'), (10, '10th/Sophomore'), (11, '11th/Junior'), (12, '12th/Senior')], default=None, null=True), + ), + ] diff --git a/housewars/models/Activity.py b/housewars/models/Activity.py index 9d0b191..585c683 100644 --- a/housewars/models/Activity.py +++ b/housewars/models/Activity.py @@ -13,6 +13,7 @@ class Activity(models.Model): name = models.CharField(max_length=100) default_quota = models.IntegerField(default=0) time = models.IntegerField(choices=TimeslotChoices) + room_number = models.IntegerField(blank=True, null=True, default=None) password = models.CharField( max_length=100, blank=True, null=True, default=None) diff --git a/housewars/models/Teacher.py b/housewars/models/Teacher.py index faf5a72..f09d013 100644 --- a/housewars/models/Teacher.py +++ b/housewars/models/Teacher.py @@ -17,7 +17,8 @@ class Teacher(models.Model): last_name = models.CharField(max_length=100) house = models.ForeignKey( House, related_name='teacher', default=None, blank=True, null=True, on_delete=models.SET_NULL) - grade = models.IntegerField(choices=GradeChoices) + grade = models.IntegerField( + choices=GradeChoices, default=None, blank=True, null=True) activity = models.OneToOneField( Activity, related_name='teacher', default=None, blank=True, null=True, on_delete=models.SET_NULL) diff --git a/housewars/tests/forms/__init__.py b/housewars/tests/forms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/housewars/tests/forms/test_activity_form.py b/housewars/tests/forms/test_activity_form.py new file mode 100644 index 0000000..4477f7e --- /dev/null +++ b/housewars/tests/forms/test_activity_form.py @@ -0,0 +1,33 @@ +from django.test import TestCase + +from housewars.forms import ActivityForm +from housewars.models import Activity, House + + +class ActivityFormTest(TestCase): + def setUp(self): + self.activity30 = Activity.objects.create(name='Dodgeball', time=30) + self.activity60 = Activity.objects.create(name='Dodgeball', time=60) + + def test_valid_time(self): + form = ActivityForm(data={ + 'activity1': self.activity30.id, + 'activity2': self.activity30.id, + }) + + self.assertTrue(form.is_valid()) + + def test_invalid_time(self): + form = ActivityForm(data={ + 'activity1': self.activity60.id, + 'activity2': self.activity30.id, + }) + + self.assertFalse(form.is_valid()) + self.assertEquals(len(form.errors), 1) + + def test_no_data(self): + form = ActivityForm(data={}) + + self.assertFalse(form.is_valid()) + self.assertEquals(len(form.errors), 2) diff --git a/housewars/tests/forms/test_points_entry_form.py b/housewars/tests/forms/test_points_entry_form.py new file mode 100644 index 0000000..293036c --- /dev/null +++ b/housewars/tests/forms/test_points_entry_form.py @@ -0,0 +1,27 @@ +from django.test import TestCase + +from housewars.forms import PointsEntryForm +from housewars.models import Activity, House, Award + + +class ActivityFormTest(TestCase): + def setUp(self): + self.house = House.objects.create(name='Hawk') + self.activity = Activity.objects.create(name='Dodgeball', time=30) + self.activity2 = Activity.objects.create(name='Dodgeball', time=30) + self.award = Award.objects.create(name='1st', activity=self.activity) + + def test_valid_time(self): + form = PointsEntryForm(data={ + 'house': self.house.id, + 'activity': self.activity.id, + 'award': self.award.id + }) + + self.assertTrue(form.is_valid()) + + def test_no_data(self): + form = PointsEntryForm(data={}) + + self.assertFalse(form.is_valid()) + self.assertEquals(len(form.errors), 3) diff --git a/housewars/tests/forms/test_user_entry_form.py b/housewars/tests/forms/test_user_entry_form.py new file mode 100644 index 0000000..fa3bd5c --- /dev/null +++ b/housewars/tests/forms/test_user_entry_form.py @@ -0,0 +1,38 @@ +from django.test import TestCase + +from housewars.forms import UserEntryForm +from housewars.models import House + + +class UserEntryFormTest(TestCase): + def setUp(self): + self.house = House.objects.create(name='Hawk', points=30) + + def test_valid(self): + form = UserEntryForm(data={ + 'first_name': 'Test', + 'last_name': 'User', + 'email': 'test.user@slps.org', + 'grade': 9, + 'house': self.house.id + }) + + self.assertTrue(form.is_valid()) + + def test_invalid_email(self): + form = UserEntryForm(data={ + 'first_name': 'Test', + 'last_name': 'User', + 'email': 'test.user@gmail.com', + 'grade': 9, + 'house': self.house.id + }) + + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 1) + + def test_no_data(self): + form = UserEntryForm(data={}) + + self.assertFalse(form.is_valid()) + self.assertEquals(len(form.errors), 5) diff --git a/housewars/tests/models/__init__.py b/housewars/tests/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/housewars/tests/models/test_house.py b/housewars/tests/models/test_house.py new file mode 100644 index 0000000..f6608f6 --- /dev/null +++ b/housewars/tests/models/test_house.py @@ -0,0 +1,23 @@ +from django.test import TestCase + +from housewars.models import Activity, House, Award, PointsEntry + + +class HouseModelTest(TestCase): + def setUp(self): + self.house = House.objects.create(name='Hawk', points=30) + self.activity = Activity.objects.create(name='Dodgeball', time=30) + self.award = Award.objects.create( + activity=self.activity, name='1st', points=30) + + def test_current_points(self): + PointsEntry.objects.create( + activity=self.activity, house=self.house, award=self.award) + + self.assertEquals(self.house.current_points, 30) + + def test_total_points(self): + PointsEntry.objects.create( + activity=self.activity, house=self.house, award=self.award) + + self.assertEquals(self.house.total_points, 60) diff --git a/housewars/tests/models/test_user_entry.py b/housewars/tests/models/test_user_entry.py new file mode 100644 index 0000000..7103726 --- /dev/null +++ b/housewars/tests/models/test_user_entry.py @@ -0,0 +1,18 @@ +from django.test import TestCase, Client +from django.urls import reverse + +from housewars.models import Activity, House, Teacher, UserEntry + + +class UserEntryTest(TestCase): + def setUp(self): + self.client = Client() + self.house = House.objects.create(name='Hawk', points=30) + self.activity = Activity.objects.create(name='Dodgeball', time=30) + self.entry = UserEntry.objects.create( + first_name='Test', last_name='User', email='test.user@slps.org', grade=9, house=self.house, activity1=self.activity, activity2=self.activity) + self.teacher = Teacher.objects.create( + first_name='Test', last_name='Teacher', grade=9, house=self.house) + + def test_mentor(self): + self.assertEquals(self.entry.mentor, self.teacher) diff --git a/housewars/tests/test_urls.py b/housewars/tests/test_urls.py new file mode 100644 index 0000000..153275b --- /dev/null +++ b/housewars/tests/test_urls.py @@ -0,0 +1,14 @@ +from django.test import TestCase +from django.urls import reverse, resolve + +from housewars.views import EntryCreateView, PointsEntryCreateView + + +class TestUrls(TestCase): + def test_entry_create_is_resolved(self): + url = reverse('housewars:signup') + self.assertEquals(resolve(url).func.view_class, EntryCreateView) + + def test_points_entry_create_is_resolved(self): + url = reverse('housewars:add_points') + self.assertEquals(resolve(url).func.view_class, PointsEntryCreateView) diff --git a/housewars/tests/utils/__init__.py b/housewars/tests/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/housewars/tests/utils/test_get_random_string.py b/housewars/tests/utils/test_get_random_string.py new file mode 100644 index 0000000..9e03294 --- /dev/null +++ b/housewars/tests/utils/test_get_random_string.py @@ -0,0 +1,15 @@ +from django.test import TestCase + +from housewars.utils import get_random_string + + +class GetRandomStringTest(TestCase): + def test_string_of_length_8(self): + """The string generated is of the correct length""" + string = get_random_string(8) + self.assertEqual(len(string), 8) + + def test_string_of_length_6(self): + """The string generated is of the correct length""" + string = get_random_string(6) + self.assertEqual(len(string), 6) diff --git a/housewars/tests/utils/test_unpack_values.py b/housewars/tests/utils/test_unpack_values.py new file mode 100644 index 0000000..56a54b3 --- /dev/null +++ b/housewars/tests/utils/test_unpack_values.py @@ -0,0 +1,25 @@ +from django.test import TestCase + +from housewars.utils import unpack_values +from housewars.models import House + + +class UnpackValuesTest(TestCase): + def setUp(self): + House.objects.create(name="Hawk") + House.objects.create(name="Snowy") + + self.test_queryset = House.objects.all() + + def test_valid_row_headers(self): + """Correctly unpacks the headers into the first index""" + values = unpack_values(self.test_queryset) + self.assertEqual( + values[0], [field.name for field in House._meta.fields]) + + def test_complete_values(self): + """Maintains the complete queryset and returns it""" + values = unpack_values(self.test_queryset) + queryset = list(self.test_queryset.values_list()) + for row in queryset: + self.assertIn(list(row), values) diff --git a/housewars/tests/views/test_points_entry_create.py b/housewars/tests/views/test_points_entry_create.py index 9bc5a9b..2082c20 100644 --- a/housewars/tests/views/test_points_entry_create.py +++ b/housewars/tests/views/test_points_entry_create.py @@ -1,15 +1,35 @@ -from django.test import TestCase +from django.test import TestCase, Client from django.urls import reverse -from ...models import Activity, House +from housewars.models import Activity, House, Award class PointsEntryCreateViewTest(TestCase): - def test_view_url_accessible_by_name(self): - response = self.client.get(reverse('housewars:add_points')) - self.assertEqual(response.status_code, 200) + def setUp(self): + self.client = Client() + self.url = reverse('housewars:add_points') + self.house = House.objects.create(name='Hawk') + self.activity = Activity.objects.create(name='Dodgeball', time=30) + self.award = Award.objects.create(activity=self.activity, name='1st') - def test_view_uses_correct_template(self): - response = self.client.get(reverse('housewars:add_points')) - self.assertEqual(response.status_code, 200) + def test_GET(self): + response = self.client.get(self.url) + + self.assertEquals(response.status_code, 200) self.assertTemplateUsed(response, 'housewars/pointsentry_form.html') + + def test_POST(self): + response = self.client.post(self.url, { + 'house': self.house.id, + 'activity': self.activity.id, + 'award': self.award.id + }) + + self.assertEquals(response.status_code, 302) + self.assertEquals(self.house.pointsentry_set.count(), 1) + + def test_failed_POST(self): + response = self.client.post(self.url) + + self.assertEquals(response.status_code, 200) + self.assertEquals(self.house.pointsentry_set.count(), 0) diff --git a/housewars/tests/views/test_user_entry_create.py b/housewars/tests/views/test_user_entry_create.py index bc5a794..88426e0 100644 --- a/housewars/tests/views/test_user_entry_create.py +++ b/housewars/tests/views/test_user_entry_create.py @@ -1,15 +1,68 @@ -from django.test import TestCase +import enum +from django.test import TestCase, Client from django.urls import reverse -from ...models import Activity, House +from housewars.models import Activity, House class UserEntryCreateViewTest(TestCase): - def test_view_url_accessible_by_name(self): - response = self.client.get(reverse('housewars:signup')) - self.assertEqual(response.status_code, 200) + def setUp(self): + self.client = Client() + self.url = reverse('housewars:signup') + self.house = House.objects.create(name='Hawk') + self.activity = Activity.objects.create( + name='Dodgeball', time=30, default_quota=5) + self.full_activity = Activity.objects.create( + name='Dodgeball', time=30) - def test_view_uses_correct_template(self): - response = self.client.get(reverse('housewars:signup')) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, 'housewars/entry_form.html') + def test_POST(self): + user_info_form = { + 'user-first_name': 'Test', + 'user-last_name': 'User', + 'user-email': 'asdfasdf@slps.org', + 'user-grade': 9, + 'user-house': self.house.id, + 'entry_create_view-current_step': 'user' + } + + activity_form = { + 'activity-activity1': self.activity.id, + 'activity-activity2': self.activity.id, + 'entry_create_view-current_step': 'activity' + } + + steps_data = [user_info_form, activity_form] + + for data in steps_data: + self.client.post(self.url, data) + + self.assertEquals(self.house.userentry_set.count(), 1) + + def test_full_activity_POST(self): + user_info_form = { + 'user-first_name': 'Test', + 'user-last_name': 'User', + 'user-email': 'asdfasdf@slps.org', + 'user-grade': 9, + 'user-house': self.house.id, + 'entry_create_view-current_step': 'user' + } + + activity_form = { + 'activity-activity1': self.full_activity.id, + 'activity-activity2': self.full_activity.id, + 'entry_create_view-current_step': 'activity' + } + + steps_data = [user_info_form, activity_form] + + for data in steps_data: + self.client.post(self.url, data) + + self.assertEquals(self.house.userentry_set.count(), 0) + + def test_empty_POST(self): + response = self.client.post(self.url) + + self.assertEquals(response.status_code, 400) + self.assertEquals(self.house.pointsentry_set.count(), 0) diff --git a/housewars/views.py b/housewars/views.py index 1fb28e3..319d4c2 100644 --- a/housewars/views.py +++ b/housewars/views.py @@ -48,7 +48,7 @@ class EntryCreateView(SessionWizardView): def done(self, form_list, **kwargs): UserEntry.objects.create(**self.get_all_cleaned_data()) - messages.success(self.request, 'Your entry has been submitted') + messages.success(self.request, 'Your signup has been submitted.') return redirect('housewars:signup') def get_success_url(self): diff --git a/requirements.txt b/requirements.txt index 1f846b9..393d543 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ async-generator==1.10 attrs==22.1.0 autopep8==1.6.0 certifi==2022.6.15 +charset-normalizer==2.1.1 Django==4.0.4 django-formtools==2.3 django-smart-selects==1.6.0 @@ -16,14 +17,17 @@ pycodestyle==2.8.0 PySocks==1.7.1 python-dotenv==0.20.0 reportlab==3.6.11 +requests==2.28.1 selenium==4.4.3 sniffio==1.3.0 sortedcontainers==2.4.0 sqlparse==0.4.2 toml==0.10.2 +tqdm==4.64.1 trio==0.21.0 trio-websocket==0.9.2 tzdata==2022.1 urllib3==1.26.12 +webdriver-manager==3.8.3 whitenoise==6.2.0 wsproto==1.2.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_points_entry_create.py b/tests/test_points_entry_create.py new file mode 100644 index 0000000..3075669 --- /dev/null +++ b/tests/test_points_entry_create.py @@ -0,0 +1,62 @@ +from django.urls import reverse +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from selenium.webdriver import Chrome +from selenium.webdriver.chrome.options import Options +from webdriver_manager.chrome import ChromeDriverManager +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support.select import Select +from selenium.webdriver.support.expected_conditions import visibility_of + +from housewars.models import House, Activity, Award + + +class UserEntryCreatePageTest(StaticLiveServerTestCase): + def setUp(self): + options = Options() + options.add_argument('--headless') + + self.browser = Chrome( + ChromeDriverManager().install(), chrome_options=options) + self.url = self.live_server_url + reverse('housewars:add_points') + + self.house = House.objects.create(name='Hawk') + self.activity = Activity.objects.create(name='Dodgeball', time=30) + self.award = Award.objects.create(name='1st', activity=self.activity) + + def tearDown(self): + self.browser.close() + + def test_user_form_submission(self): + self.browser.get(self.url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Fill in form with valid inputs + Select(self.browser.find_element(By.ID, 'id_activity') + ).select_by_visible_text('Dodgeball (30)') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Hawk') + Select(self.browser.find_element(By.ID, 'id_award') + ).select_by_visible_text('1st') + self.browser.find_element(By.ID, 'submit').click() + + # Verify that success message is shown + success_text = self.browser.find_element( + By.CSS_SELECTOR, 'div.alert.alert-success').text + self.assertEquals( + success_text, 'Your points entry has been submitted.') + + def test_no_awards_on_default(self): + self.browser.get(self.url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Verify that only null option is in options + award_select = Select(self.browser.find_element(By.ID, 'id_award')) + self.assertEquals(len(award_select.options), 1) diff --git a/tests/test_user_entry_create.py b/tests/test_user_entry_create.py new file mode 100644 index 0000000..cb22699 --- /dev/null +++ b/tests/test_user_entry_create.py @@ -0,0 +1,189 @@ +from django.urls import reverse +from django.contrib.staticfiles.testing import StaticLiveServerTestCase + +from selenium.webdriver import Chrome +from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.by import By +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support.select import Select +from selenium.webdriver.support.expected_conditions import visibility_of +from webdriver_manager.chrome import ChromeDriverManager + +from housewars.models import House, Activity, UserEntry + + +class UserEntryCreatePageTest(StaticLiveServerTestCase): + def setUp(self): + options = Options() + options.add_argument('--headless') + + self.browser = Chrome( + ChromeDriverManager().install(), chrome_options=options) + self.url = self.live_server_url + reverse('housewars:signup') + + self.house = House.objects.create(name='Hawk') + self.activity30 = Activity.objects.create( + name='Dodgeball', time=30, default_quota=5) + self.activity60 = Activity.objects.create( + name='Volleyball', time=60, default_quota=5) + self.hidden = Activity.objects.create( + name='Hidden', time=30, default_quota=1) + + def tearDown(self): + self.browser.close() + + def test_user_form_submission(self): + self.browser.get(self.url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + self.assertEqual(self.browser.title, 'House Wars - Signup') + + self.browser.find_element(By.ID, 'first-name').send_keys('Test') + self.browser.find_element(By.ID, 'last-name').send_keys('User') + self.browser.find_element( + By.ID, 'email').send_keys('test.user@slps.org') + Select(self.browser.find_element(By.ID, 'grade') + ).select_by_visible_text('9th/Freshman') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Hawk') + self.browser.find_element(By.ID, 'submit').click() + + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'activity1'))) + + Select(self.browser.find_element(By.ID, 'activity1') + ).select_by_visible_text('Dodgeball (30)') + Select(self.browser.find_element(By.ID, 'activity2') + ).select_by_visible_text('Dodgeball (30)') + + self.browser.find_element(By.ID, 'submit').click() + + success_text = self.browser.find_element( + By.CSS_SELECTOR, 'div.alert.alert-success').text + + self.assertEquals(success_text, 'Your signup has been submitted.') + + def test_user_invalid_email(self): + self.browser.get(self.live_server_url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Fill in form with valid inputs except email + self.browser.find_element(By.ID, 'first-name').send_keys('Test') + self.browser.find_element(By.ID, 'last-name').send_keys('User') + self.browser.find_element( + By.ID, 'email').send_keys('test.user@gmail.com') + Select(self.browser.find_element(By.ID, 'grade') + ).select_by_visible_text('9th/Freshman') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Hawk') + self.browser.find_element(By.ID, 'submit').click() + + # Verify that there is a domain error on submit + error_text = self.browser.find_element( + By.CSS_SELECTOR, 'div.alert.alert-danger').text + self.assertEquals(error_text, 'Please use your school email.') + + def test_user_used_email(self): + UserEntry.objects.create(first_name='Test', last_name='User', email='test.user@slps.org', grade=9, house=self.house, + activity1=self.activity30, activity2=self.activity30) + + self.browser.get(self.live_server_url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Fill in form with valid inputs and duplicate email + self.browser.find_element(By.ID, 'first-name').send_keys('Test') + self.browser.find_element(By.ID, 'last-name').send_keys('User') + self.browser.find_element( + By.ID, 'email').send_keys('test.user@slps.org') + Select(self.browser.find_element(By.ID, 'grade') + ).select_by_visible_text('9th/Freshman') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Hawk') + self.browser.find_element(By.ID, 'submit').click() + + # Verify that duplicate error shows up on submit + error_text = self.browser.find_element( + By.CSS_SELECTOR, 'div.alert.alert-danger').text + self.assertEquals( + error_text, 'A signup with this email already exists, if you want to change your signups, please email cpatino8605@slps.org.') + + def test_invalid_select_elements_are_not_visible(self): + UserEntry.objects.create(first_name='Test', last_name='User', email='user.exist@slps.org', grade=9, house=self.house, + activity1=self.hidden, activity2=self.activity30) + + self.browser.get(self.live_server_url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Fill in form with valid inputs + self.browser.find_element(By.ID, 'first-name').send_keys('Test') + self.browser.find_element(By.ID, 'last-name').send_keys('User') + self.browser.find_element( + By.ID, 'email').send_keys('test.user@slps.org') + Select(self.browser.find_element(By.ID, 'grade') + ).select_by_visible_text('9th/Freshman') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Hawk') + self.browser.find_element(By.ID, 'submit').click() + + # Wait until browser loads next step of form before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'activity1'))) + + activity1 = Select(self.browser.find_element(By.ID, 'activity1')) + activity2 = Select(self.browser.find_element(By.ID, 'activity2')) + + # Assert that full activity is now shown + self.assertRaises(NoSuchElementException, + activity1.select_by_visible_text, 'Hidden (30)') + # Asser that 60 minute activity is not shown in second slot + self.assertRaises(NoSuchElementException, + activity2.select_by_visible_text, 'Volleyball (60)') + + # Assert that valid activities are still shown in slot + activity1.select_by_visible_text('Volleyball (60)') + activity2.select_by_visible_text('Hidden (30)') + + def test_full_activity_shows_for_other_houses(self): + House.objects.create(name='Snowy') + UserEntry.objects.create(first_name='Test', last_name='User', email='user.exist@slps.org', grade=9, house=self.house, + activity1=self.hidden, activity2=self.hidden) + + self.browser.get(self.url) + + # Wait until browser loads page before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'header'))) + + # Fill in form with valid inputs and separate house + self.browser.find_element(By.ID, 'first-name').send_keys('Test') + self.browser.find_element(By.ID, 'last-name').send_keys('User') + self.browser.find_element( + By.ID, 'email').send_keys('test.user@slps.org') + Select(self.browser.find_element(By.ID, 'grade') + ).select_by_visible_text('9th/Freshman') + Select(self.browser.find_element(By.ID, 'house') + ).select_by_visible_text('Snowy') + self.browser.find_element(By.ID, 'submit').click() + + # Wait until browser loads next form step before continuing + WebDriverWait(self.browser, timeout=5).until( + visibility_of(self.browser.find_element(By.ID, 'activity1'))) + + # Verify that full activity is still showing for other house + activity1 = Select(self.browser.find_element(By.ID, 'activity1')) + activity2 = Select(self.browser.find_element(By.ID, 'activity2')) + activity1.select_by_visible_text('Hidden (30)') + activity2.select_by_visible_text('Hidden (30)')