Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions apps/desktop/src/changelog/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
chat: {
mode: "FloatingClosed",
sendEvent: vi.fn(),
},
close: vi.fn(),
leftsidebar: {
expanded: true,
},
sidebarTimelineEnabled: false,
}));

vi.mock("@hypr/changelog", () => ({
ChangelogContent: ({ content }: { content: string }) => <div>{content}</div>,
}));

vi.mock("@hypr/plugin-opener2", () => ({
commands: {
openUrl: vi.fn(),
},
}));

vi.mock("./data", () => ({
useChangelogContent: () => ({
content: "Release notes",
loading: false,
}),
}));

vi.mock("~/contexts/shell", () => ({
useShell: () => ({
chat: mocks.chat,
leftsidebar: mocks.leftsidebar,
}),
}));

vi.mock("~/shared/config", () => ({
useConfigValue: () => mocks.sidebarTimelineEnabled,
}));

vi.mock("~/shared/main", () => ({
StandardTabWrapper: ({ children }: { children: React.ReactNode }) => (
<div>{children}</div>
),
}));

vi.mock("~/store/zustand/tabs", () => ({
useTabs: (selector: (state: { close: typeof mocks.close }) => unknown) =>
selector({ close: mocks.close }),
}));

import { TabContentChangelog } from "./index";

import type { Tab } from "~/store/zustand/tabs";

describe("TabContentChangelog", () => {
beforeEach(() => {
mocks.chat.mode = "FloatingClosed";
mocks.chat.sendEvent.mockClear();
mocks.close.mockClear();
mocks.leftsidebar.expanded = true;
mocks.sidebarTimelineEnabled = false;
});

afterEach(() => {
cleanup();
});

it("adds the note header gutter when sidebar timeline mode is collapsed", () => {
mocks.sidebarTimelineEnabled = true;
mocks.leftsidebar.expanded = false;

render(<TabContentChangelog tab={buildChangelogTab()} />);

expect(getHeader().className).toContain("pl-[156px]");
});

it("does not add the collapsed sidebar gutter while the left sidebar is expanded", () => {
mocks.sidebarTimelineEnabled = true;

render(<TabContentChangelog tab={buildChangelogTab()} />);

expect(getHeader().className).not.toContain("pl-[156px]");
});
});

function getHeader() {
const heading = screen.getByRole("heading", {
name: "What's new in 1.0.36?",
});

return heading.parentElement?.parentElement?.parentElement as HTMLElement;
}

function buildChangelogTab(): Extract<Tab, { type: "changelog" }> {
return {
active: true,
pinned: false,
slotId: "slot-1",
state: {
current: "1.0.36",
previous: null,
},
type: "changelog",
};
}
22 changes: 19 additions & 3 deletions apps/desktop/src/changelog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { XIcon } from "lucide-react";
import { ChangelogContent } from "@hypr/changelog";
import { commands as openerCommands } from "@hypr/plugin-opener2";
import { Button } from "@hypr/ui/components/ui/button";
import { cn } from "@hypr/utils";

import { useChangelogContent } from "./data";

import { useShell } from "~/contexts/shell";
import { useConfigValue } from "~/shared/config";
import { useMountEffect } from "~/shared/hooks/useMountEffect";
import { StandardTabWrapper } from "~/shared/main";
import { type Tab, useTabs } from "~/store/zustand/tabs";
Expand All @@ -19,8 +21,11 @@ export function TabContentChangelog({
tab: Extract<Tab, { type: "changelog" }>;
}) {
const { current } = tab.state;
const { chat } = useShell();
const { chat, leftsidebar } = useShell();
const close = useTabs((state) => state.close);
const sidebarTimelineEnabled = useConfigValue("sidebar_timeline_enabled");
const showSidebarTimelineHeaderGutter =
sidebarTimelineEnabled && !leftsidebar.expanded;

useMountEffect(() => {
if (chat.mode !== "FloatingClosed") {
Expand All @@ -34,7 +39,11 @@ export function TabContentChangelog({
<StandardTabWrapper>
<div className="flex h-full flex-col">
<div className="shrink-0 pr-1 pl-3">
<ChangelogHeader version={current} onClose={() => close(tab)} />
<ChangelogHeader
version={current}
showSidebarTimelineHeaderGutter={showSidebarTimelineHeaderGutter}
onClose={() => close(tab)}
/>
</div>

<div className="relative mt-2 min-h-0 flex-1 overflow-hidden">
Expand Down Expand Up @@ -107,14 +116,21 @@ function ChangelogBody({
}

function ChangelogHeader({
showSidebarTimelineHeaderGutter,
version,
onClose,
}: {
showSidebarTimelineHeaderGutter: boolean;
version: string;
onClose: () => void;
}) {
return (
<div className="flex h-12 w-full items-center">
<div
className={cn([
"flex h-12 w-full items-center",
showSidebarTimelineHeaderGutter && "pl-[156px]",
])}
>
<div className="flex w-full min-w-0 items-center justify-between gap-0">
<div className="min-w-0 flex-1">
<h1 className="truncate text-xl font-semibold text-neutral-900">
Expand Down
Loading