Skip to content

Commit

Permalink
#762 #764 google ecommerce tests (#767)
Browse files Browse the repository at this point in the history
* Make a mock of google analytics for tests.

* Use SiteDriver instead of seleniumrequests.Remote

* Fix SiteDriver instantiation

* Fix wait

* Create test for google ecommerce

* Remove Remote driver for mobile tests

* Disable celery for GoogleEcommerce test case

* Review fixes

* Apply linter rules
  • Loading branch information
ArtemijRodionov authored Mar 14, 2019
1 parent 394cb2a commit f97e76b
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 61 deletions.
2 changes: 2 additions & 0 deletions shopelectro/selenium/pages/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from shopelectro.selenium.pages import Page

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

from pages.models import CustomPage

Expand Down Expand Up @@ -34,6 +35,7 @@ def fill_contacts(

def make_order(self):
self.submit_button.click()
self.driver.wait.until(EC.url_changes(self.path))

def select_payment_type(self, payment_option: PaymentOptions):
if payment_option not in PaymentOptions:
Expand Down
15 changes: 12 additions & 3 deletions shopelectro/selenium/pages/page.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from functools import wraps

from shopelectro.selenium import SiteDriver

from selenium.webdriver.common.by import By
Expand All @@ -17,10 +19,17 @@ def __init__(self, driver: SiteDriver):
self.driver = driver
self.path: str

def wait_loaded(self):
def loaded(driver):
is_sync = EC.url_contains(self.path)
is_rendered = EC.visibility_of_element_located(
(By.TAG_NAME, 'body')
)
return is_sync(driver) and is_rendered(driver)
self.driver.wait.until(loaded)

def load(self):
if not self.path:
raise ValueError(f'Set a page path to {self.__class__.__name__}')
self.driver.get(self.path)
self.driver.wait.until(EC.visibility_of_element_located(
(By.TAG_NAME, 'body')
))
self.wait_loaded()
10 changes: 8 additions & 2 deletions shopelectro/selenium/pages/success.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

from shopelectro.selenium.pages import Page

from pages.models import CustomPage
Expand All @@ -7,7 +10,10 @@ class SuccessPage(Page):

@property
def path(self):
CustomPage.objects.get(slug='order-success').url
return CustomPage.objects.get(slug='order-success').url

def is_success(self):
return 'Заказ принят' in self.driver.find_element_by_tag_name('h1').text
h1 = self.driver.wait.until(
EC.visibility_of_element_located((By.TAG_NAME, 'h1'))
).text
return 'Заказ принят' in h1
17 changes: 8 additions & 9 deletions shopelectro/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
from selenium.common.exceptions import InvalidElementStateException, WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from seleniumrequests import Remote # We use this instead of standard selenium

from shopelectro.selenium import SiteDriver

disable_celery = override_settings(USE_CELERY=False)
enable_russian_language = override_settings(
Expand Down Expand Up @@ -53,13 +52,9 @@ class SeleniumTestCase(LiveServerTestCase):
def setUpClass(cls):
"""Instantiate browser instance."""
super().setUpClass()
cls.browser = Remote(
command_executor=settings.SELENIUM_URL,
desired_capabilities=DesiredCapabilities.CHROME
)
cls.browser = SiteDriver(site_url=cls.live_server_url)
# @todo #371:15m Move selenium timeout to env var. stb2
# To be able to change it from drone without touching code.
cls.wait = WebDriverWait(cls.browser, settings.SELENIUM_WAIT_SECONDS)
cls.browser.implicitly_wait(30)
cls.browser.set_page_load_timeout(settings.SELENIUM_TIMEOUT_SECONDS)
# Fresh created browser failures on maximizing window.
Expand All @@ -71,7 +66,11 @@ def setUpClass(cls):
try:
cls.browser.maximize_window()
except WebDriverException:
print('Failed to maximize window')
print('Failed to maximize window') # Ignore CPDBear

@property
def wait(self):
return self.browser.wait

@classmethod
def tearDownClass(cls):
Expand Down
36 changes: 36 additions & 0 deletions shopelectro/tests/tests_js_analytics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.test import override_settings, tag

from shopelectro import selenium
from shopelectro.tests import helpers
from shopelectro.models import CategoryPage, Order


@tag('slow')
@helpers.disable_celery
@override_settings(DEBUG=True, INTERNAL_IPS=tuple())
class GoogleEcommerce(helpers.SeleniumTestCase):

fixtures = ['dump.json']

def test_google_ecommerce_purchase(self):
category_page = selenium.CategoryPage(
self.browser,
CategoryPage.objects.first().slug,
)
category_page.load()
category_page.add_to_cart()

order_page = selenium.OrderPage(self.browser)
order_page.load()
order_page.fill_contacts()
order_page.make_order()

success_page = selenium.SuccessPage(self.browser)
success_page.wait_loaded()
self.assertTrue(success_page.is_success())

order = Order.objects.order_by('-created').first() # Ignore PyFlakesBear
reached = self.browser.execute_script('return gaObject.results;') # Ignore PyFlakesBear

# @todo #762:30m Match an order with a transaction of Google eCommerce analytics.
# The transaction must contain correct order data and related products.
61 changes: 28 additions & 33 deletions shopelectro/tests/tests_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def show_cart_dropdown(browser):
))


