Page MenuHomePhabricator

[Cashtab] Implement unified balance header
ClosedPublic

Authored by bytesofman on Jan 19 2024, 01:04.

Details

Reviewers
emack
Group Reviewers
Restricted Project
Commits
rABCc0f4c6b1e9e4: [Cashtab] Implement unified balance header
Summary

Combine BalanceHeader and BalanceHeaderFiat into a cleaner, unit-tested component. Implement in App.js so it appears in the same position for all screens.

Note: This means the Settings screen how has the BalanceHeader at the top which, imo, is an improvment.

Features of new BalanceHeader

  • Hidden balance now controlled by css and not component replacement (faster)
  • Support for different user locale number formatting
  • Decimal places are now always constant (i.e. 2 decimal places for fiat and XEC, not sometimes 1)
  • Unit tested component
  • Unit tests for App.js
Test Plan

npm test

Diff Detail

Repository
rABC Bitcoin ABC
Branch
better-balance-header
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 26529
Build 52628: Build Diffcashtab-tests
Build 52627: arc lint + arc unit

Event Timeline

pending updates to other unit tests

mb want to skip this and just drop it straight into App.js

Failed tests logs:

====== CashTab Unit Tests: <BalanceHeaderCombined /> Renders the loader if balanceSats is not an integer ======
TypeError: Cannot read properties of null (reading 'toLocaleString')
    at toLocaleString (/work/cashtab/src/components/Common/BalanceHeaderCombined.js:56:44)
    at renderWithHooks (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:14985:18)
    at mountIndeterminateComponent (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:17811:13)
    at beginWork (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:19049:16)
    at HTMLUnknownElement.callCallback (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:3945:14)
    at HTMLUnknownElement.callTheUserObjectsOperation (/work/cashtab/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
    at innerInvokeEventListeners (/work/cashtab/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25)
    at invokeEventListeners (/work/cashtab/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
    at HTMLUnknownElementImpl._dispatch (/work/cashtab/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
    at HTMLUnknownElementImpl.dispatchEvent (/work/cashtab/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17)
    at HTMLUnknownElement.dispatchEvent (/work/cashtab/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
    at Object.invokeGuardedCallbackDev (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:3994:16)
    at invokeGuardedCallback (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
    at beginWork$1 (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:23964:7)
    at performUnitOfWork (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22779:12)
    at workLoopSync (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22707:5)
    at renderRootSync (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22670:7)
    at performSyncWorkOnRoot (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22293:18)
    at scheduleUpdateOnFiber (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:21881:7)
    at updateContainer (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:25482:3)
    at /work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:26021:7
    at unbatchedUpdates (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22431:12)
    at legacyRenderSubtreeIntoContainer (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:26020:5)
    at Object.render (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:26103:10)
    at /work/cashtab/node_modules/@testing-library/react/dist/pure.js:101:25
    at batchedUpdates$1 (/work/cashtab/node_modules/react-dom/cjs/react-dom.development.js:22380:12)
    at act (/work/cashtab/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
    at render (/work/cashtab/node_modules/@testing-library/react/dist/pure.js:97:26)
    at Object.<anonymous> (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:52:15)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests: <BalanceHeaderCombined /> Renders the BalanceHeaderCombined component correctly with default locale en-US ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  10,000,000 XEC
Received:
  10,000,000.00 XEC
    at Object.toHaveTextContent (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:84:28)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests: <BalanceHeaderCombined /> Renders the BalanceHeaderCombined component correctly with fr-FR locale ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  10 000 000 XEC
Received:
  10 000 000,00 XEC
    at Object.toHaveTextContent (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:121:28)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests: <BalanceHeaderCombined /> Balance is hidden if cashtabSettings.balanceVisible is false ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  10,000,000 XEC
Received:
  10,000,000.00 XEC
    at Object.toHaveTextContent (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:157:28)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests: <BalanceHeaderCombined /> Renders fiat price for a non-USD currency ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  10,000,000 XEC
Received:
  10,000,000.00 XEC
    at Object.toHaveTextContent (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:193:28)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests: <BalanceHeaderCombined /> Fiat price and forex are not displayed if fiatPrice is unavailable ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  10,000,000 XEC
Received:
  10,000,000.00 XEC
    at Object.toHaveTextContent (/work/cashtab/src/components/Common/__tests__/BalanceHeaderCombined.test.js:227:28)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:121:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Wallet with XEC balances and tokens ======
Error: expect(received).toMatchSnapshot()

Snapshot name: `Wallet with XEC balances and tokens 1`

New snapshot was not written. The update flag must be explicitly passed to write a new snapshot.

This is likely because this test is run in a continuous integration (CI) environment in which snapshots are not written by default.

Received: null
    at Object.toMatchSnapshot (/work/cashtab/src/components/Send/__tests__/SendToken.test.js:47:18)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Wallet with XEC balances and tokens and state field ======
Error: expect(received).toMatchSnapshot()

Snapshot name: `Wallet with XEC balances and tokens and state field 1`

New snapshot was not written. The update flag must be explicitly passed to write a new snapshot.

This is likely because this test is run in a continuous integration (CI) environment in which snapshots are not written by default.

Received:
<div
  className="sc-csuQGl jJoCcv"
>
  <div
    className="sc-jhAzac dVfipN"
  >
    6.001000000
     
    TBS
  </div>
  <div
    className="ant-row"
    style={{}}
    type="flex"
  >
    <div
      className="ant-col ant-col-24"
      style={{}}
    >
      <form
        className="ant-form ant-form-horizontal"
        onReset={[Function]}
        onSubmit={[Function]}
        style={
          {
            "width": "auto",
          }
        }
      >
        <div
          className="sc-cMljjf hLAWze"
        >
          <div
            className="ant-form-item ant-form-item-with-help"
            style={
              {
                "marginBottom": "0px",
              }
            }
          >
            <div
              className="ant-row ant-form-item-row"
              style={{}}
            >
              <div
                className="ant-col ant-form-item-control"
                style={{}}
              >
                <div
                  className="ant-form-item-control-input"
                >
                  <div
                    className="ant-form-item-control-input-content"
                  >
                    <span
                      className="ant-input-group-wrapper"
                    >
                      <span
                        className="ant-input-wrapper ant-input-group"
                      >
                        <span
                          className="ant-input-affix-wrapper"
                          hidden={null}
                          onClick={[Function]}
                          style={null}
                        >
                          <span
                            className="ant-input-prefix"
                          >
                            <span
                              aria-label="wallet"
                              className="anticon anticon-wallet sc-bxivhb iBBRHU"
                              role="img"
                            >
                              <svg
                                aria-hidden="true"
                                data-icon="wallet"
                                fill="currentColor"
                                focusable="false"
                                height="1em"
                                viewBox="64 64 896 896"
                                width="1em"
                              >
                                <path
                                  d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 464H528V448h312v128zm0 264H184V184h656v200H496c-17.7 0-32 14.3-32 32v192c0 17.7 14.3 32 32 32h344v200zM580 512a40 40 0 1080 0 40 40 0 10-80 0z"
                                />
                              </svg>
                            </span>
                          </span>
                          <input
                            autoComplete="off"
                            className="ant-input"
                            data-testid="destination-address-single"
                            hidden={null}
                            name="address"
                            onBlur={[Function]}
                            onChange={[Function]}
                            onFocus={[Function]}
                            onKeyDown={[Function]}
                            placeholder="Address"
                            required={true}
                            style={null}
                            type="text"
                            value=""
                          />
                        </span>
                        <span
                          className="ant-input-group-addon"
                        >
                          <span
                            className="sc-cvbbAY gRnXOq"
                            onClick={[Function]}
                          >
                            <span
                              aria-label="qrcode"
                              className="anticon anticon-qrcode sc-ifAKCX jqgRJL"
                              role="img"
                            >
                              <svg
                                aria-hidden="true"
                                data-icon="qrcode"
                                fill="currentColor"
                                focusable="false"
                                height="1em"
                                viewBox="64 64 896 896"
                                width="1em"
                              >
                                <path
                                  d="M468 128H160c-17.7 0-32 14.3-32 32v308c0 4.4 3.6 8 8 8h332c4.4 0 8-3.6 8-8V136c0-4.4-3.6-8-8-8zm-56 284H192V192h220v220zm-138-74h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm194 210H136c-4.4 0-8 3.6-8 8v308c0 17.7 14.3 32 32 32h308c4.4 0 8-3.6 8-8V556c0-4.4-3.6-8-8-8zm-56 284H192V612h220v220zm-138-74h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm590-630H556c-4.4 0-8 3.6-8 8v332c0 4.4 3.6 8 8 8h332c4.4 0 8-3.6 8-8V160c0-17.7-14.3-32-32-32zm-32 284H612V192h220v220zm-138-74h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm194 210h-48c-4.4 0-8 3.6-8 8v134h-78V556c0-4.4-3.6-8-8-8H556c-4.4 0-8 3.6-8 8v332c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V644h78v102c0 4.4 3.6 8 8 8h190c4.4 0 8-3.6 8-8V556c0-4.4-3.6-8-8-8zM746 832h-48c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8zm142 0h-48c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
                                />
                              </svg>
                            </span>
                          </span>
                        </span>
                      </span>
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div
          className="sc-kjoXOD kGyknS"
        >
          <a
            className="sc-gipzik iQaaeS"
            data-testid="alias-address-preview"
            href="https://explorer.e.cash/address/false"
            rel="noreferrer"
            target="_blank"
          />
        </div>
        <br />
        <div
          className="sc-cMljjf hLAWze"
        >
          <div
            className="ant-form-item ant-form-item-with-help"
          >
            <div
              className="ant-row ant-form-item-row"
              style={{}}
            >
              <div
                className="ant-col ant-form-item-control"
                style={{}}
              >
                <div
                  className="ant-form-item-control-input"
                >
                  <div
                    className="ant-form-item-control-input-content"
                  >
                    <span
                      className="ant-input-group-wrapper"
                    >
                      <span
                        className="ant-input-wrapper ant-input-group"
                      >
                        <span
                          className="ant-input-affix-wrapper"
                          hidden={null}
                          onClick={[Function]}
                          style={null}
                        >
                          <span
                            className="ant-input-prefix"
                          />
                          <input
                            className="ant-input"
                            data-testid="send-token-input"
                            hidden={null}
                            name="value"
                            onBlur={[Function]}
                            onChange={[Function]}
                            onFocus={[Function]}
                            onKeyDown={[Function]}
                            onWheel={[Function]}
                            placeholder="Amount"
                            required={true}
                            step={1e-9}
                            style={null}
                            type="number"
                            value=""
                          />
                          <span
                            className="ant-input-suffix"
                          >
                            TBS
                          </span>
                        </span>
                        <span
                          className="ant-input-group-addon"
                        >
                          <span
                            className="sc-jAaTju gZNdNw"
                            disabled={false}
                            onClick={[Function]}
                          >
                            max
                          </span>
                        </span>
                      </span>
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div
          style={
            {
              "paddingTop": "12px",
            }
          }
        >
          <button
            className="sc-kkGfuU ORPKP"
            onClick={[Function]}
          >
            Send 
            TestBits
          </button>
        </div>
      </form>
    </div>
  </div>
</div>
    at Object.toMatchSnapshot (/work/cashtab/src/components/Send/__tests__/SendToken.test.js:67:18)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Without wallet defined ======
Error: expect(received).toMatchSnapshot()

Snapshot name: `Without wallet defined 1`

New snapshot was not written. The update flag must be explicitly passed to write a new snapshot.

This is likely because this test is run in a continuous integration (CI) environment in which snapshots are not written by default.

Received: null
    at Object.toMatchSnapshot (/work/cashtab/src/components/Send/__tests__/SendToken.test.js:90:18)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Wallet without BCH balance ======
TypeError: Cannot read properties of null (reading 'toLocaleString')
    at toLocaleString (/work/cashtab/src/components/Common/BalanceHeaderCombined.js:56:44)
    at renderWithHooks (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
    at mountIndeterminateComponent (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
    at beginWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
    at performUnitOfWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
    at workLoopSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13728:5)
    at renderRootSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13691:7)
    at performSyncWorkOnRoot (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13404:18)
    at /work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2537:26
    at unstable_runWithPriority (/work/cashtab/node_modules/scheduler/cjs/scheduler.development.js:468:12)
    at runWithPriority (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2486:10)
    at flushSyncCallbackQueueImpl (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2532:9)
    at flushSyncCallbackQueue (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2519:3)
    at scheduleUpdateOnFiber (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13004:9)
    at updateContainer (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16454:3)
    at Object.create (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:17149:3)
    at Object.create (/work/cashtab/src/components/Home/__tests__/Home.test.js:16:32)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Wallet with BCH balances ======
TypeError: Cannot read properties of null (reading 'toLocaleString')
    at toLocaleString (/work/cashtab/src/components/Common/BalanceHeaderCombined.js:56:44)
    at renderWithHooks (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
    at mountIndeterminateComponent (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
    at beginWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
    at performUnitOfWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
    at workLoopSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13728:5)
    at renderRootSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13691:7)
    at performSyncWorkOnRoot (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13404:18)
    at /work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2537:26
    at unstable_runWithPriority (/work/cashtab/node_modules/scheduler/cjs/scheduler.development.js:468:12)
    at runWithPriority (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2486:10)
    at flushSyncCallbackQueueImpl (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2532:9)
    at flushSyncCallbackQueue (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2519:3)
    at scheduleUpdateOnFiber (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13004:9)
    at updateContainer (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16454:3)
    at Object.create (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:17149:3)
    at Object.create (/work/cashtab/src/components/Home/__tests__/Home.test.js:30:32)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)
====== CashTab Unit Tests:  Wallet with BCH balances and tokens ======
TypeError: Cannot read properties of null (reading 'toLocaleString')
    at toLocaleString (/work/cashtab/src/components/Common/BalanceHeaderCombined.js:56:44)
    at renderWithHooks (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
    at mountIndeterminateComponent (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
    at beginWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
    at performUnitOfWork (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
    at workLoopSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13728:5)
    at renderRootSync (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13691:7)
    at performSyncWorkOnRoot (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13404:18)
    at /work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2537:26
    at unstable_runWithPriority (/work/cashtab/node_modules/scheduler/cjs/scheduler.development.js:468:12)
    at runWithPriority (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2486:10)
    at flushSyncCallbackQueueImpl (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2532:9)
    at flushSyncCallbackQueue (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2519:3)
    at scheduleUpdateOnFiber (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13004:9)
    at updateContainer (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16454:3)
    at Object.create (/work/cashtab/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:17149:3)
    at Object.create (/work/cashtab/src/components/Home/__tests__/Home.test.js:44:32)
    at Promise.then.completed (/work/cashtab/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/work/cashtab/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/work/cashtab/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at _runTest (/work/cashtab/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/work/cashtab/node_modules/jest-circus/build/run.js:126:9)
    at run (/work/cashtab/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/work/cashtab/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/work/cashtab/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/work/cashtab/node_modules/jest-runner/build/runTest.js:444:34)
    at Object.worker (/work/cashtab/node_modules/jest-runner/build/testWorker.js:106:12)

Each failure log is accessible here:
CashTab Unit Tests: <BalanceHeaderCombined /> Renders the loader if balanceSats is not an integer
CashTab Unit Tests: <BalanceHeaderCombined /> Renders the BalanceHeaderCombined component correctly with default locale en-US
CashTab Unit Tests: <BalanceHeaderCombined /> Renders the BalanceHeaderCombined component correctly with fr-FR locale
CashTab Unit Tests: <BalanceHeaderCombined /> Balance is hidden if cashtabSettings.balanceVisible is false
CashTab Unit Tests: <BalanceHeaderCombined /> Renders fiat price for a non-USD currency
CashTab Unit Tests: <BalanceHeaderCombined /> Fiat price and forex are not displayed if fiatPrice is unavailable
CashTab Unit Tests: Wallet with XEC balances and tokens
CashTab Unit Tests: Wallet with XEC balances and tokens and state field
CashTab Unit Tests: Without wallet defined
CashTab Unit Tests: Wallet without BCH balance
CashTab Unit Tests: Wallet with BCH balances
CashTab Unit Tests: Wallet with BCH balances and tokens

Improve tests, correct rendering bugs, implement throughout app from App.js

  • Wait for D15203, D15207, and D15208 to land. You could rebase on that stack but getting a little big.
  • Rebase
  • Delete BalanceHeader component
  • Delete BalanceHeaderFiat component
  • Rename BalanceHeaderCombined to BalanceHeader
  • Delete ZeroBalanceHeader component
  • Delete all now-unused atoms from deleted components
  • Request review
  • Extension version bump when this lands
emack requested changes to this revision.Jan 22 2024, 07:04
emack added a subscriber: emack.
emack added inline comments.
cashtab/src/components/Common/BalanceHeader.js
64–65 ↗(On Diff #44415)
73–74 ↗(On Diff #44415)

as above

80 ↗(On Diff #44415)

should be in appConfig too. Is 8 decimal places standardized across exchanges?

cashtab/src/components/Common/__tests__/App.test.js
85 ↗(On Diff #44415)

Given the test description there should be a check on the presence of the onboarding text and sideshift button.

image.png (363×604 px, 49 KB)

cashtab/src/components/Common/__tests__/BalanceHeader.test.js
174 ↗(On Diff #44415)

based on the description above, where is the actual check that the balance is hidden? Is 'cash-loader' the blurring effect in front of the balance? I couldn't easily tell from looking at customIcons.js

cashtab/src/components/fixtures/mocks.js
1 ↗(On Diff #44415)

This is a duplicate of components/Send/fixtures/mocks.js. Is the intention to eventually move all those send mocks into the base components/fixtures folder?

This revision now requires changes to proceed.Jan 22 2024, 07:04

For consistency, remove the settings label (via app.js) since none of the other components use it. It will also ensure it's always positioned the same vertically.

image.png (293×565 px, 35 KB)

bytesofman added inline comments.
cashtab/src/components/Common/BalanceHeader.js
80 ↗(On Diff #44415)

dunno if it's standardized. removed magic number but this config is a Cashtab aesthetic choice based on what the price of XEC happens to be, so makes sense as a local config here.

cashtab/src/components/Common/__tests__/BalanceHeader.test.js
174 ↗(On Diff #44415)

It's the css text-shadow

hidden:
expect(BalanceFiat).toHaveStyle(text-shadow: 0 0 15px #fff`);`

cashtab/src/components/fixtures/mocks.js
1 ↗(On Diff #44415)

Yes, we have some available org optimizations for the testing.

1 - the jsdom global window matchMedia mock should run before all component jest tests, instead of appearing at the top of all of these files
2 - we should have some common mocks at the top level

Re: 2, though, we might not get to this and there's a good reason for it. It is nice to have local testing mocks because, as tests and components evolve, you often need slightly different mocks for each component. This is manageable by cloning mocks and adding keys, this type of thing. It's easier to maintain if everything just has its own mocks.

This is the first diff to put mocks at the src/components level, which is where I believe any common mocks should live.

bytesofman marked 3 inline comments as done.

no magic numbers for decimal formats, add test confirming presence of sideshift button on Home screen for zero balance wallet

Accepted with minor nit

cashtab/src/components/Common/__tests__/BalanceHeader.test.js
159 ↗(On Diff #44415)

in that case

This revision is now accepted and ready to land.Jan 22 2024, 12:07