diff --git a/components/AddTask.js b/components/AddTask.js
index 7b865f03..b5de0744 100644
--- a/components/AddTask.js
+++ b/components/AddTask.js
@@ -79,6 +79,7 @@ const CreateTaskScreen = ({ route }) => {
selectedValue={priority}
onValueChange={(itemValue, itemIndex) => setPriority(itemValue)}
style={styles.priorityPicker}
+ testID="priority-selector"
>
@@ -88,6 +89,7 @@ const CreateTaskScreen = ({ route }) => {
onPress={handleCreateTask}
label="Create Task"
disabled={!taskName.trim()}
+ testID="create-task-button"
/>
);
diff --git a/screens/SettingsScreen.js b/screens/SettingsScreen.js
index 53235148..de2a7138 100644
--- a/screens/SettingsScreen.js
+++ b/screens/SettingsScreen.js
@@ -147,12 +147,14 @@ function SelectProfile() {
placeholder={firstName ? firstName : 'John'}
placeholderTextColor={'#999897'}
onChangeText={(text) => setEditedFirstName(text)}
+ testID='first-name-input'
/>
setEditedLastName(text)}
+ testID='last-name-input'
/>
-
+
Save
diff --git a/tests/AddMeal.test.js b/tests/AddMeal.test.js
new file mode 100644
index 00000000..8b65a9d7
--- /dev/null
+++ b/tests/AddMeal.test.js
@@ -0,0 +1,107 @@
+import React from "react";
+import { render, fireEvent, waitFor } from "@testing-library/react-native";
+import AddMeal from "../components/AddMeal"; // Updated to AddMeal
+import { Alert } from "react-native";
+import { useNavigation, useRoute } from "@react-navigation/native";
+import { useMeals } from "../services/MealsContext";
+
+// Mock useMeals to return default values and a function to update these values
+jest.mock("../services/MealsContext", () => ({
+ useMeals: () => ({
+ savedMeals: [], // Default empty array for saved meals
+ setSavedMeals: jest.fn(), // Mock function to simulate setting saved meals
+ }),
+}));
+
+describe("AddMeal", () => {
+});
+jest.mock("@react-navigation/native", () => ({
+ ...jest.requireActual("@react-navigation/native"),
+ useNavigation: jest.fn(() => ({
+ navigate: jest.fn(),
+ goBack: jest.fn(),
+ })),
+ useRoute: () => ({
+ params: { userID: "123" },
+ }),
+}));
+
+// Assuming similar dependencies for AddMeal as AddTask
+jest.mock("../services/AuthAPI", () => ({
+ addMealData: jest.fn().mockResolvedValue(), // Assume this method handles meal data
+}));
+
+jest.mock("react-native", () => {
+ const actualRN = jest.requireActual("react-native");
+ return {
+ ...actualRN,
+ Alert: {
+ ...actualRN.Alert,
+ alert: jest.fn(),
+ },
+ };
+});
+
+jest.mock("../components/CreateButton", () => "CreateButton");
+jest.mock("../components/MealHeader", () => "MealHeader");
+
+jest.mock("../services/ThemeContext", () => ({
+ useTheme: () => ({
+ theme: "light",
+ toggleTheme: jest.fn(),
+ }),
+}));
+
+describe("AddMeal", () => {
+ const mockNavigate = jest.fn();
+ const mockGoBack = jest.fn();
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ jest.resetAllMocks();
+
+ useNavigation.mockReturnValue({
+ navigate: mockNavigate,
+ goBack: mockGoBack,
+ });
+ });
+
+ it("renders correctly with initial route params", () => {
+ const route = { params: { userID: "123" } };
+ const { getByPlaceholderText } = render();
+ expect(getByPlaceholderText("Meal Name")).toBeTruthy(); // Adjusted placeholder
+ });
+
+ it("handles input changes", () => {
+ const route = { params: { userID: "123" } };
+ const { getByPlaceholderText } = render();
+ const nameInput = getByPlaceholderText("Meal Name"); // Adjusted placeholder
+ fireEvent.changeText(nameInput, "New Meal");
+ expect(nameInput.props.value).toBe("New Meal");
+ });
+
+ it("adds a new meal and updates state correctly", async () => {
+ const { getByPlaceholderText, getByTestId } = render();
+ const mealNameInput = getByPlaceholderText("Meal Name");
+ const createButton = getByTestId("submit-meal");
+ fireEvent.changeText(getByPlaceholderText("Meal Name"), "Pasta");
+ fireEvent.changeText(getByPlaceholderText("Add ingredients..."), "Tomato, Cheese");
+ fireEvent.changeText(getByPlaceholderText("Servings"), "4");
+ fireEvent.changeText(getByPlaceholderText("Add instructions..."), "Cook for 20 minutes");
+
+ // Simulate button press
+ fireEvent.press(createButton);
+
+ await waitFor(() => {
+ // Check if the Alert was called with the correct arguments
+ expect(Alert.alert).toHaveBeenCalledWith("Confirm", expect.anything(), expect.anything());
+ // Simulate user confirming the creation
+ const confirmButton = Alert.alert.mock.calls[0][2][1].onPress;
+ confirmButton();
+ });
+
+ // Check if navigation was called after adding the meal
+ expect(mockNavigate).toHaveBeenCalledWith("Your Cookbook", { activeTab: "SavedMeals" });
+ });
+
+ });
\ No newline at end of file
diff --git a/tests/CreateTaskScreen.test.js b/tests/CreateTaskScreen.test.js
new file mode 100644
index 00000000..f13ec6c5
--- /dev/null
+++ b/tests/CreateTaskScreen.test.js
@@ -0,0 +1,126 @@
+import React from "react";
+import { render, fireEvent, waitFor } from "@testing-library/react-native";
+import AddTask from "../components/AddTask";
+import { Alert } from "react-native";
+import { useNavigation, useRoute } from "@react-navigation/native";
+
+// Ensuring consistent mock returns for every test instance
+jest.mock("@react-navigation/native", () => ({
+ ...jest.requireActual("@react-navigation/native"),
+ useNavigation: jest.fn(() => ({
+ navigate: jest.fn(),
+ goBack: jest.fn(),
+ })),
+ useRoute: () => ({
+ params: { userID: "123" },
+ }),
+}));
+
+// Mock Firebase and navigation
+jest.mock("firebase/auth", () => {
+ return {
+ getAuth: jest.fn(() => ({
+ currentUser: { uid: "123" },
+ signOut: jest.fn().mockResolvedValue(),
+ })),
+ };
+});
+
+jest.mock("firebase/firestore", () => {
+ return {
+ getFirestore: jest.fn(),
+ doc: jest.fn(() => ({
+ get: jest.fn(() =>
+ Promise.resolve({
+ data: () => ({
+ firstName: "John",
+ lastName: "Doe",
+ phone_number: "1234567890",
+ }),
+ })
+ ),
+ })),
+ getDoc: jest.fn(() =>
+ Promise.resolve({
+ exists: () => true,
+ data: () => ({ firstName: "John", lastName: "Doe" }),
+ })
+ ),
+ };
+});
+
+jest.mock("../services/AuthAPI", () => ({
+ saveTaskForUser: jest.fn().mockResolvedValue(),
+}));
+
+jest.mock("react-native", () => {
+ const actualRN = jest.requireActual("react-native");
+ return {
+ ...actualRN,
+ Alert: {
+ ...actualRN.Alert,
+ alert: jest.fn(),
+ },
+ };
+});
+
+jest.mock("../components/DateTimePicker", () => "DateTimePicker");
+jest.mock("../components/TypeSelector", () => "TypeSelector");
+jest.mock("../components/CreateButton", () => "CreateButton");
+
+jest.mock("../services/ThemeContext", () => ({
+ useTheme: () => ({
+ theme: "light",
+ toggleTheme: jest.fn(),
+ }),
+}));
+
+describe("AddTask", () => {
+ const mockNavigate = jest.fn();
+ const mockGoBack = jest.fn();
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ jest.resetAllMocks();
+
+ // Mock useNavigation with specific implementations for each test
+ useNavigation.mockReturnValue({
+ navigate: mockNavigate,
+ goBack: mockGoBack,
+ });
+ });
+
+ it("renders correctly with initial route params", () => {
+ const route = { params: { userID: "123" } };
+ const { getByPlaceholderText } = render();
+ expect(getByPlaceholderText("Name")).toBeTruthy();
+ });
+
+ it("handles input changes", () => {
+ const route = { params: { userID: "123" } };
+ const { getByPlaceholderText } = render();
+ const nameInput = getByPlaceholderText("Name");
+ fireEvent.changeText(nameInput, "New Task");
+ expect(nameInput.props.value).toBe("New Task");
+ });
+
+ it("calls the save task API and navigates on successful task creation", async () => {
+ const route = { params: { userID: "123" } };
+ const { getByTestId, getByPlaceholderText } = render();
+ const nameInput = getByPlaceholderText("Name");
+ fireEvent.changeText(nameInput, "New Task");
+ fireEvent.changeText(getByPlaceholderText("Location"), "Home");
+ fireEvent.changeText(getByPlaceholderText("Comments"), "Test comment");
+ fireEvent.changeText(getByTestId("priority-selector"), "high");
+ fireEvent.press(getByTestId("create-task-button"));
+
+ await waitFor(() => {
+ expect(Alert.alert).toHaveBeenCalledWith(
+ "Success", "Task created successfully!"
+ );
+ });
+
+
+ });
+
+});
diff --git a/tests/SettingScreen.test.js b/tests/SettingScreen.test.js
index 84a41c5c..8182c576 100644
--- a/tests/SettingScreen.test.js
+++ b/tests/SettingScreen.test.js
@@ -1,36 +1,49 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import SettingsScreen from '../screens/SettingsScreen';
+import { Alert } from "react-native";
+import { updateUserProfile } from '../services/AuthAPI';
-// Mock Firebase and navigation
-jest.mock('firebase/auth', () => {
+jest.mock('firebase/auth', () => ({
+ getAuth: jest.fn().mockReturnValue({
+ currentUser: { uid: '123' },
+ signOut: jest.fn().mockResolvedValue(),
+ })
+}));
+
+jest.mock("react-native/Libraries/Alert/Alert", () => ({
+ alert: jest.fn(),
+}));
+
+jest.mock('react-native', () => {
+ const actualRN = jest.requireActual('react-native');
return {
- getAuth: jest.fn(() => ({
- currentUser: { uid: '123' },
- signOut: jest.fn().mockResolvedValue(),
- })),
+ ...actualRN,
+ Alert: {
+ ...actualRN.Alert,
+ alert: jest.fn(),
+ },
};
});
-jest.mock('firebase/firestore', () => {
- return {
- getFirestore: jest.fn(),
- doc: jest.fn(() => ({
- get: jest.fn(() => Promise.resolve({
- data: () => ({ firstName: 'John', lastName: 'Doe', phone_number: '1234567890' }),
- })),
- })),
- getDoc: jest.fn(() => Promise.resolve({
- exists: () => true,
- data: () => ({ firstName: 'John', lastName: 'Doe' })
+jest.mock('firebase/firestore', () => ({
+ getFirestore: jest.fn(),
+ doc: jest.fn(() => ({
+ get: jest.fn(() => Promise.resolve({
+ data: () => ({ firstName: 'John', lastName: 'Doe', phone_number: '1234567890' }),
})),
- };
-});
+ })),
+ getDoc: jest.fn(() => Promise.resolve({
+ exists: () => true,
+ data: () => ({ firstName: 'John', lastName: 'Doe' })
+ })),
+}));
jest.mock('../services/AuthAPI', () => ({
updateUserProfile: jest.fn(),
}));
+
jest.mock('@react-navigation/core', () => ({
useNavigation: () => ({
navigate: jest.fn(),
@@ -45,49 +58,73 @@ jest.mock('../services/ThemeContext', () => ({
}),
}));
-
describe('SettingsScreen', () => {
- it('renders the initial active tab as Profile', () => {
- const { getByText } = render();
- expect(getByText('Profile')).toBeTruthy();
- });
-
- it('switches to Account tab when pressed', () => {
- const { getByText, getByTestId } = render();
- fireEvent.press(getByTestId('tab-account'));
- expect(getByText('Account')).toBeTruthy();
- });
-
- it('opens modal when Edit button is pressed in Profile tab', () => {
- const { getByTestId, getByText } = render();
- fireEvent.press(getByTestId('edit-button'));
- expect(getByText('Edit Profile Information')).toBeTruthy();
- });
-
- it('closes modal when Cancel button is pressed', () => {
- const { getByTestId, queryByText } = render();
- fireEvent.press(getByTestId('edit-button')); // Open modal
- fireEvent.press(getByTestId('cancel-button')); // Close modal
- expect(queryByText('Edit Profile Information')).toBeNull();
+ it('renders the initial active tab as Profile', () => {
+ const { getByText } = render();
+ expect(getByText('Profile')).toBeTruthy();
+ });
+
+ it('switches to Account tab when pressed', () => {
+ const { getByTestId } = render();
+ fireEvent.press(getByTestId('tab-account'));
+ // Ensure you are asserting something meaningful in the 'Account' tab context
+ });
+
+ it('opens modal when Edit button is pressed in Profile tab', () => {
+ const { getByTestId, getByText } = render();
+ fireEvent.press(getByTestId('edit-button'));
+ expect(getByText('Edit Profile Information')).toBeTruthy();
+ });
+
+ it('closes modal when Cancel button is pressed', () => {
+ const { getByTestId, queryByText } = render();
+ fireEvent.press(getByTestId('edit-button')); // Open modal
+ fireEvent.press(getByTestId('cancel-button')); // Close modal
+ expect(queryByText('Edit Profile Information')).toBeNull();
+ });
+
+ it('calls updateProfile when Save is pressed and fields are edited', async () => {
+ const { getByTestId } = render();
+ fireEvent.press(getByTestId('edit-button')); // Open modal
+ fireEvent.changeText(getByTestId('first-name-input'), 'Jane');
+ fireEvent.changeText(getByTestId('last-name-input'), 'Doe');
+ fireEvent.press(getByTestId('save-button'));
+
+ await waitFor(() => {
+ expect(updateUserProfile).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
+ firstName: 'Jane'
+ }));
});
+ });
+
+ it("logs out the user when the Sign Out button is pressed and confirmed", async () => {
+ const { getByText, getByTestId } = render();
+ const getAuth = require("firebase/auth").getAuth;
- it('calls updateProfile when Save is pressed and fields are edited', async () => {
- const updateUserProfile = require('../services/AuthAPI').updateUserProfile;
- const { getByTestId, getByPlaceholderText } = render();
- fireEvent.changeText(getByPlaceholderText('John'), 'Jane');
- fireEvent.press(getByTestId('save-button'));
+ // Navigate to Account tab
+ fireEvent.press(getByTestId("tab-account"));
+ await waitFor(() => expect(getByText("Payment Methods")).toBeTruthy());
- await waitFor(() => {
- expect(updateUserProfile).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
- firstName: 'Jane'
- }));
- });
- });
+ // Press Sign Out button
+ fireEvent.press(getByTestId("sign-out-button"));
- it('logs out the user when the Sign Out button is pressed', () => {
- const { getByText } = render();
- fireEvent.press(getByText('Sign Out'));
- expect(getAuth().signOut).toHaveBeenCalled();
- });
+ // Check if Alert.alert was called with the correct arguments
+ expect(Alert.alert).toHaveBeenCalledWith(
+ "Sign Out", // Title
+ "Are you sure you would like to sign out?", // Message
+ [
+ {
+ text: "Cancel",
+ onPress: expect.any(Function),
+ style: "cancel"
+ },
+ {
+ text: "Yes",
+ onPress: expect.any(Function)
+ }
+ ],
+ { cancelable: false }
+ );
});
-
\ No newline at end of file
+
+});