starling-devex 0.1.2

Starling: a local dev orchestrator with a central daemon, shared named-URL proxy, and a k9s-style TUI (a Rust port of Tilt + portless)
import {
  fireEvent,
  render,
  RenderOptions,
  screen,
} from "@testing-library/react"
import { SnackbarProvider } from "notistack"
import React from "react"
import { MemoryRouter } from "react-router-dom"
import LogStore, { LogStoreProvider } from "./LogStore"
import OverviewResourcePane from "./OverviewResourcePane"
import { ResourceNavProvider } from "./ResourceNav"
import { SidebarContextProvider } from "./SidebarContext"
import { nResourceView, oneResourceView, TestDataView } from "./testdata"
import { appendLinesForManifestAndSpan, Line } from "./testlogs"
import { LogLevel, UIResource } from "./types"

function customRender(
  options: {
    logStore?: LogStore
    selectedResource?: string
    view: TestDataView
    sidebarClosed?: boolean
  },
  renderOptions?: RenderOptions
) {
  const { logStore, view, selectedResource } = options
  const routerEntry = selectedResource
    ? `/r/${selectedResource}/overview`
    : "/overview"
  const validateResource = (name: string) =>
    view.uiResources?.some((res) => res.metadata?.name == name)

  return render(<OverviewResourcePane view={view} isSocketConnected={true} />, {
    wrapper: ({ children }) => (
      <MemoryRouter
        initialEntries={[routerEntry]}
        future={{ v7_startTransition: true, v7_relativeSplatPath: true }}
      >
        <LogStoreProvider value={logStore ?? new LogStore()}>
          <SnackbarProvider>
            <ResourceNavProvider validateResource={validateResource}>
              <SidebarContextProvider
                sidebarClosedForTesting={options.sidebarClosed}
              >
                {children}
              </SidebarContextProvider>
            </ResourceNavProvider>
          </SnackbarProvider>
        </LogStoreProvider>
      </MemoryRouter>
    ),
    ...renderOptions,
  })
}

describe("OverviewResourcePane", () => {
  it("renders 'not found' message when trying to view a resource that doesn't exist", () => {
    customRender({ selectedResource: "does-not-exist", view: nResourceView(2) })

    expect(screen.getByText("No resource 'does-not-exist'")).toBeInTheDocument()
  })

  it("renders 'Resource: <name>' title row for selected resource when sidebar is closed", () => {
    customRender({
      selectedResource: "_0",
      view: nResourceView(2),
      sidebarClosed: true,
    })

    expect(screen.getByText("Resource: _0")).toBeInTheDocument()
  })

  it("icon button toggles sidebar open/closed, non-selected resources should not be visible when closed", () => {
    customRender({ selectedResource: "_0", view: nResourceView(2) })

    expect(screen.getByText("_1")).toBeInTheDocument()

    const clickEvent = new MouseEvent("click", { bubbles: true })
    fireEvent(screen.getByLabelText("Collapse sidebar"), clickEvent)
    expect(screen.queryAllByText("_1")).toHaveLength(0)

    fireEvent(screen.getByLabelText("Expand sidebar"), clickEvent)
    expect(screen.getByText("_1")).toBeInTheDocument()
  })
})

describe("alert filtering", () => {
  const doTest = (
    expectedErrs: number,
    expectedWarns: number,
    prepare: (logStore: LogStore, r: UIResource) => any
  ) => {
    const logStore = new LogStore()
    const view = oneResourceView()

    const r = view.uiResources[0]

    prepare(logStore, r)

    customRender({ view, logStore, selectedResource: r.metadata?.name })

    const errorFilterButton = screen.getByRole("button", { name: /errors/i })
    const warningFilterButton = screen.getByRole("button", {
      name: /warnings/i,
    })

    expect(errorFilterButton).toHaveTextContent(`Errors (${expectedErrs})`)
    expect(warningFilterButton).toHaveTextContent(`Warnings (${expectedWarns})`)
  }

  it("creates no alerts if no build failures", () => {
    doTest(0, 0, (logStore, r) => {
      const latestBuild = r.status!.buildHistory![0] || {}
      latestBuild.spanID = "build:1"
      latestBuild.error = undefined
      latestBuild.warnings = []

      appendLinesForManifestAndSpan(logStore, r.metadata!.name!, "build:1", [
        "the build is ok!\n",
      ])
    })
  })

  it("creates alerts for build failures with existing spans", () => {
    doTest(1, 2, (logStore, r) => {
      const latestBuild = r.status!.buildHistory![0]
      latestBuild.spanID = "build:1"
      latestBuild.error = "the build failed!"
      latestBuild.warnings = ["warning 1!", "warning 2!"]

      appendLinesForManifestAndSpan(logStore, r.metadata!.name!, "build:1", [
        { level: LogLevel.WARN, anchor: true, text: "warning 1!\n" } as Line,
        { level: LogLevel.WARN, anchor: true, text: "warning 2!\n" } as Line,
        {
          level: LogLevel.ERROR,
          anchor: true,
          text: "the build failed!\n",
        } as Line,
      ])
    })
  })

  it("ignores alerts for removed spans", () => {
    doTest(0, 0, (logStore, r) => {
      const latestBuild = r.status!.buildHistory![0] || {}
      latestBuild.spanID = "build:1"
      latestBuild.error = "the build failed!"
      latestBuild.warnings = ["warning!"]

      appendLinesForManifestAndSpan(logStore, r.metadata!.name!, "build:2", [
        { level: LogLevel.WARN, anchor: true, text: "warning!\n" } as Line,
        {
          level: LogLevel.ERROR,
          anchor: true,
          text: "the build failed!\n",
        } as Line,
      ])
    })
  })
})