Add registration, implement tests

This commit is contained in:
Christian Cueni 2020-02-03 13:30:19 +01:00
parent 6beb4296f7
commit f628966ae9
9 changed files with 123 additions and 143 deletions

View File

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
#
# ITerativ GmbH
# http://www.iterativ.ch/
#
# Copyright (c) 2020 ITerativ GmbH. All rights reserved.
#
# Created on 03.02.20
# @author: chrigu <christian.cueni@iterativ.ch>
## Mocks
import json
import os
from datetime import datetime, timedelta
class MockResponse:
def __init__(self, status_code):
self.status_code = status_code
def json(self):
return {}
## Setup json data
def make_orders_valid(order_items):
for order_item in order_items['items']:
if 'created_at' in order_item:
yesterday = datetime.now() - timedelta(1)
order_item['created_at'] = datetime.strftime(yesterday, '%Y-%m-%d %H:%M:%S')
return order_items
# Load data
dir_path = os.path.dirname(os.path.realpath(__file__))
with open('{}/mock_data/valid_teacher_orders.json'.format(dir_path), 'r') as file:
valid_teacher_order_data = file.read()
with open('{}/mock_data/valid_student_orders.json'.format(dir_path), 'r') as file:
valid_student_order_data = file.read()
with open('{}/mock_data/me_data.json'.format(dir_path), 'r') as file:
me_data = file.read()
with open('{}/mock_data/email_not_confirmed_me.json'.format(dir_path), 'r') as file:
not_confirmed_email_me_data = file.read()
ME_DATA = json.loads(me_data)
NOT_CONFIRMED_ME = json.loads(not_confirmed_email_me_data)
valid_teacher_order_items = json.loads(valid_teacher_order_data)
VALID_TEACHERS_ORDERS = make_orders_valid(valid_teacher_order_items)
valid_student_order_items = json.loads(valid_student_order_data)
VALID_STUDENT_ORDERS = make_orders_valid(valid_student_order_items)

View File

@ -8,52 +8,54 @@
# Created on 2019-10-08 # Created on 2019-10-08
# @author: chrigu <christian.cueni@iterativ.ch> # @author: chrigu <christian.cueni@iterativ.ch>
import graphene import graphene
from django.conf import settings from django.contrib.auth import login
from graphene import relay from graphene import relay
from core.hep_client import HepClient, HepClientException, HepClientUnauthorizedException from core.hep_client import HepClient, HepClientException, HepClientUnauthorizedException
from users.user_signup_login_handler import handle_user_and_verify_products from users.user_signup_login_handler import handle_user_and_verify_products
class PublicFieldError(graphene.ObjectType):
code = graphene.String()
class RegistrationError(graphene.ObjectType): class RegistrationError(graphene.ObjectType):
field = graphene.String() field = graphene.String()
class Registration(relay.ClientIDMutation): class Registration(relay.ClientIDMutation):
class Input: class Input:
confirmation_key = graphene.String() confirmation_key_input = graphene.String()
success = graphene.Boolean() success = graphene.Boolean()
message = graphene.String()
errors = graphene.List(RegistrationError) # todo: change for consistency errors = graphene.List(RegistrationError) # todo: change for consistency
@classmethod @classmethod
def mutate_and_get_payload(cls, root, info, **kwargs): def mutate_and_get_payload(cls, root, info, **kwargs):
confirmation_key = kwargs.get('confirmation_key') confirmation_key = kwargs.get('confirmation_key_input')
hep_client = HepClient() hep_client = HepClient()
try: try:
user_data = hep_client.customer_activate(confirmation_key) user_data = hep_client.customer_activate(confirmation_key)
except HepClientUnauthorizedException: except HepClientUnauthorizedException:
return cls.return_login_error('invalid_credentials') return cls.return_registration_msg('invalid_key')
except HepClientException: except HepClientException:
return cls.return_login_error('unknown_error') return cls.return_registration_msg('unknown_error')
user, error_msg = handle_user_and_verify_products(user_data) user, status_msg = handle_user_and_verify_products(user_data)
if error_msg: if status_msg:
return cls.return_login_error(error_msg) return cls.return_registration_msg(status_msg)
return cls(success=False, errors=[]) login(info.context, user)
return cls(success=True, errors=[], message='success')
@classmethod @classmethod
def return_login_error(cls, message): def return_registration_msg(cls, message):
error = RegistrationError(field=message) # even if the user has no valid license treat it like a success
return cls(success=False, errors=[error]) if message == 'unknown_error':
error = RegistrationError(field=message)
return cls(success=False, errors=[error], message='')
return cls(success=True, errors=[], message=message)
class RegistrationMutations: class RegistrationMutations:

