diff --git a/jest/setupFiles.js b/jest/setupFiles.js index be21625..2ce3f26 100644 --- a/jest/setupFiles.js +++ b/jest/setupFiles.js @@ -70,10 +70,25 @@ jest.mock("react-native-base64", () => ({ encode: jest.fn(), })); -jest.mock("react-native-vector-icons/MaterialCommunityIcons", () => "Icon"); -jest.mock("react-native-vector-icons/FontAwesome5", () => "Icon"); -jest.mock("react-native-vector-icons/FontAwesome", () => "Icon"); -jest.mock("react-native-vector-icons/MaterialIcons", () => "Icon"); -jest.mock("react-native-vector-icons/Feather", () => "Icon"); -jest.mock("react-native-vector-icons/AntDesign", () => "Icon"); -jest.mock("react-native-vector-icons/Entypo", () => "Icon"); +jest.mock( + "react-native-vector-icons/MaterialCommunityIcons", + () => "MaterialCommunityIcons Icon" +); +jest.mock("react-native-vector-icons/FontAwesome5", () => "FontAwesome5 Icon"); +jest.mock("react-native-vector-icons/FontAwesome", () => "FontAwesome Icon"); +jest.mock( + "react-native-vector-icons/MaterialIcons", + () => "MaterialIcons Icon" +); +jest.mock("react-native-vector-icons/Feather", () => "Feather Icon"); +jest.mock("react-native-vector-icons/AntDesign", () => "AntDesign Icon"); +jest.mock("react-native-vector-icons/Entypo", () => "Entypo Icon"); +jest.mock("react-native-vector-icons/Ionicons", () => "Ionicons Icon"); + +jest.mock("react-native-network-info", () => ({ + NetworkInfo: { + getIPV4Address: jest.fn().mockResolvedValue("192.168.100.4"), + getGatewayIPAddress: jest.fn().mockResolvedValue("192.168.100.1"), + getSubnet: jest.fn().mockResolvedValue("255.25.255.0"), + }, +})); diff --git a/src/pages/Informations/__tests__/Informations.test.tsx b/src/pages/Informations/__tests__/Informations.test.tsx new file mode 100644 index 0000000..cefa1f4 --- /dev/null +++ b/src/pages/Informations/__tests__/Informations.test.tsx @@ -0,0 +1,63 @@ +import { fireEvent, render, screen } from "@testing-library/react-native"; + +import GeneralInfoPage from ".."; + +describe("Informations", () => { + it("should render correctly", () => { + render(); + + const title = screen.getByText(/Informações Gerais/i); + + expect(title).toBeDefined(); + }); + + it("should show contributors", () => { + render(); + + const contributors = screen.getByText(/Contribuidores/i); + + expect(contributors).toBeDefined(); + }); + + describe("Links buttons", () => { + it("should show and open github link", () => { + render(); + + const githubButton = screen.getByText(/Ir para o repositório github/i); + + expect(githubButton).toBeDefined(); + + fireEvent.press(githubButton); + }); + + it("should show and open buy me a coffee link", () => { + render(); + + const coffeeButton = screen.getByText(/Buy me a coffee/i); + + expect(coffeeButton).toBeDefined(); + + fireEvent.press(coffeeButton); + }); + + it("should show and open Privacy Policy link", () => { + render(); + + const privacyPolicyButton = screen.getByText(/Políticas de Privacidade/i); + + expect(privacyPolicyButton).toBeDefined(); + + fireEvent.press(privacyPolicyButton); + }); + + it("should show and open Terms of Use link", () => { + render(); + + const termsButton = screen.getByText(/Termos de Uso/i); + + expect(termsButton).toBeDefined(); + + fireEvent.press(termsButton); + }); + }); +}); diff --git a/src/pages/MyNetwork/__tests__/MyNetwork.test.tsx b/src/pages/MyNetwork/__tests__/MyNetwork.test.tsx new file mode 100644 index 0000000..6a9e6e1 --- /dev/null +++ b/src/pages/MyNetwork/__tests__/MyNetwork.test.tsx @@ -0,0 +1,73 @@ +import { NavigationContainer } from "@react-navigation/native"; +import { fireEvent, render, screen } from "@testing-library/react-native"; +import axios from "axios"; + +import MyNetwork from ".."; + +describe("MyNetwork", () => { + it("should render correctly", async () => { + jest + .spyOn(axios, "get") + .mockResolvedValue({ data: { ip: "201.8.168.176" } }); + + render( + + + + ); + + const title = await screen.findByText(/Informações de Rede/i); + + expect(title).toBeDefined(); + }); + + it("should copy especific text to clipboard", async () => { + render( + + + + ); + + const buttons = await screen.findAllByLabelText(/buttonCopy/i); + + expect(buttons).toHaveLength(4); + + buttons.forEach((button) => { + fireEvent.press(button); + }); + }); + + it("should show error message when get external ip fails", async () => { + jest.spyOn(axios, "get").mockResolvedValue({ data: undefined }); + + render( + + + + ); + + const error = await screen.findByText( + /Houve um problema não identificado na solicitação, tente novamente mais tarde/i + ); + + expect(error).toBeDefined(); + }); + + it("should console.error when get external ip fails", async () => { + const consoleErrorSpy = jest + .spyOn(console, "error") + .mockImplementation(() => {}); + + jest.spyOn(axios, "get").mockRejectedValue(new Error("error")); + + render( + + + + ); + + await new Promise((resolve) => setTimeout(resolve, 10)); + + consoleErrorSpy.mockRestore(); + }); +}); diff --git a/src/pages/MyNetwork/index.tsx b/src/pages/MyNetwork/index.tsx index 8167ccf..ac3cff0 100644 --- a/src/pages/MyNetwork/index.tsx +++ b/src/pages/MyNetwork/index.tsx @@ -52,15 +52,6 @@ const MyNetwork = () => { ) ); } - - /** - * if (Platform.OS === 'android') { - const airplane = false; - setAirplaneMode(airplane); - } else { - setAirplaneMode(null); - } - */ } catch (error) { // eslint-disable-next-line no-console console.error(error); @@ -86,6 +77,7 @@ const MyNetwork = () => { {geteway || t("Carregando...")} copyToClipboard(geteway ? geteway : t("000.000.0.0")) } @@ -104,6 +96,7 @@ const MyNetwork = () => { {ipAddress || t("Carregando...")} copyToClipboard(ipAddress ? ipAddress : t("000.000.000.000")) } @@ -122,6 +115,7 @@ const MyNetwork = () => { {subnet || t("Carregando...")} copyToClipboard(subnet ? subnet : t("000.000.000.0")) } @@ -140,6 +134,7 @@ const MyNetwork = () => { {ipAddressExternal || t("Carregando...")} copyToClipboard( ipAddressExternal ? ipAddressExternal : t("000.000.000.000") diff --git a/src/pages/generators/Cnpj/index.tsx b/src/pages/generators/Cnpj/index.tsx index f61538e..bdd78ba 100644 --- a/src/pages/generators/Cnpj/index.tsx +++ b/src/pages/generators/Cnpj/index.tsx @@ -29,20 +29,19 @@ export default function CnpjGeneratorPage() { const [cnpjWithPeriod, setCnpjWithPeriod] = useState(false); const formatCnpj = (Cnpj: string) => { - if (Cnpj && Cnpj.length === 14) { - return `${Cnpj.slice(0, 2)}.${Cnpj.slice(2, 5)}.${Cnpj.slice( - 5, - 8 - )}/${Cnpj.slice(8, 12)}-${Cnpj.slice(12)}`; - } - return Cnpj; + return `${Cnpj.slice(0, 2)}.${Cnpj.slice(2, 5)}.${Cnpj.slice( + 5, + 8 + )}/${Cnpj.slice(8, 12)}-${Cnpj.slice(12)}`; }; const generateRandomCnpj = () => { let randomCnpj: string; + do { randomCnpj = generateRandomDigits(); } while (!cnpjIsValid(randomCnpj).isValid); + if (cnpjWithPeriod) { setGeneratedCnpj(formatCnpj(randomCnpj)); } else { @@ -110,7 +109,7 @@ export default function CnpjGeneratorPage() { color="#007BFF" /> - + diff --git a/src/pages/generators/Cpf/__tests__/Cpf.test.tsx b/src/pages/generators/Cpf/__tests__/Cpf.test.tsx new file mode 100644 index 0000000..d9a12bd --- /dev/null +++ b/src/pages/generators/Cpf/__tests__/Cpf.test.tsx @@ -0,0 +1,99 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { fireEvent, render, screen } from "@testing-library/react-native"; + +import CpfGeneratorPage from ".."; + +describe("Cpf Generator", () => { + beforeEach(() => { + jest.clearAllMocks(); + AsyncStorage.clear(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should render correctly", () => { + render(); + + const title = screen.getByText("Gerador de CPF"); + + expect(title).toBeDefined(); + }); + + it("should generate a random CPF without punctuation", async () => { + render(); + + const input = screen.getByPlaceholderText("Clique no botão abaixo"); + + expect(input).toBeDefined(); + + const button = screen.getByText("Gerar CPF"); + + expect(button).toBeDefined(); + + fireEvent.press(button); + + expect(input.props.value).toMatch(/^\d{11}$/); + }); + + it("should change checkbox value", async () => { + render(); + + const checkbox = screen.getByRole("checkbox"); + + fireEvent(checkbox, "onValueChange", true); + + expect(checkbox.props.accessibilityState.checked).toBe(true); + + fireEvent(checkbox, "onValueChange", false); + + expect(checkbox.props.accessibilityState.checked).toBe(false); + }); + + it("should generate a random CPF with punctuation", async () => { + render(); + + const input = screen.getByPlaceholderText("Clique no botão abaixo"); + + const checkbox = screen.getByRole("checkbox"); + + const button = screen.getByText("Gerar CPF"); + + fireEvent(checkbox, "onValueChange", true); + + fireEvent.press(button); + + expect(input.props.value).toMatch(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/); + }); + + it("should copy generated CPF to clipboard", async () => { + render(); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + const button = screen.getByText("Gerar CPF"); + + fireEvent.press(button); + + fireEvent.press(buttonCopy); + }); + + it("should not copy if there is no generated CPF", async () => { + render(); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + fireEvent.press(buttonCopy); + }); + + it("should load checkbox value from AsyncStorage", async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValueOnce("true"); + + render(); + + const checkbox = await screen.findByRole("checkbox"); + + expect(checkbox.props.accessibilityState.checked).toBe(true); + }); +}); diff --git a/src/pages/generators/Cpf/index.tsx b/src/pages/generators/Cpf/index.tsx index 3dfe56b..e307797 100644 --- a/src/pages/generators/Cpf/index.tsx +++ b/src/pages/generators/Cpf/index.tsx @@ -28,13 +28,10 @@ export default function CpfGeneratorPage() { const [cpfWithPeriod, setCpfWithPeriod] = useState(false); const formatCpf = (cpf: string) => { - if (cpf && cpf.length === 11) { - return `${cpf.slice(0, 3)}.${cpf.slice(3, 6)}.${cpf.slice( - 6, - 9 - )}-${cpf.slice(9)}`; - } - return cpf; + return `${cpf.slice(0, 3)}.${cpf.slice(3, 6)}.${cpf.slice( + 6, + 9 + )}-${cpf.slice(9)}`; }; const generateRandomCpf = () => { @@ -103,7 +100,7 @@ export default function CpfGeneratorPage() { color="#007BFF" /> - + diff --git a/src/pages/generators/CreditCard/__tests__/CreditCard.test.tsx b/src/pages/generators/CreditCard/__tests__/CreditCard.test.tsx new file mode 100644 index 0000000..3e23558 --- /dev/null +++ b/src/pages/generators/CreditCard/__tests__/CreditCard.test.tsx @@ -0,0 +1,99 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { fireEvent, render, screen } from "@testing-library/react-native"; + +import CreditCardPage from ".."; + +describe("CreditCard Genarator", () => { + beforeEach(() => { + jest.clearAllMocks(); + AsyncStorage.clear(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should render correctly", () => { + render(); + + const title = screen.getByText(/Gerador de Cartão de Crédito/i); + + expect(title).toBeDefined(); + }); + + it("should generate a random CreditCard without punctuation", async () => { + render(); + + const input = screen.getByPlaceholderText("Clique no botão abaixo"); + + expect(input).toBeDefined(); + + const button = screen.getByText("Gerar Cartão de crédito"); + + expect(button).toBeDefined(); + + fireEvent.press(button); + + expect(input.props.value).toMatch(/^\d{16}$/); + }); + + it("should change checkbox value", async () => { + render(); + + const checkbox = screen.getByRole("checkbox"); + + fireEvent(checkbox, "onValueChange", true); + + expect(checkbox.props.accessibilityState.checked).toBe(true); + + fireEvent(checkbox, "onValueChange", false); + + expect(checkbox.props.accessibilityState.checked).toBe(false); + }); + + it("should generate a random CreditCard with punctuation", async () => { + render(); + + const input = screen.getByPlaceholderText("Clique no botão abaixo"); + + const checkbox = screen.getByRole("checkbox"); + + const button = screen.getByText("Gerar Cartão de crédito"); + + fireEvent(checkbox, "onValueChange", true); + + fireEvent.press(button); + + expect(input.props.value).toMatch(/^\d{4} \d{4} \d{4} \d{4}$/); + }); + + it("should copy generated CreditCard to clipboard", async () => { + render(); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + const button = screen.getByText("Gerar Cartão de crédito"); + + fireEvent.press(button); + + fireEvent.press(buttonCopy); + }); + + it("should not copy if there is no generated CreditCard", async () => { + render(); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + fireEvent.press(buttonCopy); + }); + + it("should load checkbox value from AsyncStorage", async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValueOnce("true"); + + render(); + + const checkbox = await screen.findByRole("checkbox"); + + expect(checkbox.props.accessibilityState.checked).toBe(true); + }); +}); diff --git a/src/pages/generators/CreditCard/index.tsx b/src/pages/generators/CreditCard/index.tsx index 67d6903..01088ad 100644 --- a/src/pages/generators/CreditCard/index.tsx +++ b/src/pages/generators/CreditCard/index.tsx @@ -116,7 +116,7 @@ export default function CreditCardGeneratorPage() { color="#007BFF" /> - + diff --git a/src/pages/generators/PasswordGen/__tests__/PasswordGen.test.tsx b/src/pages/generators/PasswordGen/__tests__/PasswordGen.test.tsx new file mode 100644 index 0000000..c41c76e --- /dev/null +++ b/src/pages/generators/PasswordGen/__tests__/PasswordGen.test.tsx @@ -0,0 +1,5 @@ +describe("Password Generator", () => { + it("should render correctly", () => { + expect(true).toBe(true); + }); +}); diff --git a/src/pages/validators/Cnpj/__tests__/Cnpj.test.tsx b/src/pages/validators/Cnpj/__tests__/Cnpj.test.tsx new file mode 100644 index 0000000..5d6317c --- /dev/null +++ b/src/pages/validators/Cnpj/__tests__/Cnpj.test.tsx @@ -0,0 +1,107 @@ +import Clipboard from "@react-native-clipboard/clipboard"; +import { fireEvent, render, screen } from "@testing-library/react-native"; + +import CnpjValidatorPage from ".."; + +describe("Cnpj Validator", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + it("should render correctly", () => { + render(); + + const title = screen.getByText("Validador de CNPJ"); + + const resultView = screen.queryByTestId("resultView"); + + expect(resultView).toBeNull(); + + expect(title).toBeDefined(); + }); + + it("should validate a valid CNPJ", async () => { + render(); + + const input = screen.getByPlaceholderText("48.955.245/0001-01"); + + const button = screen.getByText("Validar CNPJ"); + + fireEvent.changeText(input, "30.187.097/3277-49"); + + fireEvent.press(button); + + const resultView = await screen.findByText("CNPJ Válido"); + + expect(resultView).toBeDefined(); + }); + + it("should invalidate an invalid CNPJ", async () => { + render(); + + const input = screen.getByPlaceholderText("48.955.245/0001-01"); + + const button = screen.getByText("Validar CNPJ"); + + fireEvent.changeText(input, "48.955.245/0001-01"); + + fireEvent.press(button); + + const resultView = await screen.findByText("CNPJ Inválido"); + + expect(resultView).toBeDefined(); + }); + + it("should paste a CNPJ", async () => { + jest.spyOn(Clipboard, "getString").mockResolvedValue("30.187.097/3277-49"); + + render(); + + const buttonPaste = screen.getByTestId("buttonPaste"); + + fireEvent.press(buttonPaste); + + const input = await screen.findByDisplayValue("30.187.097/3277-49"); + + expect(input).toBeDefined(); + }); + + it("should copy a CNPJ", async () => { + render(); + + const input = screen.getByPlaceholderText("48.955.245/0001-01"); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + fireEvent.changeText(input, "30.187.097/3277-49"); + + fireEvent.press(buttonCopy); + }); + + it("should not copy if there is no CNPJ", async () => { + render(); + + const buttonCopy = screen.getByTestId("buttonCopy"); + + fireEvent.press(buttonCopy); + }); + + it("should clean a CNPJ", async () => { + render(); + + const input = screen.getByPlaceholderText("48.955.245/0001-01"); + + const buttonClean = screen.getByTestId("buttonClean"); + + fireEvent.changeText(input, "30.187.097/3277-49"); + + fireEvent.press(buttonClean); + + const emptyInput = await screen.findByDisplayValue(""); + + expect(emptyInput).toBeDefined(); + }); +}); diff --git a/src/pages/validators/Cnpj/index.tsx b/src/pages/validators/Cnpj/index.tsx index 179caef..162e60c 100644 --- a/src/pages/validators/Cnpj/index.tsx +++ b/src/pages/validators/Cnpj/index.tsx @@ -69,18 +69,21 @@ export default function CnpjValidatorPage() {