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

PRMP-1292: Download LG Record Screen | Add file size column #493

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ const testFiles = [
created: '2024-05-07T14:52:00.827602Z',
virusScannerResult: 'Clean',
id: 'test-id',
fileSize: 200,
},
{
fileName: '2of2_testy_test.pdf',
created: '2024-05-07T14:52:00.827602Z',
virusScannerResult: 'Clean',
id: 'test-id-2',
fileSize: 200,
},
{
fileName: '1of1_lone_test_file.pdf',
created: '2024-01-01T14:52:00.827602Z',
virusScannerResult: 'Clean',
id: 'test-id-3',
fileSize: 200,
},
];

Expand All @@ -40,6 +43,7 @@ const singleTestFile = [
created: '2024-01-01T14:52:00.827602Z',
virusScannerResult: 'Clean',
id: 'test-id-3',
fileSize: 200,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import usePatient from '../../../../helpers/hooks/usePatient';
import { LinkProps } from 'react-router-dom';
import LloydGeorgeSelectSearchResults, { Props } from './LloydGeorgeSelectSearchResults';
import userEvent from '@testing-library/user-event';
import { routes } from '../../../../types/generic/routes';
import { SEARCH_AND_DOWNLOAD_STATE } from '../../../../types/pages/documentSearchResultsPage/types';
import { runAxeTest } from '../../../../helpers/test/axeTestHelper';

Expand Down Expand Up @@ -57,6 +56,20 @@ describe('LloydGeorgeSelectSearchResults', () => {
expect(screen.getByTestId('toggle-selection-btn')).toBeInTheDocument();
});

it('renders the correct table headers', () => {
renderComponent({ selectedDocuments: mockSelectedDocuments });

const headers = screen.getAllByRole('columnheader');
const expectedHeaders = ['Selected', 'Filename', 'Upload date', 'File size'];

expectedHeaders.forEach((headerText, index) => {
expect(headers[index]).toHaveTextContent(headerText);
});

const filesTable = screen.getByTestId('available-files-table-title');
expect(filesTable).toHaveTextContent(/bytes|KB|MB|GB/);
});

it('shows error box when download selected files button is clicked but no files selected', async () => {
renderComponent({ selectedDocuments: [] });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SEARCH_AND_DOWNLOAD_STATE } from '../../../../types/pages/documentSearc
import ErrorBox from '../../../layout/errorBox/ErrorBox';
import PatientSummary from '../../../generic/patientSummary/PatientSummary';
import BackButton from '../../../generic/backButton/BackButton';
import formatFileSize from '../../../../helpers/utils/formatFileSize';

export type Props = {
searchResults: Array<SearchResult>;
Expand Down Expand Up @@ -108,6 +109,7 @@ const AvailableFilesTable = ({
)}
<Table.Cell className={'table-column-header'}>Filename</Table.Cell>
<Table.Cell className={'table-column-header'}>Upload date</Table.Cell>
<Table.Cell className={'table-column-header'}>File size</Table.Cell>
</Table.Row>
</Table.Head>
<Table.Body>
Expand Down Expand Up @@ -147,6 +149,12 @@ const AvailableFilesTable = ({
>
{getFormattedDatetime(new Date(result.created))}
</Table.Cell>
<Table.Cell
id={'available-files-row-' + index + '-file-size'}
data-testid="file-size"
>
{formatFileSize(result.fileSize)}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
Expand Down
1 change: 1 addition & 0 deletions app/src/helpers/test/testBuilders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const buildSearchResult = (searchResultOverride?: Partial<SearchResult>) => {
created: moment().format(),
virusScannerResult: 'Clean',
ID: '1234qwer-241ewewr',
fileSize: 224,
...searchResultOverride,
};
return result;
Expand Down
41 changes: 41 additions & 0 deletions app/src/helpers/utils/formatFileSize.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import formatFileSize from "./formatFileSize";

describe('formatFileSize', () => {

it('returns rounded file size formats for valid inputs', () => {

expect(formatFileSize(0)).toBe('0 bytes');
expect(formatFileSize(-0)).toBe('0 bytes');
expect(formatFileSize(1)).toBe('1 bytes');
expect(formatFileSize(1.5)).toBe('2 bytes');

expect(formatFileSize(1023)).toBe('1023 bytes');
expect(formatFileSize(1024)).toBe('1 KB');
expect(formatFileSize(1025)).toBe('1 KB');

expect(formatFileSize(1535)).toBe('1 KB');
expect(formatFileSize(1536)).toBe('2 KB');
expect(formatFileSize(2048)).toBe('2 KB');

expect(formatFileSize(Math.pow(2, 20) - 1)).toBe('1024 KB');
expect(formatFileSize(Math.pow(2, 20))).toBe('1 MB');
expect(formatFileSize(Math.pow(2, 20) + 1)).toBe('1 MB');

expect(formatFileSize(Math.pow(2, 30) - 1)).toBe('1024 MB');
expect(formatFileSize(Math.pow(2, 30))).toBe('1 GB');
expect(formatFileSize(Math.pow(2, 30) + 1)).toBe('1 GB');

});

it('throws "Invalid file size" exception for invalid inputs', () => {

expect(() => formatFileSize(Number.MIN_SAFE_INTEGER)).toThrow('Invalid file size');
expect(() => formatFileSize(-1)).toThrow('Invalid file size');
expect(() => formatFileSize(NaN)).toThrow('Invalid file size');
expect(() => formatFileSize(undefined as unknown as number)).toThrow('Invalid file size');
expect(() => formatFileSize(Math.pow(2, 40))).toThrow('Invalid file size'); // 1TB
expect(() => formatFileSize(Number.MAX_SAFE_INTEGER)).toThrow('Invalid file size');

});

});
1 change: 1 addition & 0 deletions app/src/types/generic/searchResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export type SearchResult = {
created: string;
virusScannerResult: string;
ID: string;
fileSize: number;
};
19 changes: 15 additions & 4 deletions lambdas/services/document_reference_search_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,21 @@ def get_document_references(self, nhs_number: str):
423, LambdaError.UploadInProgressError
)
results.extend(
document.model_dump(
include={"file_name", "created", "virus_scanner_result", "id"},
by_alias=True,
)
{
**document.model_dump(
include={
"file_name",
"created",
"virus_scanner_result",
"id",
},
by_alias=True,
),
"fileSize": self.s3_service.get_file_size(
s3_bucket_name=document.get_file_bucket(),
object_key=document.get_file_key(),
),
}
for document in documents
)
return results
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,22 @@
DocumentReference.model_validate(MOCK_SEARCH_RESPONSE["Items"][0])
]

MOCK_FILE_SIZE = 24000

EXPECTED_RESPONSE = {
"created": "2024-01-01T12:00:00.000Z",
"fileName": "document.csv",
"virusScannerResult": "Clean",
"ID": "3d8683b9-1665-40d2-8499-6e8302d507ff",
"fileSize": MOCK_FILE_SIZE,
}


@pytest.fixture
def patched_service(mocker, set_env):
service = DocumentReferenceSearchService()
mocker.patch.object(service, "s3_service")
mock_s3_service = mocker.patch.object(service, "s3_service")
mocker.patch.object(mock_s3_service, "get_file_size", return_value=MOCK_FILE_SIZE)
mocker.patch.object(service, "dynamo_service")
mocker.patch.object(service, "fetch_documents_from_table_with_filter")
mocker.patch.object(service, "is_upload_in_process", return_value=False)
Expand Down Expand Up @@ -83,10 +87,10 @@ def test_get_document_references_dynamo_return_successful_response_single_table(
patched_service, monkeypatch
):
monkeypatch.setenv("DYNAMODB_TABLE_LIST", json.dumps(["test_table"]))

patched_service.fetch_documents_from_table_with_filter.return_value = (
MOCK_DOCUMENT_REFERENCE
)

expected_results = [EXPECTED_RESPONSE]
actual = patched_service.get_document_references("1111111111")

Expand Down
Loading