github.com/tilt-dev/tilt@v0.36.0/web/src/ResourceGroupsContext.test.tsx (about)

     1  import { act, render } from "@testing-library/react"
     2  import userEvent from "@testing-library/user-event"
     3  import React from "react"
     4  import {
     5    DEFAULT_GROUP_STATE,
     6    ResourceGroupsContextProvider,
     7    useResourceGroups,
     8  } from "./ResourceGroupsContext"
     9  
    10  const GROUP_STATE_ID = "test-group-state"
    11  const LABEL_STATE_ID = "test-label-state"
    12  
    13  // This is a very basic test component that prints out the state
    14  // from the ResourceGroups context and provides buttons to trigger
    15  // methods returned by the context, so they can be tested
    16  const TestConsumer = (props: { labelName?: string }) => {
    17    const { groups, getGroup, toggleGroupExpanded } = useResourceGroups()
    18  
    19    return (
    20      <>
    21        <p id={GROUP_STATE_ID}>{JSON.stringify(groups)}</p>
    22        {/* Display the label state if a specific label is present */}
    23        {props.labelName && (
    24          <p id={LABEL_STATE_ID}>{JSON.stringify(getGroup(props.labelName))}</p>
    25        )}
    26        {/* Display a button to toggle the label state if a specific label is present */}
    27        {props.labelName && (
    28          <button onClick={() => toggleGroupExpanded(props.labelName || "")} />
    29        )}
    30      </>
    31    )
    32  }
    33  
    34  describe("ResourceGroupsContext", () => {
    35    let wrapper: HTMLElement
    36  
    37    // Helpers
    38    const groupState = () =>
    39      wrapper.querySelector(`#${GROUP_STATE_ID}`)!.innerHTML
    40    const labelState = () =>
    41      wrapper.querySelector(`#${LABEL_STATE_ID}`)!.innerHTML
    42    const clickButton = () => {
    43      userEvent.click(wrapper.querySelector("button")!)
    44    }
    45  
    46    beforeEach(() => {
    47      localStorage.clear()
    48    })
    49  
    50    afterEach(() => {
    51      localStorage.clear()
    52    })
    53  
    54    it("defaults to an empty state with no groups", () => {
    55      wrapper = renderContainer(
    56        <ResourceGroupsContextProvider>
    57          <TestConsumer />
    58        </ResourceGroupsContextProvider>
    59      )
    60  
    61      expect(groupState()).toBe(JSON.stringify({}))
    62    })
    63  
    64    describe("toggleGroupExpanded", () => {
    65      it("sets expanded to `true` when group is collapsed", () => {
    66        const testValues = { test: { expanded: false } }
    67        wrapper = renderContainer(
    68          <ResourceGroupsContextProvider initialValuesForTesting={testValues}>
    69            <TestConsumer labelName="test" />
    70          </ResourceGroupsContextProvider>
    71        )
    72        clickButton()
    73  
    74        expect(labelState()).toBe(JSON.stringify({ expanded: true }))
    75      })
    76  
    77      it("sets expanded to `false` when group is expanded", () => {
    78        const testValues = { test: { expanded: true } }
    79        wrapper = renderContainer(
    80          <ResourceGroupsContextProvider initialValuesForTesting={testValues}>
    81            <TestConsumer labelName="test" />
    82          </ResourceGroupsContextProvider>
    83        )
    84        clickButton()
    85  
    86        expect(labelState()).toBe(JSON.stringify({ expanded: false }))
    87      })
    88  
    89      it("sets expanded to `false` if a group isn't saved yet and is toggled", () => {
    90        wrapper = renderContainer(
    91          <ResourceGroupsContextProvider>
    92            <TestConsumer labelName="a-non-existent-group" />
    93          </ResourceGroupsContextProvider>
    94        )
    95        clickButton()
    96  
    97        expect(labelState()).toBe(JSON.stringify({ expanded: false }))
    98      })
    99    })
   100  
   101    describe("getGroup", () => {
   102      it("returns the correct state of a resource group", () => {
   103        const testValues = { frontend: { expanded: false } }
   104        wrapper = renderContainer(
   105          <ResourceGroupsContextProvider initialValuesForTesting={testValues}>
   106            <TestConsumer labelName="frontend" />
   107          </ResourceGroupsContextProvider>
   108        )
   109  
   110        expect(labelState()).toBe(JSON.stringify({ expanded: false }))
   111      })
   112  
   113      it("returns a default state of a resource group if a group isn't saved yet", () => {
   114        const testValues = { frontend: { expanded: false } }
   115        wrapper = renderContainer(
   116          <ResourceGroupsContextProvider initialValuesForTesting={testValues}>
   117            <TestConsumer labelName="backend" />
   118          </ResourceGroupsContextProvider>
   119        )
   120  
   121        expect(labelState()).toBe(JSON.stringify(DEFAULT_GROUP_STATE))
   122      })
   123    })
   124  
   125    it("memoizes renders", () => {
   126      let renderCount = 0
   127      let toggleGroupExpanded: any
   128      let FakeEl = React.memo(() => {
   129        let context = useResourceGroups()
   130        toggleGroupExpanded = context.toggleGroupExpanded
   131        renderCount++
   132        return <div></div>
   133      })
   134  
   135      let tree = () => {
   136        const init = { frontend: { expanded: false } }
   137        return (
   138          <ResourceGroupsContextProvider initialValuesForTesting={init}>
   139            <FakeEl />
   140          </ResourceGroupsContextProvider>
   141        )
   142      }
   143  
   144      let { rerender } = render(tree())
   145      expect(renderCount).toEqual(1)
   146  
   147      // Make sure we don't re-render
   148      rerender(tree())
   149      expect(renderCount).toEqual(1)
   150  
   151      act(() => toggleGroupExpanded("frontend"))
   152      expect(renderCount).toEqual(2)
   153    })
   154  })
   155  
   156  function renderContainer(x: any) {
   157    let { container } = render(x)
   158    return container
   159  }