Skip to content

Commit d20ba13

Browse files
authored
Merge pull request #35 from oslabs-beta/victor/marketplaceTest
Add marketplace and search bar tests
2 parents c84bdbb + b304b6d commit d20ba13

File tree

10 files changed

+233
-73
lines changed

10 files changed

+233
-73
lines changed

__tests__/BottomTabs.test.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
1-
import React from 'react';
2-
import { Provider } from 'react-redux';
31
import '@testing-library/jest-dom';
2+
43
import {
4+
fireEvent,
55
render,
66
screen,
7-
fireEvent,
87
waitFor,
98
within
109
} from '@testing-library/react';
10+
1111
import BottomTabs from '../app/src/components/bottom/BottomTabs';
12-
import ContextManager from '../app/src/components/ContextAPIManager/ContextManager';
13-
import store from '../app/src/redux/store';
12+
import { BrowserRouter } from 'react-router-dom';
1413
import ComponentPanel from '../app/src/components/right/ComponentPanel';
15-
import HTMLPanel from '../app/src/components/left/HTMLPanel';
16-
import StateManager from '../app/src/components/StateManagement/StateManagement';
14+
import ContextManager from '../app/src/components/ContextAPIManager/ContextManager';
1715
import CustomizationPanel from '../app/src/containers/CustomizationPanel';
18-
import { BrowserRouter } from 'react-router-dom';
19-
import DragDropPanel from '../app/src/components/left/DragDropPanel';
20-
import MainContainer from '../app/src/containers/MainContainer';
2116
import { DndProvider } from 'react-dnd';
17+
import DragDropPanel from '../app/src/components/left/DragDropPanel';
2218
import { HTML5Backend } from 'react-dnd-html5-backend';
19+
import HTMLPanel from '../app/src/components/left/HTMLPanel';
20+
import MainContainer from '../app/src/containers/MainContainer';
21+
import { Provider } from 'react-redux';
22+
import React from 'react';
23+
import StateManager from '../app/src/components/StateManagement/StateManagement';
24+
import store from '../app/src/redux/store';
2325

