Skip to content

Commit

Permalink
Merge branch 'main' into chore/entire-codebase-validation
Browse files Browse the repository at this point in the history
Merged
  • Loading branch information
acescudero committed Dec 13, 2024
2 parents ea969c8 + 804576b commit e5a1740
Show file tree
Hide file tree
Showing 23 changed files with 610 additions and 310 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private void validateRequest(FetcherRequest request) {
String.format("Expected fetcher_type 'direct_fetcher', but got '%s'",
request.getFetcherTypeCase().toString().toLowerCase()));
}
if (request.getDirectFetcher().getDirectType() != DirectType.DEPARTMENTS) {
if (request.getDirectFetcher().getDirectType() != DirectType.DIRECT_TYPE_DEPARTMENTS) {
throw new IllegalArgumentException(String.format(
"Expected DirectType 'DEPARTMENTS', but got '%s'. This fetcher only supports DEPARTMENTS type",
request.getDirectFetcher().getDirectType()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private void validateConfig(ModuleConfig moduleConfig) {
}

private FetcherResponse handleDirectFetcher(FetcherRequest request) {
if (request.getDirectFetcher().getDirectType() == DirectType.DEPARTMENTS) {
if (request.getDirectFetcher().getDirectType() == DirectType.DIRECT_TYPE_DEPARTMENTS) {
return departmentFetcher.fetch(request);
}
// Add more cases as we add more direct types.
Expand All @@ -64,7 +64,7 @@ private FetcherResponse handleDirectFetcher(FetcherRequest request) {

private FetcherResponse handleFilteredFetcher(FetcherRequest request) {
if (request.getFilteredFetcher()
.getFilteredType() == FilteredType.PROJECTS) {
.getFilteredType() == FilteredType.FILTERED_TYPE_PROJECTS) {
return projectFetcher.fetch(request);
}
// Add more cases as we add more filtered types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public ResponseEntity<List<DepartmentDTO>> getProjects() {
ModuleConfig moduleConfig = ModuleConfig.newBuilder()
.setFetcherRequest(
FetcherRequest.newBuilder().setFilteredFetcher(FilteredFetcher
.newBuilder().setFilteredType(FilteredType.PROJECTS)))
.newBuilder().setFilteredType(FilteredType.FILTERED_TYPE_PROJECTS)))
.build();
ModuleResponse moduleResponse = moduleInvoker.processConfig(moduleConfig);
return ResponseEntity.ok(moduleResponse.getFetcherResponse()
Expand Down
7 changes: 4 additions & 3 deletions backend/src/main/proto/fetcher/fetcher_module.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ message FetcherRequest {
oneof fetcher_type {
DirectFetcher direct_fetcher = 1;
FilteredFetcher filtered_fetcher = 2;
// We will need a filtered fetcher type in the future.
}
}

Expand All @@ -25,7 +24,8 @@ message DirectFetcher {
}

enum DirectType {
DEPARTMENTS = 0;
DIRECT_TYPE_UNSPECIFIED = 0;
DIRECT_TYPE_DEPARTMENTS = 1;
// Add more if needed, e.g. Majors, Umbrella topics, etc.
}

Expand All @@ -34,6 +34,7 @@ message FilteredFetcher {
}

enum FilteredType {
PROJECTS = 0;
FILTERED_TYPE_UNSPECIFIED = 0;
FILTERED_TYPE_PROJECTS = 1;
// Add more if needed, e.g. Students.
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void testFetch_validRequest_returnsExpectedResponse() {

FetcherRequest request = FetcherRequest.newBuilder()
.setDirectFetcher(
DirectFetcher.newBuilder().setDirectType(DirectType.DEPARTMENTS))
DirectFetcher.newBuilder().setDirectType(DirectType.DIRECT_TYPE_DEPARTMENTS))
.build();
FetcherResponse response = departmentFetcher.fetch(request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void setUp() {
public void testProcessConfig_validRequest_directType_returnsExpectedResponse() {
FetcherRequest mockRequest = FetcherRequest.newBuilder()
.setDirectFetcher(
DirectFetcher.newBuilder().setDirectType(DirectType.DEPARTMENTS))
DirectFetcher.newBuilder().setDirectType(DirectType.DIRECT_TYPE_DEPARTMENTS))
.build();

FetcherResponse mockResponse = FetcherResponse.newBuilder()
Expand All @@ -64,7 +64,7 @@ public void testProcessConfig_validRequest_directType_returnsExpectedResponse()
public void testProcessConfig_validRequest_filteredType_returnsExpectedResponse() {
FetcherRequest mockRequest = FetcherRequest.newBuilder()
.setFilteredFetcher(
FilteredFetcher.newBuilder().setFilteredType(FilteredType.PROJECTS))
FilteredFetcher.newBuilder().setFilteredType(FilteredType.FILTERED_TYPE_PROJECTS))
.build();

MajorWithProjects majorWithProjects =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void testFetch_validRequest_returnsExpectedResponse() {

FetcherRequest request = FetcherRequest.newBuilder()
.setFilteredFetcher(
FilteredFetcher.newBuilder().setFilteredType(FilteredType.PROJECTS))
FilteredFetcher.newBuilder().setFilteredType(FilteredType.FILTERED_TYPE_PROJECTS))
.build();
FetcherResponse response = projectFetcher.fetch(request);

Expand Down Expand Up @@ -141,7 +141,7 @@ public void testFetch_projectWithMultipleMajors_returnsCorrectHierarchy() {
// Execute test
FetcherRequest request = FetcherRequest.newBuilder()
.setFilteredFetcher(
FilteredFetcher.newBuilder().setFilteredType(FilteredType.PROJECTS))
FilteredFetcher.newBuilder().setFilteredType(FilteredType.FILTERED_TYPE_PROJECTS))
.build();
FetcherResponse response = projectFetcher.fetch(request);

Expand Down Expand Up @@ -237,7 +237,7 @@ public void testFetch_projectInMultipleDepartments_returnsCorrectHierarchy() {
// Execute test
FetcherRequest request = FetcherRequest.newBuilder()
.setFilteredFetcher(
FilteredFetcher.newBuilder().setFilteredType(FilteredType.PROJECTS))
FilteredFetcher.newBuilder().setFilteredType(FilteredType.FILTERED_TYPE_PROJECTS))
.build();
FetcherResponse response = projectFetcher.fetch(request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void setUp() {
public void testProcessConfig_validFetcherRequest_returnsExpectedResponse() {
FetcherRequest mockRequest = FetcherRequest.newBuilder()
.setDirectFetcher(
DirectFetcher.newBuilder().setDirectType(DirectType.DEPARTMENTS))
DirectFetcher.newBuilder().setDirectType(DirectType.DIRECT_TYPE_DEPARTMENTS))
.build();
FetcherResponse mockResponse = FetcherResponse.newBuilder()
.setDepartmentCollection(
Expand Down
Binary file added frontend/public/USD_Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/USD_Logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/USD_Logo.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
Expand All @@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>OUR SEARCH</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
4 changes: 2 additions & 2 deletions frontend/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
"type": "image/x-icon"
},
{
"src": "logo192.png",
"src": "USD_Logo.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"src": "USD_Logo.png",
"type": "image/png",
"sizes": "512x512"
}
Expand Down
72 changes: 41 additions & 31 deletions frontend/src/__tests__/MainAccordion.test.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,51 @@
import React, { act } from 'react'
import React from 'react'
import { render, screen } from '@testing-library/react'
import MainAccordion from '../components/MainAccordion'
import { mockResearchOps } from '../resources/mockData'
import { errorLoadingPostingsMessage } from '../resources/constants'
import userEvent from '@testing-library/user-event'
import MajorAccordion from '../components/MajorAccordion'
import { mockMajorNoPosts, mockMajorOnePost } from '../resources/mockData'

const mockSetSelectedPost = jest.fn()
describe('MajorAccordion', () => {
const mockSetSelectedPost = jest.fn()

describe('MainAccordion', () => {
test('renders correct number of departments and majors', () => {
render(<MainAccordion
postings={mockResearchOps}
setSelectedPost={mockSetSelectedPost}
isStudent
/>)
test('renders major name', () => {
render(
<MajorAccordion
major={mockMajorNoPosts}
numPosts={mockMajorNoPosts.posts.length}
setSelectedPost={mockSetSelectedPost}
isStudent
/>
)

mockResearchOps.forEach(department => {
const departmentHeader = screen.getByText(department.name)
expect(departmentHeader).toBeInTheDocument()
// Find the major name using test ID instead of text content
// to account for multiple elements that include the name of the
// major.
const majorNameEl = screen.getByTestId('major-name')
expect(majorNameEl).toHaveTextContent(mockMajorNoPosts.name)
expect(screen.getByText('(0 opportunities)')).toBeInTheDocument()
})

// Expand the accordion to check for majors
act(() => {
departmentHeader.click()
})
test('renders posts for the major', async () => {
render(
<MajorAccordion
major={mockMajorOnePost}
numPosts={mockMajorOnePost.posts.length}
setSelectedPost={mockSetSelectedPost}
isStudent
/>
)

department.majors.forEach(major => {
expect(screen.getByText(major.name)).toBeInTheDocument()
})
})
})
// Find the major name using test ID
const majorNameEl = screen.getByTestId('major-name')
expect(majorNameEl).toHaveTextContent(mockMajorOnePost.name)
expect(screen.getByText('(1 opportunities)')).toBeInTheDocument()

test('renders message if no students/research opportunities exist', () => {
render(<MainAccordion
postings={[]}
setSelectedPost={mockSetSelectedPost}
isStudent
/>)
// Find and click the accordion summary
const accordionButton = screen.getByRole('button')
await userEvent.click(accordionButton)

expect(screen.getByText(errorLoadingPostingsMessage)).toBeInTheDocument()
// After expansion, verify the post content
const firstPostName = mockMajorOnePost.posts[0].name
expect(screen.getByText(firstPostName)).toBeInTheDocument()
})
})
65 changes: 43 additions & 22 deletions frontend/src/__tests__/MajorAccordion.test.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,56 @@
import React, { act } from 'react'
import { render, screen } from '@testing-library/react'
import React from 'react'
import { render, screen, act, within } from '@testing-library/react'
import MajorAccordion from '../components/MajorAccordion'
import { mockMajorNoPosts, mockMajorOnePost } from '../resources/mockData'

describe('MajorAccordion', () => {
const mockSetSelectedPost = jest.fn()

test('renders major name', () => {
render(<MajorAccordion
major={mockMajorNoPosts}
setSelectedPost={mockSetSelectedPost}
isStudent
/>)
describe('MajorAccordion', function () {
function getMockSetSelectedPost () {
return jest.fn()
}

it('renders major name with 0 opportunities', function () {
render(
<MajorAccordion
major={mockMajorNoPosts}
numPosts={mockMajorNoPosts.posts.length}
setSelectedPost={getMockSetSelectedPost()}
isStudent
/>
)
expect(screen.getByText(mockMajorNoPosts.name)).toBeInTheDocument()
expect(screen.getByText('(0 opportunities)')).toBeInTheDocument()
})

test('renders posts for the major', () => {
render(<MajorAccordion
major={mockMajorOnePost}
setSelectedPost={mockSetSelectedPost}
isStudent
/>)
it('renders major name and posts when present', function () {
render(
<MajorAccordion
major={mockMajorOnePost}
numPosts={mockMajorOnePost.posts.length}
setSelectedPost={getMockSetSelectedPost()}
isStudent
/>
)

// Find the expandable summary button
const majorButton = screen.getByRole('button', {
name: new RegExp(`${mockMajorOnePost.name}.*\\(${mockMajorOnePost.posts.length} opportunities\\)`, 'i')
})

expect(majorButton).toBeInTheDocument()

const majorHeader = screen.getByText(mockMajorOnePost.name)
expect(majorHeader).toBeInTheDocument()
// Check for the major name within the summary (button)
expect(within(majorButton).getByText(mockMajorOnePost.name)).toBeInTheDocument()

// Expand the accordion to check for posts
// Expand the accordion
act(() => {
majorHeader.click()
expect(screen.getByText(mockMajorOnePost.posts[0].name)).toBeInTheDocument() // refer to post[0] because there is only one post in this mock data
majorButton.click()
})

// After expansion, find the region and check for the post name
const accordionRegion = screen.getByRole('region')
expect(accordionRegion).toBeInTheDocument()

const postName = mockMajorOnePost.posts[0].name
expect(within(accordionRegion).getByText(postName)).toBeInTheDocument()
})
})
3 changes: 2 additions & 1 deletion frontend/src/__tests__/PostDialog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ describe('PostDialog Component', () => {

// Faculty
expect(screen.getByText('Faculty:')).toBeInTheDocument()
expect(screen.getByText('John Doe ([email protected])')).toBeInTheDocument()
expect(screen.getByText('John Doe')).toBeInTheDocument()
expect(screen.getByText('[email protected]')).toBeInTheDocument()
})

it('renders the close button and triggers onClose when clicked', () => {
Expand Down
Loading

0 comments on commit e5a1740

Please sign in to comment.