Skip to content

Commit f6c9f04

Browse files
authored
fix: CoverageTrend not displaying coverage percentage (#3530)
1 parent 0785ad8 commit f6c9f04

File tree

8 files changed

+291
-124
lines changed

8 files changed

+291
-124
lines changed

src/pages/RepoPage/CoverageTab/OverviewTab/Summary/CoverageTrend/CoverageTrend.test.jsx

Lines changed: 0 additions & 102 deletions
This file was deleted.
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2+
import { render, screen } from '@testing-library/react'
3+
import { graphql, HttpResponse } from 'msw'
4+
import { setupServer } from 'msw/node'
5+
import { Suspense } from 'react'
6+
import { MemoryRouter, Route } from 'react-router-dom'
7+
8+
import CoverageTrend from './CoverageTrend'
9+
10+
vi.mock('../TrendDropdown', () => ({ default: () => 'TrendDropdown' }))
11+
12+
const mockOverview = {
13+
owner: {
14+
isCurrentUserActivated: true,
15+
repository: {
16+
__typename: 'Repository',
17+
private: false,
18+
defaultBranch: 'main',
19+
oldestCommitAt: '2022-10-10T11:59:59',
20+
coverageEnabled: true,
21+
bundleAnalysisEnabled: true,
22+
languages: ['javascript'],
23+
testAnalyticsEnabled: true,
24+
},
25+
},
26+
}
27+
28+
const mockBranch = {
29+
owner: {
30+
repository: {
31+
__typename: 'Repository',
32+
branch: { name: 'main', head: { commitid: 'commit-123' } },
33+
},
34+
},
35+
}
36+
37+
const mockBranches = {
38+
owner: {
39+
repository: {
40+
__typename: 'Repository',
41+
branches: {
42+
edges: [{ node: { name: 'main', head: { commitid: 'commit-123' } } }],
43+
pageInfo: { hasNextPage: false, endCursor: null },
44+
},
45+
},
46+
},
47+
}
48+
49+
const mockBranchMeasurements = {
50+
owner: {
51+
repository: {
52+
__typename: 'Repository',
53+
coverageAnalytics: {
54+
measurements: [
55+
{ timestamp: '2023-01-01T00:00:00+00:00', max: 40 },
56+
{ timestamp: '2023-01-02T00:00:00+00:00', max: 80 },
57+
{ timestamp: '2023-01-03T00:00:00+00:00', max: 90 },
58+
{ timestamp: '2023-01-04T00:00:00+00:00', max: 100 },
59+
],
60+
},
61+
},
62+
},
63+
}
64+
65+
const mockNoBranchMeasurements = {
66+
owner: {
67+
repository: {
68+
__typename: 'Repository',
69+
coverageAnalytics: {
70+
measurements: [],
71+
},
72+
},
73+
},
74+
}
75+
76+
const server = setupServer()
77+
const queryClient = new QueryClient({
78+
defaultOptions: { queries: { retry: false, suspense: true } },
79+
})
80+
81+
const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
82+
<QueryClientProvider client={queryClient}>
83+
<MemoryRouter initialEntries={['/gh/test-org/test-repo']}>
84+
<Route path="/:provider/:owner/:repo">
85+
<Suspense fallback={null}>{children}</Suspense>
86+
</Route>
87+
</MemoryRouter>
88+
</QueryClientProvider>
89+
)
90+
91+
beforeAll(() => {
92+
server.listen()
93+
})
94+
95+
afterEach(() => {
96+
queryClient.clear()
97+
server.resetHandlers()
98+
})
99+
100+
afterAll(() => {
101+
server.close()
102+
})
103+
104+
interface SetupArgs {
105+
hasBranchMeasurements?: boolean
106+
}
107+
108+
describe('CoverageTrend', () => {
109+
function setup({ hasBranchMeasurements = true }: SetupArgs) {
110+
server.use(
111+
graphql.query('GetRepoOverview', () => {
112+
return HttpResponse.json({ data: mockOverview })
113+
}),
114+
graphql.query('GetBranches', () => {
115+
return HttpResponse.json({ data: mockBranches })
116+
}),
117+
graphql.query('GetBranch', () => {
118+
return HttpResponse.json({ data: mockBranch })
119+
}),
120+
graphql.query('GetBranchCoverageMeasurements', () => {
121+
if (!hasBranchMeasurements) {
122+
return HttpResponse.json({ data: mockNoBranchMeasurements })
123+
}
124+
125+
return HttpResponse.json({ data: mockBranchMeasurements })
126+
})
127+
)
128+
}
129+
130+
describe('coverage exists', () => {
131+
it('rendered the change %', async () => {
132+
setup({ hasBranchMeasurements: true })
133+
render(<CoverageTrend />, { wrapper })
134+
135+
const change = await screen.findByText(/60.00%+/)
136+
expect(change).toBeInTheDocument()
137+
})
138+
})
139+
140+
describe('coverage is empty', () => {
141+
it('does messages if there is no reports', async () => {
142+
setup({ hasBranchMeasurements: false })
143+
render(<CoverageTrend />, { wrapper })
144+
145+
const message = await screen.findByText(
146+
/No coverage reports found in this timespan./
147+
)
148+
expect(message).toBeInTheDocument()
149+
})
150+
})
151+
})