View File

@ -7,33 +7,26 @@
# #
# Created on 2019-10-08 # Created on 2019-10-08
# @author: chrigu <christian.cueni@iterativ.ch> # @author: chrigu <christian.cueni@iterativ.ch>
from django.core import mail from unittest.mock import patch
import requests
from django.contrib.sessions.middleware import SessionMiddleware from django.contrib.sessions.middleware import SessionMiddleware
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
from graphene.test import Client from graphene.test import Client
from api.schema import schema from api.schema import schema
from core.hep_client import HepClient from core.hep_client import HepClient
from registration.factories import LicenseTypeFactory, LicenseFactory from core.tests.mock_hep_data_factory import MockResponse, ME_DATA, VALID_TEACHERS_ORDERS
from registration.models import License from registration.models import License
from users.managers import RoleManager from users.models import User, Role, SchoolClass
from users.models import Role, User, UserRole, SchoolClass
class RegistrationTests(TestCase): class RegistrationTests(TestCase):
def setUp(self): def setUp(self):
self.teacher_role = Role.objects.create(key=Role.objects.TEACHER_KEY, name="Teacher Role")
self.student_role = Role.objects.create(key=Role.objects.STUDENT_KEY, name="Student Role")
self.teacher_license_type = LicenseTypeFactory(for_role=self.teacher_role)
self.student_license_type = LicenseTypeFactory(for_role=self.student_role)
self.teacher_license = LicenseFactory(license_type=self.teacher_license_type)
self.student_license = LicenseFactory(license_type=self.student_license_type)
request = RequestFactory().post('/') request = RequestFactory().post('/')
Role.objects.create_default_roles()
self.email = 'sepp@skillbox.iterativ.ch' self.email = 'sepp@skillbox.iterativ.ch'
self.first_name = 'Sepp' self.first_name = 'Sepp'
self.last_name = 'Feuz' self.last_name = 'Feuz'
@ -49,6 +42,7 @@ class RegistrationTests(TestCase):
mutation Registration($input: RegistrationInput!){ mutation Registration($input: RegistrationInput!){
registration(input: $input) { registration(input: $input) {
success success
message
errors { errors {
field field
} }
@ -62,72 +56,40 @@ class RegistrationTests(TestCase):
} }
}) })
# @patch.object(HepClient, 'customer_me', return_value=ME_DATA) @patch.object(HepClient, 'customer_activate', return_value=ME_DATA)
# def test_user_can_register_with_valid_confirmation_key(self, me_mock): @patch.object(HepClient, 'myskillbox_product_for_customer', return_value=None)
# @patch.object(HepClient, 'fetch_admin_token', return_value={'token': 'AABBCCDDEE**44566'})
# self.user.hep_id = ME_DATA['id'] def test_user_can_register_with_valid_confirmation_key_and_no_license(self, admin_mock, product_mock, customer_mock):
# self.user.save()
#
# now = timezone.now()
# expiry_date = now + timedelta(365)
# LicenseFactory(expire_date=expiry_date, licensee=self.user, for_role=self.teacher_role).save()
#
# result = self.make_login_mutation(self.user.email, TOKEN)
#
# self.assertTrue(result.get('data').get('login').get('success'))
# self.assertTrue(self.user.is_authenticated)
# def _assert_user_registration(self, count, email, role_key): result = self.make_register_mutation('CONFIRMATION_KEY')
# users = User.objects.filter(username=self.email)
# self.assertEqual(len(users), count) self.assertTrue(result.get('data').get('registration').get('success'))
# user_roles = UserRole.objects.filter(user__email=email, role__key=role_key) self.assertEqual(result.get('data').get('registration').get('message'), 'no_valid_license')
# self.assertEqual(len(user_roles), count)
# licenses = License.objects.filter(licensee__email=email, license_type__for_role__key=role_key) @patch.object(requests, 'post', return_value=MockResponse(401))
# self.assertEqual(len(licenses), count) def test_user_cannot_register_with_invalid_key(self, confirmation_mock):
#
# def test_user_can_register_as_teacher(self): result = self.make_register_mutation('CONFIRMATION_KEY')
# self._assert_user_registration(0, self.email, RoleManager.TEACHER_KEY)
# school_classes = SchoolClass.objects.filter(name__startswith='Meine Klasse') self.assertTrue(result.get('data').get('registration').get('success'))
# self.assertEqual(len(school_classes), 0) self.assertEqual(result.get('data').get('registration').get('message'), 'invalid_key')
# result = self.make_register_mutation(self.first_name, self.last_name, self.email, self.teacher_license_type.key)
# self.assertTrue(result.get('data').get('registration').get('success')) @patch.object(HepClient, '_customer_orders', return_value=VALID_TEACHERS_ORDERS)
# self._assert_user_registration(1, self.email, RoleManager.TEACHER_KEY) @patch.object(HepClient, 'customer_activate', return_value=ME_DATA)
# school_classes = SchoolClass.objects.filter(name__startswith='Meine Klasse') @patch.object(HepClient, 'fetch_admin_token', return_value={'token': 'AABBCCDDEE**44566'})
# self.assertEqual(len(school_classes), 1) def test_teacher_can_register_with_remote_license(self, order_mock, me_mock, admin_token_mock):
# user = User.objects.get(email=self.email) result = self.make_register_mutation('CONFIRMATION_KEY')
# self.assertTrue(school_classes[0].is_user_in_schoolclass(user))
# self.assertEqual(len(mail.outbox), 1) user = User.objects.get(email=ME_DATA['email'])
# self.assertEqual(mail.outbox[0].subject, 'Myskillbox: E-Mail bestätigen und Passwort setzen')
# user_role_key = user.user_roles.get(user=user).role.key
# def test_user_can_register_as_student(self): self.assertEqual(user_role_key, Role.objects.TEACHER_KEY)
# self._assert_user_registration(0, self.email, RoleManager.STUDENT_KEY)
# result = self.make_register_mutation(self.first_name, self.last_name, self.email, self.student_license_type.key) license = License.objects.get(licensee=user)
# self.assertTrue(result.get('data').get('registration').get('success')) self.assertEqual(license.for_role.key, Role.objects.TEACHER_KEY)
# self._assert_user_registration(1, self.email, RoleManager.STUDENT_KEY)
# school_class = SchoolClass.objects.get(users__in=[user])
# def test_existing_user_cannot_register(self): self.assertIsNotNone(school_class)
# self._assert_user_registration(0, self.email, RoleManager.STUDENT_KEY)
# self.make_register_mutation(self.first_name, self.last_name, self.email, self.student_license_type.key) self.assertTrue(result.get('data').get('registration').get('success'))
# result = self.make_register_mutation(self.first_name, self.last_name, self.email, self.student_license_type.key) self.assertTrue(user.is_authenticated)
# self.assertEqual(result.get('data').get('registration').get('errors')[0].get('field'), 'email')
#
# def test_existing_user_cannot_register_with_uppercase_email(self):
# self._assert_user_registration(0, self.email, RoleManager.STUDENT_KEY)
# self.make_register_mutation(self.first_name, self.last_name, self.email.upper(), self.student_license_type.key)
# result = self.make_register_mutation(self.first_name, self.last_name, self.email, self.student_license_type.key)
# self.assertEqual(result.get('data').get('registration').get('errors')[0].get('field'), 'email')
#
# def test_user_cannot_register_if_firstname_is_missing(self):
# result = self.make_register_mutation('', self.last_name, self.email, self.teacher_license_type.key)
# self.assertEqual(result.get('data').get('registration').get('errors')[0].get('field'), 'first_name')
# self.assertFalse(result.get('data').get('registration').get('success'))
#
# def test_user_cannot_register_if_lastname_is_missing(self):
# result = self.make_register_mutation(self.first_name, '', self.email, self.teacher_license_type.key)
# self.assertEqual(result.get('data').get('registration').get('errors')[0].get('field'), 'last_name')
# self.assertFalse(result.get('data').get('registration').get('success'))
#
# def test_user_cannot_register_if_email_is_missing(self):
# result = self.make_register_mutation(self.first_name, self.last_name, '', self.teacher_license_type.key)
# self.assertEqual(result.get('data').get('registration').get('errors')[0].get('field'), 'email')
# self.assertFalse(result.get('data').get('registration').get('success'))

