From 3242704c8765fe985fec1e4a819066a1583e8ac3 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 11:04:36 +0100 Subject: [PATCH 1/8] add basic kernel tests --- tests/src/Kernel/AlterProductEventTest.php | 70 +++++++ tests/src/Kernel/CommerceKernelTestBase.php | 32 +++ tests/src/Unit/AlterEventDataEventTest.php | 186 ++++++++++++++++++ .../src/Unit/EnhancedEcommerceEventsTest.php | 49 +++++ 4 files changed, 337 insertions(+) create mode 100644 tests/src/Kernel/AlterProductEventTest.php create mode 100644 tests/src/Kernel/CommerceKernelTestBase.php create mode 100644 tests/src/Unit/AlterEventDataEventTest.php create mode 100644 tests/src/Unit/EnhancedEcommerceEventsTest.php diff --git a/tests/src/Kernel/AlterProductEventTest.php b/tests/src/Kernel/AlterProductEventTest.php new file mode 100644 index 0000000..33c3257 --- /dev/null +++ b/tests/src/Kernel/AlterProductEventTest.php @@ -0,0 +1,70 @@ +variation = ProductVariation::create([ + 'type' => 'default', + 'sku' => $this->randomString(10), + 'status' => TRUE, + ]); + $this->variation->save(); + + $this->product = new Product(); + $this->product + ->setName($this->randomString(16)) + ->setId(1) + ->setVariant($this->variation->getTitle()) + ->setPrice('11.99'); + } + + /** + * @covers ::getProduct + */ + public function testGetProduct() { + $event = new AlterProductEvent($this->product, $this->variation); + $this->assertInstanceOf(Product::class, $event->getProduct()); + } + + /** + * @covers ::getProductVariation + */ + public function testGetProductVariation() { + $event = new AlterProductEvent($this->product, $this->variation); + $this->assertInstanceOf(ProductVariationInterface::class, $event->getProductVariation()); + } + +} diff --git a/tests/src/Kernel/CommerceKernelTestBase.php b/tests/src/Kernel/CommerceKernelTestBase.php new file mode 100644 index 0000000..4c502ce --- /dev/null +++ b/tests/src/Kernel/CommerceKernelTestBase.php @@ -0,0 +1,32 @@ +installEntitySchema('commerce_product_variation'); + $this->installEntitySchema('commerce_product'); + $this->installConfig(['commerce_product']); + } + +} diff --git a/tests/src/Unit/AlterEventDataEventTest.php b/tests/src/Unit/AlterEventDataEventTest.php new file mode 100644 index 0000000..4f69366 --- /dev/null +++ b/tests/src/Unit/AlterEventDataEventTest.php @@ -0,0 +1,186 @@ +alterEventData = new AlterEventDataEvent([]); + } + + /** + * @covers ::setEventData + * @covers ::getEventData + * + * @dataProvider eventData + */ + public function testSetEventDetailViews($event_data) { + $this->alterEventData->setEventData($event_data); + $this->assertSame($event_data, $this->alterEventData->getEventData()); + } + + /** + * List of supported event data. + * + * @return array + * Examples of event data structure by event types. + */ + public function eventData() { + return [ + 'Product detail views' => [ + [ + 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, + 'ecommerce' => [ + 'detail' => [ + 'actionField' => [ + 'list' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + ], + ], + ], + ], + ], + ], + + // @todo add product impression example. + 'Product impressions' => [ + [ + 'event' => EventTrackerService::EVENT_PRODUCT_IMPRESSIONS, + 'ecommerce' => [], + ], + ], + + // @todo add product click example. + 'Product click' => [ + [ + 'event' => EventTrackerService::EVENT_PRODUCT_CLICK, + 'ecommerce' => [], + ], + ], + + 'Add to cart' => [ + [ + 'event' => EventTrackerService::EVENT_ADD_CART, + 'ecommerce' => [ + 'currencyCode' => 'CHF', + 'add' => [ + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + 'quantity' => 1, + ], + ], + ], + ], + ], + ], + + 'Remove to cart' => [ + [ + 'event' => EventTrackerService::EVENT_REMOVE_CART, + 'ecommerce' => [ + 'remove' => [ + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + 'quantity' => 1, + ], + ], + ], + ], + ], + ], + + 'Checkout' => [ + [ + 'event' => EventTrackerService::EVENT_CHECKOUT, + 'ecommerce' => [ + 'checkout' => [ + 'actionField' => [ + 'step' => 1, + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + 'quantity' => 1, + ], + ], + ], + ], + ], + ], + + // @todo add checkout option example. + 'Checkout option' => [ + [ + 'event' => EventTrackerService::EVENT_CHECKOUT_OPTION, + 'ecommerce' => [], + ], + ], + + 'Purchase' => [ + [ + 'event' => EventTrackerService::EVENT_PURCHASE, + 'ecommerce' => [ + 'purchase' => [ + 'actionField' => [ + 'id' => '1', + 'affiliation' => 'Commerce Website', + 'revenue' => '11.99', + 'shipping' => '0', + 'coupon' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + 'quantity' => 1, + ], + ], + ], + ], + ], + ], + ]; + } + +} diff --git a/tests/src/Unit/EnhancedEcommerceEventsTest.php b/tests/src/Unit/EnhancedEcommerceEventsTest.php new file mode 100644 index 0000000..02b686d --- /dev/null +++ b/tests/src/Unit/EnhancedEcommerceEventsTest.php @@ -0,0 +1,49 @@ +assertEquals($expected, $event_name); + } + + /** + * List of supported event with expected names. + * + * @return array + * The list of CONST names & string expected value. + */ + public function eventNames() { + return [ + [ + EnhancedEcommerceEvents::ALTER_PRODUCT, + 'commerce_google_tag_manager.alter_product', + ], + [ + EnhancedEcommerceEvents::ALTER_EVENT_DATA, + 'commerce_google_tag_manager.alter_event_data', + ], + [ + EnhancedEcommerceEvents::TRACK_CHECKOUT_STEP, + 'commerce_google_tag_manager.track_checkout_step', + ], + ]; + } + +} From 97732ba05bbddda24ffba5c6779f584b3069cdee Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 11:06:05 +0100 Subject: [PATCH 2/8] fix expected 1 newline at end of file --- DEVELOPPING.md | 2 +- commerce_google_tag_manager.info.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEVELOPPING.md b/DEVELOPPING.md index 6406815..08edd2a 100644 --- a/DEVELOPPING.md +++ b/DEVELOPPING.md @@ -120,4 +120,4 @@ Maintaining code quality by adding the custom post-commit hook to yours. ```bash cat ./scripts/hooks/post-commit >> ./.git/hooks/post-commit -``` \ No newline at end of file +``` diff --git a/commerce_google_tag_manager.info.yml b/commerce_google_tag_manager.info.yml index 5f62e79..ce11218 100644 --- a/commerce_google_tag_manager.info.yml +++ b/commerce_google_tag_manager.info.yml @@ -6,4 +6,4 @@ type: module dependencies: - drupal:google_tag - drupal:commerce -- drupal:commerce_checkout \ No newline at end of file +- drupal:commerce_checkout From 390c490602ee58f938da2313749d0a93bdeede12 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 13:58:04 +0100 Subject: [PATCH 3/8] add base of EventStorage tests --- tests/src/Unit/EventStorageServiceTest.php | 163 +++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 tests/src/Unit/EventStorageServiceTest.php diff --git a/tests/src/Unit/EventStorageServiceTest.php b/tests/src/Unit/EventStorageServiceTest.php new file mode 100644 index 0000000..81807bc --- /dev/null +++ b/tests/src/Unit/EventStorageServiceTest.php @@ -0,0 +1,163 @@ +tempStore = $this->getMockBuilder(PrivateTempStoreFactory::class) + ->disableOriginalConstructor()->getMock(); + $this->eventDispatcher = $this->getMockBuilder(EventDispatcherInterface::class) + ->disableOriginalConstructor()->getMock(); + + $this->eventStorage = new EventStorageService($this->tempStore, $this->eventDispatcher); + + $this->event = [ + 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, + 'ecommerce' => [ + 'detail' => [ + 'actionField' => [ + 'list' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + ], + ], + ], + ], + ]; + $this->alterEventDataEvent = new AlterEventDataEvent($this->event); + } + + /** + * @covers ::hash + */ + public function testHash() { + $result = $this->invokeMethod($this->eventStorage, 'hash', [$this->event]); + $this->assertEquals('0e05cdf318b5832a7caf62ad11d386f4', $result); + } + + /** + * When addEvent called on a new event, we should fire an Event Alter. + * + * This should occure only when the added event has not already been added. + * This will then dispatch EnhancedEcommerceEvents::ALTER_EVENT_DATA. + * + * @covers ::addEvent + */ + public function testAddEventDispatchAlter() { + // Mock stored events, make sure the event has never been added. + $stored_events = $this->getMockBuilder(PrivateTempStore::class) + ->disableOriginalConstructor()->getMock(); + $stored_events->expects($this->once()) + ->method('get') + ->with('events') + ->willReturn([]); + + // Re-Mock the Private Temp Store & The Symfony Event Dispatcher. + $this->tempStore->expects($this->once()) + ->method('get') + ->with('commerce_google_tag_manager') + ->willReturn($stored_events); + $this->eventDispatcher->expects($this->once()) + ->method('dispatch') + ->with(EnhancedEcommerceEvents::ALTER_EVENT_DATA, $this->alterEventDataEvent); + + $this->eventStorage = new EventStorageService($this->tempStore, $this->eventDispatcher); + + $this->eventStorage->addEvent($this->event); + } + + /** + * When addEvent called on a un-new event, we should not fire an Event Alter. + * + * This should occure only when the added event has already been added. + * This will then not dispatch EnhancedEcommerceEvents::ALTER_EVENT_DATA. + * + * @covers ::addEvent + */ + public function testAddEventShouldDispatchAlterOnlyOnce() { + // Mock stored events, make sure the event has already been added. + $stored_events = $this->getMockBuilder(PrivateTempStore::class) + ->disableOriginalConstructor()->getMock(); + $stored_events->expects($this->once()) + ->method('get') + ->with('events') + ->willReturn(['0e05cdf318b5832a7caf62ad11d386f4' => $this->event]); + + // Re-Mock the Private Temp Store & The Symfony Event Dispatcher. + $this->tempStore->expects($this->once()) + ->method('get') + ->with('commerce_google_tag_manager') + ->willReturn($stored_events); + $this->eventDispatcher->expects($this->never()) + ->method('dispatch'); + + $this->eventStorage = new EventStorageService($this->tempStore, $this->eventDispatcher); + + $this->eventStorage->addEvent($this->event); + } + +} \ No newline at end of file From 4a16394c4fbe8d46852221de41ed24128cb0b7cb Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 14:12:23 +0100 Subject: [PATCH 4/8] remove uncomplete tests Remove shipping as uncomplete tests, should be added in complete separated tests/PR. --- tests/src/Unit/AlterEventDataEventTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/Unit/AlterEventDataEventTest.php b/tests/src/Unit/AlterEventDataEventTest.php index 4f69366..c078c23 100644 --- a/tests/src/Unit/AlterEventDataEventTest.php +++ b/tests/src/Unit/AlterEventDataEventTest.php @@ -164,7 +164,6 @@ public function eventData() { 'id' => '1', 'affiliation' => 'Commerce Website', 'revenue' => '11.99', - 'shipping' => '0', 'coupon' => '', ], 'products' => [ From 072697bb22fc4b191bf9c13781836e3063c72e31 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 14:12:36 +0100 Subject: [PATCH 5/8] remove uncomplete tests Remove coupon as uncomplete tests, should be added in complete separated tests/PR. --- tests/src/Unit/AlterEventDataEventTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/Unit/AlterEventDataEventTest.php b/tests/src/Unit/AlterEventDataEventTest.php index c078c23..71accdd 100644 --- a/tests/src/Unit/AlterEventDataEventTest.php +++ b/tests/src/Unit/AlterEventDataEventTest.php @@ -164,7 +164,6 @@ public function eventData() { 'id' => '1', 'affiliation' => 'Commerce Website', 'revenue' => '11.99', - 'coupon' => '', ], 'products' => [ 0 => [ From 7bb91578356e0932a549ff88a53a1d64ae5760c2 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 15:06:00 +0100 Subject: [PATCH 6/8] add Kernel tests for EventStorageService --- tests/src/Kernel/EventStorageServiceTest.php | 126 +++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 tests/src/Kernel/EventStorageServiceTest.php diff --git a/tests/src/Kernel/EventStorageServiceTest.php b/tests/src/Kernel/EventStorageServiceTest.php new file mode 100644 index 0000000..b8c1d81 --- /dev/null +++ b/tests/src/Kernel/EventStorageServiceTest.php @@ -0,0 +1,126 @@ +installSchema('system', ['key_value_expire']); + + $this->tempStore = $this->container->get('tempstore.private')->get('commerce_google_tag_manager'); + $this->eventStorage = $this->container->get('commerce_google_tag_manager.event_storage'); + $this->events = [ + '0e05cdf318b5832a7caf62ad11d386f4' => [ + 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, + 'ecommerce' => [ + 'detail' => [ + 'actionField' => [ + 'list' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + ], + ], + ], + ], + ], + ]; + } + + /** + * @covers ::getEvents + */ + public function testGetEvents() { + $this->tempStore->set('events', $this->events); + $result = $this->eventStorage->getEvents(); + $this->assertSame([ + 0 => [ + 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, + 'ecommerce' => [ + 'detail' => [ + 'actionField' => [ + 'list' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + ], + ], + ], + ], + ], + ], $result); + } + + /** + * @covers ::getEvents + */ + public function testGetEventsEmpty() { + $this->tempStore->set('events', NULL); + $result = $this->eventStorage->getEvents(); + $this->assertInternalType('array', $result); + $this->assertEmpty($result); + } + + /** + * @covers ::flush + */ + public function testFlush() { + $this->tempStore->set('events', $this->events); + $this->eventStorage->flush(); + $result = $this->tempStore->get('events'); + $this->assertNull($result); + } + +} From 366c47a8f73bab969db40fc53cb518e91eb175e9 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Thu, 29 Nov 2018 16:23:48 +0100 Subject: [PATCH 7/8] add Kernel EventStorageService::addEvent coverage --- tests/src/Kernel/EventStorageServiceTest.php | 136 +++++++++++++------ 1 file changed, 98 insertions(+), 38 deletions(-) diff --git a/tests/src/Kernel/EventStorageServiceTest.php b/tests/src/Kernel/EventStorageServiceTest.php index b8c1d81..30b1cc4 100644 --- a/tests/src/Kernel/EventStorageServiceTest.php +++ b/tests/src/Kernel/EventStorageServiceTest.php @@ -37,11 +37,18 @@ class EventStorageServiceTest extends CommerceKernelTestBase { private $eventStorage; /** - * The Google Tag Manager events structure to test with. + * The Google Tag Manager Product Detail view event structure to test with. * * @var array */ - protected $events; + protected $detailEvent; + + /** + * The Google Tag Manager Checkout event structure to test with. + * + * @var array + */ + protected $checkoutEvent; /** * {@inheritdoc} @@ -53,21 +60,40 @@ protected function setUp() { $this->tempStore = $this->container->get('tempstore.private')->get('commerce_google_tag_manager'); $this->eventStorage = $this->container->get('commerce_google_tag_manager.event_storage'); - $this->events = [ - '0e05cdf318b5832a7caf62ad11d386f4' => [ - 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, - 'ecommerce' => [ - 'detail' => [ - 'actionField' => [ - 'list' => '', + + $this->detailEvent = [ + 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, + 'ecommerce' => [ + 'detail' => [ + 'actionField' => [ + 'list' => '', + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', ], - 'products' => [ - 0 => [ - 'name' => 'Lorem Ipsum', - 'id' => '1', - 'price' => '11.99', - 'variant' => 'Lorem Ipsum', - ], + ], + ], + ], + ]; + + $this->checkoutEvent = [ + 'event' => EventTrackerService::EVENT_CHECKOUT, + 'ecommerce' => [ + 'checkout' => [ + 'actionField' => [ + 'step' => 1, + ], + 'products' => [ + 0 => [ + 'name' => 'Lorem Ipsum', + 'id' => '1', + 'price' => '11.99', + 'variant' => 'Lorem Ipsum', + 'quantity' => 1, ], ], ], @@ -79,28 +105,11 @@ protected function setUp() { * @covers ::getEvents */ public function testGetEvents() { - $this->tempStore->set('events', $this->events); + $this->tempStore->set('events', [ + '0e05cdf318b5832a7caf62ad11d386f4' => $this->detailEvent, + ]); $result = $this->eventStorage->getEvents(); - $this->assertSame([ - 0 => [ - 'event' => EventTrackerService::EVENT_PRODUCT_DETAIL_VIEWS, - 'ecommerce' => [ - 'detail' => [ - 'actionField' => [ - 'list' => '', - ], - 'products' => [ - 0 => [ - 'name' => 'Lorem Ipsum', - 'id' => '1', - 'price' => '11.99', - 'variant' => 'Lorem Ipsum', - ], - ], - ], - ], - ], - ], $result); + $this->assertSame([0 => $this->detailEvent], $result); } /** @@ -117,10 +126,61 @@ public function testGetEventsEmpty() { * @covers ::flush */ public function testFlush() { - $this->tempStore->set('events', $this->events); + $this->tempStore->set('events', [ + '0e05cdf318b5832a7caf62ad11d386f4' => $this->detailEvent, + ]); $this->eventStorage->flush(); $result = $this->tempStore->get('events'); $this->assertNull($result); } + /** + * @covers ::addEvent + * + * Asserts usage of Private Temp Store for events queue. + */ + public function testAddEvent() { + $this->eventStorage->addEvent($this->detailEvent); + + $result = $this->tempStore->get('events'); + $this->assertInternalType('array', $result); + $this->assertSame([ + '0e05cdf318b5832a7caf62ad11d386f4' => $this->detailEvent, + ], $result); + } + + /** + * @covers ::addEvent + * + * Asserts the events queue follows the FIFO (First in First out) pattern. + */ + public function testAddEventFifoQueue() { + $this->testAddEvent(); + + $this->eventStorage->addEvent($this->detailEvent); + $this->eventStorage->addEvent($this->checkoutEvent); + $events = $this->tempStore->get('events'); + + $this->assertSame([ + '0e05cdf318b5832a7caf62ad11d386f4' => $this->detailEvent, + '5d92a6ab1f5bd49c7ac5a065302dcb16' => $this->checkoutEvent, + ], $events); + } + + /** + * @covers ::addEvent + * + * Asserts strictly same event aren't added twice in the events queue. + */ + public function testAddEventSameSkipped() { + $this->testAddEvent(); + + $this->eventStorage->addEvent($this->detailEvent); + $this->eventStorage->addEvent($this->detailEvent); + $events = $this->tempStore->get('events'); + $this->assertSame([ + '0e05cdf318b5832a7caf62ad11d386f4' => $this->detailEvent, + ], $events); + } + } From 06767ec1084fbf86be3530daafe09b96470085b3 Mon Sep 17 00:00:00 2001 From: Kevin Wenger Date: Fri, 30 Nov 2018 16:25:45 +0100 Subject: [PATCH 8/8] remove unecessary call to previous tests --- tests/src/Kernel/EventStorageServiceTest.php | 4 ---- tests/src/Unit/EventStorageServiceTest.php | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/src/Kernel/EventStorageServiceTest.php b/tests/src/Kernel/EventStorageServiceTest.php index 30b1cc4..26769d5 100644 --- a/tests/src/Kernel/EventStorageServiceTest.php +++ b/tests/src/Kernel/EventStorageServiceTest.php @@ -155,8 +155,6 @@ public function testAddEvent() { * Asserts the events queue follows the FIFO (First in First out) pattern. */ public function testAddEventFifoQueue() { - $this->testAddEvent(); - $this->eventStorage->addEvent($this->detailEvent); $this->eventStorage->addEvent($this->checkoutEvent); $events = $this->tempStore->get('events'); @@ -173,8 +171,6 @@ public function testAddEventFifoQueue() { * Asserts strictly same event aren't added twice in the events queue. */ public function testAddEventSameSkipped() { - $this->testAddEvent(); - $this->eventStorage->addEvent($this->detailEvent); $this->eventStorage->addEvent($this->detailEvent); $events = $this->tempStore->get('events'); diff --git a/tests/src/Unit/EventStorageServiceTest.php b/tests/src/Unit/EventStorageServiceTest.php index 81807bc..6eb2a03 100644 --- a/tests/src/Unit/EventStorageServiceTest.php +++ b/tests/src/Unit/EventStorageServiceTest.php @@ -160,4 +160,4 @@ public function testAddEventShouldDispatchAlterOnlyOnce() { $this->eventStorage->addEvent($this->event); } -} \ No newline at end of file +}