Skip to content

Testing

Raine Revere edited this page Nov 8, 2024 · 19 revisions

Quick Start

yarn test            # unit and jsdom tests
yarn test:puppeteer  # puppeteer (docker required)
yarn test:ios        # webdriverio (browserstack account required)

Stack

  • Vitest
  • JSDOM
  • React Testing Library
  • Puppeteer
  • Browserless
  • Docker
  • WebdriverIO
  • Github Actions

Tests

The project has multiple levels of automated testing, from single function unit tests up to realistic end-to-end (E2E) tests that run tests against an actual device or browser.

Use the lowest level that is sufficient for your test case. If your test case does not require a DOM, use a unit test. If it requires a DOM but is not browser or device-specific, use an RTL test. Higher level tests may provide a more realistic testing environment, but they are slower and, in the case of webdriverio on browserstack, cost per minute of usage.

You can find the test files spread throughout the project in __test__ directories.

[INSERT DIAGRAM]

1. Unit Tests

⚡️⚡️⚡️ 1–20ms

Basic unit tests are great for testing pure functions directly.

Related tests: actions, selectors, util

2. Store Tests

⚡️⚡️⚡️ 1–20ms

The shortcut tests require dispatching Redux actions but do not need a DOM. You can use the helpers createTestStore and executeShortcut to operate directly on a Redux store, then make assertions about store.getState(). This allows shortcuts to be tested independently of the user device.

Related tests: shortcuts

3. JSDOM Tests

⚡️⚡️ 1–1000ms

Anything that tests a rendered component requires a DOM. If there are no browser or device quirks, you can get away with testing against an emulated DOM (jsdom) which is cheaper and faster than a real browser.

Related tests: components

4. E2E Tests

⚡️ 1–2s

E2E, or End-to-End, tests involve running a real browser or device and controlling it with an automation driver. You can perform common user actions like touch, click, and type. These tests are the slowest and most expensive to run.

  • puppeteer (Chrome) - Requires docker
  • webdriverio (Mobile devices) - Requires a browserstack account

To run WebdriverIO tests, add BROWSERSTACK_USERNAME=your_username and BROWSERSTACK_ACCESS_KEY=your_access_key to .env.test.local in the project root and run npm run test:e2e:ios.

Related tests: e2e

5. Visual snapshot tests

⚡️ 1–2s

Snapshot tests are a specific type of puppeteer test used to prevent visual regressions. They automate taking a screenshot after your changes and comparing it to a reference screenshot. If the screenshot differs by a certain number of pixels, then it is considered a regression and the test will fail. In the case of a failed snapshot test, a visual diff will be generated that allows you to see why it failed.

In this example, the superscript position broke so the snapshot test failed. The expected snapshot is on the left; the current snapshot is on the right.

font-size-22-superscript-1-diff

When running the tests locally, a link to the visual diff will be output in your shell. When running the tests in GitHub Actions, the visual diff can be downloaded from the artifact link added to the test output under "Upload snapshot diff artifact":

Screenshot 2024-11-08 at 11 30 25 AM

If you are absolutely sure that the change is desired, and your PR was supposed to change the visual appearance of em, then run the snapshot test with -u to update the reference snapshot.

Manual Test Cases

Various test cases that may need to be tested manually.

Touch Events

  • Enter edit mode (#1208)
  • Preserve editing: true (#1209)
  • Preserve editing: false (#1210)
  • No uncle loop (#908)
  • Tap hidden root thought (#1029)
  • Tap hidden uncle (#1128-1)
  • Tap empty Content (#1128-2)
  • Scroll (#1054)
  • Swipe over cursor (#1029-1)
  • Swipe over hidden thought (#1147)
  • Preserve editing on switch app (#940)
  • Preserve editing clicking on child edge (#946)
  • Auto-Capitalization on Enter (#999)

Render

Test enter and leave on each of the following actions:

  1. New Thought

  2. New Subthought

  3. Move Thought Up/Down

  4. Indent/Outdent

  5. SubcategorizeOne/All

  6. Toggle Pin Children

  7. Basic Navigation

    - x
      - y
        - z
          - r
            - o
        - m
          - o
        - n
    
  8. Word Wrap

    - a
      - This is a long thought that after enough typing will break into multiple lines.
      - forcebreakkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
      - c
    
  9. Toggle Table View

    - a
      - =view
        - Table
      - b
        - b1
      - c
        - c1
    
  10. Table View - Column 2 Descendants

    - a
      - =view
        - Table
      - c
        - c1
          - c2
            - c3
    
  11. Table View - Vertical Alignment

    - a
      - =view
        - Table
      - b
        - b1
        - b2
        - b3
      - c
        - c1
        - c2
        - c3
    
    - a
      - =view
        - Table
      - b
        - This is a long thought that after enough typing will break into multiple lines.
      - c
        - c1
    
    - a
      - =view
        - Table
      - This is a long thought that after enough typing will break into multiple lines.
        - b1
        - b2
      - c
        - c1
    
    - a
      - =view
        - Table
      - This is a long thought that after enough typing will break into multiple lines.
        - b1
        - b2
      - c
        - c1
    
  12. Expand/collapse large number of thoughts at once

    - one
      - =pinChildren
        - true
      - a
        - =view
          - Table
        - c
          - c1
            - c2
              - c3
                - c4
        - This is a long thought that after enough typing will break into multiple lines.
          - b1
          - b2
        - oof
          - woof
      - x
        - =pinChildren
          - true
        - y
          - y1
        - z
    
  13. Nested Tables

    - a
      - =view
        - Table
      - b
        - =view
          - Table
        - b1
          - x
        - b2
          - y