Since the error message is so generic and it’s not telling me what test failed, I did some digging and found the md from GitHub. I took the hints
section and modified the assert to use console.assert
instead of assert.deepEqual
and created a copy of my purchase
function to return an object that would pass the assert
.
I then tied the testing of this to the purchase button. I see this result when mashing purchase:
...
Tests passed
Potential infinite loop detected on line 77. Tests may fail if this is not changed.
Tests passed
...
Now, line 77 is the checkCashRegister()
function. This is a function, not a loop. As far as loops, I believe there are only two. One per purchase()
/checkCashRegister()
function. Since one is a copy of the other, they both use for (let i = cid.length - 1; i >= 0; i--) {
. This shouldn’t result in an infinite loop as i
is being set to the length, checking if it’s not negative, and decrementing. Even if cid.length
was 0, i
would start at -1 and the loop wouldn’t run.
Anyway, I do not get the infinite loop
console message when I do not run the assert tests and mash the purchase so I do not think this is the cause of the tests passing. And running the asserts show that my code is passing on consecutive calls. Also, the asserts are passing with mashing.
I really wish it would tell you what it’s testing that fails. It’s like looking for a needle in a haystack.
This is my code with the asserts:
let price = 19.5;
let cid = [
['PENNY', 0.5],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 0],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
];
const purchase = () => {
const cidValue = [
0.01,
0.05,
0.10,
0.25,
1,
5,
10,
20,
100
];
const changeDue = document.getElementById("change-due");
const cash = parseFloat(document.getElementById("cash").value);
// Prevent infinite loop
if (cid.length <= 0) {
return;
}
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 change = cash - price;
const totalCid = cid.reduce((acc, arr) => (acc + arr[1]), 0).toFixed(2);
let status = "";
if (parseFloat(totalCid) < parseFloat(change)) {
status = "Status: INSUFFICIENT_FUNDS";
} else {
if (parseFloat(totalCid) === parseFloat(change)) {
status = "Status: CLOSED";
} else {
status = "Status: OPEN";
}
for (let i = cid.length - 1; i >= 0; i--) {
let inRegister = cid[i][1];
let billValue = cidValue[i];
if (inRegister > 0 && change >= billValue) {
let amount = 0;
const amountNeeded = Math.floor(change / billValue);
const amountInRegister = Math.floor(inRegister / billValue);
if (amountInRegister >= amountNeeded) {
amount = amountNeeded * billValue;
} else {
amount = amountInRegister * billValue;
}
change = (change - amount).toFixed(2);
status += ` ${cid[i][0]}: $${amount}`;
}
}
if (parseFloat(change) !== 0) {
status = "Status: INSUFFICIENT_FUNDS";
}
}
changeDue.textContent = status;
}
runTests();
};
/* Testing */
const checkCashRegister = (price, cash, cid) => {
const cidValue = [
0.01,
0.05,
0.10,
0.25,
1,
5,
10,
20,
100
];
// Prevent infinite loop
if (cid.length <= 0) {
return;
}
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 change = cash - price;
const totalCid = cid.reduce((acc, arr) => (acc + arr[1]), 0).toFixed(2);
let status = {
status: "",
change: []
};
if (parseFloat(totalCid) < parseFloat(change)) {
// status = "Status: INSUFFICIENT_FUNDS";
status.status = "INSUFFICIENT_FUNDS";
} else {
if (parseFloat(totalCid) === parseFloat(change)) {
// status = "Status: CLOSED";
status.status = "CLOSED";
} else {
// status = "Status: OPEN";
status.status = "OPEN";
}
for (let i = cid.length - 1; i >= 0; i--) {
let inRegister = cid[i][1];
let billValue = cidValue[i];
if (inRegister > 0 && change >= billValue) {
let amount = 0;
const amountNeeded = Math.floor(change / billValue);
const amountInRegister = Math.floor(inRegister / billValue);
if (amountInRegister >= amountNeeded) {
amount = amountNeeded * billValue;
} else {
amount = amountInRegister * billValue;
}
change = (change - amount).toFixed(2);
//status += ` ${cid[i][0]}: $${amount}`;
status.change.push([cid[i][0], amount]);
}
}
if (parseFloat(change) !== 0) {
//status = "Status: INSUFFICIENT_FUNDS";
status.status = "INSUFFICIENT_FUNDS";
status.change = [];
}
}
//changeDue.textContent = status;
return status;
}
};
const runTests = () => {
console.assert(
checkCashRegister(19.5, 20, [
['PENNY', 1.01],
['NICKEL', 2.05],
['DIME', 3.1],
['QUARTER', 4.25],
['ONE', 90],
['FIVE', 55],
['TEN', 20],
['TWENTY', 60],
['ONE HUNDRED', 100]
]),
{ status: 'OPEN', change: [['QUARTER', 0.5]] }
);
console.assert(
checkCashRegister(19.5, 20, [
['PENNY', 1.01],
['NICKEL', 2.05],
['DIME', 3.1],
['QUARTER', 4.25],
['ONE', 90],
['FIVE', 55],
['TEN', 20],
['TWENTY', 60],
['ONE HUNDRED', 100]
]),
{ status: 'OPEN', change: [['QUARTER', 0.5]] }
);
console.assert(
checkCashRegister(3.26, 100, [
['PENNY', 1.01],
['NICKEL', 2.05],
['DIME', 3.1],
['QUARTER', 4.25],
['ONE', 90],
['FIVE', 55],
['TEN', 20],
['TWENTY', 60],
['ONE HUNDRED', 100]
]),
{
status: 'OPEN',
change: [
['TWENTY', 60],
['TEN', 20],
['FIVE', 15],
['ONE', 1],
['QUARTER', 0.5],
['DIME', 0.2],
['PENNY', 0.04]
]
}
);
console.assert(
checkCashRegister(19.5, 20, [
['PENNY', 0.01],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 0],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
]),
{ status: 'INSUFFICIENT_FUNDS', change: [] }
);
console.assert(
checkCashRegister(19.5, 20, [
['PENNY', 0.01],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 1],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
]),
{ status: 'INSUFFICIENT_FUNDS', change: [] }
);
console.assert(
checkCashRegister(19.5, 20, [
['PENNY', 0.5],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 0],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
]),
{
status: 'CLOSED',
change: [
['PENNY', 0.5],
['NICKEL', 0],
['DIME', 0],
['QUARTER', 0],
['ONE', 0],
['FIVE', 0],
['TEN', 0],
['TWENTY', 0],
['ONE HUNDRED', 0]
]
}
);
console.log("Tests passed");
};