refactor: remove device Pairing feature entirely (issue #645) (#650)

* refactor: remove device Pairing feature entirely (issue #645)

- Delete Pairing.kt model + pairing API endpoints (get/approve/revoke/clear)
- Delete PairingScreen/PairingViewModel + PairingCodeEntryScreen/ViewModel
- Remove NavKeys, ScreenRegistry drawer entry, Navigation.kt entry + Landing pairing button
- Remove pairing string resources (en + ko); keep connect_* config-parse strings
- Keep Telegram onboarding pairing_id flow (separate concept, per issue)
- Fix related doc comments + remaining test reference

* test: fix racy CONNECTED read in gated-mode WS test (issue #635 test)

testGatedMode_attemptsTicketFetchWithoutBareCookie asserted CONNECTED
immediately after the server-side onOpen latch fired, racing the client
handshake (WsListenerImpl sets CONNECTED on receipt of the 101). Await the
real status transition via connectionStatus.first{==CONNECTED} like the
other connect tests do. No product behavior changed.

---------

Co-authored-by: M57 <Hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-07-20 23:23:29 +03:00
1 parent e44a53366b
commit a62bc7e16c
19 files changed
+13 -892

No files matched your search

@@ -46,7 +46,6 @@ class BottomNavigationSelectionTest {
SkillsScreen,
LandingScreen,
AuthLoginScreen,
PairingCodeEntryScreen,
)
for (screen in others) {
assertEquals(
@@ -542,6 +542,15 @@ class HermesWsClientTest {
"Gated WS ticket fetch should be attempted even without a bare cookie",
connectLatch.await(5, TimeUnit.SECONDS),
)
// The server-side onOpen latch fires a hair before the client receives
// the 101 handshake and WsListenerImpl sets CONNECTED — await the real
// status transition (as every other connect test does) instead of a
// racy read that can observe CONNECTING.
runBlocking {
withTimeout(5000) {
HermesWsClient.connectionStatus.first { it == ConnectionStatus.CONNECTED }
}
}
assertEquals(ConnectionStatus.CONNECTED, HermesWsClient.connectionStatus.value)
ticketServer.shutdown()
@@ -1,55 +0,0 @@
package com.m57.hermescontrol.ui.pairing
import android.app.Application
import android.util.Log
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
class PairingCodeEntryViewModelTest {
private val mockApp: Application = mockk(relaxed = true)
@Before
fun setup() {
mockkStatic(Log::class)
every { Log.d(any(), any()) } returns 0
every { Log.e(any(), any(), any()) } returns 0
}
@After
fun teardown() {
unmockkAll()
}
@Test
fun testOnManualCodeChange_updatesStateAndClearsError() {
val viewModel = PairingCodeEntryViewModel(mockApp)
// Force an error to verify it gets cleared
// using onCodeDetected with invalid input to set the error
viewModel.onCodeDetected("invalid-code")
assertEquals(true, viewModel.uiState.value.errorMessage != null)
viewModel.onManualCodeChange("new-code")
val state = viewModel.uiState.value
assertEquals("new-code", state.manualCode)
assertNull(state.errorMessage)
}
@Test
fun testOnManualCodeChange_trimsInput() {
val viewModel = PairingCodeEntryViewModel(mockApp)
viewModel.onManualCodeChange(" trimmed-code \n")
val state = viewModel.uiState.value
assertEquals("trimmed-code", state.manualCode)
}
}