diff --git a/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.jsx b/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.jsx index d7dba39e6a..281a406570 100644 --- a/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.jsx +++ b/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.jsx @@ -5,6 +5,8 @@ import { pullFileviewString, pullTreeviewString, } from 'pages/PullRequestPage/utils' +import { useRepoSettings } from 'services/repo' +import { TierNames, useTier } from 'services/tier' import { useFlags } from 'shared/featureFlags' import ToggleHeader from 'ui/FileViewer/ToggleHeader' import TabNavigation from 'ui/TabNavigation' @@ -19,12 +21,15 @@ function PullRequestPageTabs() { directChangedFilesCount, commitsCount, } = useTabsCounts() - const { pullRequestPageFlagMultiSelect } = useFlags({ + const { data: settings, isLoading: settingsLoading } = useRepoSettings() + const { pullRequestPageFlagMultiSelect, multipleTiers } = useFlags({ pullRequestPageFlagMultiSelect: false, + multipleTiers: false, }) const { pathname, search } = useLocation() const { provider, owner, repo, pullId } = useParams() + const { data: tierData, isLoading } = useTier({ provider, owner }) const searchParams = qs.parse(search, { ignoreQueryPrefix: true }) const flags = searchParams?.flags ?? [] @@ -43,6 +48,57 @@ function PullRequestPageTabs() { } } + if (isLoading || settingsLoading) { + return null + } + + if ( + multipleTiers && + tierData === TierNames.TEAM && + settings?.repository?.private + ) { + return ( + + Files changed + {directChangedFilesCount} + + ), + options: { queryParams: { flags } }, + exact: true, + }, + { + pageName: 'pullCommits', + children: ( + <> + Commits + {commitsCount} + + ), + options: { queryParams: { flags } }, + }, + { + pageName: 'pullTreeView', + children: 'File explorer', + options: { pullId, queryParams: { flags } }, + location: customLocation, + }, + ]} + component={ + + } + /> + ) + } + return ( } /> diff --git a/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.spec.jsx b/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.spec.jsx index 6412700a29..7e923fb303 100644 --- a/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.spec.jsx +++ b/src/pages/PullRequestPage/PullRequestPageTabs/PullRequestPageTabs.spec.jsx @@ -4,6 +4,7 @@ import { graphql } from 'msw' import { setupServer } from 'msw/node' import { MemoryRouter, Route } from 'react-router-dom' +import { TierNames } from 'services/tier' import { useFlags } from 'shared/featureFlags' import PullRequestPageTabs from './PullRequestPageTabs' @@ -22,10 +23,8 @@ const mockCommits = { const mockPullData = { owner: { - isCurrentUserPartOfOrg: true, repository: { __typename: 'Repository', - private: true, pull: { pullId: 1, head: { @@ -82,22 +81,44 @@ afterAll(() => { describe('PullRequestPageTabs', () => { function setup( - { pullRequestPageFlagMultiSelect = false } = { + { + pullRequestPageFlagMultiSelect = false, + multipleTiers = false, + tierValue = TierNames.BASIC, + privateRepo = false, + } = { pullRequestPageFlagMultiSelect: false, + multipleTiers: false, + tierValue: TierNames.BASIC, + privateRepo: false, } ) { useFlags.mockReturnValue({ pullRequestPageFlagMultiSelect, + multipleTiers, }) server.use( - graphql.query('PullPageData', (req, res, ctx) => - res(ctx.status(200), ctx.data(mockPullData)) - ), + graphql.query('PullPageData', (req, res, ctx) => { + return res(ctx.status(200), ctx.data(mockPullData)) + }), graphql.query('GetCommits', (req, res, ctx) => res(ctx.status(200), ctx.data(mockCommits)) ), - graphql.query('BackfillFlagMemberships', (req, res, ctx) => - res(ctx.status(200), ctx.data({})) + graphql.query('OwnerTier', (req, res, ctx) => + res( + ctx.status(200), + ctx.data({ + owner: { plan: { tierName: tierValue.toLowerCase() } }, + }) + ) + ), + graphql.query('GetRepoSettings', (req, res, ctx) => + res( + ctx.status(200), + ctx.data({ + owner: { repository: { private: privateRepo } }, + }) + ) ) ) } @@ -300,16 +321,654 @@ describe('PullRequestPageTabs', () => { }) }) - // describe('flags select dropdown', () => { - // beforeEach(() => setup({ pullRequestPageFlagMultiSelect: true })) + describe('Team plan', () => { + describe('with pullRequestPageFlagMultiSelect flag', () => { + describe('with multiple tiers flag', () => { + describe('is a team plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: true, + privateRepo: false, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = await screen.findByText('Search for Flags') + expect(flagSelect).toBeInTheDocument() + }) + }) + + describe('is a team plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = screen.queryByText('Indirect changes') + expect(indirect).not.toBeInTheDocument() + + const flags = screen.queryByText('Flags') + expect(flags).not.toBeInTheDocument() + + const componentsTab = screen.queryByText('Components') + expect(componentsTab).not.toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: true, + privateRepo: false, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = await screen.findByText('Search for Flags') + expect(flagSelect).toBeInTheDocument() + }) + }) + + describe('is a pro plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + }) + describe('with out multiple tiers flag', () => { + describe('is a team plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: false, + privateRepo: false, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = await screen.findByText('Search for Flags') + expect(flagSelect).toBeInTheDocument() + }) + }) + + describe('is a team plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: false, + privateRepo: true, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: false, + privateRepo: false, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = await screen.findByText('Search for Flags') + expect(flagSelect).toBeInTheDocument() + }) + }) + + describe('is a pro plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: false, + privateRepo: true, + pullRequestPageFlagMultiSelect: true, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + }) + }) + }) + describe('with out pullRequestPageFlagMultiSelect flag', () => { + describe('with multiple tiers flag', () => { + describe('is a team plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: true, + privateRepo: false, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) - // it('renders flags select dropdown', async () => { - // render(, { wrapper: wrapper() }) + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) - // const multiSelect = await screen.findByRole('button', { - // name: 'All Flags', - // }) - // expect(multiSelect).toBeInTheDocument() - // }) - // }) + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a team plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = screen.queryByText('Indirect changes') + expect(indirect).not.toBeInTheDocument() + + const flags = screen.queryByText('Flags') + expect(flags).not.toBeInTheDocument() + + const componentsTab = screen.queryByText('Components') + expect(componentsTab).not.toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: true, + privateRepo: false, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + }) + describe('with out multiple tiers flag', () => { + describe('is a team plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: false, + privateRepo: false, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a team plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.TEAM, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = screen.queryByText('Indirect changes') + expect(indirect).not.toBeInTheDocument() + + const flags = screen.queryByText('Flags') + expect(flags).not.toBeInTheDocument() + + const componentsTab = screen.queryByText('Components') + expect(componentsTab).not.toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a public repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: false, + privateRepo: false, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + + describe('is a pro plan on a private repo', () => { + beforeEach(() => + setup({ + tierValue: TierNames.PRO, + multipleTiers: true, + privateRepo: true, + pullRequestPageFlagMultiSelect: false, + }) + ) + + it('renders correct tabs', async () => { + render(, { wrapper: wrapper() }) + + const components = await screen.findByText('Files changed') + expect(components).toBeInTheDocument() + + const commits = await screen.findByText('Commits') + expect(commits).toBeInTheDocument() + + const explorer = await screen.findByText('File explorer') + expect(explorer).toBeInTheDocument() + + const indirect = await screen.findByText('Indirect changes') + expect(indirect).toBeInTheDocument() + + const flags = await screen.findByText('Flags') + expect(flags).toBeInTheDocument() + + const componentsTab = await screen.findByText('Components') + expect(componentsTab).toBeInTheDocument() + }) + + it('does not render the flag select', async () => { + render(, { wrapper: wrapper() }) + + const flagSelect = screen.queryByText('Search for Flags') + expect(flagSelect).not.toBeInTheDocument() + }) + }) + }) + }) }) diff --git a/src/pages/PullRequestPage/PullRequestPageTabs/hooks/useTabsCounts.spec.js b/src/pages/PullRequestPage/PullRequestPageTabs/hooks/useTabsCounts.spec.js index 0a3316569d..d7bd78b5f6 100644 --- a/src/pages/PullRequestPage/PullRequestPageTabs/hooks/useTabsCounts.spec.js +++ b/src/pages/PullRequestPage/PullRequestPageTabs/hooks/useTabsCounts.spec.js @@ -36,7 +36,6 @@ const mockPullData = { isCurrentUserPartOfOrg: true, repository: { __typename: 'Repository', - private: true, pull: { pullId: 1, head: { diff --git a/src/pages/PullRequestPage/PullRequestPageTabs/index.js b/src/pages/PullRequestPage/PullRequestPageTabs/index.ts similarity index 100% rename from src/pages/PullRequestPage/PullRequestPageTabs/index.js rename to src/pages/PullRequestPage/PullRequestPageTabs/index.ts