Change "invalid_coupon" error into a result
This commit is contained in:
parent
5e78d08c48
commit
d1664592ce
|
|
@ -7,3 +7,8 @@ class FailureNode(graphene.Interface):
|
|||
|
||||
class SuccessNode(graphene.Interface):
|
||||
message = graphene.String()
|
||||
|
||||
|
||||
class Success(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (SuccessNode,)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import graphene
|
||||
from graphene import relay
|
||||
|
||||
from api.types import FailureNode, SuccessNode
|
||||
from api.types import FailureNode, Success
|
||||
from api.utils import get_object
|
||||
from books.models import Module, ContentBlock, Chapter
|
||||
from books.models.snapshot import Snapshot
|
||||
|
|
@ -14,23 +14,24 @@ class NotOwner(graphene.ObjectType):
|
|||
interfaces = (FailureNode,)
|
||||
|
||||
|
||||
class Success(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (SuccessNode,)
|
||||
|
||||
|
||||
NotOwnerFailure = NotOwner(reason="Not the owner")
|
||||
DeleteSnapshotSuccess = Success(message='Snapshot deleted successfully')
|
||||
DeleteSnapshotSuccess = Success(message="Snapshot deleted successfully")
|
||||
|
||||
|
||||
class UpdateSnapshotResult(graphene.Union):
|
||||
class Meta:
|
||||
types = (SnapshotNode, NotOwner,)
|
||||
types = (
|
||||
SnapshotNode,
|
||||
NotOwner,
|
||||
)
|
||||
|
||||
|
||||
class DeleteSnapshotResult(graphene.Union):
|
||||
class Meta:
|
||||
types = (Success, NotOwner,)
|
||||
types = (
|
||||
Success,
|
||||
NotOwner,
|
||||
)
|
||||
|
||||
|
||||
class CreateSnapshot(relay.ClientIDMutation):
|
||||
|
|
@ -43,12 +44,12 @@ class CreateSnapshot(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
module_slug = args.get('module')
|
||||
module_slug = args.get("module")
|
||||
module = Module.objects.get(slug=module_slug)
|
||||
user = info.context.user
|
||||
# todo: check user
|
||||
# raise NotImplementedError('Permissions')
|
||||
selected_class_id = args.get('selected_class')
|
||||
selected_class_id = args.get("selected_class")
|
||||
selected_class = get_object(SchoolClass, selected_class_id)
|
||||
snapshot = Snapshot.objects.create_snapshot(module, selected_class, user)
|
||||
return cls(snapshot=snapshot, success=True)
|
||||
|
|
@ -63,8 +64,8 @@ class UpdateSnapshot(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
id = args.get('id')
|
||||
title = args.get('title')
|
||||
id = args.get("id")
|
||||
title = args.get("title")
|
||||
user = info.context.user
|
||||
|
||||
snapshot = get_object(Snapshot, id)
|
||||
|
|
@ -84,7 +85,7 @@ class DeleteSnapshot(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
id = args.get('id')
|
||||
id = args.get("id")
|
||||
user = info.context.user
|
||||
|
||||
snapshot = get_object(Snapshot, id)
|
||||
|
|
@ -105,14 +106,17 @@ class ApplySnapshot(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
snapshot_id = args.get('snapshot')
|
||||
snapshot_id = args.get("snapshot")
|
||||
snapshot = get_object(Snapshot, snapshot_id)
|
||||
user = info.context.user
|
||||
selected_class_id = args.get('selected_class')
|
||||
selected_class_id = args.get("selected_class")
|
||||
selected_class = get_object(SchoolClass, selected_class_id)
|
||||
# permission check
|
||||
if not selected_class.users.filter(username=user.username).exists() or not user.is_teacher():
|
||||
raise PermissionError('Not allowed')
|
||||
if (
|
||||
not selected_class.users.filter(username=user.username).exists()
|
||||
or not user.is_teacher()
|
||||
):
|
||||
raise PermissionError("Not allowed")
|
||||
|
||||
# reset everything
|
||||
snapshot.reset(user, selected_class)
|
||||
|
|
@ -131,12 +135,12 @@ class ShareSnapshot(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
snapshot_id = args.get('snapshot')
|
||||
shared = args.get('shared')
|
||||
snapshot_id = args.get("snapshot")
|
||||
shared = args.get("shared")
|
||||
user = info.context.user
|
||||
snapshot = get_object(Snapshot, snapshot_id)
|
||||
if snapshot.creator != user:
|
||||
raise PermissionError('Not permitted')
|
||||
raise PermissionError("Not permitted")
|
||||
snapshot.shared = shared
|
||||
snapshot.save()
|
||||
return cls(success=True, snapshot=snapshot)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from graphene import relay
|
|||
|
||||
from oauth.hep_client import HepClient, HepClientException
|
||||
from oauth.models import OAuth2Token
|
||||
from oauth.types import InvalidCouponFailure, RedeemCouponResult, RedeemCouponSuccess
|
||||
from oauth.user_signup_login_handler import create_role_for_user
|
||||
from users.models import License
|
||||
|
||||
|
|
@ -13,39 +14,46 @@ class Coupon(relay.ClientIDMutation):
|
|||
class Input:
|
||||
coupon_code = graphene.String()
|
||||
|
||||
success = graphene.Boolean()
|
||||
result = RedeemCouponResult()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
coupon_code = kwargs.get('coupon_code').strip()
|
||||
coupon_code = kwargs.get("coupon_code").strip()
|
||||
hep_client = HepClient()
|
||||
|
||||
try:
|
||||
hep_id = info.context.user.hep_id
|
||||
except AttributeError:
|
||||
raise Exception('not_authenticated')
|
||||
raise Exception("not_authenticated")
|
||||
|
||||
try:
|
||||
# todo: differenciate between invalid_coupon and other errors like "delivery_address_not_set"
|
||||
response = hep_client.redeem_coupon(coupon_code, hep_id, request=info.context)
|
||||
response = hep_client.redeem_coupon(
|
||||
coupon_code, hep_id, request=info.context
|
||||
)
|
||||
except HepClientException:
|
||||
raise Exception('unknown_error')
|
||||
raise Exception("unknown_error")
|
||||
|
||||
if not response:
|
||||
raise Exception('invalid_coupon')
|
||||
return cls(result=InvalidCouponFailure)
|
||||
|
||||
product = hep_client.entry_to_product(response['data'], now(), 'coupon')
|
||||
product = hep_client.entry_to_product(response["data"], now(), "coupon")
|
||||
|
||||
if not product:
|
||||
raise Exception('non_myskillbox_product')
|
||||
raise Exception("non_myskillbox_product")
|
||||
|
||||
license = License.objects.create_license_for_role(info.context.user, product['activated'], product['raw'],
|
||||
product['license']['edition'],
|
||||
product['order_id'], product['isbn'])
|
||||
license = License.objects.create_license_for_role(
|
||||
info.context.user,
|
||||
product["activated"],
|
||||
product["raw"],
|
||||
product["license"]["edition"],
|
||||
product["order_id"],
|
||||
product["isbn"],
|
||||
)
|
||||
|
||||
create_role_for_user(info.context.user, license.for_role.key)
|
||||
|
||||
return cls(success=True)
|
||||
return cls(result=RedeemCouponSuccess)
|
||||
|
||||
|
||||
class CouponMutations:
|
||||
|
|
@ -77,4 +85,3 @@ class Logout(graphene.Mutation):
|
|||
class OauthMutations(object):
|
||||
logout = Logout.Field()
|
||||
coupon = Coupon.Field()
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ REDEEM_MYSKILLBOX_SUCCESS_RESPONSE = {
|
|||
"price": 100,
|
||||
"price_total": 100,
|
||||
"amount": 1,
|
||||
"authors": []
|
||||
"authors": [],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,29 +45,27 @@ REDEEM_OTHER_LICENSE_RESPONSE = {
|
|||
"price": 100,
|
||||
"price_total": 100,
|
||||
"amount": 1,
|
||||
"authors": []
|
||||
"authors": [],
|
||||
}
|
||||
}
|
||||
|
||||
INVALID_LICENSE = {
|
||||
"message": "The given data was invalid.",
|
||||
"errors": {
|
||||
"code": [
|
||||
"The coupons was already redeemed."
|
||||
]
|
||||
}
|
||||
"errors": {"code": ["The coupons was already redeemed."]},
|
||||
}
|
||||
|
||||
|
||||
class CouponTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = UserFactory(username='aschi@iterativ.ch', email='aschi@iterativ.ch', hep_id=3)
|
||||
self.user = UserFactory(
|
||||
username="aschi@iterativ.ch", email="aschi@iterativ.ch", hep_id=3
|
||||
)
|
||||
Role.objects.create_default_roles()
|
||||
self.teacher_role = Role.objects.get_default_teacher_role()
|
||||
Oauth2TokenFactory(user=self.user)
|
||||
|
||||
# adding session
|
||||
request = RequestFactory().post('/')
|
||||
request = RequestFactory().post("/")
|
||||
middleware = SessionMiddleware()
|
||||
middleware.process_request(request)
|
||||
request.user = self.user
|
||||
|
|
@ -75,23 +73,33 @@ class CouponTests(TestCase):
|
|||
self.client = Client(schema=schema, context_value=request)
|
||||
|
||||
def make_coupon_mutation(self, coupon_code, client):
|
||||
mutation = '''
|
||||
mutation = """
|
||||
mutation Coupon($input: CouponInput!){
|
||||
coupon(input: $input) {
|
||||
success
|
||||
result {
|
||||
__typename
|
||||
...on InvalidCoupon {
|
||||
reason
|
||||
}
|
||||
...on Success {
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
"""
|
||||
|
||||
return client.execute(mutation, variables={
|
||||
'input': {
|
||||
'couponCode': coupon_code
|
||||
}
|
||||
})
|
||||
return client.execute(
|
||||
mutation, variables={"input": {"couponCode": coupon_code}}
|
||||
)
|
||||
|
||||
@patch.object(BaseApp, 'post', return_value=MockResponse(200, data=REDEEM_MYSKILLBOX_SUCCESS_RESPONSE))
|
||||
@patch.object(
|
||||
BaseApp,
|
||||
"post",
|
||||
return_value=MockResponse(200, data=REDEEM_MYSKILLBOX_SUCCESS_RESPONSE),
|
||||
)
|
||||
def test_user_has_valid_skillbox_coupon(self, response_mock):
|
||||
result = self.make_coupon_mutation('COUPON--1234', self.client)
|
||||
result = self.make_coupon_mutation("COUPON--1234", self.client)
|
||||
|
||||
user_role = self.user.user_roles.get(user=self.user)
|
||||
self.assertEqual(user_role.role.key, Role.objects.TEACHER_KEY)
|
||||
|
|
@ -101,48 +109,66 @@ class CouponTests(TestCase):
|
|||
school_class = SchoolClass.objects.get(users__in=[self.user])
|
||||
self.assertIsNotNone(school_class)
|
||||
|
||||
self.assertTrue(result.get('data').get('coupon').get('success'))
|
||||
self.assertTrue(result.get("data").get("coupon").get("success"))
|
||||
self.assertTrue(self.user.is_authenticated)
|
||||
|
||||
@patch.object(BaseApp, 'post', return_value=MockResponse(200, data=REDEEM_OTHER_LICENSE_RESPONSE))
|
||||
@patch.object(
|
||||
BaseApp,
|
||||
"post",
|
||||
return_value=MockResponse(200, data=REDEEM_OTHER_LICENSE_RESPONSE),
|
||||
)
|
||||
def test_user_has_valid_non_skillbox_coupon(self, response_mock):
|
||||
result = self.make_coupon_mutation('COUPON--1234', self.client)
|
||||
result = self.make_coupon_mutation("COUPON--1234", self.client)
|
||||
|
||||
try:
|
||||
self.user.user_roles.get(user=self.user)
|
||||
self.fail("CouponTests.test_user_has_valid_non_skillbox_coupon: Should not have created user role")
|
||||
self.fail(
|
||||
"CouponTests.test_user_has_valid_non_skillbox_coupon: Should not have created user role"
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
License.objects.get(licensee=self.user)
|
||||
self.fail("CouponTests.test_user_has_valid_non_skillbox_coupon: License should not exist")
|
||||
self.fail(
|
||||
"CouponTests.test_user_has_valid_non_skillbox_coupon: License should not exist"
|
||||
)
|
||||
except License.DoesNotExist:
|
||||
pass
|
||||
|
||||
self.assertEqual(result.get('errors')[0].get('message'), 'non_myskillbox_product')
|
||||
self.assertEqual(
|
||||
result.get("errors")[0].get("message"), "non_myskillbox_product"
|
||||
)
|
||||
self.assertTrue(self.user.is_authenticated)
|
||||
|
||||
@patch.object(BaseApp, 'post', return_value=MockResponse(404, data=INVALID_LICENSE))
|
||||
@patch.object(BaseApp, "post", return_value=MockResponse(404, data=INVALID_LICENSE))
|
||||
def test_user_has_invalid_coupon(self, response_mock):
|
||||
result = self.make_coupon_mutation('COUPON--1234', self.client)
|
||||
result = self.make_coupon_mutation("COUPON--1234", self.client)
|
||||
|
||||
self.assertEqual(result.get('errors')[0].get('message'), 'invalid_coupon')
|
||||
self.assertEqual(
|
||||
result.get("data").get("coupon").get("result").get("__typename"),
|
||||
"InvalidCoupon",
|
||||
)
|
||||
|
||||
@patch.object(BaseApp, 'post', return_value=MockResponse(422, data=INVALID_LICENSE))
|
||||
@patch.object(BaseApp, "post", return_value=MockResponse(422, data=INVALID_LICENSE))
|
||||
def test_user_has_already_used_coupon(self, response_mock):
|
||||
result = self.make_coupon_mutation('COUPON--1234', self.client)
|
||||
result = self.make_coupon_mutation("COUPON--1234", self.client)
|
||||
|
||||
self.assertEqual(result.get('errors')[0].get('message'), 'invalid_coupon')
|
||||
self.assertEqual(
|
||||
result.get("data").get("coupon").get("result").get("__typename"),
|
||||
"InvalidCoupon",
|
||||
)
|
||||
|
||||
@patch.object(BaseApp, 'put', return_value=MockResponse(200, data=['201', 'Invalid Coupon']))
|
||||
@patch.object(
|
||||
BaseApp, "put", return_value=MockResponse(200, data=["201", "Invalid Coupon"])
|
||||
)
|
||||
def test_unauthenticated_user_cannot_redeem(self, response_mock):
|
||||
request = RequestFactory().post('/')
|
||||
request = RequestFactory().post("/")
|
||||
middleware = SessionMiddleware()
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
client = Client(schema=schema, context_value=request)
|
||||
|
||||
result = self.make_coupon_mutation('COUPON--1234', client)
|
||||
result = self.make_coupon_mutation("COUPON--1234", client)
|
||||
|
||||
self.assertEqual(result.get('errors')[0].get('message'), 'not_authenticated')
|
||||
self.assertEqual(result.get("errors")[0].get("message"), "not_authenticated")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import graphene
|
||||
|
||||
from api.types import FailureNode, Success
|
||||
|
||||
|
||||
class InvalidCoupon(graphene.ObjectType):
|
||||
class Meta:
|
||||
interfaces = (FailureNode,)
|
||||
|
||||
|
||||
RedeemCouponSuccess = Success(message="Coupon successfully redeemed.")
|
||||
InvalidCouponFailure = InvalidCoupon(reason="Invalid coupon provided.")
|
||||
|
||||
|
||||
class RedeemCouponResult(graphene.Union):
|
||||
class Meta:
|
||||
types = (
|
||||
Success,
|
||||
InvalidCoupon,
|
||||
)
|
||||
Loading…
Reference in New Issue