summaryrefslogtreecommitdiff
path: root/android-app/app/src/androidTest/kotlin/org/terst/nav/MainActivitySmokeTest.kt
blob: fecd9ccc4650ce87302299fced74639d493567c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package org.terst.nav

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/**
 * Smoke tests: verify the main UI surfaces launch and respond correctly.
 * Run without GPS permission — LocationService is not started.
 *
 * Locally:  ./gradlew connectedDebugAndroidTest
 * CI:       smoke-test job via android-emulator-runner
 */
@RunWith(AndroidJUnit4::class)
class MainActivitySmokeTest {

    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Before
    fun setup() {
        NavApplication.isTesting = true
    }

    // ── Launch ─────────────────────────────────────────────────────────────

    @Test
    fun mainActivity_launches_withoutCrash() {
        activityRule.scenario.onActivity { activity ->
            assert(!activity.isFinishing) { "MainActivity finished immediately after launch" }
        }
    }

    // ── Bottom nav ─────────────────────────────────────────────────────────

    @Test
    fun bottomNav_allFourTabs_areDisplayed() {
        onView(withText("Map")).check(matches(isDisplayed()))
        onView(withText("Instruments")).check(matches(isDisplayed()))
        onView(withText("Log")).check(matches(isDisplayed()))
        onView(withText("Safety")).check(matches(isDisplayed()))
    }

    @Test
    fun bottomNav_safetyTab_showsSafetyDashboard() {
        onView(withText("Safety")).perform(click())
        onView(withText("Safety Dashboard")).check(matches(isDisplayed()))
        onView(withText("ACTIVATE MOB")).check(matches(isDisplayed()))
        onView(withText("ANCHOR WATCH")).check(matches(isDisplayed()))
    }

    @Test
    fun bottomNav_logTab_showsVoiceLogUi() {
        onView(withText("Log")).perform(click())
        onView(withContentDescription("Start voice recognition")).check(matches(isDisplayed()))
    }

    @Test
    fun bottomNav_instrumentsTab_isSelectable() {
        onView(withText("Instruments")).perform(click())
        onView(withId(R.id.instrument_bottom_sheet)).check(matches(isDisplayed()))
    }

    @Test
    fun bottomNav_mapTab_returnsFromOverlay() {
        onView(withText("Safety")).perform(click())
        onView(withText("Map")).perform(click())
        onView(withId(R.id.mapView)).check(matches(isDisplayed()))
    }

    // ── Persistent FABs ────────────────────────────────────────────────────

    @Test
    fun fabMob_isAlwaysVisible() {
        onView(withContentDescription("Man Overboard")).check(matches(isDisplayed()))
    }

    @Test
    fun fabMob_remainsVisibleOnSafetyTab() {
        onView(withText("Safety")).perform(click())
        onView(withContentDescription("Man Overboard")).check(matches(isDisplayed()))
    }

    // ── Track recording ────────────────────────────────────────────────────

    @Test
    fun fabRecordTrack_isDisplayedWithRecordDescription() {
        onView(withContentDescription("Record Track")).check(matches(isDisplayed()))
    }

    @Test
    fun fabRecordTrack_togglesToStopRecording_onFirstClick() {
        onView(withContentDescription("Record Track")).perform(click())
        onView(withContentDescription("Stop Recording")).check(matches(isDisplayed()))
    }

    @Test
    fun fabRecordTrack_togglesBackToRecord_onSecondClick() {
        onView(withContentDescription("Record Track")).perform(click())
        onView(withContentDescription("Stop Recording")).perform(click())
        onView(withContentDescription("Record Track")).check(matches(isDisplayed()))
    }
}