@conorheffron/ironoc-frontend 7.0.2 → 7.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -2
- package/src/App.css +26 -0
- package/src/App.js +26 -14
- package/src/App.test.js +337 -53
- package/src/AppNavbar.js +94 -57
- package/src/Footer.js +14 -8
- package/src/LoadingSpinner.js +15 -8
- package/src/components/About.js +41 -32
- package/src/components/CoffeeCarousel.js +21 -17
- package/src/components/CoffeeHome.js +37 -28
- package/src/components/ControlledCarousel.js +76 -87
- package/src/components/Donate.js +130 -0
- package/src/components/Home.js +50 -23
- package/src/components/NotFound.js +13 -9
- package/src/components/RepoDetails.js +61 -50
- package/src/components/RepoIssues.js +65 -52
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conorheffron/ironoc-frontend",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"dependencies": {
|
|
6
|
+
"@fontsource/montserrat": "^5.1.1",
|
|
7
|
+
"@fontsource/open-sans": "^5.1.1",
|
|
6
8
|
"@testing-library/user-event": "^13.5.0",
|
|
7
9
|
"axios": "^0.28.0",
|
|
8
10
|
"bootstrap": "5.1",
|
|
@@ -15,11 +17,12 @@
|
|
|
15
17
|
"react-dom": "^18.3.1",
|
|
16
18
|
"react-router-dom": "^5.3.0",
|
|
17
19
|
"reactstrap": "^8.10.0",
|
|
20
|
+
"recharts": "^3.0.0-alpha.5",
|
|
18
21
|
"web-vitals": "^4.2.3"
|
|
19
22
|
},
|
|
20
23
|
"scripts": {
|
|
21
24
|
"start": "react-scripts start",
|
|
22
|
-
"build": "CI=false && react-scripts build",
|
|
25
|
+
"build": "CI=false && GENERATE_SOURCEMAP=false react-scripts build",
|
|
23
26
|
"test": "react-scripts test",
|
|
24
27
|
"eject": "react-scripts eject"
|
|
25
28
|
},
|
package/src/App.css
CHANGED
|
@@ -37,6 +37,16 @@
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
.App-header, .body, .table-headers, .table, .mb-3 {
|
|
41
|
+
font-family: "Open Sans";
|
|
42
|
+
font-size: 1.4em;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.nav-bar, .ft, h1, h3 {
|
|
46
|
+
font-family: "Montserrat";
|
|
47
|
+
font-size: 1.1em;
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
.carousel-caption {
|
|
41
51
|
top: 0;
|
|
42
52
|
bottom: auto;
|
|
@@ -74,6 +84,10 @@
|
|
|
74
84
|
width: 51;
|
|
75
85
|
}
|
|
76
86
|
|
|
87
|
+
.carousel-caption {
|
|
88
|
+
font-family: "Open Sans";
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
.carousel-caption h3, h5 {
|
|
78
92
|
color: navy;
|
|
79
93
|
}
|
|
@@ -94,3 +108,15 @@ p a {
|
|
|
94
108
|
height: auto;
|
|
95
109
|
margin: 0 auto;
|
|
96
110
|
}
|
|
111
|
+
|
|
112
|
+
.overview-text {
|
|
113
|
+
display: block;
|
|
114
|
+
font-size: 1rem; /* Adjust the base font-size as needed */
|
|
115
|
+
line-height: 1.5;
|
|
116
|
+
white-space: normal;
|
|
117
|
+
word-wrap: break-word;
|
|
118
|
+
overflow-wrap: break-word;
|
|
119
|
+
max-height: 200px; /* Set a max height to avoid overflow */
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
text-overflow: ellipsis; /* Add ellipsis for text overflow */
|
|
122
|
+
}
|
package/src/App.js
CHANGED
|
@@ -3,6 +3,7 @@ import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
|
|
|
3
3
|
import './App.css';
|
|
4
4
|
import Home from './components/Home';
|
|
5
5
|
import CoffeeHome from './components/CoffeeHome';
|
|
6
|
+
import Donate from './components/Donate';
|
|
6
7
|
import NotFound from './components/NotFound';
|
|
7
8
|
import About from './components/About';
|
|
8
9
|
import RepoDetails from './components/RepoDetails';
|
|
@@ -11,21 +12,32 @@ import ControlledCarousel from './components/ControlledCarousel';
|
|
|
11
12
|
|
|
12
13
|
class App extends Component {
|
|
13
14
|
render() {
|
|
15
|
+
// Default props
|
|
16
|
+
const {
|
|
17
|
+
forceRefresh = true,
|
|
18
|
+
routes = [
|
|
19
|
+
{ path: '/', exact: true, component: Home },
|
|
20
|
+
{ path: '/about', exact: true, component: About },
|
|
21
|
+
{ path: '/portfolio', exact: true, component: ControlledCarousel },
|
|
22
|
+
{ path: '/projects', exact: true, component: RepoDetails },
|
|
23
|
+
{ path: '/projects/:id', component: RepoDetails },
|
|
24
|
+
{ path: '/issues/:id/:repo', component: RepoIssues },
|
|
25
|
+
{ path: '/brews', exact: true, component: CoffeeHome },
|
|
26
|
+
{ path: '/donate', exact: true, component: Donate },
|
|
27
|
+
{ path: '*', component: NotFound }
|
|
28
|
+
]
|
|
29
|
+
} = this.props;
|
|
30
|
+
|
|
14
31
|
return (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<Route path=
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<Route path='/brews' exact={true} component={CoffeeHome}/>
|
|
24
|
-
<Route path="*" component={NotFound} />
|
|
25
|
-
</Switch>
|
|
26
|
-
</Router>
|
|
27
|
-
)
|
|
32
|
+
<Router forceRefresh={forceRefresh}>
|
|
33
|
+
<Switch>
|
|
34
|
+
{routes.map((route, index) => (
|
|
35
|
+
<Route key={index} path={route.path} exact={route.exact} component={route.component} />
|
|
36
|
+
))}
|
|
37
|
+
</Switch>
|
|
38
|
+
</Router>
|
|
39
|
+
);
|
|
28
40
|
}
|
|
29
41
|
}
|
|
30
42
|
|
|
31
|
-
export default App;
|
|
43
|
+
export default App;
|
package/src/App.test.js
CHANGED
|
@@ -1,97 +1,381 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, waitFor } from '@testing-library/react';
|
|
2
|
+
import { render, screen, act, waitFor, fireEvent } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
4
|
import Home from './components/Home';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import App from './App';
|
|
7
7
|
import CoffeeCarousel from './components/CoffeeCarousel';
|
|
8
8
|
import CoffeeHome from './components/CoffeeHome';
|
|
9
|
+
import Donate from './components/Donate';
|
|
9
10
|
import NotFound from './components/NotFound';
|
|
11
|
+
import { createMemoryHistory } from 'history';
|
|
12
|
+
import { Router, MemoryRouter } from 'react-router-dom';
|
|
13
|
+
import RepoDetails from './components/RepoDetails';
|
|
14
|
+
import RepoIssues from './components/RepoIssues';
|
|
15
|
+
import LoadingSpinner from './LoadingSpinner';
|
|
16
|
+
import AppNavBar from './AppNavbar';
|
|
10
17
|
|
|
11
18
|
// Mocking axios
|
|
12
19
|
jest.mock('axios');
|
|
13
20
|
|
|
14
|
-
test('renders learn react link', () => {
|
|
15
|
-
render(<Home />);
|
|
16
|
-
const element = screen.getByText(/Home/i);
|
|
17
|
-
expect(element).toBeInTheDocument();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
21
|
// Sample data for testing
|
|
21
22
|
const coffeeItems = [
|
|
23
|
+
{
|
|
24
|
+
title: 'Espresso',
|
|
25
|
+
ingredients: ['Water', 'Coffee beans'],
|
|
26
|
+
image: 'https://example.com/espresso.jpg',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
title: 'Cappuccino',
|
|
30
|
+
ingredients: ['Espresso', 'Steamed milk', 'Foam milk'],
|
|
31
|
+
image: 'https://example.com/cappuccino.jpg',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const mockRepoDetails = [
|
|
36
|
+
{
|
|
37
|
+
name: 'repo1',
|
|
38
|
+
fullName: 'User/repo1',
|
|
39
|
+
repoUrl: 'https://github.com/User/repo1',
|
|
40
|
+
description: 'Description of repo1',
|
|
41
|
+
appHome: 'https://repo1.com',
|
|
42
|
+
topics: ['topic1', 'topic2']
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'repo2',
|
|
46
|
+
fullName: 'User/repo2',
|
|
47
|
+
repoUrl: 'https://github.com/User/repo2',
|
|
48
|
+
description: 'Description of repo2',
|
|
49
|
+
appHome: 'https://repo2.com',
|
|
50
|
+
topics: ['topic3', 'topic4']
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const mockRepoIssues = [
|
|
55
|
+
{
|
|
56
|
+
number: 1,
|
|
57
|
+
title: 'Issue 1',
|
|
58
|
+
body: 'https://github.com/User/repo/issues/1'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
number: 2,
|
|
62
|
+
title: 'Issue 2',
|
|
63
|
+
body: 'https://github.com/User/repo/issues/2'
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const donateItems = [
|
|
22
68
|
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
69
|
+
donate: "https://www.jackandjill.ie/professionals/ways-to-donate/",
|
|
70
|
+
link: "https://www.jackandjill.ie",
|
|
71
|
+
img: "red1.png",
|
|
72
|
+
alt: "red1",
|
|
73
|
+
name: "The Jack and Jill Children’s Foundation",
|
|
74
|
+
overview: `The Jack and Jill Children’s Foundation is a nationwide charity that funds and provides in-home nursing care
|
|
75
|
+
and respite support for children with severe to profound neurodevelopmental delay, up to the age of 6.
|
|
76
|
+
This may include children with brain injury, genetic diagnosis, cerebral palsy and undiagnosed conditions.
|
|
77
|
+
Another key part of our service is end-of-life care for all children up to the age of 6, irrespective of diagnosis.`,
|
|
78
|
+
founded: 1997,
|
|
79
|
+
phone: "+353 (045) 894 538"
|
|
26
80
|
},
|
|
27
81
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
82
|
+
donate: "https://vi.ie/supporting-us/donate-now/",
|
|
83
|
+
link: "https://linktr.ee/vision_ireland",
|
|
84
|
+
img: "red2.png",
|
|
85
|
+
alt: "red2",
|
|
86
|
+
name: "Vision Ireland, the new name for NCBI",
|
|
87
|
+
overview: `Vision Ireland, the name for NCBI is Ireland’s national charity working for the rising number of people affected by sight loss.
|
|
88
|
+
Our practical and emotional advice and support help 8,000 people and their families confidently face their futures every year.`,
|
|
89
|
+
founded: 1931,
|
|
90
|
+
phone: "+353 (0)1 830 7033"
|
|
91
|
+
}
|
|
92
|
+
// Add more items as needed
|
|
32
93
|
];
|
|
33
94
|
|
|
95
|
+
describe('Home', () => {
|
|
96
|
+
test('renders Home component', async () => {
|
|
97
|
+
await act(async () => {
|
|
98
|
+
render(<Home />);
|
|
99
|
+
});
|
|
100
|
+
const element = screen.getByText(/Home/i);
|
|
101
|
+
expect(element).toBeInTheDocument();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
34
105
|
describe('CoffeeCarousel', () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
106
|
+
test('renders carousel with coffee items', () => {
|
|
107
|
+
render(<CoffeeCarousel items={coffeeItems} />);
|
|
108
|
+
|
|
109
|
+
// Check that the carousel items are rendered
|
|
110
|
+
coffeeItems.forEach((item) => {
|
|
111
|
+
expect(screen.getByText(item.title)).toBeInTheDocument();
|
|
112
|
+
expect(screen.getByAltText(item.title)).toBeInTheDocument();
|
|
113
|
+
expect(screen.getByText(item.ingredients.join(', '))).toBeInTheDocument();
|
|
44
114
|
});
|
|
115
|
+
});
|
|
45
116
|
|
|
46
|
-
|
|
47
|
-
|
|
117
|
+
test('renders carousel with correct number of items', () => {
|
|
118
|
+
render(<CoffeeCarousel items={coffeeItems} />);
|
|
48
119
|
|
|
49
|
-
|
|
50
|
-
|
|
120
|
+
// Check that the correct number of carousel items are rendered
|
|
121
|
+
const carouselItems = screen.getAllByRole('img');
|
|
51
122
|
|
|
52
|
-
|
|
53
|
-
|
|
123
|
+
expect(carouselItems.length).toBe(coffeeItems.length);
|
|
124
|
+
});
|
|
54
125
|
});
|
|
55
126
|
|
|
56
127
|
describe('CoffeeHome', () => {
|
|
57
|
-
|
|
58
|
-
|
|
128
|
+
beforeEach(() => {
|
|
129
|
+
axios.get.mockResolvedValueOnce({ data: coffeeItems });
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('renders AppNavbar component', () => {
|
|
133
|
+
render(<App />);
|
|
134
|
+
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('displays loading state initially', () => {
|
|
138
|
+
render(<CoffeeHome />);
|
|
139
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('renders CoffeeCarousel component with coffee items', async () => {
|
|
143
|
+
render(<CoffeeHome />);
|
|
144
|
+
|
|
145
|
+
// Wait for the coffee items to be fetched and rendered
|
|
146
|
+
await waitFor(() => {
|
|
147
|
+
expect(screen.getByText('Espresso')).toBeInTheDocument();
|
|
148
|
+
expect(screen.getByText('Cappuccino')).toBeInTheDocument();
|
|
59
149
|
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('NotFound', () => {
|
|
154
|
+
test('renders AppNavbar component', () => {
|
|
155
|
+
render(<NotFound />);
|
|
156
|
+
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('displays 404 error message', () => {
|
|
160
|
+
render(<NotFound />);
|
|
161
|
+
expect(screen.getByText('404 - Page Not Found')).toBeInTheDocument();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test('displays the apology message', () => {
|
|
165
|
+
render(<NotFound />);
|
|
166
|
+
expect(screen.getByText('Sorry, the page you are looking for could not be found.')).toBeInTheDocument();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
60
169
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
170
|
+
describe('RepoDetails', () => {
|
|
171
|
+
beforeEach(() => {
|
|
172
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
173
|
+
json: jest.fn().mockResolvedValue(mockRepoDetails)
|
|
64
174
|
});
|
|
175
|
+
});
|
|
65
176
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
177
|
+
afterEach(() => {
|
|
178
|
+
jest.restoreAllMocks();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('renders AppNavbar component', () => {
|
|
182
|
+
render(<App />);
|
|
183
|
+
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('renders loading state initially', () => {
|
|
187
|
+
render(<RepoDetails match={{ params: { id: 'User' } }} />);
|
|
188
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('displays repo details after fetching data', async () => {
|
|
192
|
+
const history = createMemoryHistory();
|
|
193
|
+
const { container } = render(
|
|
194
|
+
<Router history={history}>
|
|
195
|
+
<RepoDetails match={{ params: { id: 'User' } }} />
|
|
196
|
+
</Router>
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// Wait for the component to finish loading
|
|
200
|
+
await waitFor(() => {
|
|
201
|
+
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
|
69
202
|
});
|
|
70
203
|
|
|
71
|
-
|
|
72
|
-
|
|
204
|
+
// Check that repo details are displayed
|
|
205
|
+
mockRepoDetails.forEach(repo => {
|
|
206
|
+
expect(screen.getByText(repo.fullName)).toBeInTheDocument();
|
|
207
|
+
expect(screen.queryByText(repo.repoUrl)).not.toBeInTheDocument();
|
|
208
|
+
expect(screen.getByText(repo.description)).toBeInTheDocument();
|
|
209
|
+
expect(screen.queryByText(repo.appHome)).not.toBeInTheDocument();
|
|
73
210
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
211
|
+
repo.topics.forEach(topic => {
|
|
212
|
+
// Select the <td> element
|
|
213
|
+
const tdElement = screen.getByText((content, element) => {
|
|
214
|
+
// Ensure the element is a <td>
|
|
215
|
+
return element.tagName.toLowerCase() === 'td' && content.includes(topic);
|
|
78
216
|
});
|
|
217
|
+
// Check if the <td> contains the expected text
|
|
218
|
+
expect(tdElement).toBeInTheDocument();
|
|
219
|
+
expect(tdElement).toHaveTextContent(topic);
|
|
220
|
+
});
|
|
79
221
|
});
|
|
222
|
+
|
|
223
|
+
// Verify that the component does not show the loading spinner
|
|
224
|
+
expect(container.querySelector('.LoadingSpinner')).not.toBeInTheDocument();
|
|
225
|
+
});
|
|
80
226
|
});
|
|
81
227
|
|
|
82
|
-
describe('
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
228
|
+
describe('RepoIssues', () => {
|
|
229
|
+
beforeEach(() => {
|
|
230
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
231
|
+
json: jest.fn().mockResolvedValue(mockRepoIssues)
|
|
86
232
|
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
afterEach(() => {
|
|
236
|
+
jest.restoreAllMocks();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('renders AppNavbar component', () => {
|
|
240
|
+
render(<App />);
|
|
241
|
+
expect(screen.getByRole('banner')).toBeInTheDocument();
|
|
242
|
+
});
|
|
87
243
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
244
|
+
test('renders loading state initially', () => {
|
|
245
|
+
render(<RepoIssues match={{ params: { id: 'User', repo: 'ironoc-test' } }} />);
|
|
246
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test('displays repo issues after fetching data', async () => {
|
|
250
|
+
const history = createMemoryHistory();
|
|
251
|
+
const { container } = render(
|
|
252
|
+
<Router history={history}>
|
|
253
|
+
<RepoIssues match={{ params: { id: 'conors-id', repo: 'ironoc-testing' } }} />
|
|
254
|
+
</Router>
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
// Wait for the component to finish loading
|
|
258
|
+
await waitFor(() => {
|
|
259
|
+
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(screen.queryByText('conors-id')).toBeInTheDocument();
|
|
263
|
+
expect(screen.queryByText('ironoc-testing')).toBeInTheDocument();
|
|
264
|
+
|
|
265
|
+
// Check that repo issues are displayed
|
|
266
|
+
mockRepoIssues.forEach(issue => {
|
|
267
|
+
expect(screen.getByText(issue.title)).toBeInTheDocument();
|
|
268
|
+
expect(screen.getByText(issue.body)).toBeInTheDocument();
|
|
269
|
+
expect(screen.getByText(issue.number)).toBeInTheDocument();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Verify that the component does not show the loading spinner
|
|
273
|
+
expect(container.querySelector('.LoadingSpinner')).not.toBeInTheDocument();
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe('LoadingSpinner', () => {
|
|
278
|
+
test('renders LoadingSpinner component correctly', () => {
|
|
279
|
+
// Render the component
|
|
280
|
+
const { getByRole, getByText } = render(<LoadingSpinner />);
|
|
281
|
+
|
|
282
|
+
// Check if the button is present and disabled
|
|
283
|
+
const button = getByRole('button');
|
|
284
|
+
expect(button).toBeInTheDocument();
|
|
285
|
+
expect(button).toBeDisabled();
|
|
286
|
+
|
|
287
|
+
// Check if the spinner is present
|
|
288
|
+
const spinner = getByRole('button');
|
|
289
|
+
expect(spinner).toBeInTheDocument();
|
|
290
|
+
|
|
291
|
+
// Check if the button contains the text "Loading..."
|
|
292
|
+
const loadingText = getByText('Loading...');
|
|
293
|
+
expect(loadingText).toBeInTheDocument();
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
describe('AppNavBar', () => {
|
|
298
|
+
test('renders AppNavBar component correctly', () => {
|
|
299
|
+
// Render the component
|
|
300
|
+
render(<AppNavBar />);
|
|
301
|
+
|
|
302
|
+
// Check if the Navbar is present
|
|
303
|
+
const navbar = screen.getByRole('navigation');
|
|
304
|
+
expect(navbar).toBeInTheDocument();
|
|
305
|
+
|
|
306
|
+
// Check if the logo image is present
|
|
307
|
+
const logo = screen.getByAltText('');
|
|
308
|
+
expect(logo).toBeInTheDocument();
|
|
309
|
+
expect(logo).toHaveAttribute('src', 'robot-logo.png');
|
|
310
|
+
|
|
311
|
+
// Check if the "Brews" dropdown is present
|
|
312
|
+
const brewsDropdown = screen.getByText('Brews');
|
|
313
|
+
expect(brewsDropdown).toBeInTheDocument();
|
|
314
|
+
|
|
315
|
+
// Check if the "Portfolio" dropdown is present
|
|
316
|
+
const portfolioDropdown = screen.getByText('Portfolio');
|
|
317
|
+
expect(portfolioDropdown).toBeInTheDocument();
|
|
318
|
+
|
|
319
|
+
// Check if the "About" dropdown is present
|
|
320
|
+
const aboutDropdown = screen.getByText('About');
|
|
321
|
+
expect(aboutDropdown).toBeInTheDocument();
|
|
322
|
+
|
|
323
|
+
// Check if the "GitHub PM" dropdown is present
|
|
324
|
+
const githubPMDropdown = screen.getByText('GitHub PM');
|
|
325
|
+
expect(githubPMDropdown).toBeInTheDocument();
|
|
326
|
+
|
|
327
|
+
// Check if the "GitHub API" dropdown is present
|
|
328
|
+
const githubAPIDropdown = screen.getByText('GitHub API');
|
|
329
|
+
expect(githubAPIDropdown).toBeInTheDocument();
|
|
330
|
+
|
|
331
|
+
// Check if the "GitHub Projects" dropdown is present
|
|
332
|
+
const githubProjectsDropdown = screen.getByText('GitHub Projects');
|
|
333
|
+
expect(githubProjectsDropdown).toBeInTheDocument();
|
|
334
|
+
|
|
335
|
+
// Check if the "GitHub Projects" dropdown is present
|
|
336
|
+
const donateDropdown = screen.getByText('Charity Options');
|
|
337
|
+
expect(donateDropdown).toBeInTheDocument();
|
|
338
|
+
|
|
339
|
+
// Check if the "Home" link is present
|
|
340
|
+
const homeLink = screen.getByText('Home');
|
|
341
|
+
expect(homeLink).toBeInTheDocument();
|
|
342
|
+
expect(homeLink.closest('a')).toHaveAttribute('href', '/');
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
describe('App Component Routing', () => {
|
|
347
|
+
test("sends the user to about", () => {
|
|
348
|
+
const history = createMemoryHistory({ initialEntries: ["/about"] });
|
|
349
|
+
render(
|
|
350
|
+
<Router history={history}>
|
|
351
|
+
<App />
|
|
352
|
+
</Router>
|
|
353
|
+
);
|
|
354
|
+
expect(history.location.pathname).toBe("/about");
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
describe('Donate Component', () => {
|
|
359
|
+
test('renders without crashing', () => {
|
|
360
|
+
render(<Donate items={donateItems} />);
|
|
361
|
+
expect(screen.getByText('The Jack and Jill Children’s Foundation')).toBeInTheDocument();
|
|
362
|
+
expect(screen.getByText('Vision Ireland, the new name for NCBI')).toBeInTheDocument();
|
|
91
363
|
});
|
|
92
364
|
|
|
93
|
-
test('
|
|
94
|
-
render(<
|
|
95
|
-
|
|
365
|
+
test('renders all carousel items', () => {
|
|
366
|
+
render(<Donate items={donateItems} />);
|
|
367
|
+
donateItems.forEach(item => {
|
|
368
|
+
expect(screen.getByText(item.name)).toBeInTheDocument();
|
|
369
|
+
expect(screen.getByText(new RegExp(`Founded in ${item.founded}`))).toBeInTheDocument();
|
|
370
|
+
expect(screen.getByText(item.phone)).toBeInTheDocument();
|
|
371
|
+
expect(screen.getByText(new RegExp(item.link))).toBeInTheDocument();
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test('renders images with correct alt text', () => {
|
|
376
|
+
render(<Donate items={donateItems} />);
|
|
377
|
+
donateItems.forEach(item => {
|
|
378
|
+
expect(screen.getByAltText(item.alt)).toBeInTheDocument();
|
|
379
|
+
});
|
|
96
380
|
});
|
|
97
381
|
});
|