Build a Cash Register - test do not work

Hi everyone, I see that I get correct results, but I don’t pass the tests:

let price = 3.26;
let cid = [
  ['PENNY', 1.01, 0.01],
  ['NICKEL', 2.05, 0.05],
  ['DIME', 3.1, 0.1],
  ['QUARTER', 4.25, 0.25],
  ['ONE', 90, 1],
  ['FIVE', 55, 5],
  ['TEN', 20, 10],
  ['TWENTY', 60, 20],
  ['ONE HUNDRED', 100, 100]
];
let priceInfo = document.getElementById('price');
priceInfo.textContent = price;
const purchaseBtn = document.getElementById('purchase-btn');
let changeDue = document.getElementById('change-due');

const purchase = () => {
  let returnArr = [];
  const cash = parseFloat(document.getElementById('cash').value);
  let changeDueAmount = Math.round((cash - price) * 100) / 100;
  // calc total amount of change
  let changeResidue = cid.reduce((sum, num) => sum + num[1], 0);

  if (!cash) {
    alert('Please enter a valid amount');
  } else if (cash < price) {
    alert('Customer does not have enough money to purchase the item');
  } else if (cash === price) {
    changeDue.textContent = 'No change due - customer paid with exact cash';
  } else {
    let changeDueValue = 0;
    let cidLength = cid.length;
    for (let i = 1; i <= cidLength; i++) {
      let denomination = cid[cidLength - i][2];
      let availAmount = cid[cidLength - i][1];
      let amountToReturn = 0;
      // we can give change with this banknote, and we have money for this banknote
      while(availAmount !== 0 && changeDueAmount >= denomination) {
        changeDueAmount -= denomination;
        changeDueAmount = Math.round((changeDueAmount) * 100) / 100;
        availAmount -= denomination;
        availAmount = Math.round((availAmount) * 100) / 100;
        amountToReturn += denomination;
        amountToReturn = Math.round((amountToReturn) * 100) / 100;
      }
      if (amountToReturn !== 0) {
        returnArr.unshift([cid[cidLength - i][0], amountToReturn]);
      }
    }
    if (changeDueAmount > 0) {
      changeDue.textContent = 'Status: INSUFFICIENT_FUNDS';
    }
    else {
      const changeResidueLeft = changeResidue - returnArr.reduce((sum, num) => sum + num[1], 0);
      changeDue.innerHTML = changeResidueLeft === 0 ? '<p>Status: CLOSED</p>' : '<p>Status: OPEN</p>';
    
      for (let i = returnArr.length - 1; i >= 0; i-- ) {
        changeDue.innerHTML += `<p>${returnArr[i][0]}: $${returnArr[i][1]}</p>`;
      }
    }
  }    
}

purchaseBtn.addEventListener('click', purchase);

The following tests fail:

// running tests
11. When price is 19.5, the value in the #cash element is 20, cid is [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]], and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN QUARTER: $0.5".
12. When price is 3.26, the value in the #cash element is 100, cid is [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]], and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04".
13. When price is less than the value in the #cash element, total cash in drawer cid is greater than the change due, individual denomination amounts allows for returning change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: OPEN" with required change due in coins and bills sorted in highest to lowest order.
18. 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".
19. When price is less than the value in the #cash element, total cash in drawer cid is equal to change due, and the #purchase-btn element is clicked, the value in the #change-due element should be "Status: CLOSED" with change due in coins and bills sorted in highest to lowest order.
// tests completed

Hi there! Don’t use any variable in global scope, except that above two.

Is this doing what you expect?

Actually, wouldn’t the fact that you’ve added unit values in the cid array present a problem for the fCC tests?

not a problem for the tests, but when the tests change the value of cid the unit value will disappear, meaning the approach can’t work

Thanks for the clarification. Makes sense.

Thanks everyone, there were some mistakes, the major was of course the arrays structure.

This works:

let price = 19.5;
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]
];

let priceInfo = document.getElementById('price');
const purchaseBtn = document.getElementById('purchase-btn');
let changeDue = document.getElementById('change-due');
priceInfo.textContent = price;

const purchase = () => {
  let denomArr = [
    ['PENNY', 0.01],
    ['NICKEL', 0.05],
    ['DIME', 0.1],
    ['QUARTER', 0.25],
    ['ONE', 1],
    ['FIVE', 5],
    ['TEN', 10],
    ['TWENTY', 20],
    ['ONE HUNDRED', 100]
  ];
  const cash = parseFloat(document.getElementById('cash').value);
  function getDenomination(note) {
    const result = denomArr.find(denom => denom[0] === note[0]);
    return result ? result[1] : null; // Return the denomination or null if not found
  }

  let returnArr = [];
  let changeDueAmount = Math.round((cash - price) * 100) / 100;
  // calc total amount of change
  let changeResidue = cid.reduce((sum, num) => sum + num[1], 0);
  if (!cash) {
    alert('Please enter a valid amount');
  } else if (cash < price) {
    alert('Customer does not have enough money to purchase the item');
  } else if (changeResidue < changeDueAmount) {
    changeDue.textContent = 'Status: INSUFFICIENT_FUNDS';
    return;
  }

  else if (cash === price) {
    changeDue.textContent = 'No change due - customer paid with exact cash';
  } else {
    let changeDueValue = 0;
    let cidLength = cid.length;
    for (let i =cidLength -1; i >= 0; i--) {
      let denomination = getDenomination(cid[i]);
      let availAmount = cid[i][1];
      let amountToReturn = 0;
      // we can give change with this banknote, and we have money for this banknote
      while(availAmount !== 0 && changeDueAmount >= denomination) {
        changeDueAmount -= denomination;
        availAmount -= denomination;
        changeDueAmount = Math.round((changeDueAmount) * 100) / 100;
        amountToReturn += denomination;
        amountToReturn = Math.round((amountToReturn) * 100) / 100;
      }
      if (amountToReturn !== 0) {
        returnArr.unshift([cid[i][0], amountToReturn]);
      }
    }
    if (changeDueAmount > 0) {
      changeDue.textContent = 'Status: INSUFFICIENT_FUNDS';
    }
    else {
      const changeResidueLeft = changeResidue - returnArr.reduce((sum, num) => sum + num[1], 0);
      changeDue.innerHTML = changeResidueLeft === 0 ? '<p>Status: CLOSED</p>' : '<p>Status: OPEN</p>';

      for (let i = returnArr.length - 1; i >= 0; i-- ) {
        changeDue.innerHTML += `<p>${returnArr[i][0]}: $${returnArr[i][1]}</p>`;
      }
    }

  }
}

purchaseBtn.addEventListener('click', purchase);