mirror of
https://github.com/Crocmagnon/checkout.git
synced 2024-09-28 23:27:37 +02:00
292 lines
11 KiB
Python
292 lines
11 KiB
Python
|
import time
|
||
|
|
||
|
import freezegun
|
||
|
from django.urls import reverse
|
||
|
from pytest_django.live_server_helper import LiveServer
|
||
|
from selenium.webdriver import ActionChains, Keys
|
||
|
from selenium.webdriver.common.by import By
|
||
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||
|
from selenium.webdriver.support.wait import WebDriverWait
|
||
|
|
||
|
from common.models import User
|
||
|
from purchase.models import Basket
|
||
|
from purchase.tests.factories import (
|
||
|
USER_PASSWORD,
|
||
|
BasketWithItemsFactory,
|
||
|
CashierFactory,
|
||
|
PaymentMethodFactory,
|
||
|
ProductFactory,
|
||
|
)
|
||
|
|
||
|
|
||
|
@freezegun.freeze_time("2022-09-24 19:01:00+0200")
|
||
|
def test_cashier_create_and_update_basket(live_server: LiveServer, selenium: WebDriver):
|
||
|
wait = WebDriverWait(selenium, 10)
|
||
|
assert Basket.objects.count() == 0
|
||
|
|
||
|
# Setup data
|
||
|
cashier = CashierFactory()
|
||
|
products = [
|
||
|
ProductFactory(),
|
||
|
ProductFactory(),
|
||
|
ProductFactory(),
|
||
|
]
|
||
|
payment_methods = [
|
||
|
PaymentMethodFactory(),
|
||
|
PaymentMethodFactory(),
|
||
|
PaymentMethodFactory(),
|
||
|
]
|
||
|
|
||
|
login(live_server, selenium, cashier)
|
||
|
|
||
|
# Assert products are displayed
|
||
|
redirect_url = live_reverse(live_server, "purchase:new")
|
||
|
wait.until(lambda driver: driver.current_url == redirect_url)
|
||
|
displayed_products = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
||
|
assert len(displayed_products) == len(products)
|
||
|
for product, displayed_product in zip(products, displayed_products):
|
||
|
assert (
|
||
|
product.name
|
||
|
== displayed_product.find_element(By.CLASS_NAME, "card-title").text
|
||
|
)
|
||
|
|
||
|
# Assert quantity of all products is 0
|
||
|
for displayed_product in displayed_products:
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 0
|
||
|
|
||
|
# Click on - on product 1
|
||
|
displayed_product = displayed_products[0]
|
||
|
displayed_product.find_element(By.CLASS_NAME, "btn-danger").click()
|
||
|
|
||
|
# Assert quantity is still 0
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 0
|
||
|
|
||
|
# Click two times on + on product 1
|
||
|
button_plus = displayed_product.find_element(By.CLASS_NAME, "btn-success")
|
||
|
button_plus.click()
|
||
|
button_plus.click()
|
||
|
|
||
|
# Assert quantity is 2
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 2
|
||
|
|
||
|
# Adjust manually quantity for product 2: 4
|
||
|
displayed_product = displayed_products[1]
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
chain = ActionChains(selenium)
|
||
|
chain.double_click(quantity_input).perform()
|
||
|
quantity_input.send_keys("4")
|
||
|
|
||
|
# Don't add payment method
|
||
|
# Save
|
||
|
selenium.find_element(By.ID, "submit-id-submit").click()
|
||
|
|
||
|
# Assert entries saved in DB (new basket with proper products)
|
||
|
assert Basket.objects.count() == 1
|
||
|
basket = Basket.objects.priced().first()
|
||
|
assert basket.payment_method is None
|
||
|
assert basket.items.count() == 2
|
||
|
assert basket.items.get(product=products[0]).quantity == 2
|
||
|
assert (
|
||
|
basket.items.get(product=products[0]).unit_price_cents
|
||
|
== products[0].unit_price_cents
|
||
|
)
|
||
|
assert basket.items.get(product=products[1]).quantity == 4
|
||
|
assert (
|
||
|
basket.items.get(product=products[1]).unit_price_cents
|
||
|
== products[1].unit_price_cents
|
||
|
)
|
||
|
|
||
|
# Assert redirected to basket update view
|
||
|
redirect_url = live_reverse(live_server, "purchase:update", pk=basket.pk)
|
||
|
wait.until(lambda driver: driver.current_url == redirect_url)
|
||
|
|
||
|
# Assert message in green for successful basket creation
|
||
|
created_message = selenium.find_element(By.CSS_SELECTOR, ".messages .alert-success")
|
||
|
assert created_message.text == "Panier correctement créé."
|
||
|
|
||
|
# Assert message in red for missing payment method
|
||
|
missing_payment = selenium.find_element(By.CSS_SELECTOR, ".alert.alert-danger")
|
||
|
assert missing_payment.text == "Moyen de paiement manquant."
|
||
|
|
||
|
# Assert ID, price, date & product quantities
|
||
|
# Selected products have a green background
|
||
|
title = selenium.find_element(By.TAG_NAME, "h1")
|
||
|
assert title.text == f"Panier n°{basket.pk} {basket.price/100:.2f}€"
|
||
|
date = selenium.find_element(By.CLASS_NAME, "metadata")
|
||
|
assert date.text == "24 septembre 2022 19:01"
|
||
|
|
||
|
displayed_products = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
||
|
displayed_product = displayed_products[0]
|
||
|
assert "bg-success" in displayed_product.get_attribute("class")
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 2
|
||
|
displayed_product = displayed_products[1]
|
||
|
assert "bg-success" in displayed_product.get_attribute("class")
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 4
|
||
|
displayed_product = displayed_products[2]
|
||
|
assert "bg-success" not in displayed_product.get_attribute("class")
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 0
|
||
|
|
||
|
# Click on - on product 2
|
||
|
displayed_product = displayed_products[1]
|
||
|
displayed_product.find_element(By.CLASS_NAME, "btn-danger").click()
|
||
|
|
||
|
# Assert quantity is 3
|
||
|
quantity_input = displayed_product.find_element(By.CLASS_NAME, "numberinput")
|
||
|
quantity = int(quantity_input.get_attribute("value"))
|
||
|
assert quantity == 3
|
||
|
|
||
|
# Add payment method
|
||
|
selenium.find_element(By.TAG_NAME, "html").send_keys(Keys.END)
|
||
|
time.sleep(1)
|
||
|
selenium.find_element(By.ID, f"id_payment_method_{payment_methods[1].pk}").click()
|
||
|
|
||
|
# Save
|
||
|
selenium.find_element(By.ID, "submit-id-submit").click()
|
||
|
|
||
|
# Assert changed in DB
|
||
|
assert Basket.objects.count() == 1
|
||
|
basket = Basket.objects.priced().first()
|
||
|
assert basket.payment_method == payment_methods[1]
|
||
|
assert basket.items.count() == 2
|
||
|
assert basket.items.get(product=products[0]).quantity == 2
|
||
|
assert (
|
||
|
basket.items.get(product=products[0]).unit_price_cents
|
||
|
== products[0].unit_price_cents
|
||
|
)
|
||
|
assert basket.items.get(product=products[1]).quantity == 3
|
||
|
assert (
|
||
|
basket.items.get(product=products[1]).unit_price_cents
|
||
|
== products[1].unit_price_cents
|
||
|
)
|
||
|
|
||
|
# Assert redirected to same view
|
||
|
redirect_url = live_reverse(live_server, "purchase:update", pk=basket.pk)
|
||
|
wait.until(lambda driver: driver.current_url == redirect_url)
|
||
|
|
||
|
# Assert message in green for successful basket update
|
||
|
created_message = selenium.find_element(By.CSS_SELECTOR, ".messages .alert-success")
|
||
|
assert created_message.text == "Panier correctement modifié."
|
||
|
|
||
|
# Assert no more red message
|
||
|
missing_payment = selenium.find_elements(By.CSS_SELECTOR, ".alert.alert-danger")
|
||
|
assert len(missing_payment) == 0
|
||
|
|
||
|
|
||
|
def login(
|
||
|
live_server: LiveServer, selenium: WebDriver, cashier: User, url: str = "/"
|
||
|
) -> None:
|
||
|
# Go to page
|
||
|
url = live_url(live_server, url)
|
||
|
selenium.get(url)
|
||
|
# Login
|
||
|
selenium.find_element(By.ID, "id_username").send_keys(cashier.username)
|
||
|
selenium.find_element(By.ID, "id_password").send_keys(USER_PASSWORD)
|
||
|
selenium.find_element(By.ID, "id_password").send_keys(Keys.RETURN)
|
||
|
|
||
|
|
||
|
@freezegun.freeze_time("2022-09-24 19:03:00+0200")
|
||
|
def test_baskets_list(live_server: LiveServer, selenium: WebDriver):
|
||
|
wait = WebDriverWait(selenium, 10)
|
||
|
|
||
|
# Setup test data
|
||
|
cashier = CashierFactory()
|
||
|
_ = [
|
||
|
ProductFactory(),
|
||
|
ProductFactory(),
|
||
|
ProductFactory(),
|
||
|
]
|
||
|
_ = [
|
||
|
PaymentMethodFactory(),
|
||
|
PaymentMethodFactory(),
|
||
|
PaymentMethodFactory(),
|
||
|
]
|
||
|
with freezegun.freeze_time("2022-09-24 19:01:00+0200"):
|
||
|
basket_with_payment_method = BasketWithItemsFactory()
|
||
|
basket_with_payment_method = Basket.objects.priced().get(
|
||
|
pk=basket_with_payment_method.pk
|
||
|
)
|
||
|
with freezegun.freeze_time("2022-09-24 19:02:00+0200"):
|
||
|
basket_no_payment_method = BasketWithItemsFactory(payment_method=None)
|
||
|
basket_no_payment_method = Basket.objects.priced().get(
|
||
|
pk=basket_no_payment_method.pk
|
||
|
)
|
||
|
|
||
|
# Login
|
||
|
url = reverse("purchase:list")
|
||
|
login(live_server, selenium, cashier, url)
|
||
|
|
||
|
# Assert first basket (last created) has yellow background
|
||
|
# Assert basket info displayed
|
||
|
displayed_baskets = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
||
|
first_basket = displayed_baskets[0]
|
||
|
assert "bg-warning" in first_basket.get_attribute("class")
|
||
|
text = first_basket.text.replace("\n", " ")
|
||
|
assert f"n°{basket_no_payment_method.pk} " in text
|
||
|
expected_articles_count = basket_no_payment_method.items.count()
|
||
|
assert f" {expected_articles_count} article" in text
|
||
|
expected_price = basket_no_payment_method.price / 100
|
||
|
assert f" {expected_price:.2f}€" in text
|
||
|
expected_payment_method = "-"
|
||
|
assert f" {expected_payment_method} " in text
|
||
|
assert "19:02" in text
|
||
|
|
||
|
# Assert second basket (first created) doesn't have yellow background
|
||
|
# Assert basket info displayed including payment method
|
||
|
second_basket = displayed_baskets[1]
|
||
|
assert "bg-warning" not in second_basket.get_attribute("class")
|
||
|
text = second_basket.text.replace("\n", " ")
|
||
|
assert f"n°{basket_with_payment_method.pk} " in text
|
||
|
expected_articles_count = basket_with_payment_method.items.count()
|
||
|
assert f" {expected_articles_count} article" in text
|
||
|
expected_price = basket_with_payment_method.price / 100
|
||
|
assert f" {expected_price:.2f}€" in text
|
||
|
expected_payment_method = basket_with_payment_method.payment_method.name
|
||
|
assert f" {expected_payment_method} " in text
|
||
|
assert "19:01" in text
|
||
|
|
||
|
# Click on delete on second basket
|
||
|
second_basket.find_element(By.CLASS_NAME, "btn-danger").click()
|
||
|
|
||
|
# Confirm deletion
|
||
|
selenium.find_element(By.CLASS_NAME, "btn-danger").click()
|
||
|
|
||
|
# Assert object deleted in DB
|
||
|
assert Basket.objects.count() == 1
|
||
|
assert Basket.objects.first() == basket_no_payment_method
|
||
|
|
||
|
# Assert redirected to list view
|
||
|
wait.until(
|
||
|
lambda driver: driver.current_url == live_reverse(live_server, "purchase:list")
|
||
|
)
|
||
|
|
||
|
# Click on edit on remaining basket
|
||
|
displayed_baskets = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
||
|
displayed_baskets[0].find_element(By.CLASS_NAME, "btn-primary").click()
|
||
|
|
||
|
# Assert redirected to edit view
|
||
|
redirect_url = live_reverse(
|
||
|
live_server, "purchase:update", pk=basket_no_payment_method.pk
|
||
|
)
|
||
|
wait.until(lambda driver: driver.current_url == redirect_url)
|
||
|
|
||
|
|
||
|
def live_reverse(live_server: LiveServer, url_name: str, **kwargs) -> str:
|
||
|
path = reverse(url_name, kwargs=kwargs)
|
||
|
return live_url(live_server, path)
|
||
|
|
||
|
|
||
|
def live_url(live_server: LiveServer, path: str) -> str:
|
||
|
return live_server.url + path
|