complete UpdateForm component and all of its sub items with their own tests and add gitlab-ci and new eslint file

This commit is contained in:
2023-10-18 11:15:00 +03:30
parent 4f752c9a46
commit 8c2ad759b0
24 changed files with 1266 additions and 27 deletions

118
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,118 @@
image: node:latest
stages:
- build
- test
- test:build
- deploy
merge:build:
stage: build
script:
- npm install
- cp example.env.local .env.local
- cp example.env.local .env.test
only:
- merge_requests
artifacts:
paths:
- node_modules
- .env.local
- .env.test
merge:test:jest:
stage: test
script:
- npm run test
only:
- merge_requests
artifacts:
paths:
- node_modules
- .env.local
- .env.test
merge:test:lint:
stage: test
script:
- npm run lint
only:
- merge_requests
artifacts:
paths:
- node_modules
- .env.local
- .env.test
merge:test:build:
stage: test:build
script:
- npm run build
only:
- merge_requests
artifacts:
paths:
- node_modules
- .env.local
- .env.test
build:
stage: build
script:
- npm install
- cp example.env.local .env.local
- cp example.env.local .env.test
only:
- develop
- main
artifacts:
paths:
- node_modules
- .env.local
- .env.test
test:jest:
stage: test
script:
- npm run test
only:
- develop
- main
artifacts:
paths:
- node_modules
- .env.local
- .env.test
test:lint:
stage: test
script:
- npm run lint
only:
- develop
- main
artifacts:
paths:
- node_modules
- .env.local
- .env.test
test:build:
stage: test:build
script:
- npm run build
only:
- develop
- main
artifacts:
paths:
- node_modules
- .env.local
- .env.test
deploy:
stage: deploy
script:
- echo "Run deploy project"
only:
- main

View File

@@ -55,4 +55,9 @@ export const handler = [
ctx.status(200),
);
}),
rest.post(`${EXPERT_MANAGEMENT}/:id`, (req, res, ctx) => {
return res(
ctx.status(200),
);
}),
]

View File

@@ -174,6 +174,8 @@
"delete_expert": "حذف کارشناس",
"are_you_sure_text": "آیا از انجام این عملیات اطمینان دارید؟",
"button_delete": "حذف",
"delete_tooltip": "حذف"
"delete_tooltip": "حذف",
"update_tooltip": "ویرایش",
"update_expert": "ویرایش کارشناس"
}
}

View File

