Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions tests/test_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import pytest

from app.models import Product
from tests import utils


class TestProduct:
TEST_PRODUCT_NAME = "iPhone 13"
TEST_PRODUCT_DESC = "Latest Apple iPhone"

@pytest.fixture(autouse=True)
def setup(self, client):
self.client = client
with client.application.app_context():
assert Product.query.count() == 0

@pytest.fixture
def create_product(self, create_authenticated_headers):
def _create(name, description=None, subcategories=None, headers=None):
if headers is None:
headers = create_authenticated_headers()
payload = {"name": name}
if description is not None:
payload["description"] = description
if subcategories is not None:
payload["subcategories"] = subcategories
return self.client.post(
"/product/create", json=payload, headers=headers
)
return _create

def _count_products(self):
with self.client.application.app_context():
return Product.query.count()

def _verify_product_in_db(self, name, should_exist=True):
with self.client.application.app_context():
product = Product.query.filter_by(name=name).first()
if should_exist:
assert product is not None
assert product.name == name
return product
else:
assert product is None

def test_create_product(self, create_product):
response = create_product(self.TEST_PRODUCT_NAME, self.TEST_PRODUCT_DESC)

assert response.status_code == 201
data = response.get_json()
assert data["name"] == self.TEST_PRODUCT_NAME
assert data["description"] == self.TEST_PRODUCT_DESC
assert "id" in data
self._verify_product_in_db(self.TEST_PRODUCT_NAME)

def test_create_product_duplicate_name(self, create_product):
create_product(self.TEST_PRODUCT_NAME, self.TEST_PRODUCT_DESC)
response = create_product(self.TEST_PRODUCT_NAME, self.TEST_PRODUCT_DESC)

assert response.status_code == 500
assert self._count_products() == 1
self._verify_product_in_db(self.TEST_PRODUCT_NAME)

def test_get_product_by_id(self, create_product):
response = create_product("Pixel 6", "Google phone")
data = response.get_json()
p_id = data["id"]
get_resp = self.client.get(f"/product/{p_id}")

assert get_resp.status_code == 200
data = get_resp.get_json()
assert data["name"] == "Pixel 6"
assert data["id"] == p_id

def test_get_all_products(self, create_product):
create_product("A", "descA")
create_product("B", "descB")
resp = self.client.get("/products")

assert resp.status_code == 200
data = resp.get_json()
assert "products" in data
assert len(data["products"]) == 2
names = [prod["name"] for prod in data["products"]]
assert "A" in names
assert "B" in names

def test_update_product(self, create_authenticated_headers, create_product):
headers = create_authenticated_headers()
response = create_product("OldProduct", "OldDesc", headers=headers)
data = response.get_json()
p_id = data["id"]
update_resp = self.client.put(
f"/product/{p_id}/update", json={"name": "NewProduct", "description": "NewDesc"}, headers=headers
)

assert update_resp.status_code == 201
data = update_resp.get_json()
assert data["name"] == "NewProduct"
assert data["description"] == "NewDesc"
assert data["id"] == p_id
self._verify_product_in_db("NewProduct")
self._verify_product_in_db("OldProduct", should_exist=False)

def test_delete_product(self, create_authenticated_headers, create_product):
headers = create_authenticated_headers()
response = create_product("ToDelete", "desc", headers=headers)
data = response.get_json()
p_id = data["id"]
delete_resp = self.client.delete(f"/product/{p_id}", headers=headers)

assert delete_resp.status_code == 200
get_resp = self.client.get(f"/product/{p_id}")
assert get_resp.status_code == 404
self._verify_product_in_db("ToDelete", should_exist=False)

@pytest.mark.parametrize(
"get_headers, expected_code",
[
(lambda self: utils.get_expired_token_headers(self.client.application.app_context()), "token_expired"),
(lambda self: utils.get_invalid_token_headers(), "invalid_token"),
(lambda self: None, "authorization_required")
]
)
def test_create_product_token_error(self, get_headers, expected_code):
headers = get_headers(self)
response = self.client.post(
"/product/create", json={"name": "CreateTokenError"}, headers=headers
)
utils.verify_token_error_response(response, expected_code)
self._verify_product_in_db("CreateTokenError", should_exist=False)

@pytest.mark.parametrize(
"get_headers, expected_code",
[
(lambda self: utils.get_expired_token_headers(self.client.application.app_context()), "token_expired"),
(lambda self: utils.get_invalid_token_headers(), "invalid_token"),
(lambda self: None, "authorization_required")
]
)
def test_update_product_token_error(self, get_headers, create_product, create_authenticated_headers, expected_code):
headers = create_authenticated_headers()
response = create_product("UpdateTokenError", "desc", headers=headers)
data = response.get_json()
p_id = data["id"]

update_headers = get_headers(self)
update_resp = self.client.put(
f"/product/{p_id}/update",
json={"name": "UpdatedName"},
headers=update_headers,
)

utils.verify_token_error_response(update_resp, expected_code)
self._verify_product_in_db("UpdateTokenError")
self._verify_product_in_db("UpdatedName", should_exist=False)

@pytest.mark.parametrize(
"get_headers, expected_code",
[
(lambda self: utils.get_expired_token_headers(self.client.application.app_context()), "token_expired"),
(lambda self: utils.get_invalid_token_headers(), "invalid_token"),
(lambda self: None, "authorization_required")
]
)
def test_delete_product_token_error(self, get_headers, create_product, create_authenticated_headers, expected_code):
headers = create_authenticated_headers()
response = create_product("DeleteTokenError", "desc", headers=headers)
data = response.get_json()
p_id = data["id"]

delete_headers = get_headers(self)
delete_resp = self.client.delete(f"/product/{p_id}", headers=delete_headers)

utils.verify_token_error_response(delete_resp, expected_code)
self._verify_product_in_db("DeleteTokenError")

def test_products_pagination(self, create_product):
for i in range(15):
create_product(f"Product{i}", f"Description{i}")

# Page 1
resp1 = self.client.get("/products?page=1")
assert resp1.status_code == 200
data1 = resp1.get_json()
assert "products" in data1
assert len(data1["products"]) == 10

# Page 2
resp2 = self.client.get("/products?page=2")
assert resp2.status_code == 200
data2 = resp2.get_json()
assert "products" in data2
assert len(data2["products"]) == 5
Loading