Skip to content

Commit

Permalink
Updated tests, refactored components and store
Browse files Browse the repository at this point in the history
  • Loading branch information
rmanaem committed Feb 18, 2025
1 parent 62db40d commit 331577f
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 87 deletions.
6 changes: 4 additions & 2 deletions cypress/component/FileUploader.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import FileUploader from '../../src/components/FileUploader';

const props = {
displayText: 'Upload your file (.csv)',
handleClickToUpload: () => {},
handleDrop: () => {},
handleDragOver: () => {},
Expand All @@ -14,6 +15,7 @@ describe('FileUploader', () => {
it('should render the FileUploader component', () => {
cy.mount(
<FileUploader
displayText={props.displayText}
handleClickToUpload={props.handleClickToUpload}
handleDrop={props.handleDrop}
handleDragOver={props.handleDragOver}
Expand All @@ -22,7 +24,7 @@ describe('FileUploader', () => {
allowedFileType={props.allowedFileType}
/>
);
cy.get('[data-cy="upload-area"]').should('be.visible');
cy.get('[data-cy="upload-area"]').should('contain', 'Upload your file (.csv)');
});
cy.get('[data-cy="upload-area"]').should('be.visible');
cy.get('[data-cy="upload-area"]').should('contain', 'Upload your file (.csv)');
});
38 changes: 8 additions & 30 deletions cypress/component/UploadCard.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import UploadCard from '../../src/components/UploadCard';

const exampleFileName = 'ds003653_participant.tsv';
const exampleFilePath = `examples/${exampleFileName}`;
function DefaultPreviewComponent() {
return <div data-cy="default-preview">Preview Component</div>;
function MockPreviewComponent() {
return <div data-cy="some title-datatable">Preview Component</div>;
}

const props = {
title: 'some title',
allowedFileType: '.tsv',
uploadedFileName: exampleFileName,
onFileUpload: () => {},
previewComponent: <DefaultPreviewComponent />,
previewComponent: <MockPreviewComponent />,
};

describe('UploadCard', () => {
Expand All @@ -26,10 +26,7 @@ describe('UploadCard', () => {
/>
);
cy.get('[data-cy="some title-upload-card"]').should('be.visible');
cy.get('[data-cy="some title-upload-card"]').should(
'contain',
'Upload your tabular phenotypic file (.tsv format)'
);
cy.get('[data-cy="some title-upload-card"]').should('contain', 'some title');
});
beforeEach(() => {
cy.mount(
Expand Down Expand Up @@ -68,30 +65,11 @@ describe('UploadCard', () => {
});
});
});
it('should open the preview, and verify the table content', () => {
cy.get('[data-cy="uploaded-datatable-file-name"]').should('contain', exampleFileName);

cy.get('[data-cy="toggle-datatable-preview"]').click();

cy.get('[data-cy="data-table"]').should('be.visible');

cy.get('[data-cy="data-table"] th:nth-child(9)').should('contain', 'session');

// Check the value of the 5th column in the 2nd row
cy.get('[data-cy="data-table"] tr:nth-child(2) td:nth-child(5)').should('contain', 'MDD');
});
it('should navigate to the 3rd page of the table and verify the content', () => {
cy.get('[data-cy="toggle-datatable-preview"]').click();

// Go the 3rd page of the table
cy.get('[data-cy="datatable-preview-pagination"]').within(() => {
cy.get('button[aria-label="Go to next page"]').click();
cy.get('button[aria-label="Go to next page"]').click();
});
it('should open the preview, and verify the data table preview component is rendered', () => {
cy.get('[data-cy="some title-card-uploaded-file-name"]').should('contain', exampleFileName);

cy.get('[data-cy="data-table"] th:nth-child(2)').should('contain', 'age');
cy.get('[data-cy="toggle-some title-card-preview"]').click();

// Check the value of the 5th column in the 2nd row
cy.get('[data-cy="data-table"] tr:nth-child(2) td:nth-child(5)').should('contain', 'HC');
cy.get('[data-cy="toggle-some title-card-preview"]').should('be.visible');
});
});
13 changes: 13 additions & 0 deletions cypress/fixtures/examples/mock.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
participant_id age sex
sub-718211 28.4 M
sub-718213 24.6 F
sub-718216 43.6 M
sub-718217 28.4 F
sub-718218 72.1 M
sub-718219 56.2 M
sub-718220 23 M
sub-718221 22 F
sub-718222 21 M
sub-718223 45 F
sub-718224 34 M
sub-718225 65 M
27 changes: 15 additions & 12 deletions src/components/DataTablePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ import {
TablePagination,
} from '@mui/material';
import { v4 as uuidv4 } from 'uuid';
import { DataTable, Columns } from '../utils/types';
import { DataTable, Columns, Column } from '../utils/types';

function DataTablePreview({ dataTable, columns }: { dataTable: DataTable; columns: Columns }) {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);

// Define a type for the column object
type Column = { header: string };

// Use the Column type in the map function
const headers = Object.values(columns).map((column: Column) => column.header);
const rows = Object.values(dataTable);

const slicedRows = rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
// Transform column-based data into row-based data for rendering
const rowData =
Object.keys(dataTable).length > 0
? Object.values(dataTable)[0].map((_, rowIndex) =>
Object.keys(dataTable).map((colKey) => dataTable[Number(colKey)][rowIndex])
)
: [];

Check warning on line 27 in src/components/DataTablePreview.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/DataTablePreview.tsx#L27

Added line #L27 was not covered by tests

const slicedRows = rowData.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);

const handleChangePage = (_: unknown, newPage: number) => {
setPage(newPage);
Expand All @@ -37,12 +40,12 @@ function DataTablePreview({ dataTable, columns }: { dataTable: DataTable; column
return (

Check warning on line 40 in src/components/DataTablePreview.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/DataTablePreview.tsx#L40

Added line #L40 was not covered by tests
<div className="mt-6">
<TableContainer component={Paper} elevation={3} className="w-full overflow-x-auto shadow-lg">
<Table className="min-w-[768px]" data-cy="data-table">
<Table className="min-w-[768px]" data-cy="data-table-preview">
<TableHead>
<TableRow className="bg-blue-50">
{headers.map((header) => (
<TableCell

Check warning on line 47 in src/components/DataTablePreview.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/DataTablePreview.tsx#L47

Added line #L47 was not covered by tests
key={uuidv4()} // Use uuid for key
key={uuidv4()}
align="left"
sx={{ fontWeight: 'bold', color: 'primary.main' }}
>
Expand All @@ -53,11 +56,11 @@ function DataTablePreview({ dataTable, columns }: { dataTable: DataTable; column
</TableHead>
<TableBody>
{slicedRows.map((row) => {
const rowId = uuidv4(); // Generate a unique ID for the row
const rowId = uuidv4();
return (

Check warning on line 60 in src/components/DataTablePreview.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/DataTablePreview.tsx#L60

Added line #L60 was not covered by tests
<TableRow key={rowId}>
{row.map((cell) => {
const cellId = uuidv4(); // Generate a unique ID for the cell
const cellId = uuidv4();
return (

Check warning on line 64 in src/components/DataTablePreview.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/DataTablePreview.tsx#L64

Added line #L64 was not covered by tests
<TableCell key={cellId} align="left">
{cell}
Expand All @@ -73,7 +76,7 @@ function DataTablePreview({ dataTable, columns }: { dataTable: DataTable; column
data-cy="datatable-preview-pagination"
rowsPerPageOptions={[5, 10, 25, 50, 100]}
component="div"
count={rows.length}
count={rowData.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
Expand Down
4 changes: 3 additions & 1 deletion src/components/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Card, Typography, useTheme } from '@mui/material';
import { CloudUpload } from '@mui/icons-material';

interface FileUploaderProps {
displayText: string;
handleClickToUpload: () => void;
handleDrop: (event: React.DragEvent<HTMLDivElement>) => void;
handleDragOver: (event: React.DragEvent<HTMLDivElement>) => void;
Expand All @@ -11,6 +12,7 @@ interface FileUploaderProps {
}

function FileUploader({
displayText,
handleClickToUpload,
handleDrop,
handleDragOver,
Expand Down Expand Up @@ -39,7 +41,7 @@ function FileUploader({
style={{ color: theme.palette.primary.main }}
/>
<Typography variant="body1" className="mb-2">
Upload your file ({allowedFileType.replace(/,/g, ', ')})
{displayText}
</Typography>
<Typography variant="body2" className="mb-4">
<span
Expand Down
11 changes: 8 additions & 3 deletions src/components/UploadCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useState } from 'react';
import { useRef, useState } from 'react';
import { Button, Card, Typography, Collapse } from '@mui/material';
import { ExpandMore, ExpandLess } from '@mui/icons-material';
import FileUploader from './FileUploader';
Expand Down Expand Up @@ -59,6 +59,7 @@ function UploadCard({
</Typography>

<FileUploader
displayText={`Upload your file (${allowedFileType})`}
handleClickToUpload={handleClickToUpload}
handleDrop={handleDrop}
handleDragOver={handleDragOver}
Expand All @@ -69,11 +70,15 @@ function UploadCard({

{uploadedFileName && (
<div className="mt-4">

Check warning on line 72 in src/components/UploadCard.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/UploadCard.tsx#L72

Added line #L72 was not covered by tests
<Typography variant="body1" className="mb-2" data-cy="uploaded-datatable-file-name">
<Typography
variant="body1"
className="mb-2"
data-cy={`${title}-card-uploaded-file-name`}
>
<strong>{uploadedFileName}</strong>
</Typography>
<Button
data-cy="toggle-datatable-preview"
data-cy={`toggle-${title}-card-preview`}
variant="outlined"
onClick={togglePreview}
endIcon={isPreviewOpen ? <ExpandLess /> : <ExpandMore />}
Expand Down
26 changes: 14 additions & 12 deletions src/stores/data.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { act, renderHook } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { mockDataTable, mockInitialColumns } from '~/utils/mocks';
import fs from 'fs';
import path from 'path';
import useDataStore from './data';
import { mockHeaders, mockDataTable } from '../utils/mocks';

describe('store actions', () => {
it('should set dataTable', () => {
it('should process a file and update dataTable, columns, and uploadedDataTableFileName', async () => {
const { result } = renderHook(() => useDataStore());
act(() => {
result.current.setDataTable(mockDataTable);
});
expect(result.current.dataTable).toEqual(mockDataTable);
});

it('should initialize columns', () => {
const { result } = renderHook(() => useDataStore());
act(() => {
result.current.initializeColumns(mockHeaders);
const filePath = path.resolve(__dirname, '../../cypress/fixtures/examples/mock.tsv');
const fileContent = fs.readFileSync(filePath, 'utf-8');
const file = new File([fileContent], 'mock.tsv', { type: 'text/tab-separated-values' });

await act(async () => {
await result.current.processFile(file);
});
expect(result.current.columns).toEqual(mockHeaders);

expect(result.current.dataTable).toEqual(mockDataTable);
expect(result.current.columns).toEqual(mockInitialColumns);
expect(result.current.uploadedDataTableFileName).toEqual('mock.tsv');
});
});
63 changes: 36 additions & 27 deletions src/stores/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,42 @@ const useDataStore = create<DataStore>((set) => ({
initializeColumns: (data: Columns) => set({ columns: data }),

Check warning on line 19 in src/stores/data.ts

View check run for this annotation

Codecov / codecov/patch

src/stores/data.ts#L18-L19

Added lines #L18 - L19 were not covered by tests
setUploadedDataTableFileName: (fileName: string | null) =>
set({ uploadedDataTableFileName: fileName }),

Check warning on line 21 in src/stores/data.ts

View check run for this annotation

Codecov / codecov/patch

src/stores/data.ts#L21

Added line #L21 was not covered by tests
processFile: async (file: File) => {
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target?.result as string;
const rows = content.split('\n').map((row) => row.split('\t'));
const headers = rows[0];
const data = rows.slice(1);

// Transform data into column-based structure
const columnData: DataTable = {};
headers.forEach((_, columnIndex) => {
columnData[columnIndex + 1] = data.map((row) => row[columnIndex]);
});

const columns: Columns = headers.reduce((acc, header, index) => {
acc[index + 1] = { header };
return acc;
}, {} as Columns);

set({
dataTable: columnData,
columns,
uploadedDataTableFileName: file.name,
});
};
reader.readAsText(file);
},
processFile: async (file: File) =>
new Promise<void>((resolve, reject) => {
const reader = new FileReader();

reader.onload = (e) => {
const content = e.target?.result as string;
const rows = content.split('\n').map((row) => row.split('\t'));
const headers = rows[0];
const data = rows.slice(1);

// Transform data into column-based structure
const columnData: DataTable = {};
headers.forEach((_, columnIndex) => {
columnData[columnIndex + 1] = data.map((row) => row[columnIndex]);
});

const columns: Columns = headers.reduce((acc, header, index) => {
acc[index + 1] = { header };
return acc;
}, {} as Columns);

set({
dataTable: columnData,
columns,
uploadedDataTableFileName: file.name,
});

resolve();
};

reader.onerror = (error) => {
reject(error);

Check warning on line 53 in src/stores/data.ts

View check run for this annotation

Codecov / codecov/patch

src/stores/data.ts#L53

Added line #L53 was not covered by tests
};

reader.readAsText(file);
}),
}));

export default useDataStore;

0 comments on commit 331577f

Please sign in to comment.