Convert org.isoron.uhabits.acceptance

pull/709/head
Quentin Hibon 5 years ago
parent ac6df47818
commit 25b25acc94

@ -1,56 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance;
import androidx.test.filters.*;
import androidx.test.runner.*;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.isoron.uhabits.*;
import org.junit.*;
import org.junit.runner.*;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class AboutTest extends BaseUserInterfaceTest
{
@Test
public void shouldDisplayAboutScreen() {
launchApp();
clickMenu(ABOUT);
verifyDisplaysText("Loop Habit Tracker");
verifyDisplaysText("Rate this app on Google Play");
verifyDisplaysText("Developers");
verifyDisplaysText("Translators");
}
@Test
public void shouldDisplayAboutScreenFromSettings() {
launchApp();
clickMenu(SETTINGS);
clickText("About");
verifyDisplaysText("Translators");
}
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu
import org.isoron.uhabits.acceptance.steps.WidgetSteps.clickText
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@LargeTest
class AboutTest : BaseUserInterfaceTest() {
@Test
fun shouldDisplayAboutScreen() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.ABOUT)
verifyDisplaysText("Loop Habit Tracker")
verifyDisplaysText("Rate this app on Google Play")
verifyDisplaysText("Developers")
verifyDisplaysText("Translators")
}
@Test
fun shouldDisplayAboutScreenFromSettings() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.SETTINGS)
clickText("About")
verifyDisplaysText("Translators")
}
}

@ -27,6 +27,7 @@ import org.isoron.uhabits.acceptance.steps.CommonSteps.longClickText
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDoesNotDisplayText import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDoesNotDisplayText
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps import org.isoron.uhabits.acceptance.steps.ListHabitsSteps
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu
import org.isoron.uhabits.acceptance.steps.clearBackupFolder import org.isoron.uhabits.acceptance.steps.clearBackupFolder
import org.isoron.uhabits.acceptance.steps.clearDownloadFolder import org.isoron.uhabits.acceptance.steps.clearDownloadFolder
import org.isoron.uhabits.acceptance.steps.copyBackupToDownloadFolder import org.isoron.uhabits.acceptance.steps.copyBackupToDownloadFolder
@ -45,7 +46,7 @@ class BackupTest : BaseUserInterfaceTest() {
copyBackupToDownloadFolder() copyBackupToDownloadFolder()
longClickText("Wake up early") longClickText("Wake up early")
ListHabitsSteps.clickMenu(ListHabitsSteps.MenuItem.DELETE) clickMenu(ListHabitsSteps.MenuItem.DELETE)
clickText("Yes") clickText("Yes")
verifyDoesNotDisplayText("Wake up early") verifyDoesNotDisplayText("Wake up early")

@ -1,200 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance;
import androidx.test.filters.*;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.isoron.uhabits.*;
import org.junit.*;
import org.junit.runner.*;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.*;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
import static org.isoron.uhabits.acceptance.steps.EditHabitSteps.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class HabitsTest extends BaseUserInterfaceTest
{
@Test
public void shouldCreateHabit() throws Exception {
shouldCreateHabit("this is a test description");
}
@Test
public void shouldCreateHabitBlankDescription() throws Exception {
shouldCreateHabit("");
}
private void shouldCreateHabit(String description) throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
clickMenu(ADD);
verifyShowsScreen(SELECT_HABIT_TYPE);
clickText("Yes or No");
verifyShowsScreen(EDIT_HABIT);
String testName = "Hello world";
typeName(testName);
typeQuestion("Did you say hello to the world today?");
typeDescription(description);
pickFrequency();
pickColor(5);
clickSave();
verifyShowsScreen(LIST_HABITS);
verifyDisplaysText(testName);
}
@Test
public void shouldShowHabitStatistics() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
clickText("Track time");
verifyShowsScreen(SHOW_HABIT);
verifyDisplayGraphs();
}
@Test
public void shouldDeleteHabit() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
longClickText("Track time");
clickMenu(DELETE);
clickText("Yes");
verifyDoesNotDisplayText("Track time");
}
@Test
public void shouldEditHabit() throws Exception {
shouldEditHabit("this is a test description");
}
@Test
public void shouldEditHabitBlankDescription() throws Exception {
shouldEditHabit("");
}
private void shouldEditHabit(String description) throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
longClickText("Track time");
clickMenu(EDIT);
verifyShowsScreen(EDIT_HABIT);
typeName("Take a walk");
typeQuestion("Did you take a walk today?");
typeDescription(description);
clickSave();
verifyShowsScreen(LIST_HABITS);
verifyDisplaysTextInSequence("Wake up early", "Take a walk", "Meditate");
verifyDoesNotDisplayText("Track time");
}
@Test
public void shouldEditHabit_fromStatisticsScreen() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
clickText("Track time");
verifyShowsScreen(SHOW_HABIT);
clickMenu(EDIT);
verifyShowsScreen(EDIT_HABIT);
typeName("Take a walk");
typeQuestion("Did you take a walk today?");
pickColor(10);
clickSave();
verifyShowsScreen(SHOW_HABIT);
verifyDisplaysText("Take a walk");
pressBack();
verifyShowsScreen(LIST_HABITS);
verifyDisplaysText("Take a walk");
verifyDoesNotDisplayText("Track time");
}
@Test
public void shouldArchiveAndUnarchiveHabits() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
longClickText("Track time");
clickMenu(ARCHIVE);
verifyDoesNotDisplayText("Track time");
clickMenu(TOGGLE_ARCHIVED);
verifyDisplaysText("Track time");
longClickText("Track time");
clickMenu(UNARCHIVE);
clickMenu(TOGGLE_ARCHIVED);
verifyDisplaysText("Track time");
}
@Test
public void shouldToggleCheckmarksAndUpdateScore() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
longPressCheckmarks("Wake up early", 2);
clickText("Wake up early");
verifyShowsScreen(SHOW_HABIT);
verifyDisplaysText("10%");
}
@Test
public void shouldHideCompleted() throws Exception
{
launchApp();
verifyShowsScreen(LIST_HABITS);
verifyDisplaysText("Track time");
verifyDisplaysText("Wake up early");
clickMenu(TOGGLE_COMPLETED);
verifyDoesNotDisplayText("Track time");
verifyDisplaysText("Wake up early");
longPressCheckmarks("Wake up early", 1);
verifyDoesNotDisplayText("Wake up early");
clickMenu(TOGGLE_COMPLETED);
verifyDisplaysText("Track time");
verifyDisplaysText("Wake up early");
}
}

