From 63a1de7f083d8c7b39cd0b219687b71d0e3b8336 Mon Sep 17 00:00:00 2001 From: Artemiy Date: Fri, 5 Jul 2019 14:22:34 +0300 Subject: [PATCH] #929 ecommerce goals for tests (#933) * Create SiteDriver.delete_session method * Create Goals interface for selenium tests * Use the YandexEcommerceGoals in tests * Review fixes * Make rebase to master * Apply linter rules --- shopelectro/selenium/__init__.py | 1 + shopelectro/selenium/analytics_goals.py | 46 +++++++++++++++++++++++++ shopelectro/selenium/driver.py | 4 +++ shopelectro/tests/tests_js_analytics.py | 27 ++++++--------- shopelectro/tests/tests_selenium.py | 4 +-- 5 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 shopelectro/selenium/analytics_goals.py diff --git a/shopelectro/selenium/__init__.py b/shopelectro/selenium/__init__.py index d90dc6b2..1e2eb5c9 100644 --- a/shopelectro/selenium/__init__.py +++ b/shopelectro/selenium/__init__.py @@ -14,3 +14,4 @@ from .driver import SiteDriver from .pages import * +from .analytics_goals import Goals, YandexEcommerceGoals diff --git a/shopelectro/selenium/analytics_goals.py b/shopelectro/selenium/analytics_goals.py new file mode 100644 index 00000000..7f82dd82 --- /dev/null +++ b/shopelectro/selenium/analytics_goals.py @@ -0,0 +1,46 @@ +import abc + +from shopelectro.selenium import SiteDriver + +# @todo #929:30m Implement GoogleEcommerceGoals and YandexMetrikaGoals and use them in tests. + + +class Goals(abc.ABC): + """Front-end reached goals.""" + + def __init__(self, driver: SiteDriver): + self.driver = driver + + @abc.abstractmethod + def fetch(self): + raise NotImplementedError + + @abc.abstractmethod + def __iter__(self): + raise NotImplementedError + + @abc.abstractmethod + def __getitem__(self, index: int): + raise NotImplementedError + + +class YandexEcommerceGoals(Goals): # Ignore PyDocStyleBear + """ + Unwrap an excess nesting level common for every goal: + [{"ecommerce": ...}] -> ... + Structure docs: https://yandex.com/support/metrica/data/e-commerce.html + """ + + def __init__(self, driver: SiteDriver): + super().__init__(driver) + self.goals = [] + + def fetch(self): + self.goals = self.driver.execute_script('return window.dataLayer.results;') + + def __getitem__(self, index: int): + return self.goals[index][0]['ecommerce'] + + def __iter__(self): + for g in self.goals: + yield g[0]['ecommerce'] diff --git a/shopelectro/selenium/driver.py b/shopelectro/selenium/driver.py index 10fc91d9..4cf791d7 100644 --- a/shopelectro/selenium/driver.py +++ b/shopelectro/selenium/driver.py @@ -26,3 +26,7 @@ def __exit__(self, *args, **kwargs): def get(self, url): super().get(urljoin(self.site_url, url)) + + def delete_session(self): + self.delete_cookie('sessionid') + self.execute_script('localStorage.clear();') diff --git a/shopelectro/tests/tests_js_analytics.py b/shopelectro/tests/tests_js_analytics.py index 215343c2..0ba30e27 100644 --- a/shopelectro/tests/tests_js_analytics.py +++ b/shopelectro/tests/tests_js_analytics.py @@ -92,18 +92,13 @@ class YandexEcommerce(Ecommerce): def tearDown(self): # delete the session to clear the cart - self.browser.delete_cookie('sessionid') - self.browser.execute_script('localStorage.clear();') + self.browser.delete_session() super().tearDown() - # @todo #808:30m Create Goals class for tests. - # Remove these utility functions in favor of the class. - def get_goals(self): - return self.browser.execute_script('return window.dataLayer.results;') - - def get_goal(self, reached, index=0): - """Get a goal with the given index and unfold it.""" - return reached[index][0]['ecommerce'] + def get_goals(self) -> selenium.Goals: + goals = selenium.YandexEcommerceGoals(self.browser) + goals.fetch() + return goals def test_purchase(self): self.buy() @@ -113,7 +108,7 @@ def test_purchase(self): reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals) + reached = reached_goals[0] self.assertIn('purchase', reached) self.assertEqual(reached['currencyCode'], 'RUB') @@ -140,7 +135,7 @@ def test_product_detail(self): reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals) + reached = reached_goals[0] self.assertIn('detail', reached) self.assertEqual(reached['currencyCode'], 'RUB') @@ -171,7 +166,7 @@ def test_clear_cart(self): # Ignore CPDBear reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals, 2) + reached = reached_goals[2] self.assertIn('remove', reached) self.assertEqual(reached['currencyCode'], 'RUB') @@ -200,7 +195,7 @@ def test_remove_from_cart(self): reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals, 2) + reached = reached_goals[2] self.assertIn('remove', reached) self.assertEqual(reached['currencyCode'], 'RUB') @@ -227,7 +222,7 @@ def test_add_from_product_page(self): reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals, 1) # Ignore CPDBear + reached = reached_goals[1] # Ignore CPDBear self.assertIn('add', reached) self.assertEqual(reached['currencyCode'], 'RUB') @@ -258,7 +253,7 @@ def test_add_from_category_page(self): reached_goals = self.get_goals() self.assertTrue(reached_goals) - reached = self.get_goal(reached_goals) + reached = reached_goals[0] self.assertIn('add', reached) self.assertEqual(reached['currencyCode'], 'RUB') diff --git a/shopelectro/tests/tests_selenium.py b/shopelectro/tests/tests_selenium.py index 45b39454..d3a17d2d 100644 --- a/shopelectro/tests/tests_selenium.py +++ b/shopelectro/tests/tests_selenium.py @@ -636,10 +636,8 @@ def setUp(self): self.wait_page_loading() def tearDown(self): - # Delete only a session cookie to flush a cart. # If we will flush all cookies it will probably rise csrf-protection errors. - self.browser.delete_cookie('sessionid') - self.browser.execute_script('localStorage.clear();') + self.browser.delete_session() def buy_products(self): self.browser.get(self.category)