Skip to content

Challenges

Hannah edited this page Feb 24, 2021 · 6 revisions

Challenges

Same Input, Different Output from one CashRegister

I was having an incredible bug with my Cash Register where I could pass it a "cash in drawer" array, and receive half a $5 bill as change, instead of the expected 2 quarters.

The most astounding thing is that the function passed the same test multiple times in all the other ways it had been tested, including the unit tests on freeCodeCamp and in the console by running the script with Node: both transpiled, transpiled with preset, and not. But no matter what, that final test kept failing.

So after a night's sleep, I realized that I could copy-paste the original unit tests from freeCodeCamp into my own test suite to see what happened.

Lo and behold, the test copied directly from freeCodeCamp passed just fine. There must be some mistake that I made, then...

Even when I had copied exactly the input and the expected output into my test array, it was failing... So perhaps I had accidentally mutated the array when looping it...?

Finally a clue

Finally, after re-adding some console statements, I had a clue: the "faulty" unit test was decrementing the remainingBalance in the wrong order, starting with pennies instead of hundred dollar bills. Somehow, its input array representing the drawer of cash was being flipped at the very beginning of the checkCashRegister algorithm. This was unique only to this test.

Hoping to find more clues, I went back to the test suite: my next suspect was the double de-structuring that I was doing in the forEach loop... Perhaps that was... doing... something... to flip my array?

  testArr.forEach(([[price, cash, cid], expectedResult]) => {
    it(`should return ${JSON.stringify(expectedResult)} given ${price}, ${cash}, ${JSON.stringify(cid)}`, () => {
      assert.deepStrictEqual(
        checkCashRegister(price, cash, cid), expectedResult
      );
    });
  });

For reference:

[[...], expectedResult]: The first de-structuring, the outer array, is meant to refer to each array within testArr.

[[price, cash, cid], ...]: The inner array is meant to the refer to the array containing the inputs. Note that cid is also an array.

Alas, no... Removing the double de-structuring had no impact on the result: the cash in drawer array was still being flipped only for the first test.

  testArr.forEach(([input, expectedResult]) => {
    it(`should return ${JSON.stringify(expectedResult)} given ${JSON.stringify(input)}`, () => {
      assert.deepStrictEqual(
        checkCashRegister(input[0], input[1], input[2]), expectedResult
      );
    });
  });

Another clue

Aha! When I comment out the "faulty" array from testArr, the next array in testArr fails. So it has something to do with being the first array in the list: it has nothing to do with each individual set of inputs and outputs.

The next suspect was the very first test, before looping through testArr, which checks whether the function returns an object.

  it(`should return an object given ${testArr[0][0]}`, () => {
    assert.strictEqual(typeof checkCashRegister(testArr[0][0][0], testArr[0][0][1], testArr[0][0][2]), "object");
  });
  • testArr[0] = first entry in testArr: an array containing [...],{status: 'OPEN', change: [['QUARTER', 0.5]]}
  • testArr[0][0] = first entry in testArr[0]: [19.5, 20, [["PENNY", 1.01], ... ["ONE HUNDRED", 100]]
  • testArr[0][0][0] = 19.5?

Let's try the same test but without the deep nesting.

  it(`should return an object given ${testArr[0][0]}`, () => {
    assert.strictEqual(typeof checkCashRegister(testArr[0][0], testArr[0][1], testArr[0][2]), "object");
  });

FINALLY! It works! All the unit tests passed!

However, after all this headache, I don't think it makes sense to leave a unit test that isn't explicit. I'm going to hard-code this test instead.

  it(`should return an object given ${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]]}`, () => {
    assert.strictEqual(typeof 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]]), "object");
  });

Upgrading Node 14 and NPM 6

I upgraded my global npm from 6.14.x to 7.x and Node from 14.x to 15.x mid-project. Why? Well... npm was telling me to every single day... Why didn't I research the potential drawbacks of updating before updating...? Well... let's just say I won't do it again.

The global npm update seemed to have overwritten global installations: daily-use commands, such as mocha or npm test: mocha, were now having issues.

Mocha

js-capstone $ mocha
Command 'mocha' not found, but can be installed with:
...

npm test

It wasn't just global dependencies acting up; local dependencies were popping up where they hadn't before.

23 verbose stack Error: command failed (...)
$HOME/.nvm/versions/node/v15.9.0/lib/node_modules/npm/node_modules/@npmcli/promise-spawn/index.js:64:27
npm ERR! code 1
npm ERR! path /mnt/d/freeCodeCampJS/js-capstone
npm ERR! command failed
npm ERR! command sh -c mocha

npm ERR! A complete log of this run can be found in:
npm ERR!     $HOME/.npm/_logs/2021-02-23T17_52_28_892Z-debug.log

The truncated contents of the debug log:

23 verbose stack Error: command failed
23 verbose stack     at ChildProcess.<anonymous> ($HOME/.nvm/versions/node/v15.9.0/lib/node_modules/npm/node_modules/@npmcli/promise-spawn/index.js:64:27)
23 verbose stack     at ChildProcess.emit (node:events:378:20)
23 verbose stack     at maybeClose (node:internal/child_process:1067:16)
23 verbose stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:301:5)
24 verbose pkgid js-capstone@0.1.0
25 verbose cwd /mnt/d/freeCodeCampJS/js-capstone
26 verbose Linux 4.4.0-19041-Microsoft
27 verbose argv "$HOME/.nvm/versions/node/v15.9.0/bin/node" "$HOME/.nvm/versions/node/v15.9.0/bin/npm" "test"
28 verbose node v15.9.0
29 verbose npm  v7.5.4

To be continued...

Subsequent Install Fails with npm 7, React 17, and Google Firebase Hooks 2.2.0

NPM package react-firebase-hooks at version 2.2.0 it is associated with the following React 17 error message when trying to install dependencies.

npm i

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: js-capstone@0.1.0
npm ERR! Found: react@17.0.1
npm ERR! node_modules/react
npm ERR!   react@"^17.0.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0" from react-firebase-hooks@2.2.0
npm ERR! node_modules/react-firebase-hooks
npm ERR!   react-firebase-hooks@"^2.2.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

(...)

Fix the upstream dependency conflict, or retry this command with --force, or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution

Apparently, a relevant difference between npm versions 3 to 6 and version 7 is that npm 7 will not ignore peer dependencies on installation. To reset the behavior of npm 7 in this regard, the --legacy-peer-deps flag can be added to the installation command: npm i --legacy-peer-deps

Finally, by using this flag, npm was able to install dependencies.