Add join team mutation

This commit is contained in:
Ramon Wenger 2021-03-25 00:13:43 +01:00
parent 4e1ab68a52
commit a4ff9d2942
4 changed files with 116 additions and 13 deletions

View File

@ -347,6 +347,17 @@ type CreateSchoolClassPayload {
clientMutationId: String clientMutationId: String
} }
input CreateTeamInput {
name: String!
clientMutationId: String
}
type CreateTeamPayload {
success: Boolean
team: TeamNode
clientMutationId: String
}
type CustomMutation { type CustomMutation {
redeemCoupon(input: CouponInput!): CouponPayload redeemCoupon(input: CouponInput!): CouponPayload
spellCheck(input: SpellCheckInput!): SpellCheckPayload spellCheck(input: SpellCheckInput!): SpellCheckPayload
@ -365,6 +376,8 @@ type CustomMutation {
updateSchoolClass(input: UpdateSchoolClassInput!): UpdateSchoolClassPayload updateSchoolClass(input: UpdateSchoolClassInput!): UpdateSchoolClassPayload
createSchoolClass(input: CreateSchoolClassInput!): CreateSchoolClassPayload createSchoolClass(input: CreateSchoolClassInput!): CreateSchoolClassPayload
updateOnboardingProgress: UpdateOnboardingProgress updateOnboardingProgress: UpdateOnboardingProgress
createTeam(input: CreateTeamInput!): CreateTeamPayload
joinTeam(input: JoinTeamInput!): JoinTeamPayload
addProject(input: AddProjectInput!): AddProjectPayload addProject(input: AddProjectInput!): AddProjectPayload
updateProject(input: UpdateProjectInput!): UpdateProjectPayload updateProject(input: UpdateProjectInput!): UpdateProjectPayload
deleteProject(input: DeleteProjectInput!): DeleteProjectPayload deleteProject(input: DeleteProjectInput!): DeleteProjectPayload
@ -578,6 +591,17 @@ type JoinClassPayload {
clientMutationId: String clientMutationId: String
} }
input JoinTeamInput {
code: String!
clientMutationId: String
}
type JoinTeamPayload {
success: Boolean
team: TeamNode
clientMutationId: String
}
type Logout { type Logout {
success: Boolean success: Boolean
} }
@ -803,8 +827,8 @@ type SchoolClassNode implements Node {
id: ID! id: ID!
name: String! name: String!
isDeleted: Boolean! isDeleted: Boolean!
users(offset: Int, before: String, after: String, first: Int, last: Int, username: String, email: String): UserNodeConnection!
code: String code: String
users(offset: Int, before: String, after: String, first: Int, last: Int, username: String, email: String): UserNodeConnection!
moduleSet(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, slug_Icontains: String, slug_In: [String], title: String, title_Icontains: String, title_In: [String]): ModuleNodeConnection! moduleSet(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, slug_Icontains: String, slug_In: [String], title: String, title_Icontains: String, title_In: [String]): ModuleNodeConnection!
hiddenChapterTitles(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection! hiddenChapterTitles(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection!
hiddenChapterDescriptions(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection! hiddenChapterDescriptions(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection!
@ -920,6 +944,16 @@ type SyncModuleVisibilityPayload {
clientMutationId: String clientMutationId: String
} }
type TeamNode implements Node {
name: String!
isDeleted: Boolean!
code: String
id: ID!
creator: UserNode
members: [UserNode]
pk: Int
}
type TopicConnection { type TopicConnection {
pageInfo: PageInfo! pageInfo: PageInfo!
edges: [TopicEdge]! edges: [TopicEdge]!
@ -1280,6 +1314,7 @@ type UserNode implements Node {
avatarUrl: String! avatarUrl: String!
email: String! email: String!
onboardingVisited: Boolean! onboardingVisited: Boolean!
team: TeamNode
schoolClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection! schoolClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
id: ID! id: ID!
pk: Int pk: Int

View File

@ -37,6 +37,7 @@ class TeamFactory(factory.django.DjangoModelFactory):
model = Team model = Team
name = factory.Faker('name') name = factory.Faker('name')
code = factory.Sequence(lambda n: "CODE{}".format(n))
is_deleted = False is_deleted = False

View File

@ -132,7 +132,7 @@ class JoinClass(relay.ClientIDMutation):
return cls(success=True, school_class=school_class) return cls(success=True, school_class=school_class)
except SchoolClass.DoesNotExist: except SchoolClass.DoesNotExist:
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CAV = Code Not Valid raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
class AddRemoveMember(relay.ClientIDMutation): class AddRemoveMember(relay.ClientIDMutation):
@ -211,7 +211,7 @@ class CreateSchoolClass(relay.ClientIDMutation):
class CreateTeam(relay.ClientIDMutation): class CreateTeam(relay.ClientIDMutation):
class Input: class Input:
name = graphene.String() name = graphene.String(required=True)
success = graphene.Boolean() success = graphene.Boolean()
team = graphene.Field(TeamNode) team = graphene.Field(TeamNode)
@ -231,6 +231,27 @@ class CreateTeam(relay.ClientIDMutation):
return cls(success=True, team=team) return cls(success=True, team=team)
class JoinTeam(relay.ClientIDMutation):
class Input:
code = graphene.String(required=True)
success = graphene.Boolean()
team = graphene.Field(TeamNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
code = kwargs.get('code')
try:
team = Team.objects.get(Q(code__iexact=code))
user.team = team
user.save()
return cls(success=True, team=team)
except Team.DoesNotExist:
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
class UpdateOnboardingProgress(graphene.Mutation): class UpdateOnboardingProgress(graphene.Mutation):
success = graphene.Boolean() success = graphene.Boolean()
@ -254,3 +275,4 @@ class ProfileMutations:
create_school_class = CreateSchoolClass.Field() create_school_class = CreateSchoolClass.Field()
update_onboarding_progress = UpdateOnboardingProgress.Field() update_onboarding_progress = UpdateOnboardingProgress.Field()
create_team = CreateTeam.Field() create_team = CreateTeam.Field()
join_team = JoinTeam.Field()

View File

@ -3,10 +3,8 @@ from graphene import Context
from graphene.test import Client from graphene.test import Client
from api.schema import schema from api.schema import schema
from core.factories import UserFactory, TeacherFactory from core.factories import TeacherFactory
from users.factories import TeamFactory from users.factories import TeamFactory
from users.models import Role
from users.services import create_teacher
ME_QUERY = """ ME_QUERY = """
query MeQuery { query MeQuery {
@ -31,6 +29,18 @@ CREATE_MUTATION = """
} }
""" """
JOIN_TEAM_MUTATION = """
mutation JoinTeamMutation($input: JoinTeamInput!) {
joinTeam(input: $input) {
success
team {
name
code
}
}
}
"""
class TeamTest(TestCase): class TeamTest(TestCase):
def setUp(self): def setUp(self):
@ -41,15 +51,50 @@ class TeamTest(TestCase):
self.user = TeacherFactory(username='ueli', team=self.team) self.user = TeacherFactory(username='ueli', team=self.team)
self.context = Context(user=self.user) self.context = Context(user=self.user)
def test_team_query(self): @staticmethod
result = self.client.execute(ME_QUERY, context=self.context) def get_team(result):
return result.get('data').get('me').get('team')
def no_error(self, result):
self.assertIsNone(result.get('errors')) self.assertIsNone(result.get('errors'))
team = result.get('data').get('me').get('team')
self.assertEqual(team.get('name'), self.team_name) def check_me(self, context, name, code):
self.assertEqual(team.get('code'), self.code) result = self.client.execute(ME_QUERY, context=context)
self.no_error(result)
team = self.get_team(result)
self.assertEqual(team.get('name'), name)
self.assertEqual(team.get('code'), code)
def join_team(self, code, context):
variables = {
"input": {
"code": code
}
}
result = self.client.execute(JOIN_TEAM_MUTATION, variables=variables, context=context)
self.no_error(result)
success = result['data']['joinTeam']['success']
self.assertTrue(success)
def test_team_query(self):
self.check_me(self.context, self.team_name, self.code)
def test_join_team_mutation(self): def test_join_team_mutation(self):
raise NotImplementedError() teacher = TeacherFactory(username='hansli')
context = Context(user=teacher)
self.join_team(self.code, context)
self.check_me(context, self.team_name, self.code)
def test_join_second_team_mutation(self):
teacher = TeacherFactory(username='peterli')
context = Context(user=teacher)
second_team = TeamFactory()
self.join_team(self.code, context)
self.check_me(context, self.team_name, self.code)
self.join_team(second_team.code, context)
self.check_me(context, second_team.name, second_team.code)
def test_create_team_mutation(self): def test_create_team_mutation(self):
team_name = "Dunder Mifflin" team_name = "Dunder Mifflin"
@ -59,7 +104,7 @@ class TeamTest(TestCase):
} }
} }
result = self.client.execute(CREATE_MUTATION, context=self.context, variables=variables) result = self.client.execute(CREATE_MUTATION, context=self.context, variables=variables)
self.assertIsNone(result.get('errors')) self.no_error(result)
create_team = result.get('data').get('createTeam') create_team = result.get('data').get('createTeam')
team = create_team.get('team') team = create_team.get('team')
success = create_team.get('success') success = create_team.get('success')