View File

@ -21,55 +21,14 @@ from graphene.test import Client
from api.schema_public import schema from api.schema_public import schema
from core.factories import UserFactory from core.factories import UserFactory
from core.hep_client import HepClient from core.hep_client import HepClient
from core.tests.mock_hep_data_factory import MockResponse, ME_DATA, VALID_STUDENT_ORDERS, VALID_TEACHERS_ORDERS, \
NOT_CONFIRMED_ME
from registration.factories import LicenseFactory from registration.factories import LicenseFactory
from registration.models import License from registration.models import License
from users.models import Role, MagentoToken, User, SchoolClass from users.models import Role, User, SchoolClass
TOKEN = 'abcd12345!' TOKEN = 'abcd12345!'
## Setup json data
def make_orders_valid(order_items):
for order_item in order_items['items']:
if 'created_at' in order_item:
yesterday = datetime.now() - timedelta(1)
order_item['created_at'] = datetime.strftime(yesterday, '%Y-%m-%d %H:%M:%S')
return order_items
# Load data
dir_path = os.path.dirname(os.path.realpath(__file__))
with open('{}/test_data/valid_teacher_orders.json'.format(dir_path), 'r') as file:
valid_teacher_order_data = file.read()
with open('{}/test_data/valid_student_orders.json'.format(dir_path), 'r') as file:
valid_student_order_data = file.read()
with open('{}/test_data/me_data.json'.format(dir_path), 'r') as file:
me_data = file.read()
with open('{}/test_data/email_not_confirmed_me.json'.format(dir_path), 'r') as file:
not_confirmed_email_me_data = file.read()
ME_DATA = json.loads(me_data)
NOT_CONFIRMED_ME = json.loads(not_confirmed_email_me_data)
valid_teacher_order_items = json.loads(valid_teacher_order_data)
VALID_TEACHERS_ORDERS = make_orders_valid(valid_teacher_order_items)
valid_student_order_items = json.loads(valid_student_order_data)
VALID_STUDENT_ORDERS = make_orders_valid(valid_student_order_items)
## Mocks
class MockResponse:
def __init__(self, status_code):
self.status_code = status_code
def json(self):
return {}
class PasswordResetTests(TestCase): class PasswordResetTests(TestCase):

View File

@ -24,7 +24,7 @@ def handle_user_and_verify_products(user_data):
except User.DoesNotExist: except User.DoesNotExist:
user = User.objects.create_user_from_hep(user_data) user = User.objects.create_user_from_hep(user_data)
# todo check if email has changed # todo check if email has changed, any impact on our system?
try: try:
if not hep_client.is_email_verified(user_data): if not hep_client.is_email_verified(user_data):