From 327925c7bae20f866bf9047ab9d6b0c37a792225 Mon Sep 17 00:00:00 2001 From: gzbender Date: Thu, 28 Feb 2019 02:17:02 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BA=D1=80=D1=8B=D1=82=D1=8C=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B0=D0=BC=D0=B8=20-=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D1=83?= =?UTF-8?q?=D1=80=D1=81=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/content/tests.py | 3 - apps/content/tests/__init__.py | 0 apps/content/tests/mixins.py | 129 ++++++++++++++++++ apps/course/templates/course/course_edit.html | 3 +- apps/course/tests/test_views.py | 36 ++++- project/utils/selenium_utils.py | 2 +- web/src/components/CourseRedactor.vue | 6 +- web/src/components/blocks/BlockAdd.vue | 16 +-- web/src/components/blocks/BlockContent.vue | 9 +- web/src/components/blocks/BlockImage.vue | 6 +- web/src/components/blocks/BlockImageText.vue | 8 +- web/src/components/blocks/BlockImages.vue | 13 +- web/src/components/blocks/BlockText.vue | 6 +- web/src/components/blocks/BlockVideo.vue | 6 +- 14 files changed, 199 insertions(+), 44 deletions(-) delete mode 100644 apps/content/tests.py create mode 100644 apps/content/tests/__init__.py create mode 100644 apps/content/tests/mixins.py diff --git a/apps/content/tests.py b/apps/content/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/apps/content/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/apps/content/tests/__init__.py b/apps/content/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/content/tests/mixins.py b/apps/content/tests/mixins.py new file mode 100644 index 00000000..71ff7e6e --- /dev/null +++ b/apps/content/tests/mixins.py @@ -0,0 +1,129 @@ +import time + +from factory.faker import Faker +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By + + +class TestContentMixin: + content_data = [] + autosave = True + + def check_auto_saving(self): + if not self.autosave: + return + raise NotImplementedError() + + def check_content_auto_saving(self, object): + if not self.autosave: + return + print('Check content autosaving',) + self.assertEqual(object.content.all().count(), len(self.content_data)) + for i, item in enumerate(object.content.all().order_by('position', '-created_at',)): + item_data = self.content_data[i].get('data') + for key, value in item_data.items(): + print('real obj field value:', getattr(item, key, None)) + print('expected value:', value) + self.assertEqual(getattr(item, key), value) + print('OK') + + def check_content(self, inside_el=None): + print('Check content block') + self.object_data['content'] = self.content_data + block_add_el = self.wait_elem_name('block-add', inside_el) + open_el = self.wait_elem_name('block-add-open', block_add_el) + self.assertRaises(TimeoutException, lambda: self.wait_elem_name('block-add-close', block_add_el)) + open_el.click() + time.sleep(1) + close_el = self.wait_elem_name('block-add-close', block_add_el) + + block_text_el = self.wait_elem_name('block-add-block-text', block_add_el) + block_text_el.click() + time.sleep(0.5) + self.check_block_text(inside_el) + + block_image_el = self.wait_elem_name('block-add-block-image', block_add_el) + block_image_el.click() + time.sleep(0.5) + self.check_block_image(inside_el) + + block_image_text_el = self.wait_elem_name('block-add-block-image-text', block_add_el) + block_image_text_el.click() + time.sleep(0.5) + self.check_block_image_text(inside_el) + + block_images_el = self.wait_elem_name('block-add-block-images', block_add_el) + block_images_el.click() + time.sleep(0.5) + self.check_block_images(inside_el) + + block_video_el = self.wait_elem_name('block-add-block-video', block_add_el) + block_video_el.click() + time.sleep(0.5) + self.check_block_video(inside_el) + + def check_block_text(self, inside_el=None): + print('Check block text') + time.sleep(1) + block_obj = {'type': 'text', 'data': {}} + block_el = self.wait_elem_name('block-text', inside_el) + title_el = self.wait_elem_name('block-text-title', block_el) + text_el = self.wait_elem_name('block-text-text-wrap', block_el) + text_el.find_element( + By.XPATH, './/div[contains(@class, "redactor-layer")][@contenteditable]') + self.content_data.append(block_obj) + + title = Faker('sentence', nb_words=6).generate({}) + title_el.send_keys(title) + block_obj['data']['title'] = title + text = Faker('sentence', nb_words=50).generate({}) + self.driver.execute_script("arguments[0].click();", text_el) + self.driver.execute_script("arguments[0].innerHtml = arguments[1];", text_el, text) + self.driver.execute_script("arguments[0].dispatchEvent(new Event('change'));", text_el) + # text_el.send_keys(text) + block_obj['data']['text'] = '

%s

