Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new test pipeline #27

Merged
merged 7 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Run tests

on:
pull_request:
branches:
- 'master'
push:
branches:
- 'master'
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest
# TODO: Use strategy.matrix and always run on lowest and highest supported API
steps:
- name: checkout
uses: actions/checkout@v4

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Load Gradle from cache (or install + cache)
uses: gradle/actions/setup-gradle@v3

- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-29
save-always: true

- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
disable-spellchecker: true
profile: Nexus 6
script: echo "Generated AVD snapshot for caching."

- name: Save AVD to cache
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-29

- name: Add Dropbox API credentials
shell: bash
run: |
echo "dropbox.refresh_token = \"${{ secrets.DROPBOX_REFRESH_TOKEN }}\"" >> app.properties
echo "dropbox.app_key = \"${{ secrets.DROPBOX_APP_KEY }}\"" >> app.properties

- name: Run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
arch: x86_64
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
disable-spellchecker: true
profile: Nexus 6
# Tests should use the build which includes Dropbox code.
script: ./gradlew connectedPremiumDebugAndroidTest --no-watch-fs

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-api-29
path: |
**/build/reports/*
**/build/outputs/*/connected/*
4 changes: 2 additions & 2 deletions app/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-sdk
android:minSdkVersion="18"
android:minSdkVersion="21"
tools:overrideLibrary="android_libs.ub_uiautomator" />
</manifest>
</manifest>
4 changes: 2 additions & 2 deletions app/src/androidTest/java/com/orgzly/android/OrgzlyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ public void setUp() throws Exception {
// localStorage.cleanup();

setupPreferences();

dataRepository.clearDatabase();
}

@After
public void tearDown() throws Exception {
restorePreferences();

database.close();

dataRepository.clearDatabase();
}

private void setupPreferences() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
import static com.orgzly.android.espresso.util.EspressoUtils.onItemInAgenda;
import static com.orgzly.android.espresso.util.EspressoUtils.onNotesInAgenda;
import static com.orgzly.android.espresso.util.EspressoUtils.recyclerViewItemCount;
import static com.orgzly.android.espresso.util.EspressoUtils.searchForText;
import static com.orgzly.android.espresso.util.EspressoUtils.searchForTextCloseKeyboard;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;

import android.content.pm.ActivityInfo;
import android.os.SystemClock;
import android.widget.DatePicker;
import android.widget.TextView;

Expand All @@ -35,10 +35,13 @@
import com.orgzly.android.ui.main.MainActivity;

import org.joda.time.DateTime;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;

public class AgendaFragmentTest extends OrgzlyTest {
private ActivityScenario<MainActivity> scenario;

private ActivityScenario<MainActivity> defaultSetUp() {
testUtils.setupBook("book-one",
"First book used for testing\n" +
Expand All @@ -63,10 +66,17 @@ private ActivityScenario<MainActivity> defaultSetUp() {
return ActivityScenario.launch(MainActivity.class);
}

@After
@Override
public void tearDown() throws Exception {
super.tearDown();
scenario.close();
}

@Test
public void testAgendaSavedSearch() {
defaultSetUp();
searchForText(".it.done ad.7");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done ad.7");
/*
* 1 Overdue
* 1 Note B
Expand All @@ -81,17 +91,17 @@ public void testAgendaSavedSearch() {

@Test
public void testWithNoBook() {
ActivityScenario.launch(MainActivity.class);
searchForText(".it.done (s.7d or d.7d) ad.7");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard(".it.done (s.7d or d.7d) ad.7");
onNotesInAgenda().check(matches(recyclerViewItemCount(7)));
searchForText(".it.done (s.7d or d.7d) ad.3");
searchForTextCloseKeyboard(".it.done (s.7d or d.7d) ad.3");
onNotesInAgenda().check(matches(recyclerViewItemCount(3)));
}

@Test
public void testDayAgenda() {
defaultSetUp();
searchForText(".it.done (s.7d or d.7d) ad.1");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done (s.7d or d.7d) ad.1");
onNotesInAgenda().check(matches(recyclerViewItemCount(7)));
onItemInAgenda(0, R.id.item_agenda_divider_text).check(matches(allOf(withText(R.string.overdue), isDisplayed())));
onItemInAgenda(1, R.id.item_head_title_view).check(matches(allOf(withText(endsWith("Note B")), isDisplayed())));
Expand All @@ -110,15 +120,15 @@ public void testAgendaRangeEvent() {
"* Event A.\n" +
"<" + start.toString() + ">--<" + end.toString() + ">\n");

ActivityScenario.launch(MainActivity.class);
searchForText("ad.5");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard("ad.5");
onNotesInAgenda().check(matches(recyclerViewItemCount(10)));
}

@Test
public void testOneTimeTaskMarkedDone() {
defaultSetUp();
searchForText(".it.done ad.7");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done ad.7");
/*
* 1 Overdue
* 1 Note B <- Mark as done
Expand All @@ -135,17 +145,17 @@ public void testOneTimeTaskMarkedDone() {

@Test
public void testRepeaterTaskMarkedDone() {
defaultSetUp();
searchForText(".it.done ad.7");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done ad.7");
onItemInAgenda(2).perform(longClick());
onView(withId(R.id.toggle_state)).perform(click());
onNotesInAgenda().check(matches(recyclerViewItemCount(23)));
}

@Test
public void testRangeTaskMarkedDone() {
defaultSetUp();
searchForText(".it.done ad.7");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done ad.7");
onItemInAgenda(3).perform(longClick());
onView(withId(R.id.toggle_state)).perform(click());
onNotesInAgenda().check(matches(recyclerViewItemCount(17)));
Expand All @@ -154,9 +164,8 @@ public void testRangeTaskMarkedDone() {
@Test
public void testMoveTaskWithRepeaterToTomorrow() {
DateTime tomorrow = DateTime.now().withTimeAtStartOfDay().plusDays(1);

defaultSetUp();
searchForText(".it.done ad.7");
scenario = defaultSetUp();
searchForTextCloseKeyboard(".it.done ad.7");
onItemInAgenda(2).perform(longClick());
onView(withId(R.id.schedule)).perform(click());
onView(withId(R.id.date_picker_button)).perform(click());
Expand All @@ -172,9 +181,9 @@ public void testMoveTaskWithRepeaterToTomorrow() {

@Test
public void testPersistedSpinnerSelection() {
ActivityScenario<MainActivity> scenario = defaultSetUp();
scenario = defaultSetUp();

searchForText(".it.done ad.7");
searchForTextCloseKeyboard(".it.done ad.7");
onNotesInAgenda().check(matches(recyclerViewItemCount(25)));

scenario.onActivity(activity ->
Expand All @@ -190,9 +199,9 @@ public void testDeselectRemovedNoteInAgenda() {
"* TODO Note A\nSCHEDULED: <2018-01-01 +1d>\n" +
"* TODO Note B\nSCHEDULED: <2018-01-01 .+1d>\n");

ActivityScenario.launch(MainActivity.class);
scenario = ActivityScenario.launch(MainActivity.class);

searchForText("i.todo ad.3");
searchForTextCloseKeyboard("i.todo ad.3");

onNotesInAgenda().check(matches(recyclerViewItemCount(12)));

Expand All @@ -217,9 +226,9 @@ public void testDeselectRemovedNoteInAgenda() {
@Test
public void testPreselectedStateOfSelectedNote() {
testUtils.setupBook("notebook", "* TODO Note A\nSCHEDULED: <2018-01-01 +1d>");
ActivityScenario.launch(MainActivity.class);
scenario = ActivityScenario.launch(MainActivity.class);

searchForText("ad.3");
searchForTextCloseKeyboard("ad.3");

onItemInAgenda(1).perform(longClick());
onView(withId(R.id.state)).perform(click());
Expand All @@ -230,8 +239,8 @@ public void testPreselectedStateOfSelectedNote() {
@Test
public void testSwipeDivider() {
testUtils.setupBook("notebook", "* TODO Note A\nSCHEDULED: <2018-01-01 +1d>");
ActivityScenario.launch(MainActivity.class);
searchForText("ad.3");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard("ad.3");
onItemInAgenda(0).perform(swipeLeft());
onItemInAgenda(2).perform(swipeLeft());
}
Expand All @@ -240,9 +249,9 @@ public void testSwipeDivider() {
@Test
public void testOpenCorrectNote() {
testUtils.setupBook("notebook", "* TODO Note A\nSCHEDULED: <2018-01-01 +1d>");
ActivityScenario.launch(MainActivity.class);
scenario = ActivityScenario.launch(MainActivity.class);

searchForText("ad.3");
searchForTextCloseKeyboard("ad.3");

onItemInAgenda(1).perform(click());

Expand All @@ -255,9 +264,9 @@ public void testChangeStateWithReverseNoteClick() {
testUtils.setupBook("book-1","* DONE Note A");
testUtils.setupBook("book-2","* TODO Note B\nSCHEDULED: <2014-01-01>\n* TODO Note C\nSCHEDULED: <2014-01-02>\n");
AppPreferences.isReverseNoteClickAction(context, false);
ActivityScenario.launch(MainActivity.class);
scenario = ActivityScenario.launch(MainActivity.class);

searchForText(".it.done ad.7");
searchForTextCloseKeyboard(".it.done ad.7");
onItemInAgenda(1).perform(longClick());
onView(withId(R.id.state)).perform(click());
onView(withText("NEXT")).perform(click());
Expand All @@ -266,26 +275,27 @@ public void testChangeStateWithReverseNoteClick() {
@Test
public void testInactiveScheduled() {
testUtils.setupBook("notebook-1", "* Note A\nSCHEDULED: [2020-07-01]\nDEADLINE: <2020-07-01>");
ActivityScenario.launch(MainActivity.class);
searchForText("ad.1");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard("ad.1");
// Overdue, note (deadline), today
SystemClock.sleep(1000);
onNotesInAgenda().check(matches(recyclerViewItemCount(3)));
}

@Test
public void testInactiveDeadline() {
testUtils.setupBook("notebook-1", "* Note A\nDEADLINE: [2020-07-01]\nSCHEDULED: <2020-07-01>");
ActivityScenario.launch(MainActivity.class);
searchForText("ad.1");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard("ad.1");
// Overdue, note (scheduled), today
onNotesInAgenda().check(matches(recyclerViewItemCount(3)));
}

@Test
public void testInactiveScheduledAndDeadline() {
testUtils.setupBook("notebook-1", "* Note A\nSCHEDULED: [2020-07-01]\nDEADLINE: [2020-07-01]");
ActivityScenario.launch(MainActivity.class);
searchForText("ad.1");
scenario = ActivityScenario.launch(MainActivity.class);
searchForTextCloseKeyboard("ad.1");
// Today
onNotesInAgenda().check(matches(recyclerViewItemCount(1)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import static androidx.test.espresso.Espresso.pressBack;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.longClick;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
Expand Down Expand Up @@ -37,6 +36,7 @@
import com.orgzly.android.prefs.AppPreferences;
import com.orgzly.android.ui.main.MainActivity;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
Expand Down Expand Up @@ -107,6 +107,13 @@ public void setUp() throws Exception {
onView(allOf(withText("book-name"), isDisplayed())).perform(click());
}

@After
@Override
public void tearDown() throws Exception {
super.tearDown();
scenario.close();
}

@Test
public void testNoteExists() {
onNoteInBook(7, R.id.item_head_title_view).check(matches(withText("Note #7.")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import android.app.Activity;
import android.app.Instrumentation.ActivityResult;
import android.content.Intent;
import android.os.SystemClock;

import androidx.documentfile.provider.DocumentFile;
import androidx.test.core.app.ActivityScenario;
Expand Down Expand Up @@ -111,6 +112,7 @@ public void testReturnToNonExistentBookByPressingBack() {
onView(withId(R.id.fab)).check(matches(not(isDisplayed())));
pressBack();

SystemClock.sleep(500);
onView(withId(R.id.fragment_books_view_flipper)).check(matches(isDisplayed()));
onView(allOf(withText("book-2"), withId(R.id.item_book_title))).perform(click());
onView(allOf(withText(R.string.book_does_not_exist_anymore), isDisplayed())).check(doesNotExist());
Expand Down
Loading
Loading