diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java
index 7d7b1af56..035e0c150 100644
--- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java
+++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java
@@ -43,7 +43,6 @@ public class HabitsTest extends BaseUserInterfaceTest
verifyShowsScreen(LIST_HABITS);
clickMenu(ADD);
- clickText("Yes or No");
verifyShowsScreen(EDIT_HABIT);
typeName("Hello world");
diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java
index 109d98092..fe93da24e 100644
--- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java
+++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java
@@ -60,7 +60,7 @@ public abstract class ListHabitsSteps
break;
case ADD:
- clickViewWithId(R.id.actionAdd);
+ clickViewWithId(R.id.actionCreateBooleanHabit);
break;
case EDIT:
diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt
index cfbbd81a5..47dfec5ee 100644
--- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt
+++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenu.kt
@@ -39,7 +39,9 @@ class ListHabitsMenu @Inject constructor(
val nightModeItem = menu.findItem(R.id.actionToggleNightMode)
val hideArchivedItem = menu.findItem(R.id.actionHideArchived)
val hideCompletedItem = menu.findItem(R.id.actionHideCompleted)
+ val addNumericalHabit = menu.findItem(R.id.actionCreateNumeralHabit)
+ addNumericalHabit.isVisible = preferences.isDeveloper
nightModeItem.isChecked = themeSwitcher.isNightMode
hideArchivedItem.isChecked = !preferences.showArchived
hideCompletedItem.isChecked = !preferences.showCompleted
diff --git a/android/uhabits-android/src/main/res/menu/list_habits.xml b/android/uhabits-android/src/main/res/menu/list_habits.xml
index 82a3e20b4..7f8e46731 100644
--- a/android/uhabits-android/src/main/res/menu/list_habits.xml
+++ b/android/uhabits-android/src/main/res/menu/list_habits.xml
@@ -23,23 +23,12 @@
tools:context=".MainActivity">
-
+ app:showAsAction="always"/>
-
-
+
+
+
diff --git a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt b/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt
deleted file mode 100644
index 6ef06d002..000000000
--- a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsMenuTest.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2017 Álinson Santos Xavier
- *
- * 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 .
- */
-
-package org.isoron.uhabits.activities.habits.list
-
-import android.view.*
-import org.isoron.androidbase.activities.*
-import org.isoron.uhabits.*
-import org.isoron.uhabits.core.preferences.*
-import org.isoron.uhabits.core.ui.*
-import org.isoron.uhabits.core.ui.screens.habits.list.*
-import org.junit.*
-import org.mockito.*
-import org.mockito.Mockito.*
-
-class ListHabitsMenuTest : BaseAndroidJVMTest() {
- @Mock lateinit var activity: BaseActivity
- @Mock lateinit var preferences: Preferences
- @Mock lateinit var themeSwitcher: ThemeSwitcher
- @Mock lateinit var behavior: ListHabitsMenuBehavior
- lateinit var menu: ListHabitsMenu
-
- @Before
- override fun setUp() {
- super.setUp()
- menu = ListHabitsMenu(activity, preferences,
- themeSwitcher, behavior)
- }
-
- @Test
- fun testOnCreate() {
- val nightModeItem = mock(MenuItem::class.java)
- val hideArchivedItem = mock(MenuItem::class.java)
- val hideCompletedItem = mock(MenuItem::class.java)
- val androidMenu = mock(Menu::class.java)
- `when`(androidMenu.findItem(R.id.actionToggleNightMode)).thenReturn(
- nightModeItem)
- `when`(androidMenu.findItem(R.id.actionHideArchived)).thenReturn(
- hideArchivedItem)
- `when`(androidMenu.findItem(R.id.actionHideCompleted)).thenReturn(
- hideCompletedItem)
-
- `when`(preferences.showArchived).thenReturn(false)
- `when`(preferences.showCompleted).thenReturn(false)
- `when`(themeSwitcher.isNightMode).thenReturn(false)
-
- menu.onCreate(androidMenu)
-
- verify(nightModeItem).isChecked = false
- verify(hideArchivedItem).isChecked = true
- verify(hideCompletedItem).isChecked = true
- reset(nightModeItem, hideArchivedItem, hideCompletedItem)
-
- `when`(preferences.showArchived).thenReturn(true)
- `when`(preferences.showCompleted).thenReturn(true)
- `when`(themeSwitcher.isNightMode).thenReturn(true)
-
- menu.onCreate(androidMenu)
-
- verify(nightModeItem).isChecked = true
- verify(hideArchivedItem).isChecked = false
- verify(hideCompletedItem).isChecked = false
- }
-
- @Test
- fun testOnSelected_about() {
- onItemSelected(R.id.actionAbout)
- verify(behavior).onViewAbout()
- }
-
-// @Test
-// fun testOnSelected_add() {
-// onItemSelected(R.id.actionAdd)
-// verify(behavior).onCreateHabit()
-// }
-
- @Test
- fun testOnSelected_faq() {
- onItemSelected(R.id.actionFAQ)
- verify(behavior).onViewFAQ()
- }
-
- @Test
- fun testOnSelected_nightMode() {
- onItemSelected(R.id.actionToggleNightMode)
- verify(behavior).onToggleNightMode()
- }
-
- @Test
- fun testOnSelected_settings() {
- onItemSelected(R.id.actionSettings)
- verify(behavior).onViewSettings()
- }
-
- @Test
- fun testOnSelected_showArchived() {
- onItemSelected(R.id.actionHideArchived)
- verify(behavior).onToggleShowArchived()
- }
-
- @Test
- fun testOnSelected_showCompleted() {
- onItemSelected(R.id.actionHideCompleted)
- verify(behavior).onToggleShowCompleted()
- }
-
- private fun onItemSelected(actionId: Int) {
- val item = mock(MenuItem::class.java)
- `when`(item.itemId).thenReturn(actionId)
- menu.onItemSelected(item)
- }
-}
\ No newline at end of file
diff --git a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt b/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt
deleted file mode 100644
index ea206264f..000000000
--- a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreenTest.kt
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2017 Álinson Santos Xavier
- *
- * 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 .
- */
-
-package org.isoron.uhabits.activities.habits.list
-
-import android.content.*
-import dagger.*
-import org.isoron.androidbase.activities.*
-import org.isoron.uhabits.*
-import org.isoron.uhabits.activities.common.dialogs.*
-import org.isoron.uhabits.activities.habits.edit.*
-import org.isoron.uhabits.activities.habits.list.views.*
-import org.isoron.uhabits.core.commands.*
-import org.isoron.uhabits.core.models.*
-import org.isoron.uhabits.core.preferences.*
-import org.isoron.uhabits.core.ui.*
-import org.isoron.uhabits.core.ui.callbacks.*
-import org.isoron.uhabits.core.ui.screens.habits.list.*
-import org.isoron.uhabits.intents.*
-import org.isoron.uhabits.tasks.*
-import org.junit.*
-import org.junit.runner.*
-import org.mockito.*
-import org.mockito.ArgumentMatchers.*
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.verify
-import org.mockito.junit.*
-
-@RunWith(MockitoJUnitRunner::class)
-class ListHabitsScreenTest : BaseAndroidJVMTest() {
- @Mock lateinit var activity: BaseActivity
- @Mock lateinit var habit: Habit
- @Mock lateinit var intent: Intent
- @Mock lateinit var rootView: ListHabitsRootView
- @Mock lateinit var confirmDeleteDialogFactory: ConfirmDeleteDialogFactory
- @Mock lateinit var intentFactory: IntentFactory
- @Mock lateinit var colorPickerDialogFactory: ColorPickerDialogFactory
- @Mock lateinit var editHabitDialogFactory: EditHabitDialogFactory
- @Mock lateinit var themeSwitcher: ThemeSwitcher
- @Mock lateinit var prefs: Preferences
- @Mock lateinit var menu: ListHabitsMenu
- @Mock lateinit var selectionMenu: ListHabitsSelectionMenu
- @Mock lateinit var adapter: HabitCardListAdapter
- @Mock lateinit var behavior: ListHabitsBehavior
- @Mock lateinit var exportDBFactory: ExportDBTaskFactory
- @Mock lateinit var importTaskFactory: ImportDataTaskFactory
- @Mock lateinit var numberPickerFactory: NumberPickerFactory
-
- lateinit var screen: ListHabitsScreen
-
- @Before
- override fun setUp() {
- super.setUp()
- commandRunner = mock(CommandRunner::class.java)
- screen = spy(ListHabitsScreen(
- activity = activity,
- rootView = rootView,
- commandRunner = commandRunner,
- intentFactory = intentFactory,
- themeSwitcher = themeSwitcher,
- preferences = prefs,
- confirmDeleteDialogFactory = confirmDeleteDialogFactory,
- colorPickerFactory = colorPickerDialogFactory,
- editHabitDialogFactory = editHabitDialogFactory,
- menu = Lazy { menu },
- selectionMenu = Lazy { selectionMenu },
- adapter = adapter,
- behavior = Lazy { behavior },
- taskRunner = taskRunner,
- exportDBFactory = exportDBFactory,
- importTaskFactory = importTaskFactory,
- numberPickerFactory = numberPickerFactory))
-
- doNothing().`when`(screen).showMessage(anyInt())
- }
-
- @Test
- fun testApplyTheme() {
- screen.applyTheme()
- verify(activity).restartWithFade(ListHabitsActivity::class.java)
- }
-
- @Test
- fun testOnAttached() {
- screen.onAttached()
- verify(commandRunner).addListener(screen)
- }
-
- @Test
- fun testOnCommand() {
- val c = mock(DeleteHabitsCommand::class.java)
- screen.onCommandExecuted(c, null)
- verify(screen).showMessage(R.string.toast_habit_deleted)
- }
-
- @Test
- fun testOnDetach() {
- screen.onDettached()
- verify(commandRunner).removeListener(screen)
- }
-
- @Test
- fun testOnResult_bugReport() {
- screen.onResult(REQUEST_SETTINGS, RESULT_BUG_REPORT, null)
- verify(behavior).onSendBugReport()
- }
-
- @Test
- fun testOnResult_exportCSV() {
- screen.onResult(REQUEST_SETTINGS, RESULT_EXPORT_CSV, null)
- verify(behavior).onExportCSV()
- }
-
- @Test
- fun testOnResult_importData() {
- screen.onResult(REQUEST_SETTINGS, RESULT_IMPORT_DATA, null)
- testShowImportScreen()
- }
-
- @Test
- @Throws(Exception::class)
- fun testShowAboutScreen() {
- `when`(intentFactory.startAboutActivity(activity)).thenReturn(intent)
- screen.showAboutScreen()
- verify(activity).startActivity(eq(intent))
- }
-
- @Test
- fun testShowColorPicker() {
- val picker = mock(ColorPickerDialog::class.java)
- `when`(colorPickerDialogFactory.create(999)).thenReturn(picker)
- val callback = mock(OnColorPickedCallback::class.java)
-
- screen.showColorPicker(999, callback)
-
- verify(activity).showDialog(eq(picker), any())
- verify(picker).setListener(callback)
- }
-
- @Test
- fun testShowDeleteConfirmationScreen() {
- val callback = mock(OnConfirmedCallback::class.java)
- val dialog = mock(ConfirmDeleteDialog::class.java)
- `when`(confirmDeleteDialogFactory.create(callback)).thenReturn(dialog)
-
- screen.showDeleteConfirmationScreen(callback)
-
- verify(activity).showDialog(dialog)
- }
-
- @Test
- fun testShowEditHabitScreen() {
- val dialog = mock(EditHabitDialog::class.java)
- `when`(editHabitDialogFactory.edit(habit)).thenReturn(dialog)
- screen.showEditHabitsScreen(listOf(habit))
- verify(activity).showDialog(eq(dialog), any())
- }
-
- @Test
- fun testShowFAQScreen() {
- `when`(intentFactory.viewFAQ(activity)).thenReturn(intent)
- screen.showFAQScreen()
- verify(activity).startActivity(intent)
- }
-
- @Test
- fun testShowHabitScreen() {
- `when`(intentFactory.startShowHabitActivity(activity, habit))
- .thenReturn(intent)
- screen.showHabitScreen(habit)
- verify(activity).startActivity(intent)
- }
-
- @Test
- fun testShowImportScreen() {
- `when`(intentFactory.openDocument()).thenReturn(intent)
- screen.showImportScreen()
- verify(activity).startActivityForResult(intent, REQUEST_OPEN_DOCUMENT)
- }
-
- @Test
- fun testShowIntroScreen() {
- `when`(intentFactory.startIntroActivity(activity)).thenReturn(intent)
- screen.showIntroScreen()
- verify(activity).startActivity(intent)
- }
-
- @Test
- fun testShowSettingsScreen() {
- `when`(intentFactory.startSettingsActivity(activity)).thenReturn(intent)
- screen.showSettingsScreen()
- verify(activity).startActivityForResult(eq(intent), anyInt())
- }
-}
\ No newline at end of file
diff --git a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt b/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt
deleted file mode 100644
index 4dec267d0..000000000
--- a/android/uhabits-android/src/test/java/org/isoron/uhabits/activities/habits/list/controllers/HabitCardListControllerTest.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2017 Álinson Santos Xavier
- *
- * 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 .
- */
-
-package org.isoron.uhabits.activities.habits.list.controllers
-
-import dagger.*
-import org.isoron.uhabits.*
-import org.isoron.uhabits.activities.habits.list.*
-import org.isoron.uhabits.activities.habits.list.views.*
-import org.isoron.uhabits.core.models.*
-import org.isoron.uhabits.core.ui.screens.habits.list.*
-import org.junit.*
-import org.mockito.*
-import org.mockito.Mockito.*
-import java.util.*
-
-class HabitCardListControllerTest : BaseAndroidJVMTest() {
- private val habits = LinkedList()
- private lateinit var controller: HabitCardListController
-
- @Mock lateinit var adapter: HabitCardListAdapter
- @Mock lateinit var behavior: ListHabitsBehavior
- @Mock lateinit var selectionMenu: ListHabitsSelectionMenu
-
- @Before
- override fun setUp() {
- super.setUp()
- `when`(adapter.observable).thenReturn(ModelObservable())
- controller = HabitCardListController(adapter,
- behavior,
- Lazy { selectionMenu })
-
- repeat(10) { habits.add(fixtures.createEmptyHabit()) }
- for(i in 0..9) `when`(adapter.getItem(i)).thenReturn(habits[i])
-
- }
-
- @Test
- fun testClick_withSelection() {
- controller.onItemLongClick(0)
- verify(adapter).toggleSelection(0)
- verify(selectionMenu).onSelectionStart()
- reset(adapter, selectionMenu)
-
- controller.onItemClick(1)
- verify(adapter).toggleSelection(1)
- verify(selectionMenu).onSelectionChange()
- reset(adapter, selectionMenu)
-
- controller.onItemClick(1)
- verify(adapter).toggleSelection(1)
- verify(selectionMenu).onSelectionChange()
- reset(adapter, selectionMenu)
-
- doReturn(true).`when`(adapter).isSelectionEmpty
- controller.onItemClick(0)
- verify(adapter).toggleSelection(0)
- verify(selectionMenu).onSelectionFinish()
- }
-
- @Test
- fun testClick_withoutSelection() {
- controller.onItemClick(0)
- verify(behavior).onClickHabit(habits[0])
- }
-
- @Test
- fun testDragAndDrop_withSelection() {
- controller.onItemLongClick(0)
- verify(adapter).toggleSelection(0)
- verify(selectionMenu).onSelectionStart()
-
- controller.startDrag(1)
- verify(selectionMenu).onSelectionChange()
- verify(adapter).toggleSelection(1)
-
- controller.drop(1, 3)
- verify(behavior).onReorderHabit(habits[1], habits[3])
- verify(selectionMenu).onSelectionFinish()
- verify(adapter).performReorder(1, 3)
- }
-
- @Test
- fun testDragAndDrop_withoutSelection_distinctPlace() {
- controller.startDrag(0)
- verify(selectionMenu).onSelectionStart()
- verify(adapter).toggleSelection(0)
-
- controller.drop(0, 3)
- verify(behavior).onReorderHabit(habits[0], habits[3])
- verify(selectionMenu).onSelectionFinish()
- verify(adapter).performReorder(0, 3)
- verify(adapter).clearSelection()
- }
-
- @Test
- fun testLongClick_withSelection() {
- controller.onItemLongClick(0)
- verify(adapter).toggleSelection(0)
- verify(selectionMenu).onSelectionStart()
-
- controller.onItemLongClick(1)
- verify(adapter).toggleSelection(1)
- verify(selectionMenu).onSelectionChange()
- }
-}
\ No newline at end of file