' % text + self.check_auto_saving() + + def check_block_image(self, inside_el=None): + print('Check block image') + time.sleep(1) + block_obj = {'type': 'image', 'data': {}} + block_el = self.wait_elem_name('block-image', inside_el) + title_el = self.wait_elem_name('block-image-title', block_el) + image_el = self.wait_elem_name('block-image-image', block_el) + self.content_data.append(block_obj) + + title = Faker('sentence', nb_words=6).generate({}) + title_el.send_keys(title) + block_obj['data']['title'] = title + # TODO: check image upload + self.check_auto_saving() + + def check_block_image_text(self, inside_el=None): + print('Check block image-text') + time.sleep(1) + block_obj = {'type': 'image-text', 'data': {}} + block_el = self.wait_elem_name('block-image-text', inside_el) + title_el = self.wait_elem_name('block-image-text-title', block_el) + text_el = self.wait_elem_name('block-image-text-text-wrap', block_el).find_element( + By.XPATH, './/div[contains(@class, "redactor-layer")][@contenteditable]') + image_el = self.wait_elem_name('block-image-text-image', block_el) + self.content_data.append(block_obj) + + title = Faker('sentence', nb_words=6).generate({}) + title_el.send_keys(title) + block_obj['data']['title'] = title + text = Faker('sentence', nb_words=50).generate({}) + self.driver.execute_script("arguments[0].click();", text_el) + self.driver.execute_script("arguments[0].innerHtml = arguments[1];", text_el, text) + self.driver.execute_script("arguments[0].dispatchEvent(new Event('change'));", text_el) + # text_el.send_keys(text) + block_obj['data']['text'] = '

%s

' % text + # TODO: check image upload + self.check_auto_saving() + + def check_block_images(self, inside_el=None): + print('Check block images') + + def check_block_video(self, inside_el=None): + print('Check block images') diff --git a/apps/course/templates/course/course_edit.html b/apps/course/templates/course/course_edit.html index 83990c00..5fc6666a 100644 --- a/apps/course/templates/course/course_edit.html +++ b/apps/course/templates/course/course_edit.html @@ -17,7 +17,8 @@ {% endblock header_buttons %} {% block content %} - diff --git a/apps/course/tests/test_views.py b/apps/course/tests/test_views.py index 5d791de9..9ddcc30c 100644 --- a/apps/course/tests/test_views.py +++ b/apps/course/tests/test_views.py @@ -14,6 +14,7 @@ from unidecode import unidecode from project.tests.factories import create_admin, create_batch_unique, User, UserFactory, Course, CourseFactory from project.tests import SeleniumTestCase +from apps.content.tests.mixins import TestContentMixin from project.utils.selenium_utils import SeleniumExtensions as SE ''' @@ -50,7 +51,10 @@ class CoursesTestCase(TestCase): ''' -class CourseEditTestCase(SeleniumTestCase): +class CourseEditTestCase(TestContentMixin, SeleniumTestCase): + model = Course + object_id = None + object_data = {} @classmethod def setUpClass(cls): @@ -65,13 +69,23 @@ class CourseEditTestCase(SeleniumTestCase): print('teardown CourseEditTestCase') super().tearDownClass() + def check_auto_saving(self): + # TODO + time.sleep(5) + obj = self.model.objects.get(id=self.object_id) + for key, value in self.object_data.items(): + if key != 'content': + self.assertEqual(getattr(obj, key), value) + self.check_content_auto_saving(obj) + def test_course_edit(self): user = User.objects.filter(role=User.AUTHOR_ROLE).first() self.login(user) url = self.get_url(reverse('course_create')) - print('url', url) + print('url is', url) self.driver.get(url) print('page opened', self.driver.current_url) + 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') @@ -92,17 +106,25 @@ class CourseEditTestCase(SeleniumTestCase): title = Faker('sentence', nb_words=6).generate({}) title_el.send_keys(title) slug = slugify(unidecode(title[:90])) - print('title', title, 'slug', slug) - time.sleep(1) + self.object_data['title'] = title + self.object_data['slug'] = slug + # print('title:', title) + # print('slug:', slug) + time.sleep(2) 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 + print("is_paid_input_el.get_attribute('checked')", is_paid_input_el.get_attribute('checked')) 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(0.5) + 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: @@ -112,7 +134,7 @@ class CourseEditTestCase(SeleniumTestCase): except: self.fail('Price, old price and access_duration elements not shown') - self.assertFalse(is_deferred_input_el.get_attribute('checked')) + 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() @@ -121,6 +143,8 @@ class CourseEditTestCase(SeleniumTestCase): time_el = self.wait_elem_name('course-time') except: self.fail('Date and time elements not shown') + + self.check_content(content_el) # lessons_el = self.wait_elem_name('course-lessons') # add_lesson_el = self.wait_elem_name('course-add-lesson') diff --git a/project/utils/selenium_utils.py b/project/utils/selenium_utils.py index 5bf62c6b..4f523d1b 100644 --- a/project/utils/selenium_utils.py +++ b/project/utils/selenium_utils.py @@ -17,7 +17,7 @@ class ElementIn(object): def __call__(self, driver): try: - return getattr(self.element, self.find_fn)(self.locator) + return getattr(self.element, self.find_fn)(*self.locator) except: return False diff --git a/web/src/components/CourseRedactor.vue b/web/src/components/CourseRedactor.vue index 5dd557c8..709bea46 100644 --- a/web/src/components/CourseRedactor.vue +++ b/web/src/components/CourseRedactor.vue @@ -99,14 +99,16 @@
СТОИМОСТЬ
- +
СТОИМОСТЬ БЕЗ СКИДКИ
- +
diff --git a/web/src/components/blocks/BlockAdd.vue b/web/src/components/blocks/BlockAdd.vue index 0090a8df..0a3c9bd1 100644 --- a/web/src/components/blocks/BlockAdd.vue +++ b/web/src/components/blocks/BlockAdd.vue @@ -1,7 +1,7 @@