Compare commits

...

3 Commits

Author SHA1 Message Date
Nikolas Garza
8a85ca0261 remove unit tests that just check for classes....will use e2e for full validation 2025-10-21 15:07:31 -07:00
Nikolas Garza
32eb1becce address cubic comments 2025-10-21 14:57:38 -07:00
Nikolas Garza
fe2f72f458 projects sidebar enhancements 2025-10-21 14:37:37 -07:00
6 changed files with 213 additions and 15 deletions

View File

@@ -90,9 +90,7 @@ module.exports = {
testEnvironment: "jsdom",
testMatch: [
// React component integration tests
"**/src/app/**/*.test.tsx",
"**/src/components/**/*.test.tsx",
"**/src/lib/**/*.test.tsx",
"**/src/**/*.test.tsx",
// Add more patterns here as you add more integration tests
],
},

View File

@@ -6,9 +6,16 @@ import { AgentIcon } from "@/refresh-components/AgentIcon";
import Text from "@/refresh-components/texts/Text";
import { useAgentsContext } from "@/refresh-components/contexts/AgentsContext";
import { useMemo } from "react";
import Button from "@/refresh-components/buttons/Button";
import SvgFolderPlus from "@/icons/folder-plus";
import {
useChatModal,
ModalIds,
} from "@/refresh-components/contexts/ChatModalContext";
export default function WelcomeMessage() {
const { currentAgent } = useAgentsContext();
const { toggleModal } = useChatModal();
// If no agent is active OR the current agent is the default one, we show the Onyx logo.
const isDefaultAgent = !currentAgent || currentAgent.id === 0;
@@ -24,7 +31,8 @@ export default function WelcomeMessage() {
"flex-col",
"items-center",
"justify-center",
"mb-6"
"mb-6",
"gap-4"
)}
>
<div className="flex items-center">
@@ -46,6 +54,19 @@ export default function WelcomeMessage() {
</div>
)}
</div>
<Button
tertiary
onClick={() => toggleModal(ModalIds.CreateProjectModal, true)}
data-testid="new-project-button"
className="hover:bg-background-tint-03"
>
<div className="flex flex-row gap-1 items-center">
<SvgFolderPlus className="h-4 w-4 stroke-text-03" />
<Text text03 mainUiAction>
New Project
</Text>
</div>
</Button>
</div>
);
}

View File

@@ -449,15 +449,17 @@ function AppSidebarInner() {
<ProjectFolderButton key={project.id} project={project} />
))}
<SidebarTab
leftIcon={SvgFolderPlus}
onClick={() =>
toggleModal(ModalIds.CreateProjectModal, true)
}
lowlight
>
New Project
</SidebarTab>
{projects.length === 0 && (
<SidebarTab
leftIcon={SvgFolderPlus}
onClick={() =>
toggleModal(ModalIds.CreateProjectModal, true)
}
lowlight
>
New Project
</SidebarTab>
)}
</SidebarSection>
{/* Recents */}

View File