@ -0,0 +1,193 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.acceptance.steps.CommonSteps
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
import org.isoron.uhabits.acceptance.steps.CommonSteps.longClickText
import org.isoron.uhabits.acceptance.steps.CommonSteps.pressBack
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplayGraphs
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysTextInSequence
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDoesNotDisplayText
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyShowsScreen
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.clickSave
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.pickColor
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.pickFrequency
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.typeDescription
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.typeName
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.typeQuestion
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.longPressCheckmarks
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@LargeTest
class HabitsTest : BaseUserInterfaceTest() {
@Test
@Throws(Exception::class)
fun shouldCreateHabit() {
shouldCreateHabit("this is a test description")
}
@Test
@Throws(Exception::class)
fun shouldCreateHabitBlankDescription() {
shouldCreateHabit("")
}
@Throws(Exception::class)
private fun shouldCreateHabit(description: String) {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
clickMenu(ListHabitsSteps.MenuItem.ADD)
verifyShowsScreen(CommonSteps.Screen.SELECT_HABIT_TYPE)
clickText("Yes or No")
verifyShowsScreen(CommonSteps.Screen.EDIT_HABIT)
val testName = "Hello world"
typeName(testName)
typeQuestion("Did you say hello to the world today?")
typeDescription(description)
pickFrequency()
pickColor(5)
clickSave()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
verifyDisplaysText(testName)
}
@Test
@Throws(Exception::class)
fun shouldShowHabitStatistics() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
clickText("Track time")
verifyShowsScreen(CommonSteps.Screen.SHOW_HABIT)
verifyDisplayGraphs()
}
@Test
@Throws(Exception::class)
fun shouldDeleteHabit() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
longClickText("Track time")
clickMenu(ListHabitsSteps.MenuItem.DELETE)
clickText("Yes")
verifyDoesNotDisplayText("Track time")
}
@Test
@Throws(Exception::class)
fun shouldEditHabit() {
shouldEditHabit("this is a test description")
}
@Test
@Throws(Exception::class)
fun shouldEditHabitBlankDescription() {
shouldEditHabit("")
}
@Throws(Exception::class)
private fun shouldEditHabit(description: String) {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
longClickText("Track time")
clickMenu(ListHabitsSteps.MenuItem.EDIT)
verifyShowsScreen(CommonSteps.Screen.EDIT_HABIT)
typeName("Take a walk")
typeQuestion("Did you take a walk today?")
typeDescription(description)
clickSave()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
verifyDisplaysTextInSequence("Wake up early", "Take a walk", "Meditate")
verifyDoesNotDisplayText("Track time")
}
@Test
@Throws(Exception::class)
fun shouldEditHabit_fromStatisticsScreen() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
clickText("Track time")
verifyShowsScreen(CommonSteps.Screen.SHOW_HABIT)
clickMenu(ListHabitsSteps.MenuItem.EDIT)
verifyShowsScreen(CommonSteps.Screen.EDIT_HABIT)
typeName("Take a walk")
typeQuestion("Did you take a walk today?")
pickColor(10)
clickSave()
verifyShowsScreen(CommonSteps.Screen.SHOW_HABIT)
verifyDisplaysText("Take a walk")
pressBack()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
verifyDisplaysText("Take a walk")
verifyDoesNotDisplayText("Track time")
}
@Test
@Throws(Exception::class)
fun shouldArchiveAndUnarchiveHabits() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
longClickText("Track time")
clickMenu(ListHabitsSteps.MenuItem.ARCHIVE)
verifyDoesNotDisplayText("Track time")
clickMenu(ListHabitsSteps.MenuItem.TOGGLE_ARCHIVED)
verifyDisplaysText("Track time")
longClickText("Track time")
clickMenu(ListHabitsSteps.MenuItem.UNARCHIVE)
clickMenu(ListHabitsSteps.MenuItem.TOGGLE_ARCHIVED)
verifyDisplaysText("Track time")
}
@Test
@Throws(Exception::class)
fun shouldToggleCheckmarksAndUpdateScore() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
longPressCheckmarks("Wake up early", 2)
clickText("Wake up early")
verifyShowsScreen(CommonSteps.Screen.SHOW_HABIT)
verifyDisplaysText("10%")
}
@Test
@Throws(Exception::class)
fun shouldHideCompleted() {
launchApp()
verifyShowsScreen(CommonSteps.Screen.LIST_HABITS)
verifyDisplaysText("Track time")
verifyDisplaysText("Wake up early")
clickMenu(ListHabitsSteps.MenuItem.TOGGLE_COMPLETED)
verifyDoesNotDisplayText("Track time")
verifyDisplaysText("Wake up early")
longPressCheckmarks("Wake up early", 1)
verifyDoesNotDisplayText("Wake up early")
clickMenu(ListHabitsSteps.MenuItem.TOGGLE_COMPLETED)
verifyDisplaysText("Track time")
verifyDisplaysText("Wake up early")
}
}

@ -1,71 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance;
import androidx.test.filters.*;
import androidx.test.runner.*;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.isoron.uhabits.*;
import org.junit.*;
import org.junit.runner.*;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*;
import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class LinksTest extends BaseUserInterfaceTest
{
@Test
public void shouldLinkToSourceCode() throws Exception
{
launchApp();
clickMenu(ABOUT);
clickText("View source code at GitHub");
verifyOpensWebsite("github.com");
}
@Test
public void shouldLinkToTranslationWebsite() throws Exception
{
launchApp();
clickMenu(ABOUT);
clickText("Help translate this app");
verifyOpensWebsite("translate.loophabits.org");
}
@Test
public void shouldLinkToHelp() throws Exception {
launchApp();
clickMenu(HELP);
verifyOpensWebsite("github.com");
}
@Test
public void shouldLinkToHelpFromSettings() throws Exception {
launchApp();
clickMenu(SETTINGS);
clickText("Help & FAQ");
verifyOpensWebsite("github.com");
}
}

