forked from expo/troggle
630 lines
24 KiB
Python
630 lines
24 KiB
Python
|
"""
|
||
|
IGNORED tests
|
||
|
- all test files with hyphens in the filename are ignored
|
||
|
- filnames with _ are OK
|
||
|
|
||
|
$ python manage.py test cuy.photologue --parallel
|
||
|
only runs the photologue tests. Working.(well, it was working..)
|
||
|
|
||
|
$ python manage.py test cuy.mailman --parallel
|
||
|
|
||
|
$ python manage.py test paypal.standard --parallel
|
||
|
needs work: a very large test suite
|
||
|
|
||
|
$ python manage.py test tagging --parallel
|
||
|
a huge suite - needs a lot of work to with Django 1.11 & python3
|
||
|
|
||
|
$ python manage.py test cuy.club --parallel
|
||
|
Runs the tests in this file only
|
||
|
"""
|
||
|
|
||
|
import unittest
|
||
|
import re
|
||
|
from django.test import TestCase, SimpleTestCase, TransactionTestCase, Client
|
||
|
|
||
|
class ImportTest(TestCase):
|
||
|
def test_import_imports(self):
|
||
|
# Need to go through all modules and copy all imports here
|
||
|
from django.conf import settings
|
||
|
from django.contrib.auth.decorators import login_required
|
||
|
from django.contrib.auth.models import User
|
||
|
from django.core import management
|
||
|
from django.db import connection, connections
|
||
|
from django.http import HttpResponse
|
||
|
from django.http import HttpResponse, HttpResponseRedirect
|
||
|
from django.shortcuts import get_object_or_404, render
|
||
|
from django.template.defaultfilters import slugify
|
||
|
from django.utils.timezone import get_current_timezone, make_aware
|
||
|
from io import StringIO
|
||
|
from cuy.club.models import Member, Article, Event, WebpageCategory, Webpage
|
||
|
from cuy.website.views.generic import PUBLIC_LOGIN
|
||
|
from cuy.club.models import Member
|
||
|
from django.db.utils import IntegrityError
|
||
|
|
||
|
|
||
|
class SimpleTest(SimpleTestCase):
|
||
|
def test_arith_mult(self):
|
||
|
"""
|
||
|
Tests that 10 x 10 always equals 100.
|
||
|
"""
|
||
|
self.assertEqual(10*10, 100)
|
||
|
|
||
|
|
||
|
class DataTests(TestCase ):
|
||
|
'''These check that the NULL and NON-UNIQUE constraints are working in the database '''
|
||
|
@classmethod
|
||
|
def setUpTestData(cls):
|
||
|
pass
|
||
|
|
||
|
def setUp(self):
|
||
|
from cuy.club.models import Member
|
||
|
from django.contrib.auth.models import User
|
||
|
m = Member()
|
||
|
m.pk=8000
|
||
|
m.user_id = 9000 # not NULL constraint
|
||
|
m.save()
|
||
|
self.member = m
|
||
|
|
||
|
u = User()
|
||
|
u.pk = 9000
|
||
|
u.user_id = 8000
|
||
|
u.username, u.password ='stinker', 'secretword'
|
||
|
u.email='philip.sargent+SP@gmail.com'
|
||
|
u.first_name, u.last_name ='Stinker', 'Pinker'
|
||
|
u.save()
|
||
|
self.user = u
|
||
|
|
||
|
def tearDown(self):
|
||
|
#self.member.delete() # must delete member before user
|
||
|
#self.user.delete() # horrible crash, why?
|
||
|
pass
|
||
|
|
||
|
def test_member_not_null_field(self):
|
||
|
from cuy.club.models import Member
|
||
|
from django.db.utils import IntegrityError
|
||
|
n = Member()
|
||
|
try:
|
||
|
n.save()
|
||
|
except IntegrityError as ex:
|
||
|
t = re.search(r'NOT NULL constraint failed: club_member.user_id', str(ex))
|
||
|
self.assertIsNotNone(t, "Exception is not the expected 'NOT NULL constraint failed'")
|
||
|
n.user_id = 1000
|
||
|
try:
|
||
|
n.save
|
||
|
except:
|
||
|
return self.assertIsNotNone(None, "Failed to save valid Member to database")
|
||
|
|
||
|
def test_member_not_unique_field(self):
|
||
|
from cuy.club.models import Member
|
||
|
from django.db.utils import IntegrityError
|
||
|
m1 = Member()
|
||
|
m2 = Member()
|
||
|
m1.user_id = 1000
|
||
|
m2.user_id = m1.user_id
|
||
|
m1.save()
|
||
|
try:
|
||
|
m2.save()
|
||
|
except IntegrityError as ex:
|
||
|
t = re.search(r'UNIQUE constraint failed: club_member.user_id', str(ex))
|
||
|
return self.assertIsNotNone(t, "IntegrityError as expected but message is not the expected 'UNIQUE constraint failed'" )
|
||
|
self.assertIsNotNone(None, "Failed to enforce 'UNIQUE constraint' on saving two Member objects with same user_id")
|
||
|
|
||
|
def test_article_invalid_date(self):
|
||
|
from cuy.club.models import Member, Article
|
||
|
from django.db.utils import IntegrityError
|
||
|
from django.core.exceptions import ValidationError
|
||
|
|
||
|
a = Article()
|
||
|
m = self.member
|
||
|
a.author_id = m.user_id
|
||
|
|
||
|
a.publish="not a valid datetime"
|
||
|
try:
|
||
|
a.save()
|
||
|
except ValidationError as ex:
|
||
|
t = re.search(r'value has an invalid format. It must be in YYYY-MM-DD HH:MM', str(ex))
|
||
|
self.assertIsNotNone(t, "Exception is not the expected 'invalid format'")
|
||
|
|
||
|
def test_article_and_author_not_null(self):
|
||
|
from cuy.club.models import Member, Article
|
||
|
from django.db.utils import IntegrityError
|
||
|
from django.core.exceptions import ValidationError
|
||
|
|
||
|
a2 = Article()
|
||
|
a2.publish ="2021-02-17 17:25"
|
||
|
a2.author_id = None
|
||
|
|
||
|
try:
|
||
|
a2.save()
|
||
|
except IntegrityError as ex:
|
||
|
t = re.search(r'NOT NULL constraint failed: club_article.author_id', str(ex))
|
||
|
self.assertIsNotNone(t, "Exception is not the expected 'NOT NULL constraint failed'")
|
||
|
except:
|
||
|
self.assertIsNotNone(None, "Exception is not the expected 'NOT NULL constraint failed' IntegrityError")
|
||
|
|
||
|
def test_article_and_author_ok(self):
|
||
|
from cuy.club.models import Member, Article
|
||
|
from django.db.utils import IntegrityError
|
||
|
from django.core.exceptions import ValidationError
|
||
|
m = self.member
|
||
|
|
||
|
a3 = Article()
|
||
|
a3.pk = 5000
|
||
|
a3.publish ="2021-02-17 17:25"
|
||
|
|
||
|
a3.author_id = m.pk
|
||
|
try:
|
||
|
a3.save()
|
||
|
except:
|
||
|
return self.assertIsNotNone(None, "Failed to save valid Article to database")
|
||
|
|
||
|
|
||
|
def test_member_and_user(self):
|
||
|
u = self.user
|
||
|
m = self.member
|
||
|
|
||
|
m.user = u
|
||
|
self.assertEqual(m.user.last_name, 'Pinker')
|
||
|
m.save()
|
||
|
u.save()
|
||
|
|
||
|
class FixturePageTests(TestCase):
|
||
|
fixtures = ['cuyc_basic_data.json', 'test_data.json', 'auth_user_gussie']
|
||
|
|
||
|
def setUp(self):
|
||
|
from django.contrib.auth.models import User
|
||
|
self.user = User.objects.get(username='gussie')
|
||
|
self.member = self.user.profile
|
||
|
|
||
|
def tearDown(self):
|
||
|
pass
|
||
|
|
||
|
def test_fix_event_loaded(self):
|
||
|
from cuy.club.models import Event
|
||
|
e = Event.objects.get(slug='spring-in-the-med')
|
||
|
self.assertEqual(str(e.shore_contact.first_name()), 'Stiffy')
|
||
|
self.assertEqual(str(e.organiser.last_name()), 'Fittleworth')
|
||
|
|
||
|
def test_fix_page_all_trips(self):
|
||
|
response = self.client.get('/programme/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Spring in the Arctic', content)
|
||
|
self.assertIsNotNone(t, "Failed to see Event loaded from fixture")
|
||
|
t = re.search(r'High Summer in the Irish Sea', content)
|
||
|
self.assertIsNotNone(t, "Failed to see Event loaded from fixture")
|
||
|
|
||
|
def test_fix_page_event(self):
|
||
|
response = self.client.get('/programme/events/spring-in-the-arctic/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Spring in the Arctic', content)
|
||
|
self.assertIsNotNone(t, "Failed to see Event loaded from fixture")
|
||
|
|
||
|
def test_fix_admin_login_fail(self):
|
||
|
c = self.client
|
||
|
from django.contrib.auth.models import User
|
||
|
from cuy.club.models import Member
|
||
|
m = Member.objects.get(pk=9002)
|
||
|
u = User.objects.get(username='bingo')
|
||
|
|
||
|
self.assertTrue(u.is_active, 'User \'' + u.username + '\' is INACTIVE')
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails to work if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
|
||
|
response = c.get('/admin/')
|
||
|
content = response.content.decode()
|
||
|
with open('admin-op.html', 'w') as f:
|
||
|
f.write(content)
|
||
|
t = re.search(r'Site administration', content)
|
||
|
self.assertIsNone(t, 'Logged in as \'' + u.username + '\' (not staff) but still managed to get the Admin page' )
|
||
|
|
||
|
|
||
|
class ComplexLoginTests(TestCase):
|
||
|
'''These test the login and capabilities of logged-in users'''
|
||
|
def setUp(self):
|
||
|
'''setUp runs once for each test in this class'''
|
||
|
from cuy.club.models import Member, MEMBER_TYPES, AFFILIATION
|
||
|
from django.contrib.auth.models import User
|
||
|
m = Member()
|
||
|
m.pk=8000
|
||
|
m.user_id = 9000 # not NULL constraint
|
||
|
m.email = "philip.sargent+HG@gmail.com"
|
||
|
m.member_type = MEMBER_TYPES[1]
|
||
|
m.affiliation = AFFILIATION[3]
|
||
|
m.committee_email_prefix = 'honoria'
|
||
|
|
||
|
u = User()
|
||
|
u.pk = 9000
|
||
|
u.user_id = 8000
|
||
|
u.username, u.password ='honoria', 'secretword'
|
||
|
u.email='philip.sargent+HG@gmail.com'
|
||
|
u.first_name, u.last_name ='Honoria', 'Glossop'
|
||
|
u.is_staff = True
|
||
|
u.is_superuser = True
|
||
|
|
||
|
u.set_password(u.password) # This creates a new salt and thus a new key for EACH test
|
||
|
u.save() # vital that we save all this before attempting login
|
||
|
#print ('\n',u.password)
|
||
|
m.save()
|
||
|
self.user = u
|
||
|
self.member = m
|
||
|
|
||
|
from cuy.club.models import ClubRole, Elected
|
||
|
cr = ClubRole()
|
||
|
cr.id = 7000
|
||
|
cr.title = 'Skipper'
|
||
|
cr.short_description = 'Club skipper who can lead trips'
|
||
|
cr.committee_position = True
|
||
|
cr.rank = 8
|
||
|
cr.save()
|
||
|
self.clubrole = cr
|
||
|
|
||
|
e = Elected()
|
||
|
e.member = m
|
||
|
e.club_role = cr
|
||
|
e.save()
|
||
|
self.elected = e
|
||
|
|
||
|
def tearDown(self):
|
||
|
self.client.logout() # not needed as each test creates a new self.client
|
||
|
#self.member.delete()
|
||
|
##self.user.delete() # id attribute set to None !
|
||
|
pass
|
||
|
|
||
|
def test_login_redirect_for_non_logged_on_user(self):
|
||
|
c = self.client
|
||
|
# Need to login first. Tests that we are redirected to login page if not logged in
|
||
|
response = c.get('/committee/appointments/')
|
||
|
self.assertRedirects(response, "/login/?next=/committee/appointments/")
|
||
|
|
||
|
def test_ordinary_login(self):
|
||
|
c = self.client
|
||
|
u = self.user
|
||
|
|
||
|
self.assertTrue(u.is_active, 'User \'' + u.username + '\' is INACTIVE')
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails to work if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
response = c.get('/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Hello Honoria', content)
|
||
|
self.assertIsNotNone(t, 'Logged in as \'' + u.username + '\' but failed to get personal greeting' )
|
||
|
|
||
|
def test_authentication_login(self):
|
||
|
c = self.client
|
||
|
u = self.user
|
||
|
|
||
|
self.assertTrue(u.is_active, 'User \'' + u.username + '\' is INACTIVE')
|
||
|
|
||
|
# This is weird. I thought that the user had to login before she was in the authenticated state
|
||
|
self.assertTrue(u.is_authenticated, 'User \'' + u.username + '\' is NOT AUTHENTICATED before login')
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails to work if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
|
||
|
self.assertTrue(u.is_authenticated, 'User \'' + u.username + '\' is NOT AUTHENTICATED after login')
|
||
|
|
||
|
c.logout()
|
||
|
self.assertFalse(u.is_authenticated, 'User \'' + u.username + '\' is STILL AUTHENTICATED after logout')
|
||
|
|
||
|
def test_admin_login(self):
|
||
|
c = self.client
|
||
|
u = self.user
|
||
|
m = self.member
|
||
|
|
||
|
m.user = u
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails to work if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
|
||
|
response = c.get('/admin/')
|
||
|
content = response.content.decode()
|
||
|
# with open('admin-op.html', 'w') as f:
|
||
|
# f.write(content)
|
||
|
t = re.search(r'Site administration', content)
|
||
|
self.assertIsNotNone(t, 'Logged in as \'' + u.username + '\' but failed to get the Admin page' )
|
||
|
|
||
|
def test_user_account_login(self):
|
||
|
# User must be associated with a Member for whom is_committee() is True
|
||
|
c = self.client
|
||
|
u = self.user
|
||
|
m = self.member
|
||
|
|
||
|
m.user = u
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
|
||
|
response = c.get('/accounts/profile/')
|
||
|
content = response.content.decode()
|
||
|
# with open('account-profile-op.html', 'w') as f:
|
||
|
# f.write(content)
|
||
|
t = re.search(r'CUYC Member Profile - Cambridge University Yacht Club', content)
|
||
|
self.assertIsNotNone(t, 'Logged in as \'' + u.username + '\' but failed to get /accounts/profile/ content')
|
||
|
|
||
|
def test_committee_login(self):
|
||
|
from django.contrib.auth.models import User
|
||
|
# User must be associated with a Member for whom is_committee() is True
|
||
|
c = self.client # inherited from TestCase
|
||
|
u = self.user
|
||
|
m = self.member
|
||
|
cr = self.clubrole
|
||
|
e = self.elected
|
||
|
|
||
|
m.user = u
|
||
|
|
||
|
logged_in = c.login(username=u.username, password='secretword') # fails if password=u.password !
|
||
|
self.assertTrue(logged_in, 'FAILED to login as \'' + u.username + '\'')
|
||
|
response = c.get('/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Hello Honoria', content)
|
||
|
self.assertIsNotNone(t, 'Logged in as \'' + u.username + '\' but failed to get personal greeting' )
|
||
|
|
||
|
response = c.get('/committee/appointments/')
|
||
|
content = response.content.decode()
|
||
|
# with open('cmttee-op.html', 'w') as f:
|
||
|
# f.write(content)
|
||
|
t = re.search(r'A word of warning...', content)
|
||
|
self.assertIsNotNone(t, 'Logged in as \'' + u.username + '\' but failed to get /committee/ content')
|
||
|
|
||
|
def test_user_force(self):
|
||
|
from django.conf import settings
|
||
|
c = self.client
|
||
|
u = self.user
|
||
|
m = self.member
|
||
|
|
||
|
m.user = u
|
||
|
|
||
|
try:
|
||
|
c.force_login(u)
|
||
|
except:
|
||
|
self.assertIsNotNone(None, 'Unexpected exception trying to force_login as \'' + u.username + '\' but failed (Bad Django documentation?)')
|
||
|
|
||
|
response = c.get('/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Hello Honoria', content)
|
||
|
self.assertIsNotNone(t, 'Forced logged in as \'' + u.username + '\' but failed to get personal greeting' )
|
||
|
|
||
|
response = c.get('/accounts/profile/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'From here you can update your', content)
|
||
|
self.assertIsNotNone(t, 'Forced logged in as \'' + u.username + '\' but failed to get /accounts/profile/ content')
|
||
|
|
||
|
|
||
|
class DynamicPageTests(TestCase):
|
||
|
def setUp(self):
|
||
|
pass
|
||
|
|
||
|
def tearDown(self):
|
||
|
pass
|
||
|
|
||
|
def test_empty_yachts(self):
|
||
|
# no page there initially
|
||
|
response = self.client.get('/yachts/')
|
||
|
content = response.content.decode()
|
||
|
self.assertEqual(response.status_code, 404)
|
||
|
|
||
|
def test_full_yachts(self):
|
||
|
'''Creating a WebpageCategory and an index webpage creates a valid url
|
||
|
'''
|
||
|
from cuy.club.models import WebpageCategory, Webpage
|
||
|
wc = WebpageCategory()
|
||
|
wc.pk = 8000
|
||
|
wc.id = 8000
|
||
|
wc.name, wc.slug ='Yachts', 'yachts'
|
||
|
wc.save()
|
||
|
self.webcategory = wc
|
||
|
|
||
|
p = Webpage()
|
||
|
p.pk = 9000
|
||
|
p.id = 9000
|
||
|
p.category_id = wc.id
|
||
|
p.description = "Current Yacht"
|
||
|
p.edited = 1
|
||
|
p.event_id = None
|
||
|
p.index = 1
|
||
|
p.markup = "<h1>Skylark</h1>"
|
||
|
p.ordering = 10
|
||
|
p.slug = "yacht"
|
||
|
p.title = "Skylark Yacht"
|
||
|
p.save()
|
||
|
self.webpage = p
|
||
|
|
||
|
response = self.client.get('/yachts/')
|
||
|
content = response.content.decode()
|
||
|
self.assertEqual(response.status_code, 200)
|
||
|
|
||
|
class PageTests(TestCase):
|
||
|
def setUp(self):
|
||
|
# Every test needs a client.
|
||
|
# new in Django 1.5 no need to create self.client first
|
||
|
# https://docs.djangoproject.com/en/dev/topics/testing/tools/#django.test.LiveServerTestCase
|
||
|
#self.client = Client()
|
||
|
pass
|
||
|
|
||
|
def tearDown(self):
|
||
|
pass
|
||
|
|
||
|
def test_basic_admin(self):
|
||
|
response = self.client.get('/admin/login/')
|
||
|
self.assertEqual(response.status_code, 200)
|
||
|
|
||
|
def test_basic_admindoc(self):
|
||
|
# Need to login first. Tests that we are redirected
|
||
|
response = self.client.get('/admin/doc/models/')
|
||
|
self.assertRedirects(response, "/admin/login/?next=/admin/doc/models/")
|
||
|
|
||
|
def test_basic_programme(self):
|
||
|
response = self.client.get('/programme/')
|
||
|
self.assertEqual(response.status_code, 200)
|
||
|
|
||
|
def test_basic_login (self):
|
||
|
# Need to login first
|
||
|
response = self.client.post('/login/', {'username': 'gussie', 'password': 'secretword'})
|
||
|
if response.status_code == 302:
|
||
|
print(response['location'])
|
||
|
self.assertEqual(response.status_code, 200) # fails because user does not exist
|
||
|
|
||
|
def test_basic_committee(self):
|
||
|
# Need to login first. Tests that we are redirected to login page
|
||
|
response = self.client.get('/committee/')
|
||
|
self.assertRedirects(response, "/login/?next=/committee/")
|
||
|
|
||
|
# --- Check non-logged-in users cannot see these
|
||
|
def test_basic_gallery(self):
|
||
|
response = self.client.get('/gallery/')
|
||
|
self.assertEqual(response.status_code, 200)
|
||
|
|
||
|
def test_basic_sitemap(self):
|
||
|
response = self.client.get('/site-map/')
|
||
|
self.assertEqual(response.status_code, 200)
|
||
|
|
||
|
|
||
|
|
||
|
# --- public club pages created by content in templates/*.html
|
||
|
def test_basic_club(self):
|
||
|
response = self.client.get('/club/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'offers opportunities for members of the university to sail yachts', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_basic_programme(self):
|
||
|
response = self.client.get('/programme/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'If you would like to go on any of these events', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_basic_programme_onshore(self):
|
||
|
response = self.client.get('/programme/on_shore/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'All Upcoming Shore Based Events', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_equal_opps(self):
|
||
|
response = self.client.get('/club/equal-opps/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'commitment to a policy of equal opportunities', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_safety(self):
|
||
|
response = self.client.get('/club/safety/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'endeavour to maintain the highest levels of safety', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_safety_risk(self):
|
||
|
response = self.client.get('/club/safety/risk/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'rules for the use of safety lines to be described and monitored by the skipper.', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_safetypolicy(self):
|
||
|
response = self.client.get('/club/safetypolicy/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'should be capable of swimming at least fifty meters in clothing and keeping afloat for at least five minutes', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_safety_rules(self):
|
||
|
response = self.client.get('/club/safety/rules/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Safety Officer is responsible for the maintenance of safety records', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_regulations(self):
|
||
|
response = self.client.get('/club/regulations/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Sanger Institute, the Babraham Institute, Wellcome and MRC Research Laboratories', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_constitution(self):
|
||
|
response = self.client.get('/club/constitution/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'to provide a wide variety of safe and affordable yacht sailing', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_clubcommittee(self):
|
||
|
response = self.client.get('/club/committee/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'CUYC elects new officers as needed, usually at the beginning of each term', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_damages(self):
|
||
|
response = self.client.get('/club/damages/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'all crew participants may be required to contribute to the payment of damages', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_training(self):
|
||
|
response = self.client.get('/training/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'members of the club are always happy to pass on informal training tips', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_racing(self):
|
||
|
response = self.client.get('/racing/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'CUYC Racing Squad', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_blog(self):
|
||
|
response = self.client.get('/blog/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Latest Posts', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_gallery(self):
|
||
|
response = self.client.get('/gallery/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Photo Galleries', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_about_photos(self):
|
||
|
response = self.client.get('/about_photos/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'have been supplied by members of CUYC', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_loginhelp(self):
|
||
|
response = self.client.get('/login/help/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Existing CUYC Member, without an account?', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_loginregister(self):
|
||
|
response = self.client.get('/login/register/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'If you are, or have ever been, a CUYC or CUCrC member', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
# --- These pages are not connected to top level public menus but are in fact public
|
||
|
def test_page_club_tripinformation(self):
|
||
|
response = self.client.get('/club/trip-information/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'organisers have a choice to add a sum to the trip fee quoted on the website to cover expenses', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_club_trippayment(self):
|
||
|
response = self.client.get('/club/trip-information/payment/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'All payments to the club should be sent via Paypal', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_club_trip_typical_day(self):
|
||
|
response = self.client.get('/club/trip-information/typical-day/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Skipper and first mate crawl out of their sleeping bags early', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_club_trip_faq(self):
|
||
|
response = self.client.get('/club/trip-information/faq/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'Different people are seasick in different ways', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|
||
|
def test_page_club_trip_kit(self):
|
||
|
response = self.client.get('/club/trip-information/kit/')
|
||
|
content = response.content.decode()
|
||
|
t = re.search(r'appropriate quantity of base layer clothes to match the duration', content)
|
||
|
self.assertIsNotNone(t)
|
||
|
|