@@ -38,7 +38,7 @@ const CreateFormMock = ({Component}) => {
};
describe("PersonalInfo Component From Expert Management", () => {
describe("PersonalInfo Component From Expert Management (create)", () => {
describe("Rendering", () => {
it("full_name TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);

View File

@@ -1,11 +1,10 @@
import {act, findByRole, findByText, fireEvent, render, screen, waitFor} from "@testing-library/react";
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import {useTranslations} from "next-intl";
import * as Yup from "yup";
import {Formik} from "formik";
import MockAppWithProviders from "../../../../../../../../../../mocks/AppWithProvider";
import PositionAndRole from "../../PositionAndRole";
import {MenuItem, Select} from "@mui/material";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
@@ -28,7 +27,7 @@ const CreateFormMock = ({Component}) => {
);
};
describe("CreateContent Component From Expert Management", () => {
describe("PositionAndRole Component From Expert Management (create)", () => {
describe("Rendering", () => {
it("Position TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);

View File

@@ -5,8 +5,6 @@ import * as Yup from "yup";
import {Formik} from "formik";
import Province from "../../Province";
import MockAppWithProviders from "../../../../../../../../../../mocks/AppWithProvider";
import PositionAndRole
from "@/components/dashboard/expert-management/Form/CreateForm/CreateContent/RestInfo/PositionAndRole";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
@@ -27,7 +25,7 @@ const CreateFormMock = ({Component}) => {
);
};
describe("CreateContent Component From Expert Management", () => {
describe("Province Component From Expert Management (create)", () => {
describe("Rendering", () => {
it("Province Select Box Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={Province}/></MockAppWithProviders>);

View File

@@ -1,6 +1,5 @@
import {FormControl, FormHelperText, Grid, InputLabel, MenuItem, Select} from "@mui/material";
import {useTranslations} from "next-intl";
import {useState} from "react";
import useProvince from "@/lib/app/hooks/useProvince";
import useRequest from "@/lib/app/hooks/useRequest";

View File

@@ -5,7 +5,6 @@ import {useTranslations} from "next-intl";
import * as Yup from "yup";
import {Formik} from "formik";
import UserInfo from "../../UserInfo";
import PersonalInfo from "@/components/dashboard/expert-management/Form/CreateForm/CreateContent/PersonalInfo";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
@@ -33,7 +32,7 @@ const CreateFormMock = ({Component}) => {
);
};
describe("CreateContent Component From Expert Management", () => {
describe("UserInfo Component From Expert Management (create)", () => {
describe("Rendering", () => {
it("UserName TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={UserInfo}/></MockAppWithProviders>);

View File

@@ -2,8 +2,6 @@ import {fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import CreateContent from "../../CreateContent";
import MockAppWithProviders from "../../../../../../../../mocks/AppWithProvider";
import userEvent from '@testing-library/user-event';
import CreateForm from "@/components/dashboard/expert-management/Form/CreateForm";
function selectDropdownItem(screen, openerTestId, itemText) {
const opener = screen.getByTestId(openerTestId);
@@ -16,16 +14,16 @@ function setInputValue(screen, inputElement, value) {
fireEvent.change(inputElement, {target: {value}});
}
describe("CreateContent Component From Expert Management", () => {
describe("CreateContent Component From Expert Management (create)", () => {
describe("Rendering", () => {
it("Password TextField Rendered", async () => {
it("close button Rendered", async () => {
render(<MockAppWithProviders><CreateContent/></MockAppWithProviders>);
await waitFor(() => {
const cancelBtn = screen.queryByText('بستن');
expect(cancelBtn).toBeInTheDocument();
});
});
it("Password TextField Rendered", async () => {
it("confirm button Rendered", async () => {
render(<MockAppWithProviders><CreateContent/></MockAppWithProviders>);
await waitFor(() => {
const cancelBtn = screen.queryByText('ثبت');
@@ -33,8 +31,6 @@ describe("CreateContent Component From Expert Management", () => {
});
});
});
describe("Behavioral", () => {
});
describe("Form Submission", () => {
it('Should enable the submit button when the inputs are valid', async () => {
render(<MockAppWithProviders><CreateContent/></MockAppWithProviders>);

View File

@@ -0,0 +1,219 @@
import {act, fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import MockAppWithProviders from "../../../../../../../../../mocks/AppWithProvider";
import * as Yup from "yup";
import {Formik} from "formik";
import PersonalInfo from "@/components/dashboard/expert-management/Form/CreateForm/CreateContent/PersonalInfo";
import {useTranslations} from "next-intl";
import Province from "@/components/dashboard/expert-management/Form/CreateForm/CreateContent/RestInfo/Province";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
const validationSchema = Yup.object().shape({
full_name: Yup.string().required(t("ExpertMangement.error_message_full_name")),
email: Yup.string().required(t("ExpertMangement.error_message_email")),
phone_number: Yup.string().required(t("ExpertMangement.error_message_phone_number")),
telephone_id: Yup.string().required(t("ExpertMangement.error_message_telephone_id")),
national_id: Yup.string().required(t("ExpertMangement.error_message_national_id")),
gender: Yup.string().required(t("ExpertMangement.error_message_gender"))
});
return (
<Formik
initialValues={{
full_name: "",
email: "",
phone_number: "",
telephone_id: "",
national_id: "",
gender: ""
}}
validationSchema={validationSchema}
onSubmit={(values, {}) => {
}}
>
{formikProps => (<Component formik={formikProps}></Component>)}
</Formik>
);
};
describe("PersonalInfo Component From Expert Management (update)", () => {
describe("Rendering", () => {
it("full_name TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const fullNameTextField = screen.queryByLabelText('نام کامل');
expect(fullNameTextField).toBeInTheDocument();
});
});
it("Email TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const emailTextField = screen.queryByLabelText('پست الکترونیک');
expect(emailTextField).toBeInTheDocument();
});
});
it("Phone Number TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const phoneNumberTextField = screen.queryByLabelText('شماره همراه');
expect(phoneNumberTextField).toBeInTheDocument();
});
});
it("telephone id TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const telephoneIdTextField = screen.queryByLabelText('کد تلفن');
expect(telephoneIdTextField).toBeInTheDocument();
});
});
it("National Id TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const nationalIdTextField = screen.queryByLabelText('کد ملی');
expect(nationalIdTextField).toBeInTheDocument();
});
});
it("Gender Select Box Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
await waitFor(() => {
const genderSelectBox = screen.getByTestId('select-box');
expect(genderSelectBox).toBeInTheDocument();
});
});
});
describe("Behavioral", () => {
it("Name TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const nameTextField = screen.queryByLabelText('نام کامل');
fireEvent.change(nameTextField, {target: {value: 'exampleName'}});
await act(() => {
expect(nameTextField).toHaveValue('exampleName');
})
});
it("Email TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const emailTextField = screen.queryByLabelText('پست الکترونیک');
fireEvent.change(emailTextField, {target: {value: 'exampleEmail'}});
await act(() => {
expect(emailTextField).toHaveValue('exampleEmail');
})
});
it("Phone Number TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const phoneNumberTextField = screen.queryByLabelText('شماره همراه');
fireEvent.change(phoneNumberTextField, {target: {value: 'examplePhoneNumber'}});
await act(() => {
expect(phoneNumberTextField).toHaveValue('examplePhoneNumber');
})
});
it("Telephone Id TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const telephoneIdTextField = screen.queryByLabelText('کد تلفن');
fireEvent.change(telephoneIdTextField, {target: {value: 'exampleTelephoneId'}});
await act(() => {
expect(telephoneIdTextField).toHaveValue('exampleTelephoneId');
})
});
it("National Id TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const nationalIdTextField = screen.queryByLabelText('کد ملی');
fireEvent.change(nationalIdTextField, {target: {value: 'exampleNationalId'}});
await act(() => {
expect(nationalIdTextField).toHaveValue('exampleNationalId');
})
});
it("Gender Select Box Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const genderSelectBox = screen.getByTestId('select-box');
const genderSelectOpener = await waitFor(() => screen.getByTestId("option-opener-gender"));
await waitFor(() => {
expect(genderSelectBox).toBeInTheDocument();
});
fireEvent.mouseDown(genderSelectOpener);
await waitFor(() => {
const selectItem = screen.queryByText("مرد");
expect(selectItem).toBeInTheDocument();
});
});
});
describe("validation", () => {
it('Should See Error When Name Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const nameInput = screen.queryByLabelText('نام کامل');
fireEvent.change(nameInput, {target: {value: ''}});
fireEvent.blur(nameInput);
await waitFor(() => {
expect(screen.queryByText("نام کامل خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should See Error When Email Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const emailInput = screen.queryByLabelText('پست الکترونیک');
fireEvent.change(emailInput, {target: {value: ''}});
fireEvent.blur(emailInput);
await waitFor(() => {
expect(screen.queryByText("پست الکترونیک خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should See Error When Phone Number Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const phoneNumberInput = screen.queryByLabelText('شماره همراه');
fireEvent.change(phoneNumberInput, {target: {value: ''}});
fireEvent.blur(phoneNumberInput);
await waitFor(() => {
expect(screen.queryByText("شماره همراه خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should See Error When telephone Id Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const telephoneIdTextField = screen.queryByLabelText('کد تلفن');
fireEvent.change(telephoneIdTextField, {target: {value: ''}});
fireEvent.blur(telephoneIdTextField);
await waitFor(() => {
expect(screen.queryByText("کد تلفن خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should See Error When National Id Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const nationalIdInput = screen.queryByLabelText('کد ملی');
fireEvent.change(nationalIdInput, {target: {value: ''}});
fireEvent.blur(nationalIdInput);
await waitFor(() => {
expect(screen.queryByText("کد ملی خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should Select An Item With Valid Value of gender', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PersonalInfo}/></MockAppWithProviders>);
const genderInput = screen.getByTestId("input-gender")
const genderSelectOpener = await waitFor(() => screen.getByTestId("option-opener-gender"));
fireEvent.mouseDown(genderSelectOpener);
const selectItem = await waitFor(() => screen.queryByText("مرد"));
expect(selectItem).toBeInTheDocument();
fireEvent.click(selectItem);
await waitFor(() => {
expect(genderInput.value).toBe('male')
});
});
})
});

View File

@@ -0,0 +1,128 @@
import {FormControl, FormHelperText, Grid, InputLabel, MenuItem, Select, TextField} from "@mui/material";
import {useTranslations} from "next-intl";
const PersonalInfo = ({formik}) => {
const t = useTranslations();
const genderList = [
{id: 1, name_en: "male", name_fa: "مرد"},
{id: 2, name_en: "female", name_fa: "زن"}
]
return (
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid item xs={12} sm={6} md={4}>
<TextField
name="full_name"
label={t("ExpertMangement.text_field_full_name")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.full_name}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.full_name && !!formik.errors.full_name}
helperText={formik.touched.full_name && formik.errors.full_name ? formik.errors.full_name : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<TextField
name="national_id"
label={t("ExpertMangement.text_field_national_id")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.national_id}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.national_id && !!formik.errors.national_id}
helperText={formik.touched.national_id && formik.errors.national_id ? formik.errors.national_id : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<TextField
name="phone_number"
label={t("ExpertMangement.text_field_phone_number")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.phone_number}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.phone_number && !!formik.errors.phone_number}
helperText={formik.touched.phone_number && formik.errors.phone_number ? formik.errors.phone_number : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<TextField
name="email"
label={t("ExpertMangement.text_field_email")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.email && !!formik.errors.email}
helperText={formik.touched.email && formik.errors.email ? formik.errors.email : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<TextField
name="telephone_id"
label={t("ExpertMangement.text_field_telephone_id")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.telephone_id}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.telephone_id && !!formik.errors.telephone_id}
helperText={formik.touched.telephone_id && formik.errors.telephone_id ? formik.errors.telephone_id : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<FormControl
error={formik.touched.gender && !!formik.errors.gender}
sx={{width: "100%", mt: 2}}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_gender")}</InputLabel>
<Select
name="gender"
label={t("ExpertMangement.text_field_gender")}
value={formik.values.gender}
onChange={(e) => {
formik.setFieldValue("gender", e.target.value);
}}
inputProps={{
"data-testid": "input-gender"
}}
data-testid="select-box"
SelectDisplayProps={{"data-testid": 'option-opener-gender'}}
onBlur={formik.handleBlur}
fullWidth
variant="outlined"
>
{(
genderList.map((item) => (
<MenuItem key={item.id} value={item.name_en}>
{item.name_fa}
</MenuItem>
))
)}
</Select>
<FormHelperText>
{formik.touched.gender && formik.errors.gender ? formik.errors.gender : ""}
</FormHelperText>
</FormControl>
</Grid>
</Grid>
)
}
export default PersonalInfo

View File

@@ -0,0 +1,75 @@
import {FormControl, FormHelperText, Grid, InputLabel, MenuItem, Select, TextField} from "@mui/material";
import {useTranslations} from "next-intl";
import useRequest from "@/lib/app/hooks/useRequest";
import useRole from "@/lib/app/hooks/useRole";
import {log} from "next/dist/server/typescript/utils";
const PositionAndRole = ({formik}) => {
const t = useTranslations();
const requestServer = useRequest()
const {roleList, isLoadingRoleList, errorRoleList} = useRole();
return (
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid item xs={12} sm={6}>
<TextField
name="position"
label={t("ExpertMangement.text_field_position")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.position}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.position && !!formik.errors.position}
helperText={formik.touched.position && formik.errors.position ? formik.errors.position : null}
sx={{width: "100%"}}
/>
</Grid>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.roles && !!formik.errors.roles}
sx={{width: "100%", mt: 2}}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_roles")}</InputLabel>
<Select
name="roles"
label={t("ExpertMangement.text_field_roles")}
disabled={isLoadingRoleList || errorRoleList}
value={isLoadingRoleList || errorRoleList ? "" : formik.values.roles}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
fullWidth
inputProps={{
"data-testid": "input-role-id"
}}
data-testid="select-box"
SelectDisplayProps={{"data-testid": 'option-opener-role'}}
variant="outlined"
>
{isLoadingRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_roles_list")}
</MenuItem>
) : errorRoleList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_roles")}
</MenuItem>
) : (
roleList.map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.name_fa}
</MenuItem>
))
)}
</Select>
<FormHelperText>
{formik.touched.roles && formik.errors.roles ? formik.errors.roles : ""}
</FormHelperText>
</FormControl>
</Grid>
</Grid>
)
}
export default PositionAndRole

View File

@@ -0,0 +1,96 @@
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import {useTranslations} from "next-intl";
import * as Yup from "yup";
import {Formik} from "formik";
import MockAppWithProviders from "../../../../../../../../../../mocks/AppWithProvider";
import PositionAndRole from "../../PositionAndRole";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
const validationSchema = Yup.object().shape({
position: Yup.string().required(t("ExpertMangement.error_message_position")),
roles: Yup.string().required(t("ExpertMangement.error_message_roles"))
});
return (
<Formik
initialValues={{
position: "",
roles: ""
}}
validationSchema={validationSchema}
onSubmit={(values, {}) => {
}}
>
{formikProps => (<Component formik={formikProps}></Component>)}
</Formik>
);
};
describe("PositionAndRole Component From Expert Management (update)", () => {
describe("Rendering", () => {
it("Position TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
await waitFor(() => {
const positionTextField = screen.queryByLabelText('سمت');
expect(positionTextField).toBeInTheDocument();
});
});
it("Role Select Box Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
const roleSelect = screen.getByTestId('select-box');
await waitFor(() => {
expect(roleSelect).toBeInTheDocument();
});
});
});
describe("Behavioral", () => {
it("Position TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
const positionTextField = screen.queryByLabelText('سمت');
fireEvent.change(positionTextField, {target: {value: 'examplePosition'}});
await waitFor(() => {
expect(positionTextField).toHaveValue('examplePosition');
})
});
it("Role Select Box Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
const roleSelect = screen.getByTestId("option-opener-role");
await waitFor(() => {
expect(roleSelect).toBeInTheDocument();
});
fireEvent.mouseDown(roleSelect);
await waitFor(() => {
const selectItem = screen.queryByText("ادمین");
expect(selectItem).toBeInTheDocument();
});
});
});
describe("validation", () => {
it('Should See Error When Position Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
const positionInput = screen.queryByLabelText('سمت');
fireEvent.change(positionInput, {target: {value: ''}});
fireEvent.blur(positionInput);
await waitFor(() => {
expect(screen.queryByText("سمت خود را وارد کنید")).toBeInTheDocument()
});
});
it('Should Select An Item With Valid Value of role', async () => {
render(<MockAppWithProviders><CreateFormMock Component={PositionAndRole}/></MockAppWithProviders>);
const roleInput = await waitFor(() => screen.getByTestId("input-role-id"));
const roleSelectOpener = await waitFor(() => screen.getByTestId("option-opener-role"));
fireEvent.mouseDown(roleSelectOpener);
const selectItem = await waitFor(() => screen.queryByText("ادمین"));
expect(selectItem).toBeInTheDocument();
fireEvent.click(selectItem);
await waitFor(() => {
expect(roleInput.value).toBe('1')
});
});
})
});

View File

@@ -0,0 +1,71 @@
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import {useTranslations} from "next-intl";
import * as Yup from "yup";
import {Formik} from "formik";
import Province from "../../Province";
import MockAppWithProviders from "../../../../../../../../../../mocks/AppWithProvider";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
const validationSchema = Yup.object().shape({
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
});
return (
<Formik
initialValues={{
province_id: "",
}}
validationSchema={validationSchema}
onSubmit={(values, {}) => {
}}
>
{formikProps => (<Component formik={formikProps}></Component>)}
</Formik>
);
};
describe("Province Component From Expert Management (update)", () => {
describe("Rendering", () => {
it("Province Select Box Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={Province}/></MockAppWithProviders>);
await waitFor(() => {
const provinceSelectBox = screen.getByTestId('select-box');
expect(provinceSelectBox).toBeInTheDocument();
});
});
});
describe("Behavioral", () => {
it("Province Select Box Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={Province}/></MockAppWithProviders>);
const provinceSelectBox = screen.getByTestId('select-box');
const provinceSelectOpener = await waitFor(() => screen.getByTestId("option-opener-province"));
await waitFor(() => {
expect(provinceSelectBox).toBeInTheDocument();
});
fireEvent.mouseDown(provinceSelectOpener);
await waitFor(() => {
const selectItem = screen.queryByText("آذربایجان شرقی");
expect(selectItem).toBeInTheDocument();
});
});
});
describe("validation", () => {
it('Should Select An Item With Valid Value of province', async () => {
render(<MockAppWithProviders><CreateFormMock Component={Province}/></MockAppWithProviders>);
const provinceInput = screen.getByTestId("input-province-id")
const provinceSelectOpener = await waitFor(() => screen.getByTestId("option-opener-province"));
fireEvent.mouseDown(provinceSelectOpener);
const selectItem = await waitFor(() => screen.queryByText("آذربایجان شرقی"));
expect(selectItem).toBeInTheDocument();
fireEvent.click(selectItem);
await waitFor(() => {
expect(provinceInput.value).toBe('1')
});
});
})
});

View File

@@ -0,0 +1,61 @@
import {FormControl, FormHelperText, Grid, InputLabel, MenuItem, Select} from "@mui/material";
import {useTranslations} from "next-intl";
import useProvince from "@/lib/app/hooks/useProvince";
import useRequest from "@/lib/app/hooks/useRequest";
const Province = ({formik}) => {
const t = useTranslations();
const requestServer = useRequest()
const {provinceList, isLoadingProvinceList, errorProvinceList} = useProvince();
return (
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid item xs={12} sm={6}>
<FormControl
error={formik.touched.province_id && !!formik.errors.province_id}
sx={{width: "100%", mt: 2}}
size="small"
>
<InputLabel>{t("ExpertMangement.text_field_province_id")}</InputLabel>
<Select
name="province_id"
disabled={isLoadingProvinceList || errorProvinceList}
label={t("ExpertMangement.text_field_province_id")}
value={isLoadingProvinceList || errorProvinceList ? "" : formik.values.province_id}
onChange={(e) => {
formik.setFieldValue("province_id", e.target.value);
}}
inputProps={{
"data-testid": "input-province-id"
}}
data-testid="select-box"
SelectDisplayProps={{"data-testid": 'option-opener-province'}}
onBlur={formik.handleBlur}
fullWidth
variant="outlined"
>
{isLoadingProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_loading_provinces_list")}
</MenuItem>
) : errorProvinceList ? (
<MenuItem>
{t("ExpertMangement.text_field_error_fetching_provinces")}
</MenuItem>
) : (
provinceList.map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.name}
</MenuItem>
))
)}
</Select>
<FormHelperText>
{formik.touched.province_id && formik.errors.province_id ? formik.errors.province_id : ""}
</FormHelperText>
</FormControl>
</Grid>
</Grid>
)
}
export default Province

View File

@@ -0,0 +1,12 @@
import Province from "./Province";
import PositionAndRole from "./PositionAndRole";
const RestInfo = ({formik}) => {
return (
<>
<Province formik={formik}/>
<PositionAndRole formik={formik}/>
</>
)
}
export default RestInfo

View File

@@ -0,0 +1,62 @@
import {act, fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import MockAppWithProviders from "../../../../../../../../../mocks/AppWithProvider";
import {useTranslations} from "next-intl";
import * as Yup from "yup";
import {Formik} from "formik";
import UserInfo from "../../UserInfo";
const CreateFormMock = ({Component}) => {
const t = useTranslations();
const validationSchema = Yup.object().shape({
username: Yup.string().required(t("ExpertMangement.error_message_username")),
});
return (
<Formik
initialValues={{
username: "",
}}
validationSchema={validationSchema}
onSubmit={(values, {}) => {
}}
>
{formikProps => (<Component formik={formikProps}></Component>)}
</Formik>
);
};
describe("UserInfo Component From Expert Management (update)", () => {
describe("Rendering", () => {
it("UserName TextField Rendered", async () => {
render(<MockAppWithProviders><CreateFormMock Component={UserInfo}/></MockAppWithProviders>);
await waitFor(() => {
const usernameTextField = screen.queryByLabelText('نام کاربری');
expect(usernameTextField).toBeInTheDocument();
});
});
});
describe("Behavioral", () => {
it("Username TextField Work Correctly", async () => {
render(<MockAppWithProviders><CreateFormMock Component={UserInfo}/></MockAppWithProviders>);
const usernameTextField = screen.queryByLabelText('نام کاربری');
fireEvent.change(usernameTextField, {target: {value: 'exampleUsername'}});
await act(() => {
expect(usernameTextField).toHaveValue('exampleUsername');
})
});
});
describe("validation", () => {
it('Should See Error When Username Input Is Empty', async () => {
render(<MockAppWithProviders><CreateFormMock Component={UserInfo}/></MockAppWithProviders>);
const usernameInput = screen.queryByLabelText('نام کاربری');
fireEvent.change(usernameInput, {target: {value: ''}});
fireEvent.blur(usernameInput);
await waitFor(() => {
expect(screen.queryByText("نام کاربری خود را وارد کنید")).toBeInTheDocument()
});
});
})
});

View File

@@ -0,0 +1,29 @@
import {Grid, TextField} from "@mui/material";
import {useTranslations} from "next-intl";
const UserInfo = ({formik}) => {
const t = useTranslations();
return (
<>
<Grid container justifyContent="space-around" spacing={2} sx={{pb: 2}}>
<Grid item xs={12} sm={6}>
<TextField
name="username"
label={t("ExpertMangement.text_field_username")}
variant="outlined"
margin="normal"
size="small"
value={formik.values.username}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched.username && !!formik.errors.username}
helperText={formik.touched.username && formik.errors.username ? formik.errors.username : null}
sx={{width: "100%"}}
/>
</Grid>
</Grid>
</>
)
}
export default UserInfo

View File

@@ -0,0 +1,87 @@
import {fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import MockAppWithProviders from "../../../../../../../../mocks/AppWithProvider";
import UpdateContent from "../../UpdateContent";
const row = {
original: {
avatar: null,
created_at: "2023-10-10T13:05:01.000000Z",
email: "fisher.sigrid@yahoo.com",
full_name: "Anibal Labadie",
gender: "female",
id: 85,
national_id: "5944646138",
phone_number: "09731311720",
position: "boss1",
province_fa: "اردبیل",
province_id: 3,
roles: [{
created_at: "2023-10-10T13:03:18.000000Z",
guard_name: "api",
id: 2,
name: "manager",
name_fa: "مدیر"
}],
telephone_id: "tel-3110",
updated_at: "2023-10-17T10:57:12.000000Z",
username: "florence.kihn",
}
}
function selectDropdownItem(screen, openerTestId, itemText) {
const opener = screen.getByTestId(openerTestId);
fireEvent.mouseDown(opener);
const selectItem = screen.queryByText(itemText);
fireEvent.click(selectItem);
}
function setInputValue(screen, inputElement, value) {
fireEvent.change(inputElement, {target: {value}});
}
describe("UpdateContent Component From Expert Management (update)", () => {
describe("Rendering", () => {
it("close button Rendered", async () => {
render(<MockAppWithProviders><UpdateContent row={row}/></MockAppWithProviders>);
await waitFor(() => {
const cancelBtn = screen.queryByText('بستن');
expect(cancelBtn).toBeInTheDocument();
});
});
it("confirm button Rendered", async () => {
render(<MockAppWithProviders><UpdateContent row={row}/></MockAppWithProviders>);
await waitFor(() => {
const confirmBtn = screen.queryByText('ثبت');
expect(confirmBtn).toBeInTheDocument();
});
});
});
describe("Form Submission", () => {
it('Should enable the submit button when the inputs are valid', async () => {
render(<MockAppWithProviders><UpdateContent row={row}/></MockAppWithProviders>);
const submitButton = screen.queryByText('ثبت');
const nameInput = screen.queryByLabelText('نام کامل');
const usernameInput = screen.queryByLabelText('نام کاربری');
const emailInput = screen.queryByLabelText('پست الکترونیک');
const phoneNumberInput = screen.queryByLabelText('شماره همراه');
const telephoneIdInput = screen.queryByLabelText('کد تلفن');
const nationalIdInput = screen.queryByLabelText('کد ملی');
const positionInput = screen.queryByLabelText('سمت');
setInputValue(screen, nameInput, 'nameTest');
setInputValue(screen, usernameInput, 'usernameTest');
setInputValue(screen, emailInput, 'emailTest');
setInputValue(screen, phoneNumberInput, 'phoneNumberTest');
setInputValue(screen, telephoneIdInput, 'telephoneIdTest');
setInputValue(screen, nationalIdInput, 'nationalIdTest');
setInputValue(screen, positionInput, 'positionTest');
await waitFor(() => {
expect(submitButton).not.toBeDisabled();
});
});
})
});

View File

@@ -0,0 +1,108 @@
import {Box, Button, Chip, DialogActions, DialogContent, Divider,} from "@mui/material";
import * as Yup from "yup";
import {useTranslations} from "next-intl";
import {useFormik} from "formik";
import useRequest from "@/lib/app/hooks/useRequest";
import {EXPERT_MANAGEMENT} from "@/core/data/apiRoutes";
import PersonalInfo from "./PersonalInfo";
import UserInfo from "./UserInfo";
import RestInfo from "./RestInfo";
const UpdateContent = ({row, fetchUrl, mutate, setOpenUpdateDialog}) => {
const t = useTranslations();
const requestServer = useRequest()
const validationSchema = Yup.object().shape({
full_name: Yup.string().required(t("ExpertMangement.error_message_full_name")),
username: Yup.string().required(t("ExpertMangement.error_message_username")),
email: Yup.string().required(t("ExpertMangement.error_message_email")),
phone_number: Yup.string().required(t("ExpertMangement.error_message_phone_number")),
telephone_id: Yup.string().required(t("ExpertMangement.error_message_telephone_id")),
gender: Yup.string().required(t("ExpertMangement.error_message_gender")),
national_id: Yup.string().required(t("ExpertMangement.error_message_national_id")),
position: Yup.string().required(t("ExpertMangement.error_message_position")),
province_id: Yup.string().required(t("ExpertMangement.error_message_province_id")),
roles: Yup.string().required(t("ExpertMangement.error_message_roles"))
});
const formik = useFormik({
initialValues: {
full_name: row.original.full_name,
username: row.original.username,
email: row.original.email,
phone_number: row.original.phone_number,
telephone_id: row.original.telephone_id,
gender: row.original.gender,
national_id: row.original.national_id,
position: row.original.position,
province_id: row.original.province_id,
roles: row.original.roles[0].id
},
validationSchema,
onSubmit: (values, {setSubmitting}) => {
const formData = new FormData();
formData.append("full_name", values.full_name);
formData.append("national_id", values.national_id);
formData.append("phone_number", values.phone_number);
formData.append("telephone_id", values.telephone_id);
formData.append("gender", values.gender);
formData.append("email", values.email);
formData.append("username", values.username);
formData.append("province_id", values.province_id);
formData.append("position", values.position);
formData.append("roles", values.roles);
requestServer(`${EXPERT_MANAGEMENT}/${row.original.id}`, 'post', {auth: true, data: formData})
.then((response) => {
setOpenUpdateDialog(false)
mutate(fetchUrl)
}).catch(() => {
}).finally(() => {
setSubmitting(false);
});
},
});
return (
<>
<DialogContent>
<Box sx={{my: 1}}>
<Divider>
<Chip
label={t("ExpertMangement.personal_info")}
/>
</Divider>
</Box>
<PersonalInfo formik={formik}/>
<Box sx={{my: 1}}>
<Divider>
<Chip
label={t("ExpertMangement.user_info")}
/>
</Divider>
</Box>
<UserInfo formik={formik}/>
<Box sx={{my: 1}}>
<Divider>
<Chip
label={t("ExpertMangement.rest_info")}
/>
</Divider>
</Box>
<RestInfo formik={formik}/>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenUpdateDialog(false)} variant="outlined" color="secondary"
disabled={formik.isSubmitting} autoFocus>
{t("ExpertMangement.button_cancel")}
</Button>
<Button onClick={formik.handleSubmit} variant="contained" color="primary"
disabled={formik.isSubmitting || !formik.isValid || !formik.dirty}>
{t("ExpertMangement.button_confirm")}
</Button>
</DialogActions>
</>
)
}
export default UpdateContent

View File

@@ -0,0 +1,147 @@
import {act, fireEvent, render, screen, waitFor} from "@testing-library/react";
import React from 'react';
import MockAppWithProviders from "../../../../../../../mocks/AppWithProvider";
import UpdateForm from "../../UpdateForm";
const row = {
original: {
avatar: null,
created_at: "2023-10-10T13:05:01.000000Z",
email: "fisher.sigrid@yahoo.com",
full_name: "Anibal Labadie",
gender: "female",
id: 85,
national_id: "5944646138",
phone_number: "09731311720",
position: "boss1",
province_fa: "اردبیل",
province_id: 3,
roles: [{
created_at: "2023-10-10T13:03:18.000000Z",
guard_name: "api",
id: 2,
name: "manager",
name_fa: "مدیر"
}],
telephone_id: "tel-3110",
updated_at: "2023-10-17T10:57:12.000000Z",
username: "florence.kihn",
}
}
function selectDropdownItem(screen, openerTestId, itemText) {
const opener = screen.getByTestId(openerTestId);
fireEvent.mouseDown(opener);
const selectItem = screen.queryByText(itemText);
fireEvent.click(selectItem);
}
function setInputValue(screen, inputElement, value) {
fireEvent.change(inputElement, {target: {value}});
}
describe("CreateForm Component From Expert Management", () => {
describe("Rendering", () => {
it("Update Expert Button Rendered", () => {
render(<MockAppWithProviders><UpdateForm row={row}/></MockAppWithProviders>);
const UpdateButton = screen.getByTestId('update-button');
expect(UpdateButton).toBeInTheDocument();
});
});
describe("Behavioral", () => {
it("by Clicking Update Button Dialog Should Append To Document", async () => {
render(<MockAppWithProviders><UpdateForm row={row}/></MockAppWithProviders>);
const UpdateButton = screen.getByTestId('update-button');
fireEvent.click(UpdateButton);
await act(() => {
const UpdateDialog = screen.getByRole('dialog', {name: "ویرایش کارشناس"})
expect(UpdateDialog).toBeInTheDocument();
});
});
});
describe("Form Submission", () => {
it('Should request to api and if get success close dialog', async () => {
render(<MockAppWithProviders><UpdateForm row={row}/></MockAppWithProviders>);
const UpdateButton = screen.getByTestId('update-button');
fireEvent.click(UpdateButton);
const submitButton = screen.queryByText('ثبت');
const nameInput = screen.queryByLabelText('نام کامل');
const usernameInput = screen.queryByLabelText('نام کاربری');
const emailInput = screen.queryByLabelText('پست الکترونیک');
const phoneNumberInput = screen.queryByLabelText('شماره همراه');
const telephoneIdInput = screen.queryByLabelText('کد تلفن');
const nationalIdInput = screen.queryByLabelText('کد ملی');
const positionInput = screen.queryByLabelText('سمت');
selectDropdownItem(screen, "option-opener-province", "آذربایجان شرقی");
selectDropdownItem(screen, "option-opener-role", "ادمین");
selectDropdownItem(screen, "option-opener-gender", "مرد");
setInputValue(screen, nameInput, 'nameTest');
setInputValue(screen, usernameInput, 'usernameTest');
setInputValue(screen, emailInput, 'email@gmail.com');
setInputValue(screen, phoneNumberInput, '0914577458');
setInputValue(screen, telephoneIdInput, '091');
setInputValue(screen, nationalIdInput, 'nationalIdTest');
setInputValue(screen, positionInput, 'positionTest');
expect(submitButton).not.toBeDisabled();
fireEvent.click(submitButton);
await waitFor(() => {
const dialogContent = screen.queryByTestId('update-dialog-content');
expect(dialogContent).not.toBeInTheDocument();
});
});
it('Should request to api and if get error keep previous data', async () => {
render(<MockAppWithProviders><UpdateForm row={row}/></MockAppWithProviders>);
const UpdateButton = screen.getByTestId('update-button');
fireEvent.click(UpdateButton);
const submitButton = screen.queryByText('ثبت');
const nameInput = screen.queryByLabelText('نام کامل');
const usernameInput = screen.queryByLabelText('نام کاربری');
const emailInput = screen.queryByLabelText('پست الکترونیک');
const phoneNumberInput = screen.queryByLabelText('شماره همراه');
const telephoneIdInput = screen.queryByLabelText('کد تلفن');
const nationalIdInput = screen.queryByLabelText('کد ملی');
const positionInput = screen.queryByLabelText('سمت');
const provinceInput = screen.getByTestId("input-province-id")
const roleInput = screen.getByTestId("input-role-id")
const genderInput = screen.getByTestId("input-gender")
selectDropdownItem(screen, "option-opener-province", "آذربایجان شرقی");
selectDropdownItem(screen, "option-opener-role", "ادمین");
selectDropdownItem(screen, "option-opener-gender", "مرد");
setInputValue(screen, nameInput, 'nameTest');
setInputValue(screen, usernameInput, 'usernameTest');
setInputValue(screen, emailInput, 'emailTest@gmail.com');
setInputValue(screen, phoneNumberInput, '0914577458');
setInputValue(screen, telephoneIdInput, '091');
setInputValue(screen, nationalIdInput, 'nationalIdTest');
setInputValue(screen, positionInput, 'positionTest');
expect(submitButton).not.toBeDisabled();
await fireEvent.click(submitButton);
await waitFor(() => {
expect(nameInput).toHaveValue('nameTest');
expect(usernameInput).toHaveValue('usernameTest');
expect(emailInput).toHaveValue('emailTest@gmail.com');
expect(phoneNumberInput).toHaveValue('0914577458');
expect(telephoneIdInput).toHaveValue('091');
expect(nationalIdInput).toHaveValue('nationalIdTest');
expect(positionInput).toHaveValue('positionTest');
expect(provinceInput).toHaveValue('1');
expect(roleInput).toHaveValue('1');
expect(genderInput).toHaveValue('male');
});
});
})
});

View File

@@ -1,7 +1,33 @@
const Update = () => {
return (
<></>
)
}
import {useTranslations} from "next-intl";
import {Dialog, DialogTitle, IconButton, Tooltip} from "@mui/material";
import EditIcon from '@mui/icons-material/Edit';
import {useState} from "react";
import UpdateContent from "./UpdateContent";
export default Update
const Update = ({row, fetchUrl, mutate}) => {
const t = useTranslations();
const [openUpdateDialog, setOpenUpdateDialog] = useState(false);
return (
<>
<Tooltip title={t("ExpertMangement.update_tooltip")}>
<IconButton
color="primary"
data-testid="update-button"
onClick={() => {
setOpenUpdateDialog(true)
}}
>
<EditIcon/>
</IconButton>
</Tooltip>
<Dialog data-testid="update-dialog-content" fullWidth maxWidth={'lg'} open={openUpdateDialog}
PaperProps={{sx: {boxShadow: 'rgba(60, 64, 67, 0.3) 0px 1px 16px 0px, rgba(60, 64, 67, 0.15) 0px 1px 10px 0px'}}}>
<DialogTitle>{t("ExpertMangement.update_expert")}</DialogTitle>
<UpdateContent row={row} mutate={mutate} fetchUrl={fetchUrl} setOpenUpdateDialog={setOpenUpdateDialog}/>
</Dialog>
</>
);
};
export default Update;

View File

@@ -16,7 +16,8 @@ const useProvince = () => {
const {data, isLoading} = useSWR(GET_PROVINCE_LIST, fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false
revalidateOnReconnect: false,
keepPreviousData: true
});
return {

View File

@@ -16,7 +16,8 @@ const useRole = () => {
const {data, isLoading} = useSWR(GET_ROLE_LIST, fetcher, {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false
revalidateOnReconnect: false,
keepPreviousData: true
});
return {