@ -0,0 +1,69 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyOpensWebsite
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu
import org.isoron.uhabits.acceptance.steps.WidgetSteps.clickText
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@LargeTest
class LinksTest : BaseUserInterfaceTest() {
@Test
@Throws(Exception::class)
fun shouldLinkToSourceCode() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.ABOUT)
clickText("View source code at GitHub")
verifyOpensWebsite("github.com")
}
@Test
@Throws(Exception::class)
fun shouldLinkToTranslationWebsite() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.ABOUT)
clickText("Help translate this app")
verifyOpensWebsite("translate.loophabits.org")
}
@Test
@Throws(Exception::class)
fun shouldLinkToHelp() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.HELP)
verifyOpensWebsite("github.com")
}
@Test
@Throws(Exception::class)
fun shouldLinkToHelpFromSettings() {
launchApp()
clickMenu(ListHabitsSteps.MenuItem.SETTINGS)
clickText("Help & FAQ")
verifyOpensWebsite("github.com")
}
}

@ -1,55 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance;
import androidx.test.filters.*;
import org.isoron.uhabits.*;
import org.junit.*;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
import static org.isoron.uhabits.acceptance.steps.WidgetSteps.*;
import static org.isoron.uhabits.acceptance.steps.WidgetSteps.clickText;
@LargeTest
public class WidgetTest extends BaseUserInterfaceTest
{
@Test
public void shouldCreateAndToggleCheckmarkWidget() throws Exception
{
dragCheckmarkWidgetToHomeScreen();
Thread.sleep(3000);
clickText("Wake up early");
clickText("Save");
verifyCheckmarkWidgetIsShown();
clickCheckmarkWidget();
launchApp();
clickText("Wake up early");
verifyDisplaysText("5%");
pressHome();
clickCheckmarkWidget();
launchApp();
clickText("Wake up early");
verifyDisplaysText("0%");
}
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance
import androidx.test.filters.LargeTest
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
import org.isoron.uhabits.acceptance.steps.CommonSteps.pressHome
import org.isoron.uhabits.acceptance.steps.CommonSteps.verifyDisplaysText
import org.isoron.uhabits.acceptance.steps.WidgetSteps.clickCheckmarkWidget
import org.isoron.uhabits.acceptance.steps.WidgetSteps.clickText
import org.isoron.uhabits.acceptance.steps.WidgetSteps.dragCheckmarkWidgetToHomeScreen
import org.isoron.uhabits.acceptance.steps.WidgetSteps.verifyCheckmarkWidgetIsShown
import org.junit.Test
@LargeTest
class WidgetTest : BaseUserInterfaceTest() {
@Test
@Throws(Exception::class)
fun shouldCreateAndToggleCheckmarkWidget() {
dragCheckmarkWidgetToHomeScreen()
Thread.sleep(3000)
clickText("Wake up early")
clickText("Save")
verifyCheckmarkWidgetIsShown()
clickCheckmarkWidget()
launchApp()
clickText("Wake up early")
verifyDisplaysText("5%")
pressHome()
clickCheckmarkWidget()
launchApp()
clickText("Wake up early")
verifyDisplaysText("0%")
}
}

@ -20,8 +20,8 @@
package org.isoron.uhabits.acceptance.steps package org.isoron.uhabits.acceptance.steps
import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.UiSelector
import org.isoron.uhabits.BaseUserInterfaceTest.device
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
import org.isoron.uhabits.acceptance.steps.CommonSteps.device
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.SETTINGS import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.SETTINGS
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu

@ -1,177 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps;
import android.view.*;
import androidx.annotation.*;
import androidx.recyclerview.widget.*;
import androidx.test.espresso.*;
import androidx.test.espresso.contrib.*;
import androidx.test.uiautomator.*;
import org.hamcrest.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.habits.list.*;
import static android.os.Build.VERSION.*;
import static androidx.test.espresso.Espresso.*;
import static androidx.test.espresso.action.ViewActions.*;
import static androidx.test.espresso.assertion.PositionAssertions.*;
import static androidx.test.espresso.assertion.ViewAssertions.*;
import static androidx.test.espresso.matcher.ViewMatchers.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
public class CommonSteps extends BaseUserInterfaceTest
{
public static void pressBack()
{
device.pressBack();
}
public static void clickText(String text)
{
scrollToText(text);
onView(withText(text)).perform(click());
}
public static void clickText(@StringRes int id)
{
onView(withText(id)).perform(click());
}
public static void launchApp()
{
startActivity(ListHabitsActivity.class);
assertTrue(
device.wait(Until.hasObject(By.pkg("org.isoron.uhabits")), 5000));
device.waitForIdle();
}
public static void longClickText(String text)
{
scrollToText(text);
onView(withText(text)).perform(longClick());
}
public static void pressHome()
{
device.pressHome();
device.waitForIdle();
}
public static void scrollToText(String text)
{
try
{
if (device
.findObject(new UiSelector().className(RecyclerView.class))
.exists())
{
onView(instanceOf(RecyclerView.class)).perform(
RecyclerViewActions.scrollTo(
hasDescendant(withText(text))));
}
else
{
onView(withText(text)).perform(scrollTo());
}
}
catch (PerformException e)
{
//ignored
}
}
public static void verifyDisplayGraphs()
{
verifyDisplaysView("HistoryCard");
verifyDisplaysView("ScoreCard");
}
public static void verifyDisplaysText(String text)
{
scrollToText(text);
onView(withText(text)).check(matches(isEnabled()));
}
public static void verifyDisplaysTextInSequence(String... text)
{
verifyDisplaysText(text[0]);
for(int i = 1; i < text.length; i++) {
verifyDisplaysText(text[i]);
onView(withText(text[i])).check(isCompletelyBelow(withText(text[i-1])));
}
}
private static void verifyDisplaysView(String className)
{
onView(withClassName(endsWith(className))).check(matches(isEnabled()));
}
public static void verifyDoesNotDisplayText(String text)
{
onView(withText(text)).check(doesNotExist());
}
public static void verifyOpensWebsite(String url) throws Exception
{
String browser_pkg = "org.chromium.webview_shell";
if(SDK_INT <= 23) {
browser_pkg = "com.android.browser";
}
assertTrue(device.wait(Until.hasObject(By.pkg(browser_pkg)), 5000));
device.waitForIdle();
assertTrue(device.findObject(new UiSelector().textContains(url)).exists());
}
public enum Screen
{
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
}
public static void verifyShowsScreen(Screen screen)
{
switch(screen)
{
case LIST_HABITS:
onView(withClassName(endsWith("ListHabitsRootView")))
.check(matches(isDisplayed()));
break;
case SHOW_HABIT:
onView(withId(R.id.subtitleCard)).check(matches(isDisplayed()));
break;
case EDIT_HABIT:
onView(withId(R.id.questionInput)).check(matches(isDisplayed()));
break;
case SELECT_HABIT_TYPE:
onView(withText(R.string.yes_or_no_example)).check(matches(isDisplayed()));
break;
default:
throw new IllegalStateException();
}
}
}

@ -0,0 +1,157 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps
import android.os.Build.VERSION
import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso
import androidx.test.espresso.PerformException
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.PositionAssertions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
import junit.framework.Assert.assertTrue
import org.hamcrest.CoreMatchers
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
object CommonSteps : BaseUserInterfaceTest() {
fun pressBack() {
device.pressBack()
}
fun clickText(text: String?) {
scrollToText(text)
Espresso.onView(ViewMatchers.withText(text)).perform(ViewActions.click())
}
fun clickText(@StringRes id: Int) {
Espresso.onView(ViewMatchers.withText(id)).perform(ViewActions.click())
}
fun launchApp() {
startActivity(ListHabitsActivity::class.java)
assertTrue(
device.wait(Until.hasObject(By.pkg("org.isoron.uhabits")), 5000)
)
device.waitForIdle()
}
fun longClickText(text: String?) {
scrollToText(text)
Espresso.onView(ViewMatchers.withText(text)).perform(ViewActions.longClick())
}
fun pressHome() {
device.pressHome()
device.waitForIdle()
}
fun scrollToText(text: String?) {
try {
if (device
.findObject(UiSelector().className(RecyclerView::class.java))
.exists()
) {
Espresso.onView(CoreMatchers.instanceOf(RecyclerView::class.java)).perform(
RecyclerViewActions.scrollTo<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText(text))
)
)
} else {
Espresso.onView(ViewMatchers.withText(text)).perform(ViewActions.scrollTo())
}
} catch (e: PerformException) {
// ignored
}
}
fun verifyDisplayGraphs() {
verifyDisplaysView("HistoryCard")
verifyDisplaysView("ScoreCard")
}
fun verifyDisplaysText(text: String?) {
scrollToText(text)
Espresso.onView(ViewMatchers.withText(text))
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
}
fun verifyDisplaysTextInSequence(vararg text: String?) {
verifyDisplaysText(text[0])
for (i in 1 until text.size) {
verifyDisplaysText(text[i])
Espresso.onView(ViewMatchers.withText(text[i])).check(
PositionAssertions.isCompletelyBelow(
ViewMatchers.withText(
text[i - 1]
)
)
)
}
}
private fun verifyDisplaysView(className: String) {
Espresso.onView(ViewMatchers.withClassName(CoreMatchers.endsWith(className)))
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
}
fun verifyDoesNotDisplayText(text: String?) {
Espresso.onView(ViewMatchers.withText(text)).check(ViewAssertions.doesNotExist())
}
@Throws(Exception::class)
fun verifyOpensWebsite(url: String?) {
var browserPkg = "org.chromium.webview_shell"
if (VERSION.SDK_INT <= 23) {
browserPkg = "com.android.browser"
}
assertTrue(device.wait(Until.hasObject(By.pkg(browserPkg)), 5000))
device.waitForIdle()
assertTrue(device.findObject(UiSelector().textContains(url)).exists())
}
fun verifyShowsScreen(screen: Screen?) {
when (screen) {
Screen.LIST_HABITS ->
Espresso.onView(ViewMatchers.withClassName(CoreMatchers.endsWith("ListHabitsRootView")))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
Screen.SHOW_HABIT ->
Espresso.onView(ViewMatchers.withId(R.id.subtitleCard))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
Screen.EDIT_HABIT ->
Espresso.onView(ViewMatchers.withId(R.id.questionInput))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
Screen.SELECT_HABIT_TYPE ->
Espresso.onView(ViewMatchers.withText(R.string.yes_or_no_example))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
else -> throw IllegalStateException()
}
}
enum class Screen {
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
}
}

