Покрыть тестами - заполнение курсов.

remotes/origin/feature/testing_courses_30-01-19
gzbender 7 years ago
parent 45427829f8
commit 59797388ac
  1. 1
      apps/auth/__init__.py
  2. 25
      apps/auth/migrations/0001_initial.py
  3. 27
      apps/auth/models.py
  4. 41
      apps/course/tests/test_views.py
  5. 2
      project/settings.py
  6. 21
      project/tests/__init__.py
  7. 1
      project/tests/factories.py
  8. 15
      requirements.txt
  9. 3
      web/src/components/CourseRedactor.vue

@ -0,0 +1 @@
default_app_config = 'apps.auth.apps.AuthConfig'

@ -0,0 +1,25 @@
# Generated by Django 2.0.7 on 2019-02-19 18:31
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='TempToken',
fields=[
('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_temp_token', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
),
]

@ -1,8 +1,29 @@
import binascii
import os
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from rest_framework.authtoken.models import Token
class TempToken(models.Model):
key = models.CharField(_("Key"), max_length=40, primary_key=True)
user = models.OneToOneField(
settings.AUTH_USER_MODEL, related_name='auth_temp_token',
on_delete=models.CASCADE, verbose_name=_("User")
)
created = models.DateTimeField(_("Created"), auto_now_add=True)
class TempToken(Token):
class Meta:
app_label = 'auth'
app_label = 'lilcity_auth'
def save(self, *args, **kwargs):
if not self.key:
self.key = self.generate_key()
return super().save(*args, **kwargs)
def generate_key(self):
return binascii.hexlify(os.urandom(20)).decode()
def __str__(self):
return self.key

@ -1,7 +1,9 @@
from datetime import timedelta
from random import randint
import time
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from factory.faker import Faker
from django.utils import timezone
from django.test import TestCase
@ -10,7 +12,7 @@ from django.conf import settings
from django.utils.text import slugify
from unidecode import unidecode
from project.tests.factories import *
from project.tests.factories import create_admin, create_batch_unique, User, UserFactory, Course, CourseFactory
from project.tests import SeleniumTestCase
from project.utils.selenium_utils import SeleniumExtensions as SE
@ -51,7 +53,8 @@ class CoursesTestCase(TestCase):
class CourseEditTestCase(SeleniumTestCase):
@classmethod
def setUpTestData(cls):
def setUpClass(cls):
super().setUpClass()
create_admin()
UserFactory.create_batch(5, role=User.AUTHOR_ROLE)
# create_batch_unique(CourseFactory, status=Course.STATUS_CHOICES[:3], price=[0, 1000],
@ -63,24 +66,22 @@ class CourseEditTestCase(SeleniumTestCase):
super().tearDownClass()
def test_course_edit(self):
print('go to google')
self.driver.get('http://www.google.com')
return
user = User.objects.filter(role=User.AUTHOR_ROLE).first()
self.client.force_login(user)
self.login(user)
url = self.get_url(reverse('course_create'))
print('url', url)
self.driver.get(url)
print('page opened', self.driver.current_url)
# 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_name('course-is-paid-input')
is_paid_input_el = self.wait_elem_css('[name=course-is-paid-input]:checked')
age_el = self.wait_elem_name('course-age')
is_featured_el = self.wait_elem_name('course-is-featured')
# 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')
@ -88,26 +89,32 @@ class CourseEditTestCase(SeleniumTestCase):
lessons_btn_el = self.wait_elem_name('course-lessons-btn')
content_el = self.wait_elem_name('course-content')
title = Faker('sentence', nb_words=6)
title = Faker('sentence', nb_words=6).generate({})
title_el.send_keys(title)
slug = slugify(unidecode(title[:90]))
print('title', title, 'slug', slug)
self.assertEqual(slug_el.text, slug)
time.sleep(1)
self.assertEqual(slug_el.get_attribute('value'), slug)
print("is_paid_input_el.get_attribute('checked')", is_paid_input_el.get_attribute('checked'))
self.assertFalse(is_paid_input_el.get_attribute('checked'))
self.assertRaises(callable=lambda: self.driver.find_element_by_name('course-price'))
self.assertRaises(callable=lambda: self.driver.find_element_by_name('course-old-price'))
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)
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 and old price elements not shown')
self.fail('Price, old price and access_duration elements not shown')
self.assertFalse(is_deferred_input_el.get_attribute('checked'))
self.assertRaises(callable=lambda: self.driver.find_element_by_name('course-date'))
self.assertRaises(callable=lambda: self.driver.find_element_by_name('course-time'))
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')

