def test_non_staff_user_can_only_see_his_order(user_api_client, order): # FIXME: Remove client.login() when JWT authentication is re-enabled. user_api_client.login(username=order.user.email, password='******') query = """ query OrderQuery($id: ID!) { order(id: $id) { orderId } } """ ID = graphene.Node.to_global_id('Order', order.id) variables = json.dumps({'id': ID}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) order_data = content['data']['order'] assert order_data['orderId'] == order.pk order.user = None order.save() response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) order_data = content['data']['order'] assert not order_data
def test_voucher_permissions( staff_api_client, staff_user, permission_manage_discounts): query = """ query vouchers{ vouchers(first: 1) { edges { node { name } } } } """ # Query to ensure user with no permissions can't see vouchers response = staff_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) message = 'You do not have permission to perform this action' assert content['errors'][0]['message'] == message # Give staff user proper permissions staff_user.user_permissions.add(permission_manage_discounts) # Query again response = staff_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) assert 'errors' not in content
def test_create_token_mutation(admin_client, staff_user): query = ''' mutation { tokenCreate(email: "%(email)s", password: "******") { token errors { field message } } } ''' success_query = query % {'email': staff_user.email, 'password': '******'} response = admin_client.post( reverse('api'), json.dumps({'query': success_query}), content_type='application/json') content = get_graphql_content(response) assert 'errors' not in content token_data = content['data']['tokenCreate'] assert token_data['token'] assert not token_data['errors'] error_query = query % {'email': staff_user.email, 'password': '******'} response = admin_client.post( reverse('api'), json.dumps({'query': error_query}), content_type='application/json') content = get_graphql_content(response) assert 'errors' not in content token_data = content['data']['tokenCreate'] assert not token_data['token'] errors = token_data['errors'] assert errors assert not errors[0]['field']
def test_query_users(admin_api_client, user_api_client): query = """ query Users($isStaff: Boolean) { users(isStaff: $isStaff) { totalCount edges { node { isStaff } } } } """ variables = json.dumps({'isStaff': True}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) users = content['data']['users']['edges'] assert users assert all([user['node']['isStaff'] for user in users]) variables = json.dumps({'isStaff': False}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) users = content['data']['users']['edges'] assert users assert all([not user['node']['isStaff'] for user in users]) # check permissions response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response)
def test_category_create_mutation(admin_api_client): query = """ mutation($name: String, $slug: String, $description: String, $parentId: ID) { categoryCreate( input: { name: $name slug: $slug description: $description parent: $parentId } ) { category { id name slug description parent { name id } } errors { field message } } } """ category_name = 'Test category' category_slug = slugify(category_name) category_description = 'Test description' # test creating root category variables = json.dumps({ 'name': category_name, 'description': category_description, 'slug': category_slug}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['categoryCreate'] assert data['errors'] == [] assert data['category']['name'] == category_name assert data['category']['description'] == category_description assert not data['category']['parent'] # test creating subcategory parent_id = data['category']['id'] variables = json.dumps({ 'name': category_name, 'description': category_description, 'parentId': parent_id, 'slug': category_slug}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['categoryCreate'] assert data['errors'] == [] assert data['category']['parent']['id'] == parent_id
def test_category_level(user_api_client, default_category): category = default_category query = """ query leveled_categories($level: Int) { categories(level: $level) { edges { node { name parent { name } } } } } """ child = Category.objects.create( name='child', slug='chi-ld', parent=category) variables = json.dumps({'level': 0}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content category_data = content['data']['categories']['edges'][0]['node'] assert category_data['name'] == category.name assert category_data['parent'] == None query = """ query leveled_categories($level: Int) { categories(level: $level) { edges { node { name parent { name } } } } } """ variables = json.dumps({'level': 1}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content category_data = content['data']['categories']['edges'][0]['node'] assert category_data['name'] == child.name assert category_data['parent']['name'] == category.name
def test_update_collection(admin_api_client, collection): query = """ mutation updateCollection( $name: String!, $slug: String!, $id: ID!, $isPublished: Boolean!) { collectionUpdate( id: $id, input: {name: $name, slug: $slug, isPublished: $isPublished}) { collection { name slug } } } """ collection_id = to_global_id('Collection', collection.id) name = 'new-name' slug = 'new-slug' variables = json.dumps( {'name': name, 'slug': slug, 'id': collection_id, 'isPublished': True}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['collectionUpdate']['collection'] assert data['name'] == name assert data['slug'] == slug
def test_voucher_query( admin_api_client, voucher): query = """ query vouchers{ vouchers(first: 1) { edges { node { type name code usageLimit used startDate discountValueType discountValue } } } } """ response = admin_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['vouchers']['edges'][0]['node'] assert data['type'] == voucher.type.upper() assert data['name'] == voucher.name assert data['code'] == voucher.code assert data['usageLimit'] == voucher.usage_limit assert data['used'] == voucher.used assert data['startDate'] == voucher.start_date.isoformat() assert data['discountValueType'] == voucher.discount_value_type.upper() assert data['discountValue'] == voucher.discount_value
def test_address_validator_uses_geip_when_country_code_missing( user_api_client, monkeypatch): query = """ query getValidator($input: AddressValidationInput!) { addressValidator(input: $input) { countryCode, countryName } } """ variables = json.dumps({'input': { 'countryCode': None, 'countryArea': None, 'cityArea': None }}) mock_country_by_ip = Mock(return_value=Mock(code='US')) monkeypatch.setattr( 'saleor.graphql.account.resolvers.get_client_ip', lambda request: Mock(return_value='127.0.0.1')) monkeypatch.setattr( 'saleor.graphql.account.resolvers.get_country_by_ip', mock_country_by_ip) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert mock_country_by_ip.called assert 'errors' not in content data = content['data']['addressValidator'] assert data['countryCode'] == 'US' assert data['countryName'] == 'UNITED STATES'
def test_address_validator(user_api_client): query = """ query getValidator($input: AddressValidationInput!) { addressValidator(input: $input) { countryCode countryName addressFormat addressLatinFormat postalCodeMatchers } } """ variables = json.dumps({'input': { 'countryCode': 'PL', 'countryArea': None, 'cityArea': None }}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['addressValidator'] assert data['countryCode'] == 'PL' assert data['countryName'] == 'POLAND' assert data['addressFormat'] is not None assert data['addressLatinFormat'] is not None matcher = data['postalCodeMatchers'][0] matcher = re.compile(matcher) assert matcher.match('00-123')
def test_validate_voucher(voucher, admin_api_client): query = """ mutation voucherUpdate( $id: ID!, $type: VoucherTypeEnum) { voucherUpdate( id: $id, input: {type: $type}) { errors { field message } } } """ # apparently can't do so via pytest parametrize # as it parses VoucherTypeEnum into str format fields = ( (VoucherTypeEnum.CATEGORY, 'categories'), (VoucherTypeEnum.PRODUCT, 'products'), (VoucherTypeEnum.COLLECTION, 'collections')) for voucher_type, field_name in fields: variables = json.dumps({ 'type': voucher_type.name, 'id': graphene.Node.to_global_id('Voucher', voucher.id)}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) data = content['data']['voucherUpdate']['errors'][0] assert data['field'] == field_name assert data['message'] == 'This field is required.'
def test_create_product_attribute(admin_api_client): query = """ mutation createAttribute($name: String!, $slug: String!) { productAttributeCreate(input: {name: $name, slug: $slug}) { productAttribute { name slug values { name slug } } } } """ name = 'test name' slug = 'test-slug' variables = json.dumps({'name': name, 'slug': slug}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productAttributeCreate']['productAttribute'] assert data['name'] == name assert data['slug'] == slug assert not data['values']
def test_shop_endpoint(settings, admin_api_client): query = """ query shop { shop { permissions { code name } languages { code language } phonePrefixes } } """ languages = settings.LANGUAGES response = admin_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['shop'] permissions = data['permissions'] permissions_codes = {permission.get('code') for permission in permissions} assert len(permissions_codes) == len(MODELS_PERMISSIONS) for code in permissions_codes: assert code in MODELS_PERMISSIONS assert len(data['languages']) == len(languages) assert len(data['phonePrefixes']) == len(COUNTRY_CODE_TO_REGION_CODE)
def test_update_sale(user_api_client, admin_api_client, sale): query = """ mutation saleUpdate($type: DiscountValueTypeEnum, $id: ID!) { saleUpdate(id: $id, input: {type: $type}) { errors { field message } sale { type } } } """ # Set discount value type to 'fixed' and change it in mutation sale.type = DiscountValueType.FIXED sale.save() variables = json.dumps({ 'id': graphene.Node.to_global_id('Sale', sale.id), 'type': DiscountValueTypeEnum.PERCENTAGE.name}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['saleUpdate']['sale'] assert data['type'] == DiscountValueType.PERCENTAGE.upper()
def test_create_collection(admin_api_client, product_list): query = """ mutation createCollection( $name: String!, $slug: String!, $products: [ID], $backgroundImage: Upload!, $isPublished: Boolean!) { collectionCreate( input: {name: $name, slug: $slug, products: $products, backgroundImage: $backgroundImage, isPublished: $isPublished}) { collection { name slug products { totalCount } } } } """ product_ids = [ to_global_id('Product', product.pk) for product in product_list] image_file, image_name = create_image() name = 'test-name' slug = 'test-slug' variables = { 'name': name, 'slug': slug, 'products': product_ids, 'backgroundImage': image_name, 'isPublished': True} body = get_multipart_request_body(query, variables, image_file, image_name) response = admin_api_client.post_multipart(reverse('api'), body) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['collectionCreate']['collection'] assert data['name'] == name assert data['slug'] == slug assert data['products']['totalCount'] == len(product_ids) collection = Collection.objects.get(slug=slug) assert collection.background_image.file
def test_reorder_images(admin_api_client, product_with_images): query = """ mutation reorderImages($product_id: ID!, $images_ids: [ID]!) { productImageReorder(productId: $product_id, imagesIds: $images_ids) { product { id } } } """ product = product_with_images images = product.images.all() image_0 = images[0] image_1 = images[1] image_0_id = graphene.Node.to_global_id('ProductImage', image_0.id) image_1_id = graphene.Node.to_global_id('ProductImage', image_1.id) product_id = graphene.Node.to_global_id('Product', product.id) variables = { 'product_id': product_id, 'images_ids': [image_1_id, image_0_id]} response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content # Check if order has been changed product.refresh_from_db() reordered_images = product.images.all() reordered_image_0 = reordered_images[0] reordered_image_1 = reordered_images[1] assert image_0.id == reordered_image_1.id assert image_1.id == reordered_image_0.id
def test_invalid_product_image_create_mutation(admin_api_client, product): query = """ mutation createProductImage($image: Upload!, $product: ID!) { productImageCreate(input: {image: $image, product: $product}) { image { id url sortOrder } errors { field message } } } """ image_file, image_name = create_pdf_file_with_image_ext() variables = { 'product': graphene.Node.to_global_id('Product', product.id), 'image': image_name} body = get_multipart_request_body(query, variables, image_file, image_name) response = admin_api_client.post_multipart(reverse('api'), body) content = get_graphql_content(response) assert 'errors' not in content assert content['data']['productImageCreate']['errors'] == [{ 'field': 'image', 'message': 'Invalid file type'}] product.refresh_from_db() assert product.images.count() == 0
def test_product_type(user_api_client, product_type): query = """ query { productTypes { totalCount edges { node { id name products(first: 1) { edges { node { id } } } } } } } """ response = user_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) no_product_types = ProductType.objects.count() assert 'errors' not in content assert content['data']['productTypes']['totalCount'] == no_product_types assert len(content['data']['productTypes']['edges']) == no_product_types
def test_update_attribute_choice_value(admin_api_client, pink_choice_value): value = pink_choice_value query = """ mutation updateChoice($id: ID!, $name: String!, $slug: String!) { attributeChoiceValueUpdate( id: $id, input: {name: $name, slug: $slug}) { attributeChoiceValue { name slug } } } """ id = graphene.Node.to_global_id('ProductAttributeValue', value.id) name = 'Crimson' slug = value.slug variables = json.dumps( {'name': name, 'slug': slug, 'id': id}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content value.refresh_from_db() data = content[ 'data']['attributeChoiceValueUpdate']['attributeChoiceValue'] assert data['name'] == name == value.name
def test_sale_delete_mutation(user_api_client, admin_api_client, sale): query = """ mutation DeleteSale($id: ID!) { saleDelete(id: $id) { sale { name id } errors { field message } } } """ variables = json.dumps({ 'id': graphene.Node.to_global_id('Sale', sale.id)}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['saleDelete'] assert data['sale']['name'] == sale.name with pytest.raises(sale._meta.model.DoesNotExist): sale.refresh_from_db()
def test_create_attribute_choice_value(admin_api_client, color_attribute): attribute = color_attribute query = """ mutation createChoice($attribute: ID!, $name: String!, $slug: String!) { attributeChoiceValueCreate( input: {attribute: $attribute, name: $name, slug: $slug}) { attributeChoiceValue { name slug } } } """ attribute_id = graphene.Node.to_global_id('ProductAttribute', attribute.id) name = 'test name' slug = 'test-slug' variables = json.dumps( {'name': name, 'slug': slug, 'attribute': attribute_id}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content[ 'data']['attributeChoiceValueCreate']['attributeChoiceValue'] assert data['name'] == name assert data['slug'] == slug
def test_query_staff( admin_api_client, user_api_client, staff_user, customer_user, admin_user): query = """ { staffUsers { edges { node { email isStaff } } } } """ variables = json.dumps({}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) data = content['data']['staffUsers']['edges'] assert len(data) == 2 staff_emails = [user['node']['email'] for user in data] assert sorted(staff_emails) == [admin_user.email, staff_user.email] assert all([user['node']['isStaff'] for user in data]) # check permissions response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response)
def test_create_sale(user_api_client, admin_api_client): query = """ mutation saleCreate( $type: DiscountValueTypeEnum, $name: String, $value: Decimal) { saleCreate(input: {name: $name, type: $type, value: $value}) { errors { field message } sale { type name value } } } """ variables = json.dumps({ 'name': 'test sale', 'type': DiscountValueTypeEnum.FIXED.name, 'value': '10.12'}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['saleCreate']['sale'] assert data['type'] == DiscountValueType.FIXED.upper() assert data['name'] == 'test sale' assert data['value'] == 10.12
def test_password_reset_email( send_password_reset_mock, admin_api_client, customer_user): query = """ mutation ResetPassword($email: String!) { passwordReset(email: $email) { errors { field message } } } """ email = customer_user.email variables = json.dumps({'email': email}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['passwordReset'] assert data is None assert send_password_reset_mock.call_count == 1 args, kwargs = send_password_reset_mock.call_args call_context = args[0] call_email = args[1] assert call_email == email assert 'token' in call_context
def test_validate_voucher(voucher, admin_api_client, product): query = """ mutation voucherUpdate( $product_id: ID, $id: ID!, $type: VoucherTypeEnum) { voucherUpdate( id: $id, input: {product: $product_id, type: $type}) { errors { field message } voucher { product { name } } } } """ assert not voucher.product variables = json.dumps({ 'type': VoucherTypeEnum.PRODUCT.name, 'id': graphene.Node.to_global_id('Voucher', voucher.id), 'product': graphene.Node.to_global_id('Product', product.id)}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) data = content['data']['voucherUpdate']['errors'][0] assert data['field'] == 'product' assert data['message'] == 'This field is required.'
def test_create_address_mutation(admin_api_client, customer_user): query = """ mutation CreateUserAddress($user: ID!, $city: String!, $country: String!) { addressCreate(input: {userId: $user, city: $city, country: $country}) { errors { field message } address { id city country } } } """ user_id = graphene.Node.to_global_id('User', customer_user.id) variables = json.dumps( {'user': user_id, 'city': 'Dummy', 'country': 'PL'}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert content['data']['addressCreate']['errors'] == [] address_response = content['data']['addressCreate']['address'] assert address_response['city'] == 'Dummy' assert address_response['country'] == 'PL' address_obj = Address.objects.get(city='Dummy') assert address_obj.user_addresses.first() == customer_user
def test_token_create_user_data( permission_manage_orders, staff_client, staff_user): query = """ mutation { tokenCreate(email: "%(email)s", password: "******") { user { id email permissions { code name } } } } """ permission = permission_manage_orders staff_user.user_permissions.add(permission) code = '.'.join([permission.content_type.name, permission.codename]) name = permission.name user_id = graphene.Node.to_global_id('User', staff_user.id) query = query % {'email': staff_user.email, 'password': '******'} response = staff_client.post( reverse('api'), json.dumps({'query': query}), content_type='application/json') content = get_graphql_content(response) assert 'errors' not in content token_data = content['data']['tokenCreate'] assert token_data['user']['id'] == user_id assert token_data['user']['email'] == staff_user.email assert token_data['user']['permissions'][0]['name'] == name assert token_data['user']['permissions'][0]['code'] == code
def test_staff_update(admin_api_client, staff_user, user_api_client): query = """ mutation UpdateStaff($id: ID!, $permissions: [String]) { staffUpdate(id: $id, input: {permissions: $permissions}) { errors { field message } user { permissions { code } } } } """ id = graphene.Node.to_global_id('User', staff_user.id) variables = json.dumps({'id': id, 'permissions': []}) # check unauthorized access response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['staffUpdate'] assert data['errors'] == [] assert data['user']['permissions'] == []
def test_cancel_fulfillment_restock_items( admin_api_client, fulfillment, admin_user): query = """ mutation cancelFulfillment($id: ID!, $restock: Boolean) { fulfillmentCancel(id: $id, input: {restock: $restock}) { fulfillment { status } } } """ fulfillment_id = graphene.Node.to_global_id('Fulfillment', fulfillment.id) variables = json.dumps({'id': fulfillment_id, 'restock': True}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['fulfillmentCancel']['fulfillment'] assert data['status'] == FulfillmentStatus.CANCELED.upper() event_restocked_items = fulfillment.order.events.get() assert event_restocked_items.type == ( OrderEvents.FULFILLMENT_RESTOCKED_ITEMS.value) assert event_restocked_items.parameters == { 'quantity': fulfillment.get_total_quantity()} assert event_restocked_items.user == admin_user
def test_customer_update(admin_api_client, customer_user, user_api_client): query = """ mutation UpdateCustomer($id: ID!, $note: String) { customerUpdate(id: $id, input: {note: $note}) { errors { field message } user { id email isStaff isActive note } } } """ id = graphene.Node.to_global_id('User', customer_user.id) note = 'Test update note' variables = json.dumps({'id': id, 'note': note}) # check unauthorized access response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['customerUpdate'] assert data['errors'] == [] assert data['user']['note'] == note
def test_customer_create(admin_api_client, user_api_client): query = """ mutation CreateCustomer($email: String, $note: String) { customerCreate(input: {email: $email, note: $note}) { errors { field message } user { id email isStaff isActive note } } } """ email = '*****@*****.**' note = 'Test user' variables = json.dumps({'email': email, 'note': note}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['customerCreate'] assert data['errors'] == [] assert data['user']['email'] == email assert data['user']['note'] == note assert data['user']['isStaff'] == False assert data['user']['isActive'] == True
def test_update_voucher(user_api_client, admin_api_client, voucher): query = """ mutation voucherUpdate($code: String, $discountValueType: DiscountValueTypeEnum, $id: ID!) { voucherUpdate(id: $id, input: { code: $code, discountValueType: $discountValueType}) { errors { field message } voucher { code discountValueType } } } """ # Set discount value type to 'fixed' and change it in mutation voucher.discount_value_type = DiscountValueType.FIXED voucher.save() assert voucher.code != 'testcode123' variables = json.dumps({ 'id': graphene.Node.to_global_id('Voucher', voucher.id), 'code': 'testcode123', 'discountValueType': DiscountValueTypeEnum.PERCENTAGE.name}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['voucherUpdate']['voucher'] assert data['code'] == 'testcode123' assert data['discountValueType'] == DiscountValueType.PERCENTAGE.upper()
def test_update_sale(user_api_client, admin_api_client, sale): query = """ mutation saleUpdate($type: DiscountValueTypeEnum, $id: ID!) { saleUpdate(id: $id, input: {type: $type}) { errors { field message } sale { type } } } """ # Set discount value type to 'fixed' and change it in mutation sale.type = DiscountValueType.FIXED sale.save() variables = json.dumps({ 'id': graphene.Node.to_global_id('Sale', sale.id), 'type': DiscountValueTypeEnum.PERCENTAGE.name }) response = user_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) assert_no_permission(response) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['saleUpdate']['sale'] assert data['type'] == DiscountValueType.PERCENTAGE.upper()
def test_draft_order_complete(admin_api_client, admin_user, draft_order): order = draft_order query = """ mutation draftComplete($id: ID!) { draftOrderComplete(id: $id) { order { status } } } """ line_1, line_2 = order.lines.order_by('-quantity').all() line_1.quantity = 1 line_1.save(update_fields=['quantity']) assert line_1.variant.quantity_available >= line_1.quantity assert line_2.variant.quantity_available < line_2.quantity order_id = graphene.Node.to_global_id('Order', order.id) variables = json.dumps({'id': order_id}) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['draftOrderComplete']['order'] order.refresh_from_db() assert data['status'] == order.status.upper() missing_stock_event, draft_placed_event = OrderEvent.objects.all() assert missing_stock_event.user == admin_user assert missing_stock_event.type == OrderEvents.OVERSOLD_ITEMS.value assert missing_stock_event.parameters == {'oversold_items': [str(line_2)]} assert draft_placed_event.user == admin_user assert draft_placed_event.type == OrderEvents.PLACED_FROM_DRAFT.value assert draft_placed_event.parameters == {}
def test_create_attribute_choice_value(admin_api_client, color_attribute): attribute = color_attribute query = """ mutation createChoice($attribute: ID!, $name: String!, $slug: String!, $value: String!) { attributeChoiceValueCreate( input: {attribute: $attribute, name: $name, slug: $slug, value: $value}) { attributeChoiceValue { name slug type value } } } """ attribute_id = graphene.Node.to_global_id('ProductAttribute', attribute.id) name = 'test name' slug = 'test-slug' value = 'test-string' variables = json.dumps({ 'name': name, 'slug': slug, 'value': value, 'attribute': attribute_id }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['attributeChoiceValueCreate'][ 'attributeChoiceValue'] assert data['name'] == name assert data['slug'] == slug assert data['value'] == value assert data['type'] == 'STRING'
def test_shipping_zone_query(user_api_client, shipping_zone): shipping = shipping_zone query = """ query ShippingQuery($id: ID!) { shippingZone(id: $id) { name shippingMethods { price { amount } } priceRange { start { amount } stop { amount } } } } """ ID = graphene.Node.to_global_id('ShippingZone', shipping.id) variables = json.dumps({'id': ID}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content shipping_data = content['data']['shippingZone'] assert shipping_data['name'] == shipping.name num_of_shipping_methods = shipping_zone.shipping_methods.count() assert len(shipping_data['shippingMethods']) == num_of_shipping_methods price_range = shipping.price_range data_price_range = shipping_data['priceRange'] assert data_price_range['start']['amount'] == price_range.start.amount assert data_price_range['stop']['amount'] == price_range.stop.amount
def test_category_query(user_api_client, product): category = Category.objects.first() query = ''' query { category(id: "%(category_pk)s") { id name ancestors { edges { node { name } } } children { edges { node { name } } } } } ''' % {'category_pk': graphene.Node.to_global_id('Category', category.pk)} response = user_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) assert 'errors' not in content category_data = content['data']['category'] assert category_data is not None assert category_data['name'] == category.name assert ( len(category_data['ancestors']['edges']) == category.get_ancestors().count()) assert ( len(category_data['children']['edges']) == category.get_children().count())
def test_menu_items_query(user_api_client, menu_item, collection): query = """ query menuitem($id: ID!) { menuItem(id: $id) { name children { totalCount } collection { name } category { id } page { id } url } } """ menu_item.collection = collection menu_item.save() variables = json.dumps( {'id': graphene.Node.to_global_id('MenuItem', menu_item.pk)}) response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['menuItem'] assert data['name'] == menu_item.name assert data['url'] == menu_item.collection.get_absolute_url() assert data['children']['totalCount'] == menu_item.children.count() assert data['collection']['name'] == collection.name assert not data['category'] assert not data['page']
def test_staff_update(admin_api_client, staff_user, user_api_client): query = """ mutation UpdateStaff( $id: ID!, $permissions: [String], $is_active: Boolean) { staffUpdate( id: $id, input: {permissions: $permissions, isActive: $is_active}) { errors { field message } user { permissions { code } isActive } } } """ id = graphene.Node.to_global_id('User', staff_user.id) variables = json.dumps({'id': id, 'permissions': [], 'is_active': False}) # check unauthorized access response = user_api_client.post( reverse('api'), {'query': query, 'variables': variables}) assert_no_permission(response) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['staffUpdate'] assert data['errors'] == [] assert data['user']['permissions'] == [] assert data['user']['isActive'] == False
def test_update_menu_item(admin_api_client, menu, menu_item, page): query = """ mutation updateMenuItem($id: ID!, $page: ID) { menuItemUpdate(id: $id, input: {page: $page}) { menuItem { url } } } """ # Menu item before update has url, but no page assert menu_item.url assert not menu_item.page menu_item_id = graphene.Node.to_global_id('MenuItem', menu_item.pk) page_id = graphene.Node.to_global_id('Page', page.pk) variables = json.dumps({'id': menu_item_id, 'page': page_id}) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['menuItemUpdate']['menuItem'] assert data['url'] == page.get_absolute_url()
def test_collection_image_query(user_api_client, collection): image_file, image_name = create_image() collection.background_image = image_file collection.save() collection_id = graphene.Node.to_global_id('Collection', collection.pk) query = """ query fetchCollection($id: ID!){ collection(id: $id) { backgroundImage { url(size: 120) } } } """ variables = json.dumps({'id': collection_id}) response = user_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['collection'] thumbnail_url = collection.background_image.thumbnail['120x120'].url assert data['backgroundImage']['url'] == thumbnail_url
def test_product_image_create_mutation(admin_api_client, product): query = """ mutation createProductImage($image: Upload!, $product: ID!) { productImageCreate(input: {image: $image, product: $product}) { productImage { id url sortOrder } } } """ image_file, image_name = create_image() variables = { 'product': graphene.Node.to_global_id('Product', product.id), 'image': image_name } body = get_multipart_request_body(query, variables, image_file, image_name) response = admin_api_client.post_multipart(reverse('api'), body) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productImageCreate'] product.refresh_from_db() assert product.images.first().image.file
def test_category_delete_mutation(admin_api_client, category): query = """ mutation($id: ID!) { categoryDelete(id: $id) { category { name } errors { field message } } } """ variables = json.dumps({ 'id': graphene.Node.to_global_id('Category', category.id)}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['categoryDelete'] assert data['category']['name'] == category.name with pytest.raises(category._meta.model.DoesNotExist): category.refresh_from_db()
def test_create_fulfillment(admin_api_client, order_with_lines): order = order_with_lines query = """ mutation fulfillOrder( $order: ID, $lines: [FulfillmentLineInput], $tracking: String) { fulfillmentCreate( input: {lines: $lines, order: $order, trackingNumber: $tracking}) { fulfillment { fulfillmentOrder status trackingNumber lines { totalCount } } } } """ order_id = graphene.Node.to_global_id('Order', order.id) order_line = order.lines.first() order_line_id = graphene.Node.to_global_id('OrderLine', order_line.id) tracking = 'Flames tracking' variables = json.dumps( {'order': order_id, 'lines': [{'orderLineId': order_line_id, 'quantity': 1}], 'tracking': tracking}) response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['fulfillmentCreate']['fulfillment'] assert data['fulfillmentOrder'] == 1 assert data['status'] == FulfillmentStatus.FULFILLED.upper() assert data['trackingNumber'] == tracking assert data['lines']['totalCount'] == 1
def test_update_product_attribute(admin_api_client, color_attribute): attribute = color_attribute query = """ mutation updateAttribute($id: ID!, $name: String!, $slug: String!) { productAttributeUpdate(id: $id, input: {name: $name, slug: $slug}) { productAttribute { name } } } """ name = 'Wings name' slug = attribute.slug id = graphene.Node.to_global_id('ProductAttribute', attribute.id) variables = json.dumps({'name': name, 'id': id, 'slug': slug}) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) attribute.refresh_from_db() assert 'errors' not in content data = content['data']['productAttributeUpdate']['productAttribute'] assert data['name'] == name == attribute.name
def test_delete_attribute_choice_value(admin_api_client, color_attribute, pink_choice_value): value = pink_choice_value value = color_attribute.values.get(name='Red') query = """ mutation updateChoice($id: ID!) { attributeChoiceValueDelete(id: $id) { attributeChoiceValue { name slug } } } """ id = graphene.Node.to_global_id('ProductAttributeValue', value.id) variables = json.dumps({'id': id}) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content with pytest.raises(value._meta.model.DoesNotExist): value.refresh_from_db()
def test_create_fulfillment_not_sufficient_quantity(admin_api_client, order_with_lines, admin_user, quantity, error_message): query = CREATE_FULFILLMENT_QUERY order_line = order_with_lines.lines.first() order_line_id = graphene.Node.to_global_id('OrderLine', order_line.id) variables = json.dumps({ 'order': graphene.Node.to_global_id('Order', order_with_lines.id), 'lines': [{ 'orderLineId': order_line_id, 'quantity': quantity }] }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) data = content['data']['orderFulfillmentCreate'] assert 'errors' in data assert data['errors'][0]['field'] == str(order_line) assert data['errors'][0]['message'] == error_message
def test_delete_variant(admin_api_client, product): query = """ mutation variantDelete($id: ID!) { productVariantDelete(id: $id) { productVariant { sku id } } } """ variant = product.variants.first() variant_id = graphene.Node.to_global_id('ProductVariant', variant.pk) variables = json.dumps({'id': variant_id}) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productVariantDelete'] assert data['productVariant']['sku'] == variant.sku with pytest.raises(variant._meta.model.DoesNotExist): variant.refresh_from_db()
def test_draft_order_line_remove(draft_order, permission_manage_orders, staff_api_client): order = draft_order line = order.lines.first() line_id = graphene.Node.to_global_id('OrderLine', line.id) variables = json.dumps({'id': line_id}) # mutation should fail without proper permissions response = staff_api_client.post(reverse('api'), { 'query': DRAFT_ORDER_LINE_DELETE_MUTATION, 'variables': variables }) assert_no_permission(response) # assign permissions staff_api_client.user.user_permissions.add(permission_manage_orders) response = staff_api_client.post(reverse('api'), { 'query': DRAFT_ORDER_LINE_DELETE_MUTATION, 'variables': variables }) content = get_graphql_content(response) data = content['data']['draftOrderLineDelete'] assert data['orderLine']['id'] == line_id assert line not in order.lines.all()
def test_reorder_images(admin_api_client, product_with_images): query = """ mutation reorderImages($product_id: ID!, $images_ids: [ID]!) { productImageReorder(productId: $product_id, imagesIds: $images_ids) { product { id } } } """ product = product_with_images images = product.images.all() image_0 = images[0] image_1 = images[1] image_0_id = graphene.Node.to_global_id('ProductImage', image_0.id) image_1_id = graphene.Node.to_global_id('ProductImage', image_1.id) product_id = graphene.Node.to_global_id('Product', product.id) variables = { 'product_id': product_id, 'images_ids': [image_1_id, image_0_id] } response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content # Check if order has been changed product.refresh_from_db() reordered_images = product.images.all() reordered_image_0 = reordered_images[0] reordered_image_1 = reordered_images[1] assert image_0.id == reordered_image_1.id assert image_1.id == reordered_image_0.id
def test_product_image_delete(admin_api_client, product_with_image): product = product_with_image query = """ mutation deleteProductImage($id: ID!) { productImageDelete(id: $id) { image { id url } } } """ image_obj = product.images.first() node_id = graphene.Node.to_global_id('ProductImage', image_obj.id) variables = {'id': node_id} response = admin_api_client.post( reverse('api'), {'query': query, 'variables': variables}) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productImageDelete'] assert data['image']['url'] == image_obj.image.url with pytest.raises(image_obj._meta.model.DoesNotExist): image_obj.refresh_from_db() assert node_id == data['image']['id']
def test_fetch_product_by_id(user_api_client, product): query = ''' query ($productId: ID!) { node(id: $productId) { ... on Product { name } } } ''' response = user_api_client.post( reverse('api'), { 'query': query, 'variables': json.dumps({ 'productId': graphene.Node.to_global_id('Product', product.id) }) }) content = get_graphql_content(response) assert 'errors' not in content product_data = content['data']['node'] assert product_data['name'] == product.name
def test_query_product_image_by_id(user_api_client, product_with_image): image = product_with_image.images.first() query = ''' query productImageById($imageId: ID!, $productId: ID!) { product(id: $productId) { imageById(id: $imageId) { id url } } } ''' variables = json.dumps({ 'productId': graphene.Node.to_global_id('Product', product_with_image.pk), 'imageId': graphene.Node.to_global_id('ProductImage', image.pk) }) response = user_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content
def test_product_variants_by_ids(user_api_client, variant): query = ''' query getProduct($ids: [ID!]) { productVariants(ids: $ids) { edges { node { id } } } } ''' variant_id = graphene.Node.to_global_id('ProductVariant', variant.id) variables = json.dumps({'ids': [variant_id]}) response = user_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productVariants'] assert data['edges'][0]['node']['id'] == variant_id assert len(data['edges']) == 1
def test_product_type_update_mutation(admin_api_client, product_type): query = """ mutation updateProductType( $id: ID!, $name: String!, $hasVariants: Boolean!, $isShippingRequired: Boolean!, $productAttributes: [ID], ) { productTypeUpdate( id: $id, input: { name: $name, hasVariants: $hasVariants, isShippingRequired: $isShippingRequired, productAttributes: $productAttributes }) { productType { name isShippingRequired hasVariants variantAttributes { totalCount } productAttributes { totalCount } } } } """ product_type_name = 'test type updated' has_variants = True require_shipping = False product_type_id = graphene.Node.to_global_id('ProductType', product_type.id) # Test scenario: remove all product attributes using [] as input # but do not change variant attributes product_attributes = [] product_attributes_ids = [ graphene.Node.to_global_id('ProductAttribute', att.id) for att in product_attributes ] variant_attributes = product_type.variant_attributes.all() variables = json.dumps({ 'id': product_type_id, 'name': product_type_name, 'hasVariants': has_variants, 'isShippingRequired': require_shipping, 'productAttributes': product_attributes_ids }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productTypeUpdate'] assert data['productType']['name'] == product_type_name assert data['productType']['hasVariants'] == has_variants assert data['productType']['isShippingRequired'] == require_shipping assert data['productType']['productAttributes']['totalCount'] == 0 no_va = variant_attributes.count() assert data['productType']['variantAttributes']['totalCount'] == no_va
def test_product_type_create_mutation(admin_api_client, product_type): query = """ mutation createProductType( $name: String!, $taxRate: TaxRateType!, $hasVariants: Boolean!, $isShippingRequired: Boolean!, $productAttributes: [ID], $variantAttributes: [ID]) { productTypeCreate( input: { name: $name, taxRate: $taxRate, hasVariants: $hasVariants, isShippingRequired: $isShippingRequired, productAttributes: $productAttributes, variantAttributes: $variantAttributes}) { productType { name taxRate isShippingRequired hasVariants variantAttributes { edges { node { name } } } productAttributes { edges { node { name } } } } } } """ product_type_name = 'test type' has_variants = True require_shipping = True product_attributes = product_type.product_attributes.all() product_attributes_ids = [ graphene.Node.to_global_id('ProductAttribute', att.id) for att in product_attributes ] variant_attributes = product_type.variant_attributes.all() variant_attributes_ids = [ graphene.Node.to_global_id('ProductAttribute', att.id) for att in variant_attributes ] variables = json.dumps({ 'name': product_type_name, 'hasVariants': has_variants, 'taxRate': 'STANDARD', 'isShippingRequired': require_shipping, 'productAttributes': product_attributes_ids, 'variantAttributes': variant_attributes_ids }) initial_count = ProductType.objects.count() response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content assert ProductType.objects.count() == initial_count + 1 data = content['data']['productTypeCreate'] assert data['productType']['name'] == product_type_name assert data['productType']['hasVariants'] == has_variants assert data['productType']['isShippingRequired'] == require_shipping no_pa = product_attributes.count() assert len(data['productType']['productAttributes']['edges']) == no_pa no_va = variant_attributes.count() assert len(data['productType']['variantAttributes']['edges']) == no_va new_instance = ProductType.objects.latest('pk') assert new_instance.tax_rate == 'standard'
def test_product_query(admin_api_client, product): category = Category.objects.first() product = category.products.first() query = ''' query { category(id: "%(category_id)s") { products { edges { node { id name url thumbnailUrl images { edges { node { url } } } variants { edges { node { name stockQuantity } } } availability { available, priceRange { start { gross { amount currency localized } net { amount currency localized } currency } } } purchaseCost { start { amount } stop { amount } } margin { start stop } } } } } } ''' % { 'category_id': graphene.Node.to_global_id('Category', category.id) } response = admin_api_client.post(reverse('api'), {'query': query}) content = get_graphql_content(response) assert 'errors' not in content assert content['data']['category'] is not None product_edges_data = content['data']['category']['products']['edges'] assert len(product_edges_data) == category.products.count() product_data = product_edges_data[0]['node'] assert product_data['name'] == product.name assert product_data['url'] == product.get_absolute_url() gross = product_data['availability']['priceRange']['start']['gross'] assert float(gross['amount']) == float(product.price.amount) from saleor.product.utils.costs import get_product_costs_data purchase_cost, margin = get_product_costs_data(product) assert purchase_cost.start.amount == product_data['purchaseCost']['start'][ 'amount'] assert purchase_cost.stop.amount == product_data['purchaseCost']['stop'][ 'amount'] assert margin[0] == product_data['margin']['start'] assert margin[1] == product_data['margin']['stop']
def test_update_product(admin_api_client, category, non_default_category, product): query = """ mutation updateProduct( $productId: ID!, $categoryId: ID!, $name: String!, $description: String!, $isPublished: Boolean!, $chargeTaxes: Boolean!, $taxRate: TaxRateType!, $price: Decimal!, $attributes: [AttributeValueInput!]) { productUpdate( id: $productId, input: { category: $categoryId, name: $name, description: $description, isPublished: $isPublished, chargeTaxes: $chargeTaxes, taxRate: $taxRate, price: $price, attributes: $attributes }) { product { category { name } description isPublished chargeTaxes taxRate name price { amount } productType { name } attributes { attribute { name } value { name } } } errors { message field } } } """ product_id = graphene.Node.to_global_id('Product', product.pk) category_id = graphene.Node.to_global_id('Category', non_default_category.pk) product_description = 'updated description' product_name = 'updated name' product_isPublished = True product_chargeTaxes = True product_taxRate = 'STANDARD' product_price = "33.12" variables = json.dumps({ 'productId': product_id, 'categoryId': category_id, 'name': product_name, 'description': product_description, 'isPublished': product_isPublished, 'chargeTaxes': product_chargeTaxes, 'taxRate': product_taxRate, 'price': product_price }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productUpdate'] assert data['errors'] == [] assert data['product']['name'] == product_name assert data['product']['description'] == product_description assert data['product']['isPublished'] == product_isPublished assert data['product']['chargeTaxes'] == product_chargeTaxes assert data['product']['taxRate'] == product_taxRate.lower() assert not data['product']['category']['name'] == category.name
def test_create_product(admin_api_client, product_type, category, size_attribute): query = """ mutation createProduct( $productTypeId: ID!, $categoryId: ID! $name: String!, $description: String!, $isPublished: Boolean!, $chargeTaxes: Boolean!, $taxRate: TaxRateType!, $price: Decimal!, $attributes: [AttributeValueInput!]) { productCreate( input: { category: $categoryId, productType: $productTypeId, name: $name, description: $description, isPublished: $isPublished, chargeTaxes: $chargeTaxes, taxRate: $taxRate, price: $price, attributes: $attributes }) { product { category { name } description isPublished chargeTaxes taxRate name price { amount } productType { name } attributes { attribute { slug } value { slug } } } errors { message field } } } """ product_type_id = graphene.Node.to_global_id('ProductType', product_type.pk) category_id = graphene.Node.to_global_id('Category', category.pk) product_description = 'test description' product_name = 'test name' product_isPublished = True product_chargeTaxes = True product_taxRate = 'STANDARD' product_price = "22.33" # Default attribute defined in product_type fixture color_attr = product_type.product_attributes.get(name='Color') color_value_slug = color_attr.values.first().slug color_attr_slug = color_attr.slug # Add second attribute product_type.product_attributes.add(size_attribute) size_attr_slug = product_type.product_attributes.get(name='Size').slug non_existent_attr_value = 'The cake is a lie' # test creating root product variables = json.dumps({ 'productTypeId': product_type_id, 'categoryId': category_id, 'name': product_name, 'description': product_description, 'isPublished': product_isPublished, 'chargeTaxes': product_chargeTaxes, 'taxRate': product_taxRate, 'price': product_price, 'attributes': [{ 'slug': color_attr_slug, 'value': color_value_slug }, { 'slug': size_attr_slug, 'value': non_existent_attr_value }] }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productCreate'] assert data['errors'] == [] assert data['product']['name'] == product_name assert data['product']['description'] == product_description assert data['product']['isPublished'] == product_isPublished assert data['product']['chargeTaxes'] == product_chargeTaxes assert data['product']['taxRate'] == product_taxRate.lower() assert data['product']['productType']['name'] == product_type.name assert data['product']['category']['name'] == category.name values = (data['product']['attributes'][0]['value']['slug'], data['product']['attributes'][1]['value']['slug']) assert slugify(non_existent_attr_value) in values assert color_value_slug in values
def test_create_variant(admin_api_client, product, product_type): query = """ mutation createVariant ( $productId: ID!, $sku: String!, $priceOverride: Decimal, $costPrice: Decimal, $quantity: Int!, $attributes: [AttributeValueInput], $weight: WeightScalar, $trackInventory: Boolean!) { productVariantCreate( input: { product: $productId, sku: $sku, priceOverride: $priceOverride, costPrice: $costPrice, quantity: $quantity, attributes: $attributes, trackInventory: $trackInventory, weight: $weight }) { productVariant { name sku attributes { attribute { slug } value { slug } } quantity priceOverride { currency amount localized } costPrice { currency amount localized } weight { value unit } } } } """ product_id = graphene.Node.to_global_id('Product', product.pk) sku = "1" price_override = 1.32 cost_price = 3.22 quantity = 10 weight = 10.22 variant_slug = product_type.variant_attributes.first().slug variant_value = 'test-value' variables = json.dumps({ 'productId': product_id, 'sku': sku, 'quantity': quantity, 'costPrice': cost_price, 'priceOverride': price_override, 'weight': weight, 'attributes': [{ 'slug': variant_slug, 'value': variant_value }], 'trackInventory': True }) response = admin_api_client.post(reverse('api'), { 'query': query, 'variables': variables }) content = get_graphql_content(response) assert 'errors' not in content data = content['data']['productVariantCreate']['productVariant'] assert data['name'] == variant_value assert data['quantity'] == quantity assert data['costPrice']['amount'] == cost_price assert data['priceOverride']['amount'] == price_override assert data['sku'] == sku assert data['attributes'][0]['attribute']['slug'] == variant_slug assert data['attributes'][0]['value']['slug'] == variant_value assert data['weight']['unit'] == 'kg' assert data['weight']['value'] == weight