Created
June 27, 2017 01:18
-
-
Save rohans-doordash/de1b669075d6cdd46fe68890a9948244 to your computer and use it in GitHub Desktop.
Login MVP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.data; | |
import android.support.annotation.NonNull; | |
import android.support.annotation.VisibleForTesting; | |
import com.doordash.mvpexample.api.AuthenticationApi; | |
import com.doordash.mvpexample.helpers.SharedPreferencesHelper; | |
import com.doordash.mvpexample.models.Token; | |
import javax.inject.Inject; | |
import io.reactivex.Single; | |
public class AuthenticationManager { | |
@VisibleForTesting | |
static final String AUTH_TOKEN_SHARED_PREFS_KEY = "auth-token"; | |
private SharedPreferencesHelper sharedPreferencesHelper; | |
private AuthenticationApi authenticationApi; | |
@Inject | |
public AuthenticationManager(AuthenticationApi authenticationApi, | |
SharedPreferencesHelper sharedPreferencesHelper) { | |
this.sharedPreferencesHelper = sharedPreferencesHelper; | |
this.authenticationApi = authenticationApi; | |
} | |
public Single<Token> getAuthToken(@NonNull String email, @NonNull String password) { | |
return Single.fromCallable(() -> { | |
String sharedPreferencesString = sharedPreferencesHelper.getString(AUTH_TOKEN_SHARED_PREFS_KEY); | |
if (sharedPreferencesString != null) { | |
return Single.just(new Token(sharedPreferencesString)); | |
} | |
return authenticationApi.getTokenForCredentials(email, password).map(token -> { | |
sharedPreferencesHelper.save(AUTH_TOKEN_SHARED_PREFS_KEY, token.getToken()); | |
return token; | |
}); | |
}).flatMap(tokenSingle -> tokenSingle); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.data; | |
import com.doordash.mvpexample.api.AuthenticationApi; | |
import com.doordash.mvpexample.helpers.SharedPreferencesHelper; | |
import com.doordash.mvpexample.models.Token; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.mockito.Mock; | |
import org.mockito.MockitoAnnotations; | |
import io.reactivex.Single; | |
import static com.doordash.mvpexample.data.AuthenticationManager.AUTH_TOKEN_SHARED_PREFS_KEY; | |
import static junit.framework.Assert.assertEquals; | |
import static org.mockito.Mockito.verify; | |
import static org.mockito.Mockito.when; | |
public class AuthenticationManagerTest { | |
private static final String EMAIL = "user@website.com"; | |
private static final String PASSWORD = "password"; | |
private static final String API_TOKEN = "api-token"; | |
private static final String CACHED_TOKEN = "cached-token"; | |
@Mock | |
AuthenticationApi authenticationApi; | |
@Mock | |
SharedPreferencesHelper sharedPreferencesHelper; | |
private AuthenticationManager authenticationManager; | |
@Before | |
public void setUp() throws Exception { | |
// instantiate manager with mock dependencies | |
MockitoAnnotations.initMocks(this); | |
authenticationManager = new AuthenticationManager(authenticationApi, sharedPreferencesHelper); | |
} | |
@Test | |
public void getAuthToken_whenNotCached_callApiAndCache() throws Exception { | |
when(sharedPreferencesHelper.getString(AUTH_TOKEN_SHARED_PREFS_KEY)) | |
.thenReturn(null); // cache is empty | |
when(authenticationApi.getTokenForCredentials(EMAIL, PASSWORD)) | |
.thenReturn(Single.just(new Token(API_TOKEN))); // api will succeed | |
Token token = authenticationManager.getAuthToken(EMAIL, PASSWORD).blockingGet(); | |
assertEquals(API_TOKEN, token.getToken()); | |
verify(sharedPreferencesHelper).save(AUTH_TOKEN_SHARED_PREFS_KEY, API_TOKEN); | |
} | |
@Test | |
public void getAuthToken_whenCached_getCachedValue() throws Exception { | |
when(sharedPreferencesHelper.getString(AUTH_TOKEN_SHARED_PREFS_KEY)) | |
.thenReturn(CACHED_TOKEN); // cache is filled | |
Token token = authenticationManager.getAuthToken(EMAIL, PASSWORD).blockingGet(); | |
assertEquals(CACHED_TOKEN, token.getToken()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.ui.login; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.AppCompatEditText; | |
import android.widget.Toast; | |
import com.doordash.mvpexample.R; | |
import com.doordash.mvpexample.application.MvpApplication; | |
import com.doordash.mvpexample.ui.MainActivity; | |
import javax.inject.Inject; | |
import butterknife.BindView; | |
import butterknife.ButterKnife; | |
import butterknife.OnClick; | |
public class LoginActivity extends AppCompatActivity implements LoginContract.View { | |
@Inject | |
LoginContract.Presenter presenter; | |
@BindView(R.id.login_email) | |
AppCompatEditText emailEditText; | |
@BindView(R.id.login_password) | |
AppCompatEditText passwordEditText; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_login); | |
MvpApplication.getAppComponent().inject(this); | |
ButterKnife.bind(this); | |
presenter.setView(this); | |
} | |
@Override | |
protected void onPause() { | |
presenter.onPause(); | |
super.onPause(); | |
} | |
@NonNull | |
@Override | |
public String getEmailInput() { | |
return emailEditText.getText().toString(); | |
} | |
@NonNull | |
@Override | |
public String getPasswordInput() { | |
return passwordEditText.getText().toString(); | |
} | |
@Override | |
public void goToMainActivity() { | |
startActivity(MainActivity.makeIntent(this)); | |
} | |
@Override | |
public void showError(@NonNull String error) { | |
Toast.makeText(this, error, Toast.LENGTH_LONG).show(); | |
} | |
@OnClick(R.id.login_button) | |
public void onClickLoginButton() { | |
presenter.onClickLoginButton(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.ui.login; | |
import android.support.annotation.NonNull; | |
import com.doordash.mvpexample.ui.BaseContract; | |
public class LoginContract { | |
public interface View { | |
void goToMainActivity(); | |
void showError(@NonNull String error); | |
@NonNull | |
String getEmailInput(); | |
@NonNull | |
String getPasswordInput(); | |
} | |
public interface Presenter { | |
/** | |
* Late initializer for {@link View} interface | |
*/ | |
void setView(View view); | |
void onPause(); | |
void onClickLoginButton(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.ui.login; | |
import com.doordash.mvpexample.data.AuthenticationDataSource; | |
import com.doordash.mvpexample.helpers.rx.RxSchedulerProvider; | |
import com.doordash.mvpexample.models.Token; | |
import com.doordash.mvpexample.ui.BaseRxPresenter; | |
import io.reactivex.SingleObserver; | |
import io.reactivex.disposables.Disposable; | |
public class LoginPresenter implements LoginContract.Presenter { | |
private AuthenticationManager authenticationManager; | |
public LoginPresenter(RxSchedulerProvider rxSchedulerProvider, | |
AuthenticationManager authenticationManager) { | |
super(rxSchedulerProvider); | |
this.authenticationManager = authenticationManager; | |
} | |
public void onClickLoginButton() { | |
authenticationManager.getAuthToken(view.getEmailInput(), view.getPasswordInput()) | |
.subscribe(new SingleObserver<Token>() { | |
@Override | |
public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) { | |
addDisposable(d); | |
} | |
@Override | |
public void onSuccess(@io.reactivex.annotations.NonNull Token token) { | |
view.goToMainActivity(); | |
} | |
@Override | |
public void onError(@io.reactivex.annotations.NonNull Throwable e) { | |
view.showError(e.getLocalizedMessage()); | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.ui.login; | |
import com.doordash.mvpexample.data.AuthenticationDataSource; | |
import com.doordash.mvpexample.helpers.rx.ImmediateRxSchedulerProvider; | |
import com.doordash.mvpexample.models.Token; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.mockito.Mock; | |
import org.mockito.MockitoAnnotations; | |
import io.reactivex.Single; | |
import static org.mockito.Mockito.verify; | |
import static org.mockito.Mockito.when; | |
public class LoginPresenterTest { | |
private static final String EMAIL = "user@website.com"; | |
private static final String PASSWORD = "password"; | |
private static final String TOKEN = "token"; | |
@Mock | |
AuthenticationDataSource authenticationDataSource; | |
@Mock | |
LoginContract.View loginView; | |
LoginPresenter presenter; | |
@Before | |
public void setUp() throws Exception { | |
// instantiate presenter with mock dependencies | |
// pass in ImmediateRxSchedulerProvider to make rx calls blocking | |
MockitoAnnotations.initMocks(this); | |
presenter = new LoginPresenter(new ImmediateRxSchedulerProvider(), authenticationDataSource); | |
presenter.setView(loginView); | |
// mock view getters | |
when(loginView.getEmailInput()).thenReturn(EMAIL); | |
when(loginView.getPasswordInput()).thenReturn(PASSWORD); | |
} | |
@Test | |
public void onClickLoginButton_whenLoginSucceeds_goToMainActivity() throws Exception { | |
when(authenticationDataSource.getAuthToken(EMAIL, PASSWORD)) | |
.thenReturn(Single.just(new Token(TOKEN))); // fake successful login | |
presenter.onClickLoginButton(); | |
verify(loginView).goToMainActivity(); | |
} | |
@Test | |
public void onClickLoginButton_whenLoginFails_showError() throws Exception { | |
Exception error = new Exception("error message"); | |
when(authenticationDataSource.getAuthToken(EMAIL, PASSWORD)) | |
.thenReturn(Single.error(error)); // fake failed login | |
presenter.onClickLoginButton(); | |
verify(loginView).showError(error.getLocalizedMessage()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.doordash.mvpexample.models; | |
import android.support.annotation.NonNull; | |
public class Token { | |
private String token; | |
public Token(@NonNull String token) { | |
this.token = token; | |
} | |
public String getToken() { | |
return token; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment