from datetime import datetime, timedelta import pytest from ordr3.repo import AbstractOrderRepository class FakeOrderRepository(AbstractOrderRepository): """ Repository implementation for testing """ def __init__(self, session): self._orders = set() self._users = set() def add_order(self, order): """ add an order to the datastore """ self._orders.add(order) def get_order(self, reference): """ retrieve an order from the datastore """ return next(o for o in self._orders if o.id == reference) def list_orders(self): return sorted(self._orders, reverse=True, key=lambda x: x.created_on) def add_user(self, user): """ add a user to the datastore """ self._users.add(user) def get_user(self, reference): """ retrieve a user from the datastore """ return next(o for o in self._users if o.id == reference) def get_user_by_username(self, reference): """ retrieve a user from the datastore by username """ return next(o for o in self._users if o.username == reference) def get_user_by_email(self, reference): """ retrieve a user from the datastore by email """ return next(o for o in self._users if o.email == reference) def list_users(self): return sorted(self._users, key=lambda x: x.username) class FakePasslibContext: def __init__(self, needs_update): self.needs_update = needs_update def verify_and_update(self, password, hash): if password != hash: return False, None if self.needs_update: return True, password[::-1] else: return True, None @pytest.fixture def prefilled_repo(): from itertools import count from ordr3.models import OrderItem, OrderStatus i = count() catalog = { 1: "Ethanol", 2: "Aceton", 3: "NaOH", 4: "Coffee", 5: "Water", } def _create_order(item, date, status): order = OrderItem(next(i), catalog[item], item, "", "", "", "", "") order.created_on = date order.status = status return order month = timedelta(days=30) today = datetime.now() repo = FakeOrderRepository(session=None) # should be consumables repo.add_order(_create_order(1, today - month * 1, OrderStatus.ORDERED)) repo.add_order(_create_order(1, today - month * 2, OrderStatus.ORDERED)) repo.add_order(_create_order(1, today - month * 3, OrderStatus.COMPLETED)) repo.add_order(_create_order(2, today - month * 1, OrderStatus.ORDERED)) repo.add_order(_create_order(2, today - month * 2, OrderStatus.ORDERED)) repo.add_order(_create_order(2, today - month * 3, OrderStatus.COMPLETED)) # no consumable, only two repeats repo.add_order(_create_order(3, today - month * 1, OrderStatus.ORDERED)) repo.add_order(_create_order(3, today - month * 2, OrderStatus.ORDERED)) # no consumable, only two repeats in the last two years repo.add_order(_create_order(4, today - month * 1, OrderStatus.ORDERED)) repo.add_order(_create_order(4, today - month * 2, OrderStatus.ORDERED)) repo.add_order(_create_order(4, today - month * 50, OrderStatus.ORDERED)) # no consumable, one order on hold repo.add_order(_create_order(5, today - month * 1, OrderStatus.ORDERED)) repo.add_order(_create_order(5, today - month * 2, OrderStatus.ORDERED)) repo.add_order(_create_order(5, today - month * 3, OrderStatus.HOLD)) return repo def test_service_find_consumables(prefilled_repo): from ordr3.services import find_consumables result = find_consumables(prefilled_repo) assert len(result) == 2 assert [o.id for o in result] == [3, 0] def test_create_log_entry(prefilled_repo): from ordr3.services import create_log_entry from ordr3.models import OrderStatus, User order = prefilled_repo.get_order(1) user = User(*list("ABCDEFG")) create_log_entry(order, OrderStatus.APPROVAL, user) assert len(order.log) == 1 log_entry = order.log[0] assert log_entry.order_id == order.id assert log_entry.status == OrderStatus.APPROVAL assert log_entry.by == "B" assert log_entry.user_id == "A" assert isinstance(log_entry.date, datetime) assert order.status == log_entry.status assert order.created_by == log_entry.by assert order.created_on == log_entry.date @pytest.mark.parametrize( "update,new_hash", [(False, "1234"), (True, "4321"),], # noqa: E231 ) def test_verify_username_and_password_valid(update, new_hash): from ordr3.models import User, UserRole from ordr3.services import verify_credentials user = User(2, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER) repo = FakeOrderRepository(None) repo.add_user(user) pass_ctx = FakePasslibContext(update) user = verify_credentials(repo, pass_ctx, user.username, user.password) assert user is not None assert user.password == new_hash @pytest.mark.parametrize( "name,pwd", [("You", "1234"), ("Me", "abcd"),], # noqa: E231 ) def test_verify_username_and_password_invalid(name, pwd): from ordr3.models import User, UserRole from ordr3.services import verify_credentials user = User(2, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER) repo = FakeOrderRepository(None) repo.add_user(user) pass_ctx = FakePasslibContext(False) assert verify_credentials(repo, pass_ctx, name, pwd) is None