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/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..c702fb0394 --- /dev/null +++ b/apps/spruce/src/pages/projectAndRepoSettings/shared/GithubNavGuideCue.tsx @@ -0,0 +1,41 @@ +import { useState } from "react"; +import { + GuideCue, + GuideCueProps, + TooltipAlign, +} 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"]; +}; + +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/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 }) => { 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) => (