From 1d885ea238f30bc3b667434778728cda28d36825 Mon Sep 17 00:00:00 2001 From: David Remer Date: Thu, 26 Oct 2023 09:08:24 +0300 Subject: [PATCH] Add order created|cancelled|completed triggers [MAILPOET-5661] --- .../integrations/woocommerce/index.tsx | 6 ++ .../steps/order-cancelled/icon.tsx | 36 +++++++ .../steps/order-cancelled/index.tsx | 18 ++++ .../steps/order-completed/icon.tsx | 36 +++++++ .../steps/order-completed/index.tsx | 18 ++++ .../woocommerce/steps/order-created/icon.tsx | 16 +++ .../woocommerce/steps/order-created/index.tsx | 22 ++++ mailpoet/lib/Automation/Engine/WordPress.php | 4 + .../Triggers/Orders/OrderCancelledTrigger.php | 28 +++++ .../Triggers/Orders/OrderCompletedTrigger.php | 28 +++++ .../Triggers/Orders/OrderCreatedTrigger.php | 100 ++++++++++++++++++ .../Orders/OrderStatusChangedTrigger.php | 4 +- .../WooCommerce/WooCommerceIntegration.php | 20 ++++ mailpoet/lib/DI/ContainerConfigurator.php | 3 + .../Orders/AbstractOrderSingleStatusTest.php | 57 ++++++++++ .../Orders/OrderCancelledTriggerTest.php | 19 ++++ .../Orders/OrderCompletedTriggerTest.php | 19 ++++ .../Orders/OrderCreatedTriggerTest.php | 71 +++++++++++++ .../Orders/OrderStatusChangeTriggerTest.php | 3 + 19 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/icon.tsx create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/index.tsx create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/icon.tsx create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/index.tsx create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/icon.tsx create mode 100644 mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/index.tsx create mode 100644 mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTrigger.php create mode 100644 mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTrigger.php create mode 100644 mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTrigger.php create mode 100644 mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/AbstractOrderSingleStatusTest.php create mode 100644 mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTriggerTest.php create mode 100644 mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTriggerTest.php create mode 100644 mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTriggerTest.php diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/index.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/index.tsx index 4520d1a4c8..0cb5f83a05 100644 --- a/mailpoet/assets/js/src/automation/integrations/woocommerce/index.tsx +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/index.tsx @@ -1,5 +1,8 @@ import { registerStepType } from '../../editor/store'; import { step as OrderStatusChanged } from './steps/order-status-changed'; +import { step as OrderCompletedTrigger } from './steps/order-completed'; +import { step as OrderCancelledTrigger } from './steps/order-cancelled'; +import { step as OrderCreatedTrigger } from './steps/order-created'; import { step as AbandonedCartTrigger } from './steps/abandoned-cart'; import { MailPoet } from '../../../mailpoet'; import { step as BuysAProductTrigger } from './steps/buys-a-product'; @@ -12,6 +15,9 @@ export const initialize = (): void => { return; } registerStepType(OrderStatusChanged); + registerStepType(OrderCompletedTrigger); + registerStepType(OrderCancelledTrigger); + registerStepType(OrderCreatedTrigger); registerStepType(AbandonedCartTrigger); registerStepType(BuysAProductTrigger); registerStepType(BuysFromACategory); diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/icon.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/icon.tsx new file mode 100644 index 0000000000..02b52dc60b --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/icon.tsx @@ -0,0 +1,36 @@ +export function Icon(): JSX.Element { + return ( + + + + + + + + ); +} diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/index.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/index.tsx new file mode 100644 index 0000000000..ea52a7a854 --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-cancelled/index.tsx @@ -0,0 +1,18 @@ +import { __, _x } from '@wordpress/i18n'; +import { StepType } from '../../../../editor/store'; +import { Icon } from './icon'; + +const keywords = [__('woocommerce', 'mailpoet'), __('order', 'mailpoet')]; +export const step: StepType = { + key: 'woocommerce:order-cancelled', + group: 'triggers', + title: () => __('Order cancelled', 'mailpoet'), + description: () => + __('Start the automation when an order is cancelled.', 'mailpoet'), + subtitle: () => _x('Trigger', 'noun', 'mailpoet'), + keywords, + foreground: '#2271b1', + background: '#f0f6fc', + icon: () => , + edit: () => null, +} as const; diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/icon.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/icon.tsx new file mode 100644 index 0000000000..34b4de906c --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/icon.tsx @@ -0,0 +1,36 @@ +export function Icon(): JSX.Element { + return ( + + + + + + + + ); +} diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/index.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/index.tsx new file mode 100644 index 0000000000..3c28ae90bb --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-completed/index.tsx @@ -0,0 +1,18 @@ +import { __, _x } from '@wordpress/i18n'; +import { StepType } from '../../../../editor/store'; +import { Icon } from './icon'; + +const keywords = [__('woocommerce', 'mailpoet'), __('order', 'mailpoet')]; +export const step: StepType = { + key: 'woocommerce:order-completed', + group: 'triggers', + title: () => __('Order completed', 'mailpoet'), + description: () => + __('Start the automation when an order is completed.', 'mailpoet'), + subtitle: () => _x('Trigger', 'noun', 'mailpoet'), + keywords, + foreground: '#2271b1', + background: '#f0f6fc', + icon: () => , + edit: () => null, +} as const; diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/icon.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/icon.tsx new file mode 100644 index 0000000000..6e452fc6ab --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/icon.tsx @@ -0,0 +1,16 @@ +export function Icon(): JSX.Element { + return ( + + + + ); +} diff --git a/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/index.tsx b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/index.tsx new file mode 100644 index 0000000000..6966d88c0e --- /dev/null +++ b/mailpoet/assets/js/src/automation/integrations/woocommerce/steps/order-created/index.tsx @@ -0,0 +1,22 @@ +import { __, _x } from '@wordpress/i18n'; +import { StepType } from '../../../../editor/store'; +import { Icon } from './icon'; + +const keywords = [ + __('woocommerce', 'mailpoet'), + __('order', 'mailpoet'), + __('new', 'mailpoet'), +]; +export const step: StepType = { + key: 'woocommerce:order-created', + group: 'triggers', + title: () => __('Order created', 'mailpoet'), + description: () => + __('Start the automation when an order is created.', 'mailpoet'), + subtitle: () => _x('Trigger', 'noun', 'mailpoet'), + keywords, + foreground: '#2271b1', + background: '#f0f6fc', + icon: () => , + edit: () => null, +} as const; diff --git a/mailpoet/lib/Automation/Engine/WordPress.php b/mailpoet/lib/Automation/Engine/WordPress.php index 909b82af4d..6cb815b6db 100644 --- a/mailpoet/lib/Automation/Engine/WordPress.php +++ b/mailpoet/lib/Automation/Engine/WordPress.php @@ -21,6 +21,10 @@ class WordPress { return add_action($hookName, $callback, $priority, $acceptedArgs); } + public function removeAction(string $hookName, callable $callback, int $priority = 10): bool { + return remove_action($hookName, $callback, $priority); + } + /** @param mixed ...$arg */ public function doAction(string $hookName, ...$arg): void { do_action($hookName, ...$arg); diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTrigger.php b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTrigger.php new file mode 100644 index 0000000000..3676eacbd3 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTrigger.php @@ -0,0 +1,28 @@ +getSinglePayloadByClass(OrderStatusChangePayload::class); + return $orderPayload->getTo() === 'cancelled'; + } + + public function getArgsSchema(): ObjectSchema { + return Builder::object(); + } +} diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTrigger.php b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTrigger.php new file mode 100644 index 0000000000..99b6db9a92 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTrigger.php @@ -0,0 +1,28 @@ +getSinglePayloadByClass(OrderStatusChangePayload::class); + return $orderPayload->getTo() === 'completed'; + } + + public function getArgsSchema(): ObjectSchema { + return Builder::object(); + } +} diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTrigger.php b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTrigger.php new file mode 100644 index 0000000000..057f83bce0 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTrigger.php @@ -0,0 +1,100 @@ +wp = $wp; + } + + public function getKey(): string { + return 'woocommerce:order-created'; + } + + public function getName(): string { + return __('Order created', 'mailpoet'); + } + + public function registerHooks(): void { + $this->wp->addAction( + 'woocommerce_new_order', + [ + $this, + 'handleCreate', + ], + 10, + 2 + ); + } + + /** + * @param int $orderId + * @param \WC_Order $order + * @return void + */ + public function handleCreate($orderId, $order) { + + if (in_array($orderId, $this->processedOrders)) { + return; + } + /** + * Creating an order via wc_create_order() does not yet set crucial information like the customer's email address. + * It just creates the order object and saves it to the database. We need therefore to wait for the order to have at least the billing address stored. + **/ + if (!$order->get_billing_email()) { + add_action( + 'woocommerce_after_order_object_save', + function($order) use ($orderId) { + if ((int)$orderId !== (int)$order->get_id()) { + return; + } + $this->handleCreate($order->get_id(), $order); + } + ); + return; + } + $this->processedOrders[] = $orderId; + $this->wp->doAction(Hooks::TRIGGER, $this, [ + new Subject(OrderSubject::KEY, ['order_id' => $order->get_id()]), + new Subject(CustomerSubject::KEY, ['customer_id' => $order->get_customer_id()]), + ]); + } + + public function isTriggeredBy(StepRunArgs $args): bool { + return true; + } + + public function getArgsSchema(): ObjectSchema { + return Builder::object(); + } + + public function getSubjectKeys(): array { + return [ + OrderSubject::KEY, + CustomerSubject::KEY, + ]; + } + + public function validate(StepValidationArgs $args): void { + } +} diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangedTrigger.php b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangedTrigger.php index 9376ef9dfc..cb57361ce4 100644 --- a/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangedTrigger.php +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangedTrigger.php @@ -19,10 +19,10 @@ use MailPoet\WP\Functions; class OrderStatusChangedTrigger implements Trigger { /** @var Functions */ - private $wp; + protected $wp; /** @var WooCommerce */ - private $woocommerce; + protected $woocommerce; public function __construct( Functions $wp, diff --git a/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php b/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php index 95b9ccb6c1..4fdb935ed6 100644 --- a/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php +++ b/mailpoet/lib/Automation/Integrations/WooCommerce/WooCommerceIntegration.php @@ -11,6 +11,9 @@ use MailPoet\Automation\Integrations\WooCommerce\SubjectTransformers\WordPressUs use MailPoet\Automation\Integrations\WooCommerce\Triggers\AbandonedCart\AbandonedCartTrigger; use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger; use MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromACategoryTrigger; +use MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCancelledTrigger; +use MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCompletedTrigger; +use MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCreatedTrigger; use MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderStatusChangedTrigger; class WooCommerceIntegration { @@ -18,6 +21,14 @@ class WooCommerceIntegration { /** @var OrderStatusChangedTrigger */ private $orderStatusChangedTrigger; + /** @var OrderCreatedTrigger */ + private $orderCreatedTrigger; + + /** @var OrderCompletedTrigger */ + private $orderCompletedTrigger; + + private $orderCancelledTrigger; + /** @var AbandonedCartTrigger */ private $abandonedCartTrigger; @@ -50,6 +61,9 @@ class WooCommerceIntegration { public function __construct( OrderStatusChangedTrigger $orderStatusChangedTrigger, + OrderCreatedTrigger $orderCreatedTrigger, + OrderCompletedTrigger $orderCompletedTrigger, + OrderCancelledTrigger $orderCancelledTrigger, AbandonedCartTrigger $abandonedCartTrigger, BuysAProductTrigger $buysAProductTrigger, BuysFromACategoryTrigger $buysFromACategoryTrigger, @@ -62,6 +76,9 @@ class WooCommerceIntegration { WooCommerce $wooCommerce ) { $this->orderStatusChangedTrigger = $orderStatusChangedTrigger; + $this->orderCreatedTrigger = $orderCreatedTrigger; + $this->orderCompletedTrigger = $orderCompletedTrigger; + $this->orderCancelledTrigger = $orderCancelledTrigger; $this->abandonedCartTrigger = $abandonedCartTrigger; $this->buysAProductTrigger = $buysAProductTrigger; $this->buysFromACategoryTrigger = $buysFromACategoryTrigger; @@ -88,6 +105,9 @@ class WooCommerceIntegration { $registry->addSubject($this->orderStatusChangeSubject); $registry->addSubject($this->customerSubject); $registry->addTrigger($this->orderStatusChangedTrigger); + $registry->addTrigger($this->orderCreatedTrigger); + $registry->addTrigger($this->orderCompletedTrigger); + $registry->addTrigger($this->orderCancelledTrigger); $registry->addTrigger($this->abandonedCartTrigger); $registry->addTrigger($this->buysAProductTrigger); $registry->addTrigger($this->buysFromACategoryTrigger); diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index 67afef26eb..6f7a973cd3 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -208,6 +208,9 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Fields\TermOptionsBuilder::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Fields\TermParentsLoader::class)->setPublic(true); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderStatusChangedTrigger::class)->setPublic(true)->setShared(false); + $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCreatedTrigger::class)->setPublic(true)->setShared(false); + $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCompletedTrigger::class)->setPublic(true)->setShared(false); + $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderCancelledTrigger::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysAProductTrigger::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Triggers\BuysFromACategoryTrigger::class)->setPublic(true)->setShared(false); $container->autowire(\MailPoet\Automation\Integrations\WooCommerce\Subjects\OrderSubject::class)->setPublic(true)->setShared(false); diff --git a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/AbstractOrderSingleStatusTest.php b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/AbstractOrderSingleStatusTest.php new file mode 100644 index 0000000000..7ee7f50c6f --- /dev/null +++ b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/AbstractOrderSingleStatusTest.php @@ -0,0 +1,57 @@ +createMock(OrderStatusChangePayload::class); + $statusChangePayload->method('getFrom')->willReturn($from); + $statusChangePayload->method('getTo')->willReturn($to); + $stepRunArgs = $this->createMock(StepRunArgs::class); + $stepRunArgs->method('getSinglePayloadByClass')->willReturn($statusChangePayload); + $this->assertEquals($expected, $this->getTestee()->isTriggeredBy($stepRunArgs)); + } + + public function dataTestIsTriggeredBy() { + $statuses = [ + 'pending', + 'processing', + 'on-hold', + 'completed', + 'cancelled', + 'refunded', + 'failed', + ]; + + $data = []; + foreach ($statuses as $from) { + foreach ($statuses as $to) { + if ($from === $to) { + continue; + } + $data[sprintf('from_%s_to_%s', $from, $to)] = [ + 'from' => $from, + 'to' => $to, + 'expected' => $to === $this->getTriggerStatus(), + ]; + } + } + return $data; + } +} diff --git a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTriggerTest.php b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTriggerTest.php new file mode 100644 index 0000000000..472032089b --- /dev/null +++ b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCancelledTriggerTest.php @@ -0,0 +1,19 @@ +diContainer->get(OrderCancelledTrigger::class); + } + + protected function getTriggerStatus(): string { + return 'cancelled'; + } +} diff --git a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTriggerTest.php b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTriggerTest.php new file mode 100644 index 0000000000..a5b5ffc57e --- /dev/null +++ b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCompletedTriggerTest.php @@ -0,0 +1,19 @@ +diContainer->get(OrderCompletedTrigger::class); + } + + protected function getTriggerStatus(): string { + return 'completed'; + } +} diff --git a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTriggerTest.php b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTriggerTest.php new file mode 100644 index 0000000000..4df1acd25f --- /dev/null +++ b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderCreatedTriggerTest.php @@ -0,0 +1,71 @@ +testee = $this->diContainer->get(OrderCreatedTrigger::class); + $this->runStorage = $this->diContainer->get(AutomationRunStorage::class); + } + + public function testCreatesRunWhenANewOrderIsCreated() { + $orderCreatedTriggerStep = new Step( + uniqid(), + Step::TYPE_TRIGGER, + $this->testee->getKey(), + [], + [] + ); + $automation = (new AutomationFactory()) + ->withStep($orderCreatedTriggerStep) + ->withDelayAction() + ->withStatusActive() + ->create(); + $this->testee->registerHooks(); + + $this->assertEmpty($this->runStorage->getAutomationRunsForAutomation($automation)); + + $order = wc_create_order(['customer_id' => 1]); + $this->assertInstanceOf(\WC_Order::class, $order); + + $runs = $this->runStorage->getAutomationRunsForAutomation($automation); + $this->assertCount(1, $runs); + /** @var AutomationRun $run */ + $run = current($runs); + + $subject = $run->getSubjects(OrderSubject::KEY)[0]; + $this->assertEquals($order->get_id(), $subject->getArgs()['order_id']); + + // Test with no email address available yet. + $order = wc_create_order(); + $this->assertInstanceOf(\WC_Order::class, $order); + + $runs = $this->runStorage->getAutomationRunsForAutomation($automation); + $this->assertCount(1, $runs); + $order->set_billing_email('someone@example.com'); + $order->save(); + $runs = $this->runStorage->getAutomationRunsForAutomation($automation); + $this->assertCount(2, $runs); + $order->set_status('failed'); + $order->save(); + $runs = $this->runStorage->getAutomationRunsForAutomation($automation); + $this->assertCount(2, $runs); + } +} diff --git a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangeTriggerTest.php b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangeTriggerTest.php index 0f4b6dbc10..d67c0e568d 100644 --- a/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangeTriggerTest.php +++ b/mailpoet/tests/integration/Automation/Integrations/WooCommerce/Triggers/Orders/OrderStatusChangeTriggerTest.php @@ -6,6 +6,9 @@ use MailPoet\Automation\Engine\Data\StepRunArgs; use MailPoet\Automation\Integrations\WooCommerce\Payloads\OrderStatusChangePayload; use MailPoet\Automation\Integrations\WooCommerce\Triggers\Orders\OrderStatusChangedTrigger; +/** + * @group woo + */ class OrderStatusChangeTriggerTest extends \MailPoetTest { /** * @dataProvider dataTestIsTriggeredBy