@@ -149,6 +149,7 @@ function ProjectFolderButtonInner({ project }: ProjectFolderProps) {
params(SEARCH_PARAM_NAMES.PROJECT_ID) === String(project.id)
}
onClick={handleTextClick}
className="hover:!bg-background-tint-03"
rightChildren={
<>
<PopoverTrigger asChild onClick={noProp()}>

View File

@@ -18,12 +18,16 @@ export function SidebarSection({
className,
}: SidebarSectionProps) {
return (
<div className={cn("flex flex-col gap-spacing-inline", className)}>
<div className={cn("flex flex-col gap-spacing-inline group", className)}>
<div className="px-spacing-interline sticky top-[0rem] bg-background-tint-02 z-10 flex flex-row items-center justify-between">
<Text secondaryBody text02>
{title}
</Text>
{action && <div className="flex-shrink-0">{action}</div>}
{action && (
<div className="flex-shrink-0 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity duration-150">
{action}
</div>
)}
</div>
<div className="flex flex-col">{children}</div>
</div>

View File

@@ -0,0 +1,172 @@
import { test, expect } from "@chromatic-com/playwright";
import { loginAsRandomUser } from "../utils/auth";
test.describe("New Project Button in WelcomeMessage", () => {
test("should display New Project button in welcome message", async ({
page,
}) => {
// Clear cookies and login as a random user
await page.context().clearCookies();
await loginAsRandomUser(page);
// Navigate to the chat page (should show WelcomeMessage with no project selected)
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
// Verify WelcomeMessage is visible
const welcomeMessage = page.getByTestId("chat-intro");
await expect(welcomeMessage).toBeVisible();
// Verify the Onyx logo is displayed (default agent)
const onyxLogo = page.getByTestId("onyx-logo");
await expect(onyxLogo).toBeVisible();
// Verify the New Project button exists and is visible
const newProjectButton = page.getByTestId("new-project-button");
await expect(newProjectButton).toBeVisible();
// Verify button has correct text
await expect(newProjectButton).toContainText("New Project");
});
test("should open CreateProjectModal when New Project button is clicked", async ({
page,
}) => {
// Clear cookies and login
await page.context().clearCookies();
await loginAsRandomUser(page);
// Navigate to chat page
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
// Click the New Project button
const newProjectButton = page.getByTestId("new-project-button");
await newProjectButton.click();
// Wait for modal to appear
await page.waitForTimeout(500);
// Verify CreateProjectModal is visible
// The modal should have a title "Create New Project"
const modalTitle = page.getByText("Create New Project");
await expect(modalTitle).toBeVisible();
// Verify the input field for project name is visible
const projectNameInput = page.getByPlaceholder("What are you working on?");
await expect(projectNameInput).toBeVisible();
});
test("should create a new project from welcome screen", async ({ page }) => {
// Clear cookies and login
await page.context().clearCookies();
await loginAsRandomUser(page);
// Navigate to chat page
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
// Click the New Project button
const newProjectButton = page.getByTestId("new-project-button");
await newProjectButton.click();
// Wait for modal to appear
await page.waitForTimeout(500);
// Enter project name
const projectName = `E2E Test Project ${Date.now()}`;
const projectNameInput = page.getByPlaceholder("What are you working on?");
await projectNameInput.fill(projectName);
// Submit the form (press Enter or click submit button)
await projectNameInput.press("Enter");
// Wait for navigation to the new project
await page.waitForURL(/projectid=/, { timeout: 10000 });
// Verify URL contains projectid parameter
expect(page.url()).toContain("projectid=");
// Verify WelcomeMessage is no longer visible
const welcomeMessage = page.getByTestId("chat-intro");
await expect(welcomeMessage).not.toBeVisible();
// Verify project name appears on the page (in the ProjectContextPanel)
await expect(page.getByText(projectName)).toBeVisible();
// Verify Files section is visible in ProjectContextPanel
await expect(page.getByText("Files")).toBeVisible();
await expect(
page.getByText("Chats in this project can access these files.")
).toBeVisible();
});
test("should not show WelcomeMessage when project is selected", async ({
page,
}) => {
// Clear cookies and login
await page.context().clearCookies();
await loginAsRandomUser(page);
// Navigate to chat page
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
// Create a project using the sidebar button first
const newProjectButton = page.getByTestId("new-project-button");
await newProjectButton.click();
await page.waitForTimeout(500);
const projectName = `E2E Test Project ${Date.now()}`;
const projectNameInput = page.getByPlaceholder("What are you working on?");
await projectNameInput.fill(projectName);
await projectNameInput.press("Enter");
// Wait for project to be created and URL to update
await page.waitForURL(/projectid=/, { timeout: 10000 });
// Verify WelcomeMessage is not visible (ProjectContextPanel should be shown instead)
const welcomeMessage = page.getByTestId("chat-intro");
await expect(welcomeMessage).not.toBeVisible();
// Verify New Project button from welcome message is not visible
const welcomeNewProjectButton = page.getByTestId("new-project-button");
await expect(welcomeNewProjectButton).not.toBeVisible();
});
test("should show WelcomeMessage again when returning to chat without project", async ({
page,
}) => {
// Clear cookies and login
await page.context().clearCookies();
await loginAsRandomUser(page);
// Create a project first
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
const newProjectButton = page.getByTestId("new-project-button");
await newProjectButton.click();
await page.waitForTimeout(500);
const projectName = `E2E Test Project ${Date.now()}`;
const projectNameInput = page.getByPlaceholder("What are you working on?");
await projectNameInput.fill(projectName);
await projectNameInput.press("Enter");
// Wait for project to be created and URL to update
await page.waitForURL(/projectid=/, { timeout: 10000 });
// Navigate back to chat page without project
await page.goto("http://localhost:3000/chat");
await page.waitForLoadState("networkidle");
// Verify WelcomeMessage is visible again
const welcomeMessage = page.getByTestId("chat-intro");
await expect(welcomeMessage).toBeVisible();
// Verify New Project button is visible
const welcomeNewProjectButton = page.getByTestId("new-project-button");
await expect(welcomeNewProjectButton).toBeVisible();
});
});