Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4e6cd53 authored by mitulsheth's avatar mitulsheth
Browse files

feat: Murena Workspace Login and Places Sync

parent 4083693d
Loading
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -64,10 +64,10 @@ android {
    compileSdk = 36

    defaultConfig {
        applicationId = "foundation.e.maps"
        applicationId = "foundation.e.map"
        minSdk = 26
        targetSdk = 36
        versionCode = System.getenv("VERSION_CODE")?.toIntOrNull() ?: 1
        versionCode = System.getenv("VERSION_CODE")?.toIntOrNull() ?: 2
        versionName = System.getenv("VERSION_NAME") ?: "debug"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -100,6 +100,12 @@ android {
            keyAlias = System.getenv("KEY_ALIAS")
            keyPassword = System.getenv("KEY_PASSWORD")
        }
        create("platform") {
            storeFile = file("${rootDir.path}/keystore/platform.jks")
            storePassword = "platform"
            keyAlias = "platform"
            keyPassword = "platform"
        }
    }

    buildTypes {
@@ -117,6 +123,7 @@ android {
            resValue("string", "default_api_key", stadiaKey.orEmpty())
        }
        debug {
            signingConfig = signingConfigs["platform"] as ApkSigningConfig
            applicationIdSuffix = ".debug"
            manifestPlaceholders["icon"] = "@mipmap/ic_launcher_debug"
            manifestPlaceholders["round_icon"] = "@mipmap/ic_launcher_round_debug"
@@ -239,6 +246,7 @@ dependencies {
    implementation(libs.kotlinx.coroutines.android)
    implementation(libs.room.runtime)
    implementation(libs.room.ktx)
    implementation(libs.work.runtime.ktx)
    ksp(libs.room.compiler)
    implementation(libs.androidx.navigation.compose)
    implementation(libs.gson)
+1 −1
Original line number Diff line number Diff line
@@ -35,6 +35,6 @@ class ExampleInstrumentedTest {
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("earth.maps.cardinal", appContext.packageName)
        assertEquals("foundation.e.map.debug", appContext.packageName)
    }
}
 No newline at end of file
+136 −0
Original line number Diff line number Diff line
/*
 *     Cardinal Maps
 *     Copyright (C) 2026 Cardinal Maps Authors
 *
 *     This program 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.
 *
 *     This program 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 <https://www.gnu.org/licenses/>.
 */

package earth.maps.cardinal.ui.sync

import android.content.Context
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import earth.maps.cardinal.R
import earth.maps.cardinal.ui.theme.AppTheme
import java.util.Locale
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MurenaSyncWelcomeScreenTest {

    @get:Rule
    val composeTestRule = createComposeRule()

    private lateinit var actions: MutableList<MurenaSyncAction>
    private val context: Context
        get() = InstrumentationRegistry.getInstrumentation().targetContext
    private val robot by lazy { MurenaSyncWelcomeRobot(composeTestRule, context) }

    @Before
    fun setup() {
        actions = mutableListOf()
    }

    @Test
    fun welcomeScreen_displaysMurenaSyncChoice() {
        robot
            .setContent(onAction = actions::add)
            .assertWelcomeContent()
    }

    @Test
    fun chooseAccountButton_dispatchesChooseAccountAction() {
        robot
            .setContent(onAction = actions::add)
            .clickChooseAccount()

        composeTestRule.runOnIdle {
            assertEquals(listOf(MurenaSyncAction.OnChooseAccountClick), actions)
        }
    }

    @Test
    fun storeLocallyButton_dispatchesUseLocalMapsAction() {
        robot
            .setContent(onAction = actions::add)
            .clickStoreLocally()

        composeTestRule.runOnIdle {
            assertEquals(listOf(MurenaSyncAction.OnUseLocalMapsClick), actions)
        }
    }
}

private class MurenaSyncWelcomeRobot(
    private val composeTestRule: ComposeContentTestRule,
    private val context: Context
) {
    fun setContent(
        state: MurenaSyncState = MurenaSyncState(),
        onAction: (MurenaSyncAction) -> Unit
    ) = apply {
        composeTestRule.setContent {
            AppTheme {
                MurenaSyncWelcomeScreen(
                    state = state,
                    snackBarHostState = remember { SnackbarHostState() },
                    onAction = onAction
                )
            }
        }
    }

    fun assertWelcomeContent() = apply {
        composeTestRule.onNodeWithText(text(R.string.murena_sync_welcome_title))
            .assertIsDisplayed()
        composeTestRule.onNodeWithText(text(R.string.murena_sync_welcome_message))
            .assertIsDisplayed()
        composeTestRule.onNodeWithText(uppercaseText(R.string.murena_sync_choose_account))
            .performScrollTo()
            .assertIsDisplayed()
        composeTestRule.onNodeWithText(uppercaseText(R.string.murena_sync_use_local_maps))
            .performScrollTo()
            .assertIsDisplayed()
    }

    fun clickChooseAccount() = apply {
        composeTestRule.onNodeWithText(uppercaseText(R.string.murena_sync_choose_account))
            .performScrollTo()
            .performClick()
    }

    fun clickStoreLocally() = apply {
        composeTestRule.onNodeWithText(uppercaseText(R.string.murena_sync_use_local_maps))
            .performScrollTo()
            .performClick()
    }

    private fun text(id: Int): String = context.getString(id)

    private fun uppercaseText(id: Int): String {
        return text(id).uppercase(Locale.getDefault())
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@@ -50,6 +52,12 @@
            android:name="com.stadiamaps.ferrostar.core.service.FerrostarForegroundService"
            android:foregroundServiceType="location" />

        <activity
            android:name=".data.sync.MurenaAuthTokenActivity"
            android:excludeFromRecents="true"
            android:exported="false"
            android:theme="@style/Theme.CardinalMaps" />

        <activity
            android:name=".MainActivity"
            android:exported="true"
+2 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@
      "maxzoom": 6
    }
  },
  "sprite": "https://maps.earth/tileserver/styles/basic/sprite",
  "glyphs": "https://maps.earth/tileserver/fonts/{fontstack}/{range}.pbf",
  "sprite": "https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite",
  "glyphs": "https://tiles.openstreetmap.us/fonts/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "background",
Loading