@ -1,92 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps;
import androidx.test.uiautomator.*;
import org.isoron.uhabits.*;
import static androidx.test.espresso.Espresso.*;
import static androidx.test.espresso.action.ViewActions.*;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.matcher.ViewMatchers.*;
import static org.isoron.uhabits.BaseUserInterfaceTest.*;
public class EditHabitSteps
{
public static void clickSave()
{
onView(withId(R.id.buttonSave)).perform(click());
}
public static void pickFrequency()
{
onView(withId(R.id.boolean_frequency_picker)).perform(click());
onView(withText("SAVE")).perform(click());
}
public static void pickColor(int color)
{
onView(withId(R.id.colorButton)).perform(click());
device.findObject(By.descStartsWith(String.format("Color %d", color))).click();
}
public static void typeName(String name)
{
typeTextWithId(R.id.nameInput, name);
}
public static void typeQuestion(String name)
{
typeTextWithId(R.id.questionInput, name);
}
public static void typeDescription(String description)
{
typeTextWithId(R.id.notesInput, description);
}
public static void setReminder()
{
onView(withId(R.id.reminderTimePicker)).perform(click());
onView(withId(R.id.done_button)).perform(click());
}
public static void clickReminderDays()
{
onView(withId(R.id.reminderDatePicker)).perform(click());
}
public static void unselectAllDays()
{
onView(withText("Saturday")).perform(click());
onView(withText("Sunday")).perform(click());
onView(withText("Monday")).perform(click());
onView(withText("Tuesday")).perform(click());
onView(withText("Wednesday")).perform(click());
onView(withText("Thursday")).perform(click());
onView(withText("Friday")).perform(click());
}
private static void typeTextWithId(int id, String name)
{
onView(withId(id)).perform(clearText(), typeText(name), closeSoftKeyboard());
}
}

