From 0f1446b668a4653150d12d238c0a21568551db7f Mon Sep 17 00:00:00 2001 From: Sophia Yang Date: Fri, 1 May 2026 10:24:18 -0400 Subject: [PATCH 1/4] add guidecue --- apps/spruce/src/constants/cookies.ts | 1 + .../shared/GithubNavGuideCue.tsx | 42 ++++++++++++++++++ .../projectAndRepoSettings/shared/index.tsx | 44 ++++++++++--------- 3 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx diff --git a/apps/spruce/src/constants/cookies.ts b/apps/spruce/src/constants/cookies.ts index 0edcd92550..4bb01df897 100644 --- a/apps/spruce/src/constants/cookies.ts +++ b/apps/spruce/src/constants/cookies.ts @@ -18,4 +18,5 @@ export const TASK_HISTORY_INACTIVE_COMMITS_VIEW = "task-history-inactive-commits-view"; export const SEEN_TASK_REVIEW_TOOLTIP = "seen-task-review-tooltip"; export const SEEN_TEST_SELECTION_GUIDE_CUE = "seen-test-selection-guide-cue"; +export const SEEN_GITHUB_NAV_GUIDE_CUE = "seen-github-nav-guide-cue"; export const OMIT_INACTIVE_WATERFALL_BUILDS = "omit-inactive-waterfall-builds"; diff --git a/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx new file mode 100644 index 0000000000..2e59e08d9c --- /dev/null +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx @@ -0,0 +1,42 @@ +// GithubNavGuideCue.tsx +import { useState } from "react"; +import { + GuideCue, + type GuideCueProps, + TooltipAlign, +} from "@leafygreen-ui/guide-cue"; +import Cookies from "js-cookie"; +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "constants/cookies"; + +type Props = { + refEl: GuideCueProps["refEl"]; +}; + +export const GithubNavGuideCue: React.FC = ({ refEl }) => { + const [open, setOpen] = useState( + Cookies.get(SEEN_GITHUB_NAV_GUIDE_CUE) !== "true", + ); + + const close = () => { + Cookies.set(SEEN_GITHUB_NAV_GUIDE_CUE, "true", { expires: 365 }); + setOpen(false); + }; + + return ( + + GitHub-related settings like Pull Requests, Commit Checks, and Git Tags + now live under this GitHub section. + + ); +}; diff --git a/apps/spruce/src/pages/projectAndRepoSettings/shared/index.tsx b/apps/spruce/src/pages/projectAndRepoSettings/shared/index.tsx index 0614940e04..0f216c9739 100644 --- a/apps/spruce/src/pages/projectAndRepoSettings/shared/index.tsx +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/index.tsx @@ -1,3 +1,4 @@ +import { useRef } from "react"; import styled from "@emotion/styled"; import { FormSkeleton } from "@leafygreen-ui/skeleton-loader"; import { useParams, Link, Navigate } from "react-router-dom"; @@ -24,6 +25,7 @@ import { ProjectSettingsQuery, RepoSettingsQuery } from "gql/generated/types"; import { ProjectSettingsProvider } from "./Context"; import { CreateDuplicateProjectButton } from "./CreateDuplicateProjectButton"; import { getTabTitle } from "./getTabTitle"; +import { GithubNavGuideCue } from "./GithubNavGuideCue"; import { ProjectSettingsTabs } from "./Tabs"; import { projectOnlyTabs } from "./tabs/types"; import { ProjectType } from "./tabs/utils"; @@ -79,6 +81,7 @@ const SharedSettings: React.FC = ({ const otherTabs: ProjectSettingsTabRoutes[] = [ ProjectSettingsTabRoutes.EventLog, ]; + const githubGroupRef = useRef(null); if (!tabRouteValues.includes(tab as ProjectSettingsTabRoutes)) { return ( @@ -134,7 +137,7 @@ const SharedSettings: React.FC = ({ {showNewProjectNavigation ? ( <> - {/* Grouped, collapsible nav when feature flag is on */} + {/* Grouped nav when feature flag is on */} } header="Evergreen" @@ -151,25 +154,26 @@ const SharedSettings: React.FC = ({ /> ))} - - } - header="GitHub" - > - {githubTabs.map((v) => ( - - ))} - - +
+ } + header="GitHub" + > + {githubTabs.map((v) => ( + + ))} + + +
} header="ChangeLog"> {otherTabs.map((v) => ( Date: Fri, 1 May 2026 11:04:32 -0400 Subject: [PATCH 2/4] set cookie to true for tests --- apps/spruce/cypress/support/e2e.ts | 2 ++ .../projectSettings/commit_checks.spec.ts | 21 +++++++++++++--- .../tests/projectSettings/git_tags.spec.ts | 25 ++++++++++++++----- .../tests/projectSettings/merge_queue.spec.ts | 25 ++++++++++++++----- .../projectSettings/pull_requests.spec.ts | 17 +++++++++++++ .../shared/ProjectNavbar.test.tsx | 3 +++ 6 files changed, 78 insertions(+), 15 deletions(-) diff --git a/apps/spruce/cypress/support/e2e.ts b/apps/spruce/cypress/support/e2e.ts index f1097f0419..431b680677 100644 --- a/apps/spruce/cypress/support/e2e.ts +++ b/apps/spruce/cypress/support/e2e.ts @@ -21,6 +21,7 @@ import { SEEN_TASK_HISTORY_ONBOARDING_TUTORIAL, SEEN_TASK_REVIEW_TOOLTIP, SEEN_TEST_SELECTION_GUIDE_CUE, + SEEN_GITHUB_NAV_GUIDE_CUE, } from "constants/cookies"; import { hasOperationName, isMutation } from "../utils/graphql-test-utils"; @@ -158,6 +159,7 @@ const hostMutations = ["ReprovisionToNew", "RestartJasper", "UpdateHostStatus"]; cy.setCookie(SEEN_TASK_HISTORY_ONBOARDING_TUTORIAL, "true"); cy.setCookie(SEEN_TASK_REVIEW_TOOLTIP, "true"); cy.setCookie(SEEN_TEST_SELECTION_GUIDE_CUE, "true"); + cy.setCookie(SEEN_GITHUB_NAV_GUIDE_CUE, "true"); mutationDispatched = false; clearAmboyDB = false; cy.intercept("POST", "/graphql/query", (req) => { diff --git a/apps/spruce/playwright/tests/projectSettings/commit_checks.spec.ts b/apps/spruce/playwright/tests/projectSettings/commit_checks.spec.ts index 3401cef622..6240bdadbd 100644 --- a/apps/spruce/playwright/tests/projectSettings/commit_checks.spec.ts +++ b/apps/spruce/playwright/tests/projectSettings/commit_checks.spec.ts @@ -1,11 +1,18 @@ +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "../../../src/constants/cookies"; import { test, expect } from "../../fixtures"; import { validateToast } from "../../helpers"; test.describe("Commit Checks project settings when GitHub webhooks are disabled", () => { - const origin = "/project/logkeeper/settings/commit-checks"; - test.beforeEach(async ({ authenticatedPage: page }) => { - await page.goto(origin); + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); + await page.goto("/project/logkeeper/settings/commit-checks"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", "true", @@ -37,6 +44,14 @@ test.describe("Commit Checks project settings when GitHub webhooks are disabled" test.describe("Commit Checks project settings when GitHub webhooks are enabled", () => { test.beforeEach(async ({ authenticatedPage: page }) => { + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); await page.goto("/project/spruce/settings/commit-checks"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", diff --git a/apps/spruce/playwright/tests/projectSettings/git_tags.spec.ts b/apps/spruce/playwright/tests/projectSettings/git_tags.spec.ts index f6939633ee..30d949030b 100644 --- a/apps/spruce/playwright/tests/projectSettings/git_tags.spec.ts +++ b/apps/spruce/playwright/tests/projectSettings/git_tags.spec.ts @@ -1,12 +1,19 @@ import { clickRadio } from "@evg-ui/playwright-config/helpers"; +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "../../../src/constants/cookies"; import { test, expect } from "../../fixtures"; import { validateToast } from "../../helpers"; test.describe("Git Tags project settings when GitHub webhooks are disabled", () => { - const origin = "/project/logkeeper/settings/git-tags"; - test.beforeEach(async ({ authenticatedPage: page }) => { - await page.goto(origin); + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); + await page.goto("/project/logkeeper/settings/git-tags"); await expect(page.getByTestId("save-settings-button")).toBeDisabled(); }); @@ -34,10 +41,16 @@ test.describe("Git Tags project settings when GitHub webhooks are disabled", () }); test.describe("Git Tags project settings when GitHub webhooks are enabled", () => { - const origin = "/repo/602d70a2b2373672ee493184/settings/git-tags"; - test.beforeEach(async ({ authenticatedPage: page }) => { - await page.goto(origin); + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); + await page.goto("/repo/602d70a2b2373672ee493184/settings/git-tags"); await expect(page.getByTestId("save-settings-button")).toBeDisabled(); }); diff --git a/apps/spruce/playwright/tests/projectSettings/merge_queue.spec.ts b/apps/spruce/playwright/tests/projectSettings/merge_queue.spec.ts index a90abdcb0e..9dbe93942d 100644 --- a/apps/spruce/playwright/tests/projectSettings/merge_queue.spec.ts +++ b/apps/spruce/playwright/tests/projectSettings/merge_queue.spec.ts @@ -1,11 +1,18 @@ +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "../../../src/constants/cookies"; import { test, expect } from "../../fixtures"; import { validateToast } from "../../helpers"; test.describe("Merge Queue project settings when GitHub webhooks are disabled", () => { - const origin = "/project/logkeeper/settings/merge-queue"; - test.beforeEach(async ({ authenticatedPage: page }) => { - await page.goto(origin); + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); + await page.goto("/project/logkeeper/settings/merge-queue"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", "true", @@ -36,10 +43,16 @@ test.describe("Merge Queue project settings when GitHub webhooks are disabled", }); test.describe("Merge Queue project settings when GitHub webhooks are enabled", () => { - const origin = "/project/spruce/settings/merge-queue"; - test.beforeEach(async ({ authenticatedPage: page }) => { - await page.goto(origin); + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); + await page.goto("/project/spruce/settings/merge-queue"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", "true", diff --git a/apps/spruce/playwright/tests/projectSettings/pull_requests.spec.ts b/apps/spruce/playwright/tests/projectSettings/pull_requests.spec.ts index d35b6cfab5..2b2dfbfeb5 100644 --- a/apps/spruce/playwright/tests/projectSettings/pull_requests.spec.ts +++ b/apps/spruce/playwright/tests/projectSettings/pull_requests.spec.ts @@ -1,8 +1,17 @@ +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "../../../src/constants/cookies"; import { test, expect } from "../../fixtures"; import { validateToast } from "../../helpers"; test.describe("Pull Requests project settings when GitHub webhooks are disabled", () => { test.beforeEach(async ({ authenticatedPage: page }) => { + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); await page.goto("/project/logkeeper/settings/pull-requests"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", @@ -35,6 +44,14 @@ test.describe("Pull Requests project settings when GitHub webhooks are disabled" test.describe("Pull Requests project settings when GitHub webhooks are enabled", () => { test.beforeEach(async ({ authenticatedPage: page }) => { + await page.context().addCookies([ + { + name: SEEN_GITHUB_NAV_GUIDE_CUE, + value: "true", + domain: "localhost", + path: "/", + }, + ]); await page.goto("/repo/602d70a2b2373672ee493184/settings/pull-requests"); await expect(page.getByTestId("save-settings-button")).toHaveAttribute( "aria-disabled", diff --git a/apps/spruce/src/pages/projectAndRepoSettings/shared/ProjectNavbar.test.tsx b/apps/spruce/src/pages/projectAndRepoSettings/shared/ProjectNavbar.test.tsx index 185a67abe2..19eab7999a 100644 --- a/apps/spruce/src/pages/projectAndRepoSettings/shared/ProjectNavbar.test.tsx +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/ProjectNavbar.test.tsx @@ -1,10 +1,12 @@ // TODO DEVPROD-31534: Delete this file when the feature flag is removed +import Cookies from "js-cookie"; import { vi } from "vitest"; import { renderWithRouterMatch as render, screen, userEvent, } from "@evg-ui/lib/test_utils"; +import { SEEN_GITHUB_NAV_GUIDE_CUE } from "constants/cookies"; import { ProjectType } from "./tabs/utils"; vi.mock("components/ProjectSelect", () => ({ @@ -29,6 +31,7 @@ const navItems = [ describe("Feature flag tests for DEVPROD-31534", () => { beforeEach(() => { vi.resetModules(); + Cookies.set(SEEN_GITHUB_NAV_GUIDE_CUE, "true"); }); navItems.forEach(({ dataCy, tabLabel }) => { From 815a55aec4cf4c0ccd57730bedb76c63bda33020 Mon Sep 17 00:00:00 2001 From: Sophia Yang Date: Fri, 1 May 2026 11:09:14 -0400 Subject: [PATCH 3/4] nits --- .../pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx index 2e59e08d9c..f86ac3ed53 100644 --- a/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx @@ -1,8 +1,7 @@ -// GithubNavGuideCue.tsx import { useState } from "react"; import { GuideCue, - type GuideCueProps, + GuideCueProps, TooltipAlign, } from "@leafygreen-ui/guide-cue"; import Cookies from "js-cookie"; @@ -25,7 +24,6 @@ export const GithubNavGuideCue: React.FC = ({ refEl }) => { return ( Date: Fri, 1 May 2026 11:11:43 -0400 Subject: [PATCH 4/4] nit2 --- .../pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx index f86ac3ed53..c702fb0394 100644 --- a/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx @@ -6,6 +6,7 @@ import { } from "@leafygreen-ui/guide-cue"; import Cookies from "js-cookie"; import { SEEN_GITHUB_NAV_GUIDE_CUE } from "constants/cookies"; +import { showNewProjectNavigation } from "constants/featureFlags"; type Props = { refEl: GuideCueProps["refEl"]; @@ -24,7 +25,7 @@ export const GithubNavGuideCue: React.FC = ({ refEl }) => { return (