diff --git a/__mocks__/react-native-localize.ts b/__mocks__/react-native-localize.ts
new file mode 100644
index 0000000..bc40dd1
--- /dev/null
+++ b/__mocks__/react-native-localize.ts
@@ -0,0 +1,2 @@
+// __mocks__/react-native-localize.ts
+export * from "react-native-localize/mock"; // or "react-native-localize/mock/jest"
diff --git a/jest/setupFiles.js b/jest/setupFiles.js
index 0099594..60cb858 100644
--- a/jest/setupFiles.js
+++ b/jest/setupFiles.js
@@ -49,14 +49,14 @@ jest.mock("react-i18next", () => ({
}));
jest.mock("react-native-responsive-fontsize", () => ({
- RFValue: jest.fn(),
- RFPercentage: jest.fn(),
- fixedRFValue: jest.fn(),
+ RFValue: jest.fn().mockImplementation(() => 10),
+ RFPercentage: jest.fn().mockImplementation(() => 10),
+ fixedRFValue: jest.fn().mockImplementation(() => 10),
}));
jest.mock("react-native-responsive-screen", () => ({
- widthPercentageToDP: jest.fn(),
- heightPercentageToDP: jest.fn(),
- width: jest.fn(),
- height: jest.fn(),
+ widthPercentageToDP: jest.fn().mockImplementation(() => 10),
+ heightPercentageToDP: jest.fn().mockImplementation(() => 10),
+ width: jest.fn().mockImplementation(() => 10),
+ height: jest.fn().mockImplementation(() => 10),
}));
diff --git a/src/components/DrawerContent/__tests__/DrawerContent.test.tsx b/src/components/DrawerContent/__tests__/DrawerContent.test.tsx
index 29caa2f..c44270e 100644
--- a/src/components/DrawerContent/__tests__/DrawerContent.test.tsx
+++ b/src/components/DrawerContent/__tests__/DrawerContent.test.tsx
@@ -1,9 +1,60 @@
-import { render } from "@testing-library/react-native";
+import { fireEvent, render, screen } from "@testing-library/react-native";
import CustomDrawerContent from "..";
describe("DrawerContent", () => {
it("should render correctly", () => {
render();
+
+ expect(screen.getByText(/Principal/i)).toBeTruthy();
+ });
+
+ describe("Main menu", () => {
+ it("should navigate to the correct screen", async () => {
+ render();
+
+ const drawerItem = await screen.findAllByTestId("drawerItem");
+
+ drawerItem.forEach((item) => {
+ fireEvent.press(item);
+ });
+
+ expect(screen.getByText(/Principal/i)).toBeTruthy();
+ });
+
+ it("should open and close the sub menu", async () => {
+ render();
+
+ const drawerItem = await screen.findAllByTestId("drawerItem");
+
+ fireEvent.press(drawerItem[2]);
+
+ const drawerItemSub = await screen.findAllByTestId("drawerItemSub");
+
+ expect(drawerItemSub).toHaveLength(4);
+
+ fireEvent.press(drawerItem[2]);
+
+ expect(screen.queryByTestId("drawerItemSub")).toBeNull();
+ });
+ });
+
+ describe("Sub menu", () => {
+ it("should navigate to the correct screen", async () => {
+ render();
+
+ const drawerItem = await screen.findAllByTestId("drawerItem");
+
+ fireEvent.press(drawerItem[2]);
+ fireEvent.press(drawerItem[3]);
+
+ const drawerItemSub = await screen.findAllByTestId("drawerItemSub");
+
+ drawerItemSub.forEach((item) => {
+ fireEvent.press(item);
+ });
+
+ expect(screen.getByText(/Principal/i)).toBeTruthy();
+ });
});
});
diff --git a/src/components/DrawerContent/index.tsx b/src/components/DrawerContent/index.tsx
index 0e95d25..bc3b48a 100644
--- a/src/components/DrawerContent/index.tsx
+++ b/src/components/DrawerContent/index.tsx
@@ -42,6 +42,7 @@ const CustomDrawerContent = () => {
{drawerMenu.map((item, index) => (
{
LayoutAnimation.configureNext(
LayoutAnimation.create(200, "easeInEaseOut", "opacity")
@@ -59,6 +60,7 @@ const CustomDrawerContent = () => {
<>
{item.menuList?.map((subItem, subIndex) => (
navigation.navigate(subItem.route)}
>
diff --git a/src/components/LogoComponent/__tests__/LogoComponent.test.tsx b/src/components/LogoComponent/__tests__/LogoComponent.test.tsx
new file mode 100644
index 0000000..a9501a5
--- /dev/null
+++ b/src/components/LogoComponent/__tests__/LogoComponent.test.tsx
@@ -0,0 +1,15 @@
+import { render } from "@testing-library/react-native";
+
+import LogoComponent from "..";
+
+describe("LogoComponent", () => {
+ it("should render correctly", () => {
+ render(
+
+ );
+ });
+});
diff --git a/src/components/LogoComponent/index.tsx b/src/components/LogoComponent/index.tsx
index 02f89ee..2cd7ee8 100644
--- a/src/components/LogoComponent/index.tsx
+++ b/src/components/LogoComponent/index.tsx
@@ -13,7 +13,9 @@ interface LogoComponentProps {
const LogoComponent = ({ style, width, height }: LogoComponentProps) => {
const { theme } = useTheme();
const Logo = theme === "light" ? Marca : MarcaLight;
- return ;
+ return (
+
+ );
};
export default LogoComponent;
diff --git a/src/components/PrivacyPolicesAndTerms/__tests__/PrivacyPolicesAndTerms.test.tsx b/src/components/PrivacyPolicesAndTerms/__tests__/PrivacyPolicesAndTerms.test.tsx
new file mode 100644
index 0000000..ce039bf
--- /dev/null
+++ b/src/components/PrivacyPolicesAndTerms/__tests__/PrivacyPolicesAndTerms.test.tsx
@@ -0,0 +1,115 @@
+import AsyncStorage from "@react-native-async-storage/async-storage";
+import {
+ fireEvent,
+ render,
+ screen,
+ waitFor,
+} from "@testing-library/react-native";
+import { Alert } from "react-native";
+
+import PrivacyPolicesAndTerms from "..";
+import type { NavigationType } from "../../../types/navigationProps";
+
+const mockNavigation = {
+ navigate: jest.fn(),
+ dispatch: jest.fn(),
+ reset: jest.fn(),
+ goBack: jest.fn(),
+ isFocused: jest.fn(),
+} as unknown as NavigationType;
+
+jest.mock("react-native-vector-icons/MaterialCommunityIcons", () => "Icon");
+
+describe("PrivacyPolicesAndTerms", () => {
+ it("should render correctly", () => {
+ render();
+ });
+
+ describe("open links", () => {
+ it("should open the terms link", () => {
+ render();
+
+ const button = screen.getByText("Ler termos de uso");
+
+ fireEvent.press(button);
+ });
+
+ it("should open the privacy link", () => {
+ render();
+
+ const button = screen.getByText("Ler politicas de privacidade");
+
+ fireEvent.press(button);
+ });
+ });
+
+ describe("checkbox", () => {
+ it("should apear activeSpan if checkbox is not checked", async () => {
+ render();
+
+ const button = screen.getByText("Continuar");
+
+ fireEvent.press(button);
+
+ const textActiveSpan = await screen.findByText(
+ "Para continuar vocĂȘ precisa aceitar os termos"
+ );
+
+ expect(textActiveSpan).toBeTruthy();
+ });
+
+ it("should not apear activeSpan if checkbox is checked", async () => {
+ render();
+
+ const checkbox = screen.getByTestId("checkbox");
+
+ fireEvent.press(checkbox);
+
+ const button = screen.getByText("Continuar");
+
+ fireEvent.press(button);
+
+ const textActiveSpan = screen.queryByText(
+ "Para continuar vocĂȘ precisa aceitar os termos"
+ );
+
+ await waitFor(() => {
+ expect(textActiveSpan).toBeNull();
+ });
+ });
+
+ it("should check the checkbox", () => {
+ render();
+
+ const checkbox = screen.getByTestId("checkbox");
+
+ fireEvent.press(checkbox);
+ });
+ });
+
+ describe("error handling", () => {
+ it("should show alert on AsyncStorage.setItem error", async () => {
+ jest.spyOn(Alert, "alert");
+
+ (AsyncStorage.setItem as jest.Mock).mockRejectedValueOnce(
+ new Error("AsyncStorage error")
+ );
+
+ render();
+
+ const checkbox = screen.getByTestId("checkbox");
+
+ fireEvent.press(checkbox);
+
+ const button = screen.getByText("Continuar");
+
+ fireEvent.press(button);
+
+ await waitFor(() => {
+ expect(Alert.alert).toHaveBeenCalledWith(
+ "Alguma coisa errada aconteceu, contate o desenvolvedor"
+ );
+ });
+ });
+ });
+});
diff --git a/src/components/PrivacyPolicesAndTerms/index.tsx b/src/components/PrivacyPolicesAndTerms/index.tsx
index 122863d..b0c85e6 100644
--- a/src/components/PrivacyPolicesAndTerms/index.tsx
+++ b/src/components/PrivacyPolicesAndTerms/index.tsx
@@ -94,6 +94,7 @@ export default function PrivacyPolicesAndTerms({
style={styles.checkboxContainer}
onPress={handleCheckboxChange}
activeOpacity={0.8}
+ testID="checkbox"
>
{checkboxIcon}
diff --git a/src/components/Responsive/__tests__/Responsive.test.ts b/src/components/Responsive/__tests__/Responsive.test.ts
new file mode 100644
index 0000000..87fcba4
--- /dev/null
+++ b/src/components/Responsive/__tests__/Responsive.test.ts
@@ -0,0 +1,35 @@
+import {
+ height,
+ RFPercentage,
+ RFValue,
+ RFValueWithFixedSecondParam,
+ width,
+} from "..";
+
+describe("Responsive", () => {
+ it("should calculate width correctly", () => {
+ const calculatedWidth = width("100%");
+ expect(calculatedWidth).toBeGreaterThan(0);
+ });
+
+ it("should calculate height correctly", () => {
+ const calculatedHeight = height(50);
+ expect(calculatedHeight).toBeGreaterThan(0);
+ });
+
+ it("should calculate RFPercentage correctly", () => {
+ const calculatedRFPercentage = RFPercentage(50);
+ expect(calculatedRFPercentage).toBeGreaterThan(0);
+ });
+
+ it("should calculate RFValue correctly", () => {
+ const calculatedRFValue = RFValue(16);
+ expect(calculatedRFValue).toBeGreaterThan(0);
+ });
+
+ it("should calculate RFValueWithFixedSecondParam correctly", () => {
+ const calculatedRFValueWithFixedSecondParam =
+ RFValueWithFixedSecondParam(16);
+ expect(calculatedRFValueWithFixedSecondParam).toBeGreaterThan(0);
+ });
+});
diff --git a/src/components/Urls/__tests__/Urls.test.ts b/src/components/Urls/__tests__/Urls.test.ts
new file mode 100644
index 0000000..04a3bc9
--- /dev/null
+++ b/src/components/Urls/__tests__/Urls.test.ts
@@ -0,0 +1,19 @@
+import { termsURL, privacyURL, buyMeACoffeeURL, repoGithubURL } from "..";
+
+describe("Urls", () => {
+ it("should have the correct terms URL", () => {
+ expect(termsURL).toBe("https://2devs.tech/terms");
+ });
+
+ it("should have the correct privacy URL", () => {
+ expect(privacyURL).toBe("https://2devs.tech/PrivacyPolicy");
+ });
+
+ it("should have the correct buy me a coffee URL", () => {
+ expect(buyMeACoffeeURL).toBe("https://www.buymeacoffee.com/gabriellogan");
+ });
+
+ it("should have the correct GitHub repository URL", () => {
+ expect(repoGithubURL).toBe("https://github.com/gabriel-logan/2Devs-Mobile");
+ });
+});