From 3496a204893cf2c355a7acae08bc63f8a4ef3c1d Mon Sep 17 00:00:00 2001 From: Lorenz Padberg Date: Tue, 5 Apr 2022 11:07:03 +0200 Subject: [PATCH] created learnpath factories --- local-setup-for-tests.sh | 16 +++ server/example.env | 3 + server/local.env | 0 server/setup_test_data.sh | 5 + .../vbv_lernwelt/core/create_default_users.py | 33 +++++ .../commands/create_default_users.py | 9 ++ .../core/management/commands/dummy_data.py | 117 ++++++++++++++++++ .../management/commands/migrate_locales.py | 11 ++ .../commands/create_default_learingpath.py | 11 ++ .../commands/delete_default_learingpath.py | 14 +++ .../learnpath/migrations/0001_initial.py | 49 +++----- .../0002_alter_circle_description.py | 18 +++ .../migrations/0002_auto_20220329_1506.py | 55 -------- server/vbv_lernwelt/learnpath/models.py | 18 +-- .../tests/create_default_learning_path.py | 50 +++++++- .../learnpath/tests/learningpath_factories.py | 33 ++++- 16 files changed, 344 insertions(+), 98 deletions(-) create mode 100755 local-setup-for-tests.sh create mode 100644 server/local.env create mode 100644 server/setup_test_data.sh create mode 100644 server/vbv_lernwelt/core/create_default_users.py create mode 100644 server/vbv_lernwelt/core/management/commands/create_default_users.py create mode 100644 server/vbv_lernwelt/core/management/commands/dummy_data.py create mode 100644 server/vbv_lernwelt/core/management/commands/migrate_locales.py create mode 100644 server/vbv_lernwelt/learnpath/management/commands/create_default_learingpath.py create mode 100644 server/vbv_lernwelt/learnpath/management/commands/delete_default_learingpath.py create mode 100644 server/vbv_lernwelt/learnpath/migrations/0002_alter_circle_description.py delete mode 100644 server/vbv_lernwelt/learnpath/migrations/0002_auto_20220329_1506.py diff --git a/local-setup-for-tests.sh b/local-setup-for-tests.sh new file mode 100755 index 00000000..7acc2b41 --- /dev/null +++ b/local-setup-for-tests.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ./setup-for-tests.sh + +export DATABASE_HOST=postgres +export DATABASE_PORT=5432 +export DATABASE_URL=postgres://$DATABASE_USER:$PG_PASSWORD@$DATABASE_HOST:$DATABASE_PORT/$DATABASE_NAME +psql -U $DATABASE_USER -h $DATABASE_HOST -c "drop database $DATABASE_NAME" + +npm install --prefix client +#npm run "install:cypress" --prefix client +psql -U $DATABASE_USER -h $DATABASE_HOST -c "create database $DATABASE_NAME" +python server/manage.py dummy_data +python server/manage.py runserver & +npm run dev --prefix client & +cd client +/node_modules/.bin/cypress run diff --git a/server/example.env b/server/example.env index f5e90aee..70c4e1d7 100644 --- a/server/example.env +++ b/server/example.env @@ -1,3 +1,6 @@ + export VBV_DATABASE_URL='postgres://vbv_lernwelt@localhost:5432/vbv_lernwelt' #export VBV_DJANGO_LOGGING_CONF=VBV_DJANGO_LOGGING_CONF_CONSOLE_COLOR export VBV_DJANGO_DEBUG=True +export PATH=/Applications/Postgres.app/Contents/Versions/14/bin:$PATH + diff --git a/server/local.env b/server/local.env new file mode 100644 index 00000000..e69de29b diff --git a/server/setup_test_data.sh b/server/setup_test_data.sh new file mode 100644 index 00000000..7a1dd173 --- /dev/null +++ b/server/setup_test_data.sh @@ -0,0 +1,5 @@ +python manage.py migrate +python manage.py createcachetable +python manage.py create_default_users +#python manage.py create_default_learingpath + diff --git a/server/vbv_lernwelt/core/create_default_users.py b/server/vbv_lernwelt/core/create_default_users.py new file mode 100644 index 00000000..d76bb7d3 --- /dev/null +++ b/server/vbv_lernwelt/core/create_default_users.py @@ -0,0 +1,33 @@ +from django.contrib.auth.hashers import make_password +from django.contrib.auth.models import Group + +from models import User + + +def create_test_users(user_model=User, group_model=Group): + admin_group, created = group_model.objects.get_or_create(name='admin_group') + content_creator_grop, created = group_model.objects.get_or_create(name='content_creator_grop') + student_group, created = group_model.objects.get_or_create(name='student_group') + + admin_user, created = _get_or_create_user(user_model=user_model, + username='admin', + password='admin') + admin_user.groups.add(admin_group) + admin_user.save() + + student_user, created = _get_or_create_user(user_model=user_model, username='student', password='student') + student_user.groups.add(student_group) + student_user.save() + + +def _get_or_create_user(user_model, *args, **kwargs): + username = kwargs.get('username', None) + password = kwargs.get('password', None) + created = False + + user = user_model.objects.filter(username=username).first() + + if not user: + user = user_model.objects.create(username=username, password=make_password(password)) + created = True + return user, created diff --git a/server/vbv_lernwelt/core/management/commands/create_default_users.py b/server/vbv_lernwelt/core/management/commands/create_default_users.py new file mode 100644 index 00000000..2ebc99d4 --- /dev/null +++ b/server/vbv_lernwelt/core/management/commands/create_default_users.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# +# Iterativ GmbH +# http://www.iterativ.ch/ +# +# Copyright (c) 2015 Iterativ GmbH. All rights reserved. +# +# Created on 2022-04-05 +# @author: lorenz.padberg@iterativ.ch diff --git a/server/vbv_lernwelt/core/management/commands/dummy_data.py b/server/vbv_lernwelt/core/management/commands/dummy_data.py new file mode 100644 index 00000000..0e11c4b1 --- /dev/null +++ b/server/vbv_lernwelt/core/management/commands/dummy_data.py @@ -0,0 +1,117 @@ +import os +import random +import shutil +from uuid import uuid1 + +import wagtail_factories +from django.conf import settings +from django.core import management +from django.core.management import BaseCommand +from django.db import connection +from wagtail.core.models import Page + +from books.factories import BookFactory, TopicFactory, ModuleFactory, ChapterFactory, ContentBlockFactory +from core.factories import UserFactory +from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory +from users.services import create_users, create_student + +from .data.module_data import data +from .data.user_data import user_data + + +class Command(BaseCommand): + + def ensure_clean_dir(self, folder): + path = os.path.join(settings.MEDIA_ROOT, folder) + if os.path.exists(path): + shutil.rmtree(path) + if not os.path.exists(path): + os.makedirs(path) + + def filter_data(self, input_data, filter_keyword): + filters = [filter_keyword] if not isinstance(filter_keyword, list) else filter_keyword + return {k: v for (k, v) in input_data.items() if not (k in filters)} + + def handle(self, *args, **options): + with connection.cursor() as cursor: + cursor.execute("DROP SCHEMA IF EXISTS public CASCADE;") + cursor.execute( + "CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION {};".format(settings.DATABASES['default']['USER'])) + cursor.execute("GRANT ALL ON SCHEMA public TO {};".format(settings.DATABASES['default']['USER'])) + management.call_command('migrate', verbosity=0, interactive=False) + + self.ensure_clean_dir('images') + self.ensure_clean_dir('original_images') + self.ensure_clean_dir('documents') + + site = wagtail_factories.SiteFactory.create(is_default_site=True) + + Page.objects.get(title='Root').delete() + + UserFactory( + username='test', + is_staff=True, + is_superuser=True, + first_name='Nicol', + last_name='Bolas', + onboarding_visited=True + ) + + create_users(user_data) + + # create student without class + create_student( + username='hansli', + first_name='Hansli', + last_name='Alleini' + ) + + for book_idx, book_data in enumerate(data): + book = BookFactory.create(parent=site.root_page, **self.filter_data(book_data, 'topics')) + + default_topics = [{} for _ in range(0, random.randint(5, 8))] + topics_data = book_data.get('topics', default_topics) + + for topic_idx, topic_data in enumerate(topics_data): + topic = TopicFactory.create(parent=book, **self.filter_data(topic_data, 'modules')) + + default_modules = [{} for _ in range(0, random.randint(3, 6))] + modules_data = topic_data.get('modules', default_modules) + + for module_idx, module_data in enumerate(modules_data): + module = ModuleFactory.create(parent=topic, + **self.filter_data(module_data, ['objective_groups', 'chapters'])) + + default_objective_groups = [{} for _ in range(0, 2)] + objective_group_data = module_data.get('objective_groups', default_objective_groups) + + for objective_group_idx, objective_group_entry in enumerate(objective_group_data): + factory_params = self.filter_data(objective_group_entry, 'objectives') + objective_group = ObjectiveGroupFactory.create(module=module, + + **factory_params) + + default_objectives = [{} for _ in range(0, 4)] + objectives_data = objective_group_entry.get('objectives', default_objectives) + + for objective_idx, objective_data in enumerate(objectives_data): + ObjectiveFactory.create(group=objective_group, **objective_data) + + default_chapters = [{} for _ in range(0, 2)] + chapters_data = module_data.get('chapters', default_chapters) + + for chapter_idx, chapter_data in enumerate(chapters_data): + chapter = ChapterFactory.create(parent=module, + **self.filter_data(chapter_data, 'content_blocks')) + + default_content_blocks = [{} for _ in range(0, 4)] + content_blocks_data = chapter_data.get('content_blocks', default_content_blocks) + + for content_block_idx, content_block_data in enumerate(content_blocks_data): + # ContentBlockFactory.create(parent=chapter, **self.filter_data(content_block_data, 'contents')) + ContentBlockFactory.create(parent=chapter, module=module, slug=f'{uuid1()}', **content_block_data) + + # now create all and rooms + management.call_command('dummy_rooms', verbosity=0) + management.call_command('dummy_news', verbosity=0) + diff --git a/server/vbv_lernwelt/core/management/commands/migrate_locales.py b/server/vbv_lernwelt/core/management/commands/migrate_locales.py new file mode 100644 index 00000000..3941eef8 --- /dev/null +++ b/server/vbv_lernwelt/core/management/commands/migrate_locales.py @@ -0,0 +1,11 @@ +# pylint: disable=import-outside-toplevel + +import djclick as click +from django.contrib.auth import get_user_model + +from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path, \ + delete_default_learning_path + + +def command(): + delete_default_learning_path() diff --git a/server/vbv_lernwelt/learnpath/management/commands/create_default_learingpath.py b/server/vbv_lernwelt/learnpath/management/commands/create_default_learingpath.py new file mode 100644 index 00000000..5faf3e59 --- /dev/null +++ b/server/vbv_lernwelt/learnpath/management/commands/create_default_learingpath.py @@ -0,0 +1,11 @@ +# pylint: disable=import-outside-toplevel + +import djclick as click +from django.contrib.auth import get_user_model + +from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path + + +@click.command() +def command(): + create_default_learning_path() diff --git a/server/vbv_lernwelt/learnpath/management/commands/delete_default_learingpath.py b/server/vbv_lernwelt/learnpath/management/commands/delete_default_learingpath.py new file mode 100644 index 00000000..2da68a66 --- /dev/null +++ b/server/vbv_lernwelt/learnpath/management/commands/delete_default_learingpath.py @@ -0,0 +1,14 @@ +# pylint: disable=import-outside-toplevel + +import djclick as click +from django.contrib.auth import get_user_model + +from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path, \ + delete_default_learning_path + +import djclick as click + + +@click.command() +def command(): + delete_default_learning_path() diff --git a/server/vbv_lernwelt/learnpath/migrations/0001_initial.py b/server/vbv_lernwelt/learnpath/migrations/0001_initial.py index b48e97d9..90020cff 100644 --- a/server/vbv_lernwelt/learnpath/migrations/0001_initial.py +++ b/server/vbv_lernwelt/learnpath/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.12 on 2022-03-29 09:21 +# Generated by Django 3.2.12 on 2022-04-04 14:52 from django.db import migrations, models import django.db.models.deletion @@ -14,66 +14,55 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='LearnBlock', + name='Circle', fields=[ ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), - ('internal_name', models.CharField(max_length=255)), + ('description', models.TextField(default='')), ], options={ - 'abstract': False, + 'verbose_name': 'Circle', }, bases=('wagtailcore.page',), ), migrations.CreateModel( - name='Circle', + name='LearningPath', fields=[ - ('learnblock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='learnpath.learnblock')), - ('description', models.TextField(default='')), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ], options={ - 'abstract': False, + 'verbose_name': 'Learning Path', }, - bases=('learnpath.learnblock',), + bases=('wagtailcore.page',), ), migrations.CreateModel( - name='LearnPath', + name='LearningSequence', fields=[ - ('learnblock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='learnpath.learnblock')), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ], options={ - 'abstract': False, + 'verbose_name': 'homepage', }, - bases=('learnpath.learnblock',), + bases=('wagtailcore.page',), ), migrations.CreateModel( - name='LearnSequence', + name='LearningUnit', fields=[ - ('learnblock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='learnpath.learnblock')), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ], options={ - 'abstract': False, + 'verbose_name': 'Learning Unig', }, - bases=('learnpath.learnblock',), - ), - migrations.CreateModel( - name='LearnUnit', - fields=[ - ('learnblock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='learnpath.learnblock')), - ], - options={ - 'abstract': False, - }, - bases=('learnpath.learnblock',), + bases=('wagtailcore.page',), ), migrations.CreateModel( name='Topic', fields=[ - ('learnblock_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='learnpath.learnblock')), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ('is_visible', models.BooleanField(default=True)), ], options={ - 'abstract': False, + 'verbose_name': 'Topic', }, - bases=('learnpath.learnblock',), + bases=('wagtailcore.page',), ), ] diff --git a/server/vbv_lernwelt/learnpath/migrations/0002_alter_circle_description.py b/server/vbv_lernwelt/learnpath/migrations/0002_alter_circle_description.py new file mode 100644 index 00000000..d8270c77 --- /dev/null +++ b/server/vbv_lernwelt/learnpath/migrations/0002_alter_circle_description.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2022-04-04 15:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('learnpath', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='circle', + name='description', + field=models.TextField(blank=True, default=''), + ), + ] diff --git a/server/vbv_lernwelt/learnpath/migrations/0002_auto_20220329_1506.py b/server/vbv_lernwelt/learnpath/migrations/0002_auto_20220329_1506.py deleted file mode 100644 index 2ef45943..00000000 --- a/server/vbv_lernwelt/learnpath/migrations/0002_auto_20220329_1506.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 3.2.12 on 2022-03-29 13:06 - -from django.conf import settings -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('wagtailcore', '0066_collection_management_permissions'), - ('wagtailredirects', '0007_add_autocreate_fields'), - ('contenttypes', '0002_remove_content_type_name'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('wagtailforms', '0004_add_verbose_name_plural'), - ('learnpath', '0001_initial'), - ] - - operations = [ - migrations.RenameModel( - old_name='LearnPath', - new_name='LearningPath', - ), - migrations.RenameModel( - old_name='LearnSequence', - new_name='LearningSequence', - ), - migrations.RenameModel( - old_name='LearnUnit', - new_name='LearningUnit', - ), - migrations.AlterModelOptions( - name='circle', - options={'verbose_name': 'Circle'}, - ), - migrations.AlterModelOptions( - name='learningpath', - options={'verbose_name': 'Learning Path'}, - ), - migrations.AlterModelOptions( - name='learningsequence', - options={'verbose_name': 'homepage'}, - ), - migrations.AlterModelOptions( - name='learningunit', - options={'verbose_name': 'Learning Unig'}, - ), - migrations.AlterModelOptions( - name='topic', - options={'verbose_name': 'Topic'}, - ), - migrations.RemoveField( - model_name='learnblock', - name='internal_name', - ), - ] diff --git a/server/vbv_lernwelt/learnpath/models.py b/server/vbv_lernwelt/learnpath/models.py index 4a7f5e8e..1fe67446 100644 --- a/server/vbv_lernwelt/learnpath/models.py +++ b/server/vbv_lernwelt/learnpath/models.py @@ -1,15 +1,18 @@ # Create your models here. from django.db import models -from wagtail.core.models import Page from wagtail.admin.edit_handlers import FieldPanel +from wagtail.core.fields import RichTextField +from wagtail.core.models import Page + +# class HomePage(Page): +# body = RichTextField(default='', blank=True) # -# -# class LearnBlock(Page): -# pass -# # id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) -# +# content_panels = Page.content_panels + [ +# FieldPanel('body', classname="full"), +# ] + class LearningPath(Page): content_panels = Page.content_panels + [ @@ -28,7 +31,6 @@ class LearningPath(Page): class Topic(Page): is_visible = models.BooleanField(default=True) - content_panels = Page.content_panels + [ FieldPanel('is_visible', classname="full"), ] @@ -47,7 +49,7 @@ class Topic(Page): class Circle(Page): - description = models.TextField(default="") + description = models.TextField(default="", blank=True) parent_page_types = ['learnpath.Topic'] subpage_types = ['learnpath.LearningSequence'] diff --git a/server/vbv_lernwelt/learnpath/tests/create_default_learning_path.py b/server/vbv_lernwelt/learnpath/tests/create_default_learning_path.py index ab2c5144..365b3e8b 100644 --- a/server/vbv_lernwelt/learnpath/tests/create_default_learning_path.py +++ b/server/vbv_lernwelt/learnpath/tests/create_default_learning_path.py @@ -1,6 +1,50 @@ -from vbv_lernwelt.learnpath.models import LearningPath -from vbv_lernwelt.learnpath.tests.learningpath_factories import LearningPathFactory +import wagtail_factories +from wagtail.core.models import Site + +from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit +from vbv_lernwelt.learnpath.tests.learningpath_factories import LearningPathFactory, TopicFactory, CircleFactory, LearningSequenceFactory, LearningUnitFactory def create_default_learning_path(): - lp = LearningPathFactory() + site = Site.objects.filter(is_default_site=True).first() + + if not site: + site = wagtail_factories.SiteFactory.get(is_default_site=True) + + lp = LearningPathFactory.create(title="Versicherungsvermittler/in", parent=site.root_page) + + tp = TopicFactory.create(title="Basis", is_visible=False, parent=lp) + + circle_1 = CircleFactory.create(title="Basis", parent=tp, description="""In diesem Circle erklären wir dir, wie der Lehrgang + Versicherungsvermittler / in " aufgebaut ist. Zudem vermitteln wir dir die wichtigsten Grundlagen, + damit erfolgreich mit deinem Lernpfad starten kannst.""") + + ls_1 = LearningSequenceFactory.create(title='Einleitung', parent=circle_1) + lu_1 = LearningUnitFactory.create(title="Herzlich Willkommmen", parent=ls_1) + + ls_2 = LearningSequenceFactory.create(title='Grundlagen', parent=circle_1) + lu_1 = LearningUnitFactory.create(title="Herzlich Willkommmen", parent=ls_2) + + tp = TopicFactory.create(title="Gewinnen von Kunden", parent=lp) + circle_2 = CircleFactory.create(title="Gewinnen", parent=tp) + + tp = TopicFactory.create(title="Beraten der Kunden", parent=lp) + circle_3 = CircleFactory.create(title="Einstieg", parent=tp) + circle_4 = CircleFactory.create(title="Analyse", parent=tp) + circle_5 = CircleFactory.create(title="Lösung", parent=tp) + circle_6 = CircleFactory.create(title="Abschluss", parent=tp) + + tp = TopicFactory.create(title="Betreuen und Ausbauen des Kundenstamms", parent=lp) + circle_7 = CircleFactory.create(title="Betreuen", parent=tp) + + tp = TopicFactory.create(title="Prüfung", is_visible=False, parent=lp) + circle_7 = CircleFactory.create(title="Prüfungsvorbereitung", parent=tp) + + +def delete_default_learning_path(): + LearningUnit.objects.all().delete() + LearningSequence.objects.all().delete() + Circle.objects.all().delete() + Topic.objects.all().delete() + LearningPath.objects.all().delete() + diff --git a/server/vbv_lernwelt/learnpath/tests/learningpath_factories.py b/server/vbv_lernwelt/learnpath/tests/learningpath_factories.py index cb85cd85..b13d7dc7 100644 --- a/server/vbv_lernwelt/learnpath/tests/learningpath_factories.py +++ b/server/vbv_lernwelt/learnpath/tests/learningpath_factories.py @@ -1,6 +1,6 @@ - import wagtail_factories -from vbv_lernwelt.learnpath.models import LearningPath + +from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit class LearningPathFactory(wagtail_factories.PageFactory): @@ -8,3 +8,32 @@ class LearningPathFactory(wagtail_factories.PageFactory): class Meta: model = LearningPath + + +class TopicFactory(wagtail_factories.PageFactory): + title = "Gewinnen von Kunden" + is_visible = True + + class Meta: + model = Topic + + +class CircleFactory(wagtail_factories.PageFactory): + title = "Gewinnen" + + class Meta: + model = Circle + + +class LearningSequenceFactory(wagtail_factories.PageFactory): + title = "Grundlagen" + + class Meta: + model = LearningSequence + + +class LearningUnitFactory(wagtail_factories.PageFactory): + title = "Herzlich Willkommen" + + class Meta: + model = LearningUnit