@ -59,7 +59,7 @@ INSTALLED_APPS = [
'django_user_agents',
'imagekit',
] + [
'apps.auth.apps',
'apps.auth',
'apps.user',
'apps.notification',
'apps.payment',

@ -1,13 +1,14 @@
from django.test import TestCase
from django.test import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.by import By
from pyvirtualdisplay import Display
from django.conf import settings
from project.utils.selenium_utils import SeleniumExtensions as SE
from django.conf import settings
from apps.auth.models import TempToken
class SeleniumTestCase(TestCase):
class SeleniumTestCase(LiveServerTestCase ):
@classmethod
def setUpClass(cls):
@ -18,12 +19,12 @@ class SeleniumTestCase(TestCase):
@classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
cls.display.stop()
super().tearDownClass()
def get_url(self, url):
return 'http://%s%s' % (settings.MAIN_HOST, url)
def get_url(self, url=''):
return '%s%s' % (self.live_server_url, url)
def wait_elem_xpath(self, xpath, inside_el=None, wait_time=10):
return SE.wait_elem(self.driver, (By.XPATH, xpath), inside_el, wait_time)
@ -40,5 +41,13 @@ class SeleniumTestCase(TestCase):
def wait_elem_name(self, name, inside_el=None, wait_time=10):
return SE.wait_elem(self.driver, (By.NAME, name), inside_el, wait_time)
def wait_elem_id(self, id, inside_el=None, wait_time=10):
return SE.wait_elem(self.driver, (By.ID, id), inside_el, wait_time)
def wait_elems_name(self, name, inside_el=None, wait_time=10):
return SE.wait_elems(self.driver, (By.NAME, name), inside_el, wait_time)
def login(self, user):
tt = TempToken.objects.create(user=user)
self.driver.get('%s?temp-token=%s' % (self.get_url(), tt.key))

@ -75,6 +75,7 @@ class UserFactory(DjangoModelFactory):
gallery = None
photo = None #factory.SubFactory(ImageObjectFactory)
is_active = True
auth_token = None
class CategoryFactory(DjangoModelFactory):

@ -38,5 +38,16 @@ drf_dynamic_fields
flower==0.9.2
unidecode
factory-boy==2.11.1
pyvirtualdisplay==0.2.1 # + sudo apt-get install xvfb + sudo apt-get install chromium-chromedriver
# + sudo ln -s /usr/lib/chromium-browser/chromedriver /usr/bin/chromedriver
pyvirtualdisplay==0.2.1
selenium
# sudo apt-get install xvfb
# sudo apt-get install libappindicator3-1 fonts-liberation
# wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
# sudo apt-get install unzip
# wget -N https://chromedriver.storage.googleapis.com/73.0.3683.20/chromedriver_linux64.zip
# unzip chromedriver_linux64.zip
# chmod +x chromedriver
# sudo mv -f chromedriver /usr/local/share/chromedriver
# sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
# sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver

@ -90,7 +90,7 @@
<div class="field__label field__label_gray">ПРОДОЛЖИТЕЛЬНОСТЬ ДОСТУПА</div>
<div class="field__wrap field__wrap__appended">
<input type="text" class="field__input field__input__appended" v-model.number="course.access_duration"
@input="$v.course.access_duration.$touch()">
@input="$v.course.access_duration.$touch()" name="course-access-duration">
<button disabled class="field__append">{{pluralize(course.access_duration, ['день', 'дня', 'дней'])}}</button>
</div>
</div>
@ -612,7 +612,6 @@
this.lessons = data.lessons.map((lessonJson) => {
return api.convertLessonJson(lessonJson);
});
this.course.access_duration = this.course.access_duration || '';
},
loadCourseDraft() {
//console.log('loadCourseDraft');

Loading…
Cancel
Save