@ -0,0 +1,83 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps
import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.uiautomator.By
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.R
object EditHabitSteps {
fun clickSave() {
Espresso.onView(ViewMatchers.withId(R.id.buttonSave)).perform(ViewActions.click())
}
fun pickFrequency() {
Espresso.onView(ViewMatchers.withId(R.id.boolean_frequency_picker))
.perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("SAVE")).perform(ViewActions.click())
}
fun pickColor(color: Int) {
Espresso.onView(ViewMatchers.withId(R.id.colorButton)).perform(ViewActions.click())
BaseUserInterfaceTest.device.findObject(By.descStartsWith(String.format("Color %d", color)))
.click()
}
fun typeName(name: String) {
typeTextWithId(R.id.nameInput, name)
}
fun typeQuestion(name: String) {
typeTextWithId(R.id.questionInput, name)
}
fun typeDescription(description: String) {
typeTextWithId(R.id.notesInput, description)
}
fun setReminder() {
Espresso.onView(ViewMatchers.withId(R.id.reminderTimePicker)).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withId(R.id.done_button)).perform(ViewActions.click())
}
fun clickReminderDays() {
Espresso.onView(ViewMatchers.withId(R.id.reminderDatePicker)).perform(ViewActions.click())
}
fun unselectAllDays() {
Espresso.onView(ViewMatchers.withText("Saturday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Sunday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Monday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Tuesday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Wednesday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Thursday")).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText("Friday")).perform(ViewActions.click())
}
private fun typeTextWithId(id: Int, name: String) {
Espresso.onView(ViewMatchers.withId(id)).perform(
ViewActions.clearText(),
ViewActions.typeText(name),
ViewActions.closeSoftKeyboard()
)
}
}

@ -1,161 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps;
import androidx.test.espresso.*;
import android.view.*;
import org.hamcrest.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.habits.list.views.*;
import java.util.*;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.*;
import static org.isoron.uhabits.BaseUserInterfaceTest.device;
import static org.isoron.uhabits.acceptance.steps.CommonSteps.clickText;
public abstract class ListHabitsSteps
{
public static void clickMenu(MenuItem item)
{
switch (item)
{
case ABOUT:
clickTextInsideOverflowMenu(R.string.about);
break;
case HELP:
clickTextInsideOverflowMenu(R.string.help);
break;
case SETTINGS:
clickTextInsideOverflowMenu(R.string.settings);
break;
case ADD:
clickViewWithId(R.id.actionCreateHabit);
break;
case EDIT:
clickViewWithId(R.id.action_edit_habit);
break;
case DELETE:
clickTextInsideOverflowMenu(R.string.delete);
break;
case ARCHIVE:
clickTextInsideOverflowMenu(R.string.archive);
break;
case UNARCHIVE:
clickTextInsideOverflowMenu(R.string.unarchive);
break;
case TOGGLE_ARCHIVED:
clickViewWithId(R.id.action_filter);
clickText(R.string.hide_archived);
break;
case TOGGLE_COMPLETED:
clickViewWithId(R.id.action_filter);
clickText(R.string.hide_completed);
break;
}
}
private static void clickTextInsideOverflowMenu(int id) {
onView(allOf(withContentDescription("More options"), withParent(withParent(withClassName(endsWith("Toolbar")))))).perform(click());
onView(withText(id)).perform(click());
}
private static void clickViewWithId(int id)
{
onView(withId(id)).perform(click());
}
private static ViewAction longClickDescendantWithClass(Class cls, int count)
{
return new ViewAction()
{
@Override
public Matcher<View> getConstraints()
{
return isEnabled();
}
@Override
public String getDescription()
{
return "perform on children";
}
@Override
public void perform(UiController uiController, View view)
{
LinkedList<ViewGroup> stack = new LinkedList<>();
if (view instanceof ViewGroup) stack.push((ViewGroup) view);
int countRemaining = count;
while (!stack.isEmpty())
{
ViewGroup vg = stack.pop();
for (int i = 0; i < vg.getChildCount(); i++)
{
View v = vg.getChildAt(i);
if (v instanceof ViewGroup) stack.push((ViewGroup) v);
if (cls.isInstance(v) && countRemaining > 0)
{
v.performLongClick();
uiController.loopMainThreadUntilIdle();
countRemaining--;
}
}
}
}
};
}
public static void longPressCheckmarks(String habit, int count)
{
CommonSteps.scrollToText(habit);
onView(allOf(hasDescendant(withText(habit)),
withClassName(endsWith("HabitCardView")))).perform(
longClickDescendantWithClass(CheckmarkButtonView.class, count));
device.waitForIdle();
}
public enum MenuItem
{
ABOUT, HELP, SETTINGS, EDIT, DELETE, ARCHIVE, TOGGLE_ARCHIVED,
UNARCHIVE, TOGGLE_COMPLETED, ADD
}
}

@ -0,0 +1,123 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps
import android.view.View
import android.view.ViewGroup
import androidx.test.espresso.Espresso
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers
import org.hamcrest.CoreMatchers
import org.hamcrest.Matcher
import org.isoron.uhabits.BaseUserInterfaceTest
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.habits.list.views.CheckmarkButtonView
import java.util.LinkedList
object ListHabitsSteps {
fun clickMenu(item: MenuItem?) {
when (item) {
MenuItem.ABOUT -> clickTextInsideOverflowMenu(R.string.about)
MenuItem.HELP -> clickTextInsideOverflowMenu(R.string.help)
MenuItem.SETTINGS -> clickTextInsideOverflowMenu(R.string.settings)
MenuItem.ADD -> clickViewWithId(R.id.actionCreateHabit)
MenuItem.EDIT -> clickViewWithId(R.id.action_edit_habit)
MenuItem.DELETE -> clickTextInsideOverflowMenu(R.string.delete)
MenuItem.ARCHIVE -> clickTextInsideOverflowMenu(R.string.archive)
MenuItem.UNARCHIVE -> clickTextInsideOverflowMenu(R.string.unarchive)
MenuItem.TOGGLE_ARCHIVED -> {
clickViewWithId(R.id.action_filter)
CommonSteps.clickText(R.string.hide_archived)
}
MenuItem.TOGGLE_COMPLETED -> {
clickViewWithId(R.id.action_filter)
CommonSteps.clickText(R.string.hide_completed)
}
}
}
private fun clickTextInsideOverflowMenu(id: Int) {
Espresso.onView(
CoreMatchers.allOf(
ViewMatchers.withContentDescription("More options"),
ViewMatchers.withParent(
ViewMatchers.withParent(
ViewMatchers.withClassName(
CoreMatchers.endsWith("Toolbar")
)
)
)
)
).perform(ViewActions.click())
Espresso.onView(ViewMatchers.withText(id)).perform(ViewActions.click())
}
private fun clickViewWithId(id: Int) {
Espresso.onView(ViewMatchers.withId(id)).perform(ViewActions.click())
}
private fun longClickDescendantWithClass(cls: Class<*>, count: Int): ViewAction {
return object : ViewAction {
override fun getConstraints(): Matcher<View> {
return ViewMatchers.isEnabled()
}
override fun getDescription(): String {
return "perform on children"
}
override fun perform(uiController: UiController, view: View) {
val stack = LinkedList<ViewGroup>()
if (view is ViewGroup) stack.push(view)
var countRemaining = count
while (!stack.isEmpty()) {
val vg = stack.pop()
for (i in 0 until vg.childCount) {
val v = vg.getChildAt(i)
if (v is ViewGroup) stack.push(v)
if (cls.isInstance(v) && countRemaining > 0) {
v.performLongClick()
uiController.loopMainThreadUntilIdle()
countRemaining--
}
}
}
}
}
}
fun longPressCheckmarks(habit: String?, count: Int) {
CommonSteps.scrollToText(habit)
Espresso.onView(
CoreMatchers.allOf(
ViewMatchers.hasDescendant(ViewMatchers.withText(habit)),
ViewMatchers.withClassName(CoreMatchers.endsWith("HabitCardView"))
)
).perform(
longClickDescendantWithClass(CheckmarkButtonView::class.java, count)
)
BaseUserInterfaceTest.device.waitForIdle()
}
enum class MenuItem {
ABOUT, HELP, SETTINGS, EDIT, DELETE, ARCHIVE, TOGGLE_ARCHIVED, UNARCHIVE, TOGGLE_COMPLETED, ADD
}
}

@ -1,87 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps;
import androidx.test.uiautomator.*;
import static android.os.Build.VERSION.SDK_INT;
import static org.junit.Assert.*;
import static org.isoron.uhabits.BaseUserInterfaceTest.*;
public class WidgetSteps {
public static void clickCheckmarkWidget() throws Exception {
String view_id = "org.isoron.uhabits:id/imageView";
device.findObject(new UiSelector().resourceId(view_id)).click();
}
public static void clickText(String s) throws Exception {
UiObject object = device.findObject(new UiSelector().text(s));
if (!object.waitForExists(1000)) {
object = device.findObject(new UiSelector().text(s.toUpperCase()));
}
object.click();
}
public static void dragCheckmarkWidgetToHomeScreen() throws Exception {
openWidgetScreen();
dragWidgetToHomeScreen();
}
private static void dragWidgetToHomeScreen() throws Exception {
int height = device.getDisplayHeight();
int width = device.getDisplayWidth();
device.findObject(new UiSelector().text("Checkmark"))
.dragTo(width / 2, height / 2, 40);
}
private static void openWidgetScreen() throws Exception {
int h = device.getDisplayHeight();
int w = device.getDisplayWidth();
if (SDK_INT <= 21) {
device.pressHome();
device.waitForIdle();
device.findObject(new UiSelector().description("Apps")).click();
device.findObject(new UiSelector().description("Apps")).click();
device.findObject(new UiSelector().description("Widgets")).click();
} else {
String list_id = "com.android.launcher3:id/widgets_list_view";
device.pressHome();
device.waitForIdle();
device.drag(w / 2, h / 2, w / 2, h / 2, 8);
UiObject button = device.findObject(new UiSelector().text("WIDGETS"));
if(!button.waitForExists(1000)) {
button = device.findObject(new UiSelector().text("Widgets"));
}
button.click();
if (SDK_INT >= 28) {
new UiScrollable(new UiSelector().resourceId(list_id))
.scrollForward();
}
new UiScrollable(new UiSelector().resourceId(list_id))
.scrollIntoView(new UiSelector().text("Checkmark"));
}
}
public static void verifyCheckmarkWidgetIsShown() throws Exception {
String view_id = "org.isoron.uhabits:id/imageView";
assertTrue(device.findObject(new UiSelector().resourceId(view_id)).exists());
assertFalse(device.findObject(new UiSelector().textStartsWith("Habit deleted")).exists());
}
}

