Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ticket 23 #26

Merged
merged 69 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
e213c3e
Pull DB changes from dev into ticket-29 (#12)
Somnus22 Sep 26, 2024
8b6cf46
feat(api): complete backend endpoint for creating request
Sep 26, 2024
13e4cc8
feat(api): complete backend endpoint for creating request
Sep 26, 2024
7aa0bae
feat(api): backend endpoint for creating request
Sep 29, 2024
039fa3e
Squashed commit of the following:
Somnus22 Sep 29, 2024
6959ce4
feat(frontend): add TypeScript types to Apply components
Somnus22 Sep 29, 2024
543d062
fix(frontend): correct TypeScript declarations for Flowbite Datepicker
Somnus22 Sep 29, 2024
1d0b36a
Merge branch 'dev_wfh' into TICKET-29
Somnus22 Sep 29, 2024
fdc15ea
update index.tsx
Somnus22 Sep 29, 2024
b01e358
fix(branch): resolve conflicts and align with remote
Somnus22 Sep 29, 2024
42e6950
fix(branch): resolve conflicts and align with remote
Somnus22 Sep 29, 2024
c444049
fix(branch): resolve conflicts and align with remote
Somnus22 Sep 29, 2024
ed4aed1
fix(tailwind): correct tailwind.config.ts settings
Somnus22 Sep 29, 2024
39b1285
feat(frontend): implement modal for form submission feedback, impleme…
Somnus22 Sep 30, 2024
59355e8
bug fix/chore: Fixed autoincrement in Request.sql insertion script
zavierr01 Sep 30, 2024
09b97ac
chore(frontend): add commented axios POST for future backend integration
Somnus22 Sep 30, 2024
7e8dfa0
chore(frontend): adjusted commented axios POST for future backend int…
Somnus22 Sep 30, 2024
64930ea
chore(frontend): adjusted commented axios POST for future backend int…
Somnus22 Sep 30, 2024
039e33d
fix(backend-api): brief description of the fix
Somnus22 Oct 1, 2024
61be6b1
Merge branch 'dev_wfh' into TICKET-29
Somnus22 Oct 1, 2024
7769174
feat(db): implement schema changes for work-from-home requests
Somnus22 Oct 2, 2024
2fa9237
Merge branch 'dev_wfh' into TICKET-29
Somnus22 Oct 2, 2024
15b9988
Update index.tsx
Somnus22 Oct 2, 2024
e30993a
feat(api): Created an API to get proportion of team that is working f…
solai-y Oct 2, 2024
7aa2123
feat(api): API to get request proportion by date
solai-y Oct 3, 2024
1f802d8
feat(api): Reject request endpoint created
solai-y Oct 3, 2024
7784777
feat(api): Approve Request endpoint
solai-y Oct 3, 2024
857ddee
feat(api): Added check for request batch
solai-y Oct 3, 2024
3d8b423
Test (Requests): Test cases for requests API endpoints
solai-y Oct 3, 2024
05d60a7
tests(requests): Added more test cases for proportion of team
solai-y Oct 4, 2024
e42aa0c
fix(proportions): Gets proportion of approved requests
solai-y Oct 4, 2024
8cb9252
Fix(Proportion): Error with status
solai-y Oct 4, 2024
218a94d
fix(50% error): Issues with checking the 50% attendance in office fixed
solai-y Oct 4, 2024
0d00015
Merge branch 'dev_wfh' into TICKET-23
zavierr01 Oct 4, 2024
a92c08c
feat: Added Feature to approve and reject requests
zavierr01 Oct 4, 2024
c84b014
chore(style): Update minor styling
zavierr01 Oct 4, 2024
f3612a4
chore(styling): Changed calendaView content logic
zavierr01 Oct 4, 2024
19c83f4
feat: add automatic rejection of 'Pending' requests after 2 months
neojw1505 Oct 4, 2024
81e143f
test: add job removal check for non-pending requests after 2 months
neojw1505 Oct 4, 2024
3e5b610
test(error codes): Updated error codes
solai-y Oct 5, 2024
f4f99e2
Fix (error 500): Approval endpoint caused error 500
solai-y Oct 5, 2024
14142bf
Merge branch 'TICKET-29' of https://github.com/e-tayfw/WorkFromHome i…
neojw1505 Oct 5, 2024
5c5578e
chore(variables): removed variables that were not being used
solai-y Oct 5, 2024
2e0115e
feat(api): add staff withdraw request APIs and test cases
neojw1505 Oct 5, 2024
6816e75
chore(integration): Removed not needed variables
zavierr01 Oct 7, 2024
ba2863d
feat: Added WIthdraw Functionality to Withdraw Requests
zavierr01 Oct 8, 2024
5c457b8
test(createRequest): created test cases for the create request endpoint
solai-y Oct 8, 2024
c9cf9b4
feat(api): update withdrawRequest API implementation and rewrite test…
neojw1505 Oct 8, 2024
9a4012b
feat: Added refresh on change of status
zavierr01 Oct 8, 2024
2c38256
fix(bug): Added automatic refresh & Fixed Integration
zavierr01 Oct 8, 2024
aa4a99f
feat: Added Withdraw button for Withdraw Rejected requests
zavierr01 Oct 8, 2024
3b1f9a1
chore(UI): Fixed UI for staff with no direct reports
zavierr01 Oct 8, 2024
6bd432c
test(approveRequest)
solai-y Oct 8, 2024
2fe0e01
Merge branch 'TICKET-29' into TICKET-23
solai-y Oct 8, 2024
42b071e
test(approve request)
solai-y Oct 9, 2024
235fdf8
test(reject request)
solai-y Oct 9, 2024
d796fa1
feat(withdraw reqeusts)
solai-y Oct 9, 2024
55a10c8
feat (integration): Updated frontend to approve and reject withdraw r…
zavierr01 Oct 11, 2024
d1ed210
chore (eslint): Update typing
zavierr01 Oct 11, 2024
36d75b3
feat(UI): Added Filtering by status and pagination
zavierr01 Oct 14, 2024
c305b49
feat(ui): Added search by staff name
zavierr01 Oct 14, 2024
d71f19d
feat(UI): Added search by staff name
zavierr01 Oct 14, 2024
e31c5e0
Merge branch 'TICKET-23' of https://github.com/e-tayfw/WorkFromHome i…
solai-y Oct 14, 2024
27f0ca3
fix (FE import)
solai-y Oct 14, 2024
581859c
chore (tests): Added JEST testing
zavierr01 Oct 14, 2024
2ed104e
Merge branch 'dev_wfh' into TICKET-23
solai-y Oct 15, 2024
6c2cfcb
dependencies: update to yarn dependencies
e-tayfw Oct 15, 2024
838fc63
Bug (Characters > 255)
solai-y Oct 16, 2024
3ad4381
Merge branch 'dev_wfh' into TICKET-23
solai-y Oct 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions backend-api/app/Http/Controllers/RequestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ public function approveRequest(Request $request)
return response()->json(['message' => "You are not allowed to approve this request"], 400);
}

