Reorganize tests

pull/87/merge
Alinson S. Xavier 8 years ago
parent cb4ab3b436
commit 29d1de46e7

@ -12,10 +12,9 @@ android {
buildConfigField "Integer", "databaseVersion", "19"
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
buildConfigField "int", "roboSdk", (System.getenv("ROBO_SDK")?: "25")
buildConfigField "int", "roboSdk", (System.getenv("ROBO_SDK") ?: "25")
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArgument "size", "medium"
}
buildTypes {
@ -23,9 +22,6 @@ android {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
debug {
testCoverageEnabled = true
}
}
lintOptions {
@ -53,7 +49,6 @@ android {
dependencies {
implementation project(":uhabits-core")
implementation 'com.android.support:appcompat-v7:25.3.1'
implementation 'com.android.support:design:25.3.1'
implementation 'com.android.support:preference-v14:25.3.1'
@ -68,14 +63,25 @@ dependencies {
implementation 'com.google.code.gson:gson:2.7'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'com.google.guava:guava:20.0'
compileOnly 'javax.annotation:jsr250-api:1.0'
compileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
testImplementation project(":uhabits-core")
testImplementation 'junit:junit:5.0-SNAPSHOT'
testImplementation 'org.hamcrest:hamcrest-library:1.4-atlassian-1'
testImplementation 'org.mockito:mockito-core:2.8.9'
testImplementation 'org.json:json:20160810'
testImplementation 'org.robolectric:robolectric:3.4-rc2'
testCompileOnly 'javax.annotation:jsr250-api:1.0'
testCompileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
testAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
testAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
androidTestImplementation project(":uhabits-core")
androidTestImplementation 'com.android.support:support-annotations:25.3.1'
androidTestImplementation 'com.android.support.test:rules:0.5'
androidTestImplementation 'com.android.support.test:runner:0.5'
@ -83,23 +89,11 @@ dependencies {
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation 'com.google.guava:guava:20.0'
compileOnly 'javax.annotation:jsr250-api:1.0'
compileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
androidTestCompileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
testAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
testAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc2'
androidTestAnnotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3'
androidTestAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.6.1-SNAPSHOT'
implementation('com.opencsv:opencsv:3.9') {
exclude group: 'commons-logging', module: 'commons-logging'
}
@ -107,43 +101,3 @@ dependencies {
exclude group: 'org.json', module: 'json'
}
}
jacoco {
toolVersion = "0.7.4.201502262128"
}
task coverageReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {
jacocoClasspath = configurations['androidJacocoAnt']
reports {
html.enabled = true
xml.enabled = true
}
def excludes = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*',
'**/*Test*.*',
'**/*$Lambda$*',
'**/*$ViewBinder*',
'**/*MembersInjector*',
'**/*_Provide*',
'**/*Module_*',
'**/com/android/**/*',
'android/**/*',
'**/*Dagger*',
'**/*_Factory*'
]
def srcDir = "${project.projectDir}/src/main/java"
def classDir = "${buildDir}/intermediates/classes/debug"
def jvmExecData = "${buildDir}/jacoco/testDebugUnitTest.exec"
def connectedExecData = "${buildDir}/outputs/code-coverage/connected/coverage.ec"
sourceDirectories = files(srcDir)
classDirectories = files(fileTree(dir: classDir, excludes: excludes))
executionData = files(jvmExecData, connectedExecData)
}

@ -26,12 +26,21 @@ import org.isoron.uhabits.tasks.*;
import dagger.*;
@Module
class SingleThreadModule
{
@Provides
@AppScope
public static TaskRunner provideTaskRunner()
{
return new SingleThreadTaskRunner();
}
}
@AppScope
@Component(modules = {
AppModule.class, SingleThreadTaskRunner.class, SQLModelFactory.class
AppModule.class, SingleThreadModule.class, SQLModelFactory.class
})
public interface AndroidTestComponent extends AppComponent
{
}

@ -27,8 +27,9 @@ import android.support.annotation.*;
import android.support.test.*;
import android.util.*;
import junit.framework.*;
import org.isoron.androidbase.*;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.tasks.*;
@ -38,17 +39,14 @@ import org.junit.*;
import java.util.*;
import java.util.concurrent.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
public class BaseAndroidTest
public class BaseAndroidTest extends TestCase
{
// 8:00am, January 25th, 2015 (UTC)
public static final long FIXED_LOCAL_TIME = 1422172800000L;
private static boolean isLooperPrepared;
protected Context testContext;
protected Context targetContext;
@ -71,14 +69,11 @@ public class BaseAndroidTest
protected BaseSystem baseSystem;
@Override
@Before
public void setUp()
{
if (!isLooperPrepared)
{
Looper.prepare();
isLooperPrepared = true;
}
if (Looper.myLooper() == null) Looper.prepare();
targetContext = InstrumentationRegistry.getTargetContext();
testContext = InstrumentationRegistry.getContext();

@ -23,7 +23,7 @@ import android.os.*;
import android.support.test.runner.*;
import android.test.suitebuilder.annotation.*;
import org.isoron.androidbase.activities.*;
import org.isoron.androidbase.*;
import org.isoron.uhabits.models.*;
import org.junit.*;
import org.junit.runner.*;

@ -22,7 +22,7 @@ package org.isoron.uhabits;
import android.support.test.runner.*;
import android.test.suitebuilder.annotation.*;
import org.isoron.androidbase.activities.*;
import org.isoron.androidbase.*;
import org.junit.*;
import org.junit.runner.*;

@ -19,8 +19,8 @@
package org.isoron.uhabits.activities.common.views;
import android.support.test.filters.*;
import android.support.test.runner.*;
import android.test.suitebuilder.annotation.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;

@ -19,8 +19,8 @@
package org.isoron.uhabits.activities.common.views;
import android.support.test.filters.*;
import android.support.test.runner.*;
import android.test.suitebuilder.annotation.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -17,7 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
package org.isoron.androidbase;
import android.content.*;
import android.os.*;
@ -44,13 +44,19 @@ import javax.inject.*;
* a bug report, obtaining device information, or requesting runtime
* permissions.
*/
@ActivityScope
public class BaseSystem
@AppScope
public class BaseSystem implements CACertSSLContextProvider
{
private Context context;
@Override
public Context getContext()
{
return context;
}
@Inject
public BaseSystem(@ActivityContext Context context)
public BaseSystem(@AppContext Context context)
{
this.context = context;
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -17,10 +17,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.utils;
package org.isoron.androidbase;
import android.content.*;
import android.support.annotation.*;
import java.io.*;
import java.security.*;
@ -29,14 +28,14 @@ import java.security.cert.*;
import javax.net.ssl.*;
public abstract class SSLUtils
public interface CACertSSLContextProvider
{
public static SSLContext getCACertSSLContext(@NonNull Context context)
default SSLContext getCACertSSLContext()
{
try
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getAssets().open("cacert.pem");
InputStream caInput = getContext().getAssets().open("cacert.pem");
Certificate ca = cf.generateCertificate(caInput);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
@ -58,4 +57,5 @@ public abstract class SSLUtils
}
}
Context getContext();
}

@ -21,6 +21,7 @@ package org.isoron.androidbase.activities;
import android.support.annotation.*;
import org.isoron.androidbase.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.models.sqlite.*;

@ -24,8 +24,10 @@ import android.graphics.*;
import android.graphics.drawable.*;
import android.net.*;
import android.os.*;
import android.provider.*;
import android.support.annotation.*;
import android.support.design.widget.*;
import android.support.v4.app.*;
import android.support.v4.content.res.*;
import android.support.v7.app.*;
import android.support.v7.view.ActionMode;
@ -34,10 +36,18 @@ import android.view.*;
import android.widget.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.notifications.*;
import org.isoron.uhabits.utils.*;
import java.io.*;
import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
import static android.media.RingtoneManager.EXTRA_RINGTONE_EXISTING_URI;
import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT;
import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT;
import static android.media.RingtoneManager.EXTRA_RINGTONE_TYPE;
import static android.media.RingtoneManager.TYPE_NOTIFICATION;
import static android.os.Build.VERSION.*;
import static android.os.Build.VERSION_CODES.*;
import static android.support.v4.content.FileProvider.*;
@ -117,6 +127,21 @@ public class BaseScreen
}
}
public static void showRingtonePicker(Fragment fragment,
int requestCode)
{
Uri existingRingtoneUri = RingtoneManager.getRingtoneUri(fragment.getContext());
Uri defaultRingtoneUri = Settings.System.DEFAULT_NOTIFICATION_URI;
Intent intent = new Intent(ACTION_RINGTONE_PICKER);
intent.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
intent.putExtra(EXTRA_RINGTONE_SHOW_DEFAULT, true);
intent.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
intent.putExtra(EXTRA_RINGTONE_DEFAULT_URI, defaultRingtoneUri);
intent.putExtra(EXTRA_RINGTONE_EXISTING_URI, existingRingtoneUri);
fragment.startActivityForResult(intent, requestCode);
}
/**
* Notifies the screen that its contents should be updated.
*/

@ -44,6 +44,8 @@ import dagger.*;
})
public interface AppComponent
{
BaseSystem getBaseSystem();
CommandRunner getCommandRunner();
@AppContext
@ -75,6 +77,8 @@ public interface AppComponent
ReminderScheduler getReminderScheduler();
RingtoneManager getRingtoneManager();
SyncManager getSyncManager();
TaskRunner getTaskRunner();
@ -82,4 +86,6 @@ public interface AppComponent
WidgetPreferences getWidgetPreferences();
WidgetUpdater getWidgetUpdater();
MidnightTimer getMidnightTimer();
}

@ -60,6 +60,7 @@ public class ListHabitsActivity extends BaseActivity
super.onCreate(savedInstanceState);
HabitsApplication app = (HabitsApplication) getApplicationContext();
midnightTimer = app.getComponent().getMidnightTimer();
component = DaggerListHabitsComponent
.builder()
@ -83,8 +84,6 @@ public class ListHabitsActivity extends BaseActivity
screen.setSelectionMenu(selectionMenu);
rootView.setController(controller, selectionMenu);
midnightTimer = component.getMidnightTimer();
if(prefs.isSyncFeatureEnabled())
startService(new Intent(this, SyncService.class));

@ -40,8 +40,6 @@ public interface ListHabitsComponent
ListHabitsMenu getMenu();
MidnightTimer getMidnightTimer();
NumberButtonControllerFactory getNumberButtonControllerFactory();
ListHabitsRootView getRootView();

@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.habits.list;
import android.support.annotation.*;
import org.isoron.androidbase.*;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.habits.list.controllers.*;

@ -70,13 +70,7 @@ public class HeaderView extends ScrollableChart
{
HabitsApplication app = (HabitsApplication) appContext;
prefs = app.getComponent().getPreferences();
}
if (context instanceof ListHabitsActivity)
{
ListHabitsComponent component =
((ListHabitsActivity) context).getListHabitsComponent();
midnightTimer = component.getMidnightTimer();
midnightTimer = app.getComponent().getMidnightTimer();
}
init();

@ -22,6 +22,7 @@ package org.isoron.uhabits.activities.habits.show;
import android.support.annotation.*;
import android.view.*;
import org.isoron.androidbase.*;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;

@ -25,10 +25,11 @@ import android.os.*;
import android.support.annotation.*;
import android.support.v7.preference.*;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.notifications.*;
import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.utils.*;
import static org.isoron.uhabits.activities.habits.list.ListHabitsScreen.*;
@ -47,7 +48,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
{
if (requestCode == RINGTONE_REQUEST_CODE)
{
RingtoneUtils.parseRingtoneData(getContext(), data);
RingtoneManager.parseRingtoneData(getContext(), data);
updateRingtoneDescription();
return;
}
@ -113,7 +114,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
if (key.equals("reminderSound"))
{
RingtoneUtils.startRingtonePickerActivity(this,
BaseScreen.showRingtonePicker(this,
RINGTONE_REQUEST_CODE);
return true;
}
@ -158,7 +159,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void updateRingtoneDescription()
{
String ringtoneName = RingtoneUtils.getRingtoneName(getContext());
String ringtoneName = RingtoneManager.getRingtoneName(getContext());
if (ringtoneName == null) return;
Preference ringtonePreference = findPreference("reminderSound");
ringtonePreference.setSummary(ringtoneName);

@ -40,7 +40,7 @@ import java.util.*;
import javax.inject.*;
import static android.graphics.BitmapFactory.*;
import static org.isoron.uhabits.utils.RingtoneUtils.*;
import static org.isoron.uhabits.notifications.RingtoneManager.*;
@AppScope
public class NotificationTray

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -17,7 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.utils;
package org.isoron.uhabits.notifications;
import android.content.*;
import android.media.*;
@ -25,14 +25,25 @@ import android.net.*;
import android.preference.*;
import android.provider.*;
import android.support.annotation.*;
import android.support.v4.app.*;
import org.isoron.androidbase.*;
import org.isoron.uhabits.*;
import javax.inject.*;
import static android.media.RingtoneManager.*;
public abstract class RingtoneUtils
@AppScope
public class RingtoneManager
{
private Context context;
@Inject
public RingtoneManager(@AppContext @NonNull Context context)
{
this.context = context;
}
@Nullable
public static String getRingtoneName(Context context)
{
@ -101,18 +112,4 @@ public abstract class RingtoneUtils
}
}
public static void startRingtonePickerActivity(Fragment fragment,
int requestCode)
{
Uri existingRingtoneUri = getRingtoneUri(fragment.getContext());
Uri defaultRingtoneUri = Settings.System.DEFAULT_NOTIFICATION_URI;
Intent intent = new Intent(ACTION_RINGTONE_PICKER);
intent.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
intent.putExtra(EXTRA_RINGTONE_SHOW_DEFAULT, true);
intent.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
intent.putExtra(EXTRA_RINGTONE_DEFAULT_URI, defaultRingtoneUri);
intent.putExtra(EXTRA_RINGTONE_EXISTING_URI, existingRingtoneUri);
fragment.startActivityForResult(intent, requestCode);
}
}

@ -19,7 +19,6 @@
package org.isoron.uhabits.sync;
import android.content.*;
import android.support.annotation.*;
import android.util.*;
@ -27,7 +26,6 @@ import org.isoron.androidbase.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.commands.*;
import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.utils.*;
import org.json.*;
import java.net.*;
@ -84,12 +82,15 @@ public class SyncManager implements CommandRunner.Listener
private boolean isListening;
private BaseSystem system;
@Inject
public SyncManager(@AppContext @NonNull Context context,
public SyncManager(@NonNull BaseSystem system,
@NonNull Preferences prefs,
@NonNull CommandRunner commandRunner,
@NonNull CommandParser commandParser)
{
this.system = system;
Log.i("SyncManager", this.toString());
this.prefs = prefs;
@ -105,7 +106,7 @@ public class SyncManager implements CommandRunner.Listener
String serverURL = prefs.getSyncAddress();
Log.d("SyncManager", clientId);
connect(context, serverURL);
connect(serverURL);
}
private JSONObject toJSONObject(String json)
@ -164,11 +165,11 @@ public class SyncManager implements CommandRunner.Listener
isListening = false;
}
private void connect(@AppContext @NonNull Context context, String serverURL)
private void connect(String serverURL)
{
try
{
IO.setDefaultSSLContext(SSLUtils.getCACertSSLContext(context));
IO.setDefaultSSLContext(system.getCACertSSLContext());
socket = IO.socket(serverURL);
logSocketEvent(socket, EVENT_CONNECT, "Connected");

@ -25,7 +25,6 @@ import android.support.annotation.*;
import com.google.auto.factory.*;
import org.isoron.androidbase.*;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.tasks.*;
import org.isoron.uhabits.utils.*;

@ -25,7 +25,6 @@ import android.util.*;
public abstract class ColorUtils
{
public static int colorToPaletteIndex(Context context, int color)
{
StyledResources res = new StyledResources(context);

@ -1,59 +0,0 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.utils;
import android.appwidget.*;
import android.content.*;
import android.os.*;
import android.support.annotation.*;
import android.widget.*;
import org.isoron.uhabits.widgets.*;
import static android.appwidget.AppWidgetManager.*;
import static org.isoron.uhabits.utils.InterfaceUtils.*;
public abstract class WidgetUtils
{
@NonNull
public static WidgetDimensions getDimensionsFromOptions(
@NonNull Context ctx, @NonNull Bundle options)
{
int maxWidth =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_WIDTH));
int maxHeight =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_HEIGHT));
int minWidth =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_WIDTH));
int minHeight =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_HEIGHT));
return new WidgetDimensions(minWidth, maxHeight, maxWidth, minHeight);
}
public static void updateAppWidget(@NonNull AppWidgetManager manager,
@NonNull BaseWidget widget)
{
RemoteViews landscape = widget.getLandscapeRemoteViews();
RemoteViews portrait = widget.getPortraitRemoteViews();
RemoteViews views = new RemoteViews(landscape, portrait);
manager.updateAppWidget(widget.getId(), views);
}
}

@ -31,7 +31,8 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.preferences.*;
import static org.isoron.uhabits.utils.WidgetUtils.*;
import static android.appwidget.AppWidgetManager.*;
import static org.isoron.uhabits.utils.InterfaceUtils.*;
public abstract class BaseWidgetProvider extends AppWidgetProvider
{
@ -39,6 +40,31 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
private WidgetPreferences widgetPrefs;
public static void updateAppWidget(@NonNull AppWidgetManager manager,
@NonNull BaseWidget widget)
{
RemoteViews landscape = widget.getLandscapeRemoteViews();
RemoteViews portrait = widget.getPortraitRemoteViews();
RemoteViews views = new RemoteViews(landscape, portrait);
manager.updateAppWidget(widget.getId(), views);
}
@NonNull
public WidgetDimensions getDimensionsFromOptions(@NonNull Context ctx,
@NonNull Bundle options)
{
int maxWidth =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_WIDTH));
int maxHeight =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_HEIGHT));
int minWidth =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_WIDTH));
int minHeight =
(int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_HEIGHT));
return new WidgetDimensions(minWidth, maxHeight, maxWidth, minHeight);
}
@Override
public void onAppWidgetOptionsChanged(@Nullable Context context,
@Nullable AppWidgetManager manager,
@ -100,7 +126,8 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
updateDependencies(context);
new Thread(() -> {
new Thread(() ->
{
Looper.prepare();
for (int id : widgetIds)
update(context, manager, id);
@ -128,8 +155,10 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
RemoteViews errorView =
new RemoteViews(context.getPackageName(), R.layout.widget_error);
if(e instanceof HabitNotFoundException) {
errorView.setCharSequence(R.id.label, "setText", context.getString(R.string.habit_not_found));
if (e instanceof HabitNotFoundException)
{
errorView.setCharSequence(R.id.label, "setText",
context.getString(R.string.habit_not_found));
}
manager.updateAppWidget(widgetId, errorView);
@ -143,8 +172,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
{
BaseWidget widget = getWidgetFromId(context, widgetId);
Bundle options = manager.getAppWidgetOptions(widgetId);
widget.setDimensions(
getDimensionsFromOptions(context, options));
widget.setDimensions(getDimensionsFromOptions(context, options));
updateAppWidget(manager, widget);
}

@ -19,13 +19,14 @@
package org.isoron.uhabits.activities.habits.list;
import org.isoron.androidbase.activities.*;
import org.isoron.androidbase.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.habits.list.model.*;
import org.isoron.uhabits.commands.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.tasks.*;
import org.isoron.uhabits.tasks.android.*;
import org.isoron.uhabits.utils.*;
import org.isoron.uhabits.widgets.*;
import org.junit.*;

@ -21,7 +21,7 @@ package org.isoron.uhabits.activities.habits.show;
import android.view.*;
import org.isoron.androidbase.activities.*;
import org.isoron.androidbase.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.tasks.*;

@ -1,37 +1,24 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
apply plugin: 'java'
dependencies {
compileOnly 'javax.annotation:jsr250-api:1.0'
compileOnly 'com.google.auto.factory:auto-factory:1.0-beta3'
implementation 'com.google.dagger:dagger:2.11-rc2'
implementation 'com.android.support:support-annotations:25.3.1'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'org.apache.commons:commons-lang3:3.5'
implementation 'com.google.code.gson:gson:2.7'
testImplementation 'junit:junit:4+'
testImplementation 'org.hamcrest:hamcrest-library:1.4-atlassian-1'
testImplementation 'org.mockito:mockito-core:2.8.9'
testImplementation 'org.json:json:20160810'
implementation ('com.opencsv:opencsv:3.9') {
exclude group: 'commons-logging', module: 'commons-logging'
}
compile 'junit:junit:4.12'
}
sourceCompatibility = "1.8"

@ -19,20 +19,8 @@
package org.isoron.uhabits.tasks;
import org.isoron.uhabits.*;
import dagger.*;
@Module
public class SingleThreadTaskRunner implements TaskRunner
{
@Provides
@AppScope
public static TaskRunner provideTaskRunner()
{
return new SingleThreadTaskRunner();
}
@Override
public void addListener(Listener listener)
{

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -19,7 +19,7 @@
package org.isoron.uhabits.utils;
import org.isoron.androidbase.activities.*;
import org.isoron.uhabits.*;
import java.util.*;
import java.util.concurrent.*;
@ -29,7 +29,7 @@ import javax.inject.*;
/**
* A class that emits events when a new day starts.
*/
@ActivityScope
@AppScope
public class MidnightTimer
{
private final List<MidnightListener> listeners;

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.models.memory.*;
import org.isoron.uhabits.utils.*;
import org.junit.*;
import java.util.*;
public class BaseUnitTest
{
protected HabitList habitList;
protected HabitFixtures fixtures;
protected MemoryModelFactory modelFactory;
@Before
public void setUp()
{
// 8:00am, January 25th, 2015 (UTC)
long fixed_local_time = 1422172800000L;
DateUtils.setFixedLocalTime(fixed_local_time);
modelFactory = new MemoryModelFactory();
habitList = modelFactory.buildHabitList();
fixtures = new HabitFixtures(modelFactory);
}
@After
public void tearDown()
{
DateUtils.setFixedLocalTime(null);
}
public long timestamp(int year, int month, int day)
{
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
cal.set(year, month, day);
return cal.getTimeInMillis();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -19,7 +19,7 @@
package org.isoron.uhabits.models;
import org.isoron.uhabits.utils.DateUtils;
import org.isoron.uhabits.utils.*;
public class HabitFixtures
{

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -26,11 +26,9 @@ import org.junit.*;
import java.io.*;
import java.util.*;
import static junit.framework.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.isoron.uhabits.models.HabitList.Order.*;
import static org.junit.Assert.*;
@SuppressWarnings("JavaDoc")
public class HabitListTest extends BaseUnitTest
@ -70,12 +68,6 @@ public class HabitListTest extends BaseUnitTest
.build());
}
@Test
public void test_size()
{
assertThat(habitList.size(), equalTo(10));
}
@Test
public void test_countActive()
{
@ -114,6 +106,54 @@ public class HabitListTest extends BaseUnitTest
assertThat(habit1, equalTo(habit2));
}
@Test
public void test_ordering()
{
HabitList list = modelFactory.buildHabitList();
Habit h1 = fixtures.createEmptyHabit();
h1.setName("A Habit");
h1.setColor(2);
Habit h2 = fixtures.createEmptyHabit();
h2.setName("B Habit");
h2.setColor(2);
Habit h3 = fixtures.createEmptyHabit();
h3.setName("C Habit");
h3.setColor(0);
Habit h4 = fixtures.createEmptyHabit();
h4.setName("D Habit");
h4.setColor(1);
list.add(h3);
list.add(h1);
list.add(h4);
list.add(h2);
list.setOrder(BY_POSITION);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h1));
assertThat(list.getByPosition(2), equalTo(h4));
assertThat(list.getByPosition(3), equalTo(h2));
list.setOrder(BY_NAME);
assertThat(list.getByPosition(0), equalTo(h1));
assertThat(list.getByPosition(1), equalTo(h2));
assertThat(list.getByPosition(2), equalTo(h3));
assertThat(list.getByPosition(3), equalTo(h4));
list.remove(h1);
list.add(h1);
assertThat(list.getByPosition(0), equalTo(h1));
list.setOrder(BY_COLOR);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h4));
assertThat(list.getByPosition(2), equalTo(h1));
assertThat(list.getByPosition(3), equalTo(h2));
}
@Test
public void test_reorder()
{
@ -150,6 +190,12 @@ public class HabitListTest extends BaseUnitTest
}
}
@Test
public void test_size()
{
assertThat(habitList.size(), equalTo(10));
}
@Test
public void test_writeCSV() throws IOException
{
@ -180,52 +226,4 @@ public class HabitListTest extends BaseUnitTest
MatcherAssert.assertThat(writer.toString(), equalTo(expectedCSV));
}
@Test
public void test_ordering()
{
HabitList list = modelFactory.buildHabitList();
Habit h1 = fixtures.createEmptyHabit();
h1.setName("A Habit");
h1.setColor(2);
Habit h2 = fixtures.createEmptyHabit();
h2.setName("B Habit");
h2.setColor(2);
Habit h3 = fixtures.createEmptyHabit();
h3.setName("C Habit");
h3.setColor(0);
Habit h4 = fixtures.createEmptyHabit();
h4.setName("D Habit");
h4.setColor(1);
list.add(h3);
list.add(h1);
list.add(h4);
list.add(h2);
list.setOrder(BY_POSITION);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h1));
assertThat(list.getByPosition(2), equalTo(h4));
assertThat(list.getByPosition(3), equalTo(h2));
list.setOrder(BY_NAME);
assertThat(list.getByPosition(0), equalTo(h1));
assertThat(list.getByPosition(1), equalTo(h2));
assertThat(list.getByPosition(2), equalTo(h3));
assertThat(list.getByPosition(3), equalTo(h4));
list.remove(h1);
list.add(h1);
assertThat(list.getByPosition(0), equalTo(h1));
list.setOrder(BY_COLOR);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h4));
assertThat(list.getByPosition(2), equalTo(h1));
assertThat(list.getByPosition(3), equalTo(h2));
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -23,7 +23,6 @@ import org.isoron.uhabits.*;
import org.junit.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*;
public class HabitTest extends BaseUnitTest
@ -41,10 +40,10 @@ public class HabitTest extends BaseUnitTest
assertFalse(habit.isArchived());
assertThat(habit.hasReminder(), is(false));
assertThat(habit.getStreaks(), is(not(nullValue())));
assertThat(habit.getScores(), is(not(nullValue())));
assertThat(habit.getRepetitions(), is(not(nullValue())));
assertThat(habit.getCheckmarks(), is(not(nullValue())));
assertNotNull(habit.getStreaks());
assertNotNull(habit.getScores());
assertNotNull(habit.getRepetitions());
assertNotNull(habit.getCheckmarks());
}
@Test

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
@ -28,7 +28,7 @@ import java.util.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.hamcrest.number.IsCloseTo.*;
public class ScoreListTest extends BaseUnitTest
{

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
Loading…
Cancel
Save