@ -0,0 +1,98 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.acceptance.steps
import android.os.Build.VERSION
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.isoron.uhabits.BaseUserInterfaceTest
object WidgetSteps {
@Throws(Exception::class)
fun clickCheckmarkWidget() {
val view_id = "org.isoron.uhabits:id/imageView"
BaseUserInterfaceTest.device.findObject(UiSelector().resourceId(view_id)).click()
}
@Throws(Exception::class)
fun clickText(s: String) {
var textObject = BaseUserInterfaceTest.device.findObject(UiSelector().text(s))
if (!textObject.waitForExists(1000)) {
textObject = BaseUserInterfaceTest.device.findObject(UiSelector().text(s.toUpperCase()))
}
textObject.click()
}
@Throws(Exception::class)
fun dragCheckmarkWidgetToHomeScreen() {
openWidgetScreen()
dragWidgetToHomeScreen()
}
@Throws(Exception::class)
private fun dragWidgetToHomeScreen() {
val height = BaseUserInterfaceTest.device.displayHeight
val width = BaseUserInterfaceTest.device.displayWidth
BaseUserInterfaceTest.device.findObject(UiSelector().text("Checkmark"))
.dragTo(width / 2, height / 2, 40)
}
@Throws(Exception::class)
private fun openWidgetScreen() {
val h = BaseUserInterfaceTest.device.displayHeight
val w = BaseUserInterfaceTest.device.displayWidth
if (VERSION.SDK_INT <= 21) {
BaseUserInterfaceTest.device.pressHome()
BaseUserInterfaceTest.device.waitForIdle()
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
BaseUserInterfaceTest.device.findObject(UiSelector().description("Widgets")).click()
} else {
val list_id = "com.android.launcher3:id/widgets_list_view"
BaseUserInterfaceTest.device.pressHome()
BaseUserInterfaceTest.device.waitForIdle()
BaseUserInterfaceTest.device.drag(w / 2, h / 2, w / 2, h / 2, 8)
var button = BaseUserInterfaceTest.device.findObject(UiSelector().text("WIDGETS"))
if (!button.waitForExists(1000)) {
button = BaseUserInterfaceTest.device.findObject(UiSelector().text("Widgets"))
}
button.click()
if (VERSION.SDK_INT >= 28) {
UiScrollable(UiSelector().resourceId(list_id))
.scrollForward()
}
UiScrollable(UiSelector().resourceId(list_id))
.scrollIntoView(UiSelector().text("Checkmark"))
}
}
@Throws(Exception::class)
fun verifyCheckmarkWidgetIsShown() {
val viewId = "org.isoron.uhabits:id/imageView"
assertTrue(
BaseUserInterfaceTest.device.findObject(UiSelector().resourceId(viewId)).exists()
)
assertFalse(
BaseUserInterfaceTest.device.findObject(UiSelector().textStartsWith("Habit deleted"))
.exists()
)
}
}

@ -1,163 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.core.test;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.models.sqlite.*;
import org.isoron.uhabits.core.utils.*;
import static org.isoron.uhabits.core.models.Entry.*;
public class HabitFixtures
{
public boolean NON_DAILY_HABIT_CHECKS[] = {
true, false, false, true, true, true, false, false, true, true
};
private final ModelFactory modelFactory;
private HabitList habitList;
public HabitFixtures(ModelFactory modelFactory, HabitList habitList)
{
this.modelFactory = modelFactory;
this.habitList = habitList;
}
public Habit createEmptyHabit()
{
Habit habit = modelFactory.buildHabit();
habit.setName("Meditate");
habit.setQuestion("Did you meditate this morning?");
habit.setColor(new PaletteColor(3));
habit.setFrequency(Frequency.DAILY);
saveIfSQLite(habit);
return habit;
}
public Habit createLongHabit()
{
Habit habit = createEmptyHabit();
habit.setFrequency(new Frequency(3, 7));
habit.setColor(new PaletteColor(4));
Timestamp today = DateUtils.getToday();
int marks[] = {0, 1, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 19, 20, 26, 27,
28, 50, 51, 52, 53, 54, 58, 60, 63, 65, 70, 71, 72, 73, 74, 75, 80,
81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120};
for (int mark : marks)
habit.getOriginalEntries().add(new Entry(today.minus(mark), YES_MANUAL));
habit.recompute();
return habit;
}
public Habit createNumericalHabit()
{
Habit habit = modelFactory.buildHabit();
habit.setType(Habit.NUMBER_HABIT);
habit.setName("Run");
habit.setQuestion("How many miles did you run today?");
habit.setUnit("miles");
habit.setTargetType(Habit.AT_LEAST);
habit.setTargetValue(2.0);
habit.setColor(new PaletteColor(1));
saveIfSQLite(habit);
Timestamp today = DateUtils.getToday();
int times[] = {0, 1, 3, 5, 7, 8, 9, 10};
int values[] = {100, 200, 300, 400, 500, 600, 700, 800};
for (int i = 0; i < times.length; i++)
{
Timestamp timestamp = today.minus(times[i]);
habit.getOriginalEntries().add(new Entry(timestamp, values[i]));
}
habit.recompute();
return habit;
}
public Habit createLongNumericalHabit(Timestamp reference)
{
Habit habit = modelFactory.buildHabit();
habit.setType(Habit.NUMBER_HABIT);
habit.setName("Walk");
habit.setQuestion("How many steps did you walk today?");
habit.setUnit("steps");
habit.setTargetType(Habit.AT_LEAST);
habit.setTargetValue(100);
habit.setColor(new PaletteColor(1));
saveIfSQLite(habit);
int times[] = {0, 5, 9, 15, 17, 21, 23, 27, 28, 35, 41, 45, 47, 53, 56, 62, 70, 73, 78,
83, 86, 94, 101, 106, 113, 114, 120, 126, 130, 133, 141, 143, 148, 151, 157, 164,
166, 171, 173, 176, 179, 183, 191, 259, 264, 268, 270, 275, 282, 284, 289, 295,
302, 306, 310, 315, 323, 325, 328, 335, 343, 349, 351, 353, 357, 359, 360, 367,
372, 376, 380, 385, 393, 400, 404, 412, 415, 418, 422, 425, 433, 437, 444, 449,
455, 460, 462, 465, 470, 471, 479, 481, 485, 489, 494, 495, 500, 501, 503, 507};
int values[] = {230, 306, 148, 281, 134, 285, 104, 158, 325, 236, 303, 210, 118, 124,
301, 201, 156, 376, 347, 367, 396, 134, 160, 381, 155, 354, 231, 134, 164, 354,
236, 398, 199, 221, 208, 397, 253, 276, 214, 341, 299, 221, 353, 250, 341, 168,
374, 205, 182, 217, 297, 321, 104, 237, 294, 110, 136, 229, 102, 271, 250, 294,
158, 319, 379, 126, 282, 155, 288, 159, 215, 247, 207, 226, 244, 158, 371, 219,
272, 228, 350, 153, 356, 279, 394, 202, 213, 214, 112, 248, 139, 245, 165, 256,
370, 187, 208, 231, 341, 312};
for (int i = 0; i < times.length; i++)
{
Timestamp timestamp = reference.minus(times[i]);
habit.getOriginalEntries().add(new Entry(timestamp, values[i]));
}
habit.recompute();
return habit;
}
public Habit createShortHabit()
{
Habit habit = modelFactory.buildHabit();
habit.setName("Wake up early");
habit.setQuestion("Did you wake up before 6am?");
habit.setFrequency(new Frequency(2, 3));
saveIfSQLite(habit);
Timestamp timestamp = DateUtils.getToday();
for (boolean c : NON_DAILY_HABIT_CHECKS)
{
int value = NO;
if (c) value = YES_MANUAL;
habit.getOriginalEntries().add(new Entry(timestamp, value));
timestamp = timestamp.minus(1);
}
habit.recompute();
return habit;
}
private void saveIfSQLite(Habit habit)
{
if (!(habit.getOriginalEntries() instanceof SQLiteEntryList)) return;
habitList.add(habit);
}
}

