-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2596 from OneCommunityGlobal/niketha_project_reload
Niketha Anand- Rotate indefinitely after adding project
- Loading branch information
Showing
3 changed files
with
156 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,87 @@ | ||
/********************************************************************************* | ||
* Component: postProject | ||
* Author: Henry Ng - 01/17/20 | ||
* This component is used to add more project into the database | ||
********************************************************************************/ | ||
import React, { useState } from 'react'; | ||
import React, { useState } from 'react'; | ||
|
||
const AddProject = props => { | ||
const [showAddButton, setShowAddButton] = useState(false); | ||
const [newName, setNewName] = useState(''); | ||
const [newCategory, setNewCategory] = useState('Unspecified'); | ||
|
||
const changeNewName = newName => { | ||
if (newName.length !== 0) { | ||
setShowAddButton(true); | ||
} else { | ||
const AddProject = props => { | ||
const [showAddButton, setShowAddButton] = useState(false); | ||
const [newName, setNewName] = useState(''); | ||
const [newCategory, setNewCategory] = useState('Unspecified'); | ||
const [loading, setLoading] = useState(false); | ||
|
||
const changeNewName = name => { | ||
if (name.length !== 0) { | ||
setShowAddButton(true); | ||
} else { | ||
setShowAddButton(false); | ||
} | ||
setNewName(name); | ||
}; | ||
|
||
const handleAddProject = () => { | ||
setLoading(true); // Start loading | ||
Promise.resolve(props.onAddNewProject(newName, newCategory)) | ||
.then(() => { | ||
// Reset fields after the project is added | ||
setNewName(''); | ||
setNewCategory('Unspecified'); | ||
setShowAddButton(false); | ||
} | ||
setNewName(newName); | ||
}; | ||
|
||
return ( | ||
<div className="input-group" id="new_project"> | ||
<div className="input-group-prepend"> | ||
<span className="input-group-text">Add new project</span> | ||
</div> | ||
<input | ||
type="text" | ||
className="form-control" | ||
aria-label="New Project" | ||
placeholder="Project Name (required) type to add." | ||
onChange={e => changeNewName(e.target.value)} | ||
/> | ||
<div className="input-group-append"> | ||
<select onChange={e => setNewCategory(e.target.value)}> | ||
<option default value="Unspecified"> | ||
Select Category | ||
</option> | ||
<option value="Food">Food</option> | ||
<option value="Energy">Energy</option> | ||
<option value="Housing">Housing</option> | ||
<option value="Education">Education</option> | ||
<option value="Society">Society</option> | ||
<option value="Economics">Economics</option> | ||
<option value="Stewardship">Stewardship</option> | ||
<option value="Other">Other</option> | ||
</select> | ||
</div> | ||
<div className="input-group-append"> | ||
{showAddButton ? ( | ||
<button | ||
className="btn btn-outline-primary" | ||
type="button" | ||
onClick={() => props.onAddNewProject(newName, newCategory)} | ||
> | ||
<i className="fa fa-plus" aria-hidden="true"></i> | ||
</button> | ||
) : null} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
}) | ||
.finally(() => { | ||
setLoading(false); // Stop loading | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="input-group" id="new_project"> | ||
<div className="input-group-prepend"> | ||
<span className="input-group-text">Add new project</span> | ||
</div> | ||
<input | ||
type="text" | ||
className="form-control" | ||
aria-label="New Project" | ||
placeholder="Project Name (required) type to add." | ||
value={newName} | ||
onChange={e => changeNewName(e.target.value)} | ||
disabled={loading} | ||
/> | ||
<div className="input-group-append"> | ||
<select | ||
value={newCategory} | ||
onChange={e => setNewCategory(e.target.value)} | ||
disabled={loading} | ||
> | ||
<option default value="Unspecified"> | ||
Select Category | ||
</option> | ||
<option value="Food">Food</option> | ||
<option value="Energy">Energy</option> | ||
<option value="Housing">Housing</option> | ||
<option value="Education">Education</option> | ||
<option value="Society">Society</option> | ||
<option value="Economics">Economics</option> | ||
<option value="Stewardship">Stewardship</option> | ||
<option value="Other">Other</option> | ||
</select> | ||
</div> | ||
<div className="input-group-append"> | ||
{showAddButton && ( | ||
<button | ||
className="btn btn-outline-primary" | ||
type="button" | ||
onClick={handleAddProject} | ||
disabled={loading} | ||
> | ||
{loading ? ( | ||
<i className="fa fa-spinner fa-spin" aria-hidden="true"></i> | ||
) : ( | ||
<i className="fa fa-plus" aria-hidden="true"></i> | ||
)} | ||
</button> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AddProject; | ||
|
||
|
||
export default AddProject; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,94 +1,90 @@ | ||
import AddProject from './AddProject'; | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import { render, screen, fireEvent, act } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
|
||
//helper function | ||
// Helper function | ||
const typeIntoInput = ({ input }) => { | ||
const inputField = screen.getByRole('textbox'); | ||
|
||
if (input) { | ||
userEvent.type(inputField, input) | ||
userEvent.type(inputField, input); | ||
} | ||
|
||
return { | ||
inputField | ||
} | ||
} | ||
inputField, | ||
}; | ||
}; | ||
|
||
describe("AddProject component structure", () => { | ||
describe('AddProject component structure', () => { | ||
beforeEach(() => { | ||
render(<AddProject />); | ||
}); | ||
|
||
beforeEach(() => { | ||
render(<AddProject />) | ||
}) | ||
|
||
test("it renders correctly", () => { | ||
expect(screen.getByText("Add new project")).toBeInTheDocument(); | ||
}) | ||
test('it renders correctly', () => { | ||
expect(screen.getByText('Add new project')).toBeInTheDocument(); | ||
}); | ||
|
||
test("input field should initially be empty", () => { | ||
test('input field should initially be empty', () => { | ||
expect(screen.getByRole('textbox').value).toBe(''); | ||
}) | ||
}); | ||
|
||
test("select element should initially have a value of unspecified", () => { | ||
test('select element should initially have a value of unspecified', () => { | ||
expect(screen.getByRole('combobox').value).toBe('Unspecified'); | ||
}) | ||
}); | ||
|
||
test("button should not be in the document when the input field is empty", () => { | ||
test('button should not be in the document when the input field is empty', () => { | ||
expect(screen.queryByRole('button')).toBeNull(); | ||
}) | ||
}); | ||
|
||
test("user should be able to type in the input field", () => { | ||
test('user should be able to type in the input field', () => { | ||
const { inputField } = typeIntoInput({ input: 'New Project Name' }); | ||
expect(inputField.value).toBe('New Project Name'); | ||
}) | ||
}); | ||
|
||
test("user should be able to select a category", () => { | ||
test('user should be able to select a category', () => { | ||
userEvent.selectOptions(screen.getByRole('combobox'), 'Food'); | ||
expect(screen.getByRole('option', { name: 'Food' }).selected).toBe(true); | ||
}) | ||
}); | ||
|
||
test("button should appear when user types in the input field", () => { | ||
test('button should appear when user types in the input field', () => { | ||
typeIntoInput({ input: '123' }); | ||
expect(screen.queryByRole('button')).not.toBeNull(); | ||
}) | ||
}) | ||
}); | ||
}); | ||
|
||
describe('AddProject component state handlers', () => { | ||
|
||
//mock the onAddNewProject function | ||
|
||
const mockAddNewProject = jest.fn(); | ||
// Mock the onAddNewProject function | ||
const mockAddNewProject = jest.fn().mockResolvedValueOnce(); | ||
|
||
beforeEach(() => { | ||
render(<AddProject onAddNewProject={mockAddNewProject} />) | ||
render(<AddProject onAddNewProject={mockAddNewProject} />); | ||
}); | ||
|
||
test("Input change handler updates state correctly", () => { | ||
test('Input change handler updates state correctly', () => { | ||
const inputField = screen.getByRole('textbox'); | ||
|
||
fireEvent.change(inputField, { target: { value: 'New Project' } }); | ||
|
||
expect(inputField.value).toBe('New Project'); | ||
}) | ||
}); | ||
|
||
test("Select change handler updates state correctly", () => { | ||
test('Select change handler updates state correctly', () => { | ||
const selectElement = screen.getByRole('combobox'); | ||
fireEvent.change(selectElement, { target: { value: 'Food' } }); | ||
expect(selectElement.value).toBe('Food'); | ||
}) | ||
}); | ||
|
||
test('Button click handler calls onAddNewProject with correct arguments', () => { | ||
test('Button click handler calls onAddNewProject with correct arguments', async () => { | ||
const inputField = screen.getByRole('textbox'); | ||
const selectElement = screen.getByRole('combobox'); | ||
|
||
fireEvent.change(inputField, { target: { value: 'New Project' } }); | ||
fireEvent.change(selectElement, { target: { value: 'Food' } }); | ||
|
||
const buttonElement = screen.queryByRole('button'); | ||
|
||
fireEvent.click(buttonElement); | ||
const buttonElement = screen.getByRole('button'); | ||
|
||
expect(mockAddNewProject).toHaveBeenLastCalledWith('New Project', 'Food'); | ||
}) | ||
}) | ||
await act(async () => { | ||
fireEvent.click(buttonElement); | ||
}); | ||
|
||
expect(mockAddNewProject).toHaveBeenCalledWith('New Project', 'Food'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters