...
 
Commits (242)
......@@ -43,10 +43,10 @@ jobs:
- store_artifacts:
path: test-results
ios:
macos:
xcode: "10.1"
xcode: "11.1.0"
working_directory: ~/mobile-native
# use a --login shell so our "set Ruby version" command gets picked up for later steps
......@@ -60,7 +60,7 @@ jobs:
command: brew install getsentry/tools/sentry-cli
- run:
name: set Ruby version
command: echo "ruby-2.4" > ~/.ruby-version
command: echo "ruby-2.6" > ~/.ruby-version
- restore_cache:
key: yarn-v1-{{ checksum "yarn.lock" }}-{{ arch }}
......@@ -68,9 +68,19 @@ jobs:
- restore_cache:
key: node-v1-{{ checksum "package.json" }}-{{ arch }}
# remove detox from CI until is fixed
# - run:
# name: Install detox
# command:
# |
# HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew
# HOMEBREW_NO_AUTO_UPDATE=1 brew install --HEAD applesimutils
# npm install -g detox-cli
# npm install -g detox
# not using a workspace here as Node and Yarn versions
# differ between our macOS executor image and the Docker containers above
- run: yarn install
- run: yarn install --frozen-lockfile
- save_cache:
key: yarn-v1-{{ checksum "yarn.lock" }}-{{ arch }}
......@@ -94,6 +104,25 @@ jobs:
paths:
- vendor/bundle
- restore_cache:
key: pods-v1-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
- run:
name: Install CocoaPods
command: pod install --verbose
working_directory: ios
- save_cache:
key: pods-v1-{{ checksum "ios/Podfile.lock" }}-{{ arch }}
paths:
- ios/Pods
# remove detox from CI until is fixed
# Run e2e
# - run: detox build -c ios.sim.release
# - run: detox test -c ios.sim.release --cleanup
### TODO- get tests running with fastlane
#- run:
......@@ -114,7 +143,7 @@ jobs:
#- store_artifacts:
# path: ios/test-results
- run:
- run:
name: Build release .ipa
command: fastlane buildrelease
working_directory: ios
......@@ -124,8 +153,8 @@ jobs:
- /release-*/
- test/circle-ci
- run:
name: Upload to crashalytics
- run:
name: Upload to crashalytics
command: echo "TODO"
working_directory: ios
branches:
......@@ -162,8 +191,8 @@ jobs:
command: |
apk add git
- checkout
- run:
name: Tag sentry release
- run:
name: Tag sentry release
command: |
version=`cat /tmp/workspace/version`
echo Tagging release with ${version}
......
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
......@@ -5,7 +5,6 @@
# Xcode
#
ios/Podfile.lock
build/
*.pbxuser
!default.pbxuser
......@@ -42,6 +41,7 @@ yarn-error.log
buck-out/
\.buckd/
*.keystore
!debug.keystore
# fastlane
#
......@@ -57,6 +57,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
......@@ -36,29 +36,6 @@ build:android:
expire_in: 7 days
when: on_success
e2e:browserstacks:
image: node:10.10.0
stage: e2e
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
script:
- yarn install
- export bsAPP=`curl -u "${bsUSER}:${bsKEY}" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "file=@./Minds-$CI_BUILD_REF_SLUG.apk"| grep -o 'bs\:\/\/.*"' | sed 's/.$//'`
- yarn e2e
tags:
- docker
dependencies:
- build:android
only:
refs:
- /^stable-*/
- /^release-*/
- /^feat-*/
- /^test-*/
allow_failure: true
deploy:s3:
image: minds/ci:latest
stage: deploy
......
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,20 +5,17 @@
* @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';
import RNBootSplash from "react-native-bootsplash";
import {
BackHandler,
......@@ -28,10 +25,10 @@ import {
Text,
Alert,
Clipboard,
StatusBar,
} 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 +44,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,17 +60,20 @@ 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 = '';
const statusBarStyle = Platform.OS === 'ios' ? 'dark-content' : 'default';
// init push service
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 () => {
......@@ -85,8 +85,9 @@ sessionService.onLogin(async () => {
});
logService.info('[App] Getting minds settings and onboarding progress');
// load minds settings and onboarding progresss on login
const results = await Promise.all([mindsService.getSettings(), stores.onboarding.getProgress(), boostedContentService.load()]);
// load minds settings and boosted content
await Promise.all([mindsService.getSettings(), boostedContentService.load()]);
logService.info('[App] updatting features');
// reload fatures on login
......@@ -96,15 +97,15 @@ sessionService.onLogin(async () => {
pushService.registerToken();
// get onboarding progress
const onboarding = results[1];
logService.info('[App] navigating to initial screen', sessionService.initialScreen);
if (onboarding && onboarding.show_onboarding) {
sessionService.setInitialScreen('OnboardingScreen');
}
// hide splash
RNBootSplash.hide({ duration: 250 });
logService.info('[App] navigating to initial screen', sessionService.initialScreen);
NavigationService.reset(sessionService.initialScreen);
NavigationService.navigate(sessionService.initialScreen);
// check onboarding progress and navigate if necessary
stores.onboarding.getProgress();
// check update
if (Platform.OS !== 'ios' && !GOOGLE_PLAY_STORE) {
......@@ -142,13 +143,10 @@ sessionService.onLogin(async () => {
//on app logout
sessionService.onLogout(() => {
// clear app badge
badgeService.setUnreadConversations(0);
badgeService.setUnreadNotifications(0);
// clear minds settings
mindsService.clear();
// clear offline cache
entitiesStorage.removeAll();
feedsStorage.removeAll();
......@@ -188,10 +186,14 @@ export default class App extends Component<Props, State> {
}
/**
* On component will mount
* contructor
*/
componentWillMount() {
if (!Text.defaultProps) Text.defaultProps = {};
constructor(props) {
super(props);
if (!Text.defaultProps) {
Text.defaultProps = {};
}
Text.defaultProps.style = {
fontFamily: 'Roboto',
color: '#444',
......@@ -203,8 +205,9 @@ export default class App extends Component<Props, State> {
*/
async componentDidMount() {
try {
// load app setting before start
const results = await Promise.all([settingsStore.init(), await Linking.getInitialURL()]),
const results = await Promise.all([settingsStore.init(), await Linking.getInitialURL()]);
deepLinkUrl = results[1];
......@@ -214,11 +217,13 @@ export default class App extends Component<Props, State> {
if (!this.handlePasswordResetDeepLink()) {
logService.info('[App] initializing session');
const token = await sessionService.init();
if (!token) {
logService.info('[App] there is no active session');
NavigationService.reset('Login');
RNBootSplash.hide({ duration: 250 });
NavigationService.navigate('Login');
} else {
logService.info('[App] session initialized');
}
......@@ -294,13 +299,13 @@ export default class App extends Component<Props, State> {
const app = (
<Provider key="app" {...stores}>
<ErrorBoundary message="An error occurred" containerStyle={CS.centered}>
<StatusBar barStyle={statusBarStyle} />
<NavigationStack
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
<FlashMessage renderCustomContent={this.renderNotification}
/>
<FlashMessage renderCustomContent={this.renderNotification} />
</ErrorBoundary>
</Provider>
);
......@@ -314,7 +319,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];
......
......@@ -12,6 +12,7 @@ import logService from './src/common/services/log.service';
import * as Sentry from '@sentry/react-native';
import { isAbort, isNetworkFail } from './src/common/helpers/abortableFetch';
import { isApiError } from './src/common/services/api.service';
import { isUserError } from './src/common/UserError';
// Init Sentry (if not running test)
......@@ -33,6 +34,10 @@ if (process.env.JEST_WORKER_ID === undefined) {
if (isAbort(hint.originalException)) {
return null;
}
// ignore user errors
if (isUserError(hint.originalException)) {
return null;
}
// only log api 500 errors
if (isApiError(hint.originalException) && hint.originalException.status < 500) {
return null;
......
......@@ -27,11 +27,13 @@ import groupsBar from './src/groups/GroupsBarStore';
import sessionService from './src/common/services/session.service';
import logService from './src/common/services/log.service';
import SubscriptionRequestStore from './src/channel/subscription/SubscriptionRequestStore';
/**
* App stores
*/
const stores = {
subscriptionRequest: new SubscriptionRequestStore(),
newsfeed: new newsfeed(),
notifications: new notifications(),
notificationsSettings: new notificationsSettings(),
......
......@@ -28,14 +28,31 @@
- iOS
- Android
## Building
## Install dependencies
- `yarn install`
- `react-native run-ios` or `react-native run-android`
- `cd ios && pod install` (iOS only)
## Building
- `yarn android` or `yarn ios`
## Testing
- `yarn test`
## Testing e2e (macOS)
Install the detox cli
- `brew tap wix/brew`
- `brew install applesimutils`
- `yarn global add detox-cli`
Run the tests
- `detox build -c ios.sim.debug`
- `detox test -c ios.sim.debug`
You can use -c ios.sim.release for e2e test a production build
### _Copyright Minds 2018_
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver) => {
// should ask for permissions
const permmision = await driver.waitForElementById('com.android.packageinstaller:id/permission_allow_button', wd.asserters.isDisplayed, 10000)
// we accept
permmision.click();
}
\ No newline at end of file
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver) => {
// select first image
const firstImage = await driver.waitForElementByAccessibilityId('Gallery image/jpeg', wd.asserters.isDisplayed, 5000);
await firstImage.click();
await sleep(3000);
}
\ No newline at end of file
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver, amount) => {
const lockButton = await driver.waitForElementByAccessibilityId('Post lock button', wd.asserters.isDisplayed, 5000);
await lockButton.click();
const postInput = await driver.waitForElementByAccessibilityId('Poster lock amount input', wd.asserters.isDisplayed, 5000);
await postInput.type(amount);
// we press post button
const postButton = await driver.elementByAccessibilityId('Poster lock done button');
await postButton.click();
}
\ No newline at end of file
export default async(driver) => {
const username = await driver.elementByAccessibilityId('username input');
const password = await driver.elementByAccessibilityId('password input');
const loginButton = await driver.elementByAccessibilityId('login button');
await username.type(process.env.loginUser);
await password.type(process.env.loginPass);
await loginButton.click();
}
\ No newline at end of file
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver, text) => {
// post screen must be shown
const postInput = await driver.waitForElementByAccessibilityId('PostInput', wd.asserters.isDisplayed, 5000);
await postInput.type(text);
// we press post button
const postButton = await driver.elementByAccessibilityId('Capture Post Button');
await postButton.click();
}
\ No newline at end of file
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver) => {
// tap the capture button
const button = await driver.waitForElementByAccessibilityId('CaptureButton', wd.asserters.isDisplayed, 10000);
button.click();
return button;
}
\ No newline at end of file
import wd from 'wd';
import sleep from '../../src/common/helpers/sleep';
export default async(driver, options) => {
// tap the toggle button
const button = await driver.waitForElementByAccessibilityId('NSFW button', wd.asserters.isDisplayed, 5000);
await button.click();
// wait until the menu is shown
await sleep(500);
for (let index = 0; index < options.length; index++) {
const name = options[index];
const element = await driver.elementByAccessibilityId(`NSFW ${name}`);
await element.click();
}
let action = new wd.TouchAction(driver);
action.tap({x:100, y:170});
await action.release().perform();
}
\ No newline at end of file
import wd from 'wd';
import reporterFactory from '../tests-helpers/browserstack-reporter.factory';
import post from './actions/post';
import login from './actions/login';
import { driver, capabilities} from './config';
import sleep from '../src/common/helpers/sleep';
import pressCapture from './actions/pressCapture';
import acceptPermissions from './actions/acceptPermissions';
import attachPostGalleryImage from './actions/attachPostGalleryImage';
import selectNsfw from './actions/selectNsfw';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
const data = {sessiondID: null};
jasmine.getEnv().addReporter(reporterFactory(data));
//TODO: add support for ios to this test (xpath)
describe('Activity flow tests', () => {
beforeAll(async () => {
await driver.init(capabilities);
data.sessiondID = await driver.getSessionId();
console.log('BROWSERSTACK_SESSION: ' + data.sessiondID);
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
// we should login
await login(driver);
});
afterAll(async () => {
await driver.quit();
});
it('should post a text and see it in the newsfeed', async () => {
const str = 'My e2e activity';
// press capture button
await pressCapture(driver);
// accept gallery permissions
await acceptPermissions(driver);
// make the post
await post(driver, str);
// should post and return to the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 10000);
// the first element of the list should be the post
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[2]');
expect(await textElement.text()).toBe(str);
});
it('should like the post', async() => {
const likeButton = await driver.waitForElementByAccessibilityId('Thumb up activity button', 5000);
await likeButton.click();
const likeCount = await driver.waitForElementByAccessibilityId('Thumb up count', 5000);
expect(await likeCount.text()).toBe('1');
});
it('should unlike the post', async() => {
const likeButton = await driver.waitForElementByAccessibilityId('Thumb down activity button', 5000);
await likeButton.click();
const likeCount = await driver.waitForElementByAccessibilityId('Thumb down count', 5000);
expect(await likeCount.text()).toBe('1');
});
});
\ No newline at end of file
import factory from '../tests-helpers/e2e-driver.factory';
const customCapabilities = {
'device' : 'Samsung Galaxy S9',
'os_version' : '8.0'
};
let driver, capabilities;
if (process.env.e2elocal) {
[driver, capabilities] = factory('androidLocal', {});
} else {
[driver, capabilities] = factory('browserStack', customCapabilities);
}
export {driver, capabilities} ;
import wd from 'wd';
import reporterFactory from '../tests-helpers/browserstack-reporter.factory';
import { driver, capabilities} from './config';
import post from './actions/post';
import login from './actions/login';
import sleep from '../src/common/helpers/sleep';
import pressCapture from './actions/pressCapture';
import acceptPermissions from './actions/acceptPermissions';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
const data = {sessiondID: null};
jasmine.getEnv().addReporter(reporterFactory(data));
describe('Discovery post edit flow', () => {
beforeAll(async () => {
await driver.init(capabilities);
data.sessiondID = await driver.getSessionId();
console.log('BROWSERSTACK_SESSION: ' + data.sessiondID);
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
// we should login
await login(driver);
});
afterAll(async () => {
await driver.quit();
});
it('should post a text and go to discovery', async () => {
const str = 'My e2e post #mye2epost';
await pressCapture(driver);
await acceptPermissions(driver);
// make the post
await post(driver, str);
// move to discovery
const discoveryTab = await driver.waitForElementByAccessibilityId('Discovery tab button', wd.asserters.isDisplayed, 10000);
await discoveryTab.click();
});
it('should search for the post', async () => {
// select all list
const all = await driver.waitForElementByAccessibilityId('Discovery All', wd.asserters.isDisplayed, 5000);
await all.click();
await sleep(500);
// select latest filter
const latest = await driver.waitForElementByAccessibilityId('Filter latest button', wd.asserters.isDisplayed, 1000);
await latest.click();
await sleep(500);
// search the post
const search = await driver.waitForElementByAccessibilityId('Discovery Search Input', wd.asserters.isDisplayed, 10000);
await search.type('mye2epost');
await sleep(4000);
// activity menu button
const activityMenu = await driver.waitForElementByAccessibilityId('Activity Menu button', wd.asserters.isDisplayed, 5000);
await activityMenu.click();
await sleep(500);
// tap edit
const edit = await driver.waitForElementByAndroidUIAutomator('new UiSelector().text("Edit")', wd.asserters.isDisplayed, 5000);
await edit.click();
// change the text
const editorInput = await driver.waitForElementByAccessibilityId('Post editor input', wd.asserters.isDisplayed, 5000);
await editorInput.type(' edited!');
// tap save
const save = await driver.waitForElementByAccessibilityId('Post editor save button', wd.asserters.isDisplayed, 5000);
await save.click();
// confirm activity text changed
await driver.waitForElementByAndroidUIAutomator('new UiSelector().text("My e2e post #mye2epost edited!")', wd.asserters.isDisplayed, 5000);
});
});
\ No newline at end of file
import wd from 'wd';
import reporterFactory from '../tests-helpers/browserstack-reporter.factory';
import { driver, capabilities} from './config';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
const data = {sessiondID: null};
jasmine.getEnv().addReporter(reporterFactory(data));
describe('Login flow', () => {
let username, password, loginButton;
beforeAll(async () => {
await driver.init(capabilities);
data.sessiondID = await driver.getSessionId();
console.log('BROWSERSTACK_SESSION: ' + data.sessiondID);
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
});
afterAll(async () => {
await driver.quit();
});
it('should shows login error on wrong credentials', async () => {
expect(await driver.hasElementByAccessibilityId('username input')).toBe(true);
expect(await driver.hasElementByAccessibilityId('password input')).toBe(true);
username = await driver.elementByAccessibilityId('username input');
await username.type('myuser');
password = await driver.elementByAccessibilityId('password input');
await password.type('mypass');
loginButton = await driver.elementByAccessibilityId('login button');
await loginButton.click();
// message should appear
await driver.waitForElementByAccessibilityId('loginMsg', wd.asserters.isDisplayed, 5000);
const textElement = await driver.elementByAccessibilityId('loginMsg');
expect(await textElement.text()).toBe('The user credentials were incorrect.');
});
it('should go to newsfeed on successful login', async () => {
// try successfull login
await username.type(process.env.loginUser);
await password.type(process.env.loginPass);
await loginButton.click();
// should open the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 5000);
});
it('should go to login after logout', async () => {
const menu = await driver.elementByAccessibilityId('Main menu button');
// tap menu button
await menu.click();
const logout = await driver.waitForElementByAccessibilityId('Logout', wd.asserters.isDisplayed, 5000);
// tap logout
logout.click();
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
})
});
\ No newline at end of file
import wd from 'wd';
import reporterFactory from '../tests-helpers/browserstack-reporter.factory';
import post from './actions/post';
import login from './actions/login';
import { driver, capabilities} from './config';
import sleep from '../src/common/helpers/sleep';
import pressCapture from './actions/pressCapture';
import acceptPermissions from './actions/acceptPermissions';
import attachPostGalleryImage from './actions/attachPostGalleryImage';
import selectNsfw from './actions/selectNsfw';
import lockPost from './actions/lockPost';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
const data = {sessiondID: null};
jasmine.getEnv().addReporter(reporterFactory(data));
//TODO: add support for ios to this test (xpath)
describe('Post flow tests', () => {
beforeAll(async () => {
await driver.init(capabilities);
data.sessiondID = await driver.getSessionId();
console.log('BROWSERSTACK_SESSION: ' + data.sessiondID);
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
// we should login
await login(driver);
});
afterAll(async () => {
await driver.quit();
});
it('should post a text and see it in the newsfeed', async () => {
const str = 'My e2e post #mye2epost';
// press capture button
await pressCapture(driver);
// accept gallery permissions
await acceptPermissions(driver);
// make the post
await post(driver, str);
// should post and return to the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 10000);
// the first element of the list should be the post
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[2]');
expect(await textElement.text()).toBe(str);
});
it('should remind the previuos post and see it in the newsfeed', async () => {
const str = 'Reminding my own post';
const remindButton = await driver.waitForElementByAccessibilityId('Remind activity button', 5000);
// tap remind
await remindButton.click();
// make the post
await post(driver, str);
// should post and return to the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 10000);
// the first element of the list should be the post
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[2]');
expect(await textElement.text()).toBe(str);
});
it('should post a nsfw and see it in the newsfeed', async () => {
const str = 'My e2e post #mye2epost';
// press capture button
await pressCapture(driver);
// select nsfw
await selectNsfw(driver, ['Nudity', 'Pornography']);
// make the post
await post(driver, str);
// should post and return to the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 10000);
// the first element of the list should be the post
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[2]');
expect(await textElement.text()).toBe(str);
});
it('should post paywalled content', async () => {
// press capture button
await pressCapture(driver);
// deselect nsfw
await selectNsfw(driver, ['Nudity', 'Pornography']);
const str = 'pay me something';
await lockPost(driver, '1');
// make the post with image and no permissions wait
await post(driver, str);
await sleep(1000);
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[3]');
expect(await textElement.text()).toBe('Locked');
});
it('should post an image and see it in the newsfeed', async () => {
const str = 'My e2e post image #mye2epostimage';
// press capture button
await pressCapture(driver);
// attach image
await attachPostGalleryImage(driver);
// make the post with image and no permissions wait
await post(driver, str);
// should post and return to the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 10000);
// the first element of the list should be the post
const textElement = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Newsfeed Screen"]/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[2]/android.view.ViewGroup/android.widget.TextView[2]');
expect(await textElement.text()).toBe(str);
});
it('should open the images in full screen after tap', async () => {
// get the Image touchable
const imageButton = await driver.waitForElementByAccessibilityId('Posted Image', wd.asserters.isDisplayed, 10000);
await imageButton.click();
const image = await driver.waitForElementByXPath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.widget.ImageView');
const goBack = await driver.waitForElementByAccessibilityId('Go back button', wd.asserters.isDisplayed, 10000);
await goBack.click();
});
it('should upload an image and cancel it', async () => {
// press capture button
await pressCapture(driver);
// attach image
await attachPostGalleryImage(driver);
await sleep(5000);
// we press post button
const deleteButton = await driver.elementByAccessibilityId('Attachment Delete Button');
await deleteButton.click();
await sleep(1000);
// should fail to find the delete button
return expect(driver.elementByAccessibilityId('Attachment Delete Button')).rejects.toHaveProperty('status', 7);
});
it('should return to the newsfeed', async () => {
// tap the back button
await driver.back();
// should open the newsfeed
await driver.waitForElementByAccessibilityId('Newsfeed Screen', wd.asserters.isDisplayed, 5000);
});
});
\ No newline at end of file
import wd from 'wd';
import reporterFactory from '../tests-helpers/browserstack-reporter.factory';
import login from './actions/login';
import { driver, capabilities} from './config';
import sleep from '../src/common/helpers/sleep';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
const data = {sessiondID: null};
jasmine.getEnv().addReporter(reporterFactory(data));
//TODO: add support for ios to this test (xpath)
describe('Top-bar tests', () => {
beforeAll(async () => {
await driver.init(capabilities);
data.sessiondID = await driver.getSessionId();
console.log('BROWSERSTACK_SESSION: ' + data.sessiondID);
await driver.waitForElementByAccessibilityId('username input', wd.asserters.isDisplayed, 5000);
// we should login
await login(driver);
});
afterAll(async () => {
await driver.quit();
});
it('should open the boost console', async () => {
const button = await driver.waitForElementByAccessibilityId('boost-console button', wd.asserters.isDisplayed, 7000);
await button.click();
const textElement = await driver.waitForElementByXPath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.widget.TextView');
expect(await textElement.text()).toBe('Boost Console');
const back = await driver.waitForElementByXPath('//android.widget.Button[@content-desc="Go back"]/android.view.ViewGroup/android.widget.ImageView');
back.click();
});
it('should open the users profile on clicking the profile avatar', async () => {
const button = await driver.waitForElementByAccessibilityId('topbar avatar button', wd.asserters.isDisplayed, 5000);
await button.click();
await driver.waitForElementByXPath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[1]/android.view.ViewGroup[3]/android.widget.ImageView');
const back = await driver.waitForElementByXPath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup/android.view.ViewGroup[1]/android.widget.ScrollView/android.view.ViewGroup/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.widget.TextView'); back.click();
});
it('should open the menu when clicking the hamburger menu', async () => {
const button = await driver.waitForElementByAccessibilityId('Main menu button', wd.asserters.isDisplayed, 5000);
await button.click();
const logoutButton = await driver.waitForElementByXPath('//android.view.ViewGroup[@content-desc="Logout"]/android.widget.TextView[2]');
expect(await logoutButton.text()).toBe('Logout');
const back = await driver.waitForElementByXPath('//android.widget.Button[@content-desc="Go back"]/android.view.ViewGroup/android.widget.ImageView');
back.click();
});
});
function load(count) {
function load(count, container) {
let activities = [...Array(count)].map((_, i) => {
const code = 'activityguid' + i;
......@@ -20,11 +20,11 @@ function load(count) {
type: "user",
subtype: false,
time_created: "1522036284",
getAvatarSource: () => {
return {
source:'http://thisisaurl'
}
}
// getAvatarSource: () => {
// return {
// source:'http://thisisaurl'
// }
// }
},
shouldBeBlured: jest.fn(),
message:"Message",
......@@ -37,19 +37,20 @@ function load(count) {
wire_totals: {
tokens: 1000000000000000000
},
_list: {
viewed: {
viewed: new Map([["1019155171608096768",true]]),
addViewed: () => {
return;
}
}
},
getThumbSource: () => {
return {
source:'http://thisisaurl'
}
}
containerObj: container
// _list: {
// viewed: {
// viewed: new Map([["1019155171608096768",true]]),
// addViewed: () => {
// return;
// }
// }
// },
// getThumbSource: () => {
// return {
// source:'http://thisisaurl'
// }
// }
}
});
......
export default {
}
\ No newline at end of file
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 {
......@@ -10,6 +9,7 @@ import {
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock'));
// mock backhandler
......@@ -18,31 +18,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');
......
import 'react-native';
import React from 'react';
import { shallow } from 'enzyme';
import {
FlatList,
KeyboardAvoidingView
} from 'react-native';
import ActivityScreen from '../../../src/newsfeed/ActivityScreen';
// import SingleEntityStore from '../../../src/common/stores/SingleEntityStore';
import RichEmbedStore from '../../../src/common/stores/RichEmbedStore';
import commentsStoreProvider from '../../../src/comments/CommentsStoreProvider';
import { commentsServiceFaker } from '../../../__mocks__/fake/CommentsFaker';
import { activitiesServiceFaker } from '../../../__mocks__/fake/ActivitiesFaker';
import CommentList from '../../../src/comments/CommentList';
jest.mock('../../../src/newsfeed/NewsfeedService');
import { getSingle } from '../../../src/newsfeed/NewsfeedService';
import entitiesService from '../../../src/common/services/entities.service';
import ActivityModel from '../../../src/newsfeed/ActivityModel';
jest.mock('../../../src/common/BaseModel');
jest.mock('../../../src/newsfeed/NewsfeedService');
jest.mock('../../../src/newsfeed/activity/Activity', () => 'Activity');
jest.mock('../../../src/comments/CommentList', () => 'CommentList');
jest.mock('../../../src/common/components/CenteredLoading', () => 'CenteredLoading');
......@@ -55,7 +49,7 @@ describe('Activity screen component', () => {
}
};
entitiesService.single.mockResolvedValue(navigation.state.params.entity);
entitiesService.single.mockResolvedValue(ActivityModel.create(navigation.state.params.entity));
screen = shallow(
<ActivityScreen navigation={navigation}/>
......@@ -65,7 +59,7 @@ describe('Activity screen component', () => {
expect(screen).toMatchSnapshot();
// unmount
await screen.instance().componentDidMount();
await screen.instance().loadEntity();
jest.runAllTicks();
......
import 'react-native';
import React from 'react';
import { Text, TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import { activitiesServiceFaker } from '../../../__mocks__/fake/ActivitiesFaker';
import renderer from 'react-test-renderer';
import OwnerBlock from '../../../src/newsfeed/activity/OwnerBlock';
import withPreventDoubleTap from '../../../src/common/components/PreventDoubleTap';
import ActivityModel from '../../../src/newsfeed/ActivityModel';
// const DebouncedTouchableOpacity = withPreventDoubleTap(TouchableOpacity);
describe('Owner component', () => {
let screen;
beforeEach(() => {
const TouchableOpacityCustom = <TouchableOpacity onPress={this.onPress} />;
const navigation = { navigate: jest.fn(), push: jest.fn() };
let activityResponse = activitiesServiceFaker().load(1);
let screen, entity, navigation;
beforeEach(() => {
navigation = { navigate: jest.fn(), push: jest.fn() };
const activityResponse = activitiesServiceFaker().load(1, {guid:1, name:'group'});
entity = ActivityModel.create(activityResponse.activities[0]);
screen = shallow(
<OwnerBlock entity ={activityResponse.activities[0]} navigation={navigation} rightToolbar={null}/>
<OwnerBlock entity ={entity} navigation={navigation} rightToolbar={null}/>
);
jest.runAllTimers();
});
it('renders correctly', async () => {
......@@ -33,58 +28,28 @@ describe('Owner component', () => {
it('should have PreventDoubleTap', async () => {
screen.update();
expect(screen.find('PreventDoubleTap')).toHaveLength(2);
expect(screen.find('PreventDoubleTap')).toHaveLength(3);
});
it('should _navToChannel on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
navigate: jest.fn(),
push: jest.fn()
};
let entity = activityResponse.activities[0];
entity.containerObj = { guid: 'guidguid' };
screen = shallow(
<OwnerBlock entity={entity} navigation={navigation} rightToolbar={null}/>
);
screen.update()
let touchables = screen.find('PreventDoubleTap');
touchables.at(0).props().onPress();
jest.runAllTimers();
expect(navigation.push).toHaveBeenCalledWith('Channel', {'entity': entity.ownerObj, 'guid': entity.ownerObj.guid});
expect(screen.find('PreventDoubleTap')).toHaveLength(3);
});
it('should nav to groups on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
navigate: jest.fn(),
push: jest.fn()
};
let entity = activityResponse.activities[0];
entity.containerObj = { guid: 'guidguid' };
screen = shallow(
<OwnerBlock entity={entity} navigation={navigation} rightToolbar={null}/>
);
screen.update()
let touchables = screen.find('PreventDoubleTap');
expect(screen.find('PreventDoubleTap')).toHaveLength(3);
//group touchable
touchables.at(2).props().onPress();
jest.runAllTimers();
expect(navigation.push).toHaveBeenCalled();
expect(navigation.push).toHaveBeenCalledWith('GroupView', {"group": {"guid": 1, "name": "group"}});
});
});
import 'react-native';
import React from 'react';
import { Text, TouchableOpacity } from "react-native";
import { TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import { activitiesServiceFaker } from '../../../__mocks__/fake/ActivitiesFaker';
import renderer from 'react-test-renderer';
import RemindOwnerBlock from '../../../src/newsfeed/activity/RemindOwnerBlock';
import formatDate from '../../../src/common/helpers/date';
import domain from '../../../src/common/helpers/domain';
import ActivityModel from '../../../src/newsfeed/ActivityModel';
describe('Remind owner component', () => {
let user, comments, entity, screen;
let entity, screen, navigation;
beforeEach(() => {
let activityResponse = activitiesServiceFaker().load(1);
entity = ActivityModel.create(activitiesServiceFaker().load(1).activities[0]);
navigation = {
navigate: jest.fn(),
push: jest.fn(),
};
screen = shallow(
<RemindOwnerBlock entity={activityResponse.activities[0]}/>
<RemindOwnerBlock entity={entity} navigation={navigation}/>
);
jest.runAllTimers();
});
it('renders correctly', async () => {
......@@ -36,26 +36,12 @@ describe('Remind owner component', () => {
it('should _navToChannel on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
navigate: jest.fn(),
push: jest.fn(),
};
let entity = activityResponse.activities[0];
screen = shallow(
<RemindOwnerBlock entity={entity} navigation={navigation} rightToolbar={null}/>
);
screen.update()
let touchables = screen.find('TouchableOpacity');
touchables.at(0).props().onPress();
jest.runAllTimers();
expect(navigation.push).toHaveBeenCalledWith('Channel', {'entity': entity.ownerObj, 'guid': entity.ownerObj.guid});
expect(screen.find(TouchableOpacity)).toHaveLength(2);
});
});
// 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 {
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"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 {
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"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 {
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
"type": "user",
}
}
/>
<CommentsAction
entity={
Object {
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"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 {
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"guid": "activityguid0",
"mature": false,
"message": "Message",
"ownerObj": Object {
"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>
`;
......@@ -17,28 +17,25 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
>
<CommentList
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Object {
"1019155171608096768": true,
},
},
},
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"is_visible": true,
"mature": false,
"mature_visibility": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"ownerObj": UserModel {
"__list": null,
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
......@@ -46,10 +43,17 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"paywall": undefined,
"perma_url": false,
"permissions": Object {},
"pinned": undefined,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"thumbs:down:count": undefined,
"thumbs:down:user_guids": undefined,
"thumbs:up:count": undefined,
"thumbs:up:user_guids": undefined,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
......@@ -62,28 +66,25 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
<Activity
autoHeight={false}
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Object {
"1019155171608096768": true,
},
},
},
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": false,
"custom_type": false,
"description": "Congratulations! ",
"edited": "",
"getThumbSource": [Function],
"guid": "activityguid0",
"is_visible": true,
"mature": false,
"mature_visibility": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"ownerObj": UserModel {
"__list": null,
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
......@@ -91,10 +92,17 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
},
"owner_guid": "824853017709780997",
"parent_guid": "838106762591510528",
"paywall": undefined,
"perma_url": false,
"permissions": Object {},
"pinned": undefined,
"rowKey": "something0",
"shouldBeBlured": [MockFunction],
"thumbnail_src": false,
"thumbs:down:count": undefined,
"thumbs:down:user_guids": undefined,
"thumbs:up:count": undefined,
"thumbs:up:user_guids": undefined,
"time_created": "1522036284",
"title": "TITLE",
"type": "activity",
......@@ -109,27 +117,18 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
"state": Object {
"params": Object {
"entity": Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"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",
......@@ -161,27 +160,18 @@ exports[`Activity screen component renders correctly with an entity as param 2`]
"state": Object {
"params": Object {
"entity": Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"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",
......
......@@ -18,7 +18,12 @@ exports[`Owner component renders correctly 1`] = `
resizeMode="cover"
source={
Object {
"source": "http://thisisaurl",
"headers": Object {
"App-Version": "3.8.0",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
},
"uri": "https://cdn.minds.com/icon/824853017709780997/medium/undefined",
}
}
style={
......@@ -62,6 +67,30 @@ exports[`Owner component renders correctly 1`] = `
}
/>
</PreventDoubleTap>
<PreventDoubleTap
onPress={[Function]}
style={
Object {
"flex": 1,
"marginLeft": 4,
}
}
>
<Text
lineBreakMode="tail"
numberOfLines={1}
style={
Object {
"color": "#888",
"fontFamily": "Roboto",
"fontWeight": "bold",
}
}
>
&gt;
group
</Text>
</PreventDoubleTap>
</View>
</View>
</View>
......
......@@ -36,7 +36,12 @@ exports[`Remind owner component renders correctly 1`] = `
resizeMode="cover"
source={
Object {
"source": "http://thisisaurl",
"headers": Object {
"App-Version": "3.8.0",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
},
"uri": "https://cdn.minds.com/icon/824853017709780997/medium/undefined",
}
}
style={
......
import 'react-native';
import React from 'react';
import { Text, TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import { activitiesServiceFaker } from '../../../../__mocks__/fake/ActivitiesFaker';
import renderer from 'react-test-renderer';
import RemindAction from '../../../../src/newsfeed/activity/actions/RemindAction';
import withPreventDoubleTap from '../../../../src/common/components/PreventDoubleTap';
import featuresService from '../../../../src/common/services/features.service';
import ActivityModel from '../../../../src/newsfeed/ActivityModel';
describe('Thumb action component', () => {
let screen;
beforeEach(() => {
const TouchableOpacityCustom = <TouchableOpacity onPress={this.onPress} />;
let screen, entity;
beforeEach(() => {
const navigation = { push: jest.fn(), state: {key:1} };
let activityResponse = activitiesServiceFaker().load(1);
entity = ActivityModel.create(activityResponse.activities[0])
screen = shallow(
<RemindAction entity={activityResponse.activities[0]} navigation={navigation} />
<RemindAction entity={entity} navigation={navigation} />
);
jest.runAllTimers();
});
it('renders correctly', async () => {
screen.update();
expect(screen).toMatchSnapshot();
});
it('should have a remind button', async () => {
screen.update();
expect(screen.find('PreventDoubleTap')).toHaveLength(1)
});
it('should navigate a thumb on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
push: jest.fn(),
state: {key:1}
};
let entity = activityResponse.activities[0];
entity.toggleVote = jest.fn();
entity.votedUp = true;
entity['thumbs:up:user_guids'] = ['1'];
screen = shallow(
<RemindAction entity={entity} navigation={navigation}/>
);
screen.update()
let touchables = screen.find('PreventDoubleTap');
touchables.at(0).props().onPress();
jest.runAllTimers();
expect(navigation.push).toBeCalled();
});
});
\ No newline at end of file
......@@ -11,24 +11,24 @@ import ThumbDownAction from '../../../../src/newsfeed/activity/actions/ThumbDown
import withPreventDoubleTap from '../../../../src/common/components/PreventDoubleTap';
import featuresService from '../../../../src/common/services/features.service';
import UserStore from '../../../../src/auth/UserStore';
import ActivityModel from '../../../../src/newsfeed/ActivityModel';
jest.mock('../../../../src/auth/UserStore');
// prevent double tap in touchable
describe('Thumb action component', () => {
let screen;
let screen, entity;
beforeEach(() => {
const TouchableOpacityCustom = <TouchableOpacity onPress={this.onPress} />;
const navigation = { navigate: jest.fn() };
let activityResponse = activitiesServiceFaker().load(1);
entity = ActivityModel.create(activityResponse.activities[0]);
screen = shallow(
<ThumbDownAction entity={activityResponse.activities[0]} navigation={navigation} />
<ThumbDownAction entity={entity} navigation={navigation} />
);
jest.runAllTimers();
});
it('renders correctly', async () => {
......@@ -43,21 +43,21 @@ describe('Thumb action component', () => {
});
it('should navigate a thumb on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
navigate: jest.fn()
const navigation = {
navigate: jest.fn()
};
let entity = activityResponse.activities[0];
entity.toggleVote = jest.fn();
entity.votedUp = true;
screen = shallow(
<ThumbDownAction entity={entity} navigation={navigation}/>
);
screen.update();
let touchables = screen.find('PreventDoubleTap');
touchables.at(0).props().onPress();
jest.runAllTimers();
expect(entity.toggleVote).toHaveBeenCalled();
......
......@@ -11,22 +11,24 @@ import ThumbUpAction from '../../../../src/newsfeed/activity/actions/ThumbUpActi
import withPreventDoubleTap from '../../../../src/common/components/PreventDoubleTap';
import featuresService from '../../../../src/common/services/features.service';
import UserStore from '../../../../src/auth/UserStore';
import ActivityModel from '../../../../src/newsfeed/ActivityModel';
jest.mock('../../../../src/auth/UserStore');
describe('Thumb action component', () => {
let screen;
let screen, entity;
beforeEach(() => {
const TouchableOpacityCustom = <TouchableOpacity onPress={this.onPress} />;
const navigation = { navigate: jest.fn() };
let activityResponse = activitiesServiceFaker().load(1);
entity = ActivityModel.create(activityResponse.activities[0]);
screen = shallow(
<ThumbUpAction entity={activityResponse.activities[0]} navigation={navigation} />
<ThumbUpAction entity={entity} navigation={navigation} />
);
jest.runAllTimers();
});
it('renders correctly', async () => {
......@@ -41,21 +43,20 @@ describe('Thumb action component', () => {
});
it('should navigate a thumb on press ', () => {
let activityResponse = activitiesServiceFaker().load(1);
const navigation = {
navigate: jest.fn()
const navigation = {
navigate: jest.fn()
};
let entity = activityResponse.activities[0];
entity.toggleVote = jest.fn();
entity.votedUp = true;
screen = shallow(
<ThumbUpAction entity={entity} navigation={navigation}/>
);
screen.update();
let touchables = screen.find('PreventDoubleTap');
touchables.at(0).props().onPress();
jest.runAllTimers();
expect(entity.toggleVote).toHaveBeenCalled();
......
......@@ -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]}
......
......@@ -8,6 +8,12 @@ exports[`Comment action component renders correctly 1`] = `
Object {
"flex": 1,
},
Object {
"alignContent": "center",
"alignItems": "center",
"alignSelf": "center",
"justifyContent": "center",
},
Object {
"flexDirection": "row",
"justifyContent": "center",
......@@ -16,16 +22,27 @@ exports[`Comment action component renders correctly 1`] = `
}
>
<Icon
color="rgb(96, 125, 139)"
allowFontScaling={false}
name="speaker-notes-off"
raised={false}
reverse={false}
reverseColor="white"
size={20}
underlayColor="white"
style={
Array [
Object {
"color": "#d8d8d8",
},
Object {
"marginRight": 5,
},
]
}
/>
<Counter
size={15}
size={14}
style={
Object {
"color": "rgb(96, 125, 139)",
}
}
/>
</PreventDoubleTap>
`;
......@@ -3,25 +3,22 @@
exports[`Owner component renders correctly 1`] = `
<View
style={
Object {
"alignItems": "center",
"flexDirection": "column",
"justifyContent": "center",
}
Array [
Object {
"alignItems": "center",
"flexDirection": "column",
},
]
}
>
<Text
style={
Array [
Object {
"paddingLeft": 4,
},
Object {
"color": "#888",
"fontWeight": "800",
"color": "rgb(96, 125, 139)",
},
Object {
"fontSize": 11,
"fontSize": 15,
},
]
}
......
......@@ -8,26 +8,42 @@ exports[`Thumb action component renders correctly 1`] = `
Object {
"flex": 1,
},
Object {
"alignContent": "center",
"alignItems": "center",
"alignSelf": "center",
"justifyContent": "center",
},
Object {
"flexDirection": "row",
"justifyContent": "center",
},
null,
]
}
testID="Remind activity button"
>
<Icon
color="rgb(96, 125, 139)"
allowFontScaling={false}
name="repeat"
raised={false}
reverse={false}
reverseColor="white"
size={20}
underlayColor="white"
style={
Array [
Object {
"color": "rgb(96, 125, 139)",
},
Object {
"marginRight": 5,
},
]
}
/>
<Counter
size={15}
size={14}
style={
Object {
"color": "rgb(96, 125, 139)",
}
}
/>
</PreventDoubleTap>
`;
......@@ -23,16 +23,27 @@ exports[`Thumb action component renders correctly 1`] = `
testID="Thumb down activity button"
>
<Icon
color="rgb(96, 125, 139)"
allowFontScaling={false}
name="thumb-down"
raised={false}
reverse={false}
reverseColor="white"
size={20}
underlayColor="white"
style={
Array [
Object {
"color": "rgb(96, 125, 139)",
},
Object {
"marginRight": 5,
},
]
}
/>
<Counter
size={15}
size={14}
style={
Object {
"color": "rgb(96, 125, 139)",
}
}
testID="Thumb down count"
/>
</PreventDoubleTap>
......
......@@ -23,16 +23,27 @@ exports[`Thumb action component renders correctly 1`] = `
testID="Thumb up activity button"
>
<Icon
color="rgb(96, 125, 139)"
allowFontScaling={false}
name="thumb-up"
raised={false}
reverse={false}
reverseColor="white"
size={20}
underlayColor="white"
style={
Array [
Object {
"color": "rgb(96, 125, 139)",
},
Object {
"marginRight": 5,
},
]
}
/>
<Counter
size={15}
size={14}
style={
Object {
"color": "rgb(96, 125, 139)",
}
}
testID="Thumb up count"
/>
</PreventDoubleTap>
......
......@@ -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');
});
});
......@@ -7,7 +7,6 @@ import UserModel from '../../src/channel/UserModel';
jest.mock('../../src/channel/ChannelService');
jest.mock('../../src/channel/UserModel');
// mock the static create method
UserModel.create = jest.fn();
......@@ -258,8 +257,10 @@ describe('user store', () => {
const fakeUser = meFactory(1);
fakeUser.admin = true;
const entity = new UserModel(fakeUser);
// mock methods called
UserModel.create.mockReturnValue(fakeUser);
UserModel.create.mockReturnValue(entity);
try {
// set the user
......
......@@ -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]}
......
......@@ -35,7 +35,7 @@ exports[`LoginForm component should renders correctly 1`] = `
},
]
}
testID="username input"
testID="usernameInput"
underlineColorAndroid="transparent"
value=""
/>
......@@ -67,7 +67,7 @@ exports[`LoginForm component should renders correctly 1`] = `
},
]
}
testID="password input"
testID="userPasswordInput"
underlineColorAndroid="transparent"
value=""
/>
......@@ -133,7 +133,9 @@ exports[`LoginForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -239,7 +241,9 @@ exports[`LoginForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -247,7 +251,7 @@ exports[`LoginForm component should renders correctly 1`] = `
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={null}
testID="login button"
testID="loginButton"
>
<View
pointerEvents="box-only"
......@@ -413,6 +417,7 @@ exports[`LoginForm component should renders correctly 1`] = `
onModalWillHide={[Function]}
onModalWillShow={[Function]}
onRequestClose={[Function]}
scrollHorizontal={false}
scrollOffset={0}
scrollOffsetMax={0}
scrollTo={null}
......@@ -428,6 +433,8 @@ exports[`LoginForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -454,6 +461,7 @@ exports[`LoginForm component should renders correctly 1`] = `
onModalWillHide={[Function]}
onModalWillShow={[Function]}
pointerEvents="box-none"
scrollHorizontal={false}
scrollOffset={0}
scrollOffsetMax={0}
scrollTo={null}
......@@ -622,7 +630,9 @@ exports[`LoginForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -636,6 +646,8 @@ exports[`LoginForm component should renders correctly 1`] = `
"borderColor": "#777777",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
"justifyContent": "center",
"margin": 4,
"opacity": 1,
"padding": 4,
......@@ -659,7 +671,9 @@ exports[`LoginForm component should renders correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -673,6 +687,8 @@ exports[`LoginForm component should renders correctly 1`] = `
"borderColor": "#4690D6",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
"justifyContent": "center",
"margin": 4,
"opacity": 1,
"padding": 4,
......
......@@ -42,7 +42,11 @@ exports[`LoginScreen component should renders correctly 1`] = `
>
<Image
resizeMode="contain"
source={1}
source={
Object {
"testUri": "../../../src/assets/logos/logo-white.png",
}
}
style={
Object {
"alignSelf": "center",
......
......@@ -105,7 +105,9 @@ exports[`RegisterForm component should renders correctly 1`] = `
/>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -181,7 +183,9 @@ exports[`RegisterForm component should renders correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -296,7 +300,9 @@ exports[`RegisterForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -402,7 +408,9 @@ exports[`RegisterForm component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -3,7 +3,9 @@
exports[`blog card component should renders correctly 1`] = `
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -12,9 +14,7 @@ exports[`blog card component should renders correctly 1`] = `
onStartShouldSetResponder={[Function]}
style={
Object {
"backgroundColor": "#FFF",
"flex": 1,
"flexDirection": "column",
"backgroundColor": "white",
"opacity": 1,
}
}
......@@ -59,68 +59,93 @@ exports[`blog card component should renders correctly 1`] = `
</View>
<View
style={
Object {
"alignItems": "stretch",
"flexDirection": "column",
"padding": 12,
"paddingLeft": 12,
"paddingRight": 12,
"width": "100%",
}
Array [
Object {
"padding": 10,
},
]
}
>
<View
style={
Object {
"flex": 1,
"flexDirection": "row",
}
Array [
Object {
"alignItems": "flex-start",
"flexDirection": "column",
},
Object {
"width": "100%",
},
]
}
>
<View
<Text
style={
Object {
"flex": 1,
}
Array [
Object {
"fontSize": 16,
},
Object {
"fontWeight": "500",
},
]
}
>
<Text
style={
Some Title
</Text>
<View
style={
Array [
Object {
"color": "#444",
"fontFamily": "Roboto",
"fontSize": 16,
"fontWeight": "800",
"letterSpacing": 0.5,
}
}
>
Some Title
</Text>
<View
style={
"marginBottom": 10,
},
Object {
"marginTop": 10,
},
Object {
"alignItems": "center",
"alignSelf": "flex-start",
"flex": 1,
"flexDirection": "row",
"justifyContent": "center",
"paddingBottom": 4,
"paddingTop": 4,
}
},
Object {
"alignItems": "center",
},
]
}
>
<View
height={24}
style={
Array [
Object {
"backgroundColor": "transparent",
"height": 24,
"paddingBottom": 10,
"paddingRight": 10,
"paddingTop": 10,
"width": 24,
},
Object {
"borderRadius": 12,
},
undefined,
]
}
width={24}
>
<View
height={24}
style={
Array [
Object {
"backgroundColor": "transparent",
"height": 24,
"paddingBottom": 10,
"paddingRight": 10,
"paddingTop": 10,
"width": 24,
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "rgba(0,0,0,0.2)",
"bottom": 0,
"flex": 1,
"justifyContent": "center",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"borderRadius": 12,
......@@ -128,53 +153,40 @@ exports[`blog card component should renders correctly 1`] = `
undefined,
]
}
width={24}
>
<View
style={
Array [
Object {
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "rgba(0,0,0,0.2)",
"bottom": 0,
"flex": 1,
"justifyContent": "center",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
},
Object {
"borderRadius": 12,
},
undefined,
]
}
/>
</View>
<Text
style={
/>
</View>
<Text
numberOfLines={1}
style={
Array [
Object {
"fontSize": 12,
},
Object {
"paddingLeft": 5,
},
Object {
"flex": 1,
},
]
}
>
SOMEUSERMANE
</Text>
<Text
style={
Array [
Object {
"color": "#888",
"fontSize": 10,
"paddingLeft": 8,
}
}
>
SOMEUSERMANE
</Text>
<Text
style={
},
Object {
"fontSize": 8,
"paddingLeft": 5,
}
}
>
Apr 27, 2018, 07:17
</Text>
</View>
},
]
}
>
Apr 27, 2018, 07:17
</Text>
</View>
</View>
</View>
......
......@@ -546,7 +546,9 @@ exports[`blog list screen component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -583,7 +585,9 @@ exports[`blog list screen component should renders correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
import 'react-native';
import React from 'react';
import { Platform, CameraRoll, TouchableOpacity } from "react-native";
import { Platform, TouchableOpacity } from "react-native";
import { shallow, render } from 'enzyme';
import CameraRoll from '@react-native-community/cameraroll';
import androidPermission from '../../src/common/services/android-permissions.service';
import { getPhotosFaker } from '../../__mocks__/fake/CameraRollFaker';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
jest.mock('../../src/common/services/android-permissions.service');
//jest.mock('TouchableOpacity', () => 'TouchableOpacity' )
jest.mock('CameraRoll');
jest.mock('@react-native-community/cameraroll');
CameraRoll.getPhotos = jest.fn();
// fake camera roll data
const response = getPhotosFaker(5);
......
import 'react-native';
import React from 'react';
import { Alert, CameraRoll } from 'react-native';
import { Alert } from 'react-native';
import { shallow } from 'enzyme';
import { Icon } from 'react-native-elements'
import CameraRoll from '@react-native-community/cameraroll';
import CapturePoster from '../../src/capture/CapturePoster';
import CapturePreview from '../../src/capture/CapturePreview';
......@@ -21,7 +22,6 @@ jest.mock('../../src/capture/CapturePosterFlags', () => 'CapturePosterFlags');
jest.mock('../../src/common/services/translation.service');
Alert.alert = jest.fn();
jest.mock('CameraRoll');
CameraRoll.getPhotos = jest.fn();
// fake camera roll data
const response = getPhotosFaker(5);
......
......@@ -2,7 +2,6 @@ import 'react-native';
import React from 'react';
import { shallow } from 'enzyme';
import { configure } from 'mobx';
import LicensePicker from '../../src/common/components/LicensePicker';
import CaptureStore from '../../src/capture/CaptureStore';
import CapturePosterFlags from '../../src/capture/CapturePosterFlags';
import HashtagStore from '../../src/common/stores/HashtagStore';
......@@ -15,6 +14,8 @@ jest.mock('../../src/common/stores/HashtagStore');
jest.mock('../../src/capture/CaptureStore');
jest.mock('../../src/common/components/LicensePicker', () => 'LicensePicker');
jest.mock('../../src/newsfeed/topbar/TagsSubBar', () => 'TagsSubBar');
jest.mock('../../src/common/components/nsfw/NsfwToggle', () => 'NsfwToggle');
Date = class extends Date {
constructor(date) {
......
......@@ -27,7 +27,9 @@ exports[`cature tabs component should renders correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -94,7 +96,9 @@ exports[`cature tabs component should renders correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -161,7 +165,9 @@ exports[`cature tabs component should renders correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -10,7 +10,6 @@ import features from '../../src/common/services/features.service';
import renderer from 'react-test-renderer';
jest.mock('../../src/channel/ChannelStore');
jest.mock('../../src/channel/UserModel');
jest.mock('../../src/common/services/features.service');
jest.mock('../../AppStores');
jest.mock('../../src/common/services/boosted-content.service');
......@@ -19,10 +18,13 @@ jest.mock('../../src/common/services/boosted-content.service');
* Tests
*/
describe('channel actions component', () => {
let store;
beforeEach(() => {
store = new ChannelStore();
store.channel = new UserModel(userFaker(1));
store.channel.toggleSubscription = jest.fn();
store.channel.toggleBlock = jest.fn();
});
it('should renders correctly', () => {
......@@ -69,13 +71,13 @@ describe('channel actions component', () => {
store.channel.subscribed = true;
store.channel.blocked = true;
opt = wrapper.instance().makeAction(1);
opt = wrapper.instance().executeAction(1);
expect(store.channel.toggleSubscription).toBeCalled();
opt = wrapper.instance().makeAction(2);
expect(store.toggleBlock).toBeCalled();
opt = wrapper.instance().executeAction(2);
expect(store.channel.toggleBlock).toBeCalled();
opt = wrapper.instance().makeAction(3);
opt = wrapper.instance().executeAction(3);
expect(navigation.push).toBeCalled();
});
......
import 'react-native';
import React from 'react';
//import { Platform, CameraRoll, TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import ChannelScreen from '../../src/channel/ChannelScreen';
import { activitiesServiceFaker } from '../../__mocks__/fake/ActivitiesFaker';
import renderer from 'react-test-renderer';
import UserStore from '../../src/auth/UserStore';
import RewardsCarousel from '../../src/channel/carousel/RewardsCarousel';
import ChannelHeader from '../../src/channel/header/ChannelHeader';
import Toolbar from '../../src/channel/toolbar/Toolbar';
import NewsfeedList from '../../src/newsfeed/NewsfeedList';
import channelService from '../../src/channel/ChannelService';
import CenteredLoading from '../../src/common/components/CenteredLoading';
import Button from '../../src/common/components/Button';
import colors from '../../src/styles/Colors';
import BlogCard from '../../src/blogs/BlogCard';
import CaptureFab from '../../src/capture/CaptureFab';
import { CommonStyle } from '../../src/styles/Common';
import UserModel from '../../src/channel/UserModel';
import Touchable from '../../src/common/components/Touchable';
import session from '../../src/common/services/session.service';
import ChannelStore from '../../src/channel/ChannelStore';
import userFaker from '../../__mocks__/fake/channel/UserFactory'
import UserModel, { USER_MODE_CLOSED, USER_MODE_OPEN } from '../../src/channel/UserModel';
import featuresService from '../../src/common/services/features.service';
jest.mock('../../src/common/helpers/abortableFetch');
jest.mock('../../src/channel/UserModel');
jest.mock('../../src/newsfeed/ActivityModel');
jest.mock('../../src/channel/carousel/RewardsCarousel', () => 'RewardsCarousel');
jest.mock('../../src/channel/header/ChannelHeader', () => 'ChannelHeader');
......@@ -45,7 +25,7 @@ jest.mock('../../src/common/services/boosted-content.service');
*/
describe('Channel screen component', () => {
let store, screen, entities, channel, navigation, activityResponse, user;
let screen, channel, navigation, user, channelStore;
beforeEach(() => {
......@@ -54,17 +34,14 @@ describe('Channel screen component', () => {
activity.wire_totals = { tokens: 20};
activity.impressions = 20;
navigation = { navigate: jest.fn() };
navigation = { navigate: jest.fn(), goBack: jest.fn() };
navigation.state = {
params: {
entity: activity
}
};
channelStore = {
channel: {
guid:'125',
blocked: false,
},
channel: new UserModel(userFaker(1)),
setChannel: jest.fn(),
feedStore: {
setChannel: jest.fn(),
......@@ -75,16 +52,14 @@ describe('Channel screen component', () => {
load: jest.fn(),
};
user = new UserStore();
channel = { store: jest.fn() };
channel.store.mockReturnValue(channelStore);
screen = shallow(
<ChannelScreen.wrappedComponent channel={channel} user={user} navigation={navigation} />
<ChannelScreen.wrappedComponent channel={channel} navigation={navigation} />
);
screen.update();
});
it('should renders correctly', () => {
......@@ -92,8 +67,7 @@ describe('Channel screen component', () => {
expect(screen).toMatchSnapshot();
});
it('should have the expectedComponents while loading, also check newsfeed', async () => {
screen.update();
it('should have the expected components while loading, also check newsfeed', async () => {
expect(screen.find('FeedList')).toHaveLength(1);
let render = screen.dive();
......@@ -101,36 +75,42 @@ describe('Channel screen component', () => {
expect(screen.find('CaptureFab')).toHaveLength(1);
});
it('should have the expected components while loading, also check flatlist for blocked', async () => {
it('should have the expectedComponents while loading, also check flatlist for blocked', async () => {
screen.update();
channelStore = {
channel: {
guid:'125',
blocked: true,
},
setChannel: jest.fn(),
feedStore: {
setChannel: jest.fn(),
},
rewards: {
merged: []
},
load: jest.fn(),
};
user = new UserStore();
channel = { store: jest.fn() };
channelStore.channel.blocked = true;
channel.store.mockReturnValue(channelStore);
await screen.update();
screen = shallow(
<ChannelScreen.wrappedComponent channel={channel} user={user} navigation={navigation} />
);
expect(screen.find('FlatList')).toHaveLength(1);
expect(screen.find('FeedList')).toHaveLength(0);
let render = screen.dive();
expect(render.find('CenteredLoading')).toHaveLength(0);
expect(screen.find('CaptureFab')).toHaveLength(1);
});
it('should show closed channel message', async () => {
channelStore.channel.blocked = false;
channelStore.channel.mode = USER_MODE_CLOSED;
await screen.update();
expect(screen).toMatchSnapshot();
});
it('should navigate back if the the VIEW permissions are removed', async () => {
channelStore.channel.mode = USER_MODE_OPEN;
// force permissions feature flag
featuresService.features = {permissions: true};
channelStore.channel.setPermissions({permissions:[]});
await screen.update();
expect(navigation.goBack).toBeCalled();
});
});
\ No newline at end of file
......@@ -14,84 +14,12 @@ exports[`channel actions component should renders correctly 1`] = `
]
}
>
<View
accessibilityLabel="Wire Button"
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"alignItems": "center",
"backgroundColor": "white",
"borderColor": "#4690D6",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
"justifyContent": "center",
"margin": 4,
"opacity": 1,
"padding": 4,
}
}
>
<Text
allowFontScaling={false}
style={
Array [
Object {
"color": undefined,
"fontSize": 18,
},
Array [
Object {
"marginLeft": 5,
},
Object {
"color": "#4690D6",
},
],
Object {
"fontFamily": "Ionicons",
"fontStyle": "normal",
"fontWeight": "normal",
},
Object {},
]
}
>
</Text>
<Text
style={
Array [
Object {
"color": "#4690D6",
},
Array [
Object {
"marginLeft": 5,
},
Object {
"marginRight": 5,
},
],
]
}
>
Wire
</Text>
</View>
<View
accessibilityLabel="More"
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -15,7 +15,6 @@ jest.mock('../../../src/auth/UserStore');
jest.mock('../../../AppStores');
jest.mock('../../../src/channel/ChannelStore');
jest.mock('../../../src/common/services/boosted-content.service');
jest.mock('TouchableHighlight', () => 'TouchableHighlight');
/**
* Tests
......
......@@ -4,7 +4,9 @@ exports[`channel header component owner should render correctly 1`] = `
<View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -131,16 +133,26 @@ exports[`channel header component owner should render correctly 1`] = `
</View>
<View>
<View>
<TouchableHighlight
onPress={[Function]}
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
undefined,
]
}
underlayColor="transparent"
>
<View>
<View
style={null}
>
<Text>
SUBSCRIBERS
</Text>
......@@ -148,7 +160,7 @@ exports[`channel header component owner should render correctly 1`] = `
50
</Text>
</View>
</TouchableHighlight>
</View>
<View>
<Text>
VIEWS
......@@ -196,9 +208,11 @@ exports[`channel header component owner should render correctly 1`] = `
}
>
<View
accessibilityLabel="Subscribe to this channel"
accessibilityLabel="Edit your channel settings"
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -232,7 +246,7 @@ exports[`channel header component owner should render correctly 1`] = `
}
>
SUBSCRIBE
Edit
</Text>
</View>
......@@ -252,7 +266,9 @@ exports[`channel header component owner should render correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
......@@ -32,7 +32,9 @@ exports[`channel subscribers component should render correctly 1`] = `
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -61,7 +63,9 @@ exports[`channel subscribers component should render correctly 1`] = `
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -375,7 +379,17 @@ exports[`channel subscribers component should render correctly 1`] = `
style={null}
>
<DiscoveryUser
entity={
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
row={
Object {
"index": 0,
"item": Object {
......@@ -464,16 +478,6 @@ exports[`channel subscribers component should render correctly 1`] = `
},
}
}
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
store={
Object {
"filter": "subscribers",
......@@ -752,7 +756,17 @@ exports[`channel subscribers component should render correctly 1`] = `
style={null}
>
<DiscoveryUser
entity={
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
row={
Object {
"index": 1,
"item": Object {
......@@ -841,16 +855,6 @@ exports[`channel subscribers component should render correctly 1`] = `
},
}
}
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
store={
Object {
"filter": "subscribers",
......@@ -1129,7 +1133,17 @@ exports[`channel subscribers component should render correctly 1`] = `
style={null}
>
<DiscoveryUser
entity={
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
row={
Object {
"index": 2,
"item": Object {
......@@ -1218,16 +1232,6 @@ exports[`channel subscribers component should render correctly 1`] = `
},
}
}
navigation={
Object {
"navigate": [MockFunction],
"state": Object {
"params": Object {
"guid": 1,
},
},
}
}
store={
Object {
"filter": "subscribers",
......@@ -1538,7 +1542,9 @@ exports[`channel subscribers component should render correctly without data 1`]
>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -1567,7 +1573,9 @@ exports[`channel subscribers component should render correctly without data 1`]
</View>
<View
accessible={true}
focusable={true}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......
import BaseModel from '../../src/common/BaseModel';
import featuresService from '../../src/common/services/features.service';
describe('base model', () => {
beforeEach(() => {
});
it('should set and validate permissions', () => {
featuresService.features = {permissions: true};
const data = {
permissions: [
'permissions1',
'permissions2',
'permissions3',
]
}
const model = new BaseModel();
model.setPermissions(data);
// should validate permissions
expect(model.can('permissions1')).toBe(true);
expect(model.can('permissions2')).toBe(true);
expect(model.can('permissions3')).toBe(true);
expect(model.can('permissions4')).toBe(false);
});
});
\ No newline at end of file
......@@ -4,7 +4,6 @@ import { shallow } from 'enzyme';
import ExplicitOverlay from '../../../src/common/components/explicit/ExplicitOverlay';
import ActivityModel from '../../../src/newsfeed/ActivityModel';
import { activitiesServiceFaker } from '../../../__mocks__/fake/ActivitiesFaker';
jest.mock('TouchableOpacity', () => 'TouchableOpacity');
describe('Explicit overlay component', () => {
......
......@@ -3,7 +3,9 @@
exports[`renders correctly 1`] = `
<View
accessible={true}
focusable={false}
isTVSelectable={true}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
......@@ -17,6 +19,8 @@ exports[`renders correctly 1`] = `
"borderColor": "#4690D6",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
"justifyContent": "center",
"margin": 4,
"opacity": 1,
"padding": 4,
......
......@@ -22,16 +22,9 @@ exports[`Media view component renders correctly 1`] = `
<ExplicitImage
entity={
Object {
"_list": Object {
"viewed": Object {
"addViewed": [Function],
"viewed": Map {
"1019155171608096768" => true,
},
},
},
"attachment_guid": false,
"blurb": false,
"containerObj": undefined,
"container_guid": "activityguid0",
"custom_data": Array [
Object {
......@@ -45,7 +38,7 @@ exports[`Media view component renders correctly 1`] = `
"getThumbSource": [MockFunction] {
"calls": Array [
Array [
"large",
"xlarge",
],
],
"results": Array [
......@@ -61,7 +54,6 @@ exports[`Media view component renders correctly 1`] = `
"mature": false,
"message": "Message",
"ownerObj": Object {
"getAvatarSource": [Function],
"guid": "824853017709780997",
"subtype": false,
"time_created": "1522036284",
......
......@@ -14,6 +14,7 @@ describe('Boosted content service', () => {
const fakeBoosts = [{guid: 1}, {guid: 2}, {guid: 3}];
boostedContentService.feedsService.getEntities.mockResolvedValue(fakeBoosts);
boostedContentService.feedsService.fetchLocal.mockResolvedValue(true);
// load the boosts
await boostedContentService.load();
......@@ -22,7 +23,7 @@ describe('Boosted content service', () => {
expect(boostedContentService.feedsService.setEndpoint).toBeCalledWith('api/v2/boost/feed');
expect(boostedContentService.feedsService.setOffset).toBeCalledWith(0);
expect(boostedContentService.feedsService.setLimit).toBeCalledWith(12);
expect(boostedContentService.feedsService.fetchRemoteOrLocal).toBeCalled();
expect(boostedContentService.feedsService.fetchLocal).toBeCalled();
// should fetch the boosts entities
expect(boostedContentService.feedsService.getEntities).toBeCalled();
......
import {
CameraRoll,
Platform,
} from 'react-native';
import service from '../../../src/common/services/download.service';
import session from '../../../src/common/services/session.service';
import RNFetchBlob from 'react-native-fetch-blob';
import CameraRoll from '@react-native-community/cameraroll';
import permissions from '../../../src/common/services/android-permissions.service';
CameraRoll.saveToCameraRoll = jest.fn();
jest.mock('../../../src/common/services/android-permissions.service');
jest.mock('../../../src/common/services/session.service');
jest.mock('react-native-fetch-blob');
/**
* Tests
*/
......@@ -27,12 +24,12 @@ describe('Download service', () => {
await service.downloadToGallery('url');
expect(CameraRoll.saveToCameraRoll).not.toHaveBeenCalled();
});
it('should call camera roll', async () => {
// call tested method
Platform.OS = 'ios';
await service.downloadToGallery('url');
expect(CameraRoll.saveToCameraRoll).toHaveBeenCalled();
});
});
});
\ No newline at end of file
import 'react-native';
import React from 'react';
import { Text, TouchableOpacity } from "react-native";
import { shallow } from 'enzyme';
import ReferralCompleteView from '../../../../src/notifications/notification/view/ReferralCompleteView';
import styles from '../../../../src/notifications/notification/style';
// fake data generation
import boostNotificationFactory from '../../../../__mocks__/fake/notifications/BoostNotificationFactory';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const entity = boostNotificationFactory('referral_complete');
const notification = renderer.create(
<ReferralCompleteView styles={styles} entity={entity}/>
).toJSON();
expect(notification).toMatchSnapshot();
});
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.