""" 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 = "

Skylark

" 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)