github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/OverviewSidebarOptions.test.tsx (about)

     1  import { render, screen } from "@testing-library/react"
     2  import userEvent from "@testing-library/user-event"
     3  import React, { ReactElement } from "react"
     4  import { MemoryRouter } from "react-router"
     5  import { AnalyticsAction, AnalyticsType } from "./analytics"
     6  import {
     7    cleanupMockAnalyticsCalls,
     8    expectIncrs,
     9    mockAnalyticsCalls,
    10  } from "./analytics_test_helpers"
    11  import { accessorsForTesting, tiltfileKeyContext } from "./BrowserStorage"
    12  import Features, { FeaturesTestProvider, Flag } from "./feature"
    13  import {
    14    TenResourcesWithLabels,
    15    TestsWithErrors,
    16    TwoResourcesTwoTests,
    17  } from "./OverviewResourceSidebar.stories"
    18  import { OverviewSidebarOptionsRoot } from "./OverviewSidebarOptions"
    19  import { ResourceGroupsContextProvider } from "./ResourceGroupsContext"
    20  import {
    21    DEFAULT_OPTIONS,
    22    ResourceListOptions,
    23    ResourceListOptionsProvider,
    24    RESOURCE_LIST_OPTIONS_KEY,
    25  } from "./ResourceListOptionsContext"
    26  import { ResourceNameFilterTextField } from "./ResourceNameFilter"
    27  import { SidebarItemNameRoot, SidebarItemRoot } from "./SidebarItemView"
    28  import {
    29    SidebarListSectionItemsRoot,
    30    SidebarResourcesRoot,
    31  } from "./SidebarResources"
    32  
    33  const resourceListOptionsAccessor = accessorsForTesting<ResourceListOptions>(
    34    RESOURCE_LIST_OPTIONS_KEY,
    35    sessionStorage
    36  )
    37  /**
    38   * TODO (lizz): These tests behave more like integration tests
    39   * and test the SidebarOptions component within the larger `SidebarResources`
    40   * component. The tests should be moved over to that component's test suite
    41   * and refactored with the react-testing-library changes.
    42   */
    43  
    44  function assertSidebarItemsAndOptions(
    45    root: HTMLElement,
    46    names: string[],
    47    expectAlertsOnTop: boolean,
    48    expectedResourceNameFilter?: string
    49  ) {
    50    let sidebar = Array.from(root.querySelectorAll(SidebarResourcesRoot))
    51    expect(sidebar).toHaveLength(1)
    52  
    53    // only check items in the "all resources" section, i.e. don't look at starred things
    54    // or we'll have duplicates
    55    let all = sidebar[0].querySelector(SidebarListSectionItemsRoot)!
    56    let items = Array.from(all.querySelectorAll(SidebarItemRoot))
    57    const observedNames = items.map(
    58      (i) => i.querySelector(SidebarItemNameRoot)?.textContent
    59    )
    60    expect(observedNames).toEqual(names)
    61  
    62    let optSetter = Array.from(
    63      sidebar[0].querySelectorAll(OverviewSidebarOptionsRoot)
    64    )
    65    expect(optSetter).toHaveLength(1)
    66  
    67    let checkbox = optSetter[0].querySelector(
    68      "input[type=checkbox]"
    69    ) as HTMLInputElement
    70    expect(checkbox.checked).toEqual(expectAlertsOnTop)
    71    if (expectedResourceNameFilter !== undefined) {
    72      expect(
    73        optSetter[0].querySelector(ResourceNameFilterTextField)!.textContent
    74      ).toEqual(expectedResourceNameFilter)
    75    }
    76  }
    77  
    78  beforeEach(() => {
    79    mockAnalyticsCalls()
    80  })
    81  
    82  afterEach(() => {
    83    cleanupMockAnalyticsCalls()
    84    localStorage.clear()
    85    resourceListOptionsAccessor.set({
    86      ...DEFAULT_OPTIONS,
    87    })
    88  })
    89  
    90  function renderContainer(x: ReactElement) {
    91    const features = new Features({
    92      [Flag.Labels]: true,
    93    })
    94    const { container } = render(
    95      <MemoryRouter>
    96        <FeaturesTestProvider value={features}>
    97          <tiltfileKeyContext.Provider value="test">
    98            <ResourceGroupsContextProvider>
    99              <ResourceListOptionsProvider>{x}</ResourceListOptionsProvider>
   100            </ResourceGroupsContextProvider>
   101          </tiltfileKeyContext.Provider>
   102        </FeaturesTestProvider>
   103      </MemoryRouter>
   104    )
   105    return container
   106  }
   107  
   108  describe("overview sidebar options", () => {
   109    it("says no matches found", () => {
   110      resourceListOptionsAccessor.set({
   111        ...DEFAULT_OPTIONS,
   112        resourceNameFilter: "asdfawfwef",
   113      })
   114      const container = renderContainer(<TwoResourcesTwoTests />)
   115      const resourceSectionItems = Array.from(
   116        container
   117          .querySelector(SidebarListSectionItemsRoot)!
   118          .querySelectorAll("li")
   119      )
   120      expect(resourceSectionItems.map((n) => n.textContent)).toEqual([
   121        "No matching resources",
   122      ])
   123    })
   124  })
   125  
   126  it("toggles/untoggles Alerts On Top sorting when button clicked", () => {
   127    const { container } = render(TestsWithErrors())
   128  
   129    const origOrder = [
   130      "(Tiltfile)",
   131      "test_0",
   132      "test_1",
   133      "test_2",
   134      "test_3",
   135      "test_4",
   136      "test_5",
   137      "test_6",
   138      "test_7",
   139    ]
   140    const alertsOnTopOrder = [
   141      "test_0",
   142      "test_2",
   143      "test_4",
   144      "test_6",
   145      "(Tiltfile)",
   146      "test_1",
   147      "test_3",
   148      "test_5",
   149      "test_7",
   150    ]
   151    assertSidebarItemsAndOptions(container, origOrder, false)
   152  
   153    let aotToggle = screen.getByLabelText("Alerts on top")
   154    userEvent.click(aotToggle)
   155  
   156    assertSidebarItemsAndOptions(container, alertsOnTopOrder, true)
   157  
   158    userEvent.click(aotToggle)
   159    assertSidebarItemsAndOptions(container, origOrder, false)
   160  })
   161  
   162  describe("expand-all button", () => {
   163    it("sends analytics onclick", () => {
   164      const container = renderContainer(<TenResourcesWithLabels />)
   165      userEvent.click(screen.getByTitle("Expand All"))
   166      expectIncrs({
   167        name: "ui.web.expandAllGroups",
   168        tags: { action: AnalyticsAction.Click, type: AnalyticsType.Detail },
   169      })
   170    })
   171  })
   172  
   173  describe("collapse-all button", () => {
   174    it("sends analytics onclick", () => {
   175      const container = renderContainer(<TenResourcesWithLabels />)
   176      userEvent.click(screen.getByTitle("Collapse All"))
   177      expectIncrs({
   178        name: "ui.web.collapseAllGroups",
   179        tags: { action: AnalyticsAction.Click, type: AnalyticsType.Detail },
   180      })
   181    })
   182  })