├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── victor.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── RestAPIParseAuthCleanAndroid.iml ├── build.gradle ├── data ├── .gitignore ├── build.gradle ├── data.iml ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ ├── entities │ │ │ └── Credentials.java │ │ ├── internal │ │ │ └── di │ │ │ │ ├── DataComponent.java │ │ │ │ └── DataModule.java │ │ ├── net │ │ │ ├── ConfigEndpoints.java │ │ │ ├── Endpoints.java │ │ │ └── RestApi.java │ │ ├── repositories │ │ │ └── SessionDataRepository.java │ │ └── storage │ │ │ └── Persistence.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ ├── net │ └── RestApiTest.java │ ├── repositories │ └── SessionDataRepositoryTest.java │ └── storage │ └── PersistenceTest.java ├── domain ├── .gitignore ├── build.gradle ├── domain.iml └── src │ ├── main │ └── java │ │ ├── entities │ │ └── User.java │ │ ├── interactors │ │ ├── GetUserUseCase.java │ │ ├── LoginUseCase.java │ │ ├── LogoutUseCase.java │ │ ├── SessionUseCase.java │ │ ├── SignUpUseCase.java │ │ └── UpdateUserCase.java │ │ ├── presenters │ │ ├── GetUserPresenter.java │ │ ├── LaunchPresenter.java │ │ ├── LoginPresenter.java │ │ ├── LogoutPresenter.java │ │ ├── Presenter.java │ │ ├── SignUpPresenter.java │ │ ├── UpdateUserPresenter.java │ │ └── subscribers │ │ │ ├── BaseCredentialsSubscriber.java │ │ │ ├── BaseProfileSubscriber.java │ │ │ └── BaseUseCaseSubscriber.java │ │ ├── respositories │ │ └── SessionRepository.java │ │ ├── schedulers │ │ ├── ObserveOn.java │ │ └── SubscribeOn.java │ │ └── views │ │ ├── CredentialsView.java │ │ ├── GetUserView.java │ │ ├── LaunchView.java │ │ ├── LoginView.java │ │ ├── LogoutView.java │ │ ├── ProfileView.java │ │ ├── SignUpView.java │ │ ├── UpdateUserView.java │ │ └── View.java │ └── test │ └── java │ ├── interactors │ ├── BaseSessionUseCaseTest.java │ ├── GetUserUseCaseTest.java │ ├── LoginUseCaseTest.java │ ├── LogoutUseCaseTest.java │ ├── SessionUseCaseTest.java │ ├── SignUpUseCaseTest.java │ └── UpdateUserUseCaseTest.java │ └── presenters │ ├── BasePresenterTest.java │ ├── GetUserPresenterTest.java │ ├── LaunchPresenterTest.java │ ├── LoginPresenterTest.java │ ├── LogoutPresenterTest.java │ ├── SignUpPresenterTest.java │ └── UpdateUserPresenterTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── presentation ├── .gitignore ├── build.gradle ├── presentation.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── ConnectionTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── activities │ │ ├── BaseActivity.java │ │ ├── CredentialsActivity.java │ │ ├── LaunchActivity.java │ │ └── ProfileActivity.java │ ├── fragments │ │ ├── BaseFragment.java │ │ ├── FragmentLogin.java │ │ ├── FragmentLogout.java │ │ ├── FragmentProfile.java │ │ └── FragmentSignUp.java │ ├── internal │ │ └── di │ │ │ ├── ApplicationComponent.java │ │ │ └── ApplicationModule.java │ ├── navigation │ │ └── Navigator.java │ └── utilities │ │ └── AndroidApplication.java │ └── res │ ├── layout │ ├── connect_activity.xml │ ├── fragment_login.xml │ ├── fragment_logout.xml │ ├── fragment_profile.xml │ ├── fragment_sign_up.xml │ └── profile_activity.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── settings.gradle └── store /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | RestAPIParseAuthCleanAndroid -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/victor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | unsubscribed 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Android Lint 39 | 40 | 41 | General 42 | 43 | 44 | Maven 45 | 46 | 47 | 48 | 49 | Android 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 1.7 76 | 77 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RestAPIParseAuthCleanAndroid 2 | An android implementation of an authentication system based on the Parse Api using the design patterns suggested by Robert C. Martin (aka Uncle Bob) on his “clean architecture”. 3 | 4 | # Technologies: 5 | Dagger 2, AndroidAnnotations, Retrofit, Mockito, Roboelectric, Robotium, RXJava, MVP, Dependency inversion, Dependency Injection 6 | -------------------------------------------------------------------------------- /RestAPIParseAuthCleanAndroid.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /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:1.3.0' 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 | jcenter() 18 | } 19 | } 20 | 21 | ext { 22 | compileSdkVersion = 22 23 | buildToolsVersion = "22.0.1" 24 | 25 | //Libraries 26 | daggerVersion = '2.0.1' 27 | rxJavaVersion = '1.0.14' 28 | rxAndroidVersion = '1.0.1' 29 | javaxAnnotationVersion = "10.0-b28" 30 | androidannotationsVersion = '3.3.2' 31 | supportAppCompatVersion = '22.2.1' 32 | gsonVersion = "1.7.2" 33 | retrofitVersion = "1.9.0" 34 | 35 | //Unit testing 36 | jUnitVersion = "4.12" 37 | mockitoVersion = "1.10.19" 38 | hamcrestVersion = "1.1" 39 | robolectricVersion = "3.0" 40 | 41 | //Integration testing 42 | supportTestRunnerVersion = "0.3" 43 | supportTestRulesVersion = "0.3" 44 | robotiumVersion = "5.3.1" 45 | 46 | domainDependencies = [ 47 | daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", 48 | dagger: "com.google.dagger:dagger:${daggerVersion}", 49 | rxJava: "io.reactivex:rxjava:${rxJavaVersion}", 50 | javaxAnnotation: "org.glassfish:javax.annotation:${javaxAnnotationVersion}" 51 | ] 52 | 53 | domainTestDependencies = [ 54 | junit: "junit:junit:${jUnitVersion}", 55 | mockito: "org.mockito:mockito-core:${mockitoVersion}", 56 | hamcrest: "org.hamcrest:hamcrest-library:${hamcrestVersion}" 57 | ] 58 | 59 | dataDependencies = [ 60 | retrofit: "com.squareup.retrofit:retrofit:${retrofitVersion}", 61 | daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", 62 | dagger: "com.google.dagger:dagger:${daggerVersion}", 63 | rxJava: "io.reactivex:rxjava:${rxJavaVersion}", 64 | javaxAnnotation: "org.glassfish:javax.annotation:${javaxAnnotationVersion}", 65 | supportAppCompat: "com.android.support:appcompat-v7:${supportAppCompatVersion}" 66 | ] 67 | 68 | dataTestDependencies = [ 69 | junit: "junit:junit:${jUnitVersion}", 70 | mockito: "org.mockito:mockito-core:${mockitoVersion}", 71 | hamcrest: "org.hamcrest:hamcrest-library:${hamcrestVersion}", 72 | robolectric: "org.robolectric:robolectric:${robolectricVersion}" 73 | ] 74 | 75 | presentationDependencies = [ 76 | daggerCompiler: "com.google.dagger:dagger-compiler:${daggerVersion}", 77 | dagger: "com.google.dagger:dagger:${daggerVersion}", 78 | rxJava: "io.reactivex:rxjava:${rxJavaVersion}", 79 | rxAndroid: "io.reactivex:rxandroid:${rxAndroidVersion}", 80 | javaxAnnotation: "org.glassfish:javax.annotation:${javaxAnnotationVersion}", 81 | androidannotations: "org.androidannotations:androidannotations-api:${androidannotationsVersion}", 82 | androidannotationsCompiler: "org.androidannotations:androidannotations:${androidannotationsVersion}", 83 | supportAppCompat: "com.android.support:appcompat-v7:${supportAppCompatVersion}" 84 | ] 85 | 86 | presentationTestDependencies = [ 87 | supportTestRunner: "com.android.support.test:runner:${supportTestRunnerVersion}", 88 | supportTestRules: "com.android.support.test:rules:${supportTestRulesVersion}", 89 | robotiumVersion: "com.jayway.android.robotium:robotium-solo:${robotiumVersion}" 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /data/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'android-apt' 3 | 4 | buildscript { 5 | repositories { 6 | jcenter() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' 11 | } 12 | } 13 | android { 14 | compileSdkVersion 22 15 | buildToolsVersion "22.0.1" 16 | 17 | defaultConfig { 18 | minSdkVersion 16 19 | targetSdkVersion 22 20 | versionCode 1 21 | versionName "1.0" 22 | } 23 | 24 | buildTypes { 25 | debug { 26 | testCoverageEnabled = true 27 | } 28 | release { 29 | minifyEnabled false 30 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 31 | } 32 | } 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_7 35 | targetCompatibility JavaVersion.VERSION_1_7 36 | } 37 | } 38 | 39 | apt { 40 | arguments { 41 | androidManifestFile variant.outputs[0].processResources.manifestFile 42 | resourcePackageName "edu.victoralbertos.restapiparseauthcleanandroid" 43 | } 44 | } 45 | 46 | dependencies { 47 | compile fileTree(dir: 'libs', include: ['*.jar']) 48 | compile project(':domain') 49 | 50 | 51 | def dataDependencies = rootProject.ext.dataDependencies 52 | 53 | compile dataDependencies.retrofit 54 | 55 | apt dataDependencies.daggerCompiler 56 | compile dataDependencies.dagger 57 | provided dataDependencies.javaxAnnotation 58 | 59 | compile dataDependencies.rxJava 60 | 61 | compile dataDependencies.supportAppCompat 62 | 63 | 64 | def dataTestDependencies = rootProject.ext.dataTestDependencies 65 | 66 | testCompile dataTestDependencies.junit 67 | testCompile dataTestDependencies.mockito 68 | testCompile dataTestDependencies.hamcrest 69 | testCompile dataTestDependencies.robolectric 70 | } 71 | -------------------------------------------------------------------------------- /data/data.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /data/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 /Users/victor/Documents/AndroidStudio/android_sdk/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 | -------------------------------------------------------------------------------- /data/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /data/src/main/java/entities/Credentials.java: -------------------------------------------------------------------------------- 1 | package entities; 2 | 3 | public class Credentials { 4 | private String sessionToken, objectId; 5 | 6 | public String getSessionToken() { 7 | return sessionToken; 8 | } 9 | 10 | public String getObjectId() { 11 | return objectId; 12 | } 13 | } -------------------------------------------------------------------------------- /data/src/main/java/internal/di/DataComponent.java: -------------------------------------------------------------------------------- 1 | package internal.di; 2 | 3 | import net.Endpoints; 4 | 5 | import dagger.Component; 6 | 7 | @Component(modules = DataModule.class) 8 | public interface DataComponent { 9 | Endpoints endpoints(); 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/internal/di/DataModule.java: -------------------------------------------------------------------------------- 1 | package internal.di; 2 | 3 | import com.google.gson.JsonObject; 4 | 5 | import net.ConfigEndpoints; 6 | import net.Endpoints; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import retrofit.ErrorHandler; 11 | import retrofit.RestAdapter; 12 | import retrofit.RetrofitError; 13 | 14 | @Module 15 | public class DataModule { 16 | @Provides Endpoints provideEndpoints() { 17 | return new RestAdapter.Builder() 18 | .setEndpoint(ConfigEndpoints.URL_BASE) 19 | .setErrorHandler(new ErrorHandler() { 20 | @Override public Throwable handleError(RetrofitError cause) { 21 | JsonObject jsonObject = (JsonObject) cause.getBodyAs(JsonObject.class); 22 | String message = jsonObject.get("error").getAsString(); 23 | return new RuntimeException(message); 24 | } 25 | }).build().create(Endpoints.class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /data/src/main/java/net/ConfigEndpoints.java: -------------------------------------------------------------------------------- 1 | package net; 2 | 3 | public interface ConfigEndpoints { 4 | String URL_BASE = "https://api.parse.com/1"; 5 | String HEADER_APP_ID = "X-Parse-Application-Id: KuDgG8xELX1anJVIG3igMOpzbt7pVEDml09R2Yow"; 6 | String HEADER_REST_API_KEY = "X-Parse-REST-API-Key: V2V9SyIMqgXrSL03pVuzDLlIH6z9nmBVHHjDMrh1"; 7 | } 8 | -------------------------------------------------------------------------------- /data/src/main/java/net/Endpoints.java: -------------------------------------------------------------------------------- 1 | package net; 2 | 3 | import com.google.gson.JsonObject; 4 | 5 | import entities.Credentials; 6 | import entities.User; 7 | import retrofit.http.Body; 8 | import retrofit.http.GET; 9 | import retrofit.http.Header; 10 | import retrofit.http.Headers; 11 | import retrofit.http.POST; 12 | import retrofit.http.PUT; 13 | import retrofit.http.Path; 14 | import retrofit.http.Query; 15 | import rx.Observable; 16 | 17 | public interface Endpoints { 18 | @Headers({ConfigEndpoints.HEADER_APP_ID, ConfigEndpoints.HEADER_REST_API_KEY}) 19 | @GET("/login") 20 | Observable login(@Query("username") String username, @Query("password") String password); 21 | 22 | @Headers({ConfigEndpoints.HEADER_APP_ID, ConfigEndpoints.HEADER_REST_API_KEY}) 23 | @POST("/users") 24 | Observable signUp(@Body User user); 25 | 26 | @Headers({ConfigEndpoints.HEADER_APP_ID, ConfigEndpoints.HEADER_REST_API_KEY}) 27 | @GET("/users/me") 28 | Observable currentSession(@Header("X-Parse-Session-Token") String token); 29 | 30 | @Headers({ConfigEndpoints.HEADER_APP_ID, ConfigEndpoints.HEADER_REST_API_KEY}) 31 | @PUT("/users/{objectId}") 32 | Observable update(@Header("X-Parse-Session-Token") String token, 33 | @Path("objectId") String objectId, @Body User user); 34 | } 35 | -------------------------------------------------------------------------------- /data/src/main/java/net/RestApi.java: -------------------------------------------------------------------------------- 1 | package net; 2 | 3 | import com.google.gson.JsonObject; 4 | 5 | import javax.inject.Inject; 6 | 7 | import entities.Credentials; 8 | import entities.User; 9 | import rx.Observable; 10 | 11 | public class RestApi { 12 | private final Endpoints endpoints; 13 | 14 | @Inject public RestApi(Endpoints endpoints) { 15 | this.endpoints = endpoints; 16 | } 17 | 18 | public Observable login(String username, String password) { 19 | return endpoints.login(username, password); 20 | } 21 | 22 | public Observable signUp(User user) { 23 | return endpoints.signUp(user); 24 | } 25 | 26 | public Observable currentSession(String token) { 27 | return endpoints.currentSession(token); 28 | } 29 | 30 | public Observable update(String token, String objectId, User user) { 31 | return endpoints.update(token, objectId, user); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /data/src/main/java/repositories/SessionDataRepository.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.gson.JsonObject; 6 | 7 | import net.RestApi; 8 | 9 | import javax.inject.Inject; 10 | 11 | import edu.victoralbertos.data.R; 12 | import entities.Credentials; 13 | import entities.User; 14 | import respositories.SessionRepository; 15 | import rx.Observable; 16 | import rx.Subscriber; 17 | import rx.functions.Func1; 18 | import storage.Persistence; 19 | 20 | public class SessionDataRepository implements SessionRepository { 21 | private final RestApi restApi; 22 | private final Persistence persistence; 23 | private final Context context; 24 | 25 | @Inject public SessionDataRepository(Context context, RestApi restApi, Persistence persistence) { 26 | this.context = context; 27 | this.restApi = restApi; 28 | this.persistence = persistence; 29 | } 30 | 31 | @Override public Observable askForLogin(String username, String password) { 32 | return restApi.login(username, password).map(new Func1() { 33 | @Override public String call(Credentials credentials) { 34 | persistence.save(Credentials.class.getName(), credentials); 35 | return context.getString(R.string.success); 36 | } 37 | }); 38 | } 39 | 40 | @Override public Observable askForUserLogged() { 41 | Credentials credentials = persistence.retrieve(Credentials.class.getName(), Credentials.class); 42 | if (credentials == null) return notLoggedUserError(); 43 | 44 | return restApi.currentSession(credentials.getSessionToken()); 45 | } 46 | 47 | @Override public Observable askForUpdateLoggedUser(User user) { 48 | Credentials credentials = persistence.retrieve(Credentials.class.getName(), Credentials.class); 49 | if (credentials == null) return notLoggedUserError(); 50 | 51 | String token = credentials.getSessionToken(); 52 | String objectId = credentials.getObjectId(); 53 | 54 | return restApi.update(token, objectId, user).map(new Func1() { 55 | @Override public String call(JsonObject jsonObject) { 56 | return context.getString(R.string.success); 57 | } 58 | }); 59 | } 60 | 61 | @Override public Observable askForSignUp(User user) { 62 | return restApi.signUp(user).map(new Func1() { 63 | @Override public String call(Credentials credentials) { 64 | persistence.save(Credentials.class.getName(), credentials); 65 | return context.getString(R.string.success); 66 | } 67 | }); 68 | } 69 | 70 | @Override public Observable askForLogout() { 71 | Credentials credentials = persistence.retrieve(Credentials.class.getName(), Credentials.class); 72 | if (credentials == null) return notLoggedUserError(); 73 | 74 | persistence.delete(Credentials.class.getName()); 75 | return Observable.just(context.getString(R.string.success)); 76 | } 77 | 78 | private Observable notLoggedUserError() { 79 | return Observable.create(new Observable.OnSubscribe() { 80 | @Override 81 | public void call(Subscriber subscriber) { 82 | subscriber.onError(new RuntimeException(context.getString(R.string.not_user_logged))); 83 | } 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /data/src/main/java/storage/Persistence.java: -------------------------------------------------------------------------------- 1 | package storage; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.google.gson.Gson; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.File; 10 | import java.io.FileReader; 11 | import java.io.FileWriter; 12 | 13 | import javax.inject.Inject; 14 | 15 | public class Persistence { 16 | private final Context context; 17 | 18 | @Inject public Persistence(Context context) { 19 | this.context = context; 20 | } 21 | 22 | public boolean save(String key, Object data) { 23 | String wrapperJSONSerialized = new Gson().toJson(data); 24 | try { 25 | File file = new File(context.getFilesDir(), key); 26 | 27 | FileWriter fileWriter = new FileWriter(file, false); 28 | fileWriter.write(wrapperJSONSerialized); 29 | fileWriter.flush(); 30 | fileWriter.close(); 31 | return true; 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | return false; 35 | } 36 | } 37 | 38 | public boolean delete(String key) { 39 | File file = new File(context.getFilesDir(), key); 40 | return file.delete(); 41 | } 42 | 43 | @Nullable public T retrieve(String key, Class clazz) { 44 | try { 45 | File file = new File(context.getFilesDir(), key); 46 | BufferedReader bufferedReader = new BufferedReader(new FileReader(file.getAbsoluteFile())); 47 | return new Gson().fromJson(bufferedReader, clazz); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /data/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Data 3 | Good! 4 | Not good! 5 | Nor user logged! 6 | 7 | -------------------------------------------------------------------------------- /data/src/test/java/net/RestApiTest.java: -------------------------------------------------------------------------------- 1 | package net; 2 | 3 | import com.google.gson.JsonObject; 4 | 5 | import org.junit.Before; 6 | import org.junit.FixMethodOrder; 7 | import org.junit.Test; 8 | import org.junit.runners.MethodSorters; 9 | 10 | import entities.Credentials; 11 | import entities.User; 12 | import internal.di.DaggerDataComponent; 13 | import rx.observers.TestSubscriber; 14 | 15 | import static org.hamcrest.MatcherAssert.assertThat; 16 | import static org.hamcrest.Matchers.is; 17 | 18 | @FixMethodOrder(MethodSorters.NAME_ASCENDING) 19 | public class RestApiTest { 20 | private RestApi restApi; 21 | 22 | @Before public void setUp() { 23 | Endpoints endpoints = DaggerDataComponent.create().endpoints(); 24 | restApi = new RestApi(endpoints); 25 | } 26 | 27 | @Test public void first_When_Sign_Up_With_Valid_Inputs_Then_Get_Credentials() { 28 | TestSubscriber subscriber = new TestSubscriber<>(); 29 | restApi.signUp(makeValidUser()).subscribe(subscriber); 30 | 31 | subscriber.awaitTerminalEvent(); 32 | credentials = subscriber.getOnNextEvents().get(0); 33 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 34 | } 35 | 36 | @Test public void first_When_Sign_Up_With_Invalid_Inputs_Then_Throw_An_ExceptionOnSubscriber() { 37 | TestSubscriber subscriber = new TestSubscriber<>(); 38 | restApi.signUp(makeInvalidUser()).subscribe(subscriber); 39 | 40 | subscriber.awaitTerminalEvent(); 41 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 42 | } 43 | 44 | @Test public void second_When_Update_With_Valid_Inputs_Then_User_Is_Updated() { 45 | TestSubscriber subscriber = new TestSubscriber<>(); 46 | restApi.update(credentials.getSessionToken(), credentials.getObjectId(), makeValidUser()).subscribe(subscriber); 47 | 48 | subscriber.awaitTerminalEvent(); 49 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 50 | } 51 | 52 | @Test public void second_When_Update_With_Invalid_Inputs_Then_User_Is_Not_Updated() { 53 | TestSubscriber subscriber = new TestSubscriber<>(); 54 | restApi.update("anInvalidToken", "anObjectId", makeInvalidUser()).subscribe(subscriber); 55 | 56 | subscriber.awaitTerminalEvent(); 57 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 58 | } 59 | 60 | @Test public void third_When_Ask_For_User_With_Valid_Inputs_Then_Get_User() { 61 | TestSubscriber subscriber = new TestSubscriber<>(); 62 | restApi.currentSession(credentials.getSessionToken()).subscribe(subscriber); 63 | 64 | subscriber.awaitTerminalEvent(); 65 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 66 | } 67 | 68 | @Test public void third_When_Ask_For_User_With_Invalid_Inputs_Then_Throw_An_Exception_On_Subscriber() { 69 | TestSubscriber subscriber = new TestSubscriber<>(); 70 | restApi.currentSession("anInvalidToken").subscribe(subscriber); 71 | 72 | subscriber.awaitTerminalEvent(); 73 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 74 | } 75 | 76 | @Test public void fourth_When_Login_With_Valid_Inputs_Then_Get_Credentials() { 77 | TestSubscriber subscriber = new TestSubscriber<>(); 78 | restApi.login(makeValidUser().getUsername(), makeValidUser().getPassword()).subscribe(subscriber); 79 | 80 | subscriber.awaitTerminalEvent(); 81 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 82 | } 83 | 84 | @Test public void fourth_When_Login_With_Invalid_Inputs_Then_Throw_An_ExceptionOnSubscriber() { 85 | TestSubscriber subscriber = new TestSubscriber<>(); 86 | restApi.login("anInvalidUsername", "anInvalidPassword").subscribe(subscriber); 87 | 88 | subscriber.awaitTerminalEvent(); 89 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 90 | } 91 | 92 | private User makeInvalidUser() { 93 | return new User(); 94 | } 95 | 96 | private static Credentials credentials; 97 | private static User user; 98 | private static User makeValidUser() { 99 | if (user != null) return user; 100 | 101 | long time = System.currentTimeMillis(); 102 | String username = "ut" + time; 103 | String email = "et@" + time + "t.com"; 104 | String phone = "pht" + time; 105 | String password = "pat" + time; 106 | return user = new User(username, email, phone, password); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /data/src/test/java/repositories/SessionDataRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package repositories; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.gson.JsonObject; 6 | 7 | import net.RestApi; 8 | 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.mockito.Mock; 12 | import org.mockito.MockitoAnnotations; 13 | 14 | import entities.Credentials; 15 | import entities.User; 16 | import rx.Observable; 17 | import rx.Subscriber; 18 | import rx.observers.TestSubscriber; 19 | import storage.Persistence; 20 | 21 | import static org.hamcrest.MatcherAssert.assertThat; 22 | import static org.hamcrest.Matchers.is; 23 | import static org.mockito.Matchers.any; 24 | import static org.mockito.Matchers.eq; 25 | import static org.mockito.Mockito.verify; 26 | import static org.mockito.Mockito.verifyZeroInteractions; 27 | import static org.mockito.Mockito.when; 28 | 29 | public class SessionDataRepositoryTest { 30 | @Mock private RestApi restApi; 31 | @Mock private Persistence persistence; 32 | @Mock private Context context; 33 | private SessionDataRepository sessionDataRepository; 34 | 35 | @Before public void setUp() { 36 | MockitoAnnotations.initMocks(this); 37 | sessionDataRepository = new SessionDataRepository(context, restApi, persistence); 38 | } 39 | 40 | @Test public void when_Login_With_Valid_Inputs_Then_Get_Credentials_And_Saved_It() { 41 | when(restApi.login(any(String.class), any(String.class))).thenReturn(Observable.just(new Credentials())); 42 | 43 | TestSubscriber subscriber = new TestSubscriber<>(); 44 | sessionDataRepository.askForLogin("username", "password").subscribe(subscriber); 45 | subscriber.awaitTerminalEvent(); 46 | 47 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 48 | verify(persistence).save(any(String.class), any(Object.class)); 49 | } 50 | 51 | @Test public void when_Login_With_Invalid_Inputs_Then_Credentials_Is_Not_Saved() { 52 | when(restApi.login(any(String.class), any(String.class))).thenReturn(Observable.create( 53 | new Observable.OnSubscribe() { 54 | @Override 55 | public void call(Subscriber subscriber) { 56 | subscriber.onError(new RuntimeException("Not Great")); 57 | } 58 | }) 59 | ); 60 | 61 | TestSubscriber subscriber = new TestSubscriber<>(); 62 | sessionDataRepository.askForLogin("username", "password").subscribe(subscriber); 63 | subscriber.awaitTerminalEvent(); 64 | 65 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 66 | verifyZeroInteractions(persistence); 67 | } 68 | 69 | @Test public void when_Get_User_Being_Logged_Then_Get_User() { 70 | Credentials credentials = new Credentials(); 71 | 72 | when(persistence.retrieve(any(String.class), eq(Credentials.class))).thenReturn(credentials); 73 | when(restApi.currentSession(null)).thenReturn(Observable.just(new User())); 74 | 75 | TestSubscriber subscriber = new TestSubscriber<>(); 76 | sessionDataRepository.askForUserLogged().subscribe(subscriber); 77 | subscriber.awaitTerminalEvent(); 78 | 79 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 80 | } 81 | 82 | @Test public void when_Get_User_Not_Being_Logged_Then_Throw_Exception_On_Subscribe() { 83 | TestSubscriber subscriber = new TestSubscriber<>(); 84 | sessionDataRepository.askForUserLogged().subscribe(subscriber); 85 | subscriber.awaitTerminalEvent(); 86 | 87 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 88 | } 89 | 90 | @Test public void when_Update_User_Being_Logged_Then_Get_User() { 91 | Credentials credentials = new Credentials(); 92 | 93 | when(persistence.retrieve(any(String.class), eq(Credentials.class))).thenReturn(credentials); 94 | when(restApi.update(any(String.class), any(String.class), any(User.class))).thenReturn(Observable.just(new JsonObject())); 95 | 96 | TestSubscriber subscriber = new TestSubscriber<>(); 97 | sessionDataRepository.askForUpdateLoggedUser(new User()).subscribe(subscriber); 98 | subscriber.awaitTerminalEvent(); 99 | 100 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 101 | } 102 | 103 | @Test public void when_Update_User_Not_Being_Logged_Then_Throw_Exception_On_Subscribe() { 104 | TestSubscriber subscriber = new TestSubscriber<>(); 105 | sessionDataRepository.askForUpdateLoggedUser(new User()).subscribe(subscriber); 106 | subscriber.awaitTerminalEvent(); 107 | 108 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 109 | } 110 | 111 | @Test public void when_Sign_Up_With_Valid_Inputs_Then_Get_Credentials_And_Saved_It() { 112 | when(restApi.signUp(any(User.class))).thenReturn(Observable.just(new Credentials())); 113 | 114 | TestSubscriber subscriber = new TestSubscriber<>(); 115 | sessionDataRepository.askForSignUp(new User()).subscribe(subscriber); 116 | subscriber.awaitTerminalEvent(); 117 | 118 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 119 | verify(persistence).save(any(String.class), any(Object.class)); 120 | } 121 | 122 | @Test public void when_Sign_Up_With_Invalid_Inputs_Then_Credentials_Is_Not_Saved() { 123 | when(restApi.signUp(null)).thenReturn(Observable.create( 124 | new Observable.OnSubscribe() { 125 | @Override 126 | public void call(Subscriber subscriber) { 127 | subscriber.onError(new RuntimeException("Not Great")); 128 | } 129 | }) 130 | ); 131 | 132 | TestSubscriber subscriber = new TestSubscriber<>(); 133 | sessionDataRepository.askForSignUp(null).subscribe(subscriber); 134 | subscriber.awaitTerminalEvent(); 135 | 136 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 137 | verifyZeroInteractions(persistence); 138 | } 139 | 140 | @Test public void when_Logout_With_Active_Session_Then_Get_A_Response_As_String() { 141 | when(persistence.retrieve(any(String.class), eq(Credentials.class))).thenReturn(new Credentials()); 142 | 143 | TestSubscriber subscriber = new TestSubscriber<>(); 144 | sessionDataRepository.askForLogout().subscribe(subscriber); 145 | subscriber.awaitTerminalEvent(); 146 | 147 | verify(persistence).delete(Credentials.class.getName()); 148 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 149 | } 150 | 151 | @Test public void when_Logout_Without_Active_Session_Then_Throw_An_Exception_On_Subscriber() { 152 | when(persistence.retrieve(any(String.class), eq(Credentials.class))).thenReturn(null); 153 | 154 | TestSubscriber subscriber = new TestSubscriber<>(); 155 | sessionDataRepository.askForLogout().subscribe(subscriber); 156 | subscriber.awaitTerminalEvent(); 157 | 158 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /data/src/test/java/storage/PersistenceTest.java: -------------------------------------------------------------------------------- 1 | package storage; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.robolectric.RobolectricGradleTestRunner; 7 | import org.robolectric.RuntimeEnvironment; 8 | import org.robolectric.annotation.Config; 9 | 10 | import edu.victoralbertos.data.BuildConfig; 11 | 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.hamcrest.core.Is.is; 14 | import static org.hamcrest.core.IsNot.not; 15 | 16 | @RunWith(RobolectricGradleTestRunner.class) 17 | @Config(constants = BuildConfig.class, sdk = 21) 18 | public class PersistenceTest { 19 | private Persistence persistence; 20 | private final static String KEY = "store"; 21 | private final static String VALUE = "dummy"; 22 | 23 | @Before public void setUp() { 24 | persistence = new Persistence(RuntimeEnvironment.application); 25 | } 26 | 27 | @Test public void when_A_Valid_Pair_Is_Supplied_Then_Get_True() { 28 | boolean result = persistence.save(KEY, VALUE); 29 | assertThat(result, is(true)); 30 | } 31 | 32 | @Test public void when_An_Invalid_Pair_Is_Supplied_Then_Get_False() { 33 | boolean result = persistence.save(null, null); 34 | assertThat(result, is(not(true))); 35 | } 36 | 37 | @Test public void when_A_Valid_Pair_Is_Supplied_And_Retrieve_Then_Get_It() { 38 | persistence.save(KEY, VALUE); 39 | 40 | String result = persistence.retrieve(KEY, String.class); 41 | assertThat(result, is(VALUE)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /domain/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /domain/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | sourceCompatibility = 1.7 4 | targetCompatibility = 1.7 5 | 6 | configurations { 7 | provided 8 | } 9 | 10 | sourceSets { 11 | main { 12 | compileClasspath += configurations.provided 13 | } 14 | } 15 | 16 | dependencies { 17 | compile fileTree(dir: 'libs', include: ['*.jar']) 18 | 19 | def domainDependencies = rootProject.ext.domainDependencies 20 | 21 | compile domainDependencies.dagger 22 | provided domainDependencies.daggerCompiler 23 | provided domainDependencies.javaxAnnotation 24 | 25 | compile domainDependencies.rxJava 26 | 27 | def domainTestDependencies = rootProject.ext.domainTestDependencies 28 | 29 | testCompile domainTestDependencies.junit 30 | testCompile domainTestDependencies.mockito 31 | testCompile domainTestDependencies.hamcrest 32 | } -------------------------------------------------------------------------------- /domain/domain.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /domain/src/main/java/entities/User.java: -------------------------------------------------------------------------------- 1 | package entities; 2 | 3 | public class User { 4 | private String username, email, phone, password; 5 | 6 | public User() {} 7 | 8 | public User(String username, String email, String phone, String password) { 9 | this.username = username; 10 | this.email = email; 11 | this.phone = phone; 12 | this.password = password; 13 | } 14 | 15 | public User(String username, String email, String phone) { 16 | this.username = username; 17 | this.email = email; 18 | this.phone = phone; 19 | } 20 | 21 | public String getUsername() { 22 | return username; 23 | } 24 | 25 | public String getPassword() { 26 | return password; 27 | } 28 | 29 | public String getEmail() { 30 | return email; 31 | } 32 | 33 | public String getPhone() { 34 | return phone; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/GetUserUseCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import schedulers.ObserveOn; 7 | import schedulers.SubscribeOn; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | 11 | public class GetUserUseCase extends SessionUseCase { 12 | @Inject public GetUserUseCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 13 | super(sessionRepository, subscribeOn, observeOn); 14 | } 15 | 16 | @Override protected Observable buildUseCaseObservable() { 17 | return sessionRepository.askForUserLogged(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/LoginUseCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import javax.inject.Inject; 4 | 5 | import schedulers.ObserveOn; 6 | import schedulers.SubscribeOn; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | 10 | public class LoginUseCase extends SessionUseCase { 11 | private String username, password; 12 | 13 | @Inject public LoginUseCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 14 | super(sessionRepository, subscribeOn, observeOn); 15 | } 16 | 17 | public void doLogin(String username, String password) { 18 | this.username = username; 19 | this.password = password; 20 | } 21 | 22 | @Override protected Observable buildUseCaseObservable() { 23 | return sessionRepository.askForLogin(username, password); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/LogoutUseCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import javax.inject.Inject; 4 | 5 | import schedulers.ObserveOn; 6 | import schedulers.SubscribeOn; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | 10 | public class LogoutUseCase extends SessionUseCase { 11 | 12 | @Inject public LogoutUseCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 13 | super(sessionRepository, subscribeOn, observeOn); 14 | } 15 | 16 | @Override protected Observable buildUseCaseObservable() { 17 | return sessionRepository.askForLogout(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/SessionUseCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import schedulers.ObserveOn; 4 | import schedulers.SubscribeOn; 5 | import respositories.SessionRepository; 6 | import rx.Observable; 7 | import rx.Subscriber; 8 | import rx.Subscription; 9 | import rx.subscriptions.Subscriptions; 10 | 11 | public abstract class SessionUseCase { 12 | protected final SessionRepository sessionRepository; 13 | private final SubscribeOn subscribeOn; 14 | private final ObserveOn observeOn; 15 | private Subscription subscription = Subscriptions.empty(); 16 | 17 | protected SessionUseCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 18 | this.sessionRepository = sessionRepository; 19 | this.subscribeOn = subscribeOn; 20 | this.observeOn = observeOn; 21 | } 22 | 23 | public void execute(Subscriber subscriber) { 24 | subscription = buildUseCaseObservable() 25 | .subscribeOn(subscribeOn.getScheduler()) 26 | .observeOn(observeOn.getScheduler()) 27 | .subscribe(subscriber); 28 | } 29 | 30 | public void unsubscribe() { 31 | if (!subscription.isUnsubscribed()) { 32 | subscription.unsubscribe(); 33 | } 34 | } 35 | 36 | protected abstract Observable buildUseCaseObservable(); 37 | } 38 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/SignUpUseCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import schedulers.ObserveOn; 7 | import schedulers.SubscribeOn; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | 11 | public class SignUpUseCase extends SessionUseCase { 12 | private User user; 13 | 14 | @Inject public SignUpUseCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 15 | super(sessionRepository, subscribeOn, observeOn); 16 | } 17 | 18 | public void setUser(User user) { 19 | this.user = user; 20 | } 21 | 22 | @Override protected Observable buildUseCaseObservable() { 23 | return sessionRepository.askForSignUp(user); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /domain/src/main/java/interactors/UpdateUserCase.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import schedulers.ObserveOn; 7 | import schedulers.SubscribeOn; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | 11 | public class UpdateUserCase extends SessionUseCase { 12 | private User user; 13 | 14 | @Inject public UpdateUserCase(SessionRepository sessionRepository, SubscribeOn subscribeOn, ObserveOn observeOn) { 15 | super(sessionRepository, subscribeOn, observeOn); 16 | } 17 | 18 | public void setUserToUpdate(User user) { 19 | this.user = user; 20 | } 21 | 22 | @Override protected Observable buildUseCaseObservable() { 23 | return sessionRepository.askForUpdateLoggedUser(user); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/GetUserPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import interactors.GetUserUseCase; 7 | import presenters.subscribers.BaseProfileSubscriber; 8 | import views.GetUserView; 9 | 10 | public class GetUserPresenter implements Presenter { 11 | private final GetUserUseCase getUserUseCase; 12 | 13 | @Inject public GetUserPresenter(GetUserUseCase getUserUseCase) { 14 | this.getUserUseCase = getUserUseCase; 15 | } 16 | 17 | @Override public void attachView(GetUserView getUserView) { 18 | getUserUseCase.execute(new BaseProfileSubscriber(getUserView) { 19 | @Override public void onNext(User user) { 20 | profileView.hideProgress(); 21 | profileView.onSuccess(user); 22 | } 23 | }); 24 | } 25 | 26 | @Override public void destroy() { 27 | getUserUseCase.unsubscribe(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/LaunchPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import interactors.GetUserUseCase; 7 | import presenters.subscribers.BaseUseCaseSubscriber; 8 | import views.LaunchView; 9 | 10 | public class LaunchPresenter implements Presenter { 11 | private final GetUserUseCase getUserUseCase; 12 | 13 | @Inject public LaunchPresenter(GetUserUseCase getUserUseCase) { 14 | this.getUserUseCase = getUserUseCase; 15 | } 16 | 17 | @Override public void attachView(LaunchView launchView) { 18 | getUserUseCase.execute(new LaunchSubscriber(launchView)); 19 | } 20 | 21 | @Override public void destroy() { 22 | getUserUseCase.unsubscribe(); 23 | } 24 | 25 | private static class LaunchSubscriber extends BaseUseCaseSubscriber { 26 | private final LaunchView launchView; 27 | 28 | public LaunchSubscriber(LaunchView launchView) { 29 | this.launchView = launchView; 30 | } 31 | 32 | @Override public void onError(Throwable e) { 33 | launchView.goToCredentials(); 34 | } 35 | 36 | @Override public void onNext(User user) { 37 | launchView.goToProfile(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/LoginPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import interactors.LoginUseCase; 6 | import presenters.subscribers.BaseCredentialsSubscriber; 7 | import views.LoginView; 8 | 9 | public class LoginPresenter implements Presenter { 10 | private final LoginUseCase loginUseCase; 11 | private LoginView loginView; 12 | 13 | @Inject public LoginPresenter(LoginUseCase loginUseCase) { 14 | this.loginUseCase = loginUseCase; 15 | } 16 | 17 | @Override public void attachView(LoginView loginView) { 18 | this.loginView = loginView; 19 | } 20 | 21 | public void doLogin(String username, String password) { 22 | loginUseCase.doLogin(username, password); 23 | loginUseCase.execute(new BaseCredentialsSubscriber(loginView) {}); 24 | } 25 | 26 | @Override public void destroy() { 27 | loginUseCase.unsubscribe(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/LogoutPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import interactors.LogoutUseCase; 6 | import presenters.subscribers.BaseProfileSubscriber; 7 | import views.LogoutView; 8 | 9 | public class LogoutPresenter implements Presenter { 10 | private final LogoutUseCase logoutUseCase; 11 | private LogoutView logoutView; 12 | 13 | @Inject public LogoutPresenter(LogoutUseCase logoutUseCase) { 14 | this.logoutUseCase = logoutUseCase; 15 | } 16 | 17 | @Override public void attachView(LogoutView logoutView) { 18 | this.logoutView = logoutView; 19 | } 20 | 21 | public void doLogout() { 22 | logoutUseCase.execute(new BaseProfileSubscriber(logoutView) { 23 | @Override public void onNext(String message) { 24 | profileView.hideProgress(); 25 | profileView.onSuccess(message); 26 | profileView.toCredentials(); 27 | } 28 | }); 29 | } 30 | 31 | @Override public void destroy() { 32 | logoutUseCase.unsubscribe(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/Presenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import views.View; 4 | 5 | public interface Presenter { 6 | void attachView(T view); 7 | void destroy(); 8 | } 9 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/SignUpPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import interactors.SignUpUseCase; 7 | import presenters.subscribers.BaseCredentialsSubscriber; 8 | import views.SignUpView; 9 | 10 | public class SignUpPresenter implements Presenter { 11 | private final SignUpUseCase singUpUseCase; 12 | private SignUpView signUpView; 13 | 14 | @Inject public SignUpPresenter(SignUpUseCase singUpUseCase) { 15 | this.singUpUseCase = singUpUseCase; 16 | } 17 | 18 | @Override public void attachView(SignUpView signUpView) { 19 | this.signUpView = signUpView; 20 | } 21 | 22 | @Override public void destroy() { 23 | singUpUseCase.unsubscribe(); 24 | } 25 | 26 | public void doSignUp(User user) { 27 | singUpUseCase.setUser(user); 28 | singUpUseCase.execute(new BaseCredentialsSubscriber(signUpView){}); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/UpdateUserPresenter.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import javax.inject.Inject; 4 | 5 | import entities.User; 6 | import interactors.UpdateUserCase; 7 | import presenters.subscribers.BaseProfileSubscriber; 8 | import views.UpdateUserView; 9 | 10 | public class UpdateUserPresenter implements Presenter { 11 | private final UpdateUserCase updateUserCase; 12 | private UpdateUserView updateUserView; 13 | 14 | @Inject public UpdateUserPresenter(UpdateUserCase updateUserCase) { 15 | this.updateUserCase = updateUserCase; 16 | } 17 | 18 | @Override public void attachView(UpdateUserView updateUserView) { 19 | this.updateUserView = updateUserView; 20 | } 21 | 22 | public void doUpdateUser(User user) { 23 | updateUserCase.setUserToUpdate(user); 24 | updateUserCase.execute(new BaseProfileSubscriber(updateUserView) { 25 | @Override public void onNext(String message) { 26 | profileView.hideProgress(); 27 | profileView.onSuccess(message); 28 | } 29 | }); 30 | } 31 | 32 | @Override public void destroy() { 33 | updateUserCase.unsubscribe(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /domain/src/main/java/presenters/subscribers/BaseCredentialsSubscriber.java: -------------------------------------------------------------------------------- 1 | package presenters.subscribers; 2 | 3 | import views.CredentialsView; 4 | 5 | public abstract class BaseCredentialsSubscriber extends BaseUseCaseSubscriber { 6 | private final View credentialsView; 7 | 8 | public BaseCredentialsSubscriber(View credentialsView) { 9 | this.credentialsView = credentialsView; 10 | } 11 | 12 | @Override public void onStart() { 13 | credentialsView.showProgress(); 14 | } 15 | 16 | @Override public void onError(Throwable e) { 17 | credentialsView.hideProgress(); 18 | credentialsView.onError(e.getMessage()); 19 | } 20 | 21 | @Override public void onNext(String response) { 22 | credentialsView.hideProgress(); 23 | credentialsView.onSuccess(response); 24 | credentialsView.goToProfile(); 25 | } 26 | } -------------------------------------------------------------------------------- /domain/src/main/java/presenters/subscribers/BaseProfileSubscriber.java: -------------------------------------------------------------------------------- 1 | package presenters.subscribers; 2 | 3 | import views.ProfileView; 4 | 5 | public abstract class BaseProfileSubscriber extends BaseUseCaseSubscriber { 6 | protected final View profileView; 7 | 8 | public BaseProfileSubscriber(View profileView) { 9 | this.profileView = profileView; 10 | } 11 | 12 | @Override public void onStart() { 13 | profileView.showProgress(); 14 | } 15 | 16 | @Override public void onError(Throwable e) { 17 | profileView.hideProgress(); 18 | profileView.onError(e.getMessage()); 19 | } 20 | } -------------------------------------------------------------------------------- /domain/src/main/java/presenters/subscribers/BaseUseCaseSubscriber.java: -------------------------------------------------------------------------------- 1 | package presenters.subscribers; 2 | 3 | import rx.Subscriber; 4 | 5 | public abstract class BaseUseCaseSubscriber extends Subscriber { 6 | @Override public void onCompleted() {} 7 | 8 | @Override public void onError(Throwable e) {} 9 | 10 | @Override public void onNext(T t) {} 11 | } 12 | -------------------------------------------------------------------------------- /domain/src/main/java/respositories/SessionRepository.java: -------------------------------------------------------------------------------- 1 | package respositories; 2 | 3 | import entities.User; 4 | import rx.Observable; 5 | 6 | public interface SessionRepository { 7 | Observable askForLogin(String username, String password); 8 | Observable askForSignUp(User user); 9 | Observable askForUserLogged(); 10 | Observable askForUpdateLoggedUser(User user); 11 | Observable askForLogout(); 12 | } -------------------------------------------------------------------------------- /domain/src/main/java/schedulers/ObserveOn.java: -------------------------------------------------------------------------------- 1 | package schedulers; 2 | 3 | import rx.Scheduler; 4 | 5 | public interface ObserveOn { 6 | Scheduler getScheduler(); 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/schedulers/SubscribeOn.java: -------------------------------------------------------------------------------- 1 | package schedulers; 2 | 3 | import rx.Scheduler; 4 | 5 | public interface SubscribeOn { 6 | Scheduler getScheduler(); 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/views/CredentialsView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface CredentialsView extends View { 4 | void showProgress(); 5 | void hideProgress(); 6 | void onError(String message); 7 | void onSuccess(String message); 8 | void goToProfile(); 9 | } 10 | -------------------------------------------------------------------------------- /domain/src/main/java/views/GetUserView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | import entities.User; 4 | 5 | public interface GetUserView extends ProfileView { 6 | void onSuccess(User user); 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/views/LaunchView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface LaunchView extends View { 4 | void goToCredentials(); 5 | void goToProfile(); 6 | } 7 | -------------------------------------------------------------------------------- /domain/src/main/java/views/LoginView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface LoginView extends CredentialsView { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /domain/src/main/java/views/LogoutView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface LogoutView extends ProfileView { 4 | void onSuccess(String message); 5 | void toCredentials(); 6 | } 7 | -------------------------------------------------------------------------------- /domain/src/main/java/views/ProfileView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface ProfileView extends View { 4 | void showProgress(); 5 | void hideProgress(); 6 | void onError(String message); 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/views/SignUpView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface SignUpView extends CredentialsView { 4 | } 5 | -------------------------------------------------------------------------------- /domain/src/main/java/views/UpdateUserView.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface UpdateUserView extends ProfileView { 4 | void onSuccess(String message); 5 | } 6 | -------------------------------------------------------------------------------- /domain/src/main/java/views/View.java: -------------------------------------------------------------------------------- 1 | package views; 2 | 3 | public interface View { 4 | } 5 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/BaseSessionUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | 4 | import org.junit.Before; 5 | import org.mockito.Mock; 6 | import org.mockito.MockitoAnnotations; 7 | 8 | import schedulers.ObserveOn; 9 | import schedulers.SubscribeOn; 10 | import rx.schedulers.Schedulers; 11 | 12 | import static org.mockito.Mockito.when; 13 | 14 | public abstract class BaseSessionUseCaseTest { 15 | @Mock protected ObserveOn observeOn; 16 | @Mock protected SubscribeOn subscribeOn; 17 | 18 | @Before public void setUp() { 19 | MockitoAnnotations.initMocks(this); 20 | when(observeOn.getScheduler()).thenReturn(Schedulers.newThread()); 21 | when(subscribeOn.getScheduler()).thenReturn(Schedulers.newThread()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/GetUserUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | import rx.Subscriber; 10 | import rx.observers.TestSubscriber; 11 | 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.hamcrest.Matchers.is; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class GetUserUseCaseTest extends BaseSessionUseCaseTest { 17 | private GetUserUseCase getUserUseCase; 18 | @Mock private SessionRepository sessionRepository; 19 | 20 | @Override public void setUp() { 21 | super.setUp(); 22 | getUserUseCase = new GetUserUseCase(sessionRepository, subscribeOn, observeOn); 23 | } 24 | 25 | @Test public void when_There_Is_A_User_Logged_Then_Get_User() { 26 | when(sessionRepository.askForUserLogged()).thenReturn(Observable.just(new User())); 27 | 28 | TestSubscriber subscriber = new TestSubscriber<>(); 29 | getUserUseCase.execute(subscriber); 30 | subscriber.awaitTerminalEvent(); 31 | 32 | assertThat(subscriber.getOnNextEvents().size(), is(1));; 33 | } 34 | 35 | @Test public void when_There_Is_Not_A_User_Logged_Then_Throw_An_Exception_On_Subscriber() { 36 | when(sessionRepository.askForUserLogged()).thenReturn(Observable.create(new Observable.OnSubscribe() { 37 | @Override 38 | public void call(Subscriber subscriber) { 39 | subscriber.onError(new RuntimeException("Not User")); 40 | } 41 | })); 42 | 43 | TestSubscriber subscriber = new TestSubscriber<>(); 44 | getUserUseCase.execute(subscriber); 45 | subscriber.awaitTerminalEvent(); 46 | 47 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/LoginUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import respositories.SessionRepository; 7 | import rx.Observable; 8 | import rx.Subscriber; 9 | import rx.observers.TestSubscriber; 10 | 11 | import static org.hamcrest.MatcherAssert.assertThat; 12 | import static org.hamcrest.Matchers.is; 13 | import static org.mockito.Mockito.when; 14 | 15 | public class LoginUseCaseTest extends BaseSessionUseCaseTest { 16 | private final static String A_VALID_USERNAME = "aValidUsername", A_VALID_PASSWORD = "aValidPassword", 17 | AN_INVALID_USERNAME = "anInvalidUsername", AN_INVALID_PASSWORD = "anInvalidPassword"; 18 | private LoginUseCase loginUseCase; 19 | @Mock private SessionRepository sessionRepository; 20 | 21 | @Override public void setUp() { 22 | super.setUp(); 23 | loginUseCase = new LoginUseCase(sessionRepository, subscribeOn, observeOn); 24 | 25 | when(sessionRepository.askForLogin(A_VALID_USERNAME, A_VALID_PASSWORD)).thenReturn(Observable.just("Great")); 26 | when(sessionRepository.askForLogin(AN_INVALID_USERNAME, AN_INVALID_PASSWORD)).thenReturn(Observable.create( 27 | new Observable.OnSubscribe() { 28 | @Override 29 | public void call(Subscriber subscriber) { 30 | subscriber.onError(new RuntimeException("Not Great")); 31 | } 32 | }) 33 | ); 34 | } 35 | 36 | @Test public void when_Login_With_Valid_Inputs_Then_Get_A_Response_As_String() { 37 | loginUseCase.doLogin(A_VALID_USERNAME, A_VALID_PASSWORD); 38 | subscribe_To_Login_And_Wait_Until_Observable_Is_Completed(0, 1); 39 | } 40 | 41 | @Test public void when_Login_With_Invalid_Inputs_Then_Throw_An_Exception_On_Subscriber() { 42 | loginUseCase.doLogin(AN_INVALID_USERNAME, AN_INVALID_PASSWORD); 43 | subscribe_To_Login_And_Wait_Until_Observable_Is_Completed(1, 0); 44 | } 45 | 46 | private void subscribe_To_Login_And_Wait_Until_Observable_Is_Completed(int expectedErrors, int expectedEvents) { 47 | TestSubscriber subscriber = new TestSubscriber<>(); 48 | loginUseCase.execute(subscriber); 49 | subscriber.awaitTerminalEvent(); 50 | 51 | assertThat(subscriber.getOnErrorEvents().size(), is(expectedErrors)); 52 | assertThat(subscriber.getOnNextEvents().size(), is(expectedEvents)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/LogoutUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import respositories.SessionRepository; 7 | import rx.Observable; 8 | import rx.Subscriber; 9 | import rx.observers.TestSubscriber; 10 | 11 | import static org.hamcrest.MatcherAssert.assertThat; 12 | import static org.hamcrest.Matchers.is; 13 | import static org.mockito.Mockito.when; 14 | 15 | public class LogoutUseCaseTest extends BaseSessionUseCaseTest { 16 | private LogoutUseCase logoutUseCase; 17 | @Mock private SessionRepository sessionRepository; 18 | 19 | @Override public void setUp() { 20 | super.setUp(); 21 | logoutUseCase = new LogoutUseCase(sessionRepository, subscribeOn, observeOn); 22 | } 23 | 24 | @Test public void when_Logout_With_Active_Session_Then_Get_A_Response_As_String() { 25 | when(sessionRepository.askForLogout()).thenReturn(Observable.just("Great!")); 26 | 27 | TestSubscriber subscriber = new TestSubscriber<>(); 28 | logoutUseCase.execute(subscriber); 29 | subscriber.awaitTerminalEvent(); 30 | 31 | assertThat(subscriber.getOnNextEvents().size(), is(1)); 32 | } 33 | 34 | @Test public void when_Logout_Without_Active_Session_Then_Throw_An_Exception_On_Subscriber() { 35 | when(sessionRepository.askForLogout()).thenReturn(Observable.create( 36 | new Observable.OnSubscribe() { 37 | @Override public void call(Subscriber subscriber) { 38 | subscriber.onError(new RuntimeException("Not Great")); 39 | } 40 | }) 41 | ); 42 | 43 | TestSubscriber subscriber = new TestSubscriber<>(); 44 | logoutUseCase.execute(subscriber); 45 | subscriber.awaitTerminalEvent(); 46 | 47 | assertThat(subscriber.getOnErrorEvents().size(), is(1)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/SessionUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.junit.runners.Parameterized; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collection; 9 | 10 | import entities.User; 11 | import respositories.SessionRepository; 12 | import rx.Observable; 13 | import rx.observers.TestSubscriber; 14 | 15 | import static org.hamcrest.MatcherAssert.assertThat; 16 | import static org.hamcrest.Matchers.is; 17 | import static org.mockito.Mockito.mock; 18 | 19 | @RunWith(Parameterized.class) 20 | public class SessionUseCaseTest extends BaseSessionUseCaseTest { 21 | private SessionUseCase sessionUseCase; 22 | 23 | @Parameterized.Parameter(value = 0) public Observable observable; 24 | @Parameterized.Parameter(value = 1) public int expectedEvents; 25 | 26 | @Override public void setUp() { 27 | super.setUp(); 28 | sessionUseCase = new SessionUseCaseTestClass(); 29 | } 30 | 31 | @Parameterized.Parameters public static Collection data() { 32 | return Arrays.asList(new Object[][]{ 33 | {Observable.empty(), 0}, {Observable.just(""), 1}, {Observable.just(new User()), 1} 34 | }); 35 | } 36 | 37 | @Test public void when_Build_Observable_Then_Get_Correct_Result() { 38 | TestSubscriber testSubscriber = new TestSubscriber<>(); 39 | sessionUseCase.execute(testSubscriber); 40 | testSubscriber.awaitTerminalEvent(); 41 | 42 | assertThat(testSubscriber.getOnNextEvents().size(), is(expectedEvents)); 43 | } 44 | 45 | @Test public void when_Session_UseCase_Unsubscribe_Then_Attached_Subscriber_Is_Unsubscribed() { 46 | TestSubscriber testSubscriber = new TestSubscriber<>(); 47 | sessionUseCase.execute(testSubscriber); 48 | sessionUseCase.unsubscribe(); 49 | 50 | assertThat(testSubscriber.isUnsubscribed(), is(true)); 51 | } 52 | 53 | private final class SessionUseCaseTestClass extends SessionUseCase { 54 | public SessionUseCaseTestClass() { 55 | super(mock(SessionRepository.class), subscribeOn, observeOn); 56 | } 57 | 58 | @Override protected Observable buildUseCaseObservable() { 59 | return observable; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/SignUpUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.hamcrest.Matchers; 4 | import org.junit.Test; 5 | import org.mockito.Mock; 6 | 7 | import entities.User; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import rx.observers.TestSubscriber; 12 | 13 | import static org.hamcrest.MatcherAssert.assertThat; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class SignUpUseCaseTest extends BaseSessionUseCaseTest { 17 | private final static User A_VALID_USER = new User(), AN_INVALID_USER = null; 18 | @Mock private SessionRepository sessionRepository; 19 | private SignUpUseCase signUpUseCase; 20 | 21 | @Override public void setUp() { 22 | super.setUp(); 23 | signUpUseCase = new SignUpUseCase(sessionRepository, subscribeOn, observeOn); 24 | 25 | when(sessionRepository.askForSignUp(A_VALID_USER)).thenReturn(Observable.just("Great")); 26 | when(sessionRepository.askForSignUp(AN_INVALID_USER)).thenReturn(Observable.create(new Observable.OnSubscribe() { 27 | @Override 28 | public void call(Subscriber subscriber) { 29 | subscriber.onError(new RuntimeException("Not great")); 30 | } 31 | })); 32 | } 33 | 34 | @Test public void when_Sign_Up_With_Valid_Inputs_Then_Get_A_Response_As_String() { 35 | signUpUseCase.setUser(A_VALID_USER); 36 | subscribe_To_Sign_Up_And_Wait_Until_Observable_Is_Completed(0,1); 37 | } 38 | 39 | @Test public void when_Sign_Up_With_Invalid_Inputs_Then_Throw_An_Exception_On_Subscriber() { 40 | signUpUseCase.setUser(AN_INVALID_USER); 41 | subscribe_To_Sign_Up_And_Wait_Until_Observable_Is_Completed(1, 0); 42 | } 43 | 44 | private void subscribe_To_Sign_Up_And_Wait_Until_Observable_Is_Completed(int expectedErrors, int expectedEvents) { 45 | TestSubscriber subscriber = new TestSubscriber<>(); 46 | signUpUseCase.execute(subscriber); 47 | subscriber.awaitTerminalEvent(); 48 | 49 | assertThat(subscriber.getOnErrorEvents().size(), Matchers.is(expectedErrors)); 50 | assertThat(subscriber.getOnNextEvents().size(), Matchers.is(expectedEvents)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /domain/src/test/java/interactors/UpdateUserUseCaseTest.java: -------------------------------------------------------------------------------- 1 | package interactors; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | import rx.Subscriber; 10 | import rx.observers.TestSubscriber; 11 | 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.hamcrest.Matchers.is; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class UpdateUserUseCaseTest extends BaseSessionUseCaseTest { 17 | private final static User A_VALID_USER = new User(), AN_INVALID_USER = null; 18 | @Mock private SessionRepository sessionRepository; 19 | private UpdateUserCase updateUserCase; 20 | 21 | @Override public void setUp() { 22 | super.setUp(); 23 | updateUserCase = new UpdateUserCase(sessionRepository, subscribeOn, observeOn); 24 | 25 | when(sessionRepository.askForUpdateLoggedUser(A_VALID_USER)).thenReturn(Observable.just("Great")); 26 | when(sessionRepository.askForUpdateLoggedUser(null)).thenReturn(Observable.create( 27 | new Observable.OnSubscribe() { 28 | @Override 29 | public void call(Subscriber subscriber) { 30 | subscriber.onError(new RuntimeException("Not Great")); 31 | } 32 | }) 33 | ); 34 | } 35 | 36 | @Test public void when_Update_With_Valid_User_Get_An_String_As_Response() { 37 | updateUserCase.setUserToUpdate(A_VALID_USER); 38 | subscribe_To_Update_And_Wait_Until_Observable_Is_Completed(0, 1); 39 | } 40 | 41 | @Test public void when_Update_With_Invalid_User_Then_Throw_An_Exception_On_Subscriber() { 42 | updateUserCase.setUserToUpdate(AN_INVALID_USER); 43 | subscribe_To_Update_And_Wait_Until_Observable_Is_Completed(1, 0); 44 | } 45 | 46 | private void subscribe_To_Update_And_Wait_Until_Observable_Is_Completed(int expectedErrors, int expectedEvents) { 47 | TestSubscriber subscriber = new TestSubscriber<>(); 48 | 49 | updateUserCase.execute(subscriber); 50 | subscriber.awaitTerminalEvent(); 51 | 52 | assertThat(subscriber.getOnErrorEvents().size(), is(expectedErrors)); 53 | assertThat(subscriber.getOnNextEvents().size(), is(expectedEvents)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/BasePresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | 4 | import org.junit.Before; 5 | import org.mockito.Mock; 6 | import org.mockito.MockitoAnnotations; 7 | 8 | import rx.schedulers.Schedulers; 9 | import schedulers.ObserveOn; 10 | import schedulers.SubscribeOn; 11 | 12 | import static org.mockito.Mockito.when; 13 | 14 | public class BasePresenterTest { 15 | protected final static int WAIT = 50; 16 | @Mock protected ObserveOn observeOn; 17 | @Mock protected SubscribeOn subscribeOn; 18 | 19 | @Before public void setUp() { 20 | MockitoAnnotations.initMocks(this); 21 | when(observeOn.getScheduler()).thenReturn(Schedulers.newThread()); 22 | when(subscribeOn.getScheduler()).thenReturn(Schedulers.newThread()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/GetUserPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import interactors.GetUserUseCase; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import views.GetUserView; 12 | 13 | import static org.mockito.Matchers.any; 14 | import static org.mockito.Mockito.mock; 15 | import static org.mockito.Mockito.timeout; 16 | import static org.mockito.Mockito.verify; 17 | 18 | public class GetUserPresenterTest extends BasePresenterTest { 19 | @Mock private GetUserView getUserView; 20 | 21 | @Test public void when_Get_User_Success_Then_On_Success_Is_Called() { 22 | GetUserPresenter getUserPresenter = new GetUserPresenter(new GetUserUseCaseSuccess()); 23 | getUserPresenter.attachView(getUserView); 24 | 25 | verify(getUserView, timeout(WAIT).times(1)).onSuccess(any(User.class)); 26 | verify(getUserView, timeout(WAIT).times(0)).onError(any(String.class)); 27 | } 28 | 29 | @Test public void when_Get_User_Failure_Then_On_Error_Is_Called() { 30 | GetUserPresenter getUserPresenter = new GetUserPresenter(new GetUserUseCaseFailure()); 31 | getUserPresenter.attachView(getUserView); 32 | 33 | verify(getUserView, timeout(WAIT).times(0)).onSuccess(any(User.class)); 34 | verify(getUserView, timeout(WAIT).times(1)).onError(any(String.class)); 35 | } 36 | 37 | private class GetUserUseCaseSuccess extends GetUserUseCase { 38 | GetUserUseCaseSuccess() { 39 | super(mock(SessionRepository.class), subscribeOn, observeOn); 40 | } 41 | 42 | @Override protected Observable buildUseCaseObservable() { 43 | return Observable.just(new User()); 44 | } 45 | } 46 | 47 | private class GetUserUseCaseFailure extends GetUserUseCase { 48 | GetUserUseCaseFailure() { 49 | super(mock(SessionRepository.class), subscribeOn, observeOn); 50 | } 51 | 52 | @Override protected Observable buildUseCaseObservable() { 53 | return Observable.create(new Observable.OnSubscribe() { 54 | @Override public void call(Subscriber subscriber) { 55 | subscriber.onError(new RuntimeException("Not great")); 56 | } 57 | }); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/LaunchPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import interactors.GetUserUseCase; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import views.LaunchView; 12 | 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.timeout; 15 | import static org.mockito.Mockito.verify; 16 | 17 | public class LaunchPresenterTest extends BasePresenterTest { 18 | private LaunchPresenter launchPresenter; 19 | @Mock LaunchView launchView; 20 | 21 | @Test public void when_User_Logged_Then_Go_To_Profile_Is_Called() { 22 | GetUserUseCaseLogged getUserUseCase = new GetUserUseCaseLogged(); 23 | launchPresenter = new LaunchPresenter(getUserUseCase); 24 | launchPresenter.attachView(launchView); 25 | 26 | verify(launchView, timeout(WAIT).times(0)).goToCredentials(); 27 | verify(launchView, timeout(WAIT).times(1)).goToProfile(); 28 | } 29 | 30 | @Test public void when_Not_User_Logged_Then_Go_To_Credentials_Is_Called() { 31 | GetUserUseCaseNotLogged getUserUseCase = new GetUserUseCaseNotLogged(); 32 | launchPresenter = new LaunchPresenter(getUserUseCase); 33 | launchPresenter.attachView(launchView); 34 | 35 | verify(launchView, timeout(WAIT).times(0)).goToProfile(); 36 | verify(launchView, timeout(WAIT).times(1)).goToCredentials(); 37 | } 38 | 39 | private class GetUserUseCaseLogged extends GetUserUseCase { 40 | GetUserUseCaseLogged() { 41 | super(mock(SessionRepository.class), subscribeOn, observeOn); 42 | } 43 | 44 | @Override protected Observable buildUseCaseObservable() { 45 | return Observable.just(new User()); 46 | } 47 | } 48 | 49 | private class GetUserUseCaseNotLogged extends GetUserUseCase { 50 | GetUserUseCaseNotLogged() { 51 | super(mock(SessionRepository.class), subscribeOn, observeOn); 52 | } 53 | 54 | @Override protected Observable buildUseCaseObservable() { 55 | return Observable.create(new Observable.OnSubscribe() { 56 | @Override 57 | public void call(Subscriber subscriber) { 58 | subscriber.onError(new RuntimeException("Not User Logged")); 59 | } 60 | }); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/LoginPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import interactors.LoginUseCase; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | import rx.Subscriber; 10 | import views.LoginView; 11 | 12 | import static org.mockito.Matchers.any; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.timeout; 15 | import static org.mockito.Mockito.verify; 16 | 17 | public class LoginPresenterTest extends BasePresenterTest { 18 | @Mock private LoginView loginView; 19 | 20 | @Test public void when_Login_Success_Then_Go_To_Profile_Is_Called() { 21 | LoginPresenter loginPresenter = new LoginPresenter(new LoginUseCaseSuccess()); 22 | loginPresenter.attachView(loginView); 23 | loginPresenter.doLogin("aValidUsername", "aValidPassword"); 24 | 25 | verify(loginView, timeout(WAIT).times(1)).goToProfile(); 26 | } 27 | 28 | @Test public void when_Login_Failure_Then_Go_To_Profile_Is_Not_Called() { 29 | LoginPresenter loginPresenter = new LoginPresenter(new LoginUseCaseFailure()); 30 | loginPresenter.attachView(loginView); 31 | loginPresenter.doLogin("anInvalidUsername", "anInvalidPassword"); 32 | 33 | verify(loginView, timeout(WAIT).times(0)).goToProfile(); 34 | verify(loginView, timeout(WAIT).times(1)).onError(any(String.class)); 35 | } 36 | 37 | private class LoginUseCaseSuccess extends LoginUseCase { 38 | public LoginUseCaseSuccess() { 39 | super(mock(SessionRepository.class), subscribeOn, observeOn); 40 | } 41 | 42 | @Override protected Observable buildUseCaseObservable() { 43 | return Observable.just("Great"); 44 | } 45 | } 46 | 47 | private class LoginUseCaseFailure extends LoginUseCase { 48 | public LoginUseCaseFailure() { 49 | super(mock(SessionRepository.class), subscribeOn, observeOn); 50 | } 51 | 52 | @Override protected Observable buildUseCaseObservable() { 53 | return Observable.create(new Observable.OnSubscribe() { 54 | @Override public void call(Subscriber subscriber) { 55 | subscriber.onError(new RuntimeException("Not great")); 56 | } 57 | }); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/LogoutPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import interactors.LogoutUseCase; 7 | import respositories.SessionRepository; 8 | import rx.Observable; 9 | import rx.Subscriber; 10 | import views.LogoutView; 11 | 12 | import static org.mockito.Matchers.any; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.timeout; 15 | import static org.mockito.Mockito.verify; 16 | 17 | public class LogoutPresenterTest extends BasePresenterTest { 18 | @Mock private LogoutView logoutView; 19 | 20 | @Test public void when_Logout_Success_Then_On_Success_Is_Called() { 21 | LogoutPresenter logoutPresenter = new LogoutPresenter(new LogoutUseCaseSuccess()); 22 | logoutPresenter.attachView(logoutView); 23 | logoutPresenter.doLogout(); 24 | 25 | verify(logoutView, timeout(WAIT).times(1)).onSuccess(any(String.class)); 26 | verify(logoutView, timeout(WAIT).times(0)).onError(any(String.class)); 27 | } 28 | 29 | @Test public void when_Logout_Failure_Then_On_Error_Is_Called() { 30 | LogoutPresenter logoutPresenter = new LogoutPresenter(new LogoutUseCaseFailure()); 31 | logoutPresenter.attachView(logoutView); 32 | logoutPresenter.doLogout(); 33 | 34 | verify(logoutView, timeout(WAIT).times(0)).onSuccess(any(String.class)); 35 | verify(logoutView, timeout(WAIT).times(1)).onError(any(String.class)); 36 | } 37 | 38 | private class LogoutUseCaseSuccess extends LogoutUseCase { 39 | LogoutUseCaseSuccess() { 40 | super(mock(SessionRepository.class), subscribeOn, observeOn); 41 | } 42 | 43 | @Override protected Observable buildUseCaseObservable() { 44 | return Observable.just("Great"); 45 | } 46 | } 47 | 48 | private class LogoutUseCaseFailure extends LogoutUseCase { 49 | LogoutUseCaseFailure() { 50 | super(mock(SessionRepository.class), subscribeOn, observeOn); 51 | } 52 | 53 | @Override protected Observable buildUseCaseObservable() { 54 | return Observable.create(new Observable.OnSubscribe() { 55 | @Override 56 | public void call(Subscriber subscriber) { 57 | subscriber.onError(new RuntimeException("Not great")); 58 | } 59 | }); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/SignUpPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import interactors.SignUpUseCase; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import views.SignUpView; 12 | 13 | import static org.mockito.Matchers.any; 14 | import static org.mockito.Mockito.mock; 15 | import static org.mockito.Mockito.timeout; 16 | import static org.mockito.Mockito.verify; 17 | 18 | public class SignUpPresenterTest extends BasePresenterTest { 19 | @Mock private SignUpView signUpView; 20 | 21 | @Test public void when_Sign_Up_Success_Then_Go_To_Profile_Is_Called() { 22 | SignUpPresenter loginPresenter = new SignUpPresenter(new SignUpUseCaseSuccess()); 23 | loginPresenter.attachView(signUpView); 24 | loginPresenter.doSignUp(new User()); 25 | 26 | verify(signUpView, timeout(WAIT).times(1)).goToProfile(); 27 | } 28 | 29 | @Test public void when_Sign_Up_Failure_Then_Go_To_Profile_Is_Not_Called() { 30 | SignUpPresenter loginPresenter = new SignUpPresenter(new SignUpUseCaseFailure()); 31 | loginPresenter.attachView(signUpView); 32 | loginPresenter.doSignUp(new User()); 33 | 34 | verify(signUpView, timeout(WAIT).times(0)).goToProfile(); 35 | verify(signUpView, timeout(WAIT).times(1)).onError(any(String.class)); 36 | } 37 | 38 | private class SignUpUseCaseSuccess extends SignUpUseCase { 39 | SignUpUseCaseSuccess() { 40 | super(mock(SessionRepository.class), subscribeOn, observeOn); 41 | } 42 | 43 | @Override protected Observable buildUseCaseObservable() { 44 | return Observable.just("Great"); 45 | } 46 | } 47 | 48 | private class SignUpUseCaseFailure extends SignUpUseCase { 49 | SignUpUseCaseFailure() { 50 | super(mock(SessionRepository.class), subscribeOn, observeOn); 51 | } 52 | 53 | @Override protected Observable buildUseCaseObservable() { 54 | return Observable.create(new Observable.OnSubscribe() { 55 | @Override public void call(Subscriber subscriber) { 56 | subscriber.onError(new RuntimeException("Not great")); 57 | } 58 | }); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /domain/src/test/java/presenters/UpdateUserPresenterTest.java: -------------------------------------------------------------------------------- 1 | package presenters; 2 | 3 | import org.junit.Test; 4 | import org.mockito.Mock; 5 | 6 | import entities.User; 7 | import interactors.UpdateUserCase; 8 | import respositories.SessionRepository; 9 | import rx.Observable; 10 | import rx.Subscriber; 11 | import views.UpdateUserView; 12 | 13 | import static org.mockito.Matchers.any; 14 | import static org.mockito.Mockito.mock; 15 | import static org.mockito.Mockito.timeout; 16 | import static org.mockito.Mockito.verify; 17 | 18 | public class UpdateUserPresenterTest extends BasePresenterTest { 19 | @Mock private UpdateUserView updateUserView; 20 | 21 | @Test public void when_Update_User_Success_Then_On_Success_Is_Called() { 22 | UpdateUserPresenter updateUserPresenter = new UpdateUserPresenter(new UpdateUserCaseSuccess()); 23 | updateUserPresenter.attachView(updateUserView); 24 | updateUserPresenter.doUpdateUser(new User()); 25 | 26 | verify(updateUserView, timeout(WAIT).times(1)).onSuccess(any(String.class)); 27 | verify(updateUserView, timeout(WAIT).times(0)).onError(any(String.class)); 28 | } 29 | 30 | @Test public void when_Update_User_Failure_Then_On_Error_Is_Called() { 31 | UpdateUserPresenter updateUserPresenter = new UpdateUserPresenter(new UpdateUserCaseFailure()); 32 | updateUserPresenter.attachView(updateUserView); 33 | updateUserPresenter.doUpdateUser(null); 34 | 35 | verify(updateUserView, timeout(WAIT).times(0)).onSuccess(any(String.class)); 36 | verify(updateUserView, timeout(WAIT).times(1)).onError(any(String.class)); 37 | } 38 | 39 | private class UpdateUserCaseSuccess extends interactors.UpdateUserCase { 40 | UpdateUserCaseSuccess() { 41 | super(mock(SessionRepository.class), subscribeOn, observeOn); 42 | } 43 | 44 | @Override protected Observable buildUseCaseObservable() { 45 | return Observable.just("Great"); 46 | } 47 | } 48 | 49 | private class UpdateUserCaseFailure extends UpdateUserCase { 50 | UpdateUserCaseFailure() { 51 | super(mock(SessionRepository.class), subscribeOn, observeOn); 52 | } 53 | 54 | @Override protected Observable buildUseCaseObservable() { 55 | return Observable.create(new Observable.OnSubscribe() { 56 | @Override public void call(Subscriber subscriber) { 57 | subscriber.onError(new RuntimeException("No great!")); 58 | } 59 | }); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VictorAlbertos/RestAPIParseAuthCleanAndroid/15926b8380b1e712620afe319f69b7e3d5e719f8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Aug 14 12:46:57 CEST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /presentation/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /presentation/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | 4 | buildscript { 5 | repositories { 6 | jcenter() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' 11 | } 12 | } 13 | 14 | android { 15 | compileSdkVersion 22 16 | buildToolsVersion "22.0.1" 17 | 18 | defaultConfig { 19 | applicationId "edu.victoralbertos.restapiparseauthcleanandroid" 20 | minSdkVersion 16 21 | targetSdkVersion 22 22 | versionCode 1 23 | versionName "1.0" 24 | 25 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 26 | } 27 | 28 | buildTypes { 29 | debug { 30 | testCoverageEnabled = true 31 | } 32 | release { 33 | minifyEnabled false 34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 35 | } 36 | } 37 | } 38 | 39 | apt { 40 | arguments { 41 | androidManifestFile variant.outputs[0].processResources.manifestFile 42 | resourcePackageName "edu.victoralbertos.restapiparseauthcleanandroid" 43 | } 44 | } 45 | 46 | dependencies { 47 | compile fileTree(dir: 'libs', include: ['*.jar']) 48 | compile project(':data') 49 | compile project(':domain') 50 | 51 | def presentationDependencies = rootProject.ext.presentationDependencies 52 | 53 | apt presentationDependencies.daggerCompiler 54 | compile presentationDependencies.dagger 55 | provided presentationDependencies.javaxAnnotation 56 | 57 | compile presentationDependencies.rxJava 58 | compile presentationDependencies.rxAndroid 59 | 60 | compile presentationDependencies.androidannotations 61 | apt presentationDependencies.androidannotationsCompiler 62 | 63 | compile presentationDependencies.supportAppCompat 64 | 65 | 66 | def presentationTestDependencies = rootProject.ext.presentationTestDependencies 67 | 68 | androidTestCompile (presentationTestDependencies.supportTestRunner) { 69 | exclude module: 'support-annotations' 70 | } 71 | 72 | androidTestCompile (presentationTestDependencies.supportTestRules) { 73 | exclude module: 'support-annotations' 74 | } 75 | 76 | androidTestCompile presentationTestDependencies.robotiumVersion 77 | } 78 | -------------------------------------------------------------------------------- /presentation/presentation.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /presentation/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 /Users/victor/Documents/AndroidStudio/android_sdk/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 | -------------------------------------------------------------------------------- /presentation/src/androidTest/java/ConnectionTest.java: -------------------------------------------------------------------------------- 1 | import android.support.test.InstrumentationRegistry; 2 | import android.support.test.runner.AndroidJUnit4; 3 | import android.test.ActivityInstrumentationTestCase2; 4 | import android.test.suitebuilder.annotation.LargeTest; 5 | import android.widget.EditText; 6 | 7 | import com.robotium.solo.Solo; 8 | 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | 13 | import activities.CredentialsActivity_; 14 | import activities.LaunchActivity_; 15 | import activities.ProfileActivity_; 16 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 17 | 18 | 19 | @RunWith(AndroidJUnit4.class) 20 | public class ConnectionTest extends ActivityInstrumentationTestCase2 { 21 | private final static int WAIT_SERVER_RESPONSE = 500; 22 | private Solo mSolo; 23 | private final UserMock mUserMock; 24 | 25 | public ConnectionTest() { 26 | super(LaunchActivity_.class); 27 | mUserMock = new UserMock(); 28 | } 29 | 30 | @Before public void setUp() { 31 | injectInstrumentation(InstrumentationRegistry.getInstrumentation()); 32 | mSolo = new Solo(getInstrumentation()); 33 | getActivity(); 34 | } 35 | 36 | @Test @LargeTest public void start() { 37 | signUp(); 38 | updateUser(); 39 | logOut(); 40 | login(); 41 | } 42 | 43 | private void signUp() { 44 | mSolo.waitForActivity(CredentialsActivity_.class); 45 | 46 | mSolo.enterText((EditText) mSolo.getView(R.id.sign_up_et_username), mUserMock.getUsername()); 47 | mSolo.enterText((EditText) mSolo.getView(R.id.sign_up_et_email), mUserMock.getEmail()); 48 | mSolo.enterText((EditText) mSolo.getView(R.id.sign_up_et_phone), mUserMock.getPhone()); 49 | mSolo.enterText((EditText) mSolo.getView(R.id.sign_up_et_password), mUserMock.getPassword()); 50 | 51 | mSolo.clickOnView(mSolo.getView(R.id.sign_up_bt_submit)); 52 | mSolo.sleep(WAIT_SERVER_RESPONSE); 53 | mSolo.assertCurrentActivity("Wrong activity!", ProfileActivity_.class); 54 | } 55 | 56 | private void updateUser() { 57 | String phoneUpdate = mUserMock.getPhone() + "666"; 58 | mSolo.clearEditText((EditText) mSolo.getView(R.id.et_phone)); 59 | mSolo.enterText((EditText) mSolo.getView(R.id.et_phone), phoneUpdate); 60 | 61 | mSolo.clickOnView(mSolo.getView(R.id.bt_update)); 62 | mSolo.sleep(WAIT_SERVER_RESPONSE); 63 | 64 | mSolo.goBack(); 65 | 66 | launchActivity(getActivity().getApplicationContext().getPackageName(), LaunchActivity_.class, null); 67 | mSolo.waitForActivity(ProfileActivity_.class); 68 | mSolo.sleep(WAIT_SERVER_RESPONSE); 69 | 70 | String candidatePhoneUpdate =((EditText) mSolo.getView(R.id.et_phone)).getText().toString(); 71 | assertEquals("Attribute phone not updated!", phoneUpdate, candidatePhoneUpdate); 72 | } 73 | 74 | private void logOut() { 75 | mSolo.clickOnView(mSolo.getView(R.id.bt_logout)); 76 | mSolo.assertCurrentActivity("Wrong activity!", CredentialsActivity_.class); 77 | } 78 | 79 | private void login() { 80 | mSolo.enterText((EditText) mSolo.getView(R.id.login_et_username), mUserMock.getUsername()); 81 | mSolo.enterText((EditText) mSolo.getView(R.id.login_et_password), mUserMock.getPassword()); 82 | mSolo.clickOnView(mSolo.getView(R.id.login_bt_submit)); 83 | 84 | mSolo.sleep(WAIT_SERVER_RESPONSE); 85 | mSolo.assertCurrentActivity("Wrong activity!", ProfileActivity_.class); 86 | } 87 | 88 | 89 | @Override public void tearDown() throws Exception { 90 | mSolo.finishOpenedActivities(); 91 | } 92 | 93 | private class UserMock { 94 | private final String username, email, phone, password; 95 | 96 | public UserMock() { 97 | long time = System.currentTimeMillis(); 98 | username = "ut" + time; 99 | email = "et@" + time + "t.com"; 100 | phone = "pht" + time; 101 | password = "pat" + time; 102 | } 103 | 104 | public String getUsername() { 105 | return username; 106 | } 107 | 108 | public String getEmail() { 109 | return email; 110 | } 111 | 112 | public String getPhone() { 113 | return phone; 114 | } 115 | 116 | public String getPassword() { 117 | return password; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /presentation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /presentation/src/main/java/activities/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package activities; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | 5 | import org.androidannotations.annotations.AfterInject; 6 | import org.androidannotations.annotations.AfterViews; 7 | import org.androidannotations.annotations.EActivity; 8 | 9 | import javax.inject.Inject; 10 | 11 | import internal.di.ApplicationComponent; 12 | import navigation.Navigator; 13 | import utilities.AndroidApplication; 14 | 15 | @EActivity 16 | public abstract class BaseActivity extends AppCompatActivity { 17 | @Inject Navigator navigator; 18 | 19 | @AfterInject protected void init() { 20 | getApplicationComponent().inject(this); 21 | } 22 | 23 | @AfterViews protected void initViews() { 24 | } 25 | 26 | public ApplicationComponent getApplicationComponent() { 27 | return ((AndroidApplication)getApplication()).getApplicationComponent(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /presentation/src/main/java/activities/CredentialsActivity.java: -------------------------------------------------------------------------------- 1 | package activities; 2 | 3 | import org.androidannotations.annotations.EActivity; 4 | 5 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 6 | 7 | @EActivity(R.layout.connect_activity) 8 | public class CredentialsActivity extends BaseActivity { 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/activities/LaunchActivity.java: -------------------------------------------------------------------------------- 1 | package activities; 2 | 3 | import org.androidannotations.annotations.EActivity; 4 | 5 | import javax.inject.Inject; 6 | 7 | import presenters.LaunchPresenter; 8 | import views.LaunchView; 9 | 10 | @EActivity 11 | public class LaunchActivity extends BaseActivity implements LaunchView { 12 | @Inject LaunchPresenter launchPresenter; 13 | 14 | @Override protected void init() { 15 | super.init(); 16 | 17 | getApplicationComponent().inject(this); 18 | launchPresenter.attachView(this); 19 | } 20 | 21 | @Override public void goToCredentials() { 22 | navigator.toCredentials(this); 23 | } 24 | 25 | @Override public void goToProfile() { 26 | navigator.toProfile(this); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /presentation/src/main/java/activities/ProfileActivity.java: -------------------------------------------------------------------------------- 1 | package activities; 2 | 3 | import org.androidannotations.annotations.EActivity; 4 | 5 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 6 | 7 | @EActivity(R.layout.profile_activity) 8 | public class ProfileActivity extends BaseActivity { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/fragments/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package fragments; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.widget.Toast; 5 | 6 | import org.androidannotations.annotations.AfterInject; 7 | import org.androidannotations.annotations.AfterViews; 8 | import org.androidannotations.annotations.EFragment; 9 | 10 | import javax.inject.Inject; 11 | 12 | import internal.di.ApplicationComponent; 13 | import navigation.Navigator; 14 | import activities.BaseActivity; 15 | 16 | @EFragment 17 | public abstract class BaseFragment extends Fragment { 18 | @Inject Navigator navigator; 19 | 20 | @AfterInject protected void init() { 21 | getApplicationComponent().inject(this); 22 | } 23 | 24 | @AfterViews protected void initViews() {} 25 | 26 | protected ApplicationComponent getApplicationComponent() { 27 | return ((BaseActivity)getActivity()).getApplicationComponent(); 28 | } 29 | 30 | protected void showToast(String message) { 31 | Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /presentation/src/main/java/fragments/FragmentLogin.java: -------------------------------------------------------------------------------- 1 | package fragments; 2 | 3 | import android.view.View; 4 | import android.widget.EditText; 5 | 6 | import org.androidannotations.annotations.Click; 7 | import org.androidannotations.annotations.EFragment; 8 | import org.androidannotations.annotations.ViewById; 9 | 10 | import javax.inject.Inject; 11 | 12 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 13 | import presenters.LoginPresenter; 14 | import views.LoginView; 15 | 16 | @EFragment(R.layout.fragment_login) 17 | public class FragmentLogin extends BaseFragment implements LoginView { 18 | @Inject LoginPresenter loginPresenter; 19 | @ViewById protected View login_pb_loading, login_bt_submit; 20 | 21 | @Override protected void init() { 22 | super.init(); 23 | getApplicationComponent().inject(this); 24 | } 25 | 26 | @Override protected void initViews() { 27 | super.initViews(); 28 | loginPresenter.attachView(this); 29 | } 30 | 31 | @Override public void showProgress() { 32 | login_bt_submit.setVisibility(View.INVISIBLE); 33 | login_pb_loading.setVisibility(View.VISIBLE); 34 | } 35 | 36 | @Override public void hideProgress() { 37 | login_bt_submit.setVisibility(View.VISIBLE); 38 | login_pb_loading.setVisibility(View.INVISIBLE); 39 | } 40 | 41 | @Override public void onError(String message) { 42 | super.showToast(message); 43 | } 44 | 45 | @Override public void onSuccess(String message) { 46 | super.showToast(message); 47 | } 48 | 49 | @Override public void onDestroy() { 50 | super.onDestroy(); 51 | loginPresenter.destroy(); 52 | } 53 | 54 | @Override public void goToProfile() { 55 | navigator.toProfile(getActivity()); 56 | } 57 | 58 | @ViewById protected EditText login_et_username, login_et_password; 59 | @Click protected void login_bt_submit() { 60 | String username = login_et_username.getText().toString(); 61 | String password = login_et_password.getText().toString(); 62 | loginPresenter.doLogin(username, password); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /presentation/src/main/java/fragments/FragmentLogout.java: -------------------------------------------------------------------------------- 1 | package fragments; 2 | 3 | import android.view.View; 4 | 5 | import org.androidannotations.annotations.Click; 6 | import org.androidannotations.annotations.EFragment; 7 | import org.androidannotations.annotations.ViewById; 8 | 9 | import javax.inject.Inject; 10 | 11 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 12 | import presenters.LogoutPresenter; 13 | import views.LogoutView; 14 | 15 | @EFragment(R.layout.fragment_logout) 16 | public class FragmentLogout extends BaseFragment implements LogoutView { 17 | @ViewById protected View pb_logout_loading, bt_logout; 18 | @Inject LogoutPresenter logoutPresenter; 19 | 20 | @Override protected void init() { 21 | super.init(); 22 | getApplicationComponent().inject(this); 23 | } 24 | 25 | @Override protected void initViews() { 26 | super.initViews(); 27 | logoutPresenter.attachView(this); 28 | } 29 | 30 | @Override public void showProgress() { 31 | pb_logout_loading.setVisibility(View.VISIBLE); 32 | bt_logout.setVisibility(View.INVISIBLE); 33 | } 34 | 35 | @Override public void hideProgress() { 36 | pb_logout_loading.setVisibility(View.INVISIBLE); 37 | bt_logout.setVisibility(View.VISIBLE); 38 | } 39 | 40 | @Override public void onError(String message) { 41 | super.showToast(message); 42 | } 43 | 44 | @Override public void onSuccess(String message) { 45 | super.showToast(message); 46 | } 47 | 48 | @Override public void toCredentials() { 49 | navigator.toCredentials(getActivity()); 50 | } 51 | 52 | @Click protected void bt_logout() { 53 | logoutPresenter.doLogout(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /presentation/src/main/java/fragments/FragmentProfile.java: -------------------------------------------------------------------------------- 1 | package fragments; 2 | 3 | import android.view.View; 4 | import android.widget.EditText; 5 | 6 | import org.androidannotations.annotations.Click; 7 | import org.androidannotations.annotations.EFragment; 8 | import org.androidannotations.annotations.ViewById; 9 | 10 | import javax.inject.Inject; 11 | 12 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 13 | import entities.User; 14 | import presenters.GetUserPresenter; 15 | import presenters.UpdateUserPresenter; 16 | import views.GetUserView; 17 | import views.UpdateUserView; 18 | 19 | @EFragment(R.layout.fragment_profile) 20 | public class FragmentProfile extends BaseFragment implements UpdateUserView, GetUserView { 21 | @ViewById protected EditText et_username, et_email, et_phone; 22 | @ViewById protected View pb_loading, bt_update; 23 | @Inject UpdateUserPresenter updateUserPresenter; 24 | @Inject GetUserPresenter getUserPresenter; 25 | 26 | @Override protected void init() { 27 | super.init(); 28 | getApplicationComponent().inject(this); 29 | } 30 | 31 | @Override protected void initViews() { 32 | super.initViews(); 33 | updateUserPresenter.attachView(this); 34 | getUserPresenter.attachView(this); 35 | } 36 | 37 | @Override public void showProgress() { 38 | bt_update.setVisibility(View.INVISIBLE); 39 | pb_loading.setVisibility(View.VISIBLE); 40 | } 41 | 42 | @Override public void hideProgress() { 43 | bt_update.setVisibility(View.VISIBLE); 44 | pb_loading.setVisibility(View.INVISIBLE); 45 | } 46 | 47 | @Override public void onError(String message) { 48 | super.showToast(message); 49 | } 50 | 51 | @Override public void onSuccess(User user) { 52 | et_username.setText(user.getUsername()); 53 | et_email.setText(user.getEmail()); 54 | et_phone.setText(user.getPhone()); 55 | } 56 | 57 | @Override public void onSuccess(String message) { 58 | super.showToast(message); 59 | } 60 | 61 | @Click protected void bt_update() { 62 | String username = et_username.getText().toString(); 63 | String email = et_email.getText().toString(); 64 | String phone = et_phone.getText().toString(); 65 | 66 | User user = new User(username, email, phone); 67 | updateUserPresenter.doUpdateUser(user); 68 | } 69 | } -------------------------------------------------------------------------------- /presentation/src/main/java/fragments/FragmentSignUp.java: -------------------------------------------------------------------------------- 1 | package fragments; 2 | 3 | import android.view.View; 4 | import android.widget.EditText; 5 | 6 | import org.androidannotations.annotations.Click; 7 | import org.androidannotations.annotations.EFragment; 8 | import org.androidannotations.annotations.ViewById; 9 | 10 | import javax.inject.Inject; 11 | 12 | import edu.victoralbertos.restapiparseauthcleanandroid.R; 13 | import entities.User; 14 | import presenters.SignUpPresenter; 15 | import views.SignUpView; 16 | 17 | @EFragment(R.layout.fragment_sign_up) 18 | public class FragmentSignUp extends BaseFragment implements SignUpView { 19 | @Inject SignUpPresenter signUpPresenter; 20 | @ViewById protected View sign_up_pb_loading, sign_up_bt_submit; 21 | @ViewById protected EditText sign_up_et_username, sign_up_et_email, sign_up_et_phone, sign_up_et_password; 22 | 23 | @Override protected void init() { 24 | super.init(); 25 | getApplicationComponent().inject(this); 26 | } 27 | 28 | @Override protected void initViews() { 29 | super.initViews(); 30 | signUpPresenter.attachView(this); 31 | } 32 | 33 | @Override public void showProgress() { 34 | sign_up_pb_loading.setVisibility(View.VISIBLE); 35 | sign_up_bt_submit.setVisibility(View.INVISIBLE); 36 | } 37 | 38 | @Override public void hideProgress() { 39 | sign_up_pb_loading.setVisibility(View.INVISIBLE); 40 | sign_up_bt_submit.setVisibility(View.VISIBLE); 41 | } 42 | 43 | @Override public void onError(String message) { 44 | super.showToast(message); 45 | } 46 | 47 | @Override public void onSuccess(String message) { 48 | super.showToast(message); 49 | } 50 | 51 | @Override public void goToProfile() { 52 | navigator.toProfile(getActivity()); 53 | } 54 | 55 | @Click protected void sign_up_bt_submit() { 56 | String username = sign_up_et_username.getText().toString(); 57 | String email = sign_up_et_email.getText().toString(); 58 | String phone = sign_up_et_phone.getText().toString(); 59 | String password = sign_up_et_password.getText().toString(); 60 | 61 | signUpPresenter.doSignUp(new User(username, email, phone, password)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /presentation/src/main/java/internal/di/ApplicationComponent.java: -------------------------------------------------------------------------------- 1 | package internal.di; 2 | 3 | import javax.inject.Singleton; 4 | 5 | import dagger.Component; 6 | import activities.BaseActivity; 7 | import activities.LaunchActivity; 8 | import fragments.BaseFragment; 9 | import fragments.FragmentLogin; 10 | import fragments.FragmentLogout; 11 | import fragments.FragmentProfile; 12 | import fragments.FragmentSignUp; 13 | 14 | @Singleton 15 | @Component(modules = ApplicationModule.class) 16 | public interface ApplicationComponent { 17 | void inject(BaseActivity baseActivity); 18 | void inject(LaunchActivity launchActivity); 19 | 20 | void inject(BaseFragment baseFragment); 21 | void inject(FragmentLogin fragmentLogin); 22 | void inject(FragmentSignUp fragmentSignUp); 23 | void inject(FragmentProfile fragmentProfile); 24 | void inject(FragmentLogout fragmentLogout); 25 | } 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/internal/di/ApplicationModule.java: -------------------------------------------------------------------------------- 1 | package internal.di; 2 | 3 | import android.content.Context; 4 | 5 | import javax.inject.Singleton; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | import schedulers.ObserveOn; 10 | import schedulers.SubscribeOn; 11 | import navigation.Navigator; 12 | import repositories.SessionDataRepository; 13 | import respositories.SessionRepository; 14 | import rx.Scheduler; 15 | import rx.android.schedulers.AndroidSchedulers; 16 | import rx.schedulers.Schedulers; 17 | import utilities.AndroidApplication; 18 | 19 | @Module(includes = DataModule.class) public class ApplicationModule { 20 | private final AndroidApplication application; 21 | 22 | public ApplicationModule(AndroidApplication application) { 23 | this.application = application; 24 | } 25 | 26 | @Provides @Singleton Context provideApplicationContext() { 27 | return application; 28 | } 29 | 30 | @Provides @Singleton public SessionRepository provideSessionRepository(SessionDataRepository sessionDataRepository) { 31 | return sessionDataRepository; 32 | } 33 | 34 | @Singleton @Provides Navigator provideNavigator() { 35 | return new Navigator(); 36 | } 37 | 38 | @Singleton @Provides SubscribeOn provideSubscribeOn() { 39 | return (new SubscribeOn() { 40 | @Override public Scheduler getScheduler() { 41 | return Schedulers.newThread(); 42 | } 43 | }); 44 | } 45 | 46 | @Singleton @Provides ObserveOn provideObserveOn() { 47 | return (new ObserveOn() { 48 | @Override public Scheduler getScheduler() { 49 | return AndroidSchedulers.mainThread(); 50 | } 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /presentation/src/main/java/navigation/Navigator.java: -------------------------------------------------------------------------------- 1 | package navigation; 2 | 3 | import android.content.Context; 4 | 5 | import javax.inject.Inject; 6 | 7 | import activities.CredentialsActivity_; 8 | import activities.ProfileActivity_; 9 | 10 | 11 | public class Navigator { 12 | @Inject public void Navigator() {} 13 | 14 | public void toCredentials(Context context) { 15 | if (context != null) 16 | CredentialsActivity_.intent(context).start(); 17 | } 18 | 19 | public void toProfile(Context context) { 20 | if (context != null) 21 | ProfileActivity_.intent(context).start(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /presentation/src/main/java/utilities/AndroidApplication.java: -------------------------------------------------------------------------------- 1 | package utilities; 2 | 3 | import android.app.Application; 4 | 5 | import internal.di.ApplicationComponent; 6 | import internal.di.ApplicationModule; 7 | import internal.di.DaggerApplicationComponent; 8 | 9 | public class AndroidApplication extends Application { 10 | private ApplicationComponent applicationComponent; 11 | 12 | @Override public void onCreate() { 13 | super.onCreate(); 14 | this.initializeInjector(); 15 | } 16 | 17 | private void initializeInjector() { 18 | this.applicationComponent = DaggerApplicationComponent.builder() 19 | .applicationModule(new ApplicationModule(this)) 20 | .build(); 21 | } 22 | 23 | public ApplicationComponent getApplicationComponent() { 24 | return applicationComponent; 25 | } 26 | } -------------------------------------------------------------------------------- /presentation/src/main/res/layout/connect_activity.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 15 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/fragment_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 22 | 23 | 30 | 31 | 35 | 36 |