if (strlen($reason) > 255) {
$reason = substr($reason, 0, 255);
}

if ($requestDB->Status == 'Withdraw Pending' && $status == 'Withdrawn') {
$newRequestLog = new RequestLog();
$newRequestLog->Request_ID = $requestDB->Request_ID;
Expand Down Expand Up @@ -481,6 +485,10 @@ public function rejectRequest(Request $request)
return response()->json(['message' => "Reason was not provided"], 401);
}

if (strlen($reason) > 255) {
$reason = substr($reason, 0, 255);
}

// check if the requst is already rejected
if ($requestDB->Status == "Withdraw Rejected") {
return response()->json(['message' => "Request was already Withdraw Rejected"], 400);
Expand Down
142 changes: 142 additions & 0 deletions test/ApproveActionHandler.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Swal from 'sweetalert2';
import { toast } from 'react-toastify';
import ActionHandler from '@/components/approve/actionHandler';
import { Provider } from 'react-redux';
import { createStore } from 'redux';

// Mock the Redux store
const mockStore = createStore(() => ({
auth: { staffId: '12345' },
}));

// Mock React Toastify
jest.mock('react-toastify', () => ({
toast: {
success: jest.fn(),
error: jest.fn(),
},
}));

// Mock SweetAlert2
jest.mock('sweetalert2', () => ({
fire: jest.fn(),
}));

// Setup axios mock adapter
const mock = new MockAdapter(axios);

describe('ActionHandler Component', () => {
const mockProps = {
requestId: 1,
requestorId: 123,
dateRequested: '2024-10-13',
requestBatch: 'Batch A',
duration: 'AM',
status: 'pending',
onWithdraw: jest.fn(),
isDisabled: false,
proportionAfterApproval: 0.5,
onRefreshRequests: jest.fn(),
};

beforeEach(() => {
mock.reset(); // Reset the axios mock before each test
});

it('should display the Approve button and handle approval correctly', async () => {
// Mock Swal.fire for approval scenario
(Swal.fire as jest.Mock).mockResolvedValueOnce({ isConfirmed: true, value: 'Optional comments' });

mock.onPost('http://127.0.0.1:8085/api/approveRequest').reply(200, {
message: 'The request has been approved successfully!',
});

render(
<Provider store={mockStore}>
<ActionHandler {...mockProps} />
</Provider>
);

const approveButton = screen.getByText('Approve');
fireEvent.click(approveButton);

await waitFor(() => expect(Swal.fire).toHaveBeenCalled());
await waitFor(() => expect(mock.history.post.length).toBe(1));
await waitFor(() =>
expect(mock.history.post[0].data).toContain('Optional comments')
);

expect(toast.success).toHaveBeenCalledWith('The request has been approved successfully!', {
position: 'top-right',
});
expect(mockProps.onRefreshRequests).toHaveBeenCalled();
});

it('should display the Reject button and handle rejection with reason', async () => {
// Mock Swal.fire for rejection scenario
(Swal.fire as jest.Mock).mockResolvedValueOnce({ isConfirmed: true, value: 'Rejection reason' });

mock.onPost('http://127.0.0.1:8085/api/rejectRequest').reply(200, {
message: 'The request has been rejected successfully!',
});

render(
<Provider store={mockStore}>
<ActionHandler {...mockProps} status="withdraw pending" />
</Provider>
);

const rejectButton = screen.getByText('Reject');
fireEvent.click(rejectButton);

await waitFor(() => expect(Swal.fire).toHaveBeenCalled());
await waitFor(() => expect(mock.history.post.length).toBe(1));
await waitFor(() =>
expect(mock.history.post[0].data).toContain('Rejection reason')
);

expect(toast.success).toHaveBeenCalledWith('The request has been rejected successfully!', {
position: 'top-right',
});
expect(mockProps.onRefreshRequests).toHaveBeenCalled();
});

it('should handle the Withdraw action and call the onWithdraw prop', async () => {
mock.onPost('http://127.0.0.1:8085/api/withdrawRequest').reply(200, {
message: 'The request has been withdrawn successfully!',
});

render(
<Provider store={mockStore}>
<ActionHandler {...mockProps} status="approved" />
</Provider>
);

const withdrawButton = screen.getByText('Withdraw');
fireEvent.click(withdrawButton);

await waitFor(() => expect(mock.history.post.length).toBe(1));
expect(mock.history.post[0].data).toContain('Request_ID');
expect(toast.success).toHaveBeenCalledWith('The request has been withdrawn successfully!', {
position: 'top-right',
});
expect(mockProps.onWithdraw).toHaveBeenCalledWith(mockProps.requestId);
expect(mockProps.onRefreshRequests).toHaveBeenCalled();
});

it('should disable the Approve button when isDisabled is true', () => {
render(
<Provider store={mockStore}>
<ActionHandler {...mockProps} isDisabled={true} />
</Provider>
);

const approveButton = screen.getByText('Approve');
expect(approveButton).toBeDisabled();
});
});
57 changes: 57 additions & 0 deletions test/ApproveTable.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import ApproveTable from '@/components/approve/table'; // Adjust the import path as necessary
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import '@testing-library/jest-dom';

// Create a mock Redux store
const mockStore = configureMockStore();
const store = mockStore({
auth: {
staffId: 123,
},
});

// Mock data for employees
const mockEmployees = [
{ Staff_ID: 1, Staff_FName: 'John', Staff_LName: 'Doe' },
{ Staff_ID: 2, Staff_FName: 'Jane', Staff_LName: 'Smith' },
{ Staff_ID: 3, Staff_FName: 'Jake', Staff_LName: 'Johnson' },
];

describe('ApproveTable Component', () => {
it('should display all employees\' full names (first + last name)', () => {
render(
<Provider store={store}>
<ApproveTable employees={mockEmployees} />
</Provider>
);

// Check if all employees' full names are rendered on the screen
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('Jane Smith')).toBeInTheDocument();
expect(screen.getByText('Jake Johnson')).toBeInTheDocument();
});

it('should filter employees based on the search term', () => {
render(
<Provider store={store}>
<ApproveTable employees={mockEmployees} />
</Provider>
);

// Find the search input by its role
const searchInput = screen.getByRole('textbox', { name: /search by name/i });

// Simulate typing 'John' into the search input
fireEvent.change(searchInput, { target: { value: 'John' } });

// Check if only the employees whose names include 'John' are displayed
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('Jake Johnson')).toBeInTheDocument();

// Check if 'Jane Smith' is not displayed (since it doesn't match 'John')
expect(screen.queryByText('Jane Smith')).not.toBeInTheDocument();
});
});
60 changes: 52 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,58 @@
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==