2426
describe('Bottom Panel Render Test', () => {
25-
test('should render all seven tabs', () => {
27+
test('should render all six tabs', () => {
2628
render(
2729
<Provider store={store}>
2830
<BottomTabs />
2931
</Provider>
3032
);
31-
expect(screen.getAllByRole('tab')).toHaveLength(7);
32-
expect(screen.getByText('Code Preview')).toBeInTheDocument();
33+
expect(screen.getAllByRole('tab')).toHaveLength(6);
34+
// expect(screen.getByText('Code Preview')).toBeInTheDocument();
3335
expect(screen.getByText('Component Tree')).toBeInTheDocument();
3436
expect(screen.getByText('Creation Panel')).toBeInTheDocument();
3537
expect(screen.getByText('Customization')).toBeInTheDocument();

__tests__/DragAndDrop.test.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import React from 'react';
21
import '@testing-library/jest-dom';
3-
import { DndProvider } from 'react-dnd';
4-
import { HTML5Backend } from 'react-dnd-html5-backend';
2+
53
import { fireEvent, render, screen } from '@testing-library/react';
6-
import DragDropPanel from '../app/src/components/left/DragDropPanel';
4+
75
import ComponentDrag from '../app/src/components/left/ComponentDrag';
6+
import { DndProvider } from 'react-dnd';
7+
import DragDropPanel from '../app/src/components/left/DragDropPanel';
8+
import { HTML5Backend } from 'react-dnd-html5-backend';
9+
import MainContainer from '../app/src/containers/MainContainer';
810
import { Provider } from 'react-redux';
11+
import React from 'react';
912
import store from '../app/src/redux/store';
10-
import MainContainer from '../app/src/containers/MainContainer';
1113
import { within } from '@testing-library/react';
1214

13-
1415
function TestContext(component) {
1516
return (
1617
<Provider store={store}>
@@ -48,7 +49,7 @@ describe('Drag and Drop Side Panel', () => {
4849
expect(screen.getByText('LinkTo')).toBeInTheDocument();
4950
});
5051

51-
test('Should render Roots Components and Reusbale components', () => {
52+
test.skip('Should render Roots Components and Reusbale components', () => {
5253
render(TestContext(<ComponentDrag />));
5354

5455
expect(screen.getByText('Root Components')).toBeInTheDocument();

__tests__/marketplace.test.tsx

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import '@testing-library/jest-dom/extend-expect';
2+
3+
import { fireEvent, render, screen } from '@testing-library/react';
4+
5+
import MarketplaceCard from '../app/src/components/marketplace/MarketplaceCard';
6+
import MarketplaceCardContainer from '../app/src/components/marketplace/MarketplaceCardContainer';
7+
import { Provider } from 'react-redux';
8+
import React from 'react';
9+
import SearchBar from '../app/src/components/marketplace/Searchbar';
10+
import axios from 'axios';
11+
import store from '../app/src/redux/store';
12+
13+
// Mocking the axios module to avoid actual network calls
14+
jest.mock('axios');
15+
jest.mock(
16+
'resources/marketplace_images/marketplace_image.png',
17+
() => 'mock-image-url'
18+
);
19+
20+
describe('MarketplaceCard Render Test', () => {
21+
const mockProject = {
22+
_id: 123,
23+
name: 'Sample Project',
24+
username: 'user123',
25+
forked: 'false',
26+
comments: [],
27+
createdAt: new Date(),
28+
likes: 0,
29+
project: {
30+
id: 'sample-project-id'
31+
},
32+
published: true,
33+
userId: 123456
34+
};
35+
36+
it('displays project name and username', () => {
37+
render(
38+
<Provider store={store}>
39+
<MarketplaceCard proj={mockProject} />
40+
</Provider>
41+
);
42+
43+
expect(screen.getByText('Sample Project')).toBeInTheDocument();
44+
expect(screen.getByText('user123')).toBeInTheDocument();
45+
});
46+
});
47+
48+
describe('MarketplaceContainer', () => {
49+
const mockProjects = [
50+
{
51+
_id: 1,
52+
name: 'Project 1',
53+
username: 'user1'
54+
},
55+
{
56+
_id: 2,
57+
name: 'Project 2',
58+
username: 'user2'
59+
}
60+
];
61+
62+
beforeEach(() => {
63+
// Set up mock axios call for every test
64+
axios.get = jest.fn().mockResolvedValue({ data: mockProjects });
65+
});
66+
67+
it('renders multiple MarketplaceCards', () => {
68+
render(
69+
<Provider store={store}>
70+
<MarketplaceCardContainer displayProjects={mockProjects} />
71+
</Provider>
72+
);
73+
74+
expect(screen.getByText('Project 1')).toBeInTheDocument();
75+
expect(screen.getByText('user1')).toBeInTheDocument();
76+
expect(screen.getByText('Project 2')).toBeInTheDocument();
77+
expect(screen.getByText('user2')).toBeInTheDocument();
78+
});
79+
});
80+
81+
const mockProjects = [
82+
{
83+
name: 'Sample Project',
84+
username: 'user123'
85+
},
86+
{
87+
name: 'Test Project',
88+
username: 'user_test'
89+
},
90+
{
91+
name: 'Hello Project',
92+
username: 'hello_user'
93+
}
94+
];
95+
96+
describe('SearchBar Component', () => {
97+
it('updates the text field value on change', () => {
98+
const updateDisplayProjects = jest.fn();
99+
100+
render(
101+
<SearchBar
102+
marketplaceProjects={mockProjects}
103+
updateDisplayProjects={updateDisplayProjects}
104+
/>
105+
);
106+
107+
const textField = screen.getByLabelText('Search') as HTMLInputElement;
108+
fireEvent.change(textField, { target: { value: 'Sample' } });
109+
110+
expect(textField.value).toBe('Sample');
111+
});
112+
113+
it('filters projects by username', () => {
114+
const updateDisplayProjects = jest.fn();
115+
116+
render(
117+
<SearchBar
118+
marketplaceProjects={mockProjects}
119+
updateDisplayProjects={updateDisplayProjects}
120+
/>
121+
);
122+
123+
const textField = screen.getByLabelText('Search');
124+
fireEvent.change(textField, { target: { value: 'test' } });
125+
126+
// Using setImmediate to wait for useEffect to execute.
127+
setTimeout(() => {
128+
expect(updateDisplayProjects).toHaveBeenCalledWith([
129+
{ name: 'Test Project', username: 'user_test' }
130+
]);
131+
});
132+
});
133+
});

app/src/components/marketplace/MarketplaceCard.tsx

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,74 +12,84 @@ import {
1212
Typography,
1313
styled
1414
} from '@mui/material';
15+
import MuiAlert, { AlertProps } from '@mui/material/Alert';
16+
import React, { useEffect } from 'react';
17+
import {
18+
openProject,
19+
resetAllState
20+
} from '../../redux/reducers/slice/appStateSlice';
21+
import { useDispatch, useSelector } from 'react-redux';
1522

1623
import { MoreVert } from '@mui/icons-material';
17-
import React, { useEffect } from 'react';
24+
import { RootState } from '../../redux/store';
25+
import Snackbar from '@mui/material/Snackbar';
26+
import axios from 'axios';
1827
import imageSrc from '../../../../resources/marketplace_images/marketplace_image.png';
1928
import { red } from '@mui/material/colors';
20-
import axios from 'axios';
21-
import { useDispatch, useSelector } from 'react-redux'
22-
import { RootState } from '../../redux/store';
2329
import { saveProject } from '../../helperFunctions/projectGetSaveDel';
2430
import { useHistory } from 'react-router-dom';
25-
import { openProject } from '../../redux/reducers/slice/appStateSlice';
26-
import MuiAlert, { AlertProps } from '@mui/material/Alert';
27-
import Snackbar from '@mui/material/Snackbar';
2831

2932
interface Project {
30-
forked: String,
31-
comments: string[]
32-
createdAt: Date
33-
likes: number
34-
name: string
35-
project: object
36-
published: boolean
37-
userId: number
38-
username: string
39-
_id: number
33+
forked: String;
34+
comments: string[];
35+
createdAt: Date;
36+
likes: number;
37+
name: string;
38+
project: object;
39+
published: boolean;
40+
userId: number;
41+
username: string;
42+
_id: number;
4043
}
4144

4245
const ITEM_HEIGHT = 48;
43-
const MarketplaceCard = ({proj} :{proj: Project}) => {
46+
const MarketplaceCard = ({ proj }: { proj: Project }) => {
4447
const dispatch = useDispatch();
4548
const history = useHistory();
4649
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
4750
const open = Boolean(anchorEl);
48-
const [alertOpen, setAlertOpen] = React.useState<boolean>(false)
49-
const state = useSelector((store:RootState) => store.appState);
51+
const [alertOpen, setAlertOpen] = React.useState<boolean>(false);
52+
const state = useSelector((store: RootState) => store.appState);
5053
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
5154
setAnchorEl(event.currentTarget);
5255
};
53-
const handleClone = async () => { // creates a copy of the project
56+
const handleClone = async () => {
57+
// creates a copy of the project
5458
const docId = proj._id;
55-
const response = await axios.get(`/cloneProject/${docId}`, { params: { username: window.localStorage.getItem('username') } });//passing in username as a query param is query params
59+
const response = await axios.get(`/cloneProject/${docId}`, {
60+
params: { username: window.localStorage.getItem('username') }
61+
}); //passing in username as a query param is query params
5662
const project = response.data.project;
5763
setAlertOpen(true);
5864
setAnchorEl(null);
59-
return {_id: project._id, name: project.name, published: project.published, ...project.project};
65+
return {
66+
_id: project._id,
67+
name: project.name,
68+
published: project.published,
69+
...project.project
70+
};
6071
};
61-
62-
const handleCloneOpen = async() => {
72+
73+
const handleCloneOpen = async () => {
6374
const project = await handleClone();
6475
history.push('/');
6576
dispatch(openProject(project));
6677
};
67-
78+
6879
const handleClose = () => {
6980
setAnchorEl(null);
7081
};
7182

72-
7383
const handleAlertClose = (
7484
event: React.SyntheticEvent | Event,
7585
reason?: string
76-
) => {
77-
if (reason === 'clickaway') {
78-
return;
79-
}
80-
setAlertOpen(false);
81-
setAnchorEl(null)
86+
) => {
87+
if (reason === 'clickaway') {
88+
return;
8289
}
90+
setAlertOpen(false);
91+
setAnchorEl(null);
92+
};
8393

8494
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(function Alert(
8595
props,
@@ -88,7 +98,6 @@ const MarketplaceCard = ({proj} :{proj: Project}) => {
8898
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
8999
});
90100

91-
92101
return (
93102
<>
94103
<Card
@@ -155,7 +164,7 @@ const MarketplaceCard = ({proj} :{proj: Project}) => {
155164
Clone and open
156165
</MenuItem>
157166
</Menu>
158-
<Snackbar
167+
<Snackbar
159168
open={alertOpen}
160169
autoHideDuration={3000}
161170
onClose={handleAlertClose}

app/src/components/marketplace/MarketplaceCardContainer.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import { Container, Grid } from '@mui/material';
33
import MarketplaceCard from './MarketplaceCard';
44
import React from 'react';
55

6-
7-
const MarketplaceCardContainer = ({displayProjects}) => {
8-
9-
6+
const MarketplaceCardContainer = ({ displayProjects }) => {
107
return (
118
<>
129
<Container>
@@ -17,9 +14,8 @@ const MarketplaceCardContainer = ({displayProjects}) => {
1714
columns={{ xs: 4, sm: 8, md: 12 }}
1815
>
1916
{displayProjects.map((proj, i) => (
20-
21-
<Grid item xs={4} sm={4} md={4} key={i}>
22-
<MarketplaceCard proj={proj}/>
17+
<Grid item xs={4} sm={4} md={4} key={proj._id}>
18+
<MarketplaceCard proj={proj} />
2319
</Grid>
2420
))}
2521
</Grid>

app/src/components/top/NavBarButtons.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,10 @@ function navbarDropDown(props) {
362362
</svg>
363363
</button>
364364
{/* {<ExportButton />} */}
365-
365+
{/*
366366
<button onClick={handleDarkModeToggle}>
367367
{isDarkMode ? 'Light' : 'Dark'} Mode {switchDark}
368-
</button>
368+
</button> */}
369369
{state.isLoggedIn && (
370370
<button onClick={handleClick}>
371371
Manage Project

0 commit comments

Comments
 (0)