Skip to content

Commit 3c9e78d

Browse files
authored
fix: resolve minification issues with Redux DevTools integration (#53)
* fix: fix Safari compatibility and TypeScript conversion * feat: implement routing with AppRoutes component and update index file
1 parent c321147 commit 3c9e78d

5 files changed

Lines changed: 317 additions & 103 deletions

File tree

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = {
2525
collectCoverage: true,
2626
collectCoverageFrom: [
2727
'src/**/*.{js,jsx,ts,tsx}',
28-
'!src/index.js',
28+
'!src/index.tsx',
2929
'!src/config/**',
3030
'!src/**/types.ts',
3131
'!src/**/mock_groups.js',

src/components/AppRoutes.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import { Routes, Route } from 'react-router-dom';
3+
4+
import LoginScreen from './LoginScreen';
5+
import App from './Main';
6+
import DashBoard from './DashBoard';
7+
import GroupList from './GroupList';
8+
import UnitList from './UnitList';
9+
import UnitMassEditPropertySelect from './UnitMassEditPropertySelect';
10+
import UnitMassEdit from './UnitMassEdit';
11+
import UnitDetails from './UnitDetails';
12+
import UnitHistory from './UnitHistory';
13+
import UpdateConfirmation from './UpdateConfirmation';
14+
import DeleteConfirmation from './DeleteConfirmation';
15+
import UpdateQueue from './UpdateQueue';
16+
import NotFound from './NotFound';
17+
18+
const AppRoutes: React.FC = () => {
19+
return (
20+
<Routes>
21+
<Route path="/login" element={<LoginScreen />} />
22+
<Route path="/" element={<App />}>
23+
<Route path="/" element={<DashBoard />} />
24+
<Route path="/group" element={<GroupList />} />
25+
<Route path="/group/:groupId" element={<UnitList />} />
26+
<Route path="/group/:groupId/mass-edit" element={<UnitMassEditPropertySelect />} />
27+
<Route path="/group/:groupId/mass-edit/:propertyId" element={<UnitMassEdit />} />
28+
<Route path="/unit/:unitId" element={<UnitDetails />} />
29+
<Route path="/unit/:unitId/history" element={<UnitHistory />} />
30+
<Route path="/unit/:unitId/update/:propertyId/:valueId" element={<UpdateConfirmation />} />
31+
<Route path="/unit/:unitId/delete/:propertyId" element={<DeleteConfirmation />} />
32+
<Route path="/queue" element={<UpdateQueue />} />
33+
<Route path="*" element={<NotFound />} />
34+
</Route>
35+
</Routes>
36+
);
37+
};
38+
39+
export default AppRoutes;
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import { MemoryRouter } from 'react-router-dom';
4+
5+
import AppRoutes from '../AppRoutes';
6+
7+
// Mock all the component imports to avoid deep rendering
8+
jest.mock('../LoginScreen', () => () => <div data-testid="login-screen">LoginScreen</div>);
9+
jest.mock('../Main', () => () => {
10+
const { Outlet } = require('react-router-dom');
11+
return (
12+
<div data-testid="main-component">
13+
<Outlet />
14+
</div>
15+
);
16+
});
17+
jest.mock('../DashBoard', () => () => <div data-testid="dashboard">DashBoard</div>);
18+
jest.mock('../GroupList', () => () => <div data-testid="group-list">GroupList</div>);
19+
jest.mock('../UnitList', () => () => <div data-testid="unit-list">UnitList</div>);
20+
jest.mock('../UnitMassEditPropertySelect', () => () => (
21+
<div data-testid="unit-mass-edit-property-select">UnitMassEditPropertySelect</div>
22+
));
23+
jest.mock('../UnitMassEdit', () => () => <div data-testid="unit-mass-edit">UnitMassEdit</div>);
24+
jest.mock('../UnitDetails', () => () => <div data-testid="unit-details">UnitDetails</div>);
25+
jest.mock('../UnitHistory', () => () => <div data-testid="unit-history">UnitHistory</div>);
26+
jest.mock('../UpdateConfirmation', () => () => (
27+
<div data-testid="update-confirmation">UpdateConfirmation</div>
28+
));
29+
jest.mock('../DeleteConfirmation', () => () => (
30+
<div data-testid="delete-confirmation">DeleteConfirmation</div>
31+
));
32+
jest.mock('../UpdateQueue', () => () => <div data-testid="update-queue">UpdateQueue</div>);
33+
jest.mock('../NotFound', () => () => <div data-testid="not-found">NotFound</div>);
34+
35+
describe('AppRoutes Component', () => {
36+
const renderWithRouter = (initialEntries: string[] = ['/']) => {
37+
return render(
38+
<MemoryRouter
39+
initialEntries={initialEntries}
40+
future={{ v7_startTransition: true, v7_relativeSplatPath: true }}
41+
>
42+
<AppRoutes />
43+
</MemoryRouter>
44+
);
45+
};
46+
47+
beforeEach(() => {
48+
jest.clearAllMocks();
49+
});
50+
51+
describe('Route Structure', () => {
52+
it('renders the Routes component', () => {
53+
renderWithRouter();
54+
// The component should render without errors
55+
expect(document.body).toBeInTheDocument();
56+
});
57+
58+
it('renders LoginScreen for /login route', () => {
59+
renderWithRouter(['/login']);
60+
expect(screen.getByTestId('login-screen')).toBeInTheDocument();
61+
expect(screen.queryByTestId('main-component')).not.toBeInTheDocument();
62+
});
63+
64+
it('renders Main component wrapper for root route', () => {
65+
renderWithRouter(['/']);
66+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
67+
expect(screen.getByTestId('dashboard')).toBeInTheDocument();
68+
});
69+
70+
it('renders GroupList for /group route', () => {
71+
renderWithRouter(['/group']);
72+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
73+
expect(screen.getByTestId('group-list')).toBeInTheDocument();
74+
});
75+
76+
it('renders NotFound for unknown routes', () => {
77+
renderWithRouter(['/unknown-path']);
78+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
79+
expect(screen.getByTestId('not-found')).toBeInTheDocument();
80+
});
81+
});
82+
83+
describe('Nested Routes with Parameters', () => {
84+
it('renders UnitList for /group/:groupId route', () => {
85+
renderWithRouter(['/group/test-group']);
86+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
87+
expect(screen.getByTestId('unit-list')).toBeInTheDocument();
88+
});
89+
90+
it('renders UnitDetails for /unit/:unitId route', () => {
91+
renderWithRouter(['/unit/123']);
92+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
93+
expect(screen.getByTestId('unit-details')).toBeInTheDocument();
94+
});
95+
96+
it('renders UnitHistory for /unit/:unitId/history route', () => {
97+
renderWithRouter(['/unit/123/history']);
98+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
99+
expect(screen.getByTestId('unit-history')).toBeInTheDocument();
100+
});
101+
102+
it('renders UnitMassEditPropertySelect for /group/:groupId/mass-edit route', () => {
103+
renderWithRouter(['/group/test-group/mass-edit']);
104+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
105+
expect(screen.getByTestId('unit-mass-edit-property-select')).toBeInTheDocument();
106+
});
107+
108+
it('renders UnitMassEdit for /group/:groupId/mass-edit/:propertyId route', () => {
109+
renderWithRouter(['/group/test-group/mass-edit/property1']);
110+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
111+
expect(screen.getByTestId('unit-mass-edit')).toBeInTheDocument();
112+
});
113+
114+
it('renders UpdateConfirmation for /unit/:unitId/update/:propertyId/:valueId route', () => {
115+
renderWithRouter(['/unit/123/update/property1/value1']);
116+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
117+
expect(screen.getByTestId('update-confirmation')).toBeInTheDocument();
118+
});
119+
120+
it('renders DeleteConfirmation for /unit/:unitId/delete/:propertyId route', () => {
121+
renderWithRouter(['/unit/123/delete/property1']);
122+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
123+
expect(screen.getByTestId('delete-confirmation')).toBeInTheDocument();
124+
});
125+
126+
it('renders UpdateQueue for /queue route', () => {
127+
renderWithRouter(['/queue']);
128+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
129+
expect(screen.getByTestId('update-queue')).toBeInTheDocument();
130+
});
131+
});
132+
133+
describe('Route Nesting Structure', () => {
134+
it('does not nest login route under Main component', () => {
135+
renderWithRouter(['/login']);
136+
expect(screen.getByTestId('login-screen')).toBeInTheDocument();
137+
expect(screen.queryByTestId('main-component')).not.toBeInTheDocument();
138+
});
139+
140+
it('nests all protected routes under Main component', () => {
141+
const protectedRoutes = [
142+
'/',
143+
'/group',
144+
'/group/test-group',
145+
'/group/test-group/mass-edit',
146+
'/group/test-group/mass-edit/property1',
147+
'/unit/123',
148+
'/unit/123/history',
149+
'/unit/123/update/property1/value1',
150+
'/unit/123/delete/property1',
151+
'/queue',
152+
'/unknown-path'
153+
];
154+
155+
protectedRoutes.forEach(route => {
156+
const { unmount } = renderWithRouter([route]);
157+
expect(screen.getByTestId('main-component')).toBeInTheDocument();
158+
unmount();
159+
});
160+
});
161+
});
162+
163+
describe('Route Matching Specificity', () => {
164+
it('matches most specific route for nested paths', () => {
165+
// Should match /unit/:unitId/history, not /unit/:unitId
166+
renderWithRouter(['/unit/123/history']);
167+
expect(screen.getByTestId('unit-history')).toBeInTheDocument();
168+
expect(screen.queryByTestId('unit-details')).not.toBeInTheDocument();
169+
});
170+
171+
it('matches catch-all route for unmatched nested paths', () => {
172+
renderWithRouter(['/unit/123/some/unknown/path']);
173+
expect(screen.getByTestId('not-found')).toBeInTheDocument();
174+
});
175+
176+
it('matches exact route for root path', () => {
177+
renderWithRouter(['/']);
178+
expect(screen.getByTestId('dashboard')).toBeInTheDocument();
179+
expect(screen.queryByTestId('group-list')).not.toBeInTheDocument();
180+
});
181+
});
182+
});

src/index.js

Lines changed: 0 additions & 102 deletions
This file was deleted.

0 commit comments

Comments
 (0)