Skip to content

Commit

Permalink
Merge pull request #130 from internxt/feature/use-cases-implementation
Browse files Browse the repository at this point in the history
[_]: Add useCases utilities to replace redux
  • Loading branch information
PixoDev authored Sep 19, 2022
2 parents c22fba3 + 2d22291 commit e277fd4
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 11 deletions.
3 changes: 3 additions & 0 deletions __mocks__/@rudderstack/rudder-sdk-react-native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
jest.mock('@rudderstack/rudder-sdk-react-native', () => {
return {};
});
3 changes: 3 additions & 0 deletions __mocks__/react-native-device-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import mockRNDeviceInfo from 'react-native-device-info/jest/react-native-device-info-mock';

jest.mock('react-native-device-info', () => mockRNDeviceInfo);
5 changes: 5 additions & 0 deletions __mocks__/react-native-permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import mock from 'react-native-permissions/mock';

jest.mock('react-native-permissions', () => {
return mock;
});
4 changes: 3 additions & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ const untranspiledModulePatterns = [
'react-native-svg',
'rn-fetch-blob',
'@internxt/rn-crypto',
'@rudderstack',
];

const config: Config.InitialOptions = {
preset: 'jest-expo',
verbose: true,
testRegex: '\\.spec\\.ts$',
testRegex: ['\\.spec\\.ts$', '\\.spec\\.tsx$'],
setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
transformIgnorePatterns: [`node_modules/(?!${untranspiledModulePatterns.join('|')})`],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
};
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@reduxjs/toolkit": "^1.6.2",
"@rudderstack/rudder-sdk-react-native": "^1.5.1",
"@sentry/react-native": "^3.4.2",
"@testing-library/react-hooks": "^8.0.1",
"@tradle/react-native-http": "^2.0.1",
"@types/luxon": "^3.0.1",
"@types/unorm": "^1.3.28",
Expand Down Expand Up @@ -155,6 +156,8 @@
"@babel/preset-env": "^7.1.6",
"@internxt/eslint-config-internxt": "^1.0.8",
"@internxt/prettier-config": "^1.0.2",
"@testing-library/jest-native": "^4.0.12",
"@testing-library/react-native": "^11.1.0",
"@types/async": "^3.2.6",
"@types/jest": "^28.1.1",
"@types/lodash": "^4.14.165",
Expand Down
2 changes: 1 addition & 1 deletion shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer;

// global.location = global.location || { port: 80 }
const isDev = typeof __DEV__ === 'boolean' && __DEV__;
process.env['NODE_ENV'] = isDev ? 'development' : 'production';
process.env['NODE_ENV'] = process.env['NODE_ENV'] || isDev ? 'development' : 'production';
if (typeof localStorage !== 'undefined') {
localStorage.debug = isDev ? '*' : '';
}
Expand Down
1 change: 1 addition & 0 deletions src/hooks/common/useUseCase/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useUseCase';
15 changes: 15 additions & 0 deletions src/hooks/common/useUseCase/useUseCase.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { renderHook, waitFor } from '@testing-library/react-native';
import { useUseCase } from './useUseCase';

describe('useUseCase hook', () => {
test('Should resolve with data once the use case function is completed without errors', async () => {
const mockedUseCase = jest.fn(async () => {
return true;
});
const { result } = renderHook(() => useUseCase<boolean>(mockedUseCase));

await waitFor(() => expect(mockedUseCase).toHaveBeenCalledTimes(1));
const [data] = result.current;
expect(data).toBe(true);
});
});
64 changes: 64 additions & 0 deletions src/hooks/common/useUseCase/useUseCase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { NotificationType } from '../../../types';
import { useEffect, useState } from 'react';
import notificationsService from 'src/services/NotificationsService';
import { DisplayableError } from 'src/services/common/errors/base';

export type UseCaseResult<T, E = unknown> = {
data: T | null;
error: E | null;
loading: boolean;
};

interface UseUseCaseConfig {
lazy: boolean;
}

