├── README.md ├── integrationtests ├── .babelrc ├── .buckconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── __mocks__ │ └── redux-mock-store.js ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ └── fonts │ │ │ │ ├── Entypo.ttf │ │ │ │ ├── EvilIcons.ttf │ │ │ │ ├── FontAwesome.ttf │ │ │ │ ├── Foundation.ttf │ │ │ │ ├── Ionicons.ttf │ │ │ │ ├── MaterialCommunityIcons.ttf │ │ │ │ ├── MaterialIcons.ttf │ │ │ │ ├── Octicons.ttf │ │ │ │ ├── SimpleLineIcons.ttf │ │ │ │ └── Zocial.ttf │ │ │ ├── java │ │ │ └── com │ │ │ │ └── integrationtests │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle ├── app.json ├── e2e │ ├── firstTest.spec.js │ ├── init.js │ └── mocha.opts ├── index.android.js ├── index.ios.js ├── ios │ ├── integrationtests-tvOS │ │ └── Info.plist │ ├── integrationtests-tvOSTests │ │ └── Info.plist │ ├── integrationtests.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── integrationtests-tvOS.xcscheme │ │ │ └── integrationtests.xcscheme │ ├── integrationtests │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── integrationtestsTests │ │ ├── Info.plist │ │ └── integrationtestsTests.m ├── js │ ├── actions │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── league.js.snap │ │ │ │ ├── navigation.js.snap │ │ │ │ └── team.js.snap │ │ │ ├── league.js │ │ │ ├── navigation.js │ │ │ └── team.js │ │ ├── league.js │ │ ├── navigation.js │ │ ├── team.js │ │ └── types.js │ ├── api │ │ └── index.js │ ├── components │ │ ├── Header.js │ │ ├── LeagueComponent.js │ │ ├── TeamComponent.js │ │ ├── __tests__ │ │ │ ├── LeagueComponent.js │ │ │ └── __snapshots__ │ │ │ │ └── LeagueComponent.js.snap │ │ └── loaders │ │ │ └── Spinner.js │ ├── configureStore.js │ ├── db │ │ ├── helpers.js │ │ └── index.js │ ├── reducers │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── league.js.snap │ │ │ │ └── team.js.snap │ │ │ ├── league.js │ │ │ └── team.js │ │ ├── index.js │ │ ├── league.js │ │ ├── navigation.js │ │ └── team.js │ ├── router │ │ ├── drawer │ │ │ ├── CustomDrawerContent.js │ │ │ ├── DrawerNavigation.js │ │ │ └── navigationConfiguration.js │ │ └── stack │ │ │ ├── StackNavigation.js │ │ │ └── navigationConfiguration.js │ └── setup.js ├── package.json └── yarn.lock ├── react-navigation-with-redux ├── .DS_Store ├── .babelrc ├── .eslintrc ├── .gitignore ├── .watchmanconfig ├── assets │ └── icons │ │ ├── app.png │ │ └── loading.png ├── exp.json ├── js │ ├── .DS_Store │ ├── actions │ │ ├── navigation.js │ │ ├── team.js │ │ └── types.js │ ├── components │ │ ├── .DS_Store │ │ ├── Header.js │ │ ├── LeagueComponent.js │ │ ├── TeamComponent.js │ │ └── loaders │ │ │ └── Spinner.js │ ├── configureStore.js │ ├── db │ │ ├── helpers.js │ │ └── index.js │ ├── reducers │ │ ├── index.js │ │ ├── league.js │ │ ├── navigation.js │ │ └── team.js │ ├── router │ │ ├── drawer │ │ │ ├── DrawerNavigation.js │ │ │ └── navigationConfiguration.js │ │ └── stack │ │ │ ├── StackNavigation.js │ │ │ └── navigationConfiguration.js │ └── setup.js ├── main.js ├── package.json └── yarn.lock └── unit-testing-jest-enzyme ├── .DS_Store ├── .babelrc ├── .eslintrc ├── .gitignore ├── .watchmanconfig ├── __mocks__ └── redux-mock-store.js ├── assets └── icons │ ├── app.png │ └── loading.png ├── exp.json ├── js ├── .DS_Store ├── actions │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── league.js.snap │ │ │ ├── navigation.js.snap │ │ │ └── team.js.snap │ │ ├── league.js │ │ ├── navigation.js │ │ └── team.js │ ├── league.js │ ├── navigation.js │ ├── team.js │ └── types.js ├── api │ └── index.js ├── components │ ├── .DS_Store │ ├── Header.js │ ├── LeagueComponent.js │ ├── TeamComponent.js │ ├── __tests__ │ │ ├── .DS_Store │ │ ├── LeagueComponent.js │ │ └── __snapshots__ │ │ │ └── LeagueComponent.js.snap │ └── loaders │ │ └── Spinner.js ├── configureStore.js ├── db │ ├── helpers.js │ └── index.js ├── reducers │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── league.js.snap │ │ │ └── team.js.snap │ │ ├── league.js │ │ └── team.js │ ├── index.js │ ├── league.js │ ├── navigation.js │ └── team.js ├── router │ ├── drawer │ │ ├── CustomDrawerContent.js │ │ ├── DrawerNavigation.js │ │ └── navigationConfiguration.js │ └── stack │ │ ├── StackNavigation.js │ │ └── navigationConfiguration.js └── setup.js ├── main.js ├── package.json └── yarn.lock /README.md: -------------------------------------------------------------------------------- 1 | This is the host repository for a serie of tutorials about react-native! 2 | 3 | Check our blog to know more! https://blog.weareredlight.com/ 4 | 5 | Tutorial #1 - React-navigation with redux - https://blog.weareredlight.com/react-native-tutorial-1-e24a6f0c6faa 6 | 7 | Tutorial #2 - Testing redux apps with Jest/Enzyme - https://blog.weareredlight.com/react-native-tutorial-2-testing-redux-apps-with-jest-enzyme-bdf4a518f839 8 | 9 | Tutorial #3 - Integration and E2E tests with Detox - https://blog.weareredlight.com/react-native-tutorial-3-integration-and-e2e-tests-with-detox-f75fc758a655 10 | -------------------------------------------------------------------------------- /integrationtests/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } 4 | -------------------------------------------------------------------------------- /integrationtests/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /integrationtests/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | emoji=true 26 | 27 | module.system=haste 28 | 29 | experimental.strict_type_args=true 30 | 31 | munge_underscores=true 32 | 33 | 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' 34 | 35 | suppress_type=$FlowIssue 36 | suppress_type=$FlowFixMe 37 | suppress_type=$FixMe 38 | 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 40 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 41 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 42 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 43 | 44 | unsafe.enable_getters_and_setters=true 45 | 46 | [version] 47 | ^0.45.0 48 | -------------------------------------------------------------------------------- /integrationtests/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /integrationtests/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/Preview.html 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /integrationtests/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /integrationtests/__mocks__/redux-mock-store.js: -------------------------------------------------------------------------------- 1 | import configureMockStore from 'redux-mock-store'; 2 | import thunk from 'redux-thunk'; 3 | 4 | const middlewares = [thunk]; 5 | const mockStore = configureMockStore(middlewares); 6 | 7 | export default mockStore; 8 | -------------------------------------------------------------------------------- /integrationtests/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | lib_deps = [] 12 | 13 | for jarfile in glob(['libs/*.jar']): 14 | name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')] 15 | lib_deps.append(':' + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | 21 | for aarfile in glob(['libs/*.aar']): 22 | name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')] 23 | lib_deps.append(':' + name) 24 | android_prebuilt_aar( 25 | name = name, 26 | aar = aarfile, 27 | ) 28 | 29 | android_library( 30 | name = "all-libs", 31 | exported_deps = lib_deps, 32 | ) 33 | 34 | android_library( 35 | name = "app-code", 36 | srcs = glob([ 37 | "src/main/java/**/*.java", 38 | ]), 39 | deps = [ 40 | ":all-libs", 41 | ":build_config", 42 | ":res", 43 | ], 44 | ) 45 | 46 | android_build_config( 47 | name = "build_config", 48 | package = "com.integrationtests", 49 | ) 50 | 51 | android_resource( 52 | name = "res", 53 | package = "com.integrationtests", 54 | res = "src/main/res", 55 | ) 56 | 57 | android_binary( 58 | name = "app", 59 | keystore = "//android/keystores:debug", 60 | manifest = "src/main/AndroidManifest.xml", 61 | package_type = "debug", 62 | deps = [ 63 | ":app-code", 64 | ], 65 | ) 66 | -------------------------------------------------------------------------------- /integrationtests/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // whether to bundle JS and assets in debug mode 22 | * bundleInDebug: false, 23 | * 24 | * // whether to bundle JS and assets in release mode 25 | * bundleInRelease: true, 26 | * 27 | * // whether to bundle JS and assets in another build variant (if configured). 28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 29 | * // The configuration property can be in the following formats 30 | * // 'bundleIn${productFlavor}${buildType}' 31 | * // 'bundleIn${buildType}' 32 | * // bundleInFreeDebug: true, 33 | * // bundleInPaidRelease: true, 34 | * // bundleInBeta: true, 35 | * 36 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 37 | * // for example: to disable dev mode in the staging build type (if configured) 38 | * devDisabledInStaging: true, 39 | * // The configuration property can be in the following formats 40 | * // 'devDisabledIn${productFlavor}${buildType}' 41 | * // 'devDisabledIn${buildType}' 42 | * 43 | * // the root of your project, i.e. where "package.json" lives 44 | * root: "../../", 45 | * 46 | * // where to put the JS bundle asset in debug mode 47 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 48 | * 49 | * // where to put the JS bundle asset in release mode 50 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 51 | * 52 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 53 | * // require('./image.png')), in debug mode 54 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 55 | * 56 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 57 | * // require('./image.png')), in release mode 58 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 59 | * 60 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 61 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 62 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 63 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 64 | * // for example, you might want to remove it from here. 65 | * inputExcludes: ["android/**", "ios/**"], 66 | * 67 | * // override which node gets called and with what additional arguments 68 | * nodeExecutableAndArgs: ["node"], 69 | * 70 | * // supply additional arguments to the packager 71 | * extraPackagerArgs: [] 72 | * ] 73 | */ 74 | 75 | apply from: "../../node_modules/react-native/react.gradle" 76 | 77 | /** 78 | * Set this to true to create two separate APKs instead of one: 79 | * - An APK that only works on ARM devices 80 | * - An APK that only works on x86 devices 81 | * The advantage is the size of the APK is reduced by about 4MB. 82 | * Upload all the APKs to the Play Store and people will download 83 | * the correct one based on the CPU architecture of their device. 84 | */ 85 | def enableSeparateBuildPerCPUArchitecture = false 86 | 87 | /** 88 | * Run Proguard to shrink the Java bytecode in release builds. 89 | */ 90 | def enableProguardInReleaseBuilds = false 91 | 92 | android { 93 | compileSdkVersion 23 94 | buildToolsVersion "23.0.1" 95 | 96 | defaultConfig { 97 | applicationId "com.integrationtests" 98 | minSdkVersion 16 99 | targetSdkVersion 22 100 | versionCode 1 101 | versionName "1.0" 102 | ndk { 103 | abiFilters "armeabi-v7a", "x86" 104 | } 105 | } 106 | splits { 107 | abi { 108 | reset() 109 | enable enableSeparateBuildPerCPUArchitecture 110 | universalApk false // If true, also generate a universal APK 111 | include "armeabi-v7a", "x86" 112 | } 113 | } 114 | buildTypes { 115 | release { 116 | minifyEnabled enableProguardInReleaseBuilds 117 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 118 | } 119 | } 120 | // applicationVariants are e.g. debug, release 121 | applicationVariants.all { variant -> 122 | variant.outputs.each { output -> 123 | // For each separate APK per architecture, set a unique version code as described here: 124 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 125 | def versionCodes = ["armeabi-v7a":1, "x86":2] 126 | def abi = output.getFilter(OutputFile.ABI) 127 | if (abi != null) { // null for the universal-debug, universal-release variants 128 | output.versionCodeOverride = 129 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 130 | } 131 | } 132 | } 133 | } 134 | 135 | dependencies { 136 | compile project(':react-native-vector-icons') 137 | compile fileTree(dir: "libs", include: ["*.jar"]) 138 | compile "com.android.support:appcompat-v7:23.0.1" 139 | compile "com.facebook.react:react-native:+" // From node_modules 140 | } 141 | 142 | // Run this once to be able to run the application with BUCK 143 | // puts all compile dependencies into folder libs for BUCK to use 144 | task copyDownloadableDepsToLibs(type: Copy) { 145 | from configurations.compile 146 | into 'libs' 147 | } 148 | -------------------------------------------------------------------------------- /integrationtests/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # TextLayoutBuilder uses a non-public Android constructor within StaticLayout. 54 | # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details. 55 | -dontwarn android.text.StaticLayout 56 | 57 | # okhttp 58 | 59 | -keepattributes Signature 60 | -keepattributes *Annotation* 61 | -keep class okhttp3.** { *; } 62 | -keep interface okhttp3.** { *; } 63 | -dontwarn okhttp3.** 64 | 65 | # okio 66 | 67 | -keep class sun.misc.Unsafe { *; } 68 | -dontwarn java.nio.file.* 69 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 70 | -dontwarn okio.** 71 | -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/java/com/integrationtests/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.integrationtests; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "integrationtests"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/java/com/integrationtests/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.integrationtests; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.react.ReactApplication; 6 | import com.oblador.vectoricons.VectorIconsPackage; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.shell.MainReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class MainApplication extends Application implements ReactApplication { 16 | 17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | return Arrays.asList( 26 | new MainReactPackage(), 27 | new VectorIconsPackage() 28 | ); 29 | } 30 | }; 31 | 32 | @Override 33 | public ReactNativeHost getReactNativeHost() { 34 | return mReactNativeHost; 35 | } 36 | 37 | @Override 38 | public void onCreate() { 39 | super.onCreate(); 40 | SoLoader.init(this, /* native exopackage */ false); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | integrationtests 3 | 4 | -------------------------------------------------------------------------------- /integrationtests/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /integrationtests/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$rootDir/../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /integrationtests/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /integrationtests/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/integrationtests/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /integrationtests/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 6 | -------------------------------------------------------------------------------- /integrationtests/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /integrationtests/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /integrationtests/android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = "debug", 3 | properties = "debug.keystore.properties", 4 | store = "debug.keystore", 5 | visibility = [ 6 | "PUBLIC", 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /integrationtests/android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /integrationtests/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'integrationtests' 2 | include ':react-native-vector-icons' 3 | project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') 4 | 5 | include ':app' 6 | -------------------------------------------------------------------------------- /integrationtests/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integrationtests", 3 | "displayName": "integrationtests" 4 | } -------------------------------------------------------------------------------- /integrationtests/e2e/firstTest.spec.js: -------------------------------------------------------------------------------- 1 | // Integration test 2 | describe('Header', () => { 3 | beforeEach(async () => { 4 | await device.reloadReactNative(); 5 | }); 6 | 7 | it('should render Header', async () => { 8 | await expect(element(by.id('Header'))).toBeVisible(); 9 | await expect(element(by.id('Header.Menu'))).toBeVisible(); 10 | await expect(element(by.id('Header.Title'))).toBeVisible(); 11 | await expect(element(by.id('DrawerItems'))).toBeNotVisible(); 12 | }); 13 | 14 | it('should open drawer', async () => { 15 | await element(by.id('Header.Menu')).tap(); 16 | await waitFor(element(by.id('DrawerItems'))).toBeVisible().withTimeout(2000); 17 | await expect(element(by.text('PremierLeague'))).toBeVisible(); 18 | await expect(element(by.text('LaLiga'))).toBeVisible(); 19 | await expect(element(by.text('SerieA'))).toBeVisible(); 20 | }); 21 | }) 22 | 23 | // E2E test 24 | const teams = [ 25 | { league: 'PremierLeague', team: 'Arsenal' }, 26 | { league: 'LaLiga', team: 'Barcelona' }, 27 | { league: 'SerieA', team: 'Milan' }, 28 | ]; 29 | 30 | for (let i = 0; i < teams.length; i += 1) { 31 | const league = teams[i].league; 32 | const team = teams[i].team; 33 | 34 | describe(`${team} - ${league}`, () => { 35 | beforeEach(async () => { 36 | await device.reloadReactNative(); 37 | }); 38 | 39 | it('should render team matches screen', async () => { 40 | await element(by.id('Header.Menu')).tap(); 41 | await waitFor(element(by.id('DrawerItems'))).toBeVisible().withTimeout(2000); 42 | await element(by.text(league)).tap(); 43 | await waitFor(element(by.text(team))).toBeVisible().withTimeout(2000); 44 | await element(by.id(`Team.${team}`)).tap(); 45 | await waitFor(element(by.id('TeamMatches'))).toBeVisible().withTimeout(5000); 46 | await expect(element(by.id('Header')).atIndex(0)).toBeVisible(); 47 | await expect(element(by.id('Header.Title')).atIndex(0)).toHaveText(team); 48 | }); 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /integrationtests/e2e/init.js: -------------------------------------------------------------------------------- 1 | require('babel-polyfill'); 2 | const detox = require('detox'); 3 | const config = require('../package.json').detox; 4 | 5 | before(async () => { 6 | await detox.init(config); 7 | }); 8 | 9 | after(async () => { 10 | await detox.cleanup(); 11 | }); -------------------------------------------------------------------------------- /integrationtests/e2e/mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive --timeout 120000 --bail -------------------------------------------------------------------------------- /integrationtests/index.android.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import setup from './js/setup'; 3 | import { AppRegistry } from 'react-native'; 4 | 5 | AppRegistry.registerComponent('integrationtests', () => setup); 6 | -------------------------------------------------------------------------------- /integrationtests/index.ios.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import setup from './js/setup'; 3 | import { AppRegistry } from 'react-native'; 4 | 5 | AppRegistry.registerComponent('integrationtests', () => setup); 6 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSExceptionDomains 45 | 46 | localhost 47 | 48 | NSExceptionAllowsInsecureHTTPLoads 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests.xcodeproj/xcshareddata/xcschemes/integrationtests-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests.xcodeproj/xcshareddata/xcschemes/integrationtests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | NSURL *jsCodeLocation; 20 | 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | 23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 24 | moduleName:@"integrationtests" 25 | initialProperties:nil 26 | launchOptions:launchOptions]; 27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | UIViewController *rootViewController = [UIViewController new]; 31 | rootViewController.view = rootView; 32 | self.window.rootViewController = rootViewController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | integrationtests 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | NSLocationWhenInUseUsageDescription 42 | 43 | NSAppTransportSecurity 44 | 45 | NSExceptionDomains 46 | 47 | localhost 48 | 49 | NSExceptionAllowsInsecureHTTPLoads 50 | 51 | 52 | 53 | 54 | UIAppFonts 55 | 56 | Entypo.ttf 57 | EvilIcons.ttf 58 | FontAwesome.ttf 59 | Foundation.ttf 60 | Ionicons.ttf 61 | MaterialCommunityIcons.ttf 62 | MaterialIcons.ttf 63 | Octicons.ttf 64 | SimpleLineIcons.ttf 65 | Zocial.ttf 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtests/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtestsTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /integrationtests/ios/integrationtestsTests/integrationtestsTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface integrationtestsTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation integrationtestsTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/__snapshots__/league.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_LEAGUE (LaLiga) 1`] = ` 4 | Array [ 5 | Object { 6 | "payload": Object { 7 | "teams": Object { 8 | "clubs": Array [ 9 | Object { 10 | "code": "BAR", 11 | "key": "barcelona", 12 | "name": "Barcelona", 13 | }, 14 | Object { 15 | "code": "ESP", 16 | "key": "espanyol", 17 | "name": "Espanyol", 18 | }, 19 | Object { 20 | "code": "RMD", 21 | "key": "madrid", 22 | "name": "R. Madrid", 23 | }, 24 | Object { 25 | "code": "ATL", 26 | "key": "atletico", 27 | "name": "Atlético", 28 | }, 29 | Object { 30 | "code": "SEV", 31 | "key": "sevilla", 32 | "name": "Sevilla", 33 | }, 34 | Object { 35 | "code": "VAL", 36 | "key": "valencia", 37 | "name": "Valencia", 38 | }, 39 | Object { 40 | "code": "MAG", 41 | "key": "malaga", 42 | "name": "Málaga", 43 | }, 44 | Object { 45 | "code": "ATH", 46 | "key": "athletic", 47 | "name": "Athletic", 48 | }, 49 | Object { 50 | "code": "GRA", 51 | "key": "granada", 52 | "name": "Granada", 53 | }, 54 | Object { 55 | "code": "CEL", 56 | "key": "celta", 57 | "name": "Celta", 58 | }, 59 | Object { 60 | "code": "RSO", 61 | "key": "realsociedad", 62 | "name": "R. Sociedad", 63 | }, 64 | Object { 65 | "code": "DEP", 66 | "key": "deportivo", 67 | "name": "Deportivo", 68 | }, 69 | Object { 70 | "code": null, 71 | "key": "eibar", 72 | "name": "Eibar", 73 | }, 74 | Object { 75 | "code": "BET", 76 | "key": "betis", 77 | "name": "Betis", 78 | }, 79 | Object { 80 | "code": null, 81 | "key": "sporting", 82 | "name": "Sporting", 83 | }, 84 | Object { 85 | "code": null, 86 | "key": "laspalmas", 87 | "name": "Las Palmas", 88 | }, 89 | Object { 90 | "code": "OSA", 91 | "key": "osasuna", 92 | "name": "Osasuna", 93 | }, 94 | Object { 95 | "code": "VLL", 96 | "key": "villareal", 97 | "name": "Villarreal CF", 98 | }, 99 | Object { 100 | "code": null, 101 | "key": "alaves", 102 | "name": "Alavés", 103 | }, 104 | Object { 105 | "code": null, 106 | "key": "leganes", 107 | "name": "Club Deportivo Leganés", 108 | }, 109 | ], 110 | "name": "Primera División 2016/17", 111 | "routeName": "LaLiga", 112 | }, 113 | }, 114 | "type": "GET_LEAGUE", 115 | }, 116 | ] 117 | `; 118 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/__snapshots__/navigation.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`BACK 1`] = ` 4 | Array [ 5 | Object { 6 | "type": "BACK", 7 | }, 8 | ] 9 | `; 10 | 11 | exports[`TOGGLE_DRAWER 1`] = ` 12 | Array [ 13 | Object { 14 | "type": "TOGGLE_DRAWER", 15 | }, 16 | ] 17 | `; 18 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/__snapshots__/team.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_TEAM (Barcelona) 1`] = ` 4 | Array [ 5 | Object { 6 | "payload": Object { 7 | "currentTeam": "Barcelona", 8 | "image": "STRING_URL", 9 | "matches": Array [ 10 | Object { 11 | "date": "2016-08-20", 12 | "score1": 6, 13 | "score2": 2, 14 | "team1": Object { 15 | "code": "BAR", 16 | "key": "barcelona", 17 | "name": "Barcelona", 18 | }, 19 | "team2": Object { 20 | "code": "BET", 21 | "key": "betis", 22 | "name": "Betis", 23 | }, 24 | }, 25 | Object { 26 | "date": "2016-08-28", 27 | "score1": 0, 28 | "score2": 1, 29 | "team1": Object { 30 | "code": "ATH", 31 | "key": "athletic", 32 | "name": "Athletic", 33 | }, 34 | "team2": Object { 35 | "code": "BAR", 36 | "key": "barcelona", 37 | "name": "Barcelona", 38 | }, 39 | }, 40 | Object { 41 | "date": "2016-09-10", 42 | "score1": 1, 43 | "score2": 2, 44 | "team1": Object { 45 | "code": "BAR", 46 | "key": "barcelona", 47 | "name": "Barcelona", 48 | }, 49 | "team2": Object { 50 | "code": null, 51 | "key": "alaves", 52 | "name": "Alavés", 53 | }, 54 | }, 55 | Object { 56 | "date": "2016-09-17", 57 | "score1": 1, 58 | "score2": 5, 59 | "team1": Object { 60 | "code": null, 61 | "key": "leganes", 62 | "name": "Club Deportivo Leganés", 63 | }, 64 | "team2": Object { 65 | "code": "BAR", 66 | "key": "barcelona", 67 | "name": "Barcelona", 68 | }, 69 | }, 70 | Object { 71 | "date": "2016-09-21", 72 | "score1": 1, 73 | "score2": 1, 74 | "team1": Object { 75 | "code": "BAR", 76 | "key": "barcelona", 77 | "name": "Barcelona", 78 | }, 79 | "team2": Object { 80 | "code": "ATL", 81 | "key": "atletico", 82 | "name": "Atlético", 83 | }, 84 | }, 85 | Object { 86 | "date": "2016-09-24", 87 | "score1": 0, 88 | "score2": 5, 89 | "team1": Object { 90 | "code": null, 91 | "key": "sporting", 92 | "name": "Sporting", 93 | }, 94 | "team2": Object { 95 | "code": "BAR", 96 | "key": "barcelona", 97 | "name": "Barcelona", 98 | }, 99 | }, 100 | Object { 101 | "date": "2016-10-02", 102 | "score1": 4, 103 | "score2": 3, 104 | "team1": Object { 105 | "code": "CEL", 106 | "key": "celta", 107 | "name": "Celta", 108 | }, 109 | "team2": Object { 110 | "code": "BAR", 111 | "key": "barcelona", 112 | "name": "Barcelona", 113 | }, 114 | }, 115 | Object { 116 | "date": "2016-10-15", 117 | "score1": null, 118 | "score2": null, 119 | "team1": Object { 120 | "code": "BAR", 121 | "key": "barcelona", 122 | "name": "Barcelona", 123 | }, 124 | "team2": Object { 125 | "code": "DEP", 126 | "key": "deportivo", 127 | "name": "Deportivo", 128 | }, 129 | }, 130 | Object { 131 | "date": "2016-10-23", 132 | "score1": null, 133 | "score2": null, 134 | "team1": Object { 135 | "code": "VAL", 136 | "key": "valencia", 137 | "name": "Valencia", 138 | }, 139 | "team2": Object { 140 | "code": "BAR", 141 | "key": "barcelona", 142 | "name": "Barcelona", 143 | }, 144 | }, 145 | Object { 146 | "date": "2016-10-30", 147 | "score1": null, 148 | "score2": null, 149 | "team1": Object { 150 | "code": "BAR", 151 | "key": "barcelona", 152 | "name": "Barcelona", 153 | }, 154 | "team2": Object { 155 | "code": "GRA", 156 | "key": "granada", 157 | "name": "Granada", 158 | }, 159 | }, 160 | Object { 161 | "date": "2016-11-06", 162 | "score1": null, 163 | "score2": null, 164 | "team1": Object { 165 | "code": "SEV", 166 | "key": "sevilla", 167 | "name": "Sevilla", 168 | }, 169 | "team2": Object { 170 | "code": "BAR", 171 | "key": "barcelona", 172 | "name": "Barcelona", 173 | }, 174 | }, 175 | Object { 176 | "date": "2016-11-20", 177 | "score1": null, 178 | "score2": null, 179 | "team1": Object { 180 | "code": "BAR", 181 | "key": "barcelona", 182 | "name": "Barcelona", 183 | }, 184 | "team2": Object { 185 | "code": "MAG", 186 | "key": "malaga", 187 | "name": "Málaga", 188 | }, 189 | }, 190 | Object { 191 | "date": "2016-11-27", 192 | "score1": null, 193 | "score2": null, 194 | "team1": Object { 195 | "code": "RSO", 196 | "key": "realsociedad", 197 | "name": "R. Sociedad", 198 | }, 199 | "team2": Object { 200 | "code": "BAR", 201 | "key": "barcelona", 202 | "name": "Barcelona", 203 | }, 204 | }, 205 | Object { 206 | "date": "2016-12-04", 207 | "score1": null, 208 | "score2": null, 209 | "team1": Object { 210 | "code": "BAR", 211 | "key": "barcelona", 212 | "name": "Barcelona", 213 | }, 214 | "team2": Object { 215 | "code": "RMD", 216 | "key": "madrid", 217 | "name": "R. Madrid", 218 | }, 219 | }, 220 | Object { 221 | "date": "2016-12-11", 222 | "score1": null, 223 | "score2": null, 224 | "team1": Object { 225 | "code": "OSA", 226 | "key": "osasuna", 227 | "name": "Osasuna", 228 | }, 229 | "team2": Object { 230 | "code": "BAR", 231 | "key": "barcelona", 232 | "name": "Barcelona", 233 | }, 234 | }, 235 | Object { 236 | "date": "2016-12-18", 237 | "score1": null, 238 | "score2": null, 239 | "team1": Object { 240 | "code": "BAR", 241 | "key": "barcelona", 242 | "name": "Barcelona", 243 | }, 244 | "team2": Object { 245 | "code": "ESP", 246 | "key": "espanyol", 247 | "name": "Espanyol", 248 | }, 249 | }, 250 | Object { 251 | "date": "2017-01-08", 252 | "score1": null, 253 | "score2": null, 254 | "team1": Object { 255 | "code": "VLL", 256 | "key": "villareal", 257 | "name": "Villarreal CF", 258 | }, 259 | "team2": Object { 260 | "code": "BAR", 261 | "key": "barcelona", 262 | "name": "Barcelona", 263 | }, 264 | }, 265 | Object { 266 | "date": "2017-01-15", 267 | "score1": null, 268 | "score2": null, 269 | "team1": Object { 270 | "code": "BAR", 271 | "key": "barcelona", 272 | "name": "Barcelona", 273 | }, 274 | "team2": Object { 275 | "code": null, 276 | "key": "laspalmas", 277 | "name": "Las Palmas", 278 | }, 279 | }, 280 | Object { 281 | "date": "2017-01-22", 282 | "score1": null, 283 | "score2": null, 284 | "team1": Object { 285 | "code": null, 286 | "key": "eibar", 287 | "name": "Eibar", 288 | }, 289 | "team2": Object { 290 | "code": "BAR", 291 | "key": "barcelona", 292 | "name": "Barcelona", 293 | }, 294 | }, 295 | Object { 296 | "date": "2017-01-29", 297 | "score1": null, 298 | "score2": null, 299 | "team1": Object { 300 | "code": "BET", 301 | "key": "betis", 302 | "name": "Betis", 303 | }, 304 | "team2": Object { 305 | "code": "BAR", 306 | "key": "barcelona", 307 | "name": "Barcelona", 308 | }, 309 | }, 310 | Object { 311 | "date": "2017-02-05", 312 | "score1": null, 313 | "score2": null, 314 | "team1": Object { 315 | "code": "BAR", 316 | "key": "barcelona", 317 | "name": "Barcelona", 318 | }, 319 | "team2": Object { 320 | "code": "ATH", 321 | "key": "athletic", 322 | "name": "Athletic", 323 | }, 324 | }, 325 | Object { 326 | "date": "2017-02-12", 327 | "score1": null, 328 | "score2": null, 329 | "team1": Object { 330 | "code": null, 331 | "key": "alaves", 332 | "name": "Alavés", 333 | }, 334 | "team2": Object { 335 | "code": "BAR", 336 | "key": "barcelona", 337 | "name": "Barcelona", 338 | }, 339 | }, 340 | Object { 341 | "date": "2017-02-19", 342 | "score1": null, 343 | "score2": null, 344 | "team1": Object { 345 | "code": "BAR", 346 | "key": "barcelona", 347 | "name": "Barcelona", 348 | }, 349 | "team2": Object { 350 | "code": null, 351 | "key": "leganes", 352 | "name": "Club Deportivo Leganés", 353 | }, 354 | }, 355 | Object { 356 | "date": "2017-02-26", 357 | "score1": null, 358 | "score2": null, 359 | "team1": Object { 360 | "code": "ATL", 361 | "key": "atletico", 362 | "name": "Atlético", 363 | }, 364 | "team2": Object { 365 | "code": "BAR", 366 | "key": "barcelona", 367 | "name": "Barcelona", 368 | }, 369 | }, 370 | Object { 371 | "date": "2017-03-01", 372 | "score1": null, 373 | "score2": null, 374 | "team1": Object { 375 | "code": "BAR", 376 | "key": "barcelona", 377 | "name": "Barcelona", 378 | }, 379 | "team2": Object { 380 | "code": null, 381 | "key": "sporting", 382 | "name": "Sporting", 383 | }, 384 | }, 385 | Object { 386 | "date": "2017-03-05", 387 | "score1": null, 388 | "score2": null, 389 | "team1": Object { 390 | "code": "BAR", 391 | "key": "barcelona", 392 | "name": "Barcelona", 393 | }, 394 | "team2": Object { 395 | "code": "CEL", 396 | "key": "celta", 397 | "name": "Celta", 398 | }, 399 | }, 400 | Object { 401 | "date": "2017-03-12", 402 | "score1": null, 403 | "score2": null, 404 | "team1": Object { 405 | "code": "DEP", 406 | "key": "deportivo", 407 | "name": "Deportivo", 408 | }, 409 | "team2": Object { 410 | "code": "BAR", 411 | "key": "barcelona", 412 | "name": "Barcelona", 413 | }, 414 | }, 415 | Object { 416 | "date": "2017-03-19", 417 | "score1": null, 418 | "score2": null, 419 | "team1": Object { 420 | "code": "BAR", 421 | "key": "barcelona", 422 | "name": "Barcelona", 423 | }, 424 | "team2": Object { 425 | "code": "VAL", 426 | "key": "valencia", 427 | "name": "Valencia", 428 | }, 429 | }, 430 | Object { 431 | "date": "2017-04-02", 432 | "score1": null, 433 | "score2": null, 434 | "team1": Object { 435 | "code": "GRA", 436 | "key": "granada", 437 | "name": "Granada", 438 | }, 439 | "team2": Object { 440 | "code": "BAR", 441 | "key": "barcelona", 442 | "name": "Barcelona", 443 | }, 444 | }, 445 | Object { 446 | "date": "2017-04-05", 447 | "score1": null, 448 | "score2": null, 449 | "team1": Object { 450 | "code": "BAR", 451 | "key": "barcelona", 452 | "name": "Barcelona", 453 | }, 454 | "team2": Object { 455 | "code": "SEV", 456 | "key": "sevilla", 457 | "name": "Sevilla", 458 | }, 459 | }, 460 | Object { 461 | "date": "2017-04-09", 462 | "score1": null, 463 | "score2": null, 464 | "team1": Object { 465 | "code": "MAG", 466 | "key": "malaga", 467 | "name": "Málaga", 468 | }, 469 | "team2": Object { 470 | "code": "BAR", 471 | "key": "barcelona", 472 | "name": "Barcelona", 473 | }, 474 | }, 475 | Object { 476 | "date": "2017-04-16", 477 | "score1": null, 478 | "score2": null, 479 | "team1": Object { 480 | "code": "BAR", 481 | "key": "barcelona", 482 | "name": "Barcelona", 483 | }, 484 | "team2": Object { 485 | "code": "RSO", 486 | "key": "realsociedad", 487 | "name": "R. Sociedad", 488 | }, 489 | }, 490 | Object { 491 | "date": "2017-04-23", 492 | "score1": null, 493 | "score2": null, 494 | "team1": Object { 495 | "code": "RMD", 496 | "key": "madrid", 497 | "name": "R. Madrid", 498 | }, 499 | "team2": Object { 500 | "code": "BAR", 501 | "key": "barcelona", 502 | "name": "Barcelona", 503 | }, 504 | }, 505 | Object { 506 | "date": "2017-04-26", 507 | "score1": null, 508 | "score2": null, 509 | "team1": Object { 510 | "code": "BAR", 511 | "key": "barcelona", 512 | "name": "Barcelona", 513 | }, 514 | "team2": Object { 515 | "code": "OSA", 516 | "key": "osasuna", 517 | "name": "Osasuna", 518 | }, 519 | }, 520 | Object { 521 | "date": "2017-04-30", 522 | "score1": null, 523 | "score2": null, 524 | "team1": Object { 525 | "code": "ESP", 526 | "key": "espanyol", 527 | "name": "Espanyol", 528 | }, 529 | "team2": Object { 530 | "code": "BAR", 531 | "key": "barcelona", 532 | "name": "Barcelona", 533 | }, 534 | }, 535 | Object { 536 | "date": "2017-05-07", 537 | "score1": null, 538 | "score2": null, 539 | "team1": Object { 540 | "code": "BAR", 541 | "key": "barcelona", 542 | "name": "Barcelona", 543 | }, 544 | "team2": Object { 545 | "code": "VLL", 546 | "key": "villareal", 547 | "name": "Villarreal CF", 548 | }, 549 | }, 550 | Object { 551 | "date": "2017-05-14", 552 | "score1": null, 553 | "score2": null, 554 | "team1": Object { 555 | "code": null, 556 | "key": "laspalmas", 557 | "name": "Las Palmas", 558 | }, 559 | "team2": Object { 560 | "code": "BAR", 561 | "key": "barcelona", 562 | "name": "Barcelona", 563 | }, 564 | }, 565 | Object { 566 | "date": "2017-05-21", 567 | "score1": null, 568 | "score2": null, 569 | "team1": Object { 570 | "code": "BAR", 571 | "key": "barcelona", 572 | "name": "Barcelona", 573 | }, 574 | "team2": Object { 575 | "code": null, 576 | "key": "eibar", 577 | "name": "Eibar", 578 | }, 579 | }, 580 | ], 581 | }, 582 | "type": "GET_TEAM", 583 | }, 584 | ] 585 | `; 586 | 587 | exports[`GET_TEAM (null) 1`] = `Array []`; 588 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/league.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../league'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | it('GET_LEAGUE (LaLiga)', () => { 11 | store.dispatch(actions.getLeague('LaLiga')); 12 | expect(store.getActions()).toMatchSnapshot(); 13 | }); 14 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/navigation.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../navigation'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | it('BACK', () => { 11 | store.dispatch(actions.back()); 12 | expect(store.getActions()).toMatchSnapshot(); 13 | }); 14 | 15 | it('TOGGLE_DRAWER', () => { 16 | store.dispatch(actions.toggleDrawer()); 17 | expect(store.getActions()).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /integrationtests/js/actions/__tests__/team.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../team'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | global.fetch = jest.fn().mockImplementation(() => Promise.resolve({ 11 | json: () => ({ 12 | Image: 'STRING_URL', 13 | }), 14 | })); 15 | 16 | it('GET_TEAM (Barcelona)', async () => { 17 | await store.dispatch(actions.getTeam('LaLiga', 'Barcelona')); 18 | expect(store.getActions()).toMatchSnapshot(); 19 | }); 20 | 21 | it('GET_TEAM (null)', () => { 22 | store.dispatch(actions.getTeam(null, null)); 23 | expect(store.getActions()).toMatchSnapshot(); 24 | }); 25 | -------------------------------------------------------------------------------- /integrationtests/js/actions/league.js: -------------------------------------------------------------------------------- 1 | import { GET_LEAGUE } from './types'; 2 | import { getTeams } from '../db/helpers'; 3 | 4 | export function getLeague(currentLeagueRoute) { 5 | const teams = getTeams(currentLeagueRoute); 6 | 7 | return { 8 | type: GET_LEAGUE, 9 | payload: { teams }, 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /integrationtests/js/actions/navigation.js: -------------------------------------------------------------------------------- 1 | import { BACK, TOGGLE_DRAWER } from './types'; 2 | 3 | export function back() { 4 | return { type: BACK }; 5 | } 6 | 7 | export function toggleDrawer() { 8 | return { type: TOGGLE_DRAWER }; 9 | } 10 | -------------------------------------------------------------------------------- /integrationtests/js/actions/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './types'; 2 | import { getMatches } from '../db/helpers'; 3 | import { getTeamLogo } from '../api'; 4 | 5 | function teamAction(currentLeague, currentTeam, image) { 6 | const matches = getMatches(currentLeague, currentTeam); 7 | return { type: GET_TEAM, payload: { matches, currentTeam, image } }; 8 | } 9 | 10 | export function getTeam(currentLeague, currentTeam) { 11 | return dispatch => getTeamLogo(currentTeam) 12 | .then(response => response.json()) 13 | .then(response => dispatch(teamAction(currentLeague, currentTeam, response.Image))) 14 | .catch(() => dispatch(teamAction(currentLeague, currentTeam, null))) 15 | ; 16 | } 17 | -------------------------------------------------------------------------------- /integrationtests/js/actions/types.js: -------------------------------------------------------------------------------- 1 | // league 2 | export const GET_LEAGUE = 'GET_LEAGUE'; 3 | 4 | // match 5 | export const GET_TEAM = 'GET_TEAM'; 6 | 7 | // navigation 8 | export const TOGGLE_DRAWER = 'TOGGLE_DRAWER'; 9 | export const BACK = 'BACK'; 10 | -------------------------------------------------------------------------------- /integrationtests/js/api/index.js: -------------------------------------------------------------------------------- 1 | export function getTeamLogo(currentTeam) { 2 | return fetch(`http://api.duckduckgo.com/?q=${currentTeam}&format=json`); 3 | } 4 | -------------------------------------------------------------------------------- /integrationtests/js/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import Icon from 'react-native-vector-icons/Ionicons'; 3 | import { connect } from 'react-redux'; 4 | import { View, Text, Image, StyleSheet } from 'react-native'; 5 | import { back, toggleDrawer } from '../actions/navigation'; 6 | 7 | const Header = ({ back, toggleDrawer, navigation, title, image }) => { 8 | const firstRoute = navigation.routes[navigation.index].routeName === 'LeagueScreen'; 9 | const name = firstRoute ? 'ios-menu' : 'ios-arrow-round-back'; 10 | const cb = firstRoute ? toggleDrawer : back; 11 | 12 | return ( 13 | 14 | 15 | { image !== null && image.length > 0 && 19 | } 20 | {title} 21 | 22 | 23 | 24 | ); 25 | }; 26 | 27 | Header.propTypes = { 28 | back: PropTypes.func.isRequired, 29 | toggleDrawer: PropTypes.func.isRequired, 30 | navigation: PropTypes.shape().isRequired, 31 | title: PropTypes.string.isRequired, 32 | image: PropTypes.string, 33 | }; 34 | 35 | const styles = StyleSheet.create({ 36 | container: { 37 | paddingTop: 25, 38 | paddingHorizontal: 12, 39 | flexDirection: 'row', 40 | justifyContent: 'space-between', 41 | alignItems: 'center', 42 | backgroundColor: '#69D8BB', 43 | }, 44 | content: { 45 | flexDirection: 'row', 46 | alignItems: 'center', 47 | justifyContent: 'center', 48 | }, 49 | text: { 50 | fontWeight: 'bold', 51 | color: 'white', 52 | }, 53 | image: { 54 | marginRight: 8, 55 | width: 16, 56 | height: 16, 57 | }, 58 | }); 59 | 60 | const mapStateToProps = state => ({ navigation: state.stack }); 61 | export default connect(mapStateToProps, { back, toggleDrawer })(Header); 62 | -------------------------------------------------------------------------------- /integrationtests/js/components/LeagueComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, TouchableOpacity, StatusBar } from 'react-native'; 4 | import Icon from 'react-native-vector-icons/Ionicons'; 5 | import Header from '../components/Header'; 6 | import { getTeam } from '../actions/team'; 7 | 8 | class LeagueComponent extends Component { 9 | 10 | static propTypes = { 11 | league: PropTypes.shape().isRequired, 12 | getTeam: PropTypes.func.isRequired, 13 | } 14 | 15 | renderTeam = ({ item, index }) => ( 16 | this.props.getTeam(this.props.league.routeName, item.name)} 20 | > 21 | 22 | {item.name} 23 | 24 | 25 | 26 | ); 27 | 28 | render() { 29 | const { league } = this.props; 30 | const { renderTeam } = this; 31 | 32 | return ( 33 | 34 | 35 |
36 | 40 | 41 | ); 42 | } 43 | } 44 | 45 | const styles = { 46 | itemContainer: { 47 | flexDirection: 'row', 48 | justifyContent: 'space-between', 49 | alignItems: 'center', 50 | paddingHorizontal: 16, 51 | paddingVertical: 10, 52 | flex: 1, 53 | }, 54 | container: { 55 | flex: 1, 56 | }, 57 | }; 58 | 59 | const mapStateToProps = ({ league }) => ({ league: league.teams }); 60 | export default connect(mapStateToProps, { getTeam })(LeagueComponent); 61 | -------------------------------------------------------------------------------- /integrationtests/js/components/TeamComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, StatusBar, StyleSheet } from 'react-native'; 4 | import Header from '../components/Header'; 5 | 6 | 7 | class TeamComponent extends Component { 8 | 9 | static propTypes = { 10 | team: PropTypes.string.isRequired, 11 | matches: PropTypes.arrayOf(PropTypes.shape()).isRequired, 12 | image: PropTypes.string, 13 | } 14 | 15 | renderMatch = ({ item }) => ( 16 | 17 | 18 | {getTeamName(item.team1.name)} 19 | 20 | 21 | {getDate(item.date)} 22 | 23 | 24 | {getTeamName(item.team2.name)} 25 | 26 | 27 | ); 28 | 29 | render() { 30 | const { team, matches, image } = this.props; 31 | const { renderMatch } = this; 32 | 33 | return ( 34 | 35 | 36 |
37 | index} 41 | /> 42 | 43 | ); 44 | } 45 | } 46 | 47 | const getTeamName = name => name.length > 15 ? `${name.substring(0, 15)}...` : name; 48 | const getDate = date => `${date.split('-')[2]}/${date.split('-')[1]}`; 49 | 50 | const styles = StyleSheet.create({ 51 | screen: { 52 | backgroundColor: 'white', 53 | flex: 1, 54 | }, 55 | home: { 56 | marginRight: 4, 57 | }, 58 | away: { 59 | marginLeft: 4, 60 | }, 61 | container: { 62 | marginBottom: 4, 63 | backgroundColor: 'white', 64 | flexDirection: 'row', 65 | }, 66 | textWrapper: { 67 | backgroundColor: '#F4F3F3', 68 | flex: 0.4, 69 | paddingLeft: 12, 70 | paddingVertical: 12, 71 | }, 72 | dateWrapper: { 73 | flex: 0.2, 74 | backgroundColor: '#69D8BB', 75 | justifyContent: 'center', 76 | alignItems: 'center', 77 | }, 78 | date: { 79 | fontSize: 10, 80 | fontWeight: 'bold', 81 | color: 'white', 82 | }, 83 | }); 84 | 85 | const mapStateToProps = state => ({ 86 | team: state.team.currentTeam, 87 | matches: state.team.matches, 88 | image: state.team.image, 89 | }); 90 | export default connect(mapStateToProps)(TeamComponent); 91 | -------------------------------------------------------------------------------- /integrationtests/js/components/__tests__/LeagueComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import toJson from 'enzyme-to-json'; 4 | import mockStore from 'redux-mock-store'; 5 | import { FlatList } from 'react-native'; 6 | import { expect as expectChai } from 'chai'; 7 | import LeagueComponent from '../LeagueComponent'; 8 | 9 | // eslint-disable-next-line 10 | const league = {"name":"English Premier League 2016/17","routeName":"PremierLeague","clubs":[{"key":"chelsea","name":"Chelsea","code":"CHE"},{"key":"arsenal","name":"Arsenal","code":"ARS"},{"key":"tottenham","name":"Tottenham Hotspur","code":"TOT"},{"key":"westham","name":"West Ham United","code":"WHU"},{"key":"crystalpalace","name":"Crystal Palace","code":"CRY"},{"key":"manutd","name":"Manchester United","code":"MUN"},{"key":"mancity","name":"Manchester City","code":"MCI"},{"key":"everton","name":"Everton","code":"EVE"},{"key":"liverpool","name":"Liverpool","code":"LIV"},{"key":"westbrom","name":"West Bromwich Albion","code":"WBA"},{"key":"stoke","name":"Stoke City","code":"STK"},{"key":"sunderland","name":"Sunderland","code":"SUN"},{"key":"southampton","name":"Southampton","code":"SOU"}]}; 11 | 12 | it('renders all children', () => { 13 | const initialState = { league: { teams: league } }; 14 | const store = mockStore(initialState); 15 | 16 | const wrapper = shallow(); 17 | 18 | const component = shallow(wrapper.getNodes()[0]); 19 | 20 | expectChai(component.find(FlatList).length).to.equal(1); 21 | expectChai(component.find(FlatList).at(0).props().data.length).to.equal(league.clubs.length); 22 | expect(toJson(component)).toMatchSnapshot(); 23 | }); 24 | -------------------------------------------------------------------------------- /integrationtests/js/components/__tests__/__snapshots__/LeagueComponent.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders all children 1`] = ` 4 | 11 | 16 | 20 | 104 | 105 | `; 106 | -------------------------------------------------------------------------------- /integrationtests/js/components/loaders/Spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, ActivityIndicator } from 'react-native'; 3 | 4 | const Spinner = () => ( 5 | 6 | 10 | 11 | ); 12 | 13 | const loaderStyle = { 14 | height: 80, 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | padding: 8, 18 | }; 19 | 20 | export default Spinner; 21 | -------------------------------------------------------------------------------- /integrationtests/js/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import reducer from './reducers'; 4 | 5 | export default function configureStore() { 6 | const enhancer = compose(applyMiddleware(thunk)); 7 | const store = createStore(reducer, enhancer); 8 | return store; 9 | } 10 | -------------------------------------------------------------------------------- /integrationtests/js/db/helpers.js: -------------------------------------------------------------------------------- 1 | import { 2 | premierLeagueTeams, 3 | laLigaTeams, 4 | serieATeams, 5 | premierLeagueMatches, 6 | laLigaMatches, 7 | serieAMatches, 8 | } from './index'; 9 | 10 | export function getTeams(currentLeague) { 11 | if (currentLeague === 'PremierLeague') { 12 | return premierLeagueTeams; 13 | } else if (currentLeague === 'LaLiga') { 14 | return laLigaTeams; 15 | } 16 | 17 | return serieATeams; 18 | } 19 | 20 | export function getMatches(currentLeague, team) { 21 | if (currentLeague === 'PremierLeague') { 22 | return reduceMatches(premierLeagueMatches, team); 23 | } else if (currentLeague === 'LaLiga') { 24 | return reduceMatches(laLigaMatches, team); 25 | } 26 | 27 | return reduceMatches(serieAMatches, team); 28 | } 29 | 30 | function reduceMatches(league, team) { 31 | let matches = []; 32 | const filterFunc = ({ team1, team2 }) => team1.name === team || team2.name === team; 33 | 34 | league.rounds.forEach((round) => { 35 | matches = [...matches, ...round.matches.filter(filterFunc)]; 36 | }); 37 | 38 | return matches; 39 | } 40 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/__tests__/__snapshots__/league.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_LEAGUE (LaLiga) 1`] = ` 4 | Object { 5 | "teams": Object { 6 | "clubs": Array [ 7 | Object { 8 | "code": "BAR", 9 | "key": "barcelona", 10 | "name": "Barcelona", 11 | }, 12 | Object { 13 | "code": "ESP", 14 | "key": "espanyol", 15 | "name": "Espanyol", 16 | }, 17 | Object { 18 | "code": "RMD", 19 | "key": "madrid", 20 | "name": "R. Madrid", 21 | }, 22 | Object { 23 | "code": "ATL", 24 | "key": "atletico", 25 | "name": "Atlético", 26 | }, 27 | Object { 28 | "code": "SEV", 29 | "key": "sevilla", 30 | "name": "Sevilla", 31 | }, 32 | Object { 33 | "code": "VAL", 34 | "key": "valencia", 35 | "name": "Valencia", 36 | }, 37 | Object { 38 | "code": "MAG", 39 | "key": "malaga", 40 | "name": "Málaga", 41 | }, 42 | Object { 43 | "code": "ATH", 44 | "key": "athletic", 45 | "name": "Athletic", 46 | }, 47 | Object { 48 | "code": "GRA", 49 | "key": "granada", 50 | "name": "Granada", 51 | }, 52 | Object { 53 | "code": "CEL", 54 | "key": "celta", 55 | "name": "Celta", 56 | }, 57 | Object { 58 | "code": "RSO", 59 | "key": "realsociedad", 60 | "name": "R. Sociedad", 61 | }, 62 | Object { 63 | "code": "DEP", 64 | "key": "deportivo", 65 | "name": "Deportivo", 66 | }, 67 | Object { 68 | "code": null, 69 | "key": "eibar", 70 | "name": "Eibar", 71 | }, 72 | Object { 73 | "code": "BET", 74 | "key": "betis", 75 | "name": "Betis", 76 | }, 77 | Object { 78 | "code": null, 79 | "key": "sporting", 80 | "name": "Sporting", 81 | }, 82 | Object { 83 | "code": null, 84 | "key": "laspalmas", 85 | "name": "Las Palmas", 86 | }, 87 | Object { 88 | "code": "OSA", 89 | "key": "osasuna", 90 | "name": "Osasuna", 91 | }, 92 | Object { 93 | "code": "VLL", 94 | "key": "villareal", 95 | "name": "Villarreal CF", 96 | }, 97 | Object { 98 | "code": null, 99 | "key": "alaves", 100 | "name": "Alavés", 101 | }, 102 | Object { 103 | "code": null, 104 | "key": "leganes", 105 | "name": "Club Deportivo Leganés", 106 | }, 107 | ], 108 | "name": "Primera División 2016/17", 109 | "routeName": "LaLiga", 110 | }, 111 | } 112 | `; 113 | 114 | exports[`INITIAL STATE 1`] = ` 115 | Object { 116 | "teams": Object { 117 | "clubs": Array [ 118 | Object { 119 | "code": "CHE", 120 | "key": "chelsea", 121 | "name": "Chelsea", 122 | }, 123 | Object { 124 | "code": "ARS", 125 | "key": "arsenal", 126 | "name": "Arsenal", 127 | }, 128 | Object { 129 | "code": "TOT", 130 | "key": "tottenham", 131 | "name": "Tottenham Hotspur", 132 | }, 133 | Object { 134 | "code": "WHU", 135 | "key": "westham", 136 | "name": "West Ham United", 137 | }, 138 | Object { 139 | "code": "CRY", 140 | "key": "crystalpalace", 141 | "name": "Crystal Palace", 142 | }, 143 | Object { 144 | "code": "MUN", 145 | "key": "manutd", 146 | "name": "Manchester United", 147 | }, 148 | Object { 149 | "code": "MCI", 150 | "key": "mancity", 151 | "name": "Manchester City", 152 | }, 153 | Object { 154 | "code": "EVE", 155 | "key": "everton", 156 | "name": "Everton", 157 | }, 158 | Object { 159 | "code": "LIV", 160 | "key": "liverpool", 161 | "name": "Liverpool", 162 | }, 163 | Object { 164 | "code": "WBA", 165 | "key": "westbrom", 166 | "name": "West Bromwich Albion", 167 | }, 168 | Object { 169 | "code": "STK", 170 | "key": "stoke", 171 | "name": "Stoke City", 172 | }, 173 | Object { 174 | "code": "SUN", 175 | "key": "sunderland", 176 | "name": "Sunderland", 177 | }, 178 | Object { 179 | "code": "SOU", 180 | "key": "southampton", 181 | "name": "Southampton", 182 | }, 183 | Object { 184 | "code": "LEI", 185 | "key": "leicester", 186 | "name": "Leicester City", 187 | }, 188 | Object { 189 | "code": "BOU", 190 | "key": "bournemouth", 191 | "name": "Bournemouth", 192 | }, 193 | Object { 194 | "code": "WAT", 195 | "key": "watford", 196 | "name": "Watford", 197 | }, 198 | Object { 199 | "code": "BUR", 200 | "key": "burnley", 201 | "name": "Burnley", 202 | }, 203 | Object { 204 | "code": "HUL", 205 | "key": "hull", 206 | "name": "Hull City", 207 | }, 208 | Object { 209 | "code": "MFC", 210 | "key": "middlesbrough", 211 | "name": "Middlesbrough", 212 | }, 213 | Object { 214 | "code": "SWA", 215 | "key": "swansea", 216 | "name": "Swansea", 217 | }, 218 | ], 219 | "name": "English Premier League 2016/17", 220 | "routeName": "PremierLeague", 221 | }, 222 | } 223 | `; 224 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/__tests__/__snapshots__/team.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_TEAM (LaLiga, Barcelona) 1`] = ` 4 | Object { 5 | "currentTeam": "", 6 | "image": "", 7 | "matches": Array [], 8 | } 9 | `; 10 | 11 | exports[`INITIAL STATE 1`] = ` 12 | Object { 13 | "currentTeam": "", 14 | "image": "", 15 | "matches": Array [], 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/__tests__/league.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import { getLeague } from '../../actions/league'; 3 | import league from '../league'; 4 | 5 | const store = mockStore(); 6 | 7 | beforeEach(() => { 8 | store.clearActions(); 9 | }); 10 | 11 | it('INITIAL STATE', () => { 12 | const action = { type: 'DUMMY' }; 13 | expect(league(undefined, action)).toMatchSnapshot(); 14 | }); 15 | 16 | it('GET_LEAGUE (LaLiga)', () => { 17 | expect(league(undefined, getLeague('LaLiga'))).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/__tests__/team.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import { getTeam } from '../../actions/team'; 3 | import team from '../team'; 4 | 5 | const store = mockStore(); 6 | 7 | beforeEach(() => { 8 | store.clearActions(); 9 | }); 10 | 11 | it('INITIAL STATE', () => { 12 | const action = { type: 'DUMMY' }; 13 | expect(team(undefined, action)).toMatchSnapshot(); 14 | }); 15 | 16 | it('GET_TEAM (LaLiga, Barcelona)', () => { 17 | expect(team(undefined, getTeam('LaLiga', 'Barcelona'))).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import league from './league'; 4 | import team from './team'; 5 | import { stack, drawer } from './navigation'; 6 | 7 | export default combineReducers({ 8 | league, 9 | team, 10 | stack, 11 | drawer, 12 | }); 13 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/league.js: -------------------------------------------------------------------------------- 1 | import { GET_LEAGUE } from '../actions/types'; 2 | import { getTeams } from '../db/helpers'; 3 | 4 | const initialState = { 5 | teams: getTeams('PremierLeague'), 6 | }; 7 | 8 | export default function (state = initialState, action) { 9 | if (action.type === GET_LEAGUE) { 10 | return { ...action.payload }; 11 | } 12 | 13 | return state; 14 | } 15 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/navigation.js: -------------------------------------------------------------------------------- 1 | import { NavigationActions } from 'react-navigation'; 2 | import { GET_TEAM, BACK, TOGGLE_DRAWER, GET_LEAGUE } from '../actions/types'; 3 | import { Stack } from '../router/stack/navigationConfiguration'; 4 | import { Drawer } from '../router/drawer/navigationConfiguration'; 5 | 6 | export function stack(state, action) { 7 | switch (action.type) { 8 | case BACK: { 9 | const navigationAction = NavigationActions.back({}); 10 | return Stack.router.getStateForAction(navigationAction, state); 11 | } 12 | case GET_TEAM: { 13 | const navigationAction = NavigationActions.navigate({ 14 | routeName: 'TeamScreen', 15 | params: { ...action.payload }, 16 | }); 17 | 18 | return Stack.router.getStateForAction(navigationAction, state); 19 | } 20 | default: return Stack.router.getStateForAction(action, state); 21 | } 22 | } 23 | 24 | const initialNavState = Drawer.router.getStateForAction( 25 | Drawer.router.getActionForPathAndParams('DrawerClose')); 26 | 27 | export function drawer(state = initialNavState, action) { 28 | switch (action.type) { 29 | case GET_LEAGUE: 30 | case TOGGLE_DRAWER: { 31 | const navigationAction = NavigationActions.navigate({ 32 | routeName: state.routes[state.index].routeName === 'DrawerOpen' ? 'DrawerClose' : 'DrawerOpen', 33 | }); 34 | 35 | return Drawer.router.getStateForAction(navigationAction, state); 36 | } 37 | default: return Drawer.router.getStateForAction(action, state) || state; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /integrationtests/js/reducers/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './../actions/types'; 2 | 3 | const initialState = { 4 | image: '', 5 | currentTeam: '', 6 | matches: [], 7 | }; 8 | 9 | export default function (state = initialState, action) { 10 | if (action.type === GET_TEAM) { 11 | return { ...action.payload }; 12 | } 13 | 14 | return state; 15 | } 16 | -------------------------------------------------------------------------------- /integrationtests/js/router/drawer/CustomDrawerContent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { DrawerItems } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { getLeague } from '../../actions/league'; 5 | 6 | const CustomDrawerContent = props => ( 7 | props.getLeague(route.key)} /> 8 | ); 9 | 10 | CustomDrawerContent.propTypes = { 11 | getLeague: PropTypes.func.isRequired, 12 | }; 13 | 14 | export default connect(undefined, { getLeague })(CustomDrawerContent); 15 | -------------------------------------------------------------------------------- /integrationtests/js/router/drawer/DrawerNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { View } from 'react-native'; 5 | import { Drawer } from './navigationConfiguration'; 6 | 7 | const DrawerNavigation = ({ dispatch, navigation }) => ( 8 | 16 | ); 17 | 18 | DrawerNavigation.propTypes = { 19 | dispatch: PropTypes.func.isRequired, 20 | navigation: PropTypes.shape().isRequired, 21 | }; 22 | 23 | const mapStateToProps = state => ({ navigation: state.drawer }); 24 | export default connect(mapStateToProps)(DrawerNavigation); 25 | -------------------------------------------------------------------------------- /integrationtests/js/router/drawer/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DrawerNavigator } from 'react-navigation'; 3 | import StackNavigation from '../stack/StackNavigation'; 4 | import CustomDrawerContent from './CustomDrawerContent'; 5 | 6 | const routeConfiguration = { 7 | PremierLeague: { 8 | screen: StackNavigation, 9 | navigationOptions: { 10 | drawer: { label: 'Premier League' }, 11 | }, 12 | }, 13 | LaLiga: { 14 | screen: StackNavigation, 15 | navigationOptions: { 16 | drawer: { label: 'La liga' }, 17 | }, 18 | }, 19 | SerieA: { 20 | screen: StackNavigation, 21 | navigationOptions: { 22 | drawer: { label: 'Serie A' }, 23 | }, 24 | }, 25 | }; 26 | 27 | export const Drawer = DrawerNavigator(routeConfiguration, { 28 | contentComponent: props => , 29 | }); 30 | -------------------------------------------------------------------------------- /integrationtests/js/router/stack/StackNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { BackHandler } from 'react-native'; 5 | import { Stack } from './navigationConfiguration'; 6 | 7 | class StackNavigation extends Component { 8 | static propTypes = { 9 | dispatch: PropTypes.func.isRequired, 10 | navigation: PropTypes.shape().isRequired, 11 | }; 12 | 13 | constructor(props) { 14 | super(props); 15 | BackHandler.addEventListener('hardwareBackPress', this.backAction); 16 | } 17 | 18 | backAction = () => this.navigator.props.navigation.goBack(); 19 | 20 | render() { 21 | const { dispatch, navigation } = this.props; 22 | 23 | return ( 24 | { this.navigator = ref; }} 26 | navigation={ 27 | addNavigationHelpers({ 28 | dispatch, 29 | state: navigation, 30 | }) 31 | } 32 | /> 33 | ); 34 | } 35 | } 36 | 37 | export default connect(state => ({ navigation: state.stack }))(StackNavigation); 38 | -------------------------------------------------------------------------------- /integrationtests/js/router/stack/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import { StackNavigator } from 'react-navigation'; 2 | 3 | import LeagueComponent from '../../components/LeagueComponent'; 4 | import TeamComponent from '../../components/TeamComponent'; 5 | 6 | const routeConfiguration = { 7 | LeagueScreen: { screen: LeagueComponent }, 8 | TeamScreen: { screen: TeamComponent }, 9 | }; 10 | 11 | const stackNavigatorConfiguration = { headerMode: 'none' }; 12 | export const Stack = StackNavigator(routeConfiguration, stackNavigatorConfiguration); 13 | -------------------------------------------------------------------------------- /integrationtests/js/setup.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import Spinner from './components/loaders/Spinner'; 4 | 5 | import DrawerNavigation from './router/drawer/DrawerNavigation'; 6 | import configureStore from './configureStore'; 7 | 8 | class Root extends Component { 9 | 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | store: configureStore(), 14 | }; 15 | } 16 | 17 | render() { 18 | const { store } = this.state; 19 | 20 | return !store 21 | ? 22 | : 23 | 24 | 25 | ; 26 | } 27 | } 28 | 29 | export default Root; 30 | -------------------------------------------------------------------------------- /integrationtests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integrationtests", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest" 8 | }, 9 | "dependencies": { 10 | "react": "16.0.0-alpha.6", 11 | "react-native": "0.44.1", 12 | "react-native-vector-icons": "^4.2.0", 13 | "react-navigation": "react-community/react-navigation", 14 | "react-redux": "^5.0.5", 15 | "redux": "^3.6.0", 16 | "redux-mock-store": "^1.2.3", 17 | "redux-thunk": "^2.2.0" 18 | }, 19 | "devDependencies": { 20 | "babel-eslint": "^7.2.3", 21 | "chai": "^4.0.2", 22 | "detox": "^5.1.3", 23 | "enzyme": "^2.8.2", 24 | "enzyme-to-json": "^1.5.1", 25 | "eslint": "^3.19.0", 26 | "eslint-config-airbnb": "^14.1.0", 27 | "eslint-plugin-import": "^2.2.0", 28 | "eslint-plugin-jsx-a11y": "^4.0.0", 29 | "eslint-plugin-react": "^6.10.3", 30 | "eslint-plugin-react-native": "^2.3.1", 31 | "jest": "20.0.3", 32 | "mocha": "^3.4.2", 33 | "react-addons-test-utils": "^15.6.0", 34 | "react-dom": "^15.6.1", 35 | "sinon": "^2.3.4" 36 | }, 37 | "jest": { 38 | "preset": "react-native", 39 | "testPathIgnorePatterns": [ 40 | "/node_modules/", 41 | "/e2e/" 42 | ], 43 | "transformIgnorePatterns": [ 44 | "node_modules/(?!(jest-)?react-native|react-navigation)" 45 | ] 46 | }, 47 | "detox": { 48 | "configurations": { 49 | "ios.sim.debug": { 50 | "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/integrationtests.app", 51 | "build": "xcodebuild -project ios/integrationtests.xcodeproj -scheme integrationtests -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build", 52 | "type": "ios.simulator", 53 | "name": "iPhone 6" 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /react-navigation-with-redux/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/react-navigation-with-redux/.DS_Store -------------------------------------------------------------------------------- /react-navigation-with-redux/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo"], 3 | "env": { 4 | "development": { 5 | "plugins": ["transform-react-jsx-source"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /react-navigation-with-redux/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "plugins": [ 5 | "react", 6 | "jsx-a11y", 7 | "import", 8 | "react-native" 9 | ], 10 | "rules": { 11 | "no-underscore-dangle": "off", 12 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], 13 | "no-use-before-define": "off", 14 | "import/prefer-default-export": "off", 15 | "no-shadow": "off", 16 | "no-nested-ternary": "off", 17 | "no-confusing-arrow": "off", 18 | }, 19 | "settings": { 20 | "import/resolver": { 21 | "node": { 22 | "extensions": [".js", ".android.js", ".ios.js"] 23 | } 24 | } 25 | }, 26 | "env": { 27 | "jest": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /react-navigation-with-redux/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | /react-navigation-with-redux/.DS_Store 5 | -------------------------------------------------------------------------------- /react-navigation-with-redux/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /react-navigation-with-redux/assets/icons/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/react-navigation-with-redux/assets/icons/app.png -------------------------------------------------------------------------------- /react-navigation-with-redux/assets/icons/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/react-navigation-with-redux/assets/icons/loading.png -------------------------------------------------------------------------------- /react-navigation-with-redux/exp.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-navigation-with-redux", 3 | "description": "An empty new project", 4 | "slug": "react-navigation-with-redux", 5 | "privacy": "public", 6 | "sdkVersion": "17.0.0", 7 | "version": "1.0.0", 8 | "orientation": "portrait", 9 | "primaryColor": "#cccccc", 10 | "icon": "./assets/icons/app.png", 11 | "loading": { 12 | "icon": "./assets/icons/loading.png", 13 | "hideExponentText": false 14 | }, 15 | "packagerOpts": { 16 | "assetExts": ["ttf", "mp4"] 17 | }, 18 | "ios": { 19 | "supportsTablet": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/react-navigation-with-redux/js/.DS_Store -------------------------------------------------------------------------------- /react-navigation-with-redux/js/actions/navigation.js: -------------------------------------------------------------------------------- 1 | import { BACK, TOGGLE_DRAWER } from './types'; 2 | 3 | export function back() { 4 | return { type: BACK }; 5 | } 6 | 7 | export function toggleDrawer() { 8 | return { type: TOGGLE_DRAWER }; 9 | } 10 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/actions/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './types'; 2 | 3 | export function getTeam(currentLeague, team) { 4 | return { 5 | type: GET_TEAM, 6 | payload: { currentLeague, team }, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/actions/types.js: -------------------------------------------------------------------------------- 1 | // match 2 | export const GET_TEAM = 'GET_TEAM'; 3 | 4 | // navigation 5 | export const TOGGLE_DRAWER = 'TOGGLE_DRAWER'; 6 | export const BACK = 'BACK'; 7 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/components/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/react-navigation-with-redux/js/components/.DS_Store -------------------------------------------------------------------------------- /react-navigation-with-redux/js/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { Ionicons } from '@expo/vector-icons'; 3 | import { connect } from 'react-redux'; 4 | import { View, Text } from 'react-native'; 5 | import { back, toggleDrawer } from '../actions/navigation'; 6 | 7 | const Header = ({ back, toggleDrawer, navigation, title }) => { 8 | const firstRoute = navigation.routes[navigation.index].routeName === 'LeagueScreen'; 9 | const name = firstRoute ? 'ios-menu' : 'ios-arrow-round-back'; 10 | const cb = firstRoute ? toggleDrawer : back; 11 | 12 | return ( 13 | 14 | {title} 15 | 16 | 17 | ); 18 | }; 19 | 20 | Header.propTypes = { 21 | back: PropTypes.func.isRequired, 22 | toggleDrawer: PropTypes.func.isRequired, 23 | navigation: PropTypes.shape().isRequired, 24 | title: PropTypes.string.isRequired, 25 | }; 26 | 27 | const styles = { 28 | container: { 29 | paddingTop: 25, 30 | paddingHorizontal: 12, 31 | flexDirection: 'row', 32 | justifyContent: 'space-between', 33 | alignItems: 'center', 34 | backgroundColor: '#69D8BB', 35 | }, 36 | text: { 37 | fontWeight: 'bold', 38 | color: 'white', 39 | }, 40 | }; 41 | 42 | const mapStateToProps = state => ({ navigation: state.stack }); 43 | export default connect(mapStateToProps, { back, toggleDrawer })(Header); 44 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/components/LeagueComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, TouchableOpacity, StatusBar } from 'react-native'; 4 | import { Ionicons } from '@expo/vector-icons'; 5 | import Header from '../components/Header'; 6 | import { getTeam } from '../actions/team'; 7 | 8 | class LeagueComponent extends Component { 9 | 10 | static propTypes = { 11 | league: PropTypes.shape().isRequired, 12 | currentLeagueRoute: PropTypes.string.isRequired, 13 | getTeam: PropTypes.func.isRequired, 14 | } 15 | 16 | renderTeam = ({ item, index }) => ( 17 | this.props.getTeam(this.props.currentLeagueRoute, item.name)} 20 | > 21 | 22 | {item.name} 23 | 24 | 25 | 26 | ); 27 | 28 | render() { 29 | const { league } = this.props; 30 | const { renderTeam } = this; 31 | 32 | return ( 33 | 34 | 35 |
36 | 40 | 41 | ); 42 | } 43 | } 44 | 45 | const styles = { 46 | container: { 47 | flexDirection: 'row', 48 | justifyContent: 'space-between', 49 | alignItems: 'center', 50 | paddingHorizontal: 16, 51 | paddingVertical: 10, 52 | }, 53 | }; 54 | 55 | const mapStateToProps = state => ({ 56 | league: state.league.teams, 57 | currentLeagueRoute: state.league.currentLeagueRoute, 58 | }); 59 | export default connect(mapStateToProps, { getTeam })(LeagueComponent); 60 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/components/TeamComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, StatusBar } from 'react-native'; 4 | import Header from '../components/Header'; 5 | 6 | class TeamComponent extends Component { 7 | 8 | static propTypes = { 9 | team: PropTypes.string.isRequired, 10 | matches: PropTypes.arrayOf(PropTypes.shape()).isRequired, 11 | } 12 | 13 | renderMatch = ({ item }) => ( 14 | 15 | 16 | {getTeamName(item.team1.name)} 17 | 18 | 19 | {getDate(item.date)} 20 | 21 | 22 | {getTeamName(item.team2.name)} 23 | 24 | 25 | ); 26 | 27 | render() { 28 | const { team, matches } = this.props; 29 | const { renderMatch } = this; 30 | return ( 31 | 32 | 33 |
34 | index} 38 | /> 39 | 40 | ); 41 | } 42 | } 43 | 44 | const getTeamName = name => name.length > 15 ? `${name.substring(0, 15)}...` : name; 45 | const getDate = date => `${date.split('-')[2]}/${date.split('-')[1]}`; 46 | 47 | const styles = { 48 | screen: { 49 | backgroundColor: 'white', 50 | }, 51 | home: { 52 | marginRight: 4, 53 | }, 54 | away: { 55 | marginLeft: 4, 56 | }, 57 | container: { 58 | marginBottom: 4, 59 | backgroundColor: 'white', 60 | flexDirection: 'row', 61 | flex: 1, 62 | }, 63 | textWrapper: { 64 | backgroundColor: '#F4F3F3', 65 | flex: 0.4, 66 | paddingLeft: 12, 67 | paddingVertical: 12, 68 | }, 69 | dateWrapper: { 70 | flex: 0.2, 71 | backgroundColor: '#69D8BB', 72 | justifyContent: 'center', 73 | alignItems: 'center', 74 | }, 75 | date: { 76 | fontSize: 10, 77 | fontWeight: 'bold', 78 | color: 'white', 79 | }, 80 | }; 81 | 82 | const mapStateToProps = state => ({ 83 | team: state.team.currentTeam, 84 | matches: state.team.matches, 85 | }); 86 | export default connect(mapStateToProps)(TeamComponent); 87 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/components/loaders/Spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, ActivityIndicator } from 'react-native'; 3 | 4 | const Spinner = () => ( 5 | 6 | 10 | 11 | ); 12 | 13 | const loaderStyle = { 14 | height: 80, 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | padding: 8, 18 | }; 19 | 20 | export default Spinner; 21 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux'; 2 | import reducer from './reducers'; 3 | 4 | export default function configureStore() { 5 | const store = createStore(reducer); 6 | return store; 7 | } 8 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/db/helpers.js: -------------------------------------------------------------------------------- 1 | import { 2 | premierLeagueTeams, 3 | laLigaTeams, 4 | serieATeams, 5 | premierLeagueMatches, 6 | laLigaMatches, 7 | serieAMatches, 8 | } from './index'; 9 | 10 | export function getTeams(currentLeague) { 11 | if (currentLeague === 'PremierLeague') { 12 | return premierLeagueTeams; 13 | } else if (currentLeague === 'LaLiga') { 14 | return laLigaTeams; 15 | } 16 | 17 | return serieATeams; 18 | } 19 | 20 | export function getMatches(currentLeague, team) { 21 | if (currentLeague === 'PremierLeague') { 22 | return reduceMatches(premierLeagueMatches, team); 23 | } else if (currentLeague === 'LaLiga') { 24 | return reduceMatches(laLigaMatches, team); 25 | } 26 | 27 | return reduceMatches(serieAMatches, team); 28 | } 29 | 30 | function reduceMatches(league, team) { 31 | let matches = []; 32 | const filterFunc = ({ team1, team2 }) => team1.name === team || team2.name === team; 33 | 34 | league.rounds.forEach((round) => { 35 | matches = [...matches, ...round.matches.filter(filterFunc)]; 36 | }); 37 | 38 | return matches; 39 | } 40 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import league from './league'; 4 | import team from './team'; 5 | import { stack, drawer } from './navigation'; 6 | 7 | export default combineReducers({ 8 | league, 9 | team, 10 | stack, 11 | drawer, 12 | }); 13 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/reducers/league.js: -------------------------------------------------------------------------------- 1 | import { getTeams } from './../db/helpers'; 2 | 3 | const initialState = { 4 | currentLeagueRoute: 'PremierLeague', 5 | teams: getTeams('PremierLeague'), 6 | }; 7 | 8 | export default function (state = initialState, action) { 9 | if (action.type === 'Navigation/NAVIGATE' && validRoute(action.routeName)) { 10 | const currentLeagueRoute = action.routeName; 11 | const teams = getTeams(currentLeagueRoute); 12 | return { 13 | teams, 14 | currentLeagueRoute, 15 | }; 16 | } 17 | 18 | return state; 19 | } 20 | 21 | function validRoute(route) { 22 | return ['PremierLeague', 'LaLiga', 'SerieA'].some(league => league === route); 23 | } 24 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/reducers/navigation.js: -------------------------------------------------------------------------------- 1 | import { NavigationActions } from 'react-navigation'; 2 | import { GET_TEAM, BACK, TOGGLE_DRAWER } from '../actions/types'; 3 | import { Stack } from '../router/stack/navigationConfiguration'; 4 | import { Drawer } from '../router/drawer/navigationConfiguration'; 5 | 6 | export function stack(state, action) { 7 | switch (action.type) { 8 | case BACK: { 9 | const navigationAction = NavigationActions.back({}); 10 | return Stack.router.getStateForAction(navigationAction, state); 11 | } 12 | case GET_TEAM: { 13 | const navigationAction = NavigationActions.navigate({ 14 | routeName: 'TeamScreen', 15 | params: { ...action.payload }, 16 | }); 17 | 18 | return Stack.router.getStateForAction(navigationAction, state); 19 | } 20 | default: return Stack.router.getStateForAction(action, state); 21 | } 22 | } 23 | 24 | const initialNavState = Drawer.router.getStateForAction( 25 | Drawer.router.getActionForPathAndParams('DrawerClose')); 26 | 27 | export function drawer(state = initialNavState, action) { 28 | switch (action.type) { 29 | case TOGGLE_DRAWER: { 30 | const navigationAction = NavigationActions.navigate({ 31 | routeName: state.routes[state.index].routeName === 'DrawerOpen' ? 'DrawerClose' : 'DrawerOpen', 32 | }); 33 | 34 | return Drawer.router.getStateForAction(navigationAction, state); 35 | } 36 | default: return Drawer.router.getStateForAction(action, state) || state; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/reducers/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './../actions/types'; 2 | import { getMatches } from './../db/helpers'; 3 | 4 | const initialState = { 5 | currentTeam: '', 6 | matches: [], 7 | }; 8 | 9 | export default function (state = initialState, action) { 10 | if (action.type === GET_TEAM) { 11 | const matches = getMatches(action.payload.currentLeague, action.payload.team); 12 | return { 13 | currentTeam: action.payload.team, 14 | matches, 15 | }; 16 | } 17 | 18 | return state; 19 | } 20 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/router/drawer/DrawerNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { Drawer } from './navigationConfiguration'; 5 | 6 | const DrawerNavigation = ({ dispatch, navigation }) => ( 7 | 15 | ); 16 | 17 | DrawerNavigation.propTypes = { 18 | dispatch: PropTypes.func.isRequired, 19 | navigation: PropTypes.shape().isRequired, 20 | }; 21 | 22 | const mapStateToProps = state => ({ navigation: state.drawer }); 23 | export default connect(mapStateToProps)(DrawerNavigation); 24 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/router/drawer/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import { DrawerNavigator } from 'react-navigation'; 2 | import StackNavigation from '../stack/StackNavigation'; 3 | 4 | const routeConfiguration = { 5 | PremierLeague: { 6 | screen: StackNavigation, 7 | navigationOptions: { 8 | drawer: { label: 'Premier League' }, 9 | }, 10 | }, 11 | LaLiga: { 12 | screen: StackNavigation, 13 | navigationOptions: { 14 | drawer: { label: 'La liga' }, 15 | }, 16 | }, 17 | SerieA: { 18 | screen: StackNavigation, 19 | navigationOptions: { 20 | drawer: { label: 'Serie A' }, 21 | }, 22 | }, 23 | }; 24 | 25 | export const Drawer = DrawerNavigator(routeConfiguration); 26 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/router/stack/StackNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { BackHandler } from 'react-native'; 5 | import { Stack } from './navigationConfiguration'; 6 | 7 | class StackNavigation extends Component { 8 | static propTypes = { 9 | dispatch: PropTypes.func.isRequired, 10 | navigation: PropTypes.shape().isRequired, 11 | }; 12 | 13 | constructor(props) { 14 | super(props); 15 | BackHandler.addEventListener('hardwareBackPress', this.backAction); 16 | } 17 | 18 | backAction = () => this.navigator.props.navigation.goBack(); 19 | 20 | render() { 21 | const { dispatch, navigation } = this.props; 22 | 23 | return ( 24 | { this.navigator = ref; }} 26 | navigation={ 27 | addNavigationHelpers({ 28 | dispatch, 29 | state: navigation, 30 | }) 31 | } 32 | /> 33 | ); 34 | } 35 | } 36 | 37 | export default connect(state => ({ navigation: state.stack }))(StackNavigation); 38 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/router/stack/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import { StackNavigator } from 'react-navigation'; 2 | 3 | import LeagueComponent from '../../components/LeagueComponent'; 4 | import TeamComponent from '../../components/TeamComponent'; 5 | 6 | const routeConfiguration = { 7 | LeagueScreen: { screen: LeagueComponent }, 8 | TeamScreen: { screen: TeamComponent }, 9 | }; 10 | 11 | const stackNavigatorConfiguration = { headerMode: 'none' }; 12 | export const Stack = StackNavigator(routeConfiguration, stackNavigatorConfiguration); 13 | -------------------------------------------------------------------------------- /react-navigation-with-redux/js/setup.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import Spinner from './components/loaders/Spinner'; 4 | 5 | import DrawerNavigation from './router/drawer/DrawerNavigation'; 6 | import configureStore from './configureStore'; 7 | 8 | class Root extends Component { 9 | 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | store: configureStore(), 14 | }; 15 | } 16 | 17 | render() { 18 | const { store } = this.state; 19 | 20 | return !store 21 | ? 22 | : 23 | 24 | 25 | ; 26 | } 27 | } 28 | 29 | export default Root; 30 | -------------------------------------------------------------------------------- /react-navigation-with-redux/main.js: -------------------------------------------------------------------------------- 1 | import Expo from 'expo'; 2 | import React from 'react'; 3 | import setup from './js/setup'; 4 | 5 | Expo.registerRootComponent(setup); 6 | -------------------------------------------------------------------------------- /react-navigation-with-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-navigation-with-redux", 3 | "version": "0.0.0", 4 | "description": "Hello Expo!", 5 | "author": null, 6 | "private": true, 7 | "main": "main.js", 8 | "scripts": { 9 | "lint": "eslint js" 10 | }, 11 | "dependencies": { 12 | "expo": "17.0.0", 13 | "react": "16.0.0-alpha.6", 14 | "react-native": "https://github.com/expo/react-native/archive/sdk-17.0.0.tar.gz", 15 | "react-navigation": "react-community/react-navigation", 16 | "react-redux": "^5.0.5", 17 | "redux": "^3.6.0" 18 | }, 19 | "devDependencies": { 20 | "babel-eslint": "^7.2.3", 21 | "eslint": "^3.19.0", 22 | "eslint-config-airbnb": "^14.1.0", 23 | "eslint-plugin-import": "^2.2.0", 24 | "eslint-plugin-jsx-a11y": "^4.0.0", 25 | "eslint-plugin-react": "^6.10.3", 26 | "eslint-plugin-react-native": "^2.3.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/.DS_Store -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo"], 3 | "env": { 4 | "development": { 5 | "plugins": ["transform-react-jsx-source"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "plugins": [ 5 | "react", 6 | "jsx-a11y", 7 | "import", 8 | "react-native" 9 | ], 10 | "rules": { 11 | "no-underscore-dangle": "off", 12 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], 13 | "no-use-before-define": "off", 14 | "import/prefer-default-export": "off", 15 | "no-shadow": "off", 16 | "no-nested-ternary": "off", 17 | "no-confusing-arrow": "off", 18 | }, 19 | "settings": { 20 | "import/resolver": { 21 | "node": { 22 | "extensions": [".js", ".android.js", ".ios.js"] 23 | } 24 | } 25 | }, 26 | "env": { 27 | "jest": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/__mocks__/redux-mock-store.js: -------------------------------------------------------------------------------- 1 | import configureMockStore from 'redux-mock-store'; 2 | import thunk from 'redux-thunk'; 3 | 4 | const middlewares = [thunk]; 5 | const mockStore = configureMockStore(middlewares); 6 | 7 | export default mockStore; 8 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/assets/icons/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/assets/icons/app.png -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/assets/icons/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/assets/icons/loading.png -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/exp.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unit-testing-jest-enzyme", 3 | "description": "An empty new project", 4 | "slug": "unit-testing-jest-enzyme", 5 | "privacy": "public", 6 | "sdkVersion": "17.0.0", 7 | "version": "1.0.0", 8 | "orientation": "portrait", 9 | "primaryColor": "#cccccc", 10 | "icon": "./assets/icons/app.png", 11 | "loading": { 12 | "icon": "./assets/icons/loading.png", 13 | "hideExponentText": false 14 | }, 15 | "packagerOpts": { 16 | "assetExts": ["ttf", "mp4"] 17 | }, 18 | "ios": { 19 | "supportsTablet": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/js/.DS_Store -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/__snapshots__/league.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_LEAGUE (LaLiga) 1`] = ` 4 | Array [ 5 | Object { 6 | "payload": Object { 7 | "teams": Object { 8 | "clubs": Array [ 9 | Object { 10 | "code": "BAR", 11 | "key": "barcelona", 12 | "name": "Barcelona", 13 | }, 14 | Object { 15 | "code": "ESP", 16 | "key": "espanyol", 17 | "name": "Espanyol", 18 | }, 19 | Object { 20 | "code": "RMD", 21 | "key": "madrid", 22 | "name": "R. Madrid", 23 | }, 24 | Object { 25 | "code": "ATL", 26 | "key": "atletico", 27 | "name": "Atlético", 28 | }, 29 | Object { 30 | "code": "SEV", 31 | "key": "sevilla", 32 | "name": "Sevilla", 33 | }, 34 | Object { 35 | "code": "VAL", 36 | "key": "valencia", 37 | "name": "Valencia", 38 | }, 39 | Object { 40 | "code": "MAG", 41 | "key": "malaga", 42 | "name": "Málaga", 43 | }, 44 | Object { 45 | "code": "ATH", 46 | "key": "athletic", 47 | "name": "Athletic", 48 | }, 49 | Object { 50 | "code": "GRA", 51 | "key": "granada", 52 | "name": "Granada", 53 | }, 54 | Object { 55 | "code": "CEL", 56 | "key": "celta", 57 | "name": "Celta", 58 | }, 59 | Object { 60 | "code": "RSO", 61 | "key": "realsociedad", 62 | "name": "R. Sociedad", 63 | }, 64 | Object { 65 | "code": "DEP", 66 | "key": "deportivo", 67 | "name": "Deportivo", 68 | }, 69 | Object { 70 | "code": null, 71 | "key": "eibar", 72 | "name": "Eibar", 73 | }, 74 | Object { 75 | "code": "BET", 76 | "key": "betis", 77 | "name": "Betis", 78 | }, 79 | Object { 80 | "code": null, 81 | "key": "sporting", 82 | "name": "Sporting", 83 | }, 84 | Object { 85 | "code": null, 86 | "key": "laspalmas", 87 | "name": "Las Palmas", 88 | }, 89 | Object { 90 | "code": "OSA", 91 | "key": "osasuna", 92 | "name": "Osasuna", 93 | }, 94 | Object { 95 | "code": "VLL", 96 | "key": "villareal", 97 | "name": "Villarreal CF", 98 | }, 99 | Object { 100 | "code": null, 101 | "key": "alaves", 102 | "name": "Alavés", 103 | }, 104 | Object { 105 | "code": null, 106 | "key": "leganes", 107 | "name": "Club Deportivo Leganés", 108 | }, 109 | ], 110 | "name": "Primera División 2016/17", 111 | "routeName": "LaLiga", 112 | }, 113 | }, 114 | "type": "GET_LEAGUE", 115 | }, 116 | ] 117 | `; 118 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/__snapshots__/navigation.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`BACK 1`] = ` 4 | Array [ 5 | Object { 6 | "type": "BACK", 7 | }, 8 | ] 9 | `; 10 | 11 | exports[`TOGGLE_DRAWER 1`] = ` 12 | Array [ 13 | Object { 14 | "type": "TOGGLE_DRAWER", 15 | }, 16 | ] 17 | `; 18 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/__snapshots__/team.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_TEAM (Barcelona) 1`] = ` 4 | Array [ 5 | Object { 6 | "payload": Object { 7 | "currentTeam": "Barcelona", 8 | "image": "STRING_URL", 9 | "matches": Array [ 10 | Object { 11 | "date": "2016-08-20", 12 | "score1": 6, 13 | "score2": 2, 14 | "team1": Object { 15 | "code": "BAR", 16 | "key": "barcelona", 17 | "name": "Barcelona", 18 | }, 19 | "team2": Object { 20 | "code": "BET", 21 | "key": "betis", 22 | "name": "Betis", 23 | }, 24 | }, 25 | Object { 26 | "date": "2016-08-28", 27 | "score1": 0, 28 | "score2": 1, 29 | "team1": Object { 30 | "code": "ATH", 31 | "key": "athletic", 32 | "name": "Athletic", 33 | }, 34 | "team2": Object { 35 | "code": "BAR", 36 | "key": "barcelona", 37 | "name": "Barcelona", 38 | }, 39 | }, 40 | Object { 41 | "date": "2016-09-10", 42 | "score1": 1, 43 | "score2": 2, 44 | "team1": Object { 45 | "code": "BAR", 46 | "key": "barcelona", 47 | "name": "Barcelona", 48 | }, 49 | "team2": Object { 50 | "code": null, 51 | "key": "alaves", 52 | "name": "Alavés", 53 | }, 54 | }, 55 | Object { 56 | "date": "2016-09-17", 57 | "score1": 1, 58 | "score2": 5, 59 | "team1": Object { 60 | "code": null, 61 | "key": "leganes", 62 | "name": "Club Deportivo Leganés", 63 | }, 64 | "team2": Object { 65 | "code": "BAR", 66 | "key": "barcelona", 67 | "name": "Barcelona", 68 | }, 69 | }, 70 | Object { 71 | "date": "2016-09-21", 72 | "score1": 1, 73 | "score2": 1, 74 | "team1": Object { 75 | "code": "BAR", 76 | "key": "barcelona", 77 | "name": "Barcelona", 78 | }, 79 | "team2": Object { 80 | "code": "ATL", 81 | "key": "atletico", 82 | "name": "Atlético", 83 | }, 84 | }, 85 | Object { 86 | "date": "2016-09-24", 87 | "score1": 0, 88 | "score2": 5, 89 | "team1": Object { 90 | "code": null, 91 | "key": "sporting", 92 | "name": "Sporting", 93 | }, 94 | "team2": Object { 95 | "code": "BAR", 96 | "key": "barcelona", 97 | "name": "Barcelona", 98 | }, 99 | }, 100 | Object { 101 | "date": "2016-10-02", 102 | "score1": 4, 103 | "score2": 3, 104 | "team1": Object { 105 | "code": "CEL", 106 | "key": "celta", 107 | "name": "Celta", 108 | }, 109 | "team2": Object { 110 | "code": "BAR", 111 | "key": "barcelona", 112 | "name": "Barcelona", 113 | }, 114 | }, 115 | Object { 116 | "date": "2016-10-15", 117 | "score1": null, 118 | "score2": null, 119 | "team1": Object { 120 | "code": "BAR", 121 | "key": "barcelona", 122 | "name": "Barcelona", 123 | }, 124 | "team2": Object { 125 | "code": "DEP", 126 | "key": "deportivo", 127 | "name": "Deportivo", 128 | }, 129 | }, 130 | Object { 131 | "date": "2016-10-23", 132 | "score1": null, 133 | "score2": null, 134 | "team1": Object { 135 | "code": "VAL", 136 | "key": "valencia", 137 | "name": "Valencia", 138 | }, 139 | "team2": Object { 140 | "code": "BAR", 141 | "key": "barcelona", 142 | "name": "Barcelona", 143 | }, 144 | }, 145 | Object { 146 | "date": "2016-10-30", 147 | "score1": null, 148 | "score2": null, 149 | "team1": Object { 150 | "code": "BAR", 151 | "key": "barcelona", 152 | "name": "Barcelona", 153 | }, 154 | "team2": Object { 155 | "code": "GRA", 156 | "key": "granada", 157 | "name": "Granada", 158 | }, 159 | }, 160 | Object { 161 | "date": "2016-11-06", 162 | "score1": null, 163 | "score2": null, 164 | "team1": Object { 165 | "code": "SEV", 166 | "key": "sevilla", 167 | "name": "Sevilla", 168 | }, 169 | "team2": Object { 170 | "code": "BAR", 171 | "key": "barcelona", 172 | "name": "Barcelona", 173 | }, 174 | }, 175 | Object { 176 | "date": "2016-11-20", 177 | "score1": null, 178 | "score2": null, 179 | "team1": Object { 180 | "code": "BAR", 181 | "key": "barcelona", 182 | "name": "Barcelona", 183 | }, 184 | "team2": Object { 185 | "code": "MAG", 186 | "key": "malaga", 187 | "name": "Málaga", 188 | }, 189 | }, 190 | Object { 191 | "date": "2016-11-27", 192 | "score1": null, 193 | "score2": null, 194 | "team1": Object { 195 | "code": "RSO", 196 | "key": "realsociedad", 197 | "name": "R. Sociedad", 198 | }, 199 | "team2": Object { 200 | "code": "BAR", 201 | "key": "barcelona", 202 | "name": "Barcelona", 203 | }, 204 | }, 205 | Object { 206 | "date": "2016-12-04", 207 | "score1": null, 208 | "score2": null, 209 | "team1": Object { 210 | "code": "BAR", 211 | "key": "barcelona", 212 | "name": "Barcelona", 213 | }, 214 | "team2": Object { 215 | "code": "RMD", 216 | "key": "madrid", 217 | "name": "R. Madrid", 218 | }, 219 | }, 220 | Object { 221 | "date": "2016-12-11", 222 | "score1": null, 223 | "score2": null, 224 | "team1": Object { 225 | "code": "OSA", 226 | "key": "osasuna", 227 | "name": "Osasuna", 228 | }, 229 | "team2": Object { 230 | "code": "BAR", 231 | "key": "barcelona", 232 | "name": "Barcelona", 233 | }, 234 | }, 235 | Object { 236 | "date": "2016-12-18", 237 | "score1": null, 238 | "score2": null, 239 | "team1": Object { 240 | "code": "BAR", 241 | "key": "barcelona", 242 | "name": "Barcelona", 243 | }, 244 | "team2": Object { 245 | "code": "ESP", 246 | "key": "espanyol", 247 | "name": "Espanyol", 248 | }, 249 | }, 250 | Object { 251 | "date": "2017-01-08", 252 | "score1": null, 253 | "score2": null, 254 | "team1": Object { 255 | "code": "VLL", 256 | "key": "villareal", 257 | "name": "Villarreal CF", 258 | }, 259 | "team2": Object { 260 | "code": "BAR", 261 | "key": "barcelona", 262 | "name": "Barcelona", 263 | }, 264 | }, 265 | Object { 266 | "date": "2017-01-15", 267 | "score1": null, 268 | "score2": null, 269 | "team1": Object { 270 | "code": "BAR", 271 | "key": "barcelona", 272 | "name": "Barcelona", 273 | }, 274 | "team2": Object { 275 | "code": null, 276 | "key": "laspalmas", 277 | "name": "Las Palmas", 278 | }, 279 | }, 280 | Object { 281 | "date": "2017-01-22", 282 | "score1": null, 283 | "score2": null, 284 | "team1": Object { 285 | "code": null, 286 | "key": "eibar", 287 | "name": "Eibar", 288 | }, 289 | "team2": Object { 290 | "code": "BAR", 291 | "key": "barcelona", 292 | "name": "Barcelona", 293 | }, 294 | }, 295 | Object { 296 | "date": "2017-01-29", 297 | "score1": null, 298 | "score2": null, 299 | "team1": Object { 300 | "code": "BET", 301 | "key": "betis", 302 | "name": "Betis", 303 | }, 304 | "team2": Object { 305 | "code": "BAR", 306 | "key": "barcelona", 307 | "name": "Barcelona", 308 | }, 309 | }, 310 | Object { 311 | "date": "2017-02-05", 312 | "score1": null, 313 | "score2": null, 314 | "team1": Object { 315 | "code": "BAR", 316 | "key": "barcelona", 317 | "name": "Barcelona", 318 | }, 319 | "team2": Object { 320 | "code": "ATH", 321 | "key": "athletic", 322 | "name": "Athletic", 323 | }, 324 | }, 325 | Object { 326 | "date": "2017-02-12", 327 | "score1": null, 328 | "score2": null, 329 | "team1": Object { 330 | "code": null, 331 | "key": "alaves", 332 | "name": "Alavés", 333 | }, 334 | "team2": Object { 335 | "code": "BAR", 336 | "key": "barcelona", 337 | "name": "Barcelona", 338 | }, 339 | }, 340 | Object { 341 | "date": "2017-02-19", 342 | "score1": null, 343 | "score2": null, 344 | "team1": Object { 345 | "code": "BAR", 346 | "key": "barcelona", 347 | "name": "Barcelona", 348 | }, 349 | "team2": Object { 350 | "code": null, 351 | "key": "leganes", 352 | "name": "Club Deportivo Leganés", 353 | }, 354 | }, 355 | Object { 356 | "date": "2017-02-26", 357 | "score1": null, 358 | "score2": null, 359 | "team1": Object { 360 | "code": "ATL", 361 | "key": "atletico", 362 | "name": "Atlético", 363 | }, 364 | "team2": Object { 365 | "code": "BAR", 366 | "key": "barcelona", 367 | "name": "Barcelona", 368 | }, 369 | }, 370 | Object { 371 | "date": "2017-03-01", 372 | "score1": null, 373 | "score2": null, 374 | "team1": Object { 375 | "code": "BAR", 376 | "key": "barcelona", 377 | "name": "Barcelona", 378 | }, 379 | "team2": Object { 380 | "code": null, 381 | "key": "sporting", 382 | "name": "Sporting", 383 | }, 384 | }, 385 | Object { 386 | "date": "2017-03-05", 387 | "score1": null, 388 | "score2": null, 389 | "team1": Object { 390 | "code": "BAR", 391 | "key": "barcelona", 392 | "name": "Barcelona", 393 | }, 394 | "team2": Object { 395 | "code": "CEL", 396 | "key": "celta", 397 | "name": "Celta", 398 | }, 399 | }, 400 | Object { 401 | "date": "2017-03-12", 402 | "score1": null, 403 | "score2": null, 404 | "team1": Object { 405 | "code": "DEP", 406 | "key": "deportivo", 407 | "name": "Deportivo", 408 | }, 409 | "team2": Object { 410 | "code": "BAR", 411 | "key": "barcelona", 412 | "name": "Barcelona", 413 | }, 414 | }, 415 | Object { 416 | "date": "2017-03-19", 417 | "score1": null, 418 | "score2": null, 419 | "team1": Object { 420 | "code": "BAR", 421 | "key": "barcelona", 422 | "name": "Barcelona", 423 | }, 424 | "team2": Object { 425 | "code": "VAL", 426 | "key": "valencia", 427 | "name": "Valencia", 428 | }, 429 | }, 430 | Object { 431 | "date": "2017-04-02", 432 | "score1": null, 433 | "score2": null, 434 | "team1": Object { 435 | "code": "GRA", 436 | "key": "granada", 437 | "name": "Granada", 438 | }, 439 | "team2": Object { 440 | "code": "BAR", 441 | "key": "barcelona", 442 | "name": "Barcelona", 443 | }, 444 | }, 445 | Object { 446 | "date": "2017-04-05", 447 | "score1": null, 448 | "score2": null, 449 | "team1": Object { 450 | "code": "BAR", 451 | "key": "barcelona", 452 | "name": "Barcelona", 453 | }, 454 | "team2": Object { 455 | "code": "SEV", 456 | "key": "sevilla", 457 | "name": "Sevilla", 458 | }, 459 | }, 460 | Object { 461 | "date": "2017-04-09", 462 | "score1": null, 463 | "score2": null, 464 | "team1": Object { 465 | "code": "MAG", 466 | "key": "malaga", 467 | "name": "Málaga", 468 | }, 469 | "team2": Object { 470 | "code": "BAR", 471 | "key": "barcelona", 472 | "name": "Barcelona", 473 | }, 474 | }, 475 | Object { 476 | "date": "2017-04-16", 477 | "score1": null, 478 | "score2": null, 479 | "team1": Object { 480 | "code": "BAR", 481 | "key": "barcelona", 482 | "name": "Barcelona", 483 | }, 484 | "team2": Object { 485 | "code": "RSO", 486 | "key": "realsociedad", 487 | "name": "R. Sociedad", 488 | }, 489 | }, 490 | Object { 491 | "date": "2017-04-23", 492 | "score1": null, 493 | "score2": null, 494 | "team1": Object { 495 | "code": "RMD", 496 | "key": "madrid", 497 | "name": "R. Madrid", 498 | }, 499 | "team2": Object { 500 | "code": "BAR", 501 | "key": "barcelona", 502 | "name": "Barcelona", 503 | }, 504 | }, 505 | Object { 506 | "date": "2017-04-26", 507 | "score1": null, 508 | "score2": null, 509 | "team1": Object { 510 | "code": "BAR", 511 | "key": "barcelona", 512 | "name": "Barcelona", 513 | }, 514 | "team2": Object { 515 | "code": "OSA", 516 | "key": "osasuna", 517 | "name": "Osasuna", 518 | }, 519 | }, 520 | Object { 521 | "date": "2017-04-30", 522 | "score1": null, 523 | "score2": null, 524 | "team1": Object { 525 | "code": "ESP", 526 | "key": "espanyol", 527 | "name": "Espanyol", 528 | }, 529 | "team2": Object { 530 | "code": "BAR", 531 | "key": "barcelona", 532 | "name": "Barcelona", 533 | }, 534 | }, 535 | Object { 536 | "date": "2017-05-07", 537 | "score1": null, 538 | "score2": null, 539 | "team1": Object { 540 | "code": "BAR", 541 | "key": "barcelona", 542 | "name": "Barcelona", 543 | }, 544 | "team2": Object { 545 | "code": "VLL", 546 | "key": "villareal", 547 | "name": "Villarreal CF", 548 | }, 549 | }, 550 | Object { 551 | "date": "2017-05-14", 552 | "score1": null, 553 | "score2": null, 554 | "team1": Object { 555 | "code": null, 556 | "key": "laspalmas", 557 | "name": "Las Palmas", 558 | }, 559 | "team2": Object { 560 | "code": "BAR", 561 | "key": "barcelona", 562 | "name": "Barcelona", 563 | }, 564 | }, 565 | Object { 566 | "date": "2017-05-21", 567 | "score1": null, 568 | "score2": null, 569 | "team1": Object { 570 | "code": "BAR", 571 | "key": "barcelona", 572 | "name": "Barcelona", 573 | }, 574 | "team2": Object { 575 | "code": null, 576 | "key": "eibar", 577 | "name": "Eibar", 578 | }, 579 | }, 580 | ], 581 | }, 582 | "type": "GET_TEAM", 583 | }, 584 | ] 585 | `; 586 | 587 | exports[`GET_TEAM (null) 1`] = `Array []`; 588 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/league.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../league'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | it('GET_LEAGUE (LaLiga)', () => { 11 | store.dispatch(actions.getLeague('LaLiga')); 12 | expect(store.getActions()).toMatchSnapshot(); 13 | }); 14 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/navigation.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../navigation'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | it('BACK', () => { 11 | store.dispatch(actions.back()); 12 | expect(store.getActions()).toMatchSnapshot(); 13 | }); 14 | 15 | it('TOGGLE_DRAWER', () => { 16 | store.dispatch(actions.toggleDrawer()); 17 | expect(store.getActions()).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/__tests__/team.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import * as actions from '../team'; 3 | 4 | const store = mockStore(); 5 | 6 | beforeEach(() => { 7 | store.clearActions(); 8 | }); 9 | 10 | global.fetch = jest.fn().mockImplementation(() => Promise.resolve({ 11 | json: () => ({ 12 | Image: 'STRING_URL', 13 | }), 14 | })); 15 | 16 | it('GET_TEAM (Barcelona)', async () => { 17 | await store.dispatch(actions.getTeam('LaLiga', 'Barcelona')); 18 | expect(store.getActions()).toMatchSnapshot(); 19 | }); 20 | 21 | it('GET_TEAM (null)', () => { 22 | store.dispatch(actions.getTeam(null, null)); 23 | expect(store.getActions()).toMatchSnapshot(); 24 | }); 25 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/league.js: -------------------------------------------------------------------------------- 1 | import { GET_LEAGUE } from './types'; 2 | import { getTeams } from '../db/helpers'; 3 | 4 | export function getLeague(currentLeagueRoute) { 5 | const teams = getTeams(currentLeagueRoute); 6 | 7 | return { 8 | type: GET_LEAGUE, 9 | payload: { teams }, 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/navigation.js: -------------------------------------------------------------------------------- 1 | import { BACK, TOGGLE_DRAWER } from './types'; 2 | 3 | export function back() { 4 | return { type: BACK }; 5 | } 6 | 7 | export function toggleDrawer() { 8 | return { type: TOGGLE_DRAWER }; 9 | } 10 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './types'; 2 | import { getMatches } from '../db/helpers'; 3 | import { getTeamLogo } from '../api'; 4 | 5 | function teamAction(currentLeague, currentTeam, image) { 6 | const matches = getMatches(currentLeague, currentTeam); 7 | return { type: GET_TEAM, payload: { matches, currentTeam, image } }; 8 | } 9 | 10 | export function getTeam(currentLeague, currentTeam) { 11 | return dispatch => getTeamLogo(currentTeam) 12 | .then(response => response.json()) 13 | .then(response => dispatch(teamAction(currentLeague, currentTeam, response.Image))) 14 | .catch(() => dispatch(teamAction(currentLeague, currentTeam, null))) 15 | ; 16 | } 17 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/actions/types.js: -------------------------------------------------------------------------------- 1 | // league 2 | export const GET_LEAGUE = 'GET_LEAGUE'; 3 | 4 | // match 5 | export const GET_TEAM = 'GET_TEAM'; 6 | 7 | // navigation 8 | export const TOGGLE_DRAWER = 'TOGGLE_DRAWER'; 9 | export const BACK = 'BACK'; 10 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/api/index.js: -------------------------------------------------------------------------------- 1 | export function getTeamLogo(currentTeam) { 2 | return fetch(`http://api.duckduckgo.com/?q=${currentTeam}&format=json`); 3 | } 4 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/js/components/.DS_Store -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { Ionicons } from '@expo/vector-icons'; 3 | import { connect } from 'react-redux'; 4 | import { View, Text, Image, StyleSheet } from 'react-native'; 5 | import { back, toggleDrawer } from '../actions/navigation'; 6 | 7 | const Header = ({ back, toggleDrawer, navigation, title, image }) => { 8 | const firstRoute = navigation.routes[navigation.index].routeName === 'LeagueScreen'; 9 | const name = firstRoute ? 'ios-menu' : 'ios-arrow-round-back'; 10 | const cb = firstRoute ? toggleDrawer : back; 11 | 12 | return ( 13 | 14 | 15 | { image !== null && image.length > 0 && 19 | } 20 | {title} 21 | 22 | 23 | 24 | ); 25 | }; 26 | 27 | Header.propTypes = { 28 | back: PropTypes.func.isRequired, 29 | toggleDrawer: PropTypes.func.isRequired, 30 | navigation: PropTypes.shape().isRequired, 31 | title: PropTypes.string.isRequired, 32 | image: PropTypes.string, 33 | }; 34 | 35 | const styles = StyleSheet.create({ 36 | container: { 37 | paddingTop: 25, 38 | paddingHorizontal: 12, 39 | flexDirection: 'row', 40 | justifyContent: 'space-between', 41 | alignItems: 'center', 42 | backgroundColor: '#69D8BB', 43 | }, 44 | content: { 45 | flexDirection: 'row', 46 | alignItems: 'center', 47 | justifyContent: 'center', 48 | }, 49 | text: { 50 | fontWeight: 'bold', 51 | color: 'white', 52 | }, 53 | image: { 54 | marginRight: 8, 55 | width: 16, 56 | height: 16, 57 | }, 58 | }); 59 | 60 | const mapStateToProps = state => ({ navigation: state.stack }); 61 | export default connect(mapStateToProps, { back, toggleDrawer })(Header); 62 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/LeagueComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, TouchableOpacity, StatusBar } from 'react-native'; 4 | import { Ionicons } from '@expo/vector-icons'; 5 | import Header from '../components/Header'; 6 | import { getTeam } from '../actions/team'; 7 | 8 | class LeagueComponent extends Component { 9 | 10 | static propTypes = { 11 | league: PropTypes.shape().isRequired, 12 | getTeam: PropTypes.func.isRequired, 13 | } 14 | 15 | renderTeam = ({ item, index }) => ( 16 | this.props.getTeam(this.props.league.routeName, item.name)} 19 | > 20 | 21 | {item.name} 22 | 23 | 24 | 25 | ); 26 | 27 | render() { 28 | const { league } = this.props; 29 | const { renderTeam } = this; 30 | 31 | return ( 32 | 33 | 34 |
35 | 39 | 40 | ); 41 | } 42 | } 43 | 44 | const styles = { 45 | itemContainer: { 46 | flexDirection: 'row', 47 | justifyContent: 'space-between', 48 | alignItems: 'center', 49 | paddingHorizontal: 16, 50 | paddingVertical: 10, 51 | flex: 1, 52 | }, 53 | container: { 54 | flex: 1, 55 | }, 56 | }; 57 | 58 | const mapStateToProps = ({ league }) => ({ league: league.teams }); 59 | export default connect(mapStateToProps, { getTeam })(LeagueComponent); 60 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/TeamComponent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { View, Text, FlatList, StatusBar, StyleSheet } from 'react-native'; 4 | import Header from '../components/Header'; 5 | 6 | 7 | class TeamComponent extends Component { 8 | 9 | static propTypes = { 10 | team: PropTypes.string.isRequired, 11 | matches: PropTypes.arrayOf(PropTypes.shape()).isRequired, 12 | image: PropTypes.string, 13 | } 14 | 15 | renderMatch = ({ item }) => ( 16 | 17 | 18 | {getTeamName(item.team1.name)} 19 | 20 | 21 | {getDate(item.date)} 22 | 23 | 24 | {getTeamName(item.team2.name)} 25 | 26 | 27 | ); 28 | 29 | render() { 30 | const { team, matches, image } = this.props; 31 | const { renderMatch } = this; 32 | 33 | return ( 34 | 35 | 36 |
37 | index} 41 | /> 42 | 43 | ); 44 | } 45 | } 46 | 47 | const getTeamName = name => name.length > 15 ? `${name.substring(0, 15)}...` : name; 48 | const getDate = date => `${date.split('-')[2]}/${date.split('-')[1]}`; 49 | 50 | const styles = StyleSheet.create({ 51 | screen: { 52 | backgroundColor: 'white', 53 | flex: 1, 54 | }, 55 | home: { 56 | marginRight: 4, 57 | }, 58 | away: { 59 | marginLeft: 4, 60 | }, 61 | container: { 62 | marginBottom: 4, 63 | backgroundColor: 'white', 64 | flexDirection: 'row', 65 | }, 66 | textWrapper: { 67 | backgroundColor: '#F4F3F3', 68 | flex: 0.4, 69 | paddingLeft: 12, 70 | paddingVertical: 12, 71 | }, 72 | dateWrapper: { 73 | flex: 0.2, 74 | backgroundColor: '#69D8BB', 75 | justifyContent: 'center', 76 | alignItems: 'center', 77 | }, 78 | date: { 79 | fontSize: 10, 80 | fontWeight: 'bold', 81 | color: 'white', 82 | }, 83 | }); 84 | 85 | const mapStateToProps = state => ({ 86 | team: state.team.currentTeam, 87 | matches: state.team.matches, 88 | image: state.team.image, 89 | }); 90 | export default connect(mapStateToProps)(TeamComponent); 91 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/__tests__/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weareredlight/react-native-tutorials/0e6262591e49b657688bf5bb36a0c83aee86165e/unit-testing-jest-enzyme/js/components/__tests__/.DS_Store -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/__tests__/LeagueComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import toJson from 'enzyme-to-json'; 4 | import mockStore from 'redux-mock-store'; 5 | import { FlatList } from 'react-native'; 6 | import { expect as expectChai } from 'chai'; 7 | import LeagueComponent from '../LeagueComponent'; 8 | 9 | // eslint-disable-next-line 10 | const league = {"name":"English Premier League 2016/17","routeName":"PremierLeague","clubs":[{"key":"chelsea","name":"Chelsea","code":"CHE"},{"key":"arsenal","name":"Arsenal","code":"ARS"},{"key":"tottenham","name":"Tottenham Hotspur","code":"TOT"},{"key":"westham","name":"West Ham United","code":"WHU"},{"key":"crystalpalace","name":"Crystal Palace","code":"CRY"},{"key":"manutd","name":"Manchester United","code":"MUN"},{"key":"mancity","name":"Manchester City","code":"MCI"},{"key":"everton","name":"Everton","code":"EVE"},{"key":"liverpool","name":"Liverpool","code":"LIV"},{"key":"westbrom","name":"West Bromwich Albion","code":"WBA"},{"key":"stoke","name":"Stoke City","code":"STK"},{"key":"sunderland","name":"Sunderland","code":"SUN"},{"key":"southampton","name":"Southampton","code":"SOU"}]}; 11 | 12 | it('renders all children', () => { 13 | const initialState = { league: { teams: league } }; 14 | const store = mockStore(initialState); 15 | 16 | const wrapper = shallow(); 17 | 18 | const component = shallow(wrapper.getNodes()[0]); 19 | 20 | expectChai(component.find(FlatList).length).to.equal(1); 21 | expectChai(component.find(FlatList).at(0).props().data.length).to.equal(league.clubs.length); 22 | expect(toJson(component)).toMatchSnapshot(); 23 | }); 24 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/__tests__/__snapshots__/LeagueComponent.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders all children 1`] = ` 4 | 11 | 16 | 20 | 104 | 105 | `; 106 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/components/loaders/Spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, ActivityIndicator } from 'react-native'; 3 | 4 | const Spinner = () => ( 5 | 6 | 10 | 11 | ); 12 | 13 | const loaderStyle = { 14 | height: 80, 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | padding: 8, 18 | }; 19 | 20 | export default Spinner; 21 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import reducer from './reducers'; 4 | 5 | export default function configureStore() { 6 | const enhancer = compose(applyMiddleware(thunk)); 7 | const store = createStore(reducer, enhancer); 8 | return store; 9 | } 10 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/db/helpers.js: -------------------------------------------------------------------------------- 1 | import { 2 | premierLeagueTeams, 3 | laLigaTeams, 4 | serieATeams, 5 | premierLeagueMatches, 6 | laLigaMatches, 7 | serieAMatches, 8 | } from './index'; 9 | 10 | export function getTeams(currentLeague) { 11 | if (currentLeague === 'PremierLeague') { 12 | return premierLeagueTeams; 13 | } else if (currentLeague === 'LaLiga') { 14 | return laLigaTeams; 15 | } 16 | 17 | return serieATeams; 18 | } 19 | 20 | export function getMatches(currentLeague, team) { 21 | if (currentLeague === 'PremierLeague') { 22 | return reduceMatches(premierLeagueMatches, team); 23 | } else if (currentLeague === 'LaLiga') { 24 | return reduceMatches(laLigaMatches, team); 25 | } 26 | 27 | return reduceMatches(serieAMatches, team); 28 | } 29 | 30 | function reduceMatches(league, team) { 31 | let matches = []; 32 | const filterFunc = ({ team1, team2 }) => team1.name === team || team2.name === team; 33 | 34 | league.rounds.forEach((round) => { 35 | matches = [...matches, ...round.matches.filter(filterFunc)]; 36 | }); 37 | 38 | return matches; 39 | } 40 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/__tests__/__snapshots__/league.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_LEAGUE (LaLiga) 1`] = ` 4 | Object { 5 | "teams": Object { 6 | "clubs": Array [ 7 | Object { 8 | "code": "BAR", 9 | "key": "barcelona", 10 | "name": "Barcelona", 11 | }, 12 | Object { 13 | "code": "ESP", 14 | "key": "espanyol", 15 | "name": "Espanyol", 16 | }, 17 | Object { 18 | "code": "RMD", 19 | "key": "madrid", 20 | "name": "R. Madrid", 21 | }, 22 | Object { 23 | "code": "ATL", 24 | "key": "atletico", 25 | "name": "Atlético", 26 | }, 27 | Object { 28 | "code": "SEV", 29 | "key": "sevilla", 30 | "name": "Sevilla", 31 | }, 32 | Object { 33 | "code": "VAL", 34 | "key": "valencia", 35 | "name": "Valencia", 36 | }, 37 | Object { 38 | "code": "MAG", 39 | "key": "malaga", 40 | "name": "Málaga", 41 | }, 42 | Object { 43 | "code": "ATH", 44 | "key": "athletic", 45 | "name": "Athletic", 46 | }, 47 | Object { 48 | "code": "GRA", 49 | "key": "granada", 50 | "name": "Granada", 51 | }, 52 | Object { 53 | "code": "CEL", 54 | "key": "celta", 55 | "name": "Celta", 56 | }, 57 | Object { 58 | "code": "RSO", 59 | "key": "realsociedad", 60 | "name": "R. Sociedad", 61 | }, 62 | Object { 63 | "code": "DEP", 64 | "key": "deportivo", 65 | "name": "Deportivo", 66 | }, 67 | Object { 68 | "code": null, 69 | "key": "eibar", 70 | "name": "Eibar", 71 | }, 72 | Object { 73 | "code": "BET", 74 | "key": "betis", 75 | "name": "Betis", 76 | }, 77 | Object { 78 | "code": null, 79 | "key": "sporting", 80 | "name": "Sporting", 81 | }, 82 | Object { 83 | "code": null, 84 | "key": "laspalmas", 85 | "name": "Las Palmas", 86 | }, 87 | Object { 88 | "code": "OSA", 89 | "key": "osasuna", 90 | "name": "Osasuna", 91 | }, 92 | Object { 93 | "code": "VLL", 94 | "key": "villareal", 95 | "name": "Villarreal CF", 96 | }, 97 | Object { 98 | "code": null, 99 | "key": "alaves", 100 | "name": "Alavés", 101 | }, 102 | Object { 103 | "code": null, 104 | "key": "leganes", 105 | "name": "Club Deportivo Leganés", 106 | }, 107 | ], 108 | "name": "Primera División 2016/17", 109 | "routeName": "LaLiga", 110 | }, 111 | } 112 | `; 113 | 114 | exports[`INITIAL STATE 1`] = ` 115 | Object { 116 | "teams": Object { 117 | "clubs": Array [ 118 | Object { 119 | "code": "CHE", 120 | "key": "chelsea", 121 | "name": "Chelsea", 122 | }, 123 | Object { 124 | "code": "ARS", 125 | "key": "arsenal", 126 | "name": "Arsenal", 127 | }, 128 | Object { 129 | "code": "TOT", 130 | "key": "tottenham", 131 | "name": "Tottenham Hotspur", 132 | }, 133 | Object { 134 | "code": "WHU", 135 | "key": "westham", 136 | "name": "West Ham United", 137 | }, 138 | Object { 139 | "code": "CRY", 140 | "key": "crystalpalace", 141 | "name": "Crystal Palace", 142 | }, 143 | Object { 144 | "code": "MUN", 145 | "key": "manutd", 146 | "name": "Manchester United", 147 | }, 148 | Object { 149 | "code": "MCI", 150 | "key": "mancity", 151 | "name": "Manchester City", 152 | }, 153 | Object { 154 | "code": "EVE", 155 | "key": "everton", 156 | "name": "Everton", 157 | }, 158 | Object { 159 | "code": "LIV", 160 | "key": "liverpool", 161 | "name": "Liverpool", 162 | }, 163 | Object { 164 | "code": "WBA", 165 | "key": "westbrom", 166 | "name": "West Bromwich Albion", 167 | }, 168 | Object { 169 | "code": "STK", 170 | "key": "stoke", 171 | "name": "Stoke City", 172 | }, 173 | Object { 174 | "code": "SUN", 175 | "key": "sunderland", 176 | "name": "Sunderland", 177 | }, 178 | Object { 179 | "code": "SOU", 180 | "key": "southampton", 181 | "name": "Southampton", 182 | }, 183 | Object { 184 | "code": "LEI", 185 | "key": "leicester", 186 | "name": "Leicester City", 187 | }, 188 | Object { 189 | "code": "BOU", 190 | "key": "bournemouth", 191 | "name": "Bournemouth", 192 | }, 193 | Object { 194 | "code": "WAT", 195 | "key": "watford", 196 | "name": "Watford", 197 | }, 198 | Object { 199 | "code": "BUR", 200 | "key": "burnley", 201 | "name": "Burnley", 202 | }, 203 | Object { 204 | "code": "HUL", 205 | "key": "hull", 206 | "name": "Hull City", 207 | }, 208 | Object { 209 | "code": "MFC", 210 | "key": "middlesbrough", 211 | "name": "Middlesbrough", 212 | }, 213 | Object { 214 | "code": "SWA", 215 | "key": "swansea", 216 | "name": "Swansea", 217 | }, 218 | ], 219 | "name": "English Premier League 2016/17", 220 | "routeName": "PremierLeague", 221 | }, 222 | } 223 | `; 224 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/__tests__/__snapshots__/team.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`GET_TEAM (LaLiga, Barcelona) 1`] = ` 4 | Object { 5 | "currentTeam": "", 6 | "image": "", 7 | "matches": Array [], 8 | } 9 | `; 10 | 11 | exports[`INITIAL STATE 1`] = ` 12 | Object { 13 | "currentTeam": "", 14 | "image": "", 15 | "matches": Array [], 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/__tests__/league.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import { getLeague } from '../../actions/league'; 3 | import league from '../league'; 4 | 5 | const store = mockStore(); 6 | 7 | beforeEach(() => { 8 | store.clearActions(); 9 | }); 10 | 11 | it('INITIAL STATE', () => { 12 | const action = { type: 'DUMMY' }; 13 | expect(league(undefined, action)).toMatchSnapshot(); 14 | }); 15 | 16 | it('GET_LEAGUE (LaLiga)', () => { 17 | expect(league(undefined, getLeague('LaLiga'))).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/__tests__/team.js: -------------------------------------------------------------------------------- 1 | import mockStore from 'redux-mock-store'; 2 | import { getTeam } from '../../actions/team'; 3 | import team from '../team'; 4 | 5 | const store = mockStore(); 6 | 7 | beforeEach(() => { 8 | store.clearActions(); 9 | }); 10 | 11 | it('INITIAL STATE', () => { 12 | const action = { type: 'DUMMY' }; 13 | expect(team(undefined, action)).toMatchSnapshot(); 14 | }); 15 | 16 | it('GET_TEAM (LaLiga, Barcelona)', () => { 17 | expect(team(undefined, getTeam('LaLiga', 'Barcelona'))).toMatchSnapshot(); 18 | }); 19 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import league from './league'; 4 | import team from './team'; 5 | import { stack, drawer } from './navigation'; 6 | 7 | export default combineReducers({ 8 | league, 9 | team, 10 | stack, 11 | drawer, 12 | }); 13 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/league.js: -------------------------------------------------------------------------------- 1 | import { GET_LEAGUE } from '../actions/types'; 2 | import { getTeams } from '../db/helpers'; 3 | 4 | const initialState = { 5 | teams: getTeams('PremierLeague'), 6 | }; 7 | 8 | export default function (state = initialState, action) { 9 | if (action.type === GET_LEAGUE) { 10 | return { ...action.payload }; 11 | } 12 | 13 | return state; 14 | } 15 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/navigation.js: -------------------------------------------------------------------------------- 1 | import { NavigationActions } from 'react-navigation'; 2 | import { GET_TEAM, BACK, TOGGLE_DRAWER, GET_LEAGUE } from '../actions/types'; 3 | import { Stack } from '../router/stack/navigationConfiguration'; 4 | import { Drawer } from '../router/drawer/navigationConfiguration'; 5 | 6 | export function stack(state, action) { 7 | switch (action.type) { 8 | case BACK: { 9 | const navigationAction = NavigationActions.back({}); 10 | return Stack.router.getStateForAction(navigationAction, state); 11 | } 12 | case GET_TEAM: { 13 | const navigationAction = NavigationActions.navigate({ 14 | routeName: 'TeamScreen', 15 | params: { ...action.payload }, 16 | }); 17 | 18 | return Stack.router.getStateForAction(navigationAction, state); 19 | } 20 | default: return Stack.router.getStateForAction(action, state); 21 | } 22 | } 23 | 24 | const initialNavState = Drawer.router.getStateForAction( 25 | Drawer.router.getActionForPathAndParams('DrawerClose')); 26 | 27 | export function drawer(state = initialNavState, action) { 28 | switch (action.type) { 29 | case GET_LEAGUE: 30 | case TOGGLE_DRAWER: { 31 | const navigationAction = NavigationActions.navigate({ 32 | routeName: state.routes[state.index].routeName === 'DrawerOpen' ? 'DrawerClose' : 'DrawerOpen', 33 | }); 34 | 35 | return Drawer.router.getStateForAction(navigationAction, state); 36 | } 37 | default: return Drawer.router.getStateForAction(action, state) || state; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/reducers/team.js: -------------------------------------------------------------------------------- 1 | import { GET_TEAM } from './../actions/types'; 2 | 3 | const initialState = { 4 | image: '', 5 | currentTeam: '', 6 | matches: [], 7 | }; 8 | 9 | export default function (state = initialState, action) { 10 | if (action.type === GET_TEAM) { 11 | return { ...action.payload }; 12 | } 13 | 14 | return state; 15 | } 16 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/router/drawer/CustomDrawerContent.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { DrawerItems } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { getLeague } from '../../actions/league'; 5 | 6 | const CustomDrawerContent = props => ( 7 | props.getLeague(route.key)} /> 8 | ); 9 | 10 | CustomDrawerContent.propTypes = { 11 | getLeague: PropTypes.func.isRequired, 12 | }; 13 | 14 | export default connect(undefined, { getLeague })(CustomDrawerContent); 15 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/router/drawer/DrawerNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { Drawer } from './navigationConfiguration'; 5 | 6 | const DrawerNavigation = ({ dispatch, navigation }) => ( 7 | 15 | ); 16 | 17 | DrawerNavigation.propTypes = { 18 | dispatch: PropTypes.func.isRequired, 19 | navigation: PropTypes.shape().isRequired, 20 | }; 21 | 22 | const mapStateToProps = state => ({ navigation: state.drawer }); 23 | export default connect(mapStateToProps)(DrawerNavigation); 24 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/router/drawer/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DrawerNavigator } from 'react-navigation'; 3 | import StackNavigation from '../stack/StackNavigation'; 4 | import CustomDrawerContent from './CustomDrawerContent'; 5 | 6 | const routeConfiguration = { 7 | PremierLeague: { 8 | screen: StackNavigation, 9 | navigationOptions: { 10 | drawer: { label: 'Premier League' }, 11 | }, 12 | }, 13 | LaLiga: { 14 | screen: StackNavigation, 15 | navigationOptions: { 16 | drawer: { label: 'La liga' }, 17 | }, 18 | }, 19 | SerieA: { 20 | screen: StackNavigation, 21 | navigationOptions: { 22 | drawer: { label: 'Serie A' }, 23 | }, 24 | }, 25 | }; 26 | 27 | export const Drawer = DrawerNavigator(routeConfiguration, { 28 | contentComponent: props => , 29 | }); 30 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/router/stack/StackNavigation.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { addNavigationHelpers } from 'react-navigation'; 3 | import { connect } from 'react-redux'; 4 | import { BackHandler } from 'react-native'; 5 | import { Stack } from './navigationConfiguration'; 6 | 7 | class StackNavigation extends Component { 8 | static propTypes = { 9 | dispatch: PropTypes.func.isRequired, 10 | navigation: PropTypes.shape().isRequired, 11 | }; 12 | 13 | constructor(props) { 14 | super(props); 15 | BackHandler.addEventListener('hardwareBackPress', this.backAction); 16 | } 17 | 18 | backAction = () => this.navigator.props.navigation.goBack(); 19 | 20 | render() { 21 | const { dispatch, navigation } = this.props; 22 | 23 | return ( 24 | { this.navigator = ref; }} 26 | navigation={ 27 | addNavigationHelpers({ 28 | dispatch, 29 | state: navigation, 30 | }) 31 | } 32 | /> 33 | ); 34 | } 35 | } 36 | 37 | export default connect(state => ({ navigation: state.stack }))(StackNavigation); 38 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/router/stack/navigationConfiguration.js: -------------------------------------------------------------------------------- 1 | import { StackNavigator } from 'react-navigation'; 2 | 3 | import LeagueComponent from '../../components/LeagueComponent'; 4 | import TeamComponent from '../../components/TeamComponent'; 5 | 6 | const routeConfiguration = { 7 | LeagueScreen: { screen: LeagueComponent }, 8 | TeamScreen: { screen: TeamComponent }, 9 | }; 10 | 11 | const stackNavigatorConfiguration = { headerMode: 'none' }; 12 | export const Stack = StackNavigator(routeConfiguration, stackNavigatorConfiguration); 13 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/js/setup.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import Spinner from './components/loaders/Spinner'; 4 | 5 | import DrawerNavigation from './router/drawer/DrawerNavigation'; 6 | import configureStore from './configureStore'; 7 | 8 | class Root extends Component { 9 | 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | store: configureStore(), 14 | }; 15 | } 16 | 17 | render() { 18 | const { store } = this.state; 19 | 20 | return !store 21 | ? 22 | : 23 | 24 | 25 | ; 26 | } 27 | } 28 | 29 | export default Root; 30 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/main.js: -------------------------------------------------------------------------------- 1 | import Expo from 'expo'; 2 | import React from 'react'; 3 | import setup from './js/setup'; 4 | 5 | Expo.registerRootComponent(setup); 6 | -------------------------------------------------------------------------------- /unit-testing-jest-enzyme/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unit-testing-jest-enzyme", 3 | "version": "0.0.0", 4 | "description": "Hello Expo!", 5 | "author": null, 6 | "private": true, 7 | "main": "main.js", 8 | "scripts": { 9 | "lint": "eslint js", 10 | "test": "jest" 11 | }, 12 | "dependencies": { 13 | "expo": "17.0.0", 14 | "react": "16.0.0-alpha.6", 15 | "react-native": "https://github.com/expo/react-native/archive/sdk-17.0.0.tar.gz", 16 | "react-navigation": "react-community/react-navigation", 17 | "react-redux": "^5.0.5", 18 | "redux": "^3.6.0", 19 | "redux-mock-store": "^1.2.3", 20 | "redux-thunk": "^2.2.0" 21 | }, 22 | "devDependencies": { 23 | "babel-eslint": "^7.2.3", 24 | "chai": "^4.0.2", 25 | "enzyme": "^2.8.2", 26 | "enzyme-to-json": "^1.5.1", 27 | "eslint": "^3.19.0", 28 | "eslint-config-airbnb": "^14.1.0", 29 | "eslint-plugin-import": "^2.2.0", 30 | "eslint-plugin-jsx-a11y": "^4.0.0", 31 | "eslint-plugin-react": "^6.10.3", 32 | "eslint-plugin-react-native": "^2.3.1", 33 | "jest": "20.0.3", 34 | "react-addons-test-utils": "^15.5.1", 35 | "react-dom": "^15.5.4", 36 | "sinon": "^2.3.4" 37 | }, 38 | "jest": { 39 | "preset": "react-native", 40 | "transformIgnorePatterns": [ 41 | "node_modules/(?!(jest-)?react-native|react-navigation)" 42 | ] 43 | } 44 | } 45 | --------------------------------------------------------------------------------