"@floating-ui/[email protected]":
version "1.6.6"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.6.tgz#f6edf703c8acb73e3802cf558c88ddb7cddc4f67"
integrity sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ==
dependencies:
"@floating-ui/utils" "^0.2.6"

"@floating-ui/core@^1.6.0":
version "1.6.8"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.8.tgz#aa43561be075815879305965020f492cdb43da12"
integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
dependencies:
"@floating-ui/utils" "^0.2.8"

"@floating-ui/dom@^1.0.0":
version "1.6.11"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.11.tgz#8631857838d34ee5712339eb7cbdfb8ad34da723"
integrity sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==
dependencies:
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.8"

"@floating-ui/react-dom@^2.1.1", "@floating-ui/react-dom@^2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
dependencies:
"@floating-ui/dom" "^1.0.0"

"@floating-ui/[email protected]":
version "0.26.21"
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.21.tgz#29fe23a5197650d48eb1b05c5c46ff61df368fb6"
integrity sha512-7P5ncDIiYd6RrwpCDbKyFzvabM014QlzlumtDbK3Bck0UueC+Rp8BLS34qcGBcN1pZCTodl4QNnCVmKv4tSxfQ==
dependencies:
"@floating-ui/react-dom" "^2.1.1"
"@floating-ui/utils" "^0.2.6"
tabbable "^6.0.0"

"@floating-ui/react@^0.26.23":
version "0.26.24"
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.24.tgz#072b9dfeca4e79ef4e3000ef1c28e0ffc86f4ed4"
integrity sha512-2ly0pCkZIGEQUq5H8bBK0XJmc1xIK/RM3tvVzY3GBER7IOD1UgmC2Y2tjj4AuS+TC+vTE1KJv2053290jua0Sw==
dependencies:
"@floating-ui/react-dom" "^2.1.2"
"@floating-ui/utils" "^0.2.8"
tabbable "^6.0.0"

"@floating-ui/utils@^0.2.6", "@floating-ui/utils@^0.2.8":
version "0.2.8"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==

"@fortawesome/[email protected]":
version "6.6.0"
resolved "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz"
Expand Down Expand Up @@ -2871,14 +2923,6 @@ bluebird@^3.7.2:
resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==

brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"

brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
Expand Down
Loading