I have an input component. It can appear and behave in 6 different ways:

Input is a:

  • Text input
  • Text input with a start adornment
  • Email input
  • Email input with a start adornment
  • Password input with an end adornment
  • Password input with a start and end adornment

Rather than repeating each test 6 times, I would like to use describe.each() rather than a straight describe().

The input will also appear and behave differently based on the user's interaction with the input.

For example, all users will start with the following flow:

  1. Initial render of input
  2. Focus in

A user may then follow a flow such as:

  1. Enters an invalid input value
  2. Focuses out
  3. Focuses in
  4. Enters a valid input (same outcome as step 1. below)
  5. Focuses out (same outcome as step 2. below)

Or another flow:

  1. Enters a valid input value
  2. Focuses out
  3. Focuses in
  4. Enters an invalid input or deletes valid input (same outcome as enters an invalid input)
  5. Focuses out (same outcome as focus out with invalid input)

Or another flow:

  1. Enters no input
  2. Focuses out (same outcome as initial render of input)

Rather than testing each step individually, would it better to set up the tests without cleanup so that I can nest the tests for each stage of the flow?

For example:

describe.each`...`("Initial render", ({...}) => {
  it("renders as snapshot", () => ....)

  describe("Then users focuses in", () => {
    fireEvent.focusIn(input)
    it("renders as snapshot", () => ....)

    describe("Then user enters valid input", () => {
      fireEvent.change(input, { target: { value: "Valid input" }})
      it("renders as snapshot", () => ....)

      describe("Then user focuses out", () => {
        fireEvent.focusOut(input)
        it("renders as snapshot", () => ....)

        describe("Then user enters an invalid or no input", () => {
          fireEvent.focusIn(input)
          fireEvent.change(input, { target: { value: "" }})
          it("renders as snapshot", () => ....)
        })
      })
    })

    describe("Then user enters an invalid input", () => {
      fireEvent.change(input, { target: { value: "$%^@!" }})
      it("renders as snapshot", () => ....)

      describe("Then user focuses out", () => {
        fireEvent.focusOut(input)
        it("renders as snapshot", () => ....)

        describe("Then user enters an valid input", () => {
          fireEvent.focusIn(input)
          fireEvent.change(input, { target: { value: "Valid input" }})
          it("renders as snapshot", () => ....)
        })
      })
    })

    describe("Then user doesn't enter any input and focuses out", () => {
      fireEvent.focusOut(input)
      it("renders as snapshot", () => ....)
    })
  })
}

If I do it this way, how do I properly setup and teardown each test, i.e. with beforeEach(cleanup), afterEach(cleanup), beforeAll(cleanup) and/or afterAll(cleanup), so that it works with the describe.each()?

0 Answers