Skip to content

Commit

Permalink
Category webhook events added (#9490)
Browse files Browse the repository at this point in the history
* [SALEOR-6449] category webhook events added

* adjustments after PR review

* BasePLugin updated

* tests improvements

* add correct typing for category events in BasePlugin

* add graphql id in payload to handle case when where is no subscription_query
  • Loading branch information
szdrasiak committed Apr 11, 2022
1 parent 89d6e52 commit 6c3162f
Show file tree
Hide file tree
Showing 11 changed files with 561 additions and 76 deletions.
9 changes: 9 additions & 0 deletions saleor/graphql/product/mutations/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ def save(cls, info, instance, cleaned_input):
if cleaned_input.get("background_image"):
create_category_background_image_thumbnails.delay(instance.pk)

@classmethod
def post_save_action(cls, info, instance, _cleaned_input):
info.context.plugins.category_created(instance)


class CategoryUpdate(CategoryCreate):
class Arguments:
Expand All @@ -161,6 +165,10 @@ class Meta:
error_type_class = ProductError
error_type_field = "product_errors"

@classmethod
def post_save_action(cls, info, instance, _cleaned_input):
info.context.plugins.category_updated(instance)


class CategoryDelete(ModelDeleteMutation):
class Arguments:
Expand All @@ -184,6 +192,7 @@ def perform_mutation(cls, _root, info, **data):
delete_categories([db_id], manager=info.context.plugins)

instance.id = db_id
info.context.plugins.category_deleted(instance)
return cls.success_response(instance)


Expand Down
157 changes: 157 additions & 0 deletions saleor/graphql/product/tests/test_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@

import graphene
import pytest
from django.utils.functional import SimpleLazyObject
from django.utils.text import slugify
from graphql_relay import to_global_id

from ....product.error_codes import ProductErrorCode
from ....product.models import Category, Product, ProductChannelListing
from ....product.tests.utils import create_image, create_pdf_file_with_image_ext
from ....tests.utils import dummy_editorjs
from ....webhook.event_types import WebhookEventAsyncType
from ...tests.utils import (
get_graphql_content,
get_graphql_content_from_response,
Expand Down Expand Up @@ -444,6 +446,66 @@ def test_category_create_mutation(
assert data["category"]["parent"]["id"] == parent_id


@patch("saleor.plugins.webhook.plugin._get_webhooks_for_event")
@patch("saleor.plugins.webhook.plugin.trigger_webhooks_async")
def test_category_create_trigger_webhook(
mocked_webhook_trigger,
mocked_get_webhooks_for_event,
any_webhook,
monkeypatch,
staff_api_client,
permission_manage_products,
media_root,
settings,
):
query = CATEGORY_CREATE_MUTATION
mocked_get_webhooks_for_event.return_value = [any_webhook]
settings.PLUGINS = ["saleor.plugins.webhook.plugin.WebhookPlugin"]

mock_create_thumbnails = Mock(return_value=None)
monkeypatch.setattr(
(
"saleor.product.thumbnails."
"create_category_background_image_thumbnails.delay"
),
mock_create_thumbnails,
)

category_name = "Test category"
description = "description"
category_slug = slugify(category_name)
category_description = dummy_editorjs(description, True)
image_file, image_name = create_image()
image_alt = "Alt text for an image."

# test creating root category
variables = {
"name": category_name,
"description": category_description,
"backgroundImage": image_name,
"backgroundImageAlt": image_alt,
"slug": category_slug,
}
body = get_multipart_request_body(query, variables, image_file, image_name)
response = staff_api_client.post_multipart(
body, permissions=[permission_manage_products]
)
content = get_graphql_content(response)
data = content["data"]["categoryCreate"]
category = Category.objects.first()

assert category
assert data["errors"] == []

mocked_webhook_trigger.assert_called_once_with(
{"id": graphene.Node.to_global_id("Category", category.id)},
WebhookEventAsyncType.CATEGORY_CREATED,
[any_webhook],
category,
SimpleLazyObject(lambda: staff_api_client.user),
)


@pytest.mark.parametrize(
"input_slug, expected_slug",
(
Expand Down Expand Up @@ -605,6 +667,65 @@ def test_category_update_mutation(
assert data["category"]["backgroundImage"]["alt"] == image_alt


@patch("saleor.plugins.webhook.plugin._get_webhooks_for_event")
@patch("saleor.plugins.webhook.plugin.trigger_webhooks_async")
def test_category_update_trigger_webhook(
mocked_webhook_trigger,
mocked_get_webhooks_for_event,
any_webhook,
monkeypatch,
staff_api_client,
category,
permission_manage_products,
media_root,
settings,
):
mocked_get_webhooks_for_event.return_value = [any_webhook]
settings.PLUGINS = ["saleor.plugins.webhook.plugin.WebhookPlugin"]
mock_create_thumbnails = Mock(return_value=None)
monkeypatch.setattr(
(
"saleor.product.thumbnails."
"create_category_background_image_thumbnails.delay"
),
mock_create_thumbnails,
)

category_name = "Updated name"
description = "description"
category_slug = slugify(category_name)
category_description = dummy_editorjs(description, True)

image_file, image_name = create_image()
image_alt = "Alt text for an image."

variables = {
"name": category_name,
"description": category_description,
"backgroundImage": image_name,
"backgroundImageAlt": image_alt,
"id": graphene.Node.to_global_id("Category", category.pk),
"slug": category_slug,
}
body = get_multipart_request_body(
MUTATION_CATEGORY_UPDATE_MUTATION, variables, image_file, image_name
)
response = staff_api_client.post_multipart(
body, permissions=[permission_manage_products]
)
content = get_graphql_content(response)
data = content["data"]["categoryUpdate"]
assert data["errors"] == []

mocked_webhook_trigger.assert_called_once_with(
{"id": variables["id"]},
WebhookEventAsyncType.CATEGORY_UPDATED,
[any_webhook],
category,
SimpleLazyObject(lambda: staff_api_client.user),
)


def test_category_update_mutation_invalid_background_image(
staff_api_client, category, permission_manage_products
):
Expand Down Expand Up @@ -867,6 +988,42 @@ def test_category_delete_mutation(
delete_versatile_image_mock.assert_not_called()


@patch("saleor.product.signals.delete_versatile_image")
@patch("saleor.plugins.webhook.plugin._get_webhooks_for_event")
@patch("saleor.plugins.webhook.plugin.trigger_webhooks_async")
def test_category_delete_trigger_webhook(
mocked_webhook_trigger,
mocked_get_webhooks_for_event,
delete_versatile_image_mock,
any_webhook,
staff_api_client,
category,
permission_manage_products,
settings,
):
mocked_get_webhooks_for_event.return_value = [any_webhook]
settings.PLUGINS = ["saleor.plugins.webhook.plugin.WebhookPlugin"]

variables = {"id": graphene.Node.to_global_id("Category", category.id)}
response = staff_api_client.post_graphql(
MUTATION_CATEGORY_DELETE, variables, permissions=[permission_manage_products]
)
content = get_graphql_content(response)
data = content["data"]["categoryDelete"]
assert data["category"]["name"] == category.name

assert not Category.objects.first()

delete_versatile_image_mock.assert_not_called()
mocked_webhook_trigger.assert_called_once_with(
{"id": variables["id"]},
WebhookEventAsyncType.CATEGORY_DELETED,
[any_webhook],
category,
SimpleLazyObject(lambda: staff_api_client.user),
)


@patch("saleor.product.signals.delete_versatile_image")
def test_delete_category_with_background_image(
delete_versatile_image_mock,
Expand Down
107 changes: 106 additions & 1 deletion saleor/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1093,42 +1093,114 @@ type WebhookEvent {

"""Enum determining type of webhook."""
enum WebhookEventTypeEnum {
"""All the events."""
ANY_EVENTS

"""A new category created."""
CATEGORY_CREATED

"""A category is updated."""
CATEGORY_UPDATED

"""A category is deleted."""
CATEGORY_DELETED

"""A new order is placed."""
ORDER_CREATED

"""
An order is confirmed (status change unconfirmed -> unfulfilled) by a staff user using the OrderConfirm mutation. It also triggers when the user completes the checkout and the shop setting `automatically_confirm_all_new_orders` is enabled.
"""
ORDER_CONFIRMED

"""Payment is made and an order is fully paid."""
ORDER_FULLY_PAID

"""
An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED.
"""
ORDER_UPDATED

"""An order is cancelled."""
ORDER_CANCELLED

"""An order is fulfilled."""
ORDER_FULFILLED
DRAFT_ORDER_CREATED
DRAFT_ORDER_UPDATED
DRAFT_ORDER_DELETED
SALE_CREATED
SALE_UPDATED
SALE_DELETED

"""An invoice for order requested."""
INVOICE_REQUESTED

"""An invoice is deleted."""
INVOICE_DELETED

"""Invoice has been sent."""
INVOICE_SENT

"""A new customer account is created."""
CUSTOMER_CREATED

"""A customer account is updated."""
CUSTOMER_UPDATED

"""A new collection is created."""
COLLECTION_CREATED

"""A collection is updated."""
COLLECTION_UPDATED

"""A collection is deleted."""
COLLECTION_DELETED

"""A new product is created."""
PRODUCT_CREATED

"""A product is updated."""
PRODUCT_UPDATED

"""A product is deleted."""
PRODUCT_DELETED

"""A new product variant is created."""
PRODUCT_VARIANT_CREATED

"""A product variant is updated."""
PRODUCT_VARIANT_UPDATED

"""A product variant is deleted."""
PRODUCT_VARIANT_DELETED
PRODUCT_VARIANT_OUT_OF_STOCK
PRODUCT_VARIANT_BACK_IN_STOCK

"""A new checkout is created."""
CHECKOUT_CREATED

"""
A checkout is updated. It also triggers all updates related to the checkout.
"""
CHECKOUT_UPDATED

"""A new fulfillment is created."""
FULFILLMENT_CREATED

"""A fulfillment is cancelled."""
FULFILLMENT_CANCELED

"""User notification triggered."""
NOTIFY_USER

"""A new page is created."""
PAGE_CREATED

"""A page is updated."""
PAGE_UPDATED

"""A page is deleted."""
PAGE_DELETED
TRANSLATION_CREATED
TRANSLATION_UPDATED
Expand Down Expand Up @@ -1181,6 +1253,15 @@ enum WebhookEventTypeAsyncEnum {
"""All the events."""
ANY_EVENTS

"""A new category created."""
CATEGORY_CREATED

"""A category is updated."""
CATEGORY_UPDATED

"""A category is deleted."""
CATEGORY_DELETED

"""A new order is placed."""
ORDER_CREATED

Expand Down Expand Up @@ -1640,6 +1721,9 @@ scalar JSONString

"""An enumeration."""
enum WebhookSampleEventTypeEnum {
CATEGORY_CREATED
CATEGORY_UPDATED
CATEGORY_DELETED
ORDER_CREATED
ORDER_CONFIRMED
ORDER_FULLY_PAID
Expand Down Expand Up @@ -16461,7 +16545,28 @@ type Subscription {
event: Event
}

union Event = OrderCreated | OrderUpdated | OrderConfirmed | OrderFullyPaid | OrderCancelled | OrderFulfilled | DraftOrderCreated | DraftOrderUpdated | DraftOrderDeleted | ProductCreated | ProductUpdated | ProductDeleted | ProductVariantCreated | ProductVariantUpdated | ProductVariantOutOfStock | ProductVariantBackInStock | ProductVariantDeleted | SaleCreated | SaleUpdated | SaleDeleted | InvoiceRequested | InvoiceDeleted | InvoiceSent | FulfillmentCreated | FulfillmentCanceled | CustomerCreated | CustomerUpdated | CollectionCreated | CollectionUpdated | CollectionDeleted | CheckoutCreated | CheckoutUpdated | PageCreated | PageUpdated | PageDeleted | TranslationCreated | TranslationUpdated
union Event = CategoryCreated | CategoryUpdated | CategoryDeleted | OrderCreated | OrderUpdated | OrderConfirmed | OrderFullyPaid | OrderCancelled | OrderFulfilled | DraftOrderCreated | DraftOrderUpdated | DraftOrderDeleted | ProductCreated | ProductUpdated | ProductDeleted | ProductVariantCreated | ProductVariantUpdated | ProductVariantOutOfStock | ProductVariantBackInStock | ProductVariantDeleted | SaleCreated | SaleUpdated | SaleDeleted | InvoiceRequested | InvoiceDeleted | InvoiceSent | FulfillmentCreated | FulfillmentCanceled | CustomerCreated | CustomerUpdated | CollectionCreated | CollectionUpdated | CollectionDeleted | CheckoutCreated | CheckoutUpdated | PageCreated | PageUpdated | PageDeleted | TranslationCreated | TranslationUpdated

type CategoryCreated {
"""
New in Saleor 3.2. Look up a category. Note: this feature is in a preview state and can be subject to changes at later point.
"""
category: Category
}

type CategoryUpdated {
"""
New in Saleor 3.2. Look up a category. Note: this feature is in a preview state and can be subject to changes at later point.
"""
category: Category
}

type CategoryDeleted {
"""
New in Saleor 3.2. Look up a category. Note: this feature is in a preview state and can be subject to changes at later point.
"""
category: Category
}

type OrderCreated {
"""
Expand Down

0 comments on commit 6c3162f

Please sign in to comment.