def test_insufficient_funds_doesnt_add_purchase(self,
                                                    machine: VendingMachine):
        """
        Test case should ensure that if the user didn't have funds to complete
        the purchase, a purchase isn't added to the log
        """

        machine.purchase_item("A1")
        assert len(machine.purchases) == 0
    def test_incorrect_position_doesnt_add_purchase(
            self, loaded_machine: VendingMachine):
        """
        Test case to ensure that if the position is invalid, a purchase
        doesn't get added to the purchase log.
        """

        loaded_machine.purchase_item("ABC123")
        assert len(loaded_machine.purchases) == 0
    def test_purchased_stock_decrements(self, loaded_machine: VendingMachine):
        """
        Mostly already captured by tests on the item, but ensuring
        that the item purchased decrements its stock
        """
        previous_stock = loaded_machine.items["A1"].remaining_stock
        loaded_machine.purchase_item("A1")
        current_stock = loaded_machine.items["A1"].remaining_stock

        assert current_stock == (previous_stock - 1)
    def test_successful_purchase_gets_logged_as_success(
            self, loaded_machine: VendingMachine, caplog):
        """
        Test case should ensure that if everything goes well, the user sees a success message
        """

        loaded_machine.purchase_item("A1")
        self.logs_one_message(caplog)
        assert "SUCCESS" in caplog.text
        assert "Purchased" in caplog.text
        assert "Enjoy!" in caplog.text
    def test_out_of_stock_doesnt_add_purchase(self,
                                              loaded_machine: VendingMachine):
        """
        Test case to ensure that if there isn't any stock left of an item, a purchase
        doesn't get added to the purchase log.
        """

        loaded_machine.items["A1"].remaining_stock = 0

        loaded_machine.purchase_item("A1")

        assert len(loaded_machine.purchases) == 0
    def test_successful_purchase_gets_added_to_purchase_log(
            self, loaded_machine: VendingMachine):
        """
        Ensures the purchase gets appended to the log
        """
        position = "A1"
        price = loaded_machine.items[position].price
        loaded_machine.purchase_item(position)
        assert len(loaded_machine.purchases) == 1
        purchase = loaded_machine.purchases[0]

        assert purchase.position == position
        assert purchase.price == price
    def test_purchased_decreases_balance(self, loaded_machine: VendingMachine):
        """
        Test case ensures that the balance on the machine gets correctly
        updated according to the price of the item purchased
        """

        current_balance = loaded_machine.balance
        price_of_item = loaded_machine.items["A1"].price
        expected_balance = current_balance - price_of_item

        loaded_machine.purchase_item("A1")

        assert loaded_machine.balance == expected_balance
    def test_insufficient_funds_gets_logged_as_error(self,
                                                     machine: VendingMachine,
                                                     caplog):
        """
        Test case should ensure that if the user hasn't loaded enough money
        into the machine that the attempt to purchase an item will
        fail.
        """

        machine.purchase_item("A1")
        self.logs_one_message(caplog)
        assert "ERROR" in caplog.text
        assert "Insufficient funds" in caplog.text
    def test_incorrect_position_gets_logged_as_error(
            self, loaded_machine: VendingMachine, caplog):
        """
        Test case should ensure that entering a position on the machine that doesn't
        exist should log an error back to the console.
        For example, A1 should exist, while ABC123 shouldn't
        """

        loaded_machine.purchase_item("ABC123")
        self.logs_one_message(caplog)
        assert "ERROR" in caplog.text
        assert "no item located" in caplog.text
        assert "Please try again!" in caplog.text
    def test_view_purchases_log(self, loaded_machine: VendingMachine, caplog):
        """
        Test case ensures that the correct number of messages get logged.
        """

        loaded_machine.purchase_item("A1")
        loaded_machine.purchase_item("A1")

        # Clearing messages emitted by purchasing the item
        caplog.clear()

        loaded_machine.view_purchases()
        assert len(caplog.records) == 3
        assert "You bought" in caplog.text
    def test_out_of_stock_gets_logged_as_error(self,
                                               loaded_machine: VendingMachine,
                                               caplog):
        """
        Test case should ensure error messages from out of stock are getting logged
        to the user correctly.
        """

        loaded_machine.items["A1"].remaining_stock = 0

        loaded_machine.purchase_item("A1")

        self.logs_one_message(caplog)
        assert "ERROR" in caplog.text
        assert "Out of stock!" in caplog.text