Build a Cash Register Project - Build a Cash Register

Tell us what’s happening:

Hi, I encountered an issue while running the last three tests automatically.

When I modify the code and input to match the test’s precondition, the result aligns with expectations.

However, after the update, rerunning the test causes some previously failed tests to pass, while previously passed tests now fail. I’m struggling to identify the issue in my code and would appreciate your help. Thank you!

  1. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be Status: INSUFFICIENT_FUNDS

  2. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be Status: INSUFFICIENT_FUNDS

  3. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]], and the #purchase-btn element is clicked, the value in the #change-due element should be Status: CLOSED PENNY: $0.5

Your code so far

WARNING

The challenge seed code and/or your solution exceeded the maximum length we can port over from the challenge.

You will need to take an additional step here so the code you wrote presents in an easy to read format.

Please copy/paste all the editor code showing in the challenge from where you just linked.

let price = 1.87;
let cid = [
  ["PENNY", 1.01],
  ["NICKEL", 2.05],
  ["DIME", 3.1],
  ["QUARTER", 4.25],
  ["ONE", 90],
  ["FIVE", 55],
  ["TEN", 20],
  ["TWENTY", 60],
  ["ONE HUNDRED", 100]
];

// Calculate the total funds in the cash drawer.
let funds = cid.reduce((a, b) => a + b[1], 0);

// Store the amount of each currency unit. 
const unitAmount = [
  ["PENNY", 0.01],
  ["NICKEL", 0.05],
  ["DIME", 0.1],
  ["QUARTER", 0.25],
  ["ONE", 1],
  ["FIVE", 5],
  ["TEN", 10],
  ["TWENTY", 20],
  ["ONE HUNDRED", 100]
]

const priceValue = document.getElementById("price-value");
const cashInput = document.getElementById("cash");
const purchaseBtn = document.getElementById("purchase-btn");
const changeDue = document.getElementById("change-due");
const cashDrawer = document.getElementById("cash-drawer"); 

// A function to set price on the UI.
const setPrice = (price) => {
  priceValue.textContent = price;
}

// A function to set cash drawer on the UI.
const setCashDrawer = (cid) => {
  cashDrawer.innerHTML = ``;
  for (const cash of cid) {
    cashDrawer.innerHTML += `
      <div class="cid" value="${cash[1]}">
        <div class="currency-unit">${cash[0]}: $<span class="amount">${cash[1]}</span></div>
      </div>
    `;
  }
}

// A function to update #change-due on the UI.
const updateChangeDue = (expectedChange) => {
    if (expectedChange >= 0) {
      if (expectedChange === 0) {
        changeDue.textContent = "No change due - customer paid with exact cash";

      } else if (funds < expectedChange) {
        changeDue.textContent = "Status: INSUFFICIENT_FUNDS";

      } else {
        const changeArr = calculate(expectedChange);
        // The value of #change-due will begin with different Status according to the funds.
        let msg = funds === 0? `Status: CLOSED\n` : `Status: OPEN\n`;
        for (const change of changeArr) {
          msg += `${change[0]}: $${change[1]}\n`;
        }
        changeDue.textContent = msg;
        setCashDrawer(cid);
      }

    } else {
      alert("Customer does not have enough money to purchase the item"); 
    }
    // Everytime after updating #change-due, clear the input.
    clearCashInput();
  }


  // A function to calculate the exact change.
  const calculate = (expectedChange) => {
    // Track the change remained to make.
    let remainChange = expectedChange;

    // Store all the changes that have been made.
    let changeArr = [];

    for (let i = cid.length - 1; i >= 0; i --) {
    
      if (remainChange === 0) {
        break;
      }

      // The count of a specific currency unit is the minimum of the required count and the count available in the cash drawer.
      let cashCount = Math.min(Math.floor(remainChange / unitAmount[i][1]), Math.floor(cid[i][1] / unitAmount[i][1]));

      if (cashCount > 0) {
        let changeValue = cashCount * unitAmount[i][1];
        
        // To avoid problems caused by floating-point precision.
        remainChange = Number((remainChange - changeValue).toFixed(2));
        funds = Number((funds - changeValue).toFixed(2));
        cid[i][1] = Number((cid[i][1] - changeValue).toFixed(2));

        changeArr.push([unitAmount[i][0], changeValue]);
      }
    }

    return changeArr;
  }

// A function to clear the input. 
const clearCashInput = () => {
  cashInput.value = "";
}

setPrice(price);
setCashDrawer(cid);

purchaseBtn.addEventListener("click", () => {
  updateChangeDue(cashInput.value - price);
})

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./styles.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
  <title>Cash Register App</title>
</head>
<body>
    <h1 id="title">Cash Register
        <span class="material-symbols-outlined" id="icon">calculate</span>
    </h1>
    <main>
        <section id="price-and-cash">
            <div>Price: <span id="price-value"></span></div>
            <label for="cash">Cash: </label>
            <input id="cash">
            <button id="purchase-btn">Purchase</button>
            <div id="change-due"></div>
        </section>
        <section id="cash-drawer"></section>
    </main>
<script src="./script.js"></script>
</body>
</html>

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36

Challenge Information:

Build a Cash Register Project - Build a Cash Register

Hello, your code does the same thing in my editor failing the last three and passing all the rest. if you mean that one challage causing others to fail it might be a test issue.

Remember that tests are run one after another. If there are some actions that are done on the input values, they need to happen every time.

So, it seems we can only wait for someone to fix the tests.

Thank you for your reply! I can get the expected results by setting the cid, price, and cash values as per the test requirements and clicking the button. However, it doesn’t pass the tests automatically. Guess it might be due to internal errors within the tests.


I ran the automatic test using the sample webpage code, and it passed all tests except the last one. I believe it’s an issue with the tests. Does anyone know how to contact the developer to address and fix this issue? :thinking:

Your problem is not caused by test issue.

When code is changed manually to check test case, the preview page is rendered again. This basically means that every line will be executed again. Take a look at the updateChangeDue function, on what variables outside of the function scope it depends on?

1 Like

Thank you for your hint!

I found an issue with “funds”. I will try to fix it and see what will happen. :smiley:

Well, I found other issues in the calculate function and updated the code, then I passed all the tests! Thank you sooooooo much for the hint again!

2 Likes

I overlooked the scenario where the value of funds is greater than expectedChange, and there are no suitable currency units in the cash drawer.

And here is part of my code updated.

        if (remainChange || !changeArr) {
            changeDue.textContent = "Status: INSUFFICIENT_FUNDS";
        } else {
            let msg = funds === 0? `Status: CLOSED\n` : `Status: OPEN\n`;
        
            for (const change of changeArr) {
                msg += `${change[0]}: $${change[1]}\n`;
            }
            
            changeDue.textContent = msg;
        }