src/pages/RepoPage/CoverageTab/OverviewTab/Summary/CoverageTrend/CoverageTrend.jsx renamed to src/pages/RepoPage/CoverageTab/OverviewTab/Summary/CoverageTrend/CoverageTrend.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,50 @@ import TotalsNumber from 'ui/TotalsNumber'
99
import { useBranchSelector, useRepoCoverageTimeseries } from '../../hooks'
1010
import TrendDropdown from '../TrendDropdown'
1111

12+
interface URLParams {
13+
provider: string
14+
owner: string
15+
repo: string
16+
}
17+
1218
function CoverageTrend() {
13-
const { repo, owner, provider } = useParams()
19+
const { repo, owner, provider } = useParams<URLParams>()
1420
const { data: overview } = useRepoOverview({
1521
provider,
1622
repo,
1723
owner,
1824
})
25+
1926
const { data: branchesData } = useBranches({ provider, repo, owner })
27+
2028
const { selection } = useBranchSelector({
21-
branches: branchesData?.branches,
22-
defaultBranch: overview?.defaultBranch,
29+
branches: branchesData?.branches ?? [],
30+
defaultBranch: overview?.defaultBranch ?? '',
2331
})
2432

25-
const { data, isFetching } = useRepoCoverageTimeseries(
26-
{
27-
branch: selection?.name,
33+
const { data, isLoading } = useRepoCoverageTimeseries({
34+
branch: selection?.name,
35+
options: {
36+
enabled: !!selection?.name,
37+
suspense: false,
38+
keepPreviousData: true,
2839
},
29-
{ enabled: !!selection?.name, suspense: false, keepPreviousData: true }
30-
)
40+
})
3141

3242
return (
3343
<SummaryField>
3444
<TrendDropdown />
3545
<div className="flex items-center gap-2 pb-[1.3rem]">
3646
{/* ^ CSS doesn't want to render like the others without a p tag in the dom. */}
37-
{data?.coverage?.length > 0 ? (
38-
<>
39-
<TotalsNumber value={data?.coverageChange} light showChange />
40-
</>
47+
{isLoading ? (
48+
<Spinner />
49+
) : data?.measurements?.length > 0 ? (
50+
<TotalsNumber value={data?.coverageChange ?? 0} light showChange />
4151
) : (
4252
<p className="text-sm font-medium">
4353
No coverage reports found in this timespan.
4454
</p>
4555
)}
46-
{isFetching && <Spinner />}
4756
</div>
4857
</SummaryField>
4958
)

src/pages/RepoPage/CoverageTab/OverviewTab/hooks/useRepoCoverageTimeseries.test.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ describe('useRepoCoverageTimeseries', () => {
157157

158158
await waitFor(() => expect(result.current.data?.measurements).toEqual([]))
159159
})
160+
161+
it('returns 0 for coverage change', async () => {
162+
setup({ noCoverageData: true })
163+
const { result } = renderHook(
164+
() => useRepoCoverageTimeseries({ branch: 'c3' }),
165+
{ wrapper: wrapper('') }
166+
)
167+
168+
await waitFor(() =>
169+
expect(result.current.data?.coverageChange).toEqual(0)
170+
)
171+
})
160172
})
161173

162174
describe('there is coverage data', () => {
@@ -176,5 +188,17 @@ describe('useRepoCoverageTimeseries', () => {
176188
])
177189
)
178190
})
191+
192+
it('returns the coverage change', async () => {
193+
setup()
194+
const { result } = renderHook(
195+
() => useRepoCoverageTimeseries({ branch: 'c3' }),
196+
{ wrapper: wrapper('') }
197+
)
198+
199+
await waitFor(() =>
200+
expect(result.current.data?.coverageChange).toEqual(15)
201+
)
202+
})
179203
})
180204
})

src/pages/RepoPage/CoverageTab/OverviewTab/hooks/useRepoCoverageTimeseries.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,12 @@ export function useRepoCoverageTimeseries({
9696
}
9797
})
9898

99+
const coverageChange =
100+
(coverage.at(-1)?.coverage ?? 0) - (coverage.at(0)?.coverage ?? 0)
101+
99102
return {
100103
...rest,
101-
data: { measurements: coverage },
104+
data: { measurements: coverage, coverageChange },
102105
}
103106
}, [data, rest])
104107
}

0 commit comments

Comments
 (0)