@ -0,0 +1,143 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.core.test
import org.isoron.uhabits.core.models.Entry
import org.isoron.uhabits.core.models.Frequency
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.ModelFactory
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.models.sqlite.SQLiteEntryList
import org.isoron.uhabits.core.utils.DateUtils.Companion.getToday
class HabitFixtures(private val modelFactory: ModelFactory, private val habitList: HabitList) {
var NON_DAILY_HABIT_CHECKS = booleanArrayOf(
true, false, false, true, true, true, false, false, true, true
)
fun createEmptyHabit(
name: String = "Meditate",
color: PaletteColor = PaletteColor(3),
position: Int = 0
): Habit {
val habit = modelFactory.buildHabit()
habit.name = name
habit.question = "Did you meditate this morning?"
habit.color = color
habit.position = position
habit.frequency = Frequency.DAILY
saveIfSQLite(habit)
return habit
}
fun createLongHabit(): Habit {
val habit = createEmptyHabit()
habit.frequency = Frequency(3, 7)
habit.color = PaletteColor(4)
val today = getToday()
val marks = intArrayOf(
0, 1, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 19, 20, 26, 27,
28, 50, 51, 52, 53, 54, 58, 60, 63, 65, 70, 71, 72, 73, 74, 75, 80,
81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120
)
for (mark in marks) habit.originalEntries.add(Entry(today.minus(mark), Entry.YES_MANUAL))
habit.recompute()
return habit
}
fun createNumericalHabit(): Habit {
val habit = modelFactory.buildHabit()
habit.type = Habit.NUMBER_HABIT
habit.name = "Run"
habit.question = "How many miles did you run today?"
habit.unit = "miles"
habit.targetType = Habit.AT_LEAST
habit.targetValue = 2.0
habit.color = PaletteColor(1)
saveIfSQLite(habit)
val today = getToday()
val times = intArrayOf(0, 1, 3, 5, 7, 8, 9, 10)
val values = intArrayOf(100, 200, 300, 400, 500, 600, 700, 800)
for (i in times.indices) {
val timestamp = today.minus(times[i])
habit.originalEntries.add(Entry(timestamp, values[i]))
}
habit.recompute()
return habit
}
fun createLongNumericalHabit(reference: Timestamp): Habit {
val habit = modelFactory.buildHabit()
habit.type = Habit.NUMBER_HABIT
habit.name = "Walk"
habit.question = "How many steps did you walk today?"
habit.unit = "steps"
habit.targetType = Habit.AT_LEAST
habit.targetValue = 100.0
habit.color = PaletteColor(1)
saveIfSQLite(habit)
val times = intArrayOf(
0, 5, 9, 15, 17, 21, 23, 27, 28, 35, 41, 45, 47, 53, 56, 62, 70, 73, 78,
83, 86, 94, 101, 106, 113, 114, 120, 126, 130, 133, 141, 143, 148, 151, 157, 164,
166, 171, 173, 176, 179, 183, 191, 259, 264, 268, 270, 275, 282, 284, 289, 295,
302, 306, 310, 315, 323, 325, 328, 335, 343, 349, 351, 353, 357, 359, 360, 367,
372, 376, 380, 385, 393, 400, 404, 412, 415, 418, 422, 425, 433, 437, 444, 449,
455, 460, 462, 465, 470, 471, 479, 481, 485, 489, 494, 495, 500, 501, 503, 507
)
val values = intArrayOf(
230, 306, 148, 281, 134, 285, 104, 158, 325, 236, 303, 210, 118, 124,
301, 201, 156, 376, 347, 367, 396, 134, 160, 381, 155, 354, 231, 134, 164, 354,
236, 398, 199, 221, 208, 397, 253, 276, 214, 341, 299, 221, 353, 250, 341, 168,
374, 205, 182, 217, 297, 321, 104, 237, 294, 110, 136, 229, 102, 271, 250, 294,
158, 319, 379, 126, 282, 155, 288, 159, 215, 247, 207, 226, 244, 158, 371, 219,
272, 228, 350, 153, 356, 279, 394, 202, 213, 214, 112, 248, 139, 245, 165, 256,
370, 187, 208, 231, 341, 312
)
for (i in times.indices) {
val timestamp = reference.minus(times[i])
habit.originalEntries.add(Entry(timestamp, values[i]))
}
habit.recompute()
return habit
}
fun createShortHabit(): Habit {
val habit = modelFactory.buildHabit()
habit.name = "Wake up early"
habit.question = "Did you wake up before 6am?"
habit.frequency = Frequency(2, 3)
saveIfSQLite(habit)
var timestamp = getToday()
for (c in NON_DAILY_HABIT_CHECKS) {
var value = Entry.NO
if (c) value = Entry.YES_MANUAL
habit.originalEntries.add(Entry(timestamp, value))
timestamp = timestamp.minus(1)
}
habit.recompute()
return habit
}
private fun saveIfSQLite(habit: Habit) {
if (habit.originalEntries !is SQLiteEntryList) return
habitList.add(habit)
}
}
Loading…
Cancel
Save