Skip to content

Commit

Permalink
Merge pull request #22 from AlanFnz/feature/20_hold-to-record-voice-note
Browse files Browse the repository at this point in the history
feat(infra): hold to record voice note phase 1
  • Loading branch information
AlanFnz authored Dec 6, 2024
2 parents d0a90d3 + 611ce15 commit 64b6b47
Show file tree
Hide file tree
Showing 21 changed files with 337 additions and 174 deletions.
32 changes: 24 additions & 8 deletions __tests__/HomeScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React from 'react';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import { NavigationContainer } from '@react-navigation/native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { render } from '@testing-library/react-native';
import configureStore from 'redux-mock-store';
import { fireEvent, render } from '@testing-library/react-native';

import foldersReducer from '@store/foldersSlice';
import foldersMockData from '@store/mockData/folders.mockData';
import HomeScreen from '@screens/HomeScreen';

jest.mock('@screens/HomeScreen/components/FolderList', () => 'FolderList');
jest.mock('@screens/HomeScreen/components/SearchBox', () => 'SearchBox');
jest.mock(
'@screens/HomeScreen/components/NotesResultsList',
() => 'NotesResultsList',
Expand All @@ -23,9 +25,8 @@ jest.mock('react-native-safe-area-context', () => ({
}));

describe('HomeScreen', () => {
const mockStore = configureStore();
const initialState = {
folders: { folders: [{ id: 1, name: 'Test Folder', notes: [] }] },
folders: foldersMockData,
};

beforeEach(() => {
Expand All @@ -41,8 +42,16 @@ describe('HomeScreen', () => {
jest.clearAllMocks();
});

const createTestStore = (preloadedState = initialState) =>
configureStore({
reducer: {
folders: foldersReducer,
},
preloadedState,
});

const renderWithProviders = (component: React.ReactNode) => {
const store = mockStore(initialState);
const store = createTestStore(initialState);

return render(
<Provider store={store}>
Expand All @@ -58,9 +67,7 @@ describe('HomeScreen', () => {

it('renders the container with correct insets', () => {
const { getByTestId } = renderWithProviders(<HomeScreen />);

const container = getByTestId('container');

expect(container.props.style.paddingTop).toBe(20);
expect(container.props.style.paddingLeft).toBe(0);
expect(container.props.style.paddingRight).toBe(-2);
Expand All @@ -70,4 +77,13 @@ describe('HomeScreen', () => {
const { getByTestId } = renderWithProviders(<HomeScreen />);
expect(getByTestId('folder-list')).toBeTruthy();
});

it('renders the notes results list when there is a search query', () => {
const { getByTestId } = renderWithProviders(<HomeScreen />);

const searchInput = getByTestId('search-input');
fireEvent.changeText(searchInput, 'Sample Note');

expect(getByTestId('notes-results')).toBeTruthy();
});
});
120 changes: 66 additions & 54 deletions __tests__/NoteDetailsScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import {
useFetchNoteDetailsQuery,
useUpdateNoteMutation,
} from '@store/queries/notes';
import NoteDetailsScreen from '@screens/NoteDetailsScreen';
import {
NavigationContainer,
RouteProp,
useNavigation,
} from '@react-navigation/native';

import foldersReducer from '@store/foldersSlice';
import {
useFetchNoteDetailsQuery,
useUpdateNoteMutation,
} from '@store/queries/notes';
import NoteDetailsScreen from '@screens/NoteDetailsScreen';
import { RootStackParamList } from '@navigation/types';
import { formatTimestampToDateTime } from '@root/src/utils';

jest.mock('@store/queries/notes', () => ({
useFetchNoteDetailsQuery: jest.fn(),
Expand All @@ -26,12 +27,29 @@ jest.mock('react-native-safe-area-context', () => ({
useSafeAreaInsets: jest.fn(),
}));

jest.mock('@react-navigation/native', () => ({
...jest.requireActual('@react-navigation/native'),
useNavigation: jest.fn(),
jest.mock('@store/queries/notes', () => ({
useFetchNoteDetailsQuery: jest.fn(),
useUpdateNoteMutation: jest.fn(() => [jest.fn()]),
useCreateNoteMutation: jest.fn(() => [jest.fn().mockResolvedValue({})]),
}));

const mockStore = configureStore([]);
jest.mock('@react-navigation/native', () => {
const actual = jest.requireActual('@react-navigation/native');
return {
...actual,
useNavigation: jest.fn(),
};
});

const createTestStore = (preloadedState = {}) => {
return configureStore({
reducer: {
folders: foldersReducer,
},
preloadedState,
});
};

const mockNavigate = jest.fn();
const mockNavigation = { navigate: mockNavigate };
const mockRoute: RouteProp<RootStackParamList, 'NoteDetails'> = {
Expand All @@ -40,7 +58,7 @@ const mockRoute: RouteProp<RootStackParamList, 'NoteDetails'> = {
params: { noteId: 1, isNew: false },
};

describe('NoteDetailScreen', () => {
describe('NoteDetailsScreen', () => {
const mockedDate = new Date('2024-10-13T11:34:00').getTime();

beforeEach(() => {
Expand All @@ -66,17 +84,16 @@ describe('NoteDetailScreen', () => {
isLoading: true,
});

const store = mockStore({
folders: {
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
},
const store = createTestStore({
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
});

const { getByText } = render(
<Provider store={store}>
<NavigationContainer>
Expand All @@ -96,23 +113,22 @@ describe('NoteDetailScreen', () => {
data: {
id: '1',
title: 'Test Note',
modifiedDate: Date.now(),
modifiedDate: mockedDate,
content: 'This is the content of the note',
},
isLoading: false,
});

const store = mockStore({
folders: {
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
},
const store = createTestStore({
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
});

const { getByDisplayValue } = render(
<Provider store={store}>
<NoteDetailsScreen
Expand Down Expand Up @@ -140,16 +156,14 @@ describe('NoteDetailScreen', () => {

(useUpdateNoteMutation as jest.Mock).mockReturnValue([mockUpdateNote]);

const store = mockStore({
folders: {
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
},
const store = createTestStore({
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
});

const { getByDisplayValue, getByTestId } = render(
Expand Down Expand Up @@ -188,16 +202,14 @@ describe('NoteDetailScreen', () => {
isLoading: false,
});

const store = mockStore({
folders: {
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
},
const store = createTestStore({
folders: [
{
id: 1,
folderName: 'Test Folder',
notes: [],
},
],
});

const { getByText } = render(
Expand All @@ -209,6 +221,6 @@ describe('NoteDetailScreen', () => {
</Provider>,
);

expect(getByText(formatTimestampToDateTime(mockedDate))).toBeTruthy();
expect(getByText('Oct 13, 2024 at 11:34 AM')).toBeTruthy();
});
});
3 changes: 3 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<application
android:name=".MainApplication"
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 23
minSdkVersion = 24
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "26.1.10909125"
Expand Down
43 changes: 37 additions & 6 deletions ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,44 @@
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
def node_require(script)
# Resolve script with node to allow for hoisting
script_path = Pod::Executable.execute_command(
'node',
['-p', "require.resolve('#{script}', {paths: [process.argv[1]]})", __dir__]
).strip
require script_path
end

# Use it to require both react-native's and this package's scripts:
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')

platform :ios, min_ios_version_supported
platform :ios, '13.4'
prepare_react_native_project!

# Uncomment permissions needed
setup_permissions([
# 'AppTrackingTransparency',
# 'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
# 'Camera',
# 'Contacts',
# 'FaceID',
# 'LocationAccuracy',
# 'LocationAlways',
# 'LocationWhenInUse',
# 'MediaLibrary',
'Microphone',
# 'Motion',
# 'Notifications',
# 'PhotoLibrary',
# 'PhotoLibraryAddOnly',
# 'Reminders',
# 'Siri',
# 'SpeechRecognition',
# 'StoreKit',
])

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
Expand Down
14 changes: 13 additions & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1520,6 +1520,8 @@ PODS:
- React-logger (= 0.75.3)
- React-perflogger (= 0.75.3)
- React-utils (= 0.75.3)
- RNAudioRecorderPlayer (3.6.12):
- React-Core
- RNCAsyncStorage (2.0.0):
- React-Core
- RNGestureHandler (2.19.0):
Expand All @@ -1543,6 +1545,8 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- RNPermissions (5.2.1):
- React-Core
- RNScreens (3.34.0):
- DoubleConversion
- glog
Expand Down Expand Up @@ -1657,8 +1661,10 @@ DEPENDENCIES:
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- RNAudioRecorderPlayer (from `../node_modules/react-native-audio-recorder-player`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNPermissions (from `../node_modules/react-native-permissions`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
Expand Down Expand Up @@ -1796,10 +1802,14 @@ EXTERNAL SOURCES:
:path: build/generated/ios
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNAudioRecorderPlayer:
:path: "../node_modules/react-native-audio-recorder-player"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNPermissions:
:path: "../node_modules/react-native-permissions"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSVG:
Expand Down Expand Up @@ -1873,14 +1883,16 @@ SPEC CHECKSUMS:
React-utils: f2afa6acd905ca2ce7bb8ffb4a22f7f8a12534e8
ReactCodegen: ff95a93d5ab5d9b2551571886271478eaa168565
ReactCommon: 289214026502e6a93484f4a46bcc0efa4f3f2864
RNAudioRecorderPlayer: 224c7de87722938aedce04000d09baa633148f5b
RNCAsyncStorage: d35c79ffba52c1013013e16b1fc295aec2feabb6
RNGestureHandler: 3b6fa2bfa341c413d3d08444b838515b58e48ee7
RNPermissions: e13041735d8b93f87800e9bf3f4cf99d3d3c9877
RNScreens: 19719a9c326e925498ac3b2d35c4e50fe87afc06
RNSVG: 4590aa95758149fa27c5c83e54a6a466349a1688
RNVectorIcons: 6382277afab3c54658e9d555ee0faa7a37827136
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63

PODFILE CHECKSUM: b77dd78f751916a06d4c622eb78ebda8b7482156
PODFILE CHECKSUM: b0c8d970337e3216aee490e2aab9990ca873d4ba

COCOAPODS: 1.15.2
Loading

0 comments on commit 64b6b47

Please sign in to comment.