def test_has_permission(self):
        user = User()
        user.register("eden", "password")
        self.store.add_manager(self.owner, user, [ManagerPermission.USERS_QUESTIONS, ManagerPermission.EDIT_MANAGER_PER])

        # All Valid - one permission.
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_INV))

        # All Valid - two permission.
        self.assertTrue(self.store.has_permission(user.get_nickname(), ManagerPermission.USERS_QUESTIONS))

        user2 = User()
        user2.register("Not a manager", "Password")

        # Invalid - not a manager
        self.assertFalse(self.store.has_permission(user2.get_nickname(), ManagerPermission.USERS_QUESTIONS))

        # Invalid - manager without the correct permission
        self.assertFalse(self.store.has_permission(user.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - Owner
        # self.assertFalse(self.store.has_permission(self.owner.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - User doesn't exist
        self.assertFalse(self.store.has_permission("user.get_nickname()", ManagerPermission.EDIT_POLICIES))
    def test_register(self):
        # All valid
        guest1 = User()
        self.assertTrue(guest1.register("valid", "valid"))
        self.assertTrue(guest1.is_registered())
        self.assertTrue(guest1.is_logged_out())
        self.assertFalse(guest1.is_logged_in())

        # All valid -username has white spaces but not empty
        guest11 = User()
        self.assertTrue(
            guest11.register("valid validovich", "valid")['response'])
        self.assertTrue(guest11.is_registered())
        self.assertTrue(guest11.is_logged_out())
        self.assertFalse(guest11.is_logged_in())

        # Invalid - username is empty
        guest2 = User()
        self.assertFalse(guest2.register("", "valid")['response'])
        self.assertFalse(guest2.is_registered())
        self.assertTrue(guest2.is_logged_out())
        self.assertFalse(guest2.is_logged_in())

        # Invalid - password is empty
        self.assertFalse(guest2.register("valid", "")['response'])
        self.assertFalse(guest2.is_registered())
        self.assertTrue(guest2.is_logged_out())
        self.assertFalse(guest2.is_logged_in())

        # Invalid - user already exist
        self.assertFalse(guest1.register("not valid", "not valid")['response'])
        self.assertEqual(guest1.get_nickname(), "valid")
    def test_get_nickname(self):
        guest = User()
        self.__user.logout()

        # All valid - user is registered
        self.assertEqual(self.__user.get_nickname(), self.__valid_name)

        # All valid - user isn't registered
        self.assertIsNone(guest.get_nickname())
    def test_add_manager(self):
        user = User()
        user.register("eden", "password")

        # All valid
        self.assertTrue(self.store.add_manager(self.owner, user, [ManagerPermission.APPOINT_MANAGER,
                                                                  ManagerPermission.EDIT_MANAGER_PER]))
        self.assertEqual(2, len(self.store.get_managers()))
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        guest = User()

        # Invalid - user doesn't register
        self.assertFalse(self.store.add_manager(self.owner, guest, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        manager = User()
        manager.register("probably eden", "password")
        guest.register("Just Guest", "Password")

        # Invalid - Owner/manager isn't manager/owner
        self.assertFalse(self.store.add_manager(guest, manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        # Invalid - Already Manager
        self.assertFalse(self.store.add_manager(self.owner, user, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        # All Valid - Appoint by manager
        self.assertTrue(self.store.add_manager(user, manager, [ManagerPermission.APPOINT_MANAGER]))

        # Invalid - Circular appointments
        self.assertFalse(self.store.add_manager(manager, user, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 3)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())
        self.assertTrue(manager in self.store.get_managers())

        self.store.edit_manager_permissions(user, manager.get_nickname(), [ManagerPermission.USERS_QUESTIONS])

        # Invalid - Manager doesn't have permissions
        self.assertFalse(self.store.add_manager(manager, guest, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 3)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())
        self.assertTrue(manager in self.store.get_managers())
    def test_add_owner(self):
        user = User()
        user.register("eden", "password")

        # All valid
        self.assertTrue(self.store.add_owner("Eytan", user)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        guest = User()

        # Invalid - user doesn't register
        self.assertFalse(self.store.add_owner("Eytan", guest)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        owner = User()
        owner.register("probably eden", "password")

        # Invalid - Owner doesn't exist
        self.assertFalse(self.store.add_owner("Eytan Not an Owner", owner)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        # Invalid - Already owner
        result = self.store.add_owner(self.owner.get_nickname(), user)['response']
        self.assertFalse(result)
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        # Invalid - Circular appointments
        self.assertFalse(self.store.add_owner(user.get_nickname(), self.owner)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        manager = User()
        manager.register("Half Eytan, half not Eytan", "Definitely Password")
        self.store.get_store_manager_appointments().append(
            StoreAppointment(self.owner, manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertTrue(manager in self.store.get_managers())

        # All valid - appoint manager as owner
        self.assertTrue(self.store.add_owner("Eytan", manager)['response'])
        self.assertEqual(len(self.store.get_owners()), 3)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(manager in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())
        self.assertFalse(manager in self.store.get_managers())
    def test_remove_products(self):
        product1: Product = Product("Chair", 100, "Furniture")
        product3: Product = Product("Sofa", 1, "Furniture")

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)

        # All Valid - one product
        self.assertTrue(self.store.remove_products("Eytan", ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5,0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Sofa", 1, "Furniture", 3, 0)

        # All valid - two products
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(self.store.remove_products("Eytan", ["Chair", "Sofa"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Sofa", 1, "Furniture", 3, 0)

        # All valid - not all inventory removed
        self.assertTrue(self.store.remove_products("Eytan", ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # All valid - Manager
        self.assertTrue(self.store.remove_products("Not Eytan", ["Sofa"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        # Invalid product
        self.assertFalse(self.store.remove_products("Not Eytan", ["Eytan's Toy"]))

        # Invalid - Manager/Owner
        self.assertFalse(self.store.remove_products("", ["Chair", "Sofa"]))

        bad_manager = User()
        bad_manager.register("Half Eytan, half not Eytan", "Definitely Password")
        self.store.get_store_manager_appointments().append(
            StoreAppointment(self.owner, bad_manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))

        # Invalid - Manager permissions
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.assertFalse(self.store.remove_products(bad_manager.get_nickname(), ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)
    def test_get_purchases(self):
        self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                            [ManagerPermission.WATCH_PURCHASE_HISTORY])
        purchase: Purchase = Purchase([{"product_name": "Chair", "product_price": 100, "amount": 5},
                                          {"product_name": "Sofa", "product_price": 1, "amount": 1}], 501,
                                         self.store.get_name(), self.owner.get_nickname())
        self.store.add_purchase(purchase)

        # All valid - owner
        self.assertListEqual(self.store.get_purchases(self.owner.get_nickname()), [purchase])

        # All valid - manager
        self.assertListEqual(self.store.get_purchases(self.manager.get_nickname()), [purchase])

        user = User()
        user.register("just a user", "but a special password")

        # Invalid - not an owner/manager
        self.assertListEqual(self.store.get_purchases(user.get_nickname()), [])

        self.store.add_manager(self.owner, user, [ManagerPermission.DEL_MANAGER])

        # Invalid - not the right permissions
        self.assertListEqual(self.store.get_purchases(user.get_nickname()), [])
    def test_remove_manager(self):
        # def remove_manager(self, appointer_nickname: str, appointee_nickname: str) -> bool:
        manager1 = User()
        manager1.register("probably eden", "password")
        self.store.add_manager(self.owner, manager1,
                               [ManagerPermission.DEL_MANAGER, ManagerPermission.APPOINT_MANAGER])

        manager2 = User()
        manager2.register("almost definitely eden", "password")
        self.store.add_manager(manager1, manager2, [ManagerPermission.EDIT_POLICIES])

        # Invalid - not the right permissions
        self.assertFalse(self.store.remove_manager(manager2.get_nickname(), self.manager.get_nickname()))
        self.assertTrue(self.manager in self.store.get_managers())

        # All valid - manager as appointer
        self.assertTrue(self.store.remove_manager(manager1.get_nickname(), manager2.get_nickname()))
        self.assertFalse(manager2 in self.store.get_managers())

        # All valid - owner as appointer
        self.assertTrue(self.store.remove_manager(self.owner.get_nickname(), manager1.get_nickname()))
        self.assertFalse(manager1 in self.store.get_managers())

        managers = self.store.get_managers()

        # Invalid - not an existing manager
        self.assertFalse(self.store.remove_manager(self.owner.get_nickname(), manager1.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())

        # Invalid - not an existing appointer
        self.assertFalse(self.store.remove_manager(manager2.get_nickname(), self.manager.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())

        user = User()
        user.register("not an owner", "not a password")
        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not the owner that appoint the manager
        self.assertFalse(self.store.remove_manager(user.get_nickname(), self.manager.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())
class UserTests(unittest.TestCase):
    def setUp(self):
        self.__valid_name = "anna9218"
        self.__valid_password = "******"
        self.__user = User()
        self.__user.register(self.__valid_name, self.__valid_password)

        self.__product = Product("Eytan's product", 12, "Eytan's category")
        self.__store: Store = Store("myStore")
        self.__products_to_add = [{
            "product": self.__product,
            "store_name": self.__store.get_name(),
            "amount": 1,
            "discount_type": DiscountType.DEFAULT,
            "purchase_type": PurchaseType.DEFAULT
        }]  # products_stores_quantity_ls

    def test_register(self):
        # All valid
        guest1 = User()
        self.assertTrue(guest1.register("valid", "valid"))
        self.assertTrue(guest1.is_registered())
        self.assertTrue(guest1.is_logged_out())
        self.assertFalse(guest1.is_logged_in())

        # All valid -username has white spaces but not empty
        guest11 = User()
        self.assertTrue(
            guest11.register("valid validovich", "valid")['response'])
        self.assertTrue(guest11.is_registered())
        self.assertTrue(guest11.is_logged_out())
        self.assertFalse(guest11.is_logged_in())

        # Invalid - username is empty
        guest2 = User()
        self.assertFalse(guest2.register("", "valid")['response'])
        self.assertFalse(guest2.is_registered())
        self.assertTrue(guest2.is_logged_out())
        self.assertFalse(guest2.is_logged_in())

        # Invalid - password is empty
        self.assertFalse(guest2.register("valid", "")['response'])
        self.assertFalse(guest2.is_registered())
        self.assertTrue(guest2.is_logged_out())
        self.assertFalse(guest2.is_logged_in())

        # Invalid - user already exist
        self.assertFalse(guest1.register("not valid", "not valid")['response'])
        self.assertEqual(guest1.get_nickname(), "valid")

    def test_login(self):
        # All Valid
        self.assertTrue(
            self.__user.login(self.__valid_name,
                              self.__valid_password)['response'])
        self.assertTrue(self.__user.is_logged_in())
        self.assertFalse(self.__user.is_logged_out())

        self.__user.logout()

        # Invalid - username + whitespaces, valid password
        self.assertFalse(
            self.__user.login(self.__valid_name + " ",
                              self.__valid_password)['response'])
        self.assertFalse(self.__user.is_logged_in())
        self.assertTrue(self.__user.is_logged_out())

        # Invalid - valid username, password + whitespaces
        self.assertFalse(
            self.__user.login(self.__valid_name,
                              self.__valid_password + " ")['response'])
        self.assertFalse(self.__user.is_logged_in())
        self.assertTrue(self.__user.is_logged_out())

        # Invalid -username doesn't exist
        self.assertFalse(
            self.__user.login("self.__valid_name",
                              self.__valid_password)['response'])
        self.assertFalse(self.__user.is_logged_in())
        self.assertTrue(self.__user.is_logged_out())

        # Invalid - incorrect password
        self.assertFalse(
            self.__user.login(self.__valid_name,
                              "self.__valid_password")['response'])
        self.assertFalse(self.__user.is_logged_in())
        self.assertTrue(self.__user.is_logged_out())

        # All Valid - second and third try
        self.assertTrue(
            self.__user.login(self.__valid_name,
                              self.__valid_password)['response'])
        self.assertTrue(self.__user.is_logged_in())
        self.assertFalse(self.__user.is_logged_out())
        self.__user.logout()

        self.assertTrue(
            self.__user.login(self.__valid_name,
                              self.__valid_password)['response'])
        self.assertTrue(self.__user.is_logged_in())
        self.assertFalse(self.__user.is_logged_out())
        self.__user.logout()

        registered = User()
        registered.register("Eytan", "Eytan's password")

        # Invalid - password of different registered user
        self.assertFalse(
            self.__user.login(self.__valid_name,
                              "Eytan's password")['response'])
        self.assertFalse(self.__user.is_logged_in())
        self.assertTrue(self.__user.is_logged_out())

        self.__user.login(self.__valid_name, self.__valid_password)

        # Invalid - user already logged in
        self.assertFalse(
            self.__user.login(self.__valid_name,
                              self.__valid_password)['response'])
        self.assertTrue(self.__user.is_logged_in())
        self.assertFalse(self.__user.is_logged_out())

        self.__user.logout()

        # Register and login other users and than try to login again
        self.assertTrue(
            registered.login("Eytan", "Eytan's password")['response'])
        registered.logout()

        other_user = User()
        other_user.register("yarin", "100")
        self.assertTrue(other_user.login("yarin", "100")['response'])
        other_user.logout()
        self.assertTrue(
            self.__user.login(self.__valid_name,
                              self.__valid_password)['response'])

    def test_logout(self):
        self.__user.login(self.__valid_name, self.__valid_password)

        # All valid
        self.assertTrue(self.__user.logout())
        self.assertTrue(self.__user.is_logged_out())
        self.assertFalse(self.__user.is_logged_in())

        # Invalid - user is already logged out
        self.assertFalse(self.__user.logout())
        self.assertTrue(self.__user.is_logged_out())
        self.assertFalse(self.__user.is_logged_in())

        guest = User()

        # Invalid - user isn't register
        self.assertFalse(guest.logout())
        self.assertTrue(guest.is_logged_out())
        self.assertFalse(guest.is_logged_in())

    def test_check_password(self):
        # All valid
        self.assertTrue(self.__user.check_password(self.__valid_password))

        # Invalid password doesn't exist
        self.assertFalse(self.__user.check_password("self.__valid_password"))

        registered = User()
        registered.register("Eytan", "Eytan's password")

        # Invalid - password exist but isn't corresponding with the username
        self.assertFalse(registered.check_password(self.__valid_password))

    def test_check_nickname(self):
        # All valid
        self.assertTrue(self.__user.check_nickname(self.__valid_name))

        # Invalid password doesn't exist
        self.assertFalse(self.__user.check_nickname("self.__valid_password"))

        registered = User()
        registered.register("Eytan", "Eytan's password")

        # Invalid - password exist but isn't corresponding with the username
        self.assertFalse(registered.check_nickname(self.__valid_name))

    def test_is_logged_in(self):
        guest = User()
        subscriber = User()
        subscriber.register("Sub", "scriber")
        self.__user.login(self.__valid_name, self.__valid_password)

        # All valid
        self.assertTrue(self.__user.is_logged_in())

        # Not valid - user is logged out
        self.assertFalse(subscriber.is_logged_in())

        # Not valid - user isn't registered
        self.assertFalse(guest.is_logged_in())

    def test_is_logged_out(self):
        guest = User()
        subscriber = User()
        subscriber.register("Sub", "scriber")
        subscriber.login("Sub", "scriber")
        self.__user.logout()

        # All valid
        self.assertTrue(self.__user.is_logged_out())

        # Not valid - user is logged out
        self.assertFalse(subscriber.is_logged_out())

        # Not valid - user isn't registered
        self.assertTrue(guest.is_logged_out())

    def test_is_registered(self):
        guest = User()
        self.__user.logout()

        # All valid - user is registered
        self.assertTrue(self.__user.is_registered())

        # All valid - user isn't registered
        self.assertFalse(guest.is_registered())

    def test_get_nickname(self):
        guest = User()
        self.__user.logout()

        # All valid - user is registered
        self.assertEqual(self.__user.get_nickname(), self.__valid_name)

        # All valid - user isn't registered
        self.assertIsNone(guest.get_nickname())

    def test_save_products_to_basket(self):
        guest = User()

        # All valid- guest
        self.assertTrue(
            guest.save_products_to_basket(self.__products_to_add)['response'])
        self.assertEqual(
            1,
            len(guest.get_shopping_cart().get_store_basket(
                self.__store.get_name()).get_products()))
        products = [
            product_as_dictionary['product']
            for product_as_dictionary in guest.get_shopping_cart().
            get_store_basket(self.__store.get_name()).get_products()
        ]
        self.assertIn(self.__product, products)

        # Valid - empty products
        self.assertTrue(guest.save_products_to_basket([])['response'])
        self.assertEqual(
            1,
            len(guest.get_shopping_cart().get_store_basket(
                self.__store.get_name()).get_products()))
        products = [
            product_as_dictionary['product']
            for product_as_dictionary in guest.get_shopping_cart().
            get_store_basket(self.__store.get_name()).get_products()
        ]
        self.assertIn(self.__product, products)

        # Invalid - product is None
        self.assertFalse(
            guest.save_products_to_basket([{
                "product":
                None,
                "store_name":
                self.__store.get_name(),
                "amount":
                1,
                "discount_type":
                DiscountType.DEFAULT,
                "purchase_type":
                PurchaseType.DEFAULT
            }])['response'])
        self.assertEqual(
            1,
            len(guest.get_shopping_cart().get_store_basket(
                self.__store.get_name()).get_products()))
        products = [
            product_as_dictionary['product']
            for product_as_dictionary in guest.get_shopping_cart().
            get_store_basket(self.__store.get_name()).get_products()
        ]
        self.assertIn(self.__product, products)

        # Invalid - Edge case - quantity is zero
        self.assertFalse(
            guest.save_products_to_basket([{
                "product":
                self.__product,
                "store_name":
                self.__store.get_name(),
                "amount":
                0,
                "discount_type":
                DiscountType.DEFAULT,
                "purchase_type":
                PurchaseType.DEFAULT
            }])['response'])
        self.assertEqual(
            1,
            len(guest.get_shopping_cart().get_store_basket(
                self.__store.get_name()).get_products()))
        products = [
            product_as_dictionary['product']
            for product_as_dictionary in guest.get_shopping_cart().
            get_store_basket(self.__store.get_name()).get_products()
        ]
        self.assertIn(self.__product, products)

        # Invalid - Negative quantity
        self.assertFalse(
            guest.save_products_to_basket([{
                "product":
                self.__product,
                "store_name":
                self.__store.get_name(),
                "amount":
                -11,
                "discount_type":
                DiscountType.DEFAULT,
                "purchase_type":
                PurchaseType.DEFAULT
            }])['response'])
        self.assertEqual(
            1,
            len(guest.get_shopping_cart().get_store_basket(
                self.__store.get_name()).get_products()))
        products = [
            product_as_dictionary['product']
            for product_as_dictionary in guest.get_shopping_cart().
            get_store_basket(self.__store.get_name()).get_products()
        ]
        self.assertIn(self.__product, products)

    # @logger
    def tearDown(self):
        # maybe delete the registered user resulted from this test
        pass

    def __repr__(self):
        return repr("UserTests")

    if __name__ == '__main__':
        unittest.main()
    def test_edit_manager_permissions(self):
        manager1 = User()
        manager1.register("probably eden", "password")
        self.store.add_manager(self.owner, manager1,
                               [ManagerPermission.EDIT_MANAGER_PER, ManagerPermission.APPOINT_MANAGER])

        manager2 = User()
        manager2.register("almost definitely eden", "password")
        self.store.add_manager(manager1, manager2, [ManagerPermission.EDIT_POLICIES])

        # All valid - owner
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_INV))

        # All valid - manager
        self.assertTrue(self.store.edit_manager_permissions(manager1, manager2.get_nickname(),
                                                            [ManagerPermission.EDIT_INV]))
        self.assertTrue(self.store.has_permission(manager2.get_nickname(), ManagerPermission.EDIT_INV))
        self.assertFalse(self.store.has_permission(manager2.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - owner, two permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.WATCH_PURCHASE_HISTORY,
                                                             ManagerPermission.DEL_OWNER]))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - owner, two permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.WATCH_PURCHASE_HISTORY,
                                                             ManagerPermission.DEL_OWNER]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - empty permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, manager1.get_nickname(), []))
        for i in range(1, 11):
            self.assertFalse(self.store.has_permission(manager1.get_nickname(), ManagerPermission(i)))

        user = User()
        user.register("not an owner", "not a password")

        # Invalid - not an owner
        self.assertFalse(self.store.edit_manager_permissions(user, self.manager.get_nickname(),
                                                            [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not a manager
        self.assertFalse(self.store.edit_manager_permissions(self.owner, user,
                                                             [ManagerPermission.EDIT_POLICIES]))
        for appointment in self.store.get_store_manager_appointments():
            self.assertFalse(appointment.get_appointee().get_nickname() == user.get_nickname())

        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not the owner which appoint the manager
        self.assertFalse(self.store.edit_manager_permissions(user, self.manager.get_nickname(),
                                                             [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - try change permissions to an owner
        self.assertFalse(self.store.edit_manager_permissions(self.owner, user,
                                                             [ManagerPermission.EDIT_POLICIES]))
        for appointment in self.store.get_store_manager_appointments():
            self.assertFalse(appointment.get_appointee().get_nickname() == user.get_nickname())
class StoreTests(unittest.TestCase):
    # @logger
    def setUp(self):
        self.store: Store = Store("myStore")
        self.owner = User()
        self.owner.register("Eytan", "password")
        self.store.get_owners_appointments().append(StoreAppointment(None, self.owner, []))
        self.manager = User()
        self.manager.register("Not Eytan", "Yes Password")
        self.store.get_store_manager_appointments().append(StoreAppointment(self.owner, self.manager,
                                                                            [ManagerPermission.EDIT_INV]))

        dis_details = {'name': "p1", 'product': "Eytan"}
        later_date = datetime(2021, 8, 21)
        pre_con__details = {'product': "Eytan", 'min_amount': 2, 'min_basket_price': None}
        leaf_pol1 = ConditionalDiscountPolicy(2.5, later_date, dis_details, pre_con__details)
        dis_details = {'name': "p2", 'product': "Eytan"}
        pre_con__details = {'product': "all", 'min_amount': None, 'min_basket_price': 1}
        leaf_pol2 = ConditionalDiscountPolicy(5, later_date, dis_details, pre_con__details)
        self.__policy = DiscountPolicy(jsonpickle.encode(leaf_pol1), jsonpickle.encode(leaf_pol2),
                                       CompositeFlag.XOR, 10, "Comp_Pol", later_date)
        self.store.get_discount_policies().insert(0, self.__policy)

        # self.__product1 = {"name": "Chair", "price": 100, "category": "Furniture", "amount": 10}
        # self.__product2 = {"name": "TV", "price": 10, "category": "Electric", "amount": 1}
        # self.__product3 = {"name": "Sofa", "price": 1, "category": "Furniture", "amount": 2}

    # @logger
    def test_get_products_by(self):
        self.store.add_products("Eytan", [{"name": "Chair", "price": 100, "category": "Furniture", "amount": 10,
                                           "purchase_type": 0},
                                          {"name": "TV", "price": 10, "category": "Electric", "amount": 1,
                                           "purchase_type": 0},
                                          {"name": "Sofa", "price": 1, "category": "Furniture", "amount": 2,
                                           "purchase_type": 0}])
        product1: Product = Product("Chair", 100, "Furniture")
        product2: Product = Product("TV", 10, "Electric")
        product3: Product = Product("Sofa", 1, "Furniture")

        # Option 1- All valid
        ls = self.store.get_products_by(1, "Chair")
        self.assertEqual(len(ls), 1)
        self.assertTrue(product1 in ls)

        # Option 1- Not an existing product
        ls = self.store.get_products_by(1, "EytanIsTheBestEver!!!")
        self.assertEqual(len(ls), 0)

        # Option 2- All valid
        ls = self.store.get_products_by(2, "a")
        self.assertEqual(len(ls), 2)
        self.assertTrue(product1 in ls)
        self.assertTrue(product3 in ls)

        # Option 2- Empty products list
        ls = self.store.get_products_by(2, "EytanIsTheBestEver!!!")
        self.assertEqual(len(ls), 0)

        # Option 3 - All valid
        ls = self.store.get_products_by(3, "Furniture")
        self.assertEqual(len(ls), 2)
        self.assertTrue(product1 in ls)
        self.assertTrue(product3 in ls)

        ls = self.store.get_products_by(3, "Electric")
        self.assertEqual(len(ls), 1)
        self.assertTrue(product2 in ls)

        # Option 3 - Not an existing category
        ls = self.store.get_products_by(3, "EytanIsTheBestEver!!!")
        self.assertEqual(len(ls), 0)

    # @logger
    def test_add_products(self):
        product1: Product = Product("Chair", 100, "Furniture")
        product3: Product = Product("Sofa", 1, "Furniture")

        # All Valid - New Products
        self.assertTrue(
            self.store.add_products("Eytan", [{"name": "Chair", "price": 100, "category": "Furniture", "amount": 5,
                                               "purchase_type": 0},
                                              {"name": "Sofa", "price": 1, "category": "Furniture", "amount": 3,
                                               "purchase_type": 0}]))
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # All valid - Existing products
        self.assertTrue(
            self.store.add_products("Eytan", [{"name": "Chair", "price": 100, "category": "Furniture", "amount": 6,
                                               "purchase_type": 0}]))
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # Invalid Product - negative price
        self.assertFalse(
            self.store.add_products("Eytan",
                                    [{"name": "Eytan's Toy", "price": -99, "category": "Furniture", "amount": 5,
                                      "purchase_type": 0}])['response'])
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("Eytan's Toy" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # Invalid amount - negative amount
        self.assertFalse(
            self.store.add_products("Eytan",
                                    [{"name": "Eytan's Toy", "price": 1, "category": "Furniture", "amount": -5,
                                      "purchase_type": 0}])['response'])
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("Eytan's Toy" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # Invalid Product - invalid name
        self.assertFalse(
            self.store.add_products("Eytan", [{"name": "", "price": 100, "category": "Furniture", "amount": 5,
                                               "purchase_type": 0}])['response'])
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # Invalid Product - invalid category
        self.assertFalse(
            self.store.add_products("Eytan", [{"name": "Eytan's Toy", "price": 100, "category": "", "amount": 5,
                                               "purchase_type": 0}])['response'])
        self.assertEqual(len(self.store.get_products_by(2, "")), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("Eytan's Toy" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

    # @logger
    def test_add_product(self):
        product1: Product = Product("Chair", 100, "Furniture")
        product3: Product = Product("Sofa", 1, "Furniture")

        # All valid

        # First Addition
        self.assertTrue(self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 5)

        # Second Addition
        self.assertTrue(self.store.add_product("Eytan", "Sofa", 1, "Furniture", 0, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Sofa"), 0)

        # Adding existing product
        self.assertTrue(self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)

        # Invalid

        # Negative amount
        self.assertFalse(self.store.add_product("Eytan", "Chair", 100, "Furniture", -5, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)

        # Negative price
        self.assertFalse(self.store.add_product("Eytan", "Chair", -100, "Furniture", 5, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)

        # Empty name
        self.assertFalse(self.store.add_product("Eytan", "", 100, "Furniture", 5, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)

        # Empty category
        self.assertFalse(self.store.add_product("Eytan", "Eytan's Toy", 100, "", 5, 0))
        self.assertEqual(self.store.get_inventory().len(), 2)
        products_names = [product.get_name() for product in self.store.get_products_by(2, "")]
        self.assertFalse("Eytan's Toy" in products_names)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

    # @logger
    def test_remove_products(self):
        product1: Product = Product("Chair", 100, "Furniture")
        product3: Product = Product("Sofa", 1, "Furniture")

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)

        # All Valid - one product
        self.assertTrue(self.store.remove_products("Eytan", ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5,0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Sofa", 1, "Furniture", 3, 0)

        # All valid - two products
        self.assertEqual(self.store.get_inventory().len(), 2)
        self.assertTrue(self.store.remove_products("Eytan", ["Chair", "Sofa"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Sofa", 1, "Furniture", 3, 0)

        # All valid - not all inventory removed
        self.assertTrue(self.store.remove_products("Eytan", ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product3 in self.store.get_products_by(2, ""))

        # All valid - Manager
        self.assertTrue(self.store.remove_products("Not Eytan", ["Sofa"]))
        self.assertEqual(self.store.get_inventory().len(), 0)

        # Invalid product
        self.assertFalse(self.store.remove_products("Not Eytan", ["Eytan's Toy"]))

        # Invalid - Manager/Owner
        self.assertFalse(self.store.remove_products("", ["Chair", "Sofa"]))

        bad_manager = User()
        bad_manager.register("Half Eytan, half not Eytan", "Definitely Password")
        self.store.get_store_manager_appointments().append(
            StoreAppointment(self.owner, bad_manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))

        # Invalid - Manager permissions
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.assertFalse(self.store.remove_products(bad_manager.get_nickname(), ["Chair"]))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product1 in self.store.get_products_by(2, ""))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 10)

    # @logger
    def test_remove_product(self):
        product2: Product = Product("Not Chair", 1, "Furniture")

        # All valid - Empty inventory
        self.assertFalse(self.store.remove_product("Chair"))

        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)
        self.store.add_product("Eytan", "Not Chair", 1, "Furniture", 3, 0)

        # All valid
        self.assertTrue(self.store.remove_product("Chair"))
        self.assertEqual(self.store.get_inventory().len(), 1)
        self.assertTrue(product2 in self.store.get_products_by(2, ""))

        # Invalid - Not an existing product
        self.assertFalse(self.store.remove_product("Eytan's Toy"))

    # @logger
    def test_change_price(self):
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)

        # All valid - first change
        self.assertTrue(self.store.change_price("Chair", 13))
        self.assertEqual(self.store.get_product("Chair").get_price(), 13)

        # All valid - second change
        self.assertTrue(self.store.change_price("Chair", 8.5))
        self.assertEqual(self.store.get_product("Chair").get_price(), 8.5)

        # Invalid- not existing product
        self.assertFalse(self.store.change_price("NNNN", 8))
        self.assertIsNone(self.store.get_product("NNNN"))

        # Invalid- negative price
        self.assertFalse(self.store.change_price("Chair", -8))
        self.assertEqual(self.store.get_product("Chair").get_price(), 8.5)

        # Edge case - change to zero
        self.assertTrue(self.store.change_price("Chair", 0.0))
        self.assertEqual(self.store.get_product("Chair").get_price(), 0)

    # @logger
    def test_change_name(self):
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)

        # All valid - first change
        self.assertTrue(self.store.change_name("Chair", "Chair222"))
        self.assertIsNotNone(self.store.get_product("Chair222"))
        self.assertIsNone(self.store.get_product("Chair"))

        # All valid - second change
        self.assertTrue(self.store.change_name("Chair222", "Blaaaa"))
        self.assertIsNotNone(self.store.get_product("Blaaaa"))
        self.assertIsNone(self.store.get_product("Chair222"))

        # Invalid - Not an existing product
        self.assertFalse(self.store.change_name("NNNN", "blaaa"))
        self.assertIsNone(self.store.get_product("NNNN"))
        self.assertIsNone(self.store.get_product("blaaa"))

        # Invalid - Empty name
        self.assertFalse(self.store.change_name("Blaaaa", ""))
        self.assertIsNone(self.store.get_product(""))
        self.assertIsNotNone(self.store.get_product("Blaaaa"))

    # @logger
    def test_change_amount(self):
        self.store.add_product("Eytan", "Chair", 100, "Furniture", 5, 0)

        # All valid - first change
        self.assertTrue(self.store.change_amount("Chair", 13))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 13)

        # All valid - second change
        self.assertTrue(self.store.change_amount("Chair", 8))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 8)

        # Invalid- not existing product
        self.assertFalse(self.store.change_amount("NNNN", 8))
        self.assertIsNone(self.store.get_product("NNNN"))

        # Invalid- negative amount
        self.assertFalse(self.store.change_amount("Chair", -8))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 8)

        # Edge case - change to zero
        self.assertTrue(self.store.change_amount("Chair", 0))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 0)

    # @logger
    def test_add_owner(self):
        user = User()
        user.register("eden", "password")

        # All valid
        self.assertTrue(self.store.add_owner("Eytan", user)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        guest = User()

        # Invalid - user doesn't register
        self.assertFalse(self.store.add_owner("Eytan", guest)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        owner = User()
        owner.register("probably eden", "password")

        # Invalid - Owner doesn't exist
        self.assertFalse(self.store.add_owner("Eytan Not an Owner", owner)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        # Invalid - Already owner
        result = self.store.add_owner(self.owner.get_nickname(), user)['response']
        self.assertFalse(result)
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        # Invalid - Circular appointments
        self.assertFalse(self.store.add_owner(user.get_nickname(), self.owner)['response'])
        self.assertEqual(len(self.store.get_owners()), 2)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())

        manager = User()
        manager.register("Half Eytan, half not Eytan", "Definitely Password")
        self.store.get_store_manager_appointments().append(
            StoreAppointment(self.owner, manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertTrue(manager in self.store.get_managers())

        # All valid - appoint manager as owner
        self.assertTrue(self.store.add_owner("Eytan", manager)['response'])
        self.assertEqual(len(self.store.get_owners()), 3)
        self.assertTrue(user in self.store.get_owners())
        self.assertTrue(manager in self.store.get_owners())
        self.assertTrue(self.owner in self.store.get_owners())
        self.assertFalse(manager in self.store.get_managers())

    # @logger
    def test_is_owner(self):
        user = User()
        user.register("eden", "password")

        # All Valid
        self.store.add_owner("Eytan", user)
        self.assertTrue(self.store.is_owner("eden"))

        # Invalid - Not an existing user
        self.assertFalse(self.store.is_owner("not eden"))

        user2 = User()
        user2.register("Maybe Eden", "Definitely password")

        # Invalid - Existing user, not an owner
        self.assertFalse(self.store.is_owner("Maybe Eden"))

        self.store.add_manager(user, user2, [ManagerPermission.WATCH_PURCHASE_HISTORY])

        # Invalid - Existing manager
        self.assertFalse(self.store.is_owner("Maybe Eden"))

    # @logger
    def test_add_manager(self):
        user = User()
        user.register("eden", "password")

        # All valid
        self.assertTrue(self.store.add_manager(self.owner, user, [ManagerPermission.APPOINT_MANAGER,
                                                                  ManagerPermission.EDIT_MANAGER_PER]))
        self.assertEqual(2, len(self.store.get_managers()))
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        guest = User()

        # Invalid - user doesn't register
        self.assertFalse(self.store.add_manager(self.owner, guest, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        manager = User()
        manager.register("probably eden", "password")
        guest.register("Just Guest", "Password")

        # Invalid - Owner/manager isn't manager/owner
        self.assertFalse(self.store.add_manager(guest, manager, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        # Invalid - Already Manager
        self.assertFalse(self.store.add_manager(self.owner, user, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 2)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())

        # All Valid - Appoint by manager
        self.assertTrue(self.store.add_manager(user, manager, [ManagerPermission.APPOINT_MANAGER]))

        # Invalid - Circular appointments
        self.assertFalse(self.store.add_manager(manager, user, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 3)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())
        self.assertTrue(manager in self.store.get_managers())

        self.store.edit_manager_permissions(user, manager.get_nickname(), [ManagerPermission.USERS_QUESTIONS])

        # Invalid - Manager doesn't have permissions
        self.assertFalse(self.store.add_manager(manager, guest, [ManagerPermission.WATCH_PURCHASE_HISTORY]))
        self.assertEqual(len(self.store.get_managers()), 3)
        self.assertTrue(user in self.store.get_managers())
        self.assertTrue(self.manager in self.store.get_managers())
        self.assertTrue(manager in self.store.get_managers())

    # @logger
    def test_is_manger(self):
        user = User()
        user.register("eden", "password")

        # All Valid
        self.store.add_manager(self.owner, user, [ManagerPermission.USERS_QUESTIONS])
        self.assertTrue(self.store.is_manager("eden"))

        # Invalid - Not an existing user
        self.assertFalse(self.store.is_manager("not eden"))

        user2 = User()
        user2.register("Maybe Eden", "Definitely password")

        # Invalid - Existing user, not an owner
        self.assertFalse(self.store.is_manager("Maybe Eden"))

        # Invalid - Existing manager
        self.assertFalse(self.store.is_manager(self.owner.get_nickname()))

    # @logger
    def test_has_permission(self):
        user = User()
        user.register("eden", "password")
        self.store.add_manager(self.owner, user, [ManagerPermission.USERS_QUESTIONS, ManagerPermission.EDIT_MANAGER_PER])

        # All Valid - one permission.
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_INV))

        # All Valid - two permission.
        self.assertTrue(self.store.has_permission(user.get_nickname(), ManagerPermission.USERS_QUESTIONS))

        user2 = User()
        user2.register("Not a manager", "Password")

        # Invalid - not a manager
        self.assertFalse(self.store.has_permission(user2.get_nickname(), ManagerPermission.USERS_QUESTIONS))

        # Invalid - manager without the correct permission
        self.assertFalse(self.store.has_permission(user.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - Owner
        # self.assertFalse(self.store.has_permission(self.owner.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - User doesn't exist
        self.assertFalse(self.store.has_permission("user.get_nickname()", ManagerPermission.EDIT_POLICIES))

    # @logger
    def test_edit_product(self):
        product1_args = ("Chair", 100, "Furniture")
        product1: Product = Product(*product1_args)
        self.store.add_product("Eytan", *product1_args, 10, 0)

        # OP name

        # All valid - owner
        self.assertTrue(self.store.edit_product(self.owner.get_nickname(), product1.get_name(), "name", "Eytan"))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 0)
        product1.set_name("Eytan")
        self.assertEqual(len(self.store.get_products_by(1, "Eytan")), 1)
        self.assertTrue(product1 in self.store.get_products_by(1, "Eytan"))

        # All valid - manager
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "name", "Chair"))
        self.assertEqual(len(self.store.get_products_by(1, "Eytan")), 0)
        product1.set_name("Chair")
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertTrue(product1 in self.store.get_products_by(1, "Chair"))

        # Invalid - product doesn't exist
        self.assertFalse(self.store.edit_product(self.manager.get_nickname(), "product1.get_name()", "name", "Chair2"))
        self.assertEqual(len(self.store.get_products_by(1, "product1.get_name()")), 0)

        # Invalid - Manager/owner doesn't exist
        self.assertFalse(self.store.edit_product("self.manager.get_nickname()", "Chair", "name", "Eytan"))
        self.assertEqual(len(self.store.get_products_by(1, "Eytan")), 0)

        manager = User()
        manager.register("probably eden", "password")
        self.store.add_manager(self.owner, manager, [ManagerPermission.EDIT_POLICIES])

        # Invalid - Manager without permissions
        self.assertFalse(self.store.edit_product(manager, "Chair", "name", "Eytan"))
        self.assertEqual(len(self.store.get_products_by(1, "Eytan")), 0)

        # OP price

        # All valid - owner
        self.assertTrue(self.store.edit_product(self.owner.get_nickname(), product1.get_name(), "price", 20))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        product1.set_price(20)
        self.assertTrue(product1 in self.store.get_products_by(1, "Chair"))

        # All valid - manager
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "price", 2))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        product1.set_price(2)
        self.assertTrue(product1 in self.store.get_products_by(1, "Chair"))

        # All valid - float
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "price", 2.12))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        product1.set_price(2.12)
        self.assertTrue(product1 in self.store.get_products_by(1, "Chair"))

        # All valid - edge case - 0
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "price", 0))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        product1.set_price(0)
        self.assertTrue(product1 in self.store.get_products_by(1, "Chair"))

        # Invalid - product doesn't exist
        self.assertFalse(self.store.edit_product(self.manager.get_nickname(), "product1.get_name()", "price", 20))
        self.assertEqual(len(self.store.get_products_by(1, "product1.get_name()")), 0)
        for product in self.store.get_products_by(2, ""):
            self.assertFalse(product.get_price() == 20)

        # Invalid - Manager/owner doesn't exist
        self.assertFalse(self.store.edit_product("self.manager.get_nickname()", "Chair", "price", 15))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_products_by(1, "Chair")[0].get_price(), 15)

        manager = User()
        manager.register("probably eden", "password")
        self.store.add_manager(self.owner, manager, [ManagerPermission.EDIT_POLICIES])

        # Invalid - Manager without permissions
        self.assertFalse(self.store.edit_product(manager, "Chair", "price", 13))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_products_by(1, "Chair")[0].get_price(), 13)

        # Invalid - negative price
        self.assertFalse(self.store.edit_product(manager, "Chair", "price", -13))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_products_by(1, "Chair")[0].get_price(), -13)

        # OP amount

        # All valid - owner
        self.assertTrue(self.store.edit_product(self.owner.get_nickname(), product1.get_name(), "amount", 20))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 20)

        # All valid - manager
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "amount", 2))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 2)

        # All valid - edge case - 0
        self.assertTrue(self.store.edit_product(self.manager.get_nickname(), product1.get_name(), "amount", 0))
        self.assertEqual(self.store.get_inventory().get_amount("Chair"), 0)

        # Invalid - product doesn't exist
        self.assertFalse(self.store.edit_product(self.manager.get_nickname(), "product1.get_name()", "amount", 20))
        self.assertEqual(len(self.store.get_products_by(1, "product1.get_name()")), 0)
        for product in self.store.get_products_by(2, ""):
            self.assertFalse(self.store.get_inventory().get_amount(product.get_name()) == 20)

        # Invalid - Manager/owner doesn't exist
        self.assertFalse(self.store.edit_product("self.manager.get_nickname()", "Chair", "amount", 15))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_inventory().get_amount("Chair"), 15)

        manager = User()
        manager.register("probably eden", "password")
        self.store.add_manager(self.owner, manager, [ManagerPermission.EDIT_POLICIES])

        # Invalid - Manager without permissions
        self.assertFalse(self.store.edit_product(manager, "Chair", "amount", 13))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_inventory().get_amount("Chair"), 13)

        # Invalid - negative price
        self.assertFalse(self.store.edit_product(manager, "Chair", "amount", -13))
        self.assertEqual(len(self.store.get_products_by(1, "Chair")), 1)
        self.assertFalse(self.store.get_inventory().get_amount("Chair"), -13)

    # @logger
    def test_edit_manager_permissions(self):
        manager1 = User()
        manager1.register("probably eden", "password")
        self.store.add_manager(self.owner, manager1,
                               [ManagerPermission.EDIT_MANAGER_PER, ManagerPermission.APPOINT_MANAGER])

        manager2 = User()
        manager2.register("almost definitely eden", "password")
        self.store.add_manager(manager1, manager2, [ManagerPermission.EDIT_POLICIES])

        # All valid - owner
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_INV))

        # All valid - manager
        self.assertTrue(self.store.edit_manager_permissions(manager1, manager2.get_nickname(),
                                                            [ManagerPermission.EDIT_INV]))
        self.assertTrue(self.store.has_permission(manager2.get_nickname(), ManagerPermission.EDIT_INV))
        self.assertFalse(self.store.has_permission(manager2.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - owner, two permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.WATCH_PURCHASE_HISTORY,
                                                             ManagerPermission.DEL_OWNER]))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - owner, two permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                                            [ManagerPermission.WATCH_PURCHASE_HISTORY,
                                                             ManagerPermission.DEL_OWNER]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # All valid - empty permissions
        self.assertTrue(self.store.edit_manager_permissions(self.owner, manager1.get_nickname(), []))
        for i in range(1, 11):
            self.assertFalse(self.store.has_permission(manager1.get_nickname(), ManagerPermission(i)))

        user = User()
        user.register("not an owner", "not a password")

        # Invalid - not an owner
        self.assertFalse(self.store.edit_manager_permissions(user, self.manager.get_nickname(),
                                                            [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not a manager
        self.assertFalse(self.store.edit_manager_permissions(self.owner, user,
                                                             [ManagerPermission.EDIT_POLICIES]))
        for appointment in self.store.get_store_manager_appointments():
            self.assertFalse(appointment.get_appointee().get_nickname() == user.get_nickname())

        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not the owner which appoint the manager
        self.assertFalse(self.store.edit_manager_permissions(user, self.manager.get_nickname(),
                                                             [ManagerPermission.EDIT_POLICIES]))
        self.assertTrue(
            self.store.has_permission(self.manager.get_nickname(), ManagerPermission.WATCH_PURCHASE_HISTORY))
        self.assertTrue(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.DEL_OWNER))
        self.assertFalse(self.store.has_permission(self.manager.get_nickname(), ManagerPermission.EDIT_POLICIES))

        # Invalid - try change permissions to an owner
        self.assertFalse(self.store.edit_manager_permissions(self.owner, user,
                                                             [ManagerPermission.EDIT_POLICIES]))
        for appointment in self.store.get_store_manager_appointments():
            self.assertFalse(appointment.get_appointee().get_nickname() == user.get_nickname())

    # @logger
    def test_remove_manager(self):
        # def remove_manager(self, appointer_nickname: str, appointee_nickname: str) -> bool:
        manager1 = User()
        manager1.register("probably eden", "password")
        self.store.add_manager(self.owner, manager1,
                               [ManagerPermission.DEL_MANAGER, ManagerPermission.APPOINT_MANAGER])

        manager2 = User()
        manager2.register("almost definitely eden", "password")
        self.store.add_manager(manager1, manager2, [ManagerPermission.EDIT_POLICIES])

        # Invalid - not the right permissions
        self.assertFalse(self.store.remove_manager(manager2.get_nickname(), self.manager.get_nickname()))
        self.assertTrue(self.manager in self.store.get_managers())

        # All valid - manager as appointer
        self.assertTrue(self.store.remove_manager(manager1.get_nickname(), manager2.get_nickname()))
        self.assertFalse(manager2 in self.store.get_managers())

        # All valid - owner as appointer
        self.assertTrue(self.store.remove_manager(self.owner.get_nickname(), manager1.get_nickname()))
        self.assertFalse(manager1 in self.store.get_managers())

        managers = self.store.get_managers()

        # Invalid - not an existing manager
        self.assertFalse(self.store.remove_manager(self.owner.get_nickname(), manager1.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())

        # Invalid - not an existing appointer
        self.assertFalse(self.store.remove_manager(manager2.get_nickname(), self.manager.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())

        user = User()
        user.register("not an owner", "not a password")
        self.store.add_owner(self.owner.get_nickname(), user)

        # Invalid - not the owner that appoint the manager
        self.assertFalse(self.store.remove_manager(user.get_nickname(), self.manager.get_nickname()))
        self.assertEqual(len(managers), len(self.store.get_managers()))
        for m in managers:
            self.assertTrue(m in self.store.get_managers())

    # @logger
    def test_get_purchases(self):
        self.store.edit_manager_permissions(self.owner, self.manager.get_nickname(),
                                            [ManagerPermission.WATCH_PURCHASE_HISTORY])
        purchase: Purchase = Purchase([{"product_name": "Chair", "product_price": 100, "amount": 5},
                                          {"product_name": "Sofa", "product_price": 1, "amount": 1}], 501,
                                         self.store.get_name(), self.owner.get_nickname())
        self.store.add_purchase(purchase)

        # All valid - owner
        self.assertListEqual(self.store.get_purchases(self.owner.get_nickname()), [purchase])

        # All valid - manager
        self.assertListEqual(self.store.get_purchases(self.manager.get_nickname()), [purchase])

        user = User()
        user.register("just a user", "but a special password")

        # Invalid - not an owner/manager
        self.assertListEqual(self.store.get_purchases(user.get_nickname()), [])

        self.store.add_manager(self.owner, user, [ManagerPermission.DEL_MANAGER])

        # Invalid - not the right permissions
        self.assertListEqual(self.store.get_purchases(user.get_nickname()), [])

    # @logger
    def test_is_in_store_inventory(self):
        self.store.add_product("Eytan", "Eytan's Product", 100, "Eytan Category", 5, 0)
        self.store.add_product("Eytan", "not Eytan's Product", 10, "Eytan Category", 2, 0)

        # All valid one product
        amount_per_product = [["Eytan's Product", 4]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertTrue(result)

        # All valid two products
        amount_per_product = [["Eytan's Product", 4], ["not Eytan's Product", 1]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertTrue(result)

        # Exactly the same as in stock
        amount_per_product = [["Eytan's Product", 5], ["not Eytan's Product", 2]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertTrue(result)

        # One product not enough in stock
        amount_per_product = [["Eytan's Product", 6], ["not Eytan's Product", 1]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertFalse(result)

        # Two product not enough in stock
        amount_per_product = [["Eytan's Product", 6], ["not Eytan's Product", 10]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertFalse(result)

        # One product doesn't exist
        amount_per_product = [["Eytan's social life", 5], ["not Eytan's Product", 1]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertFalse(result)

        # Two things that doesn't exist
        amount_per_product = [["Eytan's social life", 1], ["Liverpool's primer league title", 1]]
        result = self.store.is_in_store_inventory(amount_per_product)
        self.assertFalse(result)

    def test_purchase_policy_exists(self):
        self.store.define_purchase_policy({"name": "policy1", "products": ["product1"], "min_amount": 8})
        # policy exists
        res = self.store.purchase_policy_exists({"name": "policy1", "products": ["product1"], "min_amount": 8})
        self.assertTrue(res)

        # policy doesn't exist
        res = self.store.purchase_policy_exists({"name": "policy2", "products": ["product1", "product2"], "min_amount": 8})
        self.assertFalse(res)

        res = self.store.purchase_policy_exists({"products": ["product1", "product2"], "min_amount": 8})
        self.assertFalse(res)

        res = self.store.purchase_policy_exists({"name": "policy2", "products": ["product1"], "min_amount": 10})
        self.assertFalse(res)

    def test_add_purchase_policy(self):
        # valid details
        res = self.store.define_purchase_policy({"name": "policy1",
                                                 "products": ["product1"], "min_amount": 8})["response"]
        self.assertTrue(res)

        # invalid details
        res = self.store.define_purchase_policy({"name": "policy2",
                                                 "products": ["product1"]})["response"]
        self.assertFalse(res)

        res = self.store.define_purchase_policy({"products": ["product1"], "min_amount": 8})["response"]
        self.assertFalse(res)

    def test_update_purchase_policy(self):
        self.store.define_purchase_policy({"name": "policy1",
                                           "products": ["product1"], "min_amount": 8})
        # valid update
        res = self.store.update_purchase_policy({"name": "policy1",
                                           "products": ["product1"], "min_amount": 4})["response"]
        self.assertTrue(res)

        # invalid update
        res = self.store.update_purchase_policy({"name": "policy2",
                                                 "products": ["product1"], "min_amount": 4})["response"]
        self.assertFalse(res)

    def test_get_purchase_policies(self):
        # no policies exist
        res = self.store.get_purchase_policies()
        self.assertTrue(len(res) == 0)

        # policies exist
        self.store.define_purchase_policy({"name": "policy1",
                                           "products": ["product1"], "min_amount": 8})
        res = self.store.get_purchase_policies()
        self.assertTrue(len(res) > 0)

    def test_remove_owner(self):
        store: Store = Store("store1")
        store.get_owners_appointments().append(StoreAppointment(None, self.owner, []))
        owner1 = User()
        owner1.register("owner1", "password")
        store.add_owner(self.owner.get_nickname(), owner1)

        owner2 = User()
        owner2.register("owner2", "password")
        store.add_owner("owner1", owner2)

        owner3 = User()
        owner3.register("owner3", "password")
        store.add_owner("owner2", owner3)

        manager1 = User()
        manager1.register("manager1", "password")
        store.add_manager(owner3, manager1, [])

        manager2 = User()
        manager2.register("manager2", "password")
        store.add_manager(self.owner, manager2, [])

        # failed owner2 didn't appoint owner 2 as owner
        res = store.remove_owner("owner2", "owner1")
        self.assertEqual(res['response'], [])
        self.assertEqual(res['msg'], "Error! remove store owner failed.")

        # failed
        res = store.remove_owner("owner", "owner1")
        self.assertEqual(res['response'], [])
        self.assertEqual(res['msg'], "Error! remove store owner failed.")

        # success
        res = store.remove_owner(self.owner.get_nickname(), "owner1")

        self.assertEqual(res['response'], ['owner1 removed as owner', 'owner2 removed as owner', 'owner3 removed as owner', 'manager1 removed as manager'])
        self.assertEqual(res['msg'], "Store owner owner1 and his appointees were removed successfully.")
        self.assertFalse(store.is_owner('owner1'))
        self.assertFalse(store.is_owner('owner2'))
        self.assertFalse(store.is_owner('owner3'))
        self.assertFalse(store.is_manager('manager1'))
        self.assertTrue(store.is_manager('manager2'))

    def test_remove_owner_appointees(self):
        store: Store = Store("store")
        store.get_owners_appointments().append(StoreAppointment(None, self.owner, []))
        owner1 = User()
        owner1.register("owner1", "password")
        store.add_owner(self.owner.get_nickname(), owner1)

        owner2 = User()
        owner2.register("owner2", "password")
        store.add_owner("owner1", owner2)

        owner3 = User()
        owner3.register("owner3", "password")
        store.add_owner("owner2", owner3)

        manager1 = User()
        manager1.register("manager1", "password")
        store.add_manager(owner3, manager1, [])

        manager2 = User()
        manager2.register("manager2", "password")
        store.add_manager(self.owner, manager2, [])

        res = store.remove_owner_appointees("owner1")

        self.assertEqual(res, ['owner2 removed as owner', 'owner3 removed as owner', 'manager1 removed as manager'])
        self.assertTrue(store.is_owner('owner1'))
        self.assertFalse(store.is_owner('owner2'))
        self.assertFalse(store.is_owner('owner3'))
        self.assertFalse(store.is_manager('manager1'))
        self.assertTrue(store.is_manager('manager2'))

    def test_purchase_immediate(self):
        # purchase_immediate(self, product_name: str, product_price: int, amount: int, basket_price: int, prod_lst:[]):
        # ret format{'amount': 2, 'product_name': 'Eytan', 'product_price': 10} != 9
        result = self.store.purchase_immediate("Eytan", 10, 2, 0, ["Eytan"])
        self.assertEqual(9, result['product_price'])

        result = self.store.purchase_immediate("Eytan", 10, 2, 3, ["Eytan"])
        self.assertEqual(10, result['product_price'])

        result = self.store.purchase_immediate("Eytan2", 10, 2, 3, ["Eytan"])
        self.assertEqual(10, result['product_price'])


    # # @logger
    def tearDown(self) -> None:
        self.store.reset_policies()
        self.store = None

    def __repr__(self):
        return repr("StoreTests")
Example #12
0
class UserTests(unittest.TestCase):
    def setUp(self):
        # self.user.logoutState = StubLogout()
        # self.__valid_name = "anna9218"
        # self.__valid_pass = "******"
        # self.__invalid_input = ""
        # self.__product = StubProduct()
        # self.__store = StubStore()
        # self.__product_ls_to_add = [[self.__product, self.__store, 1]]  # products_stores_quantity_ls

        self.__user = User()
        self.__registration_state_mock = Registration()
        self.__login_state_mock = Login()
        self.__shopping_cart_mock = ShoppingCart()
        self.__purchase_history_mock = []
        self.__purchase_mock = Purchase([], 10.0, "store_name", "username")
        self.__shopping_basket_mock = ShoppingBasket()

        # self.__user.__registration = self.__user.set_registration_state(StubRegistration())
        # # self.__user.__loginState = self.__user.set_login_state(StubLogin())
        # self.__user.__shoppingCart = self.__user.set_shopping_cart(StubShoppingCart())

    def test_register(self):
        # self.assertTrue(self.__user.register(self.__valid_name, self.__valid_pass)['response'])
        # self.assertFalse(self.__user.register(self.__valid_name, self.__valid_pass)['response'])
        self.__user.is_registered = MagicMock(return_value=True)
        res = self.__user.register("nickname", "password")
        self.assertFalse(res['response'])

        self.__user.is_registered = MagicMock(return_value=False)
        self.__user.set_registration_state(self.__registration_state_mock)
        res = self.__user.register("nickname", "password")
        self.assertTrue(res['response'])

    def test_login(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.login(self.__valid_name, self.__valid_pass)['response'])
        # self.assertFalse(self.__user.login(self.__invalid_input, self.__invalid_input)['response'])
        self.__user.check_password = MagicMock(return_value=False)
        res = self.__user.login("nickname", "password")
        self.assertFalse(res['response'])

        self.__user.check_password = MagicMock(return_value=True)
        self.__user.is_logged_in = MagicMock(return_value=True)
        res = self.__user.login("nickname", "password")
        self.assertFalse(res['response'])

        self.__user.is_logged_in = MagicMock(return_value=False)
        self.__user.check_nickname = MagicMock(return_value=True)
        self.__login_state_mock.login = MagicMock(return_value=True)
        self.__user.set_login_state(self.__login_state_mock)
        self.__user.get_nickname = MagicMock(return_value="TradeManager")
        self.__user.set_registration_state(self.__registration_state_mock)
        res = self.__user.login("nickname", "password")
        self.assertTrue(res['response'])

        self.__user.get_nickname = MagicMock(return_value="nickname")
        self.__user.set_registration_state(self.__registration_state_mock)
        res = self.__user.login("nickname", "password")
        self.assertTrue(res['response'])

    def test_logout(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.__user.login(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.logout())
        self.__user.is_logged_in = MagicMock(return_value=True)
        self.__user.set_login_state(self.__login_state_mock)
        res = self.__user.logout()
        self.assertTrue(res)

        self.__user.is_logged_in = MagicMock(return_value=False)
        self.__user.set_login_state(self.__login_state_mock)
        res = self.__user.logout()
        self.assertFalse(res)

    def test_check_password(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.check_password(self.__valid_pass))
        # self.assertFalse(self.__user.check_password(self.__invalid_input))

        # hashed value of 'password'
        self.__registration_state_mock.get_password = MagicMock(
            return_value=
            'fcf0a27361d035a079499e86d461e787d8fb328cc3de44df3a96f1d8d00798774cd4375f08353275c2d46a730834e75f3003cf98555b7f19b267b8aaaa5c5b3ae052890976839ca40cc00d16a5c5515093ade62e6d46a550c4cce095c65bb789'
        )
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertTrue(self.__user.check_password("password"))
        self.assertFalse(self.__user.check_password("wrong password"))

    def test_check_nickname(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.check_nickname(self.__valid_name))
        # self.assertFalse(self.__user.check_nickname(self.__invalid_input))
        self.__registration_state_mock.get_nickname = MagicMock(
            return_value="nickname")
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertTrue(self.__user.check_nickname("nickname"))
        self.assertFalse(self.__user.check_nickname("wrong nickname"))

    def test_is_logged_in(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertFalse(self.__user.is_logged_in())
        # self.__user.login(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.is_logged_in())
        self.__login_state_mock.is_logged_in = MagicMock(return_value=True)
        self.__user.set_login_state(self.__login_state_mock)
        self.assertTrue(self.__user.is_logged_in())

        self.__login_state_mock.is_logged_in = MagicMock(return_value=False)
        self.__user.set_login_state(self.__login_state_mock)
        self.assertFalse(self.__user.is_logged_in())

    def test_is_logged_out(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.is_logged_out())
        # self.__user.login(self.__valid_name, self.__valid_pass)
        # self.assertFalse(self.__user.is_logged_out())
        self.__login_state_mock.is_logged_in = MagicMock(return_value=False)
        self.__user.set_login_state(self.__login_state_mock)
        self.assertTrue(self.__user.is_logged_out())

        self.__login_state_mock.is_logged_in = MagicMock(return_value=True)
        self.__user.set_login_state(self.__login_state_mock)
        self.assertFalse(self.__user.is_logged_out())

    def test_is_registered(self):
        # self.assertFalse(self.__user.is_registered())
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.is_registered())
        self.__registration_state_mock.is_registered = MagicMock(
            return_value=True)
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertTrue(self.__user.is_registered())

        self.__registration_state_mock.is_registered = MagicMock(
            return_value=False)
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertFalse(self.__user.is_registered())

    def test_get_nickname(self):
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertEqual(self.__user.get_nickname(), self.__valid_name, "")
        # self.assertNotEqual(self.__user.get_nickname(), self.__invalid_input, "")
        self.__registration_state_mock.get_nickname = MagicMock(
            return_value="nickname")
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertEqual(self.__user.get_nickname(), "nickname")
        self.assertNotEqual(self.__user.get_nickname(), "wrong nickname")

    def test_save_products_to_basket(self):
        # # test for guest
        # self.assertTrue(self.__user.save_products_to_basket(self.__product_ls_to_add))
        # # test for subscriber
        # self.__user.register(self.__valid_name, self.__valid_pass)
        # self.assertTrue(self.__user.save_products_to_basket(self.__product_ls_to_add))
        self.__shopping_cart_mock.add_products = MagicMock(
            return_value={
                'response': True,
                'msg': "Products were added to shopping cart successfully"
            })

        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        res = self.__user.save_products_to_basket([])
        self.assertTrue(res['response'])

        self.__shopping_cart_mock.add_products = MagicMock(
            return_value={
                'response': False,
                'msg': "Error! invalid input"
            })

        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        res = self.__user.save_products_to_basket([])
        self.assertFalse(res['response'])

    def test_view_shopping_cart(self):
        self.__shopping_cart_mock.view_shopping_cart = MagicMock(
            return_value={
                'response': [],
                'msg': "Shopping cart was retrieved successfully"
            })

        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        res = self.__user.view_shopping_cart()
        self.assertEqual(res['msg'],
                         "Shopping cart was retrieved successfully")

    def test_remove_from_shopping_cart(self):
        self.__shopping_cart_mock.remove_from_shopping_cart = MagicMock(
            return_value={
                'response': True,
                'msg':
                "Products were removed from your shopping cart successfully"
            })

        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        res = self.__user.remove_from_shopping_cart([])
        self.assertTrue(res['response'])

    def test_update_quantity_in_shopping_cart(self):
        self.__shopping_cart_mock.update_quantity = MagicMock(
            return_value={
                'response': True,
                'msg': "Shopping cart was updated successfully."
            })

        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        res = self.__user.update_quantity_in_shopping_cart([])
        self.assertTrue(res['response'])

    def test_complete_purchase(self):
        self.__shopping_cart_mock.get_store_basket = MagicMock(
            return_value=self.__shopping_basket_mock)
        self.__user.set_shopping_cart(self.__shopping_cart_mock)
        self.__purchase_mock.get_store_name = MagicMock(
            return_value="store_name")
        self.__shopping_basket_mock.complete_purchase = MagicMock(
            return_value=True)
        res = self.__user.complete_purchase(self.__purchase_mock)
        self.assertTrue(res)

    # def test_remove_purchase(self):
    #     res = self.__user.remove_purchase(self.__purchase_mock)
    #     self.assertTrue(res)

    def test_get_password(self):
        self.__registration_state_mock.get_password = MagicMock(
            return_value="password")
        self.__user.set_registration_state(self.__registration_state_mock)
        self.assertEqual(self.__user.get_password(), "password")
        self.assertNotEqual(self.__user.get_password(), "wrong password")

    def tearDown(self):
        # maybe delete the registered user resulted from this test
        pass

    def __repr__(self):
        return repr("UserTests")

    if __name__ == '__main__':
        unittest.main()