Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Presigned url #3724

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ const defaultConfig = {
SENTRY_ENVIRONMENT: 'staging',
}

const INTERNAL_API = `${defaultConfig.API_URL}/internal`

function removeReactAppPrefix(obj) {
// in .env file, the variable must start with REACT_APP_
// to be injected in the application, so we remove that
@@ -16,6 +18,7 @@ function removeReactAppPrefix(obj) {

const config = {
...defaultConfig,
INTERNAL_API,
...removeReactAppPrefix(process.env),
...window.configEnv,
}
29 changes: 21 additions & 8 deletions src/pages/CommitPage/CommitPage.spec.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { render, screen, waitFor } from 'custom-testing-library'

import { QueryClient, QueryClientProvider } from 'react-query'
import { MemoryRouter, Route } from 'react-router-dom'

import { useCommit } from 'services/commit'
import { useFileWithMainCoverage } from 'services/file'
import { useUploadPresignedUrl } from 'services/uploadPresignedUrl'

import CommitPage from './CommitPage'

jest.mock('services/commit')
jest.mock('services/file')
jest.mock('services/uploadPresignedUrl')
jest.mock('./Header/Header.js', () => () => 'The Header')
jest.mock('./subroute/CommitFileView.js', () => () => 'The Commit File View')
jest.mock(
'./Summary/CommitDetailsSummary.js',
() => () => 'Commit Details Summary'
)
const queryClient = new QueryClient()

const dataReturned = {
commit: {
@@ -88,17 +92,22 @@ const fileData = {
flagNames: [],
}

const mockedPresignedUrl = {presignedUrl: "http://minio:9000/archive/v4/raw/2022-06-23/942173DE95CBF167C5683F40B7DB34C0/ee3ecad424e67419d6c4531540f1ef5df045ff12/919ccc6d-7972-4895-b289-f2d569683a17.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=codecov-default-key%2F20220705%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220705T101702Z&X-Amz-Expires=10&X-Amz-SignedHeaders=host&X-Amz-Signature=8846492d85f62187493cbff3631ec7f0ccf2d355f768eecf294f0572cf758e4c"}

describe('CommitPage', () => {
function setup(data) {
useCommit.mockReturnValue(data)
useFileWithMainCoverage.mockReturnValue(fileData)
useUploadPresignedUrl.mockReturnValue(mockedPresignedUrl)

render(
<MemoryRouter initialEntries={['/gh/test/test-repo/commit/abcd']}>
<Route path="/:provider/:owner/:repo/commit/:commit">
<CommitPage />
</Route>
</MemoryRouter>
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={['/gh/test/test-repo/commit/abcd']}>
<Route path="/:provider/:owner/:repo/commit/:commit">
<CommitPage />
</Route>
</MemoryRouter>
</QueryClientProvider>
)
}

@@ -159,6 +168,9 @@ describe('CommitPage', () => {
describe('Commits Table', () => {
function setup(data) {
useCommit.mockReturnValue(data)
useUploadPresignedUrl.mockReturnValue({
data: '/archive/v4/raw/2022-06-23/..',
})

render(
<MemoryRouter
@@ -212,6 +224,9 @@ describe('CommitPage', () => {

describe('FileViewer', () => {
function setup(data) {
useUploadPresignedUrl.mockReturnValue({
data: '/archive/v4/raw/2022-06-23/..',
})
useCommit.mockReturnValue(data)
useFileWithMainCoverage.mockReturnValue({
data: fileData,
@@ -235,9 +250,7 @@ describe('CommitPage', () => {

it('the impacted file', () => {
expect(screen.getByTestId('spinner')).toBeInTheDocument()
waitFor(() => {
expect(screen.getByText(/index.js/)).toBeInTheDocument()
})
waitFor(()=> expect(screen.getByText(/index.js/)).toBeInTheDocument())
})
})

14 changes: 5 additions & 9 deletions src/pages/CommitPage/UploadsCard/Upload.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import PropTypes from 'prop-types'

import config from 'config'

import { useUploadPresignedUrl } from 'services/uploadPresignedUrl'
import {
ErrorCodeEnum,
UploadStateEnum,
@@ -24,6 +23,8 @@ const Upload = ({
state,
}) => {
const isCarriedForward = uploadType === UploadTypeEnum.CARRIED_FORWARD
const { data } = useUploadPresignedUrl({ path :downloadUrl })
const presignedGetUrl = data?.presignedUrl

return (
<div className="py-2 px-4 flex flex-col gap-1">
@@ -56,13 +57,8 @@ const Upload = ({
<span className="text-ds-gray-quinary text-xs">carry-forward</span>
)}
</div>
{downloadUrl && (
<A
href={`${config.API_URL}${downloadUrl}`}
hook="download report"
download
isExternal
>
{presignedGetUrl && (
<A href={presignedGetUrl} isExternal hook="get-presigned-url" download>
Download
</A>
)}
106 changes: 75 additions & 31 deletions src/pages/CommitPage/UploadsCard/Upload.spec.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
import { render, screen } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from 'react-query'
import { MemoryRouter, Route } from 'react-router-dom'

import { useUploadPresignedUrl } from 'services/uploadPresignedUrl'
import { formatTimeToNow } from 'shared/utils/dates'

import Upload from './Upload'

jest.mock('services/uploadPresignedUrl')

const queryClient = new QueryClient()
const mockedPresignedUrl = {
presignedUrl:
'http://minio:9000/archive/v4/raw/2022-06-23/942173DE95CBF167C5683F40B7DB34C0/ee3ecad424e67419d6c4531540f1ef5df045ff12/919ccc6d-7972-4895-b289-f2d569683a17.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=codecov-default-key%2F20220705%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220705T101702Z&X-Amz-Expires=10&X-Amz-SignedHeaders=host&X-Amz-Signature=8846492d85f62187493cbff3631ec7f0ccf2d355f768eecf294f0572cf758e4c',
}

describe('UploadsCard', () => {
function setup(props) {
render(<Upload {...props} />)
function setup({ props, data = mockedPresignedUrl }) {
useUploadPresignedUrl.mockReturnValue({ data })

render(
<MemoryRouter initialEntries={['/gh/codecov/test']}>
<Route path="/:provider/:owner/:repo">
<QueryClientProvider client={queryClient}>
<Upload {...props} />
</QueryClientProvider>
</Route>
</MemoryRouter>
)
}

describe('renders', () => {
beforeEach(() => {
setup({
ciUrl: 'ciUrl.com',
createdAt: '2020-08-25T16:36:19.559474+00:00',
downloadUrl: 'download.com',
buildCode: '1234',
uploadType: 'CARRIEDFORWARD',
props: {
ciUrl: 'ciUrl.com',
createdAt: '2020-08-25T16:36:19.559474+00:00',
downloadUrl: 'download.com',
buildCode: '1234',
uploadType: 'CARRIEDFORWARD',
},
})
})

@@ -35,10 +58,9 @@ describe('UploadsCard', () => {
expect(screen.getByText(createDate)).toBeInTheDocument()
})
it('renders a download link', () => {
expect(screen.getByRole('link', { name: /Download/ })).toHaveAttribute(
'href',
'download.com'
)
expect(
screen.getByRole('link', { name: /1234 external-link.svg/ })
).toHaveAttribute('href')
})

it('renders carry-forward text', () => {
@@ -48,7 +70,7 @@ describe('UploadsCard', () => {

describe('build without build link', () => {
beforeEach(() => {
setup({ buildCode: '1234' })
setup({ props: { buildCode: '1234' } })
})
it('renders a the build code', () => {
expect(screen.getByText(/1234/)).toBeInTheDocument()
@@ -61,7 +83,7 @@ describe('UploadsCard', () => {
})
describe('missinng data renders', () => {
beforeEach(() => {
setup({})
setup({ props: {}, data: null })
})

it('renders a default build code if no code was provided', () => {
@@ -81,13 +103,17 @@ describe('UploadsCard', () => {
describe('rendering flags', () => {
it('one flag', () => {
setup({
flags: ['flag1'],
props: {
flags: ['flag1'],
},
})
expect(screen.getByText(/flag1/)).toBeInTheDocument()
})
it('multiple flags', () => {
setup({
flags: ['flag1', 'flag2', 'flag3', 'flag4'],
props: {
flags: ['flag1', 'flag2', 'flag3', 'flag4'],
},
})
expect(screen.getByText(/flag1/)).toBeInTheDocument()
expect(screen.getByText(/flag2/)).toBeInTheDocument()
@@ -103,70 +129,88 @@ describe('UploadsCard', () => {

it('fileNotFoundInStorage error', () => {
setup({
errors: [{ errorCode: 'FILE_NOT_IN_STORAGE' }],
props: {
errors: [{ errorCode: 'FILE_NOT_IN_STORAGE' }],
},
})
expect(screen.getByText(/processing failed/)).toBeInTheDocument()
})
it('reportExpired error', () => {
setup({
errors: [{ errorCode: 'REPORT_EXPIRED' }],
props: {
errors: [{ errorCode: 'REPORT_EXPIRED' }],
},
})
expect(screen.getByText(/upload expired/)).toBeInTheDocument()
})
it('reportEmpty error', () => {
setup({
errors: [{ errorCode: 'REPORT_EMPTY' }],
props: {
errors: [{ errorCode: 'REPORT_EMPTY' }],
},
})
expect(screen.getByText(/upload is empty/)).toBeInTheDocument()
})
it('all errors', () => {
setup({
errors: [
{ errorCode: 'FILE_NOT_IN_STORAGE' },
{ errorCode: 'REPORT_EXPIRED' },
{ errorCode: 'REPORT_EMPTY' },
{ errorCode: 'SOME_NEW_ERROR' },
],
props: {
errors: [
{ errorCode: 'FILE_NOT_IN_STORAGE' },
{ errorCode: 'REPORT_EXPIRED' },
{ errorCode: 'REPORT_EMPTY' },
{ errorCode: 'SOME_NEW_ERROR' },
],
},
})
expect(screen.getByText(/processing failed/)).toBeInTheDocument()
expect(screen.getByText(/upload expired/)).toBeInTheDocument()
expect(screen.getByText(/upload is empty/)).toBeInTheDocument()
})
it('handles new errors the front end doesnt know how to handle', () => {
setup({
errors: [{ errorCode: 'SOME_NEW_ERROR' }],
props: {
errors: [{ errorCode: 'SOME_NEW_ERROR' }],
},
})
expect(screen.getByText(/unknown error/)).toBeInTheDocument()
})
it('handles an unexpected error type', () => {
setup({
errors: [{ errorCode: { error: 'bad config or something' } }],
props: {
errors: [{ errorCode: { error: 'bad config or something' } }],
},
})
expect(screen.getByText(/unknown error/)).toBeInTheDocument()
})
it('handles upload state error but no error code resolved as an known error', () => {
setup({
state: 'ERROR',
props: {
state: 'ERROR',
},
})
expect(screen.getByText(/unknown error/)).toBeInTheDocument()
})
it('handles upload state error but no errors returned', () => {
setup({
state: 'ERROR',
errors: [],
props: {
state: 'ERROR',
errors: [],
},
})
expect(screen.getByText(/unknown error/)).toBeInTheDocument()
})
it('If no state is provided and no errors received do not show an error', () => {
setup({
error: [],
props: {
error: [],
},
})
expect(screen.queryByText(/unknown error/)).not.toBeInTheDocument()
})
})

describe('rendering uploaded type of uploads', () => {
setup({ uploadType: 'UPLOADED' })
setup({ props: { uploadType: 'UPLOADED' } })
it('does not render carry-forward text', () => {
expect(screen.queryByText('carry-forward')).not.toBeInTheDocument()
})
14 changes: 13 additions & 1 deletion src/pages/CommitPage/UploadsCard/UploadsCard.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import { fireEvent, render, screen } from 'custom-testing-library'

import { QueryClient, QueryClientProvider } from 'react-query'
import { MemoryRouter, Route } from 'react-router-dom'

import { useUploads } from './hooks'
import UploadsCard from './UploadsCard'

const queryClient = new QueryClient()
jest.mock('./hooks')

describe('UploadsCard', () => {
function setup(mockUploads) {
useUploads.mockReturnValue(mockUploads)
render(<UploadsCard />)
render(
<MemoryRouter initialEntries={['/gh/codecov/test']}>
<Route path="/:provider/:owner/:repo">
<QueryClientProvider client={queryClient}>
<UploadsCard />
</QueryClientProvider>
</Route>
</MemoryRouter>
)
}

describe('renders', () => {
15 changes: 15 additions & 0 deletions src/services/uploadPresignedUrl/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useQuery } from 'react-query'
import { useParams } from 'react-router-dom'

import Api from 'shared/api'

function fetchUploadPresignedUrl({ provider, path }) {
return Api.get({ path, provider, isUploadPath: true })
}

export function useUploadPresignedUrl({ path }) {
const { provider } = useParams()
return useQuery(['uploadPresignedUrl', provider], () => {
return fetchUploadPresignedUrl({ provider, path })
})
}
Loading
Oops, something went wrong.