def add_to_cart(browser, live_server_url):
browser.get(live_server_url + Product.objects.first().url)
def add_to_cart(browser):
browser.get(Product.objects.first().url)
browser.find_element_by_class_name('btn-to-basket').click()


Expand All @@ -73,7 +73,7 @@ class Header(helpers.SeleniumTestCase):

def setUp(self):
"""Set up testing urls and dispatch selenium webdriver."""
self.browser.get(self.live_server_url)
self.browser.get('/')
wait_page_loading(self.browser)

def test_call_modal_not_visible(self):
Expand Down Expand Up @@ -113,7 +113,7 @@ def test_cart_hover(self):

def test_cart_flush(self):
"""We can flush cart from header's cart dropdown."""
add_to_cart(self.browser, self.live_server_url)
add_to_cart(self.browser)
show_cart_dropdown(self.browser)
self.wait.until(EC.visibility_of_element_located(
(By.CLASS_NAME, 'basket-reset')
Expand All @@ -125,7 +125,7 @@ def test_cart_flush(self):
self.assertTrue(is_cart_empty(self.browser))

def test_product_total_price_in_dropdown(self):
add_to_cart(self.browser, self.live_server_url)
add_to_cart(self.browser)
product_price = int(Product.objects.first().price)
show_cart_dropdown(self.browser)
product_total_price = self.wait.until(EC.visibility_of_element_located(
Expand All @@ -143,7 +143,7 @@ class CategoryPage(helpers.SeleniumTestCase):

def setUp(self):
def get_testing_url(slug):
return self.live_server_url + reverse('category', args=(slug,))
return reverse('category', args=(slug,))

root_category = Category.objects.filter(parent=None).first()
children_category = Category.objects.filter(parent=root_category).first()
Expand Down Expand Up @@ -422,9 +422,8 @@ def setUp(self):
"""Set up testing url and dispatch selenium webdriver."""
self.browser.delete_all_cookies()
self.product = Product.objects.get(id=self.PRODUCT_ID)
server = self.live_server_url
self.test_product_page = server + self.product.url
self.success_order = server + reverse(CustomPage.ROUTE, args=('order-success',))
self.test_product_page = self.product.url
self.success_order = reverse(CustomPage.ROUTE, args=('order-success',))
self.product_name = self.product.name
self.browser.get(self.test_product_page)
wait_page_loading(self.browser)
Expand Down Expand Up @@ -504,9 +503,9 @@ def test_one_click_buy_action(self):
self.browser.find_element_by_id(
'input-one-click-phone').send_keys('2222222222')
self.one_click.click()
self.wait.until(EC.url_to_be(self.success_order))
self.wait.until(EC.url_contains(self.success_order))

self.assertEqual(self.browser.current_url, self.success_order)
self.assertIn(self.success_order, self.browser.current_url)

@helpers.disable_celery
def test_one_click_buy_order_email(self):
Expand All @@ -525,7 +524,7 @@ def test_one_click_buy_order_email(self):
phone_field = self.browser.find_element_by_id('input-one-click-phone')
phone_field.send_keys('2222222222')
self.one_click.click()
self.wait.until(EC.url_to_be(self.success_order))
self.wait.until(EC.url_contains(self.success_order))

sent_mail_body = mail.outbox[0].body
self.assertIn('+7 (222) 222 22 22', sent_mail_body)
Expand Down Expand Up @@ -637,13 +636,10 @@ def setUp(self):
self.product_count = self.get_cell(pos=4, col='count') + '/div[2]/input'
self.add_product = self.get_cell(pos=4, col='count') + '/div[2]/span[3]/button[1]'
self.category = reverse('category', args=(Category.objects.first().page.slug,))
self.success_order_url = '{}{}'.format(
self.live_server_url,
reverse(CustomPage.ROUTE, args=('order-success',))
)
self.success_order_url = reverse(CustomPage.ROUTE, args=('order-success',))
self.buy_products()
self.wait.until_not(is_cart_empty)
self.browser.get(self.live_server_url + self.order_page.url)
self.browser.get(self.order_page.url)
wait_page_loading(self.browser)

def tearDown(self):
Expand All @@ -653,7 +649,7 @@ def tearDown(self):
self.browser.execute_script('localStorage.clear();')

def buy_products(self):
self.browser.get(self.live_server_url + self.category)
self.browser.get(self.category)
for i in range(1, 6):
self.browser.find_element_by_xpath(
'//*[@id="products-wrapper"]/div[{}]/div[2]/div[5]/button'
Expand Down Expand Up @@ -759,10 +755,10 @@ def test_confirm_order(self):
self.append_products_to_cart()
self.fill_contacts_data()
self.submit_form()
self.wait.until(EC.url_to_be(self.success_order_url))
self.assertEqual(
self.wait.until(EC.url_contains(self.success_order_url))
self.assertIn(
reverse(CustomPage.ROUTE, args=('order-success', )),
self.browser.current_url,
self.live_server_url + reverse(CustomPage.ROUTE, args=('order-success', ))
)

@helpers.disable_celery
Expand All @@ -776,7 +772,7 @@ def test_order_email(self):

self.fill_contacts_data()
self.submit_form()
self.wait.until(EC.url_to_be(self.success_order_url))
self.wait.until(EC.url_contains(self.success_order_url))
self.assertEqual(len(mail.outbox), 1)
sent_mail_body = mail.outbox[0].body

Expand Down Expand Up @@ -843,7 +839,7 @@ def setUp(self):
parent=self.page_top
)
self.browser.delete_all_cookies()
self.browser.get(self.live_server_url + self.page_last.url)
self.browser.get(self.page_last.url)
wait_page_loading(self.browser)

def tearDown(self):
Expand Down Expand Up @@ -886,6 +882,9 @@ def test_accordion_minimize_by_double_click(self):
self.assertFalse(accordion_content.is_displayed())


# @todo #762:30m Move Ya.Metrica tests to tests_js_counters.py


@tag('slow')
@helpers.disable_celery
@override_settings(DEBUG=True, INTERNAL_IPS=tuple())
Expand All @@ -894,16 +893,12 @@ class YandexMetrika(helpers.SeleniumTestCase):
CART_LOCATOR = (By.CLASS_NAME, 'js-go-to-cart')

def setUp(self):
server = self.live_server_url
product_vendor_code = Product.objects.first().vendor_code
self.product_page = server + reverse('product', args=(product_vendor_code,))
self.category_page = server + reverse(
self.product_page = reverse('product', args=(product_vendor_code,))
self.category_page = reverse(
'category', args=(Category.objects.first().page.slug,))
self.order_page_url = '{}{}'.format(
self.live_server_url,
reverse(CustomPage.ROUTE, args=('order',))
)
self.browser.get(self.live_server_url)
self.order_page_url = reverse(CustomPage.ROUTE, args=('order',))
self.browser.get('/')
wait_page_loading(self.browser)

@property
Expand Down Expand Up @@ -942,7 +937,7 @@ def buy_product(self):

def go_to_cart(self):
self.click(self.CART_LOCATOR)
self.wait.until(EC.url_to_be(self.order_page_url))
self.wait.until(EC.url_contains(self.order_page_url))

def test_download_header_price(self):
"""User clicks Download price button in site's header."""
Expand Down Expand Up @@ -1048,7 +1043,7 @@ class Search(helpers.SeleniumTestCase):
INPUT_LOCATOR = (By.CLASS_NAME, 'js-search-input')

def setUp(self):
self.browser.get(self.live_server_url)
self.browser.get('/')
wait_page_loading(self.browser)

def tearDown(self):
Expand Down
7 changes: 3 additions & 4 deletions shopelectro/tests/tests_selenium_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ class AdminPage(AdminSeleniumTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.admin_page = cls.live_server_url + reverse('admin:index')
cls.change_products_url = cls.live_server_url + reverse(
'admin:shopelectro_productpage_changelist')
cls.admin_page = reverse('admin:index')
cls.change_products_url = reverse('admin:shopelectro_productpage_changelist')
cls.title_text = 'Shopelectro administration'
cls.active_products = '//*[@id="changelist-filter"]/ul[1]/li[2]/a'
cls.inactive_products = '//*[@id="changelist-filter"]/ul[1]/li[3]/a'
Expand Down Expand Up @@ -354,7 +353,7 @@ def setUp(self):

@property
def admin_page(self):
return self.live_server_url + reverse('admin:index')
return reverse('admin:index')

def wait_tableeditor_loading(self):
self.wait_page_loading()
Expand Down
Loading

2 comments on commit f97e76b

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on f97e76b Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 762-c8b88dbe discovered in shopelectro/tests/tests_js_analytics.py and submitted as #771. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on f97e76b Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 762-afab9051 discovered in shopelectro/tests/tests_selenium.py and submitted as #772. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.