Update error handling in mutation for school class creation
This commit is contained in:
parent
d09844a67b
commit
4973037486
|
|
@ -1,9 +1,14 @@
|
||||||
mutation CreateSchoolClass($input: CreateSchoolClassInput!) {
|
mutation CreateSchoolClass($input: CreateSchoolClassInput!) {
|
||||||
createSchoolClass(input: $input) {
|
createSchoolClass(input: $input) {
|
||||||
success
|
result {
|
||||||
schoolClass {
|
__typename
|
||||||
|
...on SchoolClassNode {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
...on DuplicateName {
|
||||||
|
reason
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ from surveys.schema import SurveysQuery
|
||||||
from surveys.mutations import SurveyMutations
|
from surveys.mutations import SurveyMutations
|
||||||
from rooms.mutations import RoomMutations
|
from rooms.mutations import RoomMutations
|
||||||
from rooms.schema import RoomsQuery, ModuleRoomsQuery
|
from rooms.schema import RoomsQuery, ModuleRoomsQuery
|
||||||
from users.schema import AllUsersQuery, UsersQuery
|
from users.schema import AllUsersQuery, UsersQuery, ProfileMutations
|
||||||
from users.mutations import ProfileMutations
|
|
||||||
|
|
||||||
|
|
||||||
class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery,
|
class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import graphene
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from graphene_django.debug import DjangoDebug
|
from graphene_django.debug import DjangoDebug
|
||||||
|
|
||||||
from users.mutations_public import UserMutations
|
from users.schema import UserMutations
|
||||||
|
|
||||||
|
|
||||||
class PublicMutation(UserMutations, graphene.ObjectType):
|
class PublicMutation(UserMutations, graphene.ObjectType):
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import graphene
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
|
||||||
|
from api.graphene_wagtail import GenericStreamFieldType
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from notes.models import InstrumentBookmark
|
from notes.models import InstrumentBookmark
|
||||||
from notes.schema import InstrumentBookmarkNode
|
from notes.schema import InstrumentBookmarkNode
|
||||||
|
|
@ -25,6 +26,7 @@ class InstrumentTypeNode(DjangoObjectType):
|
||||||
class InstrumentNode(DjangoObjectType):
|
class InstrumentNode(DjangoObjectType):
|
||||||
bookmarks = graphene.List(InstrumentBookmarkNode)
|
bookmarks = graphene.List(InstrumentBookmarkNode)
|
||||||
type = graphene.Field(InstrumentTypeNode)
|
type = graphene.Field(InstrumentTypeNode)
|
||||||
|
contents = GenericStreamFieldType()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = BasicKnowledge
|
model = BasicKnowledge
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class Module(StrictHierarchyPage):
|
||||||
parent_page_types = ['books.Topic']
|
parent_page_types = ['books.Topic']
|
||||||
subpage_types = ['books.Chapter']
|
subpage_types = ['books.Chapter']
|
||||||
|
|
||||||
|
#todo: isn't this a duplicate definition?
|
||||||
def get_child_ids(self):
|
def get_child_ids(self):
|
||||||
return self.get_children().values_list('id', flat=True)
|
return self.get_children().values_list('id', flat=True)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,5 +29,3 @@ class SkillboxTestCase(TestCase):
|
||||||
user = self.teacher
|
user = self.teacher
|
||||||
request.user = user
|
request.user = user
|
||||||
return GQLClient(schema=schema, context_value=request)
|
return GQLClient(schema=schema, context_value=request)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,9 +181,9 @@ input AssignmentInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssignmentNode implements Node {
|
type AssignmentNode implements Node {
|
||||||
|
id: ID!
|
||||||
created: DateTime!
|
created: DateTime!
|
||||||
modified: DateTime!
|
modified: DateTime!
|
||||||
id: ID!
|
|
||||||
title: String!
|
title: String!
|
||||||
assignment: String!
|
assignment: String!
|
||||||
solution: String
|
solution: String
|
||||||
|
|
@ -197,9 +197,9 @@ type AssignmentNode implements Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChapterBookmarkNode implements Node {
|
type ChapterBookmarkNode implements Node {
|
||||||
|
id: ID!
|
||||||
user: PrivateUserNode!
|
user: PrivateUserNode!
|
||||||
note: NoteNode
|
note: NoteNode
|
||||||
id: ID!
|
|
||||||
chapter: ChapterNode!
|
chapter: ChapterNode!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,11 +343,12 @@ input CreateSchoolClassInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateSchoolClassPayload {
|
type CreateSchoolClassPayload {
|
||||||
success: Boolean
|
result: CreateSchoolClassResult
|
||||||
schoolClass: SchoolClassNode
|
|
||||||
clientMutationId: String
|
clientMutationId: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union CreateSchoolClassResult = SchoolClassNode | DuplicateName
|
||||||
|
|
||||||
input CreateSnapshotInput {
|
input CreateSnapshotInput {
|
||||||
module: String!
|
module: String!
|
||||||
selectedClass: ID!
|
selectedClass: ID!
|
||||||
|
|
@ -463,6 +464,10 @@ type DjangoDebugSQL {
|
||||||
encoding: String
|
encoding: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DuplicateName {
|
||||||
|
reason: String
|
||||||
|
}
|
||||||
|
|
||||||
type FieldError {
|
type FieldError {
|
||||||
code: String
|
code: String
|
||||||
}
|
}
|
||||||
|
|
@ -482,9 +487,9 @@ enum InputTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstrumentBookmarkNode implements Node {
|
type InstrumentBookmarkNode implements Node {
|
||||||
|
id: ID!
|
||||||
user: PrivateUserNode!
|
user: PrivateUserNode!
|
||||||
note: NoteNode
|
note: NoteNode
|
||||||
id: ID!
|
|
||||||
uuid: UUID
|
uuid: UUID
|
||||||
instrument: InstrumentNode!
|
instrument: InstrumentNode!
|
||||||
}
|
}
|
||||||
|
|
@ -555,9 +560,9 @@ type Logout {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleBookmarkNode {
|
type ModuleBookmarkNode {
|
||||||
|
id: ID!
|
||||||
user: PrivateUserNode!
|
user: PrivateUserNode!
|
||||||
note: NoteNode
|
note: NoteNode
|
||||||
id: ID!
|
|
||||||
module: ModuleNode!
|
module: ModuleNode!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -869,10 +874,10 @@ type Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomEntryNode implements Node {
|
type RoomEntryNode implements Node {
|
||||||
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
description: String
|
description: String
|
||||||
slug: String!
|
slug: String!
|
||||||
id: ID!
|
|
||||||
room: RoomNode!
|
room: RoomNode!
|
||||||
author: PublicUserNode
|
author: PublicUserNode
|
||||||
contents: GenericStreamFieldType
|
contents: GenericStreamFieldType
|
||||||
|
|
@ -891,10 +896,10 @@ type RoomEntryNodeEdge {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoomNode implements Node {
|
type RoomNode implements Node {
|
||||||
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
description: String
|
description: String
|
||||||
slug: String!
|
slug: String!
|
||||||
id: ID!
|
|
||||||
schoolClass: SchoolClassNode!
|
schoolClass: SchoolClassNode!
|
||||||
appearance: String!
|
appearance: String!
|
||||||
userCreated: Boolean!
|
userCreated: Boolean!
|
||||||
|
|
@ -1017,9 +1022,9 @@ type SpellCheckStepNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
type StudentSubmissionNode implements Node {
|
type StudentSubmissionNode implements Node {
|
||||||
|
id: ID!
|
||||||
created: DateTime!
|
created: DateTime!
|
||||||
modified: DateTime!
|
modified: DateTime!
|
||||||
id: ID!
|
|
||||||
text: String!
|
text: String!
|
||||||
document: String!
|
document: String!
|
||||||
assignment: AssignmentNode!
|
assignment: AssignmentNode!
|
||||||
|
|
@ -1088,10 +1093,10 @@ type SyncModuleVisibilityPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TeamNode implements Node {
|
type TeamNode implements Node {
|
||||||
name: String!
|
|
||||||
code: String
|
|
||||||
id: ID!
|
id: ID!
|
||||||
|
name: String!
|
||||||
isDeleted: Boolean!
|
isDeleted: Boolean!
|
||||||
|
code: String
|
||||||
creator: PrivateUserNode
|
creator: PrivateUserNode
|
||||||
members: [PublicUserNode]
|
members: [PublicUserNode]
|
||||||
pk: Int
|
pk: Int
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .queries import *
|
||||||
|
from .types import *
|
||||||
|
from .mutations import *
|
||||||
|
from .mutations_public import *
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import graphene
|
import graphene
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.db import IntegrityError
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
from graphql_relay import from_global_id
|
from graphql_relay import from_global_id
|
||||||
|
|
@ -9,8 +10,9 @@ from api.utils import get_object
|
||||||
from core.logger import get_logger
|
from core.logger import get_logger
|
||||||
from users.inputs import PasswordUpdateInput
|
from users.inputs import PasswordUpdateInput
|
||||||
from users.models import SchoolClass, SchoolClassMember, Team
|
from users.models import SchoolClass, SchoolClassMember, Team
|
||||||
from users.schema import SchoolClassNode, TeamNode
|
from users.schema import SchoolClassNode, TeamNode, UpdateError, FieldError, CreateSchoolClassResult
|
||||||
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
|
from users.serializers import AvatarUrlSerializer, PasswordSerialzer
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -19,15 +21,6 @@ class CodeNotFoundException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FieldError(graphene.ObjectType):
|
|
||||||
code = graphene.String()
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateError(graphene.ObjectType):
|
|
||||||
field = graphene.String()
|
|
||||||
errors = graphene.List(FieldError)
|
|
||||||
|
|
||||||
|
|
||||||
class TeacherOnlyMutation(relay.ClientIDMutation):
|
class TeacherOnlyMutation(relay.ClientIDMutation):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
@ -204,18 +197,20 @@ class CreateSchoolClass(TeacherOnlyMutation):
|
||||||
class Input:
|
class Input:
|
||||||
name = graphene.String()
|
name = graphene.String()
|
||||||
|
|
||||||
success = graphene.Boolean()
|
result = CreateSchoolClassResult()
|
||||||
school_class = graphene.Field(SchoolClassNode)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
name = kwargs.get('name')
|
name = kwargs.get('name')
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
|
try:
|
||||||
school_class = SchoolClass.objects.create(name=name)
|
school_class = SchoolClass.objects.create(name=name)
|
||||||
SchoolClassMember.objects.create(school_class=school_class, user=user)
|
SchoolClassMember.objects.create(school_class=school_class, user=user)
|
||||||
user.set_selected_class(school_class)
|
user.set_selected_class(school_class)
|
||||||
return cls(success=True, school_class=school_class)
|
return cls(result=school_class)
|
||||||
|
except IntegrityError:
|
||||||
|
return cls(result={"reason": "Name wird bereits verwendet"})
|
||||||
|
|
||||||
|
|
||||||
class CreateTeam(TeacherOnlyMutation):
|
class CreateTeam(TeacherOnlyMutation):
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import graphene
|
||||||
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
|
|
||||||
|
from basicknowledge.models import BasicKnowledge
|
||||||
|
from basicknowledge.queries import InstrumentNode
|
||||||
|
from books.models import Module
|
||||||
|
from books.schema.queries import ModuleNode
|
||||||
|
from users.models import User
|
||||||
|
|
||||||
|
from .types import PrivateUserNode
|
||||||
|
|
||||||
|
|
||||||
|
class UsersQuery(object):
|
||||||
|
me = graphene.Field(PrivateUserNode)
|
||||||
|
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
||||||
|
my_activity = DjangoFilterConnectionField(ModuleNode)
|
||||||
|
my_instrument_activity = DjangoFilterConnectionField(InstrumentNode)
|
||||||
|
|
||||||
|
def resolve_me(self, info, **kwargs):
|
||||||
|
return info.context.user
|
||||||
|
|
||||||
|
def resolve_all_users(self, info, **kwargs):
|
||||||
|
if not info.context.user.is_superuser:
|
||||||
|
return User.objects.none()
|
||||||
|
else:
|
||||||
|
return User.objects.all()
|
||||||
|
|
||||||
|
def resolve_my_activity(self, info, **kwargs):
|
||||||
|
return Module.objects.all()
|
||||||
|
|
||||||
|
def resolve_my_instrument_activity(self, info, **kwargs):
|
||||||
|
return BasicKnowledge.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
class AllUsersQuery(object):
|
||||||
|
me = graphene.Field(PrivateUserNode)
|
||||||
|
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
||||||
|
|
||||||
|
def resolve_all_users(self, info, **kwargs):
|
||||||
|
if not info.context.user.is_superuser:
|
||||||
|
return User.objects.none()
|
||||||
|
else:
|
||||||
|
return User.objects.all()
|
||||||
|
|
@ -9,13 +9,23 @@ from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
from basicknowledge.models import BasicKnowledge
|
|
||||||
from basicknowledge.queries import InstrumentNode
|
|
||||||
from books.models import Module
|
from books.models import Module
|
||||||
from books.schema.queries import ModuleNode
|
from books.schema.queries import ModuleNode
|
||||||
from users.models import SchoolClass, SchoolClassMember, Team, User
|
from users.models import SchoolClass, SchoolClassMember, Team, User
|
||||||
|
|
||||||
|
|
||||||
|
class RecentModuleFilter(FilterSet):
|
||||||
|
class Meta:
|
||||||
|
model = Module
|
||||||
|
fields = ('recent_modules',)
|
||||||
|
|
||||||
|
order_by = OrderingFilter(
|
||||||
|
fields=(
|
||||||
|
('recent_modules__visited', 'visited'),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SchoolClassNode(DjangoObjectType):
|
class SchoolClassNode(DjangoObjectType):
|
||||||
pk = graphene.Int()
|
pk = graphene.Int()
|
||||||
members = graphene.List('users.schema.ClassMemberNode')
|
members = graphene.List('users.schema.ClassMemberNode')
|
||||||
|
|
@ -64,18 +74,6 @@ class TeamNode(DjangoObjectType):
|
||||||
return self.members.all()
|
return self.members.all()
|
||||||
|
|
||||||
|
|
||||||
class RecentModuleFilter(FilterSet):
|
|
||||||
class Meta:
|
|
||||||
model = Module
|
|
||||||
fields = ('recent_modules',)
|
|
||||||
|
|
||||||
order_by = OrderingFilter(
|
|
||||||
fields=(
|
|
||||||
('recent_modules__visited', 'visited'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PublicUserNode(DjangoObjectType):
|
class PublicUserNode(DjangoObjectType):
|
||||||
full_name = graphene.String(required=True)
|
full_name = graphene.String(required=True)
|
||||||
is_me = graphene.Boolean()
|
is_me = graphene.Boolean()
|
||||||
|
|
@ -184,34 +182,25 @@ class ClassMemberNode(ObjectType):
|
||||||
return info.context.user.pk == parent.user.pk
|
return info.context.user.pk == parent.user.pk
|
||||||
|
|
||||||
|
|
||||||
class UsersQuery(object):
|
class DuplicateName(graphene.ObjectType):
|
||||||
me = graphene.Field(PrivateUserNode)
|
reason = graphene.String()
|
||||||
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
|
||||||
my_activity = DjangoFilterConnectionField(ModuleNode)
|
|
||||||
my_instrument_activity = DjangoFilterConnectionField(InstrumentNode)
|
|
||||||
|
|
||||||
def resolve_me(self, info, **kwargs):
|
|
||||||
return info.context.user
|
|
||||||
|
|
||||||
def resolve_all_users(self, info, **kwargs):
|
|
||||||
if not info.context.user.is_superuser:
|
|
||||||
return User.objects.none()
|
|
||||||
else:
|
|
||||||
return User.objects.all()
|
|
||||||
|
|
||||||
def resolve_my_activity(self, info, **kwargs):
|
|
||||||
return Module.objects.all()
|
|
||||||
|
|
||||||
def resolve_my_instrument_activity(self, info, **kwargs):
|
|
||||||
return BasicKnowledge.objects.all()
|
|
||||||
|
|
||||||
|
|
||||||
class AllUsersQuery(object):
|
class CreateSchoolClassResult(graphene.Union):
|
||||||
me = graphene.Field(PrivateUserNode)
|
class Meta:
|
||||||
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
types = (SchoolClassNode, DuplicateName)
|
||||||
|
|
||||||
def resolve_all_users(self, info, **kwargs):
|
@classmethod
|
||||||
if not info.context.user.is_superuser:
|
def resolve_type(cls, instance, info):
|
||||||
return User.objects.none()
|
if type(instance).__name__ == "SchoolClass":
|
||||||
else:
|
return SchoolClassNode
|
||||||
return User.objects.all()
|
return DuplicateName
|
||||||
|
|
||||||
|
|
||||||
|
class FieldError(graphene.ObjectType):
|
||||||
|
code = graphene.String()
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateError(graphene.ObjectType):
|
||||||
|
field = graphene.String()
|
||||||
|
errors = graphene.List(FieldError)
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
from django.test import TestCase, RequestFactory
|
from django.db import transaction
|
||||||
|
from django.test import TestCase
|
||||||
from graphene import Context
|
from graphene import Context
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
from api.schema import schema
|
from api.schema import schema
|
||||||
from api.utils import get_graphql_mutation, get_object
|
from api.utils import get_graphql_mutation, get_object
|
||||||
from core.factories import UserFactory, TeacherFactory
|
from core.factories import TeacherFactory, UserFactory
|
||||||
from core.tests.base_test import SkillboxTestCase
|
from core.tests.base_test import SkillboxTestCase
|
||||||
from users.models import SchoolClass, User
|
from users.models import SchoolClass, User
|
||||||
from users.services import create_users
|
from users.services import create_users
|
||||||
|
|
@ -101,20 +102,41 @@ class ModifySchoolClassTest(SkillboxTestCase):
|
||||||
self.assertEqual(SchoolClass.objects.count(), 2)
|
self.assertEqual(SchoolClass.objects.count(), 2)
|
||||||
class_name = 'Moordale'
|
class_name = 'Moordale'
|
||||||
mutation = get_graphql_mutation('createClass.gql')
|
mutation = get_graphql_mutation('createClass.gql')
|
||||||
result = self.client.execute(mutation, variables={
|
query_result = self.client.execute(mutation, variables={
|
||||||
'input': {
|
'input': {
|
||||||
'name': class_name
|
'name': class_name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self.assertIsNone(result.get('errors'))
|
self.assertIsNone(query_result.get('errors'))
|
||||||
id = result.get('data').get('createSchoolClass').get('schoolClass').get('id')
|
result = query_result.get('data').get('createSchoolClass').get('result')
|
||||||
|
self.assertEqual(result.get('__typename'), 'SchoolClassNode')
|
||||||
|
id = result.get('id')
|
||||||
self.assertEqual(SchoolClass.objects.count(), 3)
|
self.assertEqual(SchoolClass.objects.count(), 3)
|
||||||
school_class = get_object(SchoolClass, id)
|
school_class = get_object(SchoolClass, id)
|
||||||
self.assertEqual(school_class.name, class_name)
|
self.assertEqual(school_class.name, class_name)
|
||||||
self.assertEqual(school_class.get_teacher(), self.teacher)
|
self.assertEqual(school_class.get_teacher(), self.teacher)
|
||||||
self.assertEqual(self.teacher.selected_class.name, class_name)
|
self.assertEqual(self.teacher.selected_class.name, class_name)
|
||||||
|
|
||||||
def test_create_school_class_fail(self):
|
def test_create_school_class_duplicate_name_fail(self):
|
||||||
|
self.assertEqual(SchoolClass.objects.count(), 2)
|
||||||
|
class_name = 'skillbox'
|
||||||
|
mutation = get_graphql_mutation('createClass.gql')
|
||||||
|
# if we don't do this, django wraps the whole test in an atomic operation,
|
||||||
|
# and we trigger an exception so the query later in the test would fail
|
||||||
|
with transaction.atomic():
|
||||||
|
query_result = self.client.execute(mutation, variables={
|
||||||
|
'input': {
|
||||||
|
'name': class_name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertIsNone(query_result.get('errors'))
|
||||||
|
result = query_result.get('data').get('createSchoolClass').get('result')
|
||||||
|
self.assertEqual(result.get('__typename'), 'DuplicateName')
|
||||||
|
reason = result.get('reason')
|
||||||
|
self.assertEqual(reason, 'Name wird bereits verwendet')
|
||||||
|
self.assertEqual(SchoolClass.objects.count(), 2)
|
||||||
|
|
||||||
|
def test_create_school_class_fail_permission(self):
|
||||||
self.assertEqual(SchoolClass.objects.count(), 2)
|
self.assertEqual(SchoolClass.objects.count(), 2)
|
||||||
mutation = get_graphql_mutation('createClass.gql')
|
mutation = get_graphql_mutation('createClass.gql')
|
||||||
result = self.student_client.execute(mutation, variables={
|
result = self.student_client.execute(mutation, variables={
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue