diff --git a/__tests__/AuthScreen-test.tsx b/__tests__/AuthScreen-test.tsx index 41c73fed..b8e0e46f 100644 --- a/__tests__/AuthScreen-test.tsx +++ b/__tests__/AuthScreen-test.tsx @@ -3,6 +3,15 @@ import { screen, render, fireEvent } from '@testing-library/react-native'; import AuthScreen from '../src/screens/AuthScreen/AuthScreen'; import Strings from '../src/i18n/en'; import { Toast } from 'react-native-toast-message/lib/src/Toast'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; + +jest.mock('react-redux', () => { + return { + ...jest.requireActual('react-redux'), + useSelector: jest.fn(), + }; +}); it.skip('AuthScreen is rendered', () => { render(); @@ -21,3 +30,35 @@ it.skip('Clicking on Sign in with Github shows a toast', async () => { fireEvent.press(githubSignInBtn); screen.getByText(/Sign in with GitHub coming soon/i); }); + +describe('AuthScreen', () => { + const initialState = { + localFeatureFlag: { + isProdEnvironment: true, + }, + }; + + const mockReducer = (state = initialState) => state; + const mockStore = configureStore({ + reducer: { + localFeatureFlag: mockReducer, + }, + }); + + require('react-redux').useSelector.mockReturnValue({ + initialState, + }); + + test('Activate Camera when Camera button is pressed', () => { + const { getByText, queryByTestId } = render( + + + , + ); + + const cameraButton = getByText('Web SignIn'); + fireEvent.press(cameraButton); + + expect(queryByTestId('camera')).toBeTruthy(); + }); +}); diff --git a/package.json b/package.json index 1100385e..d758aec5 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@react-navigation/native": "^6.0.8", "@react-navigation/native-stack": "^6.9.12", "@react-navigation/stack": "^6.2.0", + "@reduxjs/toolkit": "^2.3.0", "axios": "^0.26.0", "eslint-plugin-prettier": "^4.1.0", "moment": "^2.29.4", diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx index e9cdf092..0c17c777 100644 --- a/src/context/AuthContext.tsx +++ b/src/context/AuthContext.tsx @@ -4,19 +4,25 @@ import { loggedInUserType } from './type'; type authContextProviderType = { loggedInUserData: loggedInUserType | null; + goalsData: loggedInUserType | null; isLoading: boolean; setIsLoading: () => void; setLoggedInUserData: (userData: loggedInUserType | null) => void; + setGoalsData: (userData: loggedInUserType | null) => void; }; export const AuthContext = React.createContext({ isLoading: false, loggedInUserData: null, + goalsData: null, setIsLoading: () => { return; }, setLoggedInUserData: () => { return; }, + setGoalsData: () => { + return; + }, }); type authProviderProps = { diff --git a/src/context/type.ts b/src/context/type.ts index 222f8e86..bbd90242 100644 --- a/src/context/type.ts +++ b/src/context/type.ts @@ -1,8 +1,13 @@ -export type loggedInUserType = { +export interface loggedInUserType { id: string; name: string; profileUrl: string; status: string; + twitter_id?: string; + linkedin_id?: string; + github_id: string; + username: string; + token: string; }; export interface User { diff --git a/src/react-native-walkthrough-tooltip.d.ts b/src/react-native-walkthrough-tooltip.d.ts new file mode 100644 index 00000000..3812f8eb --- /dev/null +++ b/src/react-native-walkthrough-tooltip.d.ts @@ -0,0 +1,20 @@ +declare module 'react-native-walkthrough-tooltip' { + import React from 'react'; + import { GestureResponderEvent, ViewStyle } from 'react-native'; + + export interface TooltipProps { + isVisible?: boolean; + content?: React.ReactElement; + placement?: 'top' | 'bottom' | 'left' | 'right' | 'center'; + onClose?: (event: GestureResponderEvent) => void; + closeOnContentInteraction?: boolean; + closeOnBackgroundInteraction?: boolean; + backgroundStyle?: ViewStyle; + contentStyle?: ViewStyle; + tooltipStyle?: ViewStyle; + arrowStyle?: ViewStyle; + children?: React.ReactNode; + } + + export default function Tooltip(props: TooltipProps): JSX.Element; +} diff --git a/src/screens/AuthScreen/AuthScreen.tsx b/src/screens/AuthScreen/AuthScreen.tsx index 2528fd75..a617ee82 100644 --- a/src/screens/AuthScreen/AuthScreen.tsx +++ b/src/screens/AuthScreen/AuthScreen.tsx @@ -19,20 +19,25 @@ import { AuthContext } from '../../context/AuthContext'; import { getUserData, goalsAuth, requestCameraPermission } from './Util'; import { storeData } from '../../utils/dataStore'; import AuthApis from '../../constants/apiConstant/AuthApi'; -// import { AuthApisStaging } from '../../constants/apiConstant/AuthApi'; -import { CameraScreen } from 'react-native-camera-kit'; +import { Camera } from 'react-native-camera-kit'; import CustomModal from '../../components/Modal/CustomModal'; import LoadingScreen from '../../components/LoadingScreen'; import Tooltip from 'react-native-walkthrough-tooltip'; import { useSelector } from 'react-redux'; -// import Github from '../../constants/images/Image'; import Images from '../../constants/images/Image'; import GithubSvg from '../../../assets/svgs/github_logo.js'; import WebSvg from '../../../assets/svgs/web'; +type RootState = { + localFeatureFlag: { + isProdEnvironment: boolean; + }; +}; const baseUrl = AuthApis.GITHUB_AUTH_API; const AuthScreen = () => { - const { isProdEnvironment } = useSelector((store) => store.localFeatureFlag); + const { isProdEnvironment } = useSelector( + (store: RootState) => store.localFeatureFlag, + ); const { setLoggedInUserData, setGoalsData } = useContext(AuthContext); const [loading, setLoading] = useState(false); const [cameraActive, setCameraActive] = useState(false); @@ -45,7 +50,7 @@ const AuthScreen = () => { redirectURL: 'https://realdevsquad.com/', }; - function buildUrl(url, params) { + function buildUrl(url: string, params: { [key: string]: string }) { const queryString = Object.keys(params) .map((key) => `${key}=${params[key]}`) .join('&'); @@ -59,7 +64,7 @@ const AuthScreen = () => { Platform.OS !== 'android' || requestCameraPermission(); Linking.getInitialURL(); - const handleDeepLink = async (event) => { + const handleDeepLink = async (event: { url: string }) => { const token = event.url.split('token=')[1]; token && updateUserData(token); // store token in redux }; @@ -99,7 +104,6 @@ const AuthScreen = () => { }; const handleQRCodeScanned = ({ nativeEvent }: any) => { - console.log(nativeEvent); setScannedUserID(nativeEvent.codeStringValue); setToolTip(true); }; @@ -143,14 +147,11 @@ const AuthScreen = () => { const qrCodeLogin = async () => { const deviceId = await DeviceInfo.getUniqueId(); - // const url = `${AuthApis.QR_AUTH_API}?device_id=${deviceId}` - const url = isProdEnvironment ? `${AuthApis.QR_AUTH_API}?device_id=${deviceId}` : `${AuthApis.QR_AUTH_API_STAGING}?device_id=${deviceId}`; try { const userInfo = await fetch(url); - console.log(userInfo, 'user info in rds app auth'); const userInfoJson = await userInfo.json(); if (userInfoJson.data.token) { updateUserData(userInfoJson.data.token); @@ -217,10 +218,10 @@ const AuthScreen = () => { }); } } catch (err) { - console.log(err, 'Error QR login'); Toast.show({ type: 'error', - text1: err, + text1: + (err as Error).message || 'Something went wrong, please try again', position: 'bottom', bottomOffset: 80, }); @@ -274,23 +275,9 @@ const AuthScreen = () => { - - {/* { - isProdEnvironment - ? dispatch({ type: 'DEV' }) - : dispatch({ type: 'PROD' }); - }} - > - - - {isProdEnvironment ? 'Switch to DEV' : 'Switch to Prod'} - - - */} {cameraActive && ( - { frameColor={'white'} laserColor={'white'} hideControls + testID="camera" /> )} diff --git a/tsconfig.json b/tsconfig.json index 38cc138a..0f11f3cd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -41,7 +41,10 @@ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ + "typeRoots": [ + "./node_modules/@types", + "./types" + ], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, diff --git a/yarn.lock b/yarn.lock index ab52b787..a3dc19bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2320,6 +2320,16 @@ resolved "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz" integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== +"@reduxjs/toolkit@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.3.0.tgz#d00134634d6c1678e8563ac50026e429e3b64420" + integrity sha512-WC7Yd6cNGfHx8zf+iu+Q1UPTfEcXhQ+ATi7CV1hlrSAaQBdlPzg7Ww/wJHNQem7qG9rxmWoFCDCPubSvFObGzA== + dependencies: + immer "^10.0.3" + redux "^5.0.1" + redux-thunk "^3.1.0" + reselect "^5.1.0" + "@rnx-kit/align-deps@^2.2.2": version "2.2.4" resolved "https://registry.npmjs.org/@rnx-kit/align-deps/-/align-deps-2.2.4.tgz" @@ -5080,6 +5090,11 @@ image-size@^1.0.2: dependencies: queue "6.0.2" +immer@^10.0.3: + version "10.1.1" + resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.1.tgz#206f344ea372d8ea176891545ee53ccc062db7bc" + integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" @@ -7531,6 +7546,11 @@ redux-saga@^1.2.3: dependencies: "@redux-saga/core" "^1.2.3" +redux-thunk@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3" + integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== + redux@^4.0.4, redux@^4.2.1: version "4.2.1" resolved "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz" @@ -7538,6 +7558,11 @@ redux@^4.0.4, redux@^4.2.1: dependencies: "@babel/runtime" "^7.9.2" +redux@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" + integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== + reflect.getprototypeof@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz" @@ -7624,6 +7649,11 @@ require-main-filename@^2.0.0: resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +reselect@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e" + integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz"