Skip to content
Commits on Source (46)
module.exports = {
"parser": "babel-eslint",
"plugins": [
"react",
"react-native",
"flowtype"
],
"extends": ["plugin:react-native/all", "plugin:react/recommended"],
"env": {
"react-native/react-native": true
},
"rules": {
"no-unused-vars": [1],
"react/jsx-uses-vars": [2],
"flowtype/boolean-style": [
2,
"boolean"
],
"flowtype/define-flow-type": 1,
"flowtype/delimiter-dangle": [
2,
"never"
],
"flowtype/generic-spacing": [
2,
"never"
],
"flowtype/no-mixed": 0,
"flowtype/no-primitive-constructor-types": 2,
"flowtype/no-types-missing-file-annotation": 2,
"flowtype/no-weak-types": 0,
"flowtype/object-type-delimiter": [
2,
"comma"
],
"flowtype/require-parameter-type": 2,
"flowtype/require-readonly-react-props": 0,
"flowtype/require-return-type": [
2,
"always",
{
"annotateUndefined": "never"
}
],
"flowtype/require-valid-file-annotation": 2,
"flowtype/semi": [
2,
"always"
],
"flowtype/space-after-type-colon": [
2,
"always"
],
"flowtype/space-before-generic-bracket": [
2,
"never"
],
"flowtype/space-before-type-colon": [
2,
"never"
],
"flowtype/type-id-match": [
2,
"^([A-Z][a-z0-9]+)+Type$"
],
"flowtype/union-intersection-spacing": [
2,
"always"
],
"flowtype/use-flow-type": 1,
"flowtype/valid-syntax": 1
},
"settings": {
"flowtype": {
"onlyFilesWithFlowAnnotation": true
}
}
}
\ No newline at end of file
root: true,
extends: '@react-native-community',
};
\ No newline at end of file
......@@ -5,67 +5,71 @@
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
; Ignore polyfills
node_modules/react-native/Libraries/polyfills/.*
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/warning')
node_modules/warning/.*
; Ignore polyfills
.*/Libraries/polyfills/.*
; Flow doesn't support platforms
.*/Libraries/Utilities/LoadingView.js
; Ignore metro
.*/node_modules/metro/.*
[untyped]
.*/node_modules/@react-native-community/cli/.*/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow/
node_modules/react-native/flow-github/
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
esproposal.decorators=ignore
module.system=haste
module.system.haste.use_name_reducers=true
# get basename
module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1'
# strip .js or .js.flow suffix
module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1'
# strip .ios suffix
module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1'
module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1'
module.system.haste.paths.blacklist=.*/__tests__/.*
module.system.haste.paths.blacklist=.*/__mocks__/.*
module.system.haste.paths.blacklist=<PROJECT_ROOT>/node_modules/react-native/Libraries/Animated/src/polyfills/.*
module.system.haste.paths.whitelist=<PROJECT_ROOT>/node_modules/react-native/Libraries/.*
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
module.file_ext=.js
module.file_ext=.jsx
module.file_ext=.json
module.file_ext=.native.js
module.file_ext=.ios.js
munge_underscores=true
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/react-native/react-native-implementation'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
sketchy-number=warn
untyped-type-import=warn
nonstrict-import=warn
deprecated-type=warn
unsafe-getters-setters=warn
inexact-spread=warn
unnecessary-invariant=warn
signature-verification-failure=warn
deprecated-utility=error
[strict]
deprecated-type
nonstrict-import
sketchy-null
unclear-type
unsafe-getters-setters
untyped-import
untyped-type-import
[version]
^0.92.0
^0.107.0
......@@ -42,6 +42,7 @@ yarn-error.log
buck-out/
\.buckd/
*.keystore
!debug.keystore
# fastlane
#
......@@ -57,6 +58,9 @@ buck-out/
# Bundle artifact
*.jsbundle
# CocoaPods
/ios/Pods/
# Jest cache
.jest/
......
......@@ -6,7 +6,7 @@ stages:
- deploy
test:jest:
image: node:10.10.0
image: node:10.16.3
stage: test
cache:
key: ${CI_COMMIT_REF_SLUG}
......@@ -22,7 +22,7 @@ build:android:
stage: build
before_script:
- sudo sysctl fs.inotify.max_user_watches=524288
- sudo sysctl -p
- sudo sysctl -p
script:
- yarn install
- cd android
......@@ -37,7 +37,7 @@ build:android:
when: on_success
e2e:browserstacks:
image: node:10.10.0
image: node:10.16.3
stage: e2e
cache:
key: ${CI_COMMIT_REF_SLUG}
......
module.exports = {
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
};
//import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
import './global';
import './shim'
//import crypto from "crypto"; // DO NOT REMOVE!
import React, {
Component
} from 'react';
import {
createStackNavigator,
NavigationActions
} from 'react-navigation';
import {
BackHandler,
Platform,
AppState,
Linking,
Text,
Alert,
View,
} from 'react-native';
import NavigationStack from './src/navigation/NavigationStack';
import NavigationService from './src/navigation/NavigationService';
const Stack = createStackNavigator({});
/**
* App
*/
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
appState: AppState.currentState
};
}
/**
* Handle app state changes
*/
handleAppStateChange = (nextState) => {
// if the app turns active we check for shared
if (this.state.appState.match(/inactive|background/) && nextState === 'active') {
receiveShare.handle();
}
this.setState({appState: nextState})
}
/**
* On component will mount
*/
componentWillMount() {
if (!Text.defaultProps) Text.defaultProps = {};
Text.defaultProps.style = {
fontFamily: 'Roboto',
color: '#444',
};
}
/**
* Render
*/
render() {
const app = (
<View></View>
);
return [ app ];
}
}
......@@ -5,18 +5,14 @@
* @format
* @flow
*/
import './global';
import './shim'
import crypto from "crypto"; // DO NOT REMOVE!
import React, {
Component
Component,
} from 'react';
import {
Observer,
Provider,
} from 'mobx-react/native' // import from mobx-react/native instead of mobx-react fix test
} from 'mobx-react/native'; // import from mobx-react/native instead of mobx-react fix test
import NavigationService from './src/navigation/NavigationService';
......@@ -30,8 +26,7 @@ import {
Clipboard,
} from 'react-native';
import FlashMessage from "react-native-flash-message";
import CookieManager from 'react-native-cookies';
import FlashMessage from 'react-native-flash-message';
import KeychainModalScreen from './src/keychain/KeychainModalScreen';
import BlockchainTransactionModalScreen from './src/blockchain/transaction-modal/BlockchainTransactionModalScreen';
......@@ -47,9 +42,9 @@ import sessionService from './src/common/services/session.service';
import deeplinkService from './src/common/services/deeplinks-router.service';
import badgeService from './src/common/services/badge.service';
import authService from './src/auth/AuthService';
import NotificationsService from "./src/notifications/NotificationsService";
import NotificationsService from './src/notifications/NotificationsService';
import getMaches from './src/common/helpers/getMatches';
import {CODE_PUSH_TOKEN, GOOGLE_PLAY_STORE} from './src/config/Config';
import { GOOGLE_PLAY_STORE } from './src/config/Config';
import updateService from './src/common/services/update.service';
import ErrorBoundary from './src/common/components/ErrorBoundary';
import { CommonStyle as CS } from './src/styles/Common';
......@@ -63,6 +58,7 @@ import connectivityService from './src/common/services/connectivity.service';
import sqliteStorageProviderService from './src/common/services/sqlite-storage-provider.service';
import commentStorageService from './src/comments/CommentStorageService';
import * as Sentry from '@sentry/react-native';
import apiService from './src/common/services/api.service';
import boostedContentService from './src/common/services/boosted-content.service';
let deepLinkUrl = '';
......@@ -73,7 +69,7 @@ pushService.init();
// fire sqlite init
sqliteStorageProviderService.get();
CookieManager.clearAll();
apiService.clearCookies();
// On app login (runs if the user login or if it is already logged in)
sessionService.onLogin(async () => {
......@@ -104,7 +100,7 @@ sessionService.onLogin(async () => {
}
logService.info('[App] navigating to initial screen', sessionService.initialScreen);
NavigationService.reset(sessionService.initialScreen);
NavigationService.navigate(sessionService.initialScreen);
// check update
if (Platform.OS !== 'ios' && !GOOGLE_PLAY_STORE) {
......@@ -218,7 +214,7 @@ export default class App extends Component<Props, State> {
if (!token) {
logService.info('[App] there is no active session');
NavigationService.reset('Login');
NavigationService.navigate('Login');
} else {
logService.info('[App] session initialized');
}
......@@ -299,8 +295,7 @@ export default class App extends Component<Props, State> {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
<FlashMessage renderCustomContent={this.renderNotification}
/>
<FlashMessage renderCustomContent={this.renderNotification} />
</ErrorBoundary>
</Provider>
);
......@@ -314,7 +309,7 @@ export default class App extends Component<Props, State> {
);
const tosModal = (
<TosModal user={stores.user}/>
<TosModal user={stores.user} key="tosModal"/>
)
return [ app, keychainModal, blockchainTransactionModal, tosModal];
......
......@@ -31,7 +31,7 @@
## Building
- `yarn install`
- `react-native run-ios` or `react-native run-android`
- `yarn android` or `yarn ios`
## Testing
......
export default {
}
\ No newline at end of file
import { View as mockView } from "react-native";
export default {
Value: jest.fn(),
event: jest.fn(),
add: jest.fn(),
eq: jest.fn(),
set: jest.fn(),
cond: jest.fn(),
interpolate: jest.fn(),
View: mockView,
Extrapolate: { CLAMP: jest.fn() },
Clock: jest.fn(),
greaterThan: jest.fn(),
lessThan: jest.fn(),
startClock: jest.fn(),
stopClock: jest.fn(),
clockRunning: jest.fn(),
not: jest.fn(),
or: jest.fn(),
and: jest.fn(),
spring: jest.fn(),
decay: jest.fn(),
defined: jest.fn(),
call: jest.fn(),
Code: mockView,
block: jest.fn(),
abs: jest.fn(),
greaterOrEq: jest.fn(),
lessOrEq: jest.fn(),
debug: jest.fn(),
Transition: {
Out: "Out"
},
};
export default {
Header: {}
};
export const createStackNavigator = jest.fn();
export const Header = {
HEIGHT:80,
};
export const createMaterialTopTabNavigator = jest.fn().mockImplementation(x => ({router: 'router'}));
export default {
createDrawerNavigator: jest.fn(),
withNavigation: jest.fn(),
StackActions: {
push: jest.fn().mockImplementation(x => ({...x, "type": "Navigation/PUSH"})),
replace: jest.fn().mockImplementation(x => ({...x, "type": "Navigation/REPLACE"})),
},
};
export const createAppContainer = jest.fn().mockReturnValue(function NavigationContainer(props) {return null;});
export const createSwitchNavigator = jest.fn().mockImplementation(x => ({router: 'router'}));
export const withNavigation = jest.fn();
export const Header = {
HEIGHT:80
}
export const StackActions = {
reset: jest.fn()
}
......
import 'react-native';
import React from 'react';
import App from '../App';
import videochat from '../src/common/services/videochat.service';
import sqliteStorageProviderService from '../src/common/services/sqlite-storage-provider.service';
import logService from '../src/common/services/log.service';
import {
......@@ -18,31 +17,16 @@ jest.mock('../src/common/services/sqlite-storage-provider.service')
jest.mock('../src/common/services/log.service', () => {});
jest.mock('../src/common/services/push.service');
jest.mock('react-native-gesture-handler', () => {});
jest.mock('react-navigation-stack', () => { Header: {} });
jest.mock('react-navigation', () => {
return {
createAppContainer: jest.fn().mockReturnValue(function NavigationContainer(props) {return null;}),
createDrawerNavigator: jest.fn(),
createMaterialTopTabNavigator: jest.fn().mockImplementation(x => ({router: 'router'})),
createStackNavigator: jest.fn(),
withNavigation: jest.fn(),
StackActions: {
push: jest.fn().mockImplementation(x => ({...x, "type": "Navigation/PUSH"})),
replace: jest.fn().mockImplementation(x => ({...x, "type": "Navigation/REPLACE"})),
},
NavigationActions: {
navigate: jest.fn().mockImplementation(x => x),
}
}
});
// use the web3 mock to prevent sintax error from node_tar
jest.mock('web3');
//mock notifications
jest.mock('react-native-notifications');
jest.mock('../src/common/services/videochat.service');
jest.mock('react-native-convert-ph-asset');
jest.mock('react-navigation');
jest.mock('react-navigation-tabs');
jest.mock('react-navigation-stack');
//mock i18n
jest.mock('react-native-video');
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Activity component renders correctly 1`] = `
<ContextConsumer>
<Component />
</ContextConsumer>
<View
style={
Object {
"flex": 1,
}
}
>
<View
style={
Object {
"alignItems": "center",
"display": "flex",
"flexDirection": "row",
"padding": 4,
"paddingBottom": 8,
"paddingTop": 8,
}
}
>
<ThumbUpAction
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"perma_url": false,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
"wire_totals": Object {
"tokens": 1000000000000000000,
},
}
}
me={
Object {
"guid": "guidguid",
}
}
/>
<ThumbDownAction
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"perma_url": false,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
"wire_totals": Object {
"tokens": 1000000000000000000,
},
}
}
me={
Object {
"guid": "guidguid",
}
}
/>
<WireAction
owner={
Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
}
}
/>
<CommentsAction
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"perma_url": false,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
"wire_totals": Object {
"tokens": 1000000000000000000,
},
}
}
/>
<RemindAction
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"perma_url": false,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
"wire_totals": Object {
"tokens": 1000000000000000000,
},
}
}
/>
</View>
</View>
`;
......@@ -16,7 +16,9 @@ exports[`Boost action component renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -2,19 +2,15 @@ import api from '../../src/common/services/api.service';
import session from '../../src/common/services/session.service';
import authService from '../../src/auth/AuthService';
import delay from '../../src/common/helpers/delay';
import CookieManager from 'react-native-cookies';
jest.mock('../../src/common/services/api.service');
jest.mock('../../src/common/services/session.service');
jest.mock('../../src/common/helpers/delay', () => jest.fn());
jest.mock('react-native-cookies');
describe('auth service login', () => {
beforeEach(() => {
api.post.mockClear();
session.login.mockClear();
CookieManager.clearAll.mockClear();
CookieManager.clearAll.mockResolvedValue();
delay.mockClear();
delay.mockResolvedValue();
});
......
import 'react-native';
import React from 'react';
import { Text, TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import RegisterScreen from '../../src/auth/RegisterScreen';
import { NavigationActions, StackActions } from 'react-navigation';
jest.mock('../../src/auth/RegisterForm', () => 'RegisterForm');
jest.mock('../../src/common/components/VideoBackground', () => 'VideoBackground');
......@@ -35,15 +33,14 @@ describe('RegisterScreen component', () => {
it('should navigate on RegisterForm events', async () => {
const navigation = {
dispatch: jest.fn()
dispatch: jest.fn(),
navigate: jest.fn(),
};
const wrapper = shallow(
<RegisterScreen navigation={navigation}/>
);
StackActions.reset.mockReturnValue(1)
// find register form
const registerForms = wrapper.find('RegisterForm');
......@@ -53,10 +50,7 @@ describe('RegisterScreen component', () => {
// simulate onBack event
registerForms.at(0).props().onBack();
// should call navigate
expect(StackActions.reset).toBeCalledWith({"actions": [undefined], "index": 0});
// with a navigation action with route to Login
expect(NavigationActions.navigate).toBeCalledWith({"routeName": "Login"});
expect(navigation.navigate).toBeCalledWith('Login');
});
});
......@@ -87,7 +87,9 @@ exports[`ForgotPassword component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -193,7 +195,9 @@ exports[`ForgotPassword component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -42,7 +42,11 @@ exports[`ForgotScreen component should renders correctly 1`] = `
>
<Image
resizeMode="contain"
source={1}
source={
Object {
"testUri": "../../../src/assets/logos/logo-white.png",
}
}
style={
Object {
"alignSelf": "center",
......@@ -151,7 +155,9 @@ exports[`ForgotScreen component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -257,7 +263,9 @@ exports[`ForgotScreen component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......