Skip to content
Merged
Show file tree
Hide file tree
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
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