From 28e46c9cc0ade791c828777ffbd0b51cccb73246 Mon Sep 17 00:00:00 2001 From: Ivan Kupalov Date: Sat, 10 Mar 2018 00:02:32 +0300 Subject: [PATCH] Add ComposeActivity tests. Add ServiceLocator (#542) --- app/build.gradle | 12 +- .../keylesspalace/tusky/AccountActivity.java | 4 +- .../com/keylesspalace/tusky/BaseActivity.java | 17 ++- .../keylesspalace/tusky/ComposeActivity.java | 7 +- .../com/keylesspalace/tusky/LoginActivity.kt | 11 +- .../com/keylesspalace/tusky/MainActivity.java | 49 +++++---- .../tusky/NotificationPullJobCreator.java | 21 ++-- .../keylesspalace/tusky/SplashActivity.java | 4 +- .../keylesspalace/tusky/TuskyApplication.java | 64 ++++++++--- .../tusky/fragment/NotificationsFragment.java | 19 ++-- .../tusky/fragment/PreferencesFragment.java | 35 +++--- .../tusky/fragment/SFragment.java | 38 ++++--- .../tusky/network/AuthInterceptor.java | 10 +- .../NotificationClearBroadcastReceiver.kt | 4 +- .../tusky/util/NotificationHelper.java | 58 +++++----- .../tusky/ComposeActivityTest.kt | 103 ++++++++++++++++++ .../keylesspalace/tusky/ExampleUnitTest.java | 17 --- .../tusky/FakeTuskyApplication.kt | 18 +++ 18 files changed, 337 insertions(+), 154 deletions(-) create mode 100644 app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt delete mode 100644 app/src/test/java/com/keylesspalace/tusky/ExampleUnitTest.java create mode 100644 app/src/test/java/com/keylesspalace/tusky/FakeTuskyApplication.kt diff --git a/app/build.gradle b/app/build.gradle index aa528a180..58244690d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,6 +36,11 @@ android { androidExtensions { experimental = true } + testOptions { + unitTests { + includeAndroidResources = true + } + } } ext.supportLibraryVersion = '27.1.0' @@ -68,12 +73,15 @@ dependencies { //room implementation 'android.arch.persistence.room:runtime:1.0.0' kapt 'android.arch.persistence.room:compiler:1.0.0' - testImplementation 'junit:junit:4.12' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + + testImplementation 'junit:junit:4.12' + testImplementation "org.robolectric:robolectric:3.7.1" + testCompile "org.mockito:mockito-inline:2.15.0" androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) - implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" debugImplementation 'im.dino:dbinspector:3.4.1@aar' } diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.java b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.java index 6fd0eed85..796f4959d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.java @@ -46,6 +46,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.entity.Relationship; import com.keylesspalace.tusky.interfaces.ActionButtonActivity; @@ -193,7 +194,8 @@ public final class AccountActivity extends BaseActivity implements ActionButtonA // Obtain information to fill out the profile. obtainAccount(); - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = TuskyApplication.getInstance(this).getServiceLocator() + .get(AccountManager.class).getActiveAccount(); if (accountId.equals(activeAccount.getAccountId())) { isSelf = true; diff --git a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java index d1b8ad322..a0555aeb7 100644 --- a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java @@ -34,6 +34,7 @@ import com.evernote.android.job.JobRequest; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.json.SpannedTypeAdapter; import com.keylesspalace.tusky.network.AuthInterceptor; import com.keylesspalace.tusky.network.MastodonApi; @@ -50,11 +51,15 @@ public abstract class BaseActivity extends AppCompatActivity { public MastodonApi mastodonApi; protected Dispatcher mastodonApiDispatcher; + private AccountManager accountManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + accountManager = TuskyApplication.getInstance(this).getServiceLocator() + .get(AccountManager.class); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); /* There isn't presently a way to globally change the theme of a whole application at @@ -64,7 +69,7 @@ public abstract class BaseActivity extends AppCompatActivity { ThemeUtils.setAppNightMode(theme); int style; - switch(preferences.getString("statusTextSize", "medium")) { + switch (preferences.getString("statusTextSize", "medium")) { case "large": style = R.style.TextSizeLarge; break; @@ -79,7 +84,7 @@ public abstract class BaseActivity extends AppCompatActivity { } getTheme().applyStyle(style, false); - if(redirectIfNotLoggedIn()) { + if (redirectIfNotLoggedIn()) { return; } createMastodonApi(); @@ -119,8 +124,8 @@ public abstract class BaseActivity extends AppCompatActivity { } protected String getBaseUrl() { - AccountEntity account = TuskyApplication.getAccountManager().getActiveAccount(); - if(account != null) { + AccountEntity account = accountManager.getActiveAccount(); + if (account != null) { return "https://" + account.getDomain(); } else { return ""; @@ -138,7 +143,7 @@ public abstract class BaseActivity extends AppCompatActivity { OkHttpClient.Builder okBuilder = OkHttpUtils.getCompatibleClientBuilder(preferences) - .addInterceptor(new AuthInterceptor()) + .addInterceptor(new AuthInterceptor(accountManager)) .dispatcher(mastodonApiDispatcher); if (BuildConfig.DEBUG) { @@ -155,7 +160,7 @@ public abstract class BaseActivity extends AppCompatActivity { } protected boolean redirectIfNotLoggedIn() { - if (TuskyApplication.getAccountManager().getActiveAccount() == null) { + if (accountManager.getActiveAccount() == null) { Intent intent = new Intent(this, LoginActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 05b9c9111..508c5800d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -79,6 +79,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.keylesspalace.tusky.adapter.MentionAutoCompleteAdapter; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.db.TootDao; import com.keylesspalace.tusky.db.TootEntity; import com.keylesspalace.tusky.entity.Account; @@ -160,7 +161,7 @@ public final class ComposeActivity extends BaseActivity // this only exists when a status is trying to be sent, but uploads are still occurring private ProgressDialog finishingUploadDialog; private String inReplyToId; - private ArrayList mediaQueued; + private List mediaQueued = new ArrayList<>(); private CountUpDownLatch waitForMediaLatch; private boolean showMarkSensitive; private Status.Visibility statusVisibility; // The current values of the options that will be applied @@ -205,7 +206,8 @@ public final class ComposeActivity extends BaseActivity } // setup the account image - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = TuskyApplication.getInstance(this).getServiceLocator() + .get(AccountManager.class).getActiveAccount(); if (activeAccount != null) { @@ -409,7 +411,6 @@ public final class ComposeActivity extends BaseActivity } // Initialise the empty media queue state. - mediaQueued = new ArrayList<>(); waitForMediaLatch = new CountUpDownLatch(); statusAlreadyInFlight = false; diff --git a/app/src/main/java/com/keylesspalace/tusky/LoginActivity.kt b/app/src/main/java/com/keylesspalace/tusky/LoginActivity.kt index 46778dcf4..58249b893 100644 --- a/app/src/main/java/com/keylesspalace/tusky/LoginActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/LoginActivity.kt @@ -31,6 +31,7 @@ import android.view.MenuItem import android.view.View import android.widget.EditText import android.widget.TextView +import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.entity.AccessToken import com.keylesspalace.tusky.entity.AppCredentials import com.keylesspalace.tusky.network.MastodonApi @@ -88,7 +89,7 @@ class LoginActivity : AppCompatActivity() { textView.movementMethod = LinkMovementMethod.getInstance() } - if(isAdditionalLogin()) { + if (isAdditionalLogin()) { setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowTitleEnabled(false) @@ -99,7 +100,7 @@ class LoginActivity : AppCompatActivity() { } override fun onOptionsItemSelected(item: MenuItem): Boolean { - if(item.itemId == android.R.id.home) { + if (item.itemId == android.R.id.home) { onBackPressed() return true } @@ -281,7 +282,7 @@ class LoginActivity : AppCompatActivity() { } } - private fun isAdditionalLogin() : Boolean { + private fun isAdditionalLogin(): Boolean { return intent.getBooleanExtra(LOGIN_MODE, false) } @@ -289,7 +290,9 @@ class LoginActivity : AppCompatActivity() { setLoading(true) - TuskyApplication.getAccountManager().addAccount(accessToken, domain) + TuskyApplication.getInstance(this).serviceLocator + .get(AccountManager::class.java) + .addAccount(accessToken, domain) val intent = Intent(this, MainActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index de2648390..ee96f90e1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -84,6 +84,8 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { private static int COMPOSE_RESULT = 1; + AccountManager accountManager; + private FloatingActionButton composeButton; private AccountHeader headerResult; private Drawer drawer; @@ -97,16 +99,19 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { int tabPosition = 0; + accountManager = TuskyApplication.getInstance(this).getServiceLocator() + .get(AccountManager.class); + if (intent != null) { long accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1); - if(accountId != -1) { + if (accountId != -1) { // user clicked a notification, show notification tab and switch user if necessary tabPosition = 1; - AccountEntity account = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity account = accountManager.getActiveAccount(); if (account == null || accountId != account.getId()) { - TuskyApplication.getAccountManager().setActiveAccount(accountId); + accountManager.setActiveAccount(accountId); } } } @@ -180,7 +185,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { tintTab(tab, true); - if(tab.getPosition() == 1) { + if (tab.getPosition() == 1) { NotificationHelper.clearNotificationsForActiveAccount(MainActivity.this); } } @@ -191,7 +196,8 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { } @Override - public void onTabReselected(TabLayout.Tab tab) { } + public void onTabReselected(TabLayout.Tab tab) { + } }); for (int i = 0; i < 4; i++) { @@ -385,7 +391,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { }) .build(); - if(BuildConfig.DEBUG) { + if (BuildConfig.DEBUG) { IDrawerItem debugItem = new SecondaryDrawerItem() .withIdentifier(1337) .withName("debug") @@ -399,7 +405,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { } private boolean handleProfileClick(IProfile profile, boolean current) { - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = accountManager.getActiveAccount(); //open profile when active image was clicked if (current && activeAccount != null) { @@ -409,7 +415,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { return true; } //open LoginActivity to add new account - if(profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT ) { + if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) { startActivity(LoginActivity.getIntent(this, true)); return true; } @@ -420,7 +426,7 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { private void changeAccount(long newSelectedId) { - TuskyApplication.getAccountManager().setActiveAccount(newSelectedId); + accountManager.setActiveAccount(newSelectedId); Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); @@ -432,22 +438,22 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { private void logout() { - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = accountManager.getActiveAccount(); - if(activeAccount != null) { + if (activeAccount != null) { new AlertDialog.Builder(this) .setTitle(R.string.action_logout) .setMessage(getString(R.string.action_logout_confirm, activeAccount.getFullName())) .setPositiveButton(android.R.string.yes, (dialog, which) -> { - - AccountManager accountManager = TuskyApplication.getAccountManager(); + ; NotificationHelper.deleteNotificationChannelsForAccount(accountManager.getActiveAccount(), MainActivity.this); AccountEntity newAccount = accountManager.logActiveAccountOut(); - if (!NotificationHelper.areNotificationsEnabled(MainActivity.this)) disablePushNotifications(); + if (!NotificationHelper.areNotificationsEnabled(MainActivity.this)) + disablePushNotifications(); Intent intent; if (newAccount == null) { @@ -492,11 +498,9 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { .placeholder(R.drawable.account_header_default) .into(background); - AccountManager am = TuskyApplication.getAccountManager(); + accountManager.updateActiveAccount(me); - am.updateActiveAccount(me); - - NotificationHelper.createNotificationChannelsForAccount(am.getActiveAccount(), this); + NotificationHelper.createNotificationChannelsForAccount(accountManager.getActiveAccount(), this); // Show follow requests in the menu, if this is a locked account. if (me.getLocked() && drawer.getDrawerItem(DRAWER_ITEM_FOLLOW_REQUESTS) == null) { @@ -513,19 +517,18 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity { } private void updateProfiles() { - AccountManager am = TuskyApplication.getAccountManager(); - List allAccounts = am.getAllAccountsOrderedByActive(); + List allAccounts = accountManager.getAllAccountsOrderedByActive(); //remove profiles before adding them again to avoid duplicates List profiles = new ArrayList<>(headerResult.getProfiles()); - for(IProfile profile: profiles) { - if(profile.getIdentifier() != DRAWER_ITEM_ADD_ACCOUNT) { + for (IProfile profile : profiles) { + if (profile.getIdentifier() != DRAWER_ITEM_ADD_ACCOUNT) { headerResult.removeProfile(profile); } } - for(AccountEntity acc: allAccounts) { + for (AccountEntity acc : allAccounts) { headerResult.addProfiles( new ProfileDrawerItem() .withName(acc.getDisplayName()) diff --git a/app/src/main/java/com/keylesspalace/tusky/NotificationPullJobCreator.java b/app/src/main/java/com/keylesspalace/tusky/NotificationPullJobCreator.java index bba0d0f28..89a2c4987 100644 --- a/app/src/main/java/com/keylesspalace/tusky/NotificationPullJobCreator.java +++ b/app/src/main/java/com/keylesspalace/tusky/NotificationPullJobCreator.java @@ -27,6 +27,7 @@ import com.evernote.android.job.JobCreator; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.entity.Notification; import com.keylesspalace.tusky.json.SpannedTypeAdapter; import com.keylesspalace.tusky.network.MastodonApi; @@ -101,14 +102,16 @@ public final class NotificationPullJobCreator implements JobCreator { @Override protected Result onRunJob(@NonNull Params params) { - List accountList = new ArrayList<>(TuskyApplication.getAccountManager().getAllAccountsOrderedByActive()); + AccountManager accountManager = TuskyApplication.getInstance(context).getServiceLocator() + .get(AccountManager.class); + List accountList = new ArrayList<>(accountManager.getAllAccountsOrderedByActive()); - for(AccountEntity account: accountList) { + for (AccountEntity account : accountList) { - if(account.getNotificationsEnabled()) { + if (account.getNotificationsEnabled()) { MastodonApi api = createMastodonApi(account.getDomain(), context); try { - Log.d(TAG, "getting Notifications for "+account.getFullName()); + Log.d(TAG, "getting Notifications for " + account.getFullName()); Response> notifications = api.notificationsWithAuth(String.format("Bearer %s", account.getAccessToken())).execute(); if (notifications.isSuccessful()) { @@ -136,11 +139,11 @@ public final class NotificationPullJobCreator implements JobCreator { BigInteger newestId = BigInteger.ZERO; - for(Notification notification: notificationList){ + for (Notification notification : notificationList) { BigInteger currentId = new BigInteger(notification.getId()); - if(isBiggerThan(currentId, newestId)) { + if (isBiggerThan(currentId, newestId)) { newestId = currentId; } @@ -150,13 +153,13 @@ public final class NotificationPullJobCreator implements JobCreator { } account.setLastNotificationId(newestId.toString()); - TuskyApplication.getAccountManager().saveAccount(account); - + TuskyApplication.getInstance(context).getServiceLocator() + .get(AccountManager.class).saveAccount(account); } private boolean isBiggerThan(BigInteger newId, BigInteger lastShownNotificationId) { - return lastShownNotificationId.compareTo(newId) == - 1; + return lastShownNotificationId.compareTo(newId) == -1; } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/SplashActivity.java b/app/src/main/java/com/keylesspalace/tusky/SplashActivity.java index c2390b876..0e15899f4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/SplashActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/SplashActivity.java @@ -20,6 +20,7 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.util.NotificationHelper; public class SplashActivity extends AppCompatActivity { @@ -32,7 +33,8 @@ public class SplashActivity extends AppCompatActivity { NotificationHelper.deleteLegacyNotificationChannels(this); - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = TuskyApplication.getInstance(this).getServiceLocator() + .get(AccountManager.class).getActiveAccount(); Intent intent; if (activeAccount != null) { diff --git a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java index 86c1cd566..4dd5891bb 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java +++ b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java @@ -21,6 +21,7 @@ import android.arch.persistence.room.Room; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.support.v7.app.AppCompatDelegate; import com.evernote.android.job.JobManager; @@ -35,7 +36,7 @@ public class TuskyApplication extends Application { public static final String APP_THEME_DEFAULT = ThemeUtils.THEME_NIGHT; private static AppDatabase db; - private static AccountManager accountManager; + private AccountManager accountManager; public static AppDatabase getDB() { return db; @@ -43,24 +44,33 @@ public class TuskyApplication extends Application { private static UiModeManager uiModeManager; - public static UiModeManager getUiModeManager() { return uiModeManager; } + public static UiModeManager getUiModeManager() { + return uiModeManager; + } + + public static TuskyApplication getInstance(@NonNull Context context) { + return (TuskyApplication) context.getApplicationContext(); + } + + + private ServiceLocator serviceLocator; @Override public void onCreate() { super.onCreate(); - // Initialize Picasso configuration - Picasso.Builder builder = new Picasso.Builder(this); - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - builder.downloader(new OkHttp3Downloader(OkHttpUtils.getCompatibleClient(preferences))); - if (BuildConfig.DEBUG) { - builder.listener((picasso, uri, exception) -> exception.printStackTrace()); - } + initPicasso(); - try { - Picasso.setSingletonInstance(builder.build()); - } catch (IllegalStateException e) { - throw new RuntimeException(e); - } + serviceLocator = new ServiceLocator() { + @Override + public T get(Class clazz) { + if (clazz.equals(AccountManager.class)) { + //noinspection unchecked + return (T) accountManager; + } else { + throw new IllegalArgumentException("Unknown service " + clazz); + } + } + }; db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "tuskyDB") .allowMainThreadQueries() @@ -69,7 +79,7 @@ public class TuskyApplication extends Application { JobManager.create(this).addJobCreator(new NotificationPullJobCreator(this)); - uiModeManager = (UiModeManager)getSystemService(Context.UI_MODE_SERVICE); + uiModeManager = (UiModeManager) getSystemService(Context.UI_MODE_SERVICE); //necessary for Android < APi 21 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); @@ -77,8 +87,26 @@ public class TuskyApplication extends Application { accountManager = new AccountManager(); } - public static AccountManager getAccountManager() { - return accountManager; + protected void initPicasso() { + // Initialize Picasso configuration + Picasso.Builder builder = new Picasso.Builder(this); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + builder.downloader(new OkHttp3Downloader(OkHttpUtils.getCompatibleClient(preferences))); + if (BuildConfig.DEBUG) { + builder.listener((picasso, uri, exception) -> exception.printStackTrace()); + } + try { + Picasso.setSingletonInstance(builder.build()); + } catch (IllegalStateException e) { + throw new RuntimeException(e); + } } - } \ No newline at end of file + public ServiceLocator getServiceLocator() { + return serviceLocator; + } + + public interface ServiceLocator { + T get(Class clazz); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index acad55368..6a10f6509 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -192,10 +192,12 @@ public class NotificationsFragment extends SFragment implements TabLayout layout = activity.findViewById(R.id.tab_layout); onTabSelectedListener = new TabLayout.OnTabSelectedListener() { @Override - public void onTabSelected(TabLayout.Tab tab) {} + public void onTabSelected(TabLayout.Tab tab) { + } @Override - public void onTabUnselected(TabLayout.Tab tab) {} + public void onTabUnselected(TabLayout.Tab tab) { + } @Override public void onTabReselected(TabLayout.Tab tab) { @@ -281,7 +283,7 @@ public class NotificationsFragment extends SFragment implements status.getReblog().setReblogged(reblog); } - NotificationViewData.Concrete viewdata = (NotificationViewData.Concrete)notifications.getPairedItem(position); + NotificationViewData.Concrete viewdata = (NotificationViewData.Concrete) notifications.getPairedItem(position); StatusViewData.Builder viewDataBuilder = new StatusViewData.Builder(viewdata.getStatusViewData()); viewDataBuilder.setReblogged(reblog); @@ -318,7 +320,7 @@ public class NotificationsFragment extends SFragment implements status.getReblog().setFavourited(favourite); } - NotificationViewData.Concrete viewdata = (NotificationViewData.Concrete)notifications.getPairedItem(position); + NotificationViewData.Concrete viewdata = (NotificationViewData.Concrete) notifications.getPairedItem(position); StatusViewData.Builder viewDataBuilder = new StatusViewData.Builder(viewdata.getStatusViewData()); viewDataBuilder.setFavourited(favourite); @@ -587,13 +589,14 @@ public class NotificationsFragment extends SFragment implements } private void saveNewestNotificationId(List notifications) { - AccountManager accountManager = TuskyApplication.getAccountManager(); + AccountManager accountManager = TuskyApplication.getInstance(getContext()) + .getServiceLocator().get(AccountManager.class); AccountEntity account = accountManager.getActiveAccount(); BigInteger lastNoti = new BigInteger(account.getLastNotificationId()); - for (Notification noti: notifications) { + for (Notification noti : notifications) { BigInteger a = new BigInteger(noti.getId()); - if(isBiggerThan(a, lastNoti)) { + if (isBiggerThan(a, lastNoti)) { lastNoti = a; } } @@ -606,7 +609,7 @@ public class NotificationsFragment extends SFragment implements private boolean isBiggerThan(BigInteger newId, BigInteger lastShownNotificationId) { - return lastShownNotificationId.compareTo(newId) == - 1; + return lastShownNotificationId.compareTo(newId) == -1; } private void update(@Nullable List newNotifications, @Nullable String fromId, diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/PreferencesFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/PreferencesFragment.java index 3b5cd1a67..2a2948b63 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/PreferencesFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/PreferencesFragment.java @@ -30,6 +30,7 @@ import com.keylesspalace.tusky.PreferencesActivity; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.TuskyApplication; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; public class PreferencesFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences sharedPreferences; @@ -47,20 +48,26 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre return fragment; } + private AccountManager accountManager; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + accountManager = TuskyApplication.getInstance(getActivity()).getServiceLocator() + .get(AccountManager.class); + + int preference = getArguments().getInt("preference"); addPreferencesFromResource(preference); - Preference notificationPreferences = findPreference("notificationPreferences"); + Preference notificationPreferences = findPreference("notificationPreferences"); - if(notificationPreferences != null) { + if (notificationPreferences != null) { - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = accountManager.getActiveAccount(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && activeAccount != null) { notificationPreferences.setSummary(getString(R.string.pref_summary_notifications, activeAccount.getFullName())); @@ -92,8 +99,8 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre } } - Preference timelineFilterPreferences = findPreference("timelineFilterPreferences"); - if(timelineFilterPreferences != null) { + Preference timelineFilterPreferences = findPreference("timelineFilterPreferences"); + if (timelineFilterPreferences != null) { timelineFilterPreferences.setOnPreferenceClickListener(pref -> { PreferencesActivity activity = (PreferencesActivity) getActivity(); if (activity != null) { @@ -104,8 +111,8 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre }); } - Preference httpProxyPreferences = findPreference("httpProxyPreferences"); - if(httpProxyPreferences != null) { + Preference httpProxyPreferences = findPreference("httpProxyPreferences"); + if (httpProxyPreferences != null) { httpProxyPreferences.setOnPreferenceClickListener(pref -> { PreferencesActivity activity = (PreferencesActivity) getActivity(); if (activity != null) { @@ -117,11 +124,11 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre }); } - if(preference == R.xml.notification_preferences) { + if (preference == R.xml.notification_preferences) { - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = accountManager.getActiveAccount(); - if(activeAccount != null) { + if (activeAccount != null) { CheckBoxPreference notificationPref = (CheckBoxPreference) findPreference("notificationsEnabled"); notificationPref.setChecked(activeAccount.getNotificationsEnabled()); @@ -188,10 +195,10 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre default: } - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); + AccountEntity activeAccount = accountManager.getActiveAccount(); - if(activeAccount != null) { - switch(key) { + if (activeAccount != null) { + switch (key) { case "notificationsEnabled": activeAccount.setNotificationsEnabled(sharedPreferences.getBoolean(key, true)); break; @@ -217,7 +224,7 @@ public class PreferencesFragment extends PreferenceFragment implements SharedPre activeAccount.setNotificationLight(sharedPreferences.getBoolean(key, true)); break; } - TuskyApplication.getAccountManager().saveAccount(activeAccount); + accountManager.saveAccount(activeAccount); } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java index 39f432004..2fe48c8e2 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java @@ -41,6 +41,7 @@ import com.keylesspalace.tusky.ViewTagActivity; import com.keylesspalace.tusky.ViewThreadActivity; import com.keylesspalace.tusky.ViewVideoActivity; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.entity.Attachment; import com.keylesspalace.tusky.entity.Relationship; import com.keylesspalace.tusky.entity.Status; @@ -71,19 +72,14 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov protected MastodonApi mastodonApi; @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - AccountEntity activeAccount = TuskyApplication.getAccountManager().getActiveAccount(); - if(activeAccount != null) { + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + AccountEntity activeAccount = TuskyApplication.getInstance(getContext()).getServiceLocator() + .get(AccountManager.class).getActiveAccount(); + if (activeAccount != null) { loggedInAccountId = activeAccount.getAccountId(); loggedInUsername = activeAccount.getUsername(); } - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); BaseActivity activity = (BaseActivity) getActivity(); mastodonApi = activity.mastodonApi; } @@ -153,10 +149,12 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov Call call = mastodonApi.muteAccount(id); call.enqueue(new Callback() { @Override - public void onResponse(@NonNull Call call, @NonNull Response response) {} + public void onResponse(@NonNull Call call, @NonNull Response response) { + } @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) {} + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + } }); callList.add(call); Intent intent = new Intent(TimelineReceiver.Types.MUTE_ACCOUNT); @@ -169,10 +167,12 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov Call call = mastodonApi.blockAccount(id); call.enqueue(new Callback() { @Override - public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {} + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + } @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) {} + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + } }); callList.add(call); Intent intent = new Intent(TimelineReceiver.Types.BLOCK_ACCOUNT); @@ -185,10 +185,12 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov Call call = mastodonApi.deleteStatus(id); call.enqueue(new Callback() { @Override - public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) {} + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + } @Override - public void onFailure(@NonNull Call call, @NonNull Throwable t) {} + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + } }); callList.add(call); } @@ -275,7 +277,7 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov ViewCompat.setTransitionName(view, url); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), - view, url); + view, url); startActivity(intent, options.toBundle()); } else { startActivity(intent); @@ -318,7 +320,7 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov } protected void openReportPage(String accountId, String accountUsername, String statusId, - Spanned statusContent) { + Spanned statusContent) { Intent intent = new Intent(getContext(), ReportActivity.class); intent.putExtra("account_id", accountId); intent.putExtra("account_username", accountUsername); diff --git a/app/src/main/java/com/keylesspalace/tusky/network/AuthInterceptor.java b/app/src/main/java/com/keylesspalace/tusky/network/AuthInterceptor.java index 60d0dd310..91d7c957f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/network/AuthInterceptor.java +++ b/app/src/main/java/com/keylesspalace/tusky/network/AuthInterceptor.java @@ -4,6 +4,7 @@ import android.support.annotation.NonNull; import com.keylesspalace.tusky.TuskyApplication; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import java.io.IOException; @@ -17,14 +18,17 @@ import okhttp3.Response; public final class AuthInterceptor implements Interceptor { - public AuthInterceptor() { } + AccountManager accountManager; + + public AuthInterceptor(AccountManager accountManager) { + this.accountManager = accountManager; + } @Override public Response intercept(@NonNull Chain chain) throws IOException { - AccountEntity currentAccount = TuskyApplication.getAccountManager().getActiveAccount(); - Request originalRequest = chain.request(); + AccountEntity currentAccount = accountManager.getActiveAccount(); Request.Builder builder = originalRequest.newBuilder(); if (currentAccount != null) { diff --git a/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt b/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt index bb47ce654..eda26998d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt +++ b/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt @@ -20,6 +20,7 @@ import android.content.Context import android.content.Intent import com.keylesspalace.tusky.TuskyApplication +import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.util.NotificationHelper class NotificationClearBroadcastReceiver : BroadcastReceiver() { @@ -27,7 +28,8 @@ class NotificationClearBroadcastReceiver : BroadcastReceiver() { val accountId = intent.getLongExtra(NotificationHelper.ACCOUNT_ID, -1) - val accountManager = TuskyApplication.getAccountManager() + val accountManager = TuskyApplication.getInstance(context) + .serviceLocator.get(AccountManager::class.java) val account = accountManager.getAccountById(accountId) if (account != null) { account.activeNotifications = "[]" diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java index a2c88d5e3..fafb502a4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java +++ b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java @@ -50,12 +50,16 @@ import java.util.List; public class NotificationHelper { - /** constants used in Intents */ + /** + * constants used in Intents + */ public static final String ACCOUNT_ID = "account_id"; private static final String TAG = "NotificationHelper"; - /** notification channels used on Android O+ **/ + /** + * notification channels used on Android O+ + **/ private static final String CHANNEL_MENTION = "CHANNEL_MENTION"; private static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW"; private static final String CHANNEL_BOOST = "CHANNEL_BOOST"; @@ -65,9 +69,9 @@ public class NotificationHelper { * Takes a given Mastodon notification and either creates a new Android notification or updates * the state of the existing notification to reflect the new interaction. * - * @param context to access application preferences and services - * @param body a new Mastodon notification - * @param account the account for which the notification should be shown + * @param context to access application preferences and services + * @param body a new Mastodon notification + * @param account the account for which the notification should be shown */ public static void make(final Context context, Notification body, AccountEntity account) { @@ -110,12 +114,12 @@ public class NotificationHelper { TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(resultIntent); - PendingIntent resultPendingIntent = stackBuilder.getPendingIntent((int)account.getId(), + PendingIntent resultPendingIntent = stackBuilder.getPendingIntent((int) account.getId(), PendingIntent.FLAG_UPDATE_CURRENT); Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class); deleteIntent.putExtra(ACCOUNT_ID, account.getId()); - PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, (int)account.getId(), deleteIntent, + PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, (int) account.getId(), deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT); final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(account, body)) @@ -131,7 +135,7 @@ public class NotificationHelper { builder.setContentTitle(titleForType(context, body)) .setContentText(bodyForType(body)); - if(body.getType() == Notification.Type.MENTION) { + if (body.getType() == Notification.Type.MENTION) { builder.setStyle(new NotificationCompat.BigTextStyle() .bigText(bodyForType(body))); } @@ -171,7 +175,7 @@ public class NotificationHelper { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //noinspection ConstantConditions - notificationManager.notify((int)account.getId(), builder.build()); + notificationManager.notify((int) account.getId(), builder.build()); } public static void createNotificationChannelsForAccount(AccountEntity account, Context context) { @@ -180,10 +184,10 @@ public class NotificationHelper { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); String[] channelIds = new String[]{ - CHANNEL_MENTION+account.getIdentifier(), - CHANNEL_FOLLOW+account.getIdentifier(), - CHANNEL_BOOST+account.getIdentifier(), - CHANNEL_FAVOURITE+account.getIdentifier()}; + CHANNEL_MENTION + account.getIdentifier(), + CHANNEL_FOLLOW + account.getIdentifier(), + CHANNEL_BOOST + account.getIdentifier(), + CHANNEL_FAVOURITE + account.getIdentifier()}; int[] channelNames = { R.string.notification_channel_mention_name, R.string.notification_channel_follow_name, @@ -252,15 +256,15 @@ public class NotificationHelper { } public static boolean areNotificationsEnabled(Context context) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // on Android >= O, notifications are enabled, if at least one channel is enabled NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //noinspection ConstantConditions - if(notificationManager.areNotificationsEnabled()) { - for(NotificationChannel channel: notificationManager.getNotificationChannels()) { - if(channel.getImportance() > NotificationManager.IMPORTANCE_NONE) { + if (notificationManager.areNotificationsEnabled()) { + for (NotificationChannel channel : notificationManager.getNotificationChannels()) { + if (channel.getImportance() > NotificationManager.IMPORTANCE_NONE) { Log.d(TAG, "NotificationsEnabled"); return true; } @@ -272,13 +276,15 @@ public class NotificationHelper { } else { // on Android < O, notifications are enabled, if at least one account has notification enabled - return TuskyApplication.getAccountManager().areNotificationsEnabled(); + return TuskyApplication.getInstance(context).getServiceLocator() + .get(AccountManager.class).areNotificationsEnabled(); } } public static void clearNotificationsForActiveAccount(Context context) { - AccountManager accountManager = TuskyApplication.getAccountManager(); + AccountManager accountManager = TuskyApplication.getInstance(context).getServiceLocator() + .get(AccountManager.class); AccountEntity account = accountManager.getActiveAccount(); if (account != null) { account.setActiveNotifications("[]"); @@ -286,7 +292,7 @@ public class NotificationHelper { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //noinspection ConstantConditions - notificationManager.cancel((int)account.getId()); + notificationManager.cancel((int) account.getId()); } } @@ -318,13 +324,13 @@ public class NotificationHelper { switch (notification.getType()) { default: case MENTION: - return CHANNEL_MENTION+account.getIdentifier(); + return CHANNEL_MENTION + account.getIdentifier(); case FOLLOW: - return CHANNEL_FOLLOW+account.getIdentifier(); + return CHANNEL_FOLLOW + account.getIdentifier(); case REBLOG: - return CHANNEL_BOOST+account.getIdentifier(); + return CHANNEL_BOOST + account.getIdentifier(); case FAVOURITE: - return CHANNEL_FAVOURITE+account.getIdentifier(); + return CHANNEL_FAVOURITE + account.getIdentifier(); } } @@ -354,7 +360,7 @@ public class NotificationHelper { if (array.length() > 3) { int length = array.length(); return String.format(context.getString(R.string.notification_summary_large), - array.get(length-1), array.get(length-2), array.get(length-3), length - 3); + array.get(length - 1), array.get(length - 2), array.get(length - 3), length - 3); } else if (array.length() == 3) { return String.format(context.getString(R.string.notification_summary_medium), array.get(2), array.get(1), array.get(0)); @@ -389,7 +395,7 @@ public class NotificationHelper { private static String bodyForType(Notification notification) { switch (notification.getType()) { case FOLLOW: - return "@"+ notification.getAccount().getUsername(); + return "@" + notification.getAccount().getUsername(); case MENTION: case FAVOURITE: case REBLOG: diff --git a/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt new file mode 100644 index 000000000..43ad2d3a5 --- /dev/null +++ b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt @@ -0,0 +1,103 @@ +package com.keylesspalace.tusky + +import android.widget.EditText +import com.keylesspalace.tusky.db.AccountEntity +import com.keylesspalace.tusky.db.AccountManager +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito +import org.mockito.Mockito.`when` +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.fakes.RoboMenuItem + +/** + * Created by charlag on 3/7/18. + */ + +@Config(application = FakeTuskyApplication::class) +@RunWith(RobolectricTestRunner::class) +class ComposeActivityTest { + + lateinit var activity: ComposeActivity + lateinit var application: FakeTuskyApplication + lateinit var serviceLocator: TuskyApplication.ServiceLocator + lateinit var accountManagerMock: AccountManager + + val account = AccountEntity( + id = 1, + domain = "example.token", + accessToken = "token", + isActive = true, + accountId = "1", + username = "username", + displayName = "Display Name", + profilePictureUrl = "", + notificationsEnabled = true, + notificationsMentioned = true, + notificationsFollowed = true, + notificationsReblogged = true, + notificationsFavorited = true, + notificationSound = true, + notificationVibration = true, + notificationLight = true + ) + + @Before + fun before() { + val controller = Robolectric.buildActivity(ComposeActivity::class.java) + activity = controller.get() + application = activity.application as FakeTuskyApplication + serviceLocator = Mockito.mock(TuskyApplication.ServiceLocator::class.java) + application.locator = serviceLocator + accountManagerMock = Mockito.mock(AccountManager::class.java) + `when`(serviceLocator.get(AccountManager::class.java)).thenReturn(accountManagerMock) + `when`(accountManagerMock.activeAccount).thenReturn(account) + controller.create().start() + } + + @Test + fun whenCloseButtonPressedAndEmpty_finish() { + clickUp() + assertTrue(activity.isFinishing) + } + + @Test + fun whenCloseButtonPressedNotEmpty_notFinish() { + insertSomeTextInContent() + clickUp() + assertFalse(activity.isFinishing) + // We would like to check for dialog but Robolectric doesn't work with AppCompat v7 yet + } + + @Test + fun whenBackButtonPressedAndEmpty_finish() { + clickBack() + assertTrue(activity.isFinishing) + } + + @Test + fun whenBackButtonPressedNotEmpty_notFinish() { + insertSomeTextInContent() + clickBack() + assertFalse(activity.isFinishing) + // We would like to check for dialog but Robolectric doesn't work with AppCompat v7 yet + } + + private fun clickUp() { + val menuItem = RoboMenuItem(android.R.id.home) + activity.onOptionsItemSelected(menuItem) + } + + private fun clickBack() { + activity.onBackPressed() + } + + private fun insertSomeTextInContent() { + activity.findViewById(R.id.compose_edit_field).setText("Some text") + } +} \ No newline at end of file diff --git a/app/src/test/java/com/keylesspalace/tusky/ExampleUnitTest.java b/app/src/test/java/com/keylesspalace/tusky/ExampleUnitTest.java deleted file mode 100644 index 3a2c941aa..000000000 --- a/app/src/test/java/com/keylesspalace/tusky/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.keylesspalace.tusky; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/app/src/test/java/com/keylesspalace/tusky/FakeTuskyApplication.kt b/app/src/test/java/com/keylesspalace/tusky/FakeTuskyApplication.kt new file mode 100644 index 000000000..afcca6412 --- /dev/null +++ b/app/src/test/java/com/keylesspalace/tusky/FakeTuskyApplication.kt @@ -0,0 +1,18 @@ +package com.keylesspalace.tusky + +/** + * Created by charlag on 3/7/18. + */ + +class FakeTuskyApplication : TuskyApplication() { + + lateinit var locator: ServiceLocator + + override fun initPicasso() { + // No-op + } + + override fun getServiceLocator(): ServiceLocator { + return locator + } +} \ No newline at end of file