def test_list_view_current_version(self): make_disclaimer_content(disclaimer_terms='Foo') make_disclaimer_content(disclaimer_terms='Bar') latest = make_disclaimer_content(disclaimer_terms='Foobar') assert DisclaimerContent.current() == latest resp = self.client.get(self.list_url) assert resp.context_data["current_version"] == latest.version
def test_disclaimer_health_questionnaire_required_fields(self): make_disclaimer_content( form=[ { 'type': 'text', 'required': False, 'label': 'Say something', 'name': 'text-1', 'subtype': 'text' }, { 'type': 'text', 'required': True, 'label': 'What is your favourite colour?', 'name': 'text-2', 'choices': ["red", "green", "blue"], 'subtype': 'text' } ], version=None # make sure it's the latest ) self.login(self.student_user) url = reverse('accounts:disclaimer_form', args=(self.student_user.id,)) # form data only has response for qn 0 (not required) resp = self.client.post(url, {**self.form_data}) assert resp.status_code == 200 form = resp.context_data["form"] assert form.errors == {"health_questionnaire_responses": ["Please fill in all required fields."]} form_data = {**self.form_data} del form_data["health_questionnaire_responses_0"] form_data["health_questionnaire_responses_1"] = "red" resp = self.client.post(url, {**form_data}) assert resp.status_code == 302
def test_disclaimer_health_questionnaire(self): # Make new disclaimer version with questionnaire - this should be the new current version make_disclaimer_content( form=[ { 'type': 'text', 'required': False, 'label': 'Say something', 'name': 'text-1', 'subtype': 'text' }, { 'type': 'text', 'required': True, 'label': 'What is your favourite colour?', 'name': 'text-2', 'choices': ["red", "green", "blue"], 'subtype': 'text' } ], version=None ) self.login(self.student_user) url = reverse('accounts:disclaimer_form', args=(self.student_user.id,)) resp = self.client.get(url) form = resp.context_data["form"] # disclaimer content questionnaire fields have been translated into form fields questionnaire_fields = form.fields['health_questionnaire_responses'].fields assert questionnaire_fields[0].label == "Say something" # text field initial is set to "-" assert questionnaire_fields[0].initial == "-" assert questionnaire_fields[1].label == "What is your favourite colour?"
def test_new_online_disclaimer_with_current_version_is_active(self): disclaimer_content = make_disclaimer_content( version=None ) # ensure version is incremented from any existing ones disclaimer = make_online_disclaimer(user=self.student_user, version=disclaimer_content.version) assert disclaimer.is_active make_disclaimer_content(version=None) assert disclaimer.is_active is False
def test_disclaimer_content_first_version(self): DisclaimerContent.objects.all().delete() assert DisclaimerContent.objects.exists() is False assert DisclaimerContent.current_version() == 0 content = make_disclaimer_content() assert content.version == 1.0 content1 = make_disclaimer_content() assert content1.version == 2.0
def test_add_disclaimer_content_no_content_change(self): make_disclaimer_content(disclaimer_terms='test', version=None) resp = self.client.post( reverse("studioadmin:add_disclaimer_content"), { **self.form_default, "disclaimer_terms": "test", "publish": "Publish" }) assert resp.context_data["form"].errors == { "__all__": [ 'No changes made from previous version; new version must update disclaimer content' ] }
def test_edit_published_version_with_existing_draft(self): published_disclaimer_content = make_disclaimer_content( is_draft=False, disclaimer_terms="Foo", version=None) draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(published_disclaimer_content.version, )) resp = self.client.get(url) # redirect to latest draft view assert resp.status_code == 302 assert resp.url == reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, ))
def test_disclaimer_required(self): """ test that page redirects if there is no user logged in """ url = reverse("booking:disclaimer_required", args=(self.student_user.id,)) resp = self.client.get(url) assert resp.status_code == 200 assert resp.context['has_expired_disclaimer'] is False assert resp.context['disclaimer_user'] == self.student_user self.make_disclaimer(self.student_user) make_disclaimer_content(version=None) resp = self.client.get(url) assert resp.status_code == 200 assert resp.context['has_expired_disclaimer'] is True
def test_cannot_update_terms_after_first_save(self): disclaimer_content = make_disclaimer_content( disclaimer_terms="foo", version=None # ensure version is incremented from any existing ones ) with self.assertRaises(ValueError): disclaimer_content.disclaimer_terms = 'foo1' disclaimer_content.save()
def test_edit_draft_version(self): DisclaimerContent.objects.all().delete() disclaimer_content = make_disclaimer_content(is_draft=True, disclaimer_terms="Foo", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(disclaimer_content.version, )) resp = self.client.get(url) # no previous version to reset to assert "Reset to latest published version" not in resp.rendered_content assert resp.context_data["disclaimer_content"] == disclaimer_content
def test_add_new_with_existing_draft(self): draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) resp = self.client.get(reverse("studioadmin:add_disclaimer_content")) # redirect to latest draft view assert resp.status_code == 302 assert resp.url == reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) resp = self.client.get(reverse("studioadmin:add_disclaimer_content"), follow=True) assert "Cannot add a new version while a draft already exists. Editing latest draft version" in resp.rendered_content
def test_edit_disclaimer_content_unknown_action(self): draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) with pytest.raises(ValidationError): self.client.post( url, { **self.form_default, "disclaimer_terms": "test", "foo": "Foo", "version": draft_disclaimer_content.version })
def test_edit_disclaimer_content_form_invalid(self): published_disclaimer_content = make_disclaimer_content( is_draft=False, disclaimer_terms="Foo", version=None) draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) resp = self.client.post( url, { **self.form_default, "disclaimer_terms": "Foo", "form": json.dumps(published_disclaimer_content.form), "version": draft_disclaimer_content.version, "save_draft": "Save as draft" }) assert resp.status_code == 200 assert resp.context_data["form_errors"] == { "__all__": [ "No changes made from previous version; new version must update disclaimer content" ] } draft_disclaimer_content.refresh_from_db()
def test_edit_published_version(self): disclaimer_content = make_disclaimer_content(is_draft=False, disclaimer_terms="Foo", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(disclaimer_content.version, )) resp = self.client.get(url) # No other draft versions, redirect to list view assert resp.status_code == 302 assert resp.url == reverse("studioadmin:disclaimer_contents") resp = self.client.get(url, follow=True) assert "Published disclaimer versions cannot be edited; make a new version if updates are required." in resp.rendered_content
def test_can_update_and_make_draft_published(self): content = make_disclaimer_content(is_draft=True, disclaimer_terms="first versin") first_issue_date = content.issue_date content.disclaimer_terms = "second version" content.is_draft = False content.save() assert first_issue_date < content.issue_date with self.assertRaises(ValueError): content.disclaimer_terms = "third version" content.save()
def test_reset_draft(self): published_disclaimer_content = make_disclaimer_content( is_draft=False, disclaimer_terms="Foo", version=None) draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) resp = self.client.get(url) assert "Reset to latest published version" in resp.rendered_content resp = self.client.post( url, { **self.form_default, "reset": "Reset to latest published version", "disclaimer_terms": draft_disclaimer_content.disclaimer_terms, "form": json.dumps(draft_disclaimer_content.form), "version": draft_disclaimer_content.version, }) draft_disclaimer_content.refresh_from_db() assert draft_disclaimer_content.disclaimer_terms == published_disclaimer_content.disclaimer_terms # redirects back to edit page again assert resp.status_code == 302 assert resp.url == reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, ))
def test_cannot_change_existing_published_disclaimer_version(self): content = make_disclaimer_content(disclaimer_terms="first version", version=4, is_draft=True) content.version = 3.8 content.save() assert content.version == 3.8 content.is_draft = False content.save() with pytest.raises(ValueError): content.version = 4 content.save()
def test_edit_disclaimer_content_save_as_draft(self): draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) self.client.post( url, { **self.form_default, "disclaimer_terms": "test", "save_draft": "Save as draft", "version": draft_disclaimer_content.version }) draft_disclaimer_content.refresh_from_db() assert draft_disclaimer_content.is_draft is True assert DisclaimerContent.current_version() == 0
def setUp(self): self.create_users() self.content = make_disclaimer_content( form=[{"label": "test", "type": "text"}] ) self.form_data = { "date_of_birth": '01-Jan-1990', 'address': '1 test st', 'postcode': 'TEST1', 'home_phone': '123445', 'mobile_phone': '124566', 'emergency_contact_name': 'test1', 'emergency_contact_relationship': 'mother', 'emergency_contact_phone': '4547', 'terms_accepted': True, 'health_questionnaire_responses_0': ["foo"], 'password': '******' }
def test_can_edit_draft_disclaimer_content(self): content = make_disclaimer_content(is_draft=True) first_issue_date = content.issue_date content.disclaimer_terms = "second version" content.save() assert first_issue_date < content.issue_date assert content.disclaimer_terms == "second version" content.is_draft = False content.save() with pytest.raises(ValueError): content.disclaimer_terms = "third version" content.save()
def test_publish_draft(self): draft_disclaimer_content = make_disclaimer_content( is_draft=True, disclaimer_terms="Bar", version=None) url = reverse("studioadmin:edit_disclaimer_content", args=(draft_disclaimer_content.version, )) self.client.post( url, { **self.form_default, "publish": "Publish", "disclaimer_terms": draft_disclaimer_content.disclaimer_terms, "form": json.dumps(draft_disclaimer_content.form), "version": draft_disclaimer_content.version, }) draft_disclaimer_content.refresh_from_db() assert draft_disclaimer_content.is_draft is False assert DisclaimerContent.current() == draft_disclaimer_content
def test_event_list_booked_events_no_disclaimer(self): make_disclaimer_content() resp = self.client.get(self.adult_url) assert "Complete a disclaimer" in resp.rendered_content
def test_status(self): disclaimer_content = make_disclaimer_content() assert disclaimer_content.status == "published" disclaimer_content_draft = make_disclaimer_content(is_draft=True) assert disclaimer_content_draft.status == "draft"
def test_button_display_course_event(self): # With a course event, check that the button displays as expected for: # - no disclaimer # - not booked (with and without available course blocks) # - booked and open # - cancelled (with and without available course blocks) # - no-show (with and without available course blocks) # - course full and booked # - course full and cancelled/no-show # - event cancelled # - on waiting list def _element_from_response_by_id(element_id): response = self.client.get(self.adult_url) soup = BeautifulSoup(response.rendered_content, features="html.parser") return soup.find(id=element_id) Event.objects.all().delete() self.course.number_of_events = 1 self.course.save() event = baker.make_recipe("booking.future_event", event_type=self.aerial_event_type, course=self.course) make_disclaimer_content(version=None) self.login(self.student_user) resp = self.client.get(self.adult_url) assert len(sum(list(resp.context_data['events_by_date'].values()), [])) == 1 assert "Complete a disclaimer" in resp.rendered_content # not booked, has disclaimer self.make_disclaimer(self.student_user) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Payment plan required" in book_button.text # cancelled, no block booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") assert "Payment plan required" in book_button.text booking.delete() # not booked with valid block block = baker.make_recipe( "booking.course_block", block_config__event_type=self.aerial_event_type, block_config__size=1, user=self.student_user, paid=True ) book_button = _element_from_response_by_id(f"book_{event.id}") for fragment in ["NOT BOOKED", "Payment plan available", "Course details"]: assert fragment in book_button.text # cancelled, with block booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") for fragment in ["NOT BOOKED", "Payment plan available", "Course details"]: assert fragment in book_button.text # no-show, with block booking.status = "OPEN" booking.no_show = True booking.save() book_button = _element_from_response_by_id(f"book_{event.id}") assert "Rebook" in book_button.text booking.delete() # event full baker.make(Booking, event=event, _quantity=event.max_participants) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert "Join waiting list" in waiting_list_button.text # event full, on waiting list baker.make(WaitingListUser, event=event, user=self.student_user) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert "Leave waiting list" in waiting_list_button.text # event full, has booking Booking.objects.all().delete() baker.make(Booking, user=self.student_user, event=event, block=block) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Cancel" in book_button.text
def test_button_display_dropin_event(self): def _element_from_response_by_id(element_id): response = self.client.get(self.adult_url) soup = BeautifulSoup(response.rendered_content, features="html.parser") return soup.find(id=element_id) Event.objects.all().delete() event = baker.make_recipe("booking.future_event", event_type=self.aerial_event_type) make_disclaimer_content(version=None) self.login(self.student_user) resp = self.client.get(self.adult_url) assert len(sum(list(resp.context_data['events_by_date'].values()), [])) == 1 assert "Complete a disclaimer" in resp.rendered_content # not booked, has disclaimer self.make_disclaimer(self.student_user) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Payment plan required" in book_button.text # cancelled, no block booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") assert "Payment plan required" in book_button.text booking.delete() # not booked with valid block block = baker.make_recipe( "booking.dropin_block", block_config__event_type=self.aerial_event_type, block_config__size=10, user=self.student_user, paid=True ) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Book Drop-in" in book_button.text # cancelled, with block available booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") assert "Rebook Drop-in" in book_button.text # no-show, with block booking.status = "OPEN" booking.block = block booking.no_show = True booking.save() book_button = _element_from_response_by_id(f"book_{event.id}") assert "Rebook Drop-in" in book_button.text booking.delete() # event full baker.make(Booking, event=event, _quantity=event.max_participants) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert "Join waiting list" in waiting_list_button.text # event full, on waiting list baker.make(WaitingListUser, event=event, user=self.student_user) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert "Leave waiting list" in waiting_list_button.text # event full, has booking event.max_participants += 1 event.save() baker.make(Booking, user=self.student_user, event=event, block=block) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Cancel" in book_button.text
def test_button_display_course_event(self): # With a course event, check that the button displays as expected for: # - no disclaimer # - not booked (with and without available course blocks) # - booked and open # - cancelled (with and without available course blocks) # - no-show (with and without available course blocks) # - course full and booked # - course full and cancelled/no-show # - event cancelled # - on waiting list def _element_from_response_by_id(element_id): response = self.client.get(self.url) soup = BeautifulSoup(response.rendered_content, features="html.parser") return soup.find(id=element_id) Event.objects.all().delete() self.course.number_of_events = 1 self.course.save() event = baker.make_recipe("booking.future_event", event_type=self.aerial_event_type, course=self.course) make_disclaimer_content(version=None) self.login(self.student_user) resp = self.client.get(self.url) assert len(sum(list(resp.context_data['events_by_date'].values()), [])) == 1 assert "Complete a disclaimer" in resp.rendered_content # not booked, has disclaimer. Booking button for individual events not shown self.make_disclaimer(self.student_user) book_button = _element_from_response_by_id(f"book_{event.id}") assert book_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "You need a payment plan to book this course" in course_book_button.text # cancelled, no block. Booking button for individual events not shown booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") assert book_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "You need a payment plan to book this course" in course_book_button.text booking.delete() # not booked with valid block block = baker.make_recipe( "booking.course_block", block_config__event_type=self.aerial_event_type, block_config__size=1, user=self.student_user, paid=True ) book_button = _element_from_response_by_id(f"book_{event.id}") assert book_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "Book Course" in course_book_button.text # cancelled, with block booking = baker.make(Booking, user=self.student_user, event=event, status="CANCELLED") book_button = _element_from_response_by_id(f"book_{event.id}") assert book_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "Book Course" in course_book_button.text # no-show, with block booking.status = "OPEN" booking.no_show = True booking.save() book_button = _element_from_response_by_id(f"book_{event.id}") assert "Rebook" in book_button.text course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "Student User is attending this course" in course_book_button.text booking.delete() # event full baker.make(Booking, event=event, _quantity=event.max_participants) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert waiting_list_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "This course is now full" in course_book_button.text # event full, on waiting list baker.make(WaitingListUser, event=event, user=self.student_user) waiting_list_button = _element_from_response_by_id(f"waiting_list_button_{event.id}") assert waiting_list_button is None course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "This course is now full" in course_book_button.text # event full, has booking Booking.objects.all().delete() baker.make(Booking, user=self.student_user, event=event, block=block) book_button = _element_from_response_by_id(f"book_{event.id}") assert "Cancel" in book_button.text course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "Student User is attending this course" in course_book_button.text Booking.objects.all().delete() self.course.number_of_events = 2 self.course.save() baker.make_recipe("booking.past_event", course=self.course, event_type=self.aerial_event_type) assert self.course.has_started assert self.course.allow_partial_booking is False # Course started, partial booking not allowed course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert course_book_button is None resp = self.client.get(self.url) assert "NOTE: This course has started" in resp.rendered_content self.course.allow_partial_booking = True self.course.save() # Course started, partial booking allowed, has partial block course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "Book Course" in course_book_button.text # Course started, partial booking allowed, no block block.delete() course_book_button = _element_from_response_by_id(f"book_course_{self.course.id}") assert "You need a payment plan to book this course" in course_book_button.text assert "1 class course block" in course_book_button.text
def setUp(self): self.create_users() self.content = make_disclaimer_content(version=5.0)
def test_str(self): disclaimer_content = make_disclaimer_content() assert str( disclaimer_content ) == f'Disclaimer Content - Version {disclaimer_content.version} (published)'
def test_new_version_must_have_new_terms(self): make_disclaimer_content(disclaimer_terms="foo", version=None) with pytest.raises(ValidationError) as e: make_disclaimer_content(disclaimer_terms="foo", version=None) assert str(e) == "No changes made to content; not saved"
def test_detail_view(self): policy = make_disclaimer_content(disclaimer_terms='Foo', version=4.1) resp = self.client.get( reverse("studioadmin:disclaimer_content", args=(policy.version, ))) assert resp.status_code == 200