-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #85 from COS301-SE-2024/feat/mobile-integration/bo…
…oking Feat/mobile integration/booking
- Loading branch information
Showing
36 changed files
with
2,514 additions
and
1,023 deletions.
There are no files selected for viewing
58 changes: 58 additions & 0 deletions
58
frontend/occupi-mobile3/__tests__/Login_Test/Onboarding3.test.js
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,58 @@ | ||
import React from 'react'; | ||
import { render, fireEvent } from '@testing-library/react-native'; | ||
import Onboarding3 from '../../screens/Login/Onboarding3'; | ||
import { router } from 'expo-router'; | ||
|
||
jest.mock('expo-router', () => ({ | ||
useRouter: () => ({ | ||
replace: jest.fn(), | ||
push: jest.fn(), | ||
}), | ||
router: { | ||
push: jest.fn(), | ||
}, | ||
})); | ||
|
||
jest.mock('expo-linear-gradient', () => ({ | ||
LinearGradient: ({ children }) => children, | ||
})); | ||
|
||
jest.mock('@gluestack-style/react', () => ({ | ||
StyledProvider: ({ children }) => children, | ||
useStyled: () => ({}), | ||
StyledText: 'Text', | ||
StyledView: 'View', | ||
StyledImage: 'Image', | ||
StyledButton: 'Button', | ||
// Mock other components if necessary | ||
})); | ||
|
||
jest.mock('@gluestack-ui/themed', () => ({ | ||
Box: 'View', | ||
Image: 'Image', | ||
Center: 'View', | ||
Text: 'Text', | ||
Heading: 'Text', | ||
Button: 'Button', | ||
})); | ||
|
||
describe('Onboarding3', () => { | ||
it('renders the image correctly', () => { | ||
const { getByRole } = render(<Onboarding3 />); | ||
const image = getByRole('image', { name: 'logo' }); | ||
expect(image).toBeTruthy(); | ||
}); | ||
|
||
it('renders the heading and text correctly', () => { | ||
const { getByText } = render(<Onboarding3 />); | ||
expect(getByText('Real time updates')).toBeTruthy(); | ||
expect(getByText('Provides real time updates for occupancy and capacity')).toBeTruthy(); | ||
}); | ||
|
||
it('navigates to the welcome screen when the button is pressed', () => { | ||
const { getByText } = render(<Onboarding3 />); | ||
const button = getByText('Next'); | ||
fireEvent.press(button); | ||
expect(router.push).toHaveBeenCalledWith('/welcome'); | ||
}); | ||
}); |
117 changes: 117 additions & 0 deletions
117
frontend/occupi-mobile3/__tests__/Login_Test/OtpVerification.test.js
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,117 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, act } from '@testing-library/react-native'; | ||
import OTPVerification from '../../screens/Login/OTPVerification'; | ||
import { router } from 'expo-router'; | ||
|
||
jest.mock('expo-router', () => ({ | ||
useRouter: () => ({ | ||
replace: jest.fn(), | ||
push: jest.fn(), | ||
}), | ||
router: { | ||
push: jest.fn(), | ||
}, | ||
})); | ||
|
||
jest.mock('expo-linear-gradient', () => ({ | ||
LinearGradient: ({ children }) => children, | ||
})); | ||
|
||
jest.mock('@gluestack-ui/themed', () => ({ | ||
VStack: 'View', | ||
Box: 'View', | ||
HStack: 'View', | ||
Text: 'Text', | ||
Button: 'Button', | ||
Image: 'Image', | ||
Center: 'View', | ||
FormControl: 'View', | ||
Input: 'TextInput', | ||
LinkText: 'Text', | ||
FormControlHelperText: 'Text', | ||
InputField: 'TextInput', | ||
ButtonText: 'Text', | ||
FormControlError: 'View', | ||
FormControlErrorIcon: 'View', | ||
FormControlErrorText: 'Text', | ||
Toast: 'View', | ||
ToastTitle: 'Text', | ||
useToast: () => ({ | ||
show: jest.fn(), | ||
}), | ||
Heading: 'Text', | ||
})); | ||
|
||
jest.mock('expo-random', () => ({ | ||
getRandomBytesAsync: jest.fn().mockResolvedValue(new Uint8Array(3)), | ||
})); | ||
|
||
jest.mock('expo-secure-store', () => ({ | ||
setItemAsync: jest.fn(), | ||
})); | ||
|
||
describe('OTPVerification', () => { | ||
it('renders the main text correctly', () => { | ||
const { getByText } = render(<OTPVerification />); | ||
expect(getByText('We sent you an email code')).toBeTruthy(); | ||
expect(getByText('We have sent the OTP code to [email protected]')).toBeTruthy(); | ||
}); | ||
|
||
it('renders the image correctly', () => { | ||
const { getByRole } = render(<OTPVerification />); | ||
const image = getByRole('image', { name: 'occupi' }); | ||
expect(image).toBeTruthy(); | ||
}); | ||
|
||
it('renders the countdown timer correctly', () => { | ||
const { getByText } = render(<OTPVerification />); | ||
expect(getByText('60 seconds remaining')).toBeTruthy(); | ||
}); | ||
|
||
it('updates the countdown timer every second', () => { | ||
jest.useFakeTimers(); | ||
const { getByText } = render(<OTPVerification />); | ||
|
||
act(() => { | ||
jest.advanceTimersByTime(1000); | ||
}); | ||
|
||
expect(getByText('59 seconds remaining')).toBeTruthy(); | ||
|
||
jest.useRealTimers(); | ||
}); | ||
|
||
it('validates OTP input correctly', async () => { | ||
const { getByText, getByPlaceholderText, findByText } = render(<OTPVerification />); | ||
|
||
const input = getByPlaceholderText(''); | ||
|
||
fireEvent.changeText(input, '1'); | ||
fireEvent.changeText(input, '12'); | ||
fireEvent.changeText(input, '123'); | ||
fireEvent.changeText(input, '1234'); | ||
fireEvent.changeText(input, '12345'); | ||
fireEvent.changeText(input, '123456'); | ||
|
||
const button = getByText('Verify'); | ||
fireEvent.press(button); | ||
|
||
expect(await findByText('OTP must be at least 6 characters in length')).toBeTruthy(); | ||
}); | ||
|
||
it('navigates to the home screen when OTP is correct', async () => { | ||
const { getByText, getAllByPlaceholderText } = render(<OTPVerification />); | ||
|
||
const inputs = getAllByPlaceholderText(''); | ||
inputs.forEach((input, index) => { | ||
fireEvent.changeText(input, (index + 1).toString()); | ||
}); | ||
|
||
const button = getByText('Verify'); | ||
fireEvent.press(button); | ||
|
||
await act(async () => { | ||
expect(router.push).toHaveBeenCalledWith('/home'); | ||
}); | ||
}); | ||
}); |
88 changes: 88 additions & 0 deletions
88
frontend/occupi-mobile3/__tests__/Profile_Test/Profile.test.js
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,88 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, waitFor } from '@testing-library/react-native'; | ||
import Profile from '../../screens/Profile/Profile'; | ||
import { router } from 'expo-router'; | ||
import DateTimePickerModal from 'react-native-modal-datetime-picker'; | ||
|
||
jest.mock('expo-router', () => ({ | ||
router: { | ||
push: jest.fn(), | ||
}, | ||
})); | ||
|
||
jest.mock('react-native-modal-datetime-picker', () => { | ||
return { | ||
__esModule: true, | ||
default: jest.fn().mockImplementation(({ onConfirm, onCancel }) => null), | ||
}; | ||
}); | ||
|
||
describe('Profile Component', () => { | ||
it('renders correctly', () => { | ||
const { getByText, getByPlaceholderText } = render(<Profile />); | ||
|
||
expect(getByText('My account')).toBeTruthy(); | ||
expect(getByPlaceholderText('Sabrina Carpenter')).toBeTruthy(); | ||
expect(getByText('Save')).toBeTruthy(); | ||
}); | ||
|
||
it('navigates to settings screen on back arrow press', () => { | ||
const { getByTestId } = render(<Profile />); | ||
|
||
const backArrow = getByTestId('back-arrow'); | ||
fireEvent.press(backArrow); | ||
|
||
expect(router.push).toHaveBeenCalledWith('/settings'); | ||
}); | ||
|
||
it('shows date picker on date of birth press', () => { | ||
const { getByText } = render(<Profile />); | ||
|
||
const dateOfBirth = getByText(new Date(2000, 6, 7).toLocaleDateString()); | ||
fireEvent.press(dateOfBirth); | ||
|
||
expect(DateTimePickerModal).toHaveBeenCalledWith( | ||
expect.objectContaining({ | ||
isVisible: true, | ||
}), | ||
{} | ||
); | ||
}); | ||
|
||
it('saves profile with updated details', async () => { | ||
const alertMock = jest.spyOn(global, 'alert').mockImplementation(() => {}); | ||
|
||
const { getByText, getByPlaceholderText } = render(<Profile />); | ||
|
||
fireEvent.changeText(getByPlaceholderText('Sabrina Carpenter'), 'John Doe'); | ||
fireEvent.changeText(getByPlaceholderText('[email protected]'), '[email protected]'); | ||
fireEvent.changeText(getByPlaceholderText('21546551'), '12345678'); | ||
fireEvent.changeText(getByPlaceholderText('011 101 1111'), '987 654 3210'); | ||
fireEvent.changeText(getByPlaceholderText('she/her'), 'he/him'); | ||
|
||
const saveButton = getByText('Save'); | ||
fireEvent.press(saveButton); | ||
|
||
await waitFor(() => { | ||
expect(alertMock).toHaveBeenCalledWith( | ||
'Profile Saved', | ||
expect.stringContaining('Name: John Doe') | ||
); | ||
}); | ||
|
||
alertMock.mockRestore(); | ||
}); | ||
|
||
it('updates gender selection correctly', () => { | ||
const { getByText } = render(<Profile />); | ||
|
||
fireEvent.press(getByText('Male')); | ||
expect(getByText('Male')).toBeTruthy(); | ||
|
||
fireEvent.press(getByText('Female')); | ||
expect(getByText('Female')).toBeTruthy(); | ||
|
||
fireEvent.press(getByText('Other')); | ||
expect(getByText('Other')).toBeTruthy(); | ||
}); | ||
}); |
103 changes: 103 additions & 0 deletions
103
frontend/occupi-mobile3/__tests__/Profile_Test/Settings.test.js
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,103 @@ | ||
import React from 'react'; | ||
import { render, fireEvent } from '@testing-library/react-native'; | ||
import AsyncStorage from '@react-native-async-storage/async-storage'; | ||
import Settings from '../../screens/Profile/Settings'; | ||
import { useNavigation, NavigationContainer } from '@react-navigation/native'; | ||
|
||
jest.mock('@react-native-async-storage/async-storage', () => ({ | ||
clear: jest.fn(), | ||
})); | ||
|
||
jest.mock('@react-navigation/native', () => { | ||
const actualNav = jest.requireActual('@react-navigation/native'); | ||
return { | ||
...actualNav, | ||
useNavigation: () => ({ | ||
navigate: jest.fn(), | ||
reset: jest.fn(), | ||
}), | ||
}; | ||
}); | ||
|
||
jest.mock('@gluestack-ui/themed', () => ({ | ||
useTheme: jest.fn(() => ({ theme: 'light', toggleTheme: jest.fn() })), | ||
Switch: jest.fn(({ checked, onValueChange }) => ( | ||
<switch onValueChange={onValueChange} value={checked} /> | ||
)), | ||
Icon: jest.fn(({ name, fill }) => ( | ||
<icon name={name} fill={fill} /> | ||
)), | ||
Divider: jest.fn(({ style }) => ( | ||
<divider style={style} /> | ||
)), | ||
Box: jest.fn(({ data, renderItem, ItemSeparatorComponent }) => ( | ||
<box> | ||
{data.map((item, index) => ( | ||
<React.Fragment key={index}> | ||
{renderItem({ item })} | ||
{index < data.length - 1 && <ItemSeparatorComponent />} | ||
</React.Fragment> | ||
))} | ||
</box> | ||
)), | ||
})); | ||
|
||
describe('Settings Component', () => { | ||
const renderSettings = () => ( | ||
<NavigationContainer> | ||
<Settings /> | ||
</NavigationContainer> | ||
); | ||
|
||
it('renders correctly', () => { | ||
const { getByText, getByAltText } = render(renderSettings()); | ||
|
||
expect(getByAltText('logo')).toBeTruthy(); | ||
expect(getByText('Sabrina Carpenter')).toBeTruthy(); | ||
expect(getByText('Chief Executive Officer')).toBeTruthy(); | ||
expect(getByText('Version 0.1.0')).toBeTruthy(); | ||
}); | ||
|
||
it('navigates to correct screen when list item is pressed', () => { | ||
const { getByText } = render(renderSettings()); | ||
const navigation = useNavigation(); | ||
|
||
fireEvent.press(getByText('My account')); | ||
expect(navigation.navigate).toHaveBeenCalledWith('AccountScreen'); | ||
|
||
fireEvent.press(getByText('Privacy Policy')); | ||
expect(navigation.navigate).toHaveBeenCalledWith('PrivacyPolicyScreen'); | ||
}); | ||
|
||
it('toggles notifications correctly', () => { | ||
const { getByText, getByValue } = render(renderSettings()); | ||
|
||
const notificationsToggle = getByValue(true); // assuming true is the initial value | ||
fireEvent(notificationsToggle, 'valueChange', false); | ||
|
||
expect(notificationsToggle.props.value).toBe(false); | ||
}); | ||
|
||
it('toggles dark mode correctly', () => { | ||
const { getByText, getByValue } = render(renderSettings()); | ||
const themeToggle = getByValue(false); // assuming false is the initial value | ||
|
||
fireEvent(themeToggle, 'valueChange', true); | ||
|
||
expect(themeToggle.props.value).toBe(true); | ||
}); | ||
|
||
it('logs out correctly', async () => { | ||
const { getByText, getByAltText } = render(renderSettings()); | ||
const navigation = useNavigation(); | ||
|
||
fireEvent.press(getByText('Log out')); | ||
fireEvent.press(getByText('OK')); | ||
|
||
expect(AsyncStorage.clear).toHaveBeenCalled(); | ||
expect(navigation.reset).toHaveBeenCalledWith({ | ||
index: 0, | ||
routes: [{ name: 'login' }], | ||
}); | ||
}); | ||
}); |
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
Oops, something went wrong.