-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into ft-product-display-##187419124
- Loading branch information
Showing
12 changed files
with
452 additions
and
2 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
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 |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import "@testing-library/jest-dom"; | ||
import { | ||
render, | ||
screen, | ||
fireEvent, | ||
act, | ||
waitFor, | ||
} from "@testing-library/react"; | ||
import { Provider } from "react-redux"; | ||
import { BrowserRouter as Router } from "react-router-dom"; | ||
import configureStore from "redux-mock-store"; | ||
import { thunk } from "redux-thunk"; | ||
import { ToastContainer } from "react-toastify"; | ||
|
||
import UpdatePasswordmod from "../components/password/updateModal"; | ||
// import { updatePassword } from "../redux/api/updatePasswordApiSlice"; | ||
// import updatePasswordApiSlice from "../redux/api/updatePasswordApiSlice"; | ||
|
||
jest.mock("react-toastify", () => ({ | ||
toast: { | ||
success: jest.fn(), | ||
error: jest.fn(), | ||
}, | ||
ToastContainer: () => <div />, | ||
})); | ||
|
||
jest.mock("react-redux", () => ({ | ||
...jest.requireActual("react-redux"), | ||
useDispatch: () => jest.fn(), | ||
})); | ||
|
||
const middlewares = [thunk]; | ||
// @ts-ignore | ||
const mockStore = configureStore(middlewares); | ||
const setPasswordModal = jest.fn(); | ||
// @ts-ignore | ||
const renderComponent = (store) => render( | ||
<Provider store={store}> | ||
<Router> | ||
<UpdatePasswordmod setPasswordModal={setPasswordModal} /> | ||
<ToastContainer /> | ||
</Router> | ||
</Provider>, | ||
); | ||
|
||
describe("Update Password Modal", () => { | ||
let store; | ||
beforeEach(() => { | ||
store = mockStore({ | ||
updatePassword: { | ||
loading: false, | ||
}, | ||
}); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it("update Password Modal renders correctly", () => { | ||
renderComponent(store); | ||
expect(screen.getByPlaceholderText("Old Password")).toBeInTheDocument(); | ||
expect(screen.getByPlaceholderText("New Password")).toBeInTheDocument(); | ||
expect(screen.getByPlaceholderText("Confirm Password")).toBeInTheDocument(); | ||
}); | ||
|
||
it("handles input and form submission", async () => { | ||
// const mockUpdatePassword = jest.fn(); | ||
// (useDispatch as unknown as jest.Mock).mockReturnValue(mockUpdatePassword); | ||
const mockDispatch = jest.fn(); | ||
jest.mock("react-redux", () => ({ | ||
useDispatch: () => mockDispatch, | ||
})); | ||
|
||
renderComponent(store); | ||
const currentPasswordInput = screen.getByPlaceholderText("Old Password"); | ||
const newPasswordInput = screen.getByPlaceholderText("New Password"); | ||
const confirmNewPasswordInput = screen.getByPlaceholderText("Confirm Password"); | ||
const updateButton = screen.getByRole("button", { name: /Save Changes/i }); | ||
|
||
await act(() => { | ||
fireEvent.change(currentPasswordInput, { target: { value: "Test@123" } }); | ||
fireEvent.change(newPasswordInput, { target: { value: "NewTest@123" } }); | ||
fireEvent.change(confirmNewPasswordInput, { | ||
target: { value: "NewTest@123" }, | ||
}); | ||
}); | ||
|
||
await act(() => { | ||
fireEvent.click(updateButton); | ||
console.log("updateButton", updateButton.textContent); | ||
}); | ||
|
||
await waitFor(() => { | ||
expect(mockDispatch).toHaveBeenCalledTimes(0); | ||
expect(updateButton).toHaveTextContent("Save Changes"); | ||
expect(setPasswordModal).toHaveBeenCalledTimes(0); | ||
}); | ||
}); | ||
it("Should close the Modal on cancel", async () => { | ||
renderComponent(store); | ||
const cancelButton = screen.getByRole("button", { name: /Cancel/i }); | ||
await act(() => { | ||
fireEvent.click(cancelButton); | ||
}); | ||
await waitFor(() => { | ||
expect(setPasswordModal).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
|
||
it("Should show PassWord and hide Password", async () => { | ||
renderComponent(store); | ||
const passwordInput = screen.getByPlaceholderText("Old Password"); | ||
const AllshowPasswordButton = screen.getAllByRole("button", { | ||
name: /Show/i, | ||
}); | ||
const showPasswordButton = AllshowPasswordButton[0]; | ||
await act(() => { | ||
fireEvent.click(showPasswordButton); | ||
}); | ||
await waitFor(() => { | ||
expect(passwordInput).toHaveAttribute("type", "text"); | ||
}); | ||
}); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { configureStore } from "@reduxjs/toolkit"; | ||
import axios from "axios"; | ||
|
||
import updatePasswordApiSlice, { | ||
updatePassword, | ||
} from "../redux/api/updatePasswordApiSlice"; | ||
|
||
jest.mock("axios"); | ||
|
||
describe("updatePasswordApiSlice", () => { | ||
let store; | ||
|
||
beforeEach(() => { | ||
store = configureStore({ | ||
reducer: { | ||
updatePassword: updatePasswordApiSlice, | ||
}, | ||
}); | ||
}); | ||
|
||
it("handles successful password update", async () => { | ||
const mockResponse = { data: { message: "Password updated successfully" } }; | ||
// @ts-ignore | ||
axios.put.mockResolvedValueOnce(mockResponse); | ||
|
||
await store.dispatch( | ||
updatePassword({ | ||
oldPassword: "Test@123", | ||
newPassword: "NewTest@123", | ||
confirmPassword: "NewTest@123", | ||
}), | ||
); | ||
|
||
const state = store.getState(); | ||
expect(state.updatePassword.loading).toBe(false); | ||
expect(state.updatePassword.error).toBe(null); | ||
}); | ||
|
||
it("handles failed password update", async () => { | ||
const mockError = { response: { data: { message: "Update failed" } } }; | ||
// @ts-ignore | ||
axios.put.mockRejectedValueOnce(mockError); | ||
|
||
await store.dispatch( | ||
updatePassword({ | ||
oldPassword: "Test@123", | ||
newPassword: "NewTest@123", | ||
confirmPassword: "NewTest@123", | ||
}), | ||
); | ||
|
||
const state = store.getState(); | ||
expect(state.updatePassword.loading).toBe(false); | ||
expect(state.updatePassword.error).toBe(null); | ||
}); | ||
}); |
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
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
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 |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React, { useState } from "react"; | ||
import { FieldError, UseFormRegisterReturn } from "react-hook-form"; | ||
|
||
interface PasswordInputProps { | ||
id: string; | ||
placeholder: string; | ||
register: UseFormRegisterReturn; | ||
error: FieldError | undefined; | ||
} | ||
|
||
const PasswordInput: React.FC<PasswordInputProps> = ({ | ||
id, | ||
placeholder, | ||
register, | ||
error, | ||
}) => { | ||
const [showPassword, setShowPassword] = useState(false); | ||
|
||
return ( | ||
<div className="mb-4 relative"> | ||
<input | ||
type={showPassword ? "text" : "password"} | ||
id={id} | ||
className={`w-full p-2 border-b ${error ? "border-red-500" : "border-gray-300"} pr-20`} | ||
placeholder={placeholder} | ||
{...register} | ||
/> | ||
<button | ||
type="button" | ||
onClick={() => setShowPassword(!showPassword)} | ||
className="absolute right-2 top-1/2 transform -translate-y-1/2" | ||
> | ||
{showPassword ? "Hide" : "Show"} | ||
</button> | ||
{error && <p className="text-red-500">{error.message}</p>} | ||
</div> | ||
); | ||
}; | ||
|
||
export default PasswordInput; |
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 |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import React, { useState } from "react"; | ||
import { useForm } from "react-hook-form"; | ||
import { yupResolver } from "@hookform/resolvers/yup"; | ||
import { toast, ToastContainer } from "react-toastify"; | ||
import { AxiosError } from "axios"; | ||
import { useDispatch } from "react-redux"; | ||
|
||
import updatePasswordSchema from "../../schemas/updatePasswordSchema"; | ||
import { updatePassword } from "../../redux/api/updatePasswordApiSlice"; | ||
import PasswordInput from "../common/auth/password"; | ||
|
||
interface UpdatePasswordProps { | ||
setPasswordModal: (isOpen: boolean) => void; | ||
} | ||
|
||
const UpdatePasswordmod: React.FC<UpdatePasswordProps> = ({ | ||
setPasswordModal, | ||
}) => { | ||
const dispatch = useDispatch(); | ||
const [loading, setLoading] = useState(false); | ||
const { | ||
register, | ||
handleSubmit, | ||
formState: { errors }, | ||
} = useForm({ | ||
resolver: yupResolver(updatePasswordSchema), | ||
}); | ||
|
||
const onSubmit = async (data: { | ||
oldPassword: string; | ||
newPassword: string; | ||
confirmPassword: string; | ||
}) => { | ||
try { | ||
setLoading(true); | ||
// @ts-ignore | ||
const response = await dispatch(updatePassword(data)).unwrap(); | ||
setLoading(false); | ||
toast.success(response.message); | ||
setTimeout(() => { | ||
setPasswordModal(false); | ||
}, 3000); | ||
} catch (err) { | ||
setLoading(false); | ||
const error = err as AxiosError; | ||
toast.error(error.message); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="fixed inset-0 z-40 flex items-center justify-center bg-[#D0D0D0] bg-opacity-50"> | ||
<div className="relative bg-white rounded-lg p-10 w-[90%] md:w-[65%] lg:w-[55%] xl:w-[50%] duration-75 animate-fadeIn"> | ||
<ToastContainer /> | ||
<h2 className="text-2xl mb-4 font-bold text-[#DB4444]"> | ||
Update Password | ||
</h2> | ||
<form onSubmit={handleSubmit(onSubmit)}> | ||
<PasswordInput | ||
id="oldPassword" | ||
placeholder="Old Password" | ||
register={register("oldPassword")} | ||
error={errors.oldPassword} | ||
/> | ||
|
||
<PasswordInput | ||
id="newPassword" | ||
placeholder="New Password" | ||
register={register("newPassword")} | ||
error={errors.newPassword} | ||
/> | ||
|
||
<div className="mb-4 relative"> | ||
<PasswordInput | ||
id="confirmPassword" | ||
placeholder="Confirm Password" | ||
register={register("confirmPassword")} | ||
error={errors.confirmPassword} | ||
/> | ||
</div> | ||
<div className="flex justify-center gap-4"> | ||
<button | ||
type="button" | ||
onClick={() => setPasswordModal(false)} | ||
className="bg-transparent text-primary border border-[#DB4444] px-4 py-2 rounded" | ||
> | ||
Cancel | ||
</button> | ||
<button | ||
type="submit" | ||
disabled={loading} | ||
className="bg-[#DB4444] text-white py-3 px-4 rounded " | ||
> | ||
{loading ? "Loading..." : "Save Changes"} | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UpdatePasswordmod; |
Oops, something went wrong.