Repository: streamlit/streamlit
File: frontend/app/src/App.test.tsx (TypeScript)

Code before:
        LocalStore.ACTIVE_THEME,
        JSON.stringify(cachedTheme)
      )

      // No query params
      setLocationSearch("")

      const props = getProps()
      renderApp(props)

      // Send custom theme config
      const customTheme = new CustomThemeConfig({
        primaryColor: "blue",
        light: {
          backgroundColor: "white",
        },
        dark: {
          backgroundColor: "black",
        },
      })

      sendForwardMessage("newSession", {
        ...NEW_SESSION_JSON,
        customTheme,
      })

      // Should apply cached Custom Theme Dark
      expect(props.theme.setTheme).toHaveBeenCalled()
      const appliedTheme = vi.mocked(props.theme.setTheme).mock.calls[0][0]
      expect(appliedTheme.name).toBe(CUSTOM_THEME_DARK_NAME)
    })

    it("maps embed_options to preset theme when custom theme removed", () => {
      // Mock query params with dark_theme
      setLocationSearch("?embed=true&embed_options=dark_theme")

      const props = getProps()
      renderApp(props)

      // First send custom theme
      const customTheme = new CustomThemeConfig({
        primaryColor: "blue",
        light: { backgroundColor: "white" },
        dark: { backgroundColor: "black" },
      })

      sendForwardMessage("newSession", {
        ...NEW_SESSION_JSON,
        customTheme,
      })


Review comment (suggestion):
I think we need to set the `activeTheme` to a custom theme before rendering for this test to activate the right code path:
```javascript
// Set activeTheme to a custom theme to simulate being in custom theme mode
const props = getProps()
props.theme.activeTheme = {
  name: CUSTOM_THEME_DARK_NAME,
  displayName: "Dark",
  emotion: { ...lightTheme.emotion },
  basewebTheme: lightTheme.basewebTheme,
  primitives: lightTheme.primitives,
  themeInput: { primaryColor: "blue" },
}
renderApp(props)
```
Currently, `props.theme.activeTheme` defaulted to `lightTheme` (a preset theme), so the `if (usingCustomTheme)` check was `false`

Code after:
      // Send custom theme config
      sendForwardMessage("newSession", {
        ...NEW_SESSION_JSON,
        customTheme,
      })

      // Should apply cached Custom Theme Dark
      expect(props.theme.setTheme).toHaveBeenCalled()
      const appliedTheme = vi.mocked(props.theme.setTheme).mock.calls[0][0]
      expect(appliedTheme.name).toBe(CUSTOM_THEME_DARK_NAME)
    })

    it("maps embed_options to preset theme when custom theme removed", () => {
      // Mock query params with dark_theme
      setLocationSearch("?embed=true&embed_options=dark_theme")

      const props = getProps()
      props.theme.activeTheme = {
        name: CUSTOM_THEME_DARK_NAME,
        displayName: "Dark",
        emotion: { ...darkTheme.emotion },
        basewebTheme: darkTheme.basewebTheme,
        primitives: darkTheme.primitives,
        themeInput: customTheme,
      }
      renderApp(props)

      // First send custom theme
      sendForwardMessage("newSession", {
        ...NEW_SESSION_JSON,
        customTheme,
      })

      vi.mocked(props.theme.setTheme).mockClear()

      // Then remove custom theme (send null)
      sendForwardMessage("newSession", {
        ...NEW_SESSION_JSON,
        customTheme: null,
      })

      // Should apply preset Dark theme (respecting embed_options)
      expect(props.theme.setTheme).toHaveBeenCalled()
      const appliedTheme = vi.mocked(props.theme.setTheme).mock.calls[0][0]
      expect(appliedTheme.name).toBe("Dark")
    })
  })

  describe("App theme hash change detection", () => {
    it("detects changes when sidebar config is modified", () => {
      const props = getProps()