from datetime import timedelta from random import randint import time import re from selenium.common.exceptions import TimeoutException from factory.faker import Faker from django.utils import timezone from django.test import TestCase from django.shortcuts import reverse from django.utils.text import slugify from unidecode import unidecode from selenium.webdriver.common.by import By from django.utils.html import strip_tags from project.tests.factories import create_admin, create_batch_unique, User, UserFactory, Course, CourseFactory, login_admin from project.tests import SeleniumTestCase from apps.content.tests.mixins import TestContentMixin class CoursesTestCase(TestCase): @classmethod def setUpTestData(cls): create_admin() create_batch_unique(CourseFactory, status=Course.STATUS_CHOICES[:3], price=[0, 1000], age=Course.AGE_CHOICES[:2], deferred_start_at=[None, timezone.now() + timedelta(days=randint(5, 15))]) def test_courses_url_accessible(self): print('test_courses_url_accessible') print('get ', reverse('courses')) resp = self.client.get(reverse('courses')) self.assertEqual(resp.status_code, 200) def test_course_url_accessible(self): print('test_course_url_accessible') for course in Course.objects.filter(status=Course.PUBLISHED): print('get ', course.url) resp = self.client.get(course.url) self.assertEqual(resp.status_code, 200) @login_admin def test_course_edit_url_accessible(self): print('test_course_edit_url_accessible') for course in Course.objects.all(): print('get ', reverse('course_edit', args=[course.id])) resp = self.client.get(reverse('course_edit', args=[course.id])) self.assertEqual(resp.status_code, 200) class CourseEditTestCase(TestContentMixin, SeleniumTestCase): model = Course object_id = None object_data = {} @classmethod def setUpClass(cls): super().setUpClass() create_admin() UserFactory.create_batch(5, role=User.AUTHOR_ROLE) def check_saving(self, url=None, response_code=200): print('Check saving') time.sleep(1) request = self.wait_for_request(url or f'/api/v1/courses/{self.object_id}/') self.assertEqual(request[2].get('status'), response_code) self.assertNotEqual(request[2].get('response'), None) obj = self.model.objects.get(id=self.object_id) for key, value in self.object_data.items(): if key not in ['content', 'lessons']: self.assertEqual(getattr(obj, key), value) self.check_content_saving(obj) self.check_lessons_saving(obj) def check_lessons_saving(self, obj): print('Check lessons saving', ) lessons = self.object_data.get('lessons', []) self.assertEqual(obj.lessons.all().count(), len(lessons)) for i, lesson in enumerate(obj.lessons.all().order_by('title',)): self.assertEqual(strip_tags(lesson.short_description), lessons[i]['short_description']) self.assertEqual(lesson.title, lessons[i]['title']) print('OK') def test_course_edit(self): print('test_course_edit') user = User.objects.filter(role=User.AUTHOR_ROLE).first() self.login(user) url = self.get_url(reverse('course_create')) print('url is', url) self.driver.get(url) print('page opened', self.driver.current_url) self.add_requests_log() course_redactor = self.wait_elem_name('course-redactor') # visible always elements title_el = self.wait_elem_name('course-title') slug_el = self.wait_elem_name('course-slug') category_el = self.wait_elem_name('course-category') is_paid_no_el = self.wait_elem_name('course-is-paid-no') is_paid_yes_el = self.wait_elem_name('course-is-paid-yes') is_paid_input_el = self.wait_elem_css('[name=course-is-paid-input]:checked') age_el = self.wait_elem_name('course-age') # Only for ADMIN # is_featured_el = self.wait_elem_name('course-is-featured') is_deferred_no_el = self.wait_elem_name('course-is-deferred-no') is_deferred_yes_el = self.wait_elem_name('course-is-deferred-yes') is_deferred_input_el = self.wait_elem_name('course-is-deferred-input') content_btn_el = self.wait_elem_name('course-content-btn') lessons_btn_el = self.wait_elem_name('course-lessons-btn') content_el = self.wait_elem_name('course-content') title = Faker('sentence', nb_words=6).generate({}) title_el.send_keys(title) slug = slugify(unidecode(title[:90])) slug = re.sub(r'[^-\w]+$', '', slug) slug = re.sub(r'[^-\w]', '-', slug) self.object_data['title'] = title self.object_data['slug'] = slug time.sleep(1) self.assertEqual(slug_el.get_attribute('value'), slug) # check save obj = self.model.objects.get(title=title, slug=slug) self.assertEqual(bool(obj), True) self.object_id = obj.id self.assertEqual(is_paid_input_el.get_attribute('value'), 'false') self.assertRaises(TimeoutException, callable=lambda: self.driver.find_element_by_name('course-price')) self.assertRaises(TimeoutException, callable=lambda: self.driver.find_element_by_name('course-old-price')) self.assertRaises(TimeoutException, callable=lambda: self.driver.find_element_by_name('course-access-duration')) is_paid_yes_el.click() time.sleep(1) is_paid_input_el = self.wait_elem_css('[name=course-is-paid-input]:checked') self.assertEqual(is_paid_input_el.get_attribute('value'), 'true') try: price_el = self.wait_elem_name('course-price') old_price_el = self.wait_elem_name('course-old-price') access_duration_el = self.wait_elem_name('course-access-duration') except: self.fail('Price, old price and access_duration elements not shown') self.assertEqual(is_deferred_input_el.get_attribute('checked'), 'true') self.assertRaises(TimeoutException, callable=lambda: self.driver.find_element_by_name('course-date')) self.assertRaises(TimeoutException, callable=lambda: self.driver.find_element_by_name('course-time')) is_deferred_yes_el.click() try: date_el = self.wait_elem_name('course-date') time_el = self.wait_elem_name('course-time') except: self.fail('Date and time elements not shown') price_el.send_keys(1000) self.object_data['price'] = 1000 old_price_el.send_keys(1500) self.object_data['old_price'] = 1500 access_duration_el.send_keys(15) self.object_data['access_duration'] = 15 self.check_saving() self.check_content(content_el) lessons_btn_el.click() time.sleep(0.5) # lessons_el = self.wait_elem_name('course-lessons') # lesson_edit_el = self.wait_elem_name('course-lesson-edit') # stream_el = self.wait_elem_name('course-stream') add_lesson_el = self.wait_elem_name('course-add-lesson') add_lesson_el.click() time.sleep(0.5) lesson_title_el = self.wait_elem_name('course-lesson-title') lesson_text_el = self.wait_elem_name('course-lesson-text-wrap').find_element( By.XPATH, './/div[contains(@class, "redactor-layer")][@contenteditable]') lesson_save_btn_el = self.wait_elem_name('course-lesson-save') lesson = {} title = Faker('sentence', nb_words=6).generate({}) lesson_title_el.send_keys(title) lesson['title'] = title text = Faker('sentence', nb_words=50).generate({}) lesson_text_el.click() lesson_text_el.send_keys(text) time.sleep(0.5) lesson_save_btn_el.click() self.object_data['lessons'] = [{ 'title': title, 'short_description': text }] self.check_saving('/api/v1/lessons/', 201)