export function useUseCase<T, E = unknown>(
useCase: () => Promise<T>,
config?: UseUseCaseConfig,
): [T | null, boolean, E | null, () => Promise<void>] {
const [state, setState] = useState<UseCaseResult<T, E>>({ data: null, error: null, loading: true });

useEffect(() => {
if (!config?.lazy) {
(async () => {
await executeUseCase();
})();
}
}, []);

const processError = (error: unknown) => {
if (error instanceof DisplayableError) {
notificationsService.show({
text1: error.userFriendlyMessage,
type: NotificationType.Error,
});
}
};

const resetState = () => {
setState({ ...state, error: null });
};

const executeUseCase = async () => {
if (state.data || state.error) {
resetState();
}
try {
const result = await useCase();
setState({
...state,
data: result,
loading: false,
});
} catch (error) {
processError(error);
setState({
...state,
error: error as E,
loading: false,
});
}
};
return [state.data, state.loading, state.error, executeUseCase];
}
4 changes: 2 additions & 2 deletions src/services/ErrorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import AppError from '../types';
import sentryService from './SentryService';
import { Severity } from '@sentry/react-native';

interface GlobalErrorContext {
export interface GlobalErrorContext {
email: string;
userId: string;
}

interface ErrorContext extends GlobalErrorContext {
export interface ErrorContext extends GlobalErrorContext {
level: Severity;
// Tagname and value of the tag such environment: dev or things like that
tags: { [tagName: string]: string };
Expand Down
31 changes: 31 additions & 0 deletions src/services/common/errors/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import errorService, { ErrorContext } from 'src/services/ErrorService';

export interface ReportableErrorOptions {
error: unknown;
context?: ErrorContext;
}
export class ReportableError extends Error {
private options?: ReportableErrorOptions;
constructor(options?: ReportableErrorOptions) {
super(options ? (options.error as Error).message : 'NO_MESSAGE');
this.options = options;
this.init();
}

private init() {
if (this.options) {
errorService.reportError(this.options.error as Error, this.options.context || {});
}
}
}

export class DisplayableError extends ReportableError {
public userFriendlyMessage: string;
constructor({ userFriendlyMessage, errorToReport }: { userFriendlyMessage: string; errorToReport?: Error }) {
super({
error: errorToReport,
});

this.userFriendlyMessage = userFriendlyMessage;
}
}
1 change: 1 addition & 0 deletions src/services/common/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './base';
93 changes: 86 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,13 @@
dependencies:
regenerator-runtime "^0.13.4"

"@babel/runtime@^7.12.5", "@babel/runtime@^7.7.7":
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"

"@babel/runtime@^7.14.0":
version "7.17.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
Expand All @@ -1837,13 +1844,6 @@
dependencies:
regenerator-runtime "^0.13.4"

"@babel/runtime@^7.7.7":
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"

"@babel/template@^7.0.0", "@babel/template@^7.16.0", "@babel/template@^7.3.3", "@babel/template@^7.8.6":
version "7.16.0"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz"
Expand Down Expand Up @@ -2545,6 +2545,13 @@
dependencies:
"@sinclair/typebox" "^0.24.1"

"@jest/schemas@^29.0.0":
version "29.0.0"
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a"
integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==
dependencies:
"@sinclair/typebox" "^0.24.1"

"@jest/source-map@^27.5.1":
version "27.5.1"
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
Expand Down Expand Up @@ -3312,6 +3319,32 @@
merge-deep "^3.0.2"
svgo "^1.2.2"

"@testing-library/jest-native@^4.0.12":
version "4.0.12"
resolved "https://registry.yarnpkg.com/@testing-library/jest-native/-/jest-native-4.0.12.tgz#9669a2456bf8f7ac907fca879d157fd0f29e6cb8"
integrity sha512-SjH3mLpYPLt14F2av98172nbGHrOlThKWxbSQrc9ZOsgl8mlMvWkQnFEheQooiLpZwrkoi+P48+dDMU7VaRR3A==
dependencies:
chalk "^4.1.2"
jest-diff "^29.0.1"
jest-matcher-utils "^29.0.1"
pretty-format "^29.0.1"
redent "^3.0.0"

"@testing-library/react-hooks@^8.0.1":
version "8.0.1"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12"
integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==
dependencies:
"@babel/runtime" "^7.12.5"
react-error-boundary "^3.1.0"

"@testing-library/react-native@^11.1.0":
version "11.1.0"
resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-11.1.0.tgz#50aaa9c026e4beb02c07607fb0db5f4478cdd625"
integrity sha512-syVlE9fM0tZF4MmEE09R4BoGRH6lMNAbozuluGjS2HT8rXt3unRXb8GwpLmT+xCTq9+1lnQiXobTJm8/w12Zbg==
dependencies:
pretty-format "^29.0.3"

"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
Expand Down Expand Up @@ -5805,6 +5838,11 @@ diff-sequences@^28.1.1:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6"
integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==

diff-sequences@^29.0.0:
version "29.0.0"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.0.0.tgz#bae49972ef3933556bcb0800b72e8579d19d9e4f"
integrity sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA==

diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
Expand Down Expand Up @@ -8113,6 +8151,16 @@ jest-diff@^28.1.3:
jest-get-type "^28.0.2"
pretty-format "^28.1.3"

jest-diff@^29.0.1, jest-diff@^29.0.3:
version "29.0.3"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.0.3.tgz#41cc02409ad1458ae1bf7684129a3da2856341ac"
integrity sha512-+X/AIF5G/vX9fWK+Db9bi9BQas7M9oBME7egU7psbn4jlszLFCu0dW63UgeE6cs/GANq4fLaT+8sGHQQ0eCUfg==
dependencies:
chalk "^4.0.0"
diff-sequences "^29.0.0"
jest-get-type "^29.0.0"
pretty-format "^29.0.3"

jest-docblock@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
Expand Down Expand Up @@ -8186,6 +8234,11 @@ jest-get-type@^28.0.2:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203"
integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==

jest-get-type@^29.0.0:
version "29.0.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.0.0.tgz#843f6c50a1b778f7325df1129a0fd7aa713aef80"
integrity sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw==

jest-haste-map@^26.5.2, jest-haste-map@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa"
Expand Down Expand Up @@ -8278,6 +8331,16 @@ jest-matcher-utils@^28.0.0:
jest-get-type "^28.0.2"
pretty-format "^28.1.3"

jest-matcher-utils@^29.0.1:
version "29.0.3"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.0.3.tgz#b8305fd3f9e27cdbc210b21fc7dbba92d4e54560"
integrity sha512-RsR1+cZ6p1hDV4GSCQTg+9qjeotQCgkaleIKLK7dm+U4V/H2bWedU3RAtLm8+mANzZ7eDV33dMar4pejd7047w==
dependencies:
chalk "^4.0.0"
jest-diff "^29.0.3"
jest-get-type "^29.0.0"
pretty-format "^29.0.3"

jest-message-util@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
Expand Down Expand Up @@ -10521,6 +10584,15 @@ pretty-format@^28.0.0, pretty-format@^28.1.3:
ansi-styles "^5.0.0"
react-is "^18.0.0"

pretty-format@^29.0.1, pretty-format@^29.0.3:
version "29.0.3"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.0.3.tgz#23d5f8cabc9cbf209a77d49409d093d61166a811"
integrity sha512-cHudsvQr1K5vNVLbvYF/nv3Qy/F/BcEKxGuIeMiVMRHxPOO1RxXooP8g/ZrwAp7Dx+KdMZoOc7NxLHhMrP2f9Q==
dependencies:
"@jest/schemas" "^29.0.0"
ansi-styles "^5.0.0"
react-is "^18.0.0"

prettysize@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/prettysize/-/prettysize-2.0.0.tgz"
Expand Down Expand Up @@ -10798,6 +10870,13 @@ [email protected]:
object-assign "^4.1.1"
scheduler "^0.20.1"

react-error-boundary@^3.1.0:
version "3.1.4"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
dependencies:
"@babel/runtime" "^7.12.5"

react-freeze@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.0.tgz#b21c65fe1783743007c8c9a2952b1c8879a77354"
Expand Down

0 comments on commit e277fd4

Please sign in to comment.