diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.tsx
index 32190faf2d..14d63772f6 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/FailedTestsTable/FailedTestsTable.tsx
@@ -235,13 +235,13 @@ const FailedTestsTable = () => {
},
})
- const [isDefaultBranch, setIsDefaultBranch] = useState(false)
+ const [showResetButton, setShowResetButton] = useState(false)
const [isTeamOrFreePlan, setIsTeamOrFreePlan] = useState(false)
const [isPrivate, setIsPrivate] = useState(false)
useEffect(() => {
if (testData?.defaultBranch) {
- setIsDefaultBranch(testData.defaultBranch === branch)
+ setShowResetButton(testData.defaultBranch === branch || !branch)
}
}, [testData?.defaultBranch, branch])
@@ -258,7 +258,7 @@ const FailedTestsTable = () => {
}, [testData?.private])
const hideFlakeRate =
- (isTeamOrFreePlan && isPrivate) || (!!branch && !isDefaultBranch)
+ (isTeamOrFreePlan && isPrivate) || (!!branch && !showResetButton)
const tableData = useMemo(() => {
if (!testData?.testResults) return []
@@ -325,30 +325,35 @@ const FailedTestsTable = () => {
}
}, [fetchNextPage, inView, hasNextPage])
- if (testData?.isFirstPullRequest && testData.totalCount === 0) {
+ if (
+ testData?.isFirstPullRequest &&
+ testData.totalCount === 0 &&
+ branch === testData?.defaultBranch
+ ) {
return (
No data yet
- To see data for the main branch, merge your PR into the main branch.
+ To see data for the {testData?.defaultBranch} branch, merge your PR
+ into the {testData?.defaultBranch} branch.
)
}
- if (testData.totalCount === 0 && !isLoading && !!branch) {
+ if (testData.totalCount === 0 && !isLoading) {
return (
No test results found
@@ -363,7 +368,7 @@ const FailedTestsTable = () => {
<>
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
index af9535f38a..c4ff9a56a0 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.test.tsx
@@ -148,11 +148,14 @@ describe('MetricsSection', () => {
})
})
- describe('when on default branch', () => {
+ describe.each([
+ ['default branch', 'main'],
+ ['all branches', ''],
+ ])('when on %s', (_, encodedBranch) => {
it('renders subheaders', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const runEfficiency = await screen.findByText('Improve CI Run Efficiency')
@@ -164,7 +167,7 @@ describe('MetricsSection', () => {
it('renders total test runtime card', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const title = await screen.findByText('Total test run time')
@@ -182,7 +185,7 @@ describe('MetricsSection', () => {
it('renders slowest tests card', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const title = await screen.findByText('Slowest tests')
@@ -199,7 +202,7 @@ describe('MetricsSection', () => {
it('can update the location params on button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText('12')
expect(select).toBeInTheDocument()
@@ -217,7 +220,7 @@ describe('MetricsSection', () => {
it('removes the location param on second button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText('12')
expect(select).toBeInTheDocument()
@@ -239,7 +242,7 @@ describe('MetricsSection', () => {
it('renders total flaky tests card', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const title = await screen.findByText('Flaky tests')
@@ -256,7 +259,7 @@ describe('MetricsSection', () => {
it('can update the location params on button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText(88)
expect(select).toBeInTheDocument()
@@ -274,7 +277,7 @@ describe('MetricsSection', () => {
it('removes the location param on second button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText(88)
expect(select).toBeInTheDocument()
@@ -313,7 +316,7 @@ describe('MetricsSection', () => {
it('renders total failures card', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const title = await screen.findByText('Cumulative Failures')
@@ -330,7 +333,7 @@ describe('MetricsSection', () => {
it('can update the location params on button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText(1)
expect(select).toBeInTheDocument()
@@ -370,7 +373,7 @@ describe('MetricsSection', () => {
it('renders total skips card', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const title = await screen.findByText('Skipped tests')
@@ -387,7 +390,7 @@ describe('MetricsSection', () => {
it('can update the location params on button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText(20)
expect(select).toBeInTheDocument()
@@ -405,7 +408,7 @@ describe('MetricsSection', () => {
it('removes the location param on second button click', async () => {
const { user } = setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const select = await screen.findByText(20)
expect(select).toBeInTheDocument()
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.tsx
index b38d7c0899..429e3e93f1 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/MetricsSection/MetricsSection.tsx
@@ -377,9 +377,12 @@ function MetricsSection() {
})
const decodedBranch = getDecodedBranch(branch)
- const selectedBranch = decodedBranch ?? testResults?.defaultBranch ?? ''
+ const selectedBranch = decodedBranch
- if (selectedBranch !== testResults?.defaultBranch) {
+ if (
+ selectedBranch !== undefined &&
+ selectedBranch !== testResults?.defaultBranch
+ ) {
return null
}
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.test.tsx
index 1a04fff6af..f370c9f065 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.test.tsx
@@ -134,6 +134,7 @@ interface SetupArgs {
hasNextPage?: boolean
nullOverview?: boolean
nullHead?: boolean
+ nullBranch?: boolean
}
describe('BranchSelector', () => {
@@ -142,10 +143,12 @@ describe('BranchSelector', () => {
hasNextPage = false,
nullOverview = false,
nullHead = false,
+ nullBranch = false,
}: SetupArgs = {
hasNextPage: false,
nullOverview: false,
nullHead: false,
+ nullBranch: false,
}
) {
const user = userEvent.setup()
@@ -182,6 +185,16 @@ describe('BranchSelector', () => {
branch = info.variables?.branch
}
+ if (nullBranch) {
+ return HttpResponse.json({
+ data: {
+ owner: {
+ repository: { __typename: 'Repository', branch: null },
+ },
+ },
+ })
+ }
+
let mockedBranch = mockBranch(branch)
if (nullHead) {
mockedBranch = mockBranch(branch, null)
@@ -241,7 +254,7 @@ describe('BranchSelector', () => {
wrapper: wrapper(queryClient),
})
- const dropDownBtn = await screen.findByText('main')
+ const dropDownBtn = await screen.findByText('All branches')
expect(dropDownBtn).toBeInTheDocument()
})
})
@@ -255,7 +268,7 @@ describe('BranchSelector', () => {
})
await waitFor(() =>
- expect(testLocation.pathname).toBe('/gh/codecov/test-repo/tests/main')
+ expect(testLocation.pathname).toBe('/gh/codecov/test-repo/tests')
)
})
@@ -286,7 +299,7 @@ describe('BranchSelector', () => {
await user.click(select)
const options = screen.getAllByRole('option')
- expect(options[0]).toHaveTextContent('main')
+ expect(options[0]).toHaveTextContent('All branches')
})
it('navigates to the selected branch', async () => {
@@ -367,7 +380,7 @@ describe('BranchSelector', () => {
wrapper: wrapper(queryClient),
})
- const select = await screen.findByText('main')
+ const select = await screen.findByText('All branches')
await user.click(select)
const input = await screen.findByRole('combobox')
@@ -383,9 +396,13 @@ describe('BranchSelector', () => {
it('displays select a branch in the button', async () => {
const { queryClient } = setup({
nullOverview: true,
+ nullBranch: true,
})
render( , {
- wrapper: wrapper(queryClient),
+ wrapper: wrapper(
+ queryClient,
+ '/gh/codecov/test-repo/tests/nonexistent-branch'
+ ),
})
const select = await screen.findByRole('button', {
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.tsx
index cce19a690d..dd9bb3eea4 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/BranchSelector/BranchSelector.tsx
@@ -15,6 +15,14 @@ interface URLParams {
branch?: string
}
+type Head = { commitid: string } | null
+
+interface BranchSelection {
+ name: string
+ value: string
+ head: Head
+}
+
const getDecodedBranch = (branch?: string) =>
branch ? decodeURIComponent(branch) : undefined
@@ -46,50 +54,53 @@ const BranchSelector = () => {
})
const decodedBranch = getDecodedBranch(branch)
- const selectedBranch = decodedBranch ?? overview?.defaultBranch ?? ''
const { data: searchBranchValue } = useBranch({
provider,
owner,
repo,
- branch: selectedBranch,
+ branch: decodedBranch,
opts: {
- queryKey: ['GetSelectedBranch', provider, owner, repo, selectedBranch],
- enabled: !!selectedBranch,
+ queryKey: ['GetSelectedBranch', provider, owner, repo, decodedBranch],
+ enabled: !!decodedBranch,
},
})
-
- let selection = searchBranchValue?.branch
- if (!selection) {
- selection = {
- name: 'Select branch',
- head: null,
- }
- }
-
- if (
- selectedBranch === overview?.defaultBranch &&
- !branch &&
- selection.head !== null
- ) {
- history.push(
- failedTestsLink.path({ branch: encodeURIComponent(selection?.name) })
- )
- }
+ const selection: BranchSelection = searchBranchValue?.branch
+ ? {
+ name: searchBranchValue.branch.name,
+ value: searchBranchValue.branch.name,
+ head: searchBranchValue.branch.head,
+ }
+ : {
+ name: branch ? 'Select branch' : 'All branches',
+ value: branch || '',
+ head: null,
+ }
const sortedBranchList = useMemo(() => {
- if (!branchList?.branches) return []
-
- if (overview?.defaultBranch) {
- return [
- // Pins the default branch to the top of the list always, filters it from results otherwise
- { name: overview.defaultBranch, head: null },
- ...branchList.branches.filter(
- (branch) => branch.name !== overview.defaultBranch
- ),
- ]
+ if (!branchList?.branches?.length) return []
+
+ const allBranches = { name: 'All branches', value: '', head: null as Head }
+ const defaultBranch = overview?.defaultBranch
+ ? {
+ name: overview.defaultBranch,
+ value: overview.defaultBranch,
+ head: null as Head,
+ }
+ : undefined
+ const branches = branchList.branches
+ .filter((branch) => branch.name !== defaultBranch?.name)
+ .map((branch) => ({
+ name: branch.name,
+ value: branch.name,
+ head: branch.head,
+ }))
+
+ if (defaultBranch) {
+ return [allBranches, defaultBranch, ...branches]
}
- return branchList.branches
+
+ return [allBranches, ...branches]
}, [overview?.defaultBranch, branchList.branches])
return (
@@ -107,9 +118,11 @@ const BranchSelector = () => {
ariaName="test results branch selector"
items={sortedBranchList}
value={selection}
- onChange={(item: Branch) => {
+ onChange={(item: BranchSelection) => {
history.push(
- failedTestsLink.path({ branch: encodeURIComponent(item?.name) })
+ failedTestsLink.path({
+ branch: encodeURIComponent(item.value),
+ })
)
}}
variant="gray"
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.test.tsx
index c57bb09e7e..90f7a665e7 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.test.tsx
@@ -178,11 +178,14 @@ describe('SelectorSection', () => {
})
})
- describe('when on default branch', () => {
+ describe.each([
+ ['default branch', 'main'],
+ ['all branches', ''],
+ ])('when on %s', (_, encodedBranch) => {
it('has all four selectors', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const branchSelector = await screen.findByText('Branch Context')
@@ -198,7 +201,7 @@ describe('SelectorSection', () => {
it('has 60 day retention link', async () => {
setup()
render( , {
- wrapper: wrapper('/gh/owner/repo/tests/main'),
+ wrapper: wrapper(`/gh/owner/repo/tests/${encodedBranch}`),
})
const link = await screen.findByRole('link')
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.tsx
index 68a8ff0a65..979db5a25d 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/SelectorSection/SelectorSection.tsx
@@ -77,7 +77,7 @@ function SelectorSection() {
})
const decodedBranch = getDecodedBranch(branch)
- const selectedBranch = decodedBranch ?? overview?.defaultBranch ?? ''
+ const selectedBranch = decodedBranch ?? ''
const timeValue = MeasurementTimeOptions.find(
// @ts-expect-error need to type out useLocationParams
@@ -91,7 +91,7 @@ function SelectorSection() {
return (
- {selectedBranch === overview?.defaultBranch ? (
+ {selectedBranch === overview?.defaultBranch || selectedBranch === '' ? (
<>
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.test.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.test.tsx
index be947442df..ffb89be2d6 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.test.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.test.tsx
@@ -42,7 +42,7 @@ describe('TableHeader', () => {
})
it('renders the TableHeader component', () => {
- render( , {
+ render( , {
wrapper: wrapper(),
})
const testsText = screen.getByText('Tests (50.0K)')
@@ -55,7 +55,7 @@ describe('TableHeader', () => {
})
it('updates search term on input change', async () => {
- render( , {
+ render( , {
wrapper: wrapper(),
})
const searchInput = screen.getByPlaceholderText('Search by name')
@@ -67,7 +67,7 @@ describe('TableHeader', () => {
})
it('resets to default parameters on button click', async () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?term=test'),
})
const resetButton = screen.getByText('Reset to default')
@@ -78,7 +78,7 @@ describe('TableHeader', () => {
})
it('disables reset button when parameters are default', () => {
- render( , {
+ render( , {
wrapper: wrapper(),
})
const resetButton = screen.getByText('Reset to default')
@@ -86,7 +86,7 @@ describe('TableHeader', () => {
})
it('enables reset button when parameters are not default', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?term=test'),
})
const resetButton = screen.getByText('Reset to default')
@@ -94,7 +94,7 @@ describe('TableHeader', () => {
})
it('hides reset button when not on default branch', () => {
- render( , {
+ render( , {
wrapper: wrapper(),
})
const resetButton = screen.queryByText('Reset to default')
@@ -103,7 +103,7 @@ describe('TableHeader', () => {
describe('header title', () => {
it('renders the default header title', () => {
- render( , {
+ render( , {
wrapper: wrapper(),
})
const headerTitle = screen.getByText('Tests (50.0K)')
@@ -111,7 +111,7 @@ describe('TableHeader', () => {
})
it('renders the flaky tests header title', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?parameter=FLAKY_TESTS'),
})
const headerTitle = screen.getByText('Flaky tests (50.0K)')
@@ -119,7 +119,7 @@ describe('TableHeader', () => {
})
it('renders the failed tests header title', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?parameter=FAILED_TESTS'),
})
const headerTitle = screen.getByText('Failed tests (50.0K)')
@@ -127,7 +127,7 @@ describe('TableHeader', () => {
})
it('renders the tests header title', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?parameter=TESTS'),
})
const headerTitle = screen.getByText('Tests (50.0K)')
@@ -135,7 +135,7 @@ describe('TableHeader', () => {
})
it('renders the skipped tests header title', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?parameter=SKIPPED_TESTS'),
})
const headerTitle = screen.getByText('Skipped tests (50.0K)')
@@ -143,7 +143,7 @@ describe('TableHeader', () => {
})
it('renders the slowest tests header title', () => {
- render( , {
+ render( , {
wrapper: wrapper('/gh/codecov/cool-repo/tests?parameter=SLOWEST_TESTS'),
})
const headerTitle = screen.getByText('Slowest tests (50.0K)')
diff --git a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.tsx b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.tsx
index a8cda9514b..dc3da927a3 100644
--- a/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.tsx
+++ b/src/pages/RepoPage/FailedTestsTab/FailedTestsPage/TableHeader/TableHeader.tsx
@@ -10,7 +10,7 @@ import { defaultQueryParams } from '../SelectorSection'
interface TableHeaderProps {
totalCount: number
- isDefaultBranch: boolean
+ showResetButton: boolean
}
const getHeaderTitle = (parameter: keyof typeof TestResultsFilterParameter) => {
@@ -21,7 +21,7 @@ const getHeaderTitle = (parameter: keyof typeof TestResultsFilterParameter) => {
const TableHeader: React.FC = ({
totalCount,
- isDefaultBranch,
+ showResetButton,
}) => {
const { params, updateParams } = useLocationParams(defaultQueryParams)
// @ts-expect-error, useLocationParams needs to be updated to have full types
@@ -54,7 +54,7 @@ const TableHeader: React.FC = ({
setSearchValue={handleSearchChange}
data-testid="search-input-failed-tests"
/>
- {isDefaultBranch ? (
+ {showResetButton && (
= ({
>
Reset to default
- ) : null}
+ )}
>
diff --git a/src/services/branches/useBranch.tsx b/src/services/branches/useBranch.tsx
index 5beb35918b..878369c452 100644
--- a/src/services/branches/useBranch.tsx
+++ b/src/services/branches/useBranch.tsx
@@ -41,7 +41,7 @@ export interface UseBranchArgs {
provider: string
owner: string
repo: string
- branch: string
+ branch?: string
opts?: UseQueryOptions<{ branch: Branch }>
}
@@ -76,9 +76,15 @@ export const useBranch = ({
opts,
}: UseBranchArgs) =>
useQuery({
- queryKey: ['GetBranch', provider, owner, repo, branch, query],
- queryFn: ({ signal }) =>
- Api.graphql({
+ queryKey: ['GetBranch', { provider, owner, repo, branch, query }],
+ queryFn: ({ signal }) => {
+ if (!branch) {
+ return {
+ branch: null,
+ }
+ }
+
+ return Api.graphql({
provider,
query,
signal,
@@ -127,6 +133,7 @@ export const useBranch = ({
return {
branch: data?.owner?.repository?.branch ?? null,
}
- }),
- ...(!!opts && opts),
+ })
+ },
+ ...(opts || {}),
})