fix(rust): say who is online is withheld, never that nobody is #49
@@ -70,10 +70,20 @@ data class RustServerDto(
|
|||||||
val stale: Boolean = false,
|
val stale: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** `GET /public/rust/servers/{id}/events` — the killfeed and everything else public. */
|
/**
|
||||||
|
* `GET /public/rust/servers/{id}/events` — the killfeed and everything else public.
|
||||||
|
*
|
||||||
|
* **Nothing names who is online by default** (org lead, 2026-09-22). Below the
|
||||||
|
* operator's presence audience — staff unless widened — the server withholds
|
||||||
|
* every item that says a named player was on (joins, deaths, chat, tallies) and
|
||||||
|
* says so with [presenceHidden]; [presenceAudience] is who CAN see them. The
|
||||||
|
* screen says it, so a thin feed reads as withheld rather than as a quiet server.
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RustEventListDto(
|
data class RustEventListDto(
|
||||||
val events: List<RustEventDto> = emptyList(),
|
val events: List<RustEventDto> = emptyList(),
|
||||||
|
val presenceHidden: Boolean = false,
|
||||||
|
val presenceAudience: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,10 +181,20 @@ data class RustWipeDto(
|
|||||||
val lastSeen: String? = null,
|
val lastSeen: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** `GET /public/rust/servers/{id}/online` — who is on right now. */
|
/**
|
||||||
|
* `GET /public/rust/servers/{id}/online` — who is on right now.
|
||||||
|
*
|
||||||
|
* Below the operator's presence audience the names are withheld: [hidden] is
|
||||||
|
* true, [players] is empty and [count] is still the real number — a count names
|
||||||
|
* nobody, and it is already on the server line. An empty list with [hidden] set
|
||||||
|
* must never render as "nobody is on".
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RustOnlineDto(
|
data class RustOnlineDto(
|
||||||
val players: List<RustPresenceDto> = emptyList(),
|
val players: List<RustPresenceDto> = emptyList(),
|
||||||
|
val hidden: Boolean = false,
|
||||||
|
val count: Int = 0,
|
||||||
|
val audience: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import com.runicgateway.app.core.result.ApiResult
|
|||||||
import com.runicgateway.app.core.result.map
|
import com.runicgateway.app.core.result.map
|
||||||
import com.runicgateway.app.core.result.safeApiCall
|
import com.runicgateway.app.core.result.safeApiCall
|
||||||
import com.runicgateway.app.data.api.RustApi
|
import com.runicgateway.app.data.api.RustApi
|
||||||
import com.runicgateway.app.data.api.dto.RustEventDto
|
import com.runicgateway.app.data.api.dto.RustEventListDto
|
||||||
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
||||||
import com.runicgateway.app.data.api.dto.RustPresenceDto
|
import com.runicgateway.app.data.api.dto.RustOnlineDto
|
||||||
import com.runicgateway.app.data.api.dto.RustServerDto
|
import com.runicgateway.app.data.api.dto.RustServerDto
|
||||||
import com.runicgateway.app.data.api.dto.RustWipeDto
|
import com.runicgateway.app.data.api.dto.RustWipeDto
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -50,14 +50,14 @@ class RustRepository @Inject constructor(
|
|||||||
kinds: List<String> = emptyList(),
|
kinds: List<String> = emptyList(),
|
||||||
wipe: String? = null,
|
wipe: String? = null,
|
||||||
limit: Int? = null,
|
limit: Int? = null,
|
||||||
): ApiResult<List<RustEventDto>> = safeApiCall {
|
): ApiResult<RustEventListDto> = safeApiCall {
|
||||||
api.getEvents(
|
api.getEvents(
|
||||||
id = id,
|
id = id,
|
||||||
kind = kinds.takeIf { it.isNotEmpty() }?.joinToString(","),
|
kind = kinds.takeIf { it.isNotEmpty() }?.joinToString(","),
|
||||||
wipe = wipe?.takeIf { it.isNotBlank() },
|
wipe = wipe?.takeIf { it.isNotBlank() },
|
||||||
limit = limit,
|
limit = limit,
|
||||||
)
|
)
|
||||||
}.map { it.events }
|
}
|
||||||
|
|
||||||
/** The leaderboard: per wipe when [wipe] is given, all-time otherwise. */
|
/** The leaderboard: per wipe when [wipe] is given, all-time otherwise. */
|
||||||
suspend fun leaderboard(
|
suspend fun leaderboard(
|
||||||
@@ -78,7 +78,12 @@ class RustRepository @Inject constructor(
|
|||||||
suspend fun wipes(id: String): ApiResult<List<RustWipeDto>> =
|
suspend fun wipes(id: String): ApiResult<List<RustWipeDto>> =
|
||||||
safeApiCall { api.getWipes(id) }.map { it.wipes }
|
safeApiCall { api.getWipes(id) }.map { it.wipes }
|
||||||
|
|
||||||
/** The presence board. Rows survive an unreachable server, by design. */
|
/**
|
||||||
suspend fun online(id: String): ApiResult<List<RustPresenceDto>> =
|
* The presence board. Rows survive an unreachable server, by design.
|
||||||
safeApiCall { api.getOnline(id) }.map { it.players }
|
*
|
||||||
|
* Answered whole rather than as its rows: `hidden` and `count` are what let
|
||||||
|
* the screen tell "withheld from you" from "nobody is on".
|
||||||
|
*/
|
||||||
|
suspend fun online(id: String): ApiResult<RustOnlineDto> =
|
||||||
|
safeApiCall { api.getOnline(id) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
@@ -33,8 +34,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.runicgateway.app.R
|
import com.runicgateway.app.R
|
||||||
import com.runicgateway.app.data.api.dto.RustEventDto
|
import com.runicgateway.app.data.api.dto.RustEventDto
|
||||||
|
import com.runicgateway.app.data.api.dto.RustEventListDto
|
||||||
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
||||||
import com.runicgateway.app.data.api.dto.RustPresenceDto
|
import com.runicgateway.app.data.api.dto.RustOnlineDto
|
||||||
import com.runicgateway.app.data.api.dto.RustServerDto
|
import com.runicgateway.app.data.api.dto.RustServerDto
|
||||||
import com.runicgateway.app.data.api.dto.RustWipeDto
|
import com.runicgateway.app.data.api.dto.RustWipeDto
|
||||||
import com.runicgateway.app.ui.ErrorKind
|
import com.runicgateway.app.ui.ErrorKind
|
||||||
@@ -252,7 +254,7 @@ private fun WipeFilter(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun FeedPanel(
|
private fun FeedPanel(
|
||||||
feed: Polled<List<RustEventDto>>,
|
feed: Polled<RustEventListDto>,
|
||||||
filterId: String,
|
filterId: String,
|
||||||
onFilter: (String) -> Unit,
|
onFilter: (String) -> Unit,
|
||||||
onRetry: () -> Unit,
|
onRetry: () -> Unit,
|
||||||
@@ -275,7 +277,25 @@ private fun FeedPanel(
|
|||||||
when (val s = feed.state) {
|
when (val s = feed.state) {
|
||||||
is UiState.Loading -> LoadingView()
|
is UiState.Loading -> LoadingView()
|
||||||
is UiState.Error -> ErrorView(s.kind, onRetry = onRetry)
|
is UiState.Error -> ErrorView(s.kind, onRetry = onRetry)
|
||||||
is UiState.Success -> if (s.data.isEmpty()) {
|
is UiState.Success -> {
|
||||||
|
// Said once, above the rows, so a thin feed reads as withheld
|
||||||
|
// rather than as a quiet server (org lead: nothing names who is
|
||||||
|
// online by default).
|
||||||
|
if (s.data.presenceHidden) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
if (s.data.presenceAudience == "signed_in") {
|
||||||
|
R.string.rust_feed_presence_hidden_signin
|
||||||
|
} else {
|
||||||
|
R.string.rust_feed_presence_hidden_staff
|
||||||
|
},
|
||||||
|
),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (s.data.events.isEmpty()) {
|
||||||
EmptyView(stringResource(R.string.rust_feed_empty))
|
EmptyView(stringResource(R.string.rust_feed_empty))
|
||||||
} else {
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
@@ -285,7 +305,8 @@ private fun FeedPanel(
|
|||||||
if (feed.refreshFailed) {
|
if (feed.refreshFailed) {
|
||||||
item { RefreshFailedLine() }
|
item { RefreshFailedLine() }
|
||||||
}
|
}
|
||||||
items(s.data, key = { it.id }) { FeedRow(it) }
|
items(s.data.events, key = { it.id }) { FeedRow(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,14 +465,29 @@ private fun LeaderboardPanel(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun OnlinePanel(
|
private fun OnlinePanel(
|
||||||
online: Polled<List<RustPresenceDto>>,
|
online: Polled<RustOnlineDto>,
|
||||||
serverOnline: Boolean,
|
serverOnline: Boolean,
|
||||||
onRetry: () -> Unit,
|
onRetry: () -> Unit,
|
||||||
) {
|
) {
|
||||||
when (val s = online.state) {
|
when (val s = online.state) {
|
||||||
is UiState.Loading -> LoadingView()
|
is UiState.Loading -> LoadingView()
|
||||||
is UiState.Error -> ErrorView(s.kind, onRetry = onRetry)
|
is UiState.Error -> ErrorView(s.kind, onRetry = onRetry)
|
||||||
is UiState.Success -> if (s.data.isEmpty()) {
|
// Withheld is not empty. Below the operator's audience the server sends
|
||||||
|
// the count and no names, and an empty list rendered as "nobody is on"
|
||||||
|
// would be a false statement about a full server.
|
||||||
|
is UiState.Success -> if (s.data.hidden) {
|
||||||
|
val count = s.data.count
|
||||||
|
EmptyView(
|
||||||
|
pluralStringResource(R.plurals.rust_online_hidden_count, count, count) + "\n" +
|
||||||
|
stringResource(
|
||||||
|
when (s.data.audience) {
|
||||||
|
"signed_in" -> R.string.rust_online_hidden_signin
|
||||||
|
"public" -> R.string.rust_online_hidden_public
|
||||||
|
else -> R.string.rust_online_hidden_staff
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else if (s.data.players.isEmpty()) {
|
||||||
EmptyView(
|
EmptyView(
|
||||||
stringResource(
|
stringResource(
|
||||||
if (serverOnline) R.string.rust_nobody_on else R.string.rust_presence_offline,
|
if (serverOnline) R.string.rust_nobody_on else R.string.rust_presence_offline,
|
||||||
@@ -479,7 +515,7 @@ private fun OnlinePanel(
|
|||||||
if (online.refreshFailed) {
|
if (online.refreshFailed) {
|
||||||
item { RefreshFailedLine() }
|
item { RefreshFailedLine() }
|
||||||
}
|
}
|
||||||
items(s.data, key = { it.steamId }) { player ->
|
items(s.data.players, key = { it.steamId }) { player ->
|
||||||
ShardCard(Modifier.fillMaxWidth()) {
|
ShardCard(Modifier.fillMaxWidth()) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.fillMaxWidth().padding(16.dp),
|
Modifier.fillMaxWidth().padding(16.dp),
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ package com.runicgateway.app.ui.rust
|
|||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.runicgateway.app.data.api.dto.RustEventDto
|
import com.runicgateway.app.data.api.dto.RustEventListDto
|
||||||
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
||||||
import com.runicgateway.app.data.api.dto.RustPresenceDto
|
import com.runicgateway.app.data.api.dto.RustOnlineDto
|
||||||
import com.runicgateway.app.data.api.dto.RustServerDto
|
import com.runicgateway.app.data.api.dto.RustServerDto
|
||||||
import com.runicgateway.app.data.api.dto.RustWipeDto
|
import com.runicgateway.app.data.api.dto.RustWipeDto
|
||||||
import com.runicgateway.app.data.repository.RustRepository
|
import com.runicgateway.app.data.repository.RustRepository
|
||||||
@@ -52,8 +52,10 @@ data class RustServerUi(
|
|||||||
val sort: String = RustSort.KILLS,
|
val sort: String = RustSort.KILLS,
|
||||||
/** The wipe every panel is filtered to. **Null is all time**, not "unknown". */
|
/** The wipe every panel is filtered to. **Null is all time**, not "unknown". */
|
||||||
val selectedWipe: String? = null,
|
val selectedWipe: String? = null,
|
||||||
val feed: Polled<List<RustEventDto>> = Polled(),
|
/** The whole answer, not its rows: `presenceHidden` is part of what it says. */
|
||||||
val online: Polled<List<RustPresenceDto>> = Polled(),
|
val feed: Polled<RustEventListDto> = Polled(),
|
||||||
|
/** Likewise — `hidden` and `count` are what tell "withheld" from "nobody". */
|
||||||
|
val online: Polled<RustOnlineDto> = Polled(),
|
||||||
val leaderboard: UiState<List<RustLeaderboardRowDto>> = UiState.Loading,
|
val leaderboard: UiState<List<RustLeaderboardRowDto>> = UiState.Loading,
|
||||||
val wipes: UiState<List<RustWipeDto>> = UiState.Loading,
|
val wipes: UiState<List<RustWipeDto>> = UiState.Loading,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -593,6 +593,17 @@
|
|||||||
<string name="rust_feed_empty">Nothing has happened on this server yet — or not during the wipe you are looking at.</string>
|
<string name="rust_feed_empty">Nothing has happened on this server yet — or not during the wipe you are looking at.</string>
|
||||||
<string name="rust_leaderboard_empty">Nobody has scored here yet.</string>
|
<string name="rust_leaderboard_empty">Nobody has scored here yet.</string>
|
||||||
<string name="rust_wipes_empty">This server has not reported a wipe yet.</string>
|
<string name="rust_wipes_empty">This server has not reported a wipe yet.</string>
|
||||||
|
<!-- Nothing names who is online by default (org lead, 2026-09-22). Below the
|
||||||
|
operator's audience the server sends a count and no names. -->
|
||||||
|
<plurals name="rust_online_hidden_count">
|
||||||
|
<item quantity="one">%1$d player online</item>
|
||||||
|
<item quantity="other">%1$d players online</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="rust_online_hidden_staff">Only this site’s staff can see who they are.</string>
|
||||||
|
<string name="rust_online_hidden_signin">Sign in to see who they are.</string>
|
||||||
|
<string name="rust_online_hidden_public">This site is not showing who they are right now.</string>
|
||||||
|
<string name="rust_feed_presence_hidden_staff">Joins, deaths and chat are not shown. Only this site’s staff can see what players did.</string>
|
||||||
|
<string name="rust_feed_presence_hidden_signin">Joins, deaths and chat are not shown. Sign in to see what players did.</string>
|
||||||
<string name="rust_nobody_on">The server is up and the island is empty. Somebody has to be first.</string>
|
<string name="rust_nobody_on">The server is up and the island is empty. Somebody has to be first.</string>
|
||||||
<string name="rust_presence_offline">Presence is the one thing on this page that cannot be answered from the record — it is who is connected now, and nothing is.</string>
|
<string name="rust_presence_offline">Presence is the one thing on this page that cannot be answered from the record — it is who is connected now, and nothing is.</string>
|
||||||
<string name="rust_presence_live">On the server right now.</string>
|
<string name="rust_presence_live">On the server right now.</string>
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
package com.runicgateway.app.data.api.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertNull
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nothing names who is online by default (org lead, 2026-09-22). These are the
|
||||||
|
* answers module-rust's public routes give below and inside the operator's
|
||||||
|
* presence audience, copied from a live walk against the module — and the old
|
||||||
|
* shape, from a core running a module that predates the flag.
|
||||||
|
*/
|
||||||
|
class RustPresenceDtoTest {
|
||||||
|
|
||||||
|
private val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
explicitNulls = false
|
||||||
|
coerceInputValues = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun withheldOnlineCarriesTheCountAndNoNames() {
|
||||||
|
val dto = json.decodeFromString<RustOnlineDto>(
|
||||||
|
"""{"players":[],"hidden":true,"count":2,"audience":"staff"}""",
|
||||||
|
)
|
||||||
|
assertTrue(dto.hidden)
|
||||||
|
assertEquals(2, dto.count)
|
||||||
|
assertEquals("staff", dto.audience)
|
||||||
|
assertTrue(dto.players.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun visibleOnlineNamesThePlayers() {
|
||||||
|
val dto = json.decodeFromString<RustOnlineDto>(
|
||||||
|
"""{"players":[{"steamId":"76561198000000002","name":"Builder Bea","sleeping":false,
|
||||||
|
"connectedAt":"2026-09-23T05:02:30.000Z"}],"hidden":false,"count":1,"audience":"staff"}""",
|
||||||
|
)
|
||||||
|
assertFalse(dto.hidden)
|
||||||
|
assertEquals("Builder Bea", dto.players.single().name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun anOlderModuleWithoutTheFlagReadsAsVisible() {
|
||||||
|
val dto = json.decodeFromString<RustOnlineDto>("""{"players":[]}""")
|
||||||
|
assertFalse(dto.hidden)
|
||||||
|
assertNull(dto.audience)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun aWithheldFeedSaysSo() {
|
||||||
|
val dto = json.decodeFromString<RustEventListDto>(
|
||||||
|
"""{"events":[{"id":11,"kind":"server.wipe","t":1789500000000,"wipeId":"w-20260920T000000Z",
|
||||||
|
"steamId":null,"frame":{}}],"presenceHidden":true,"presenceAudience":"signed_in"}""",
|
||||||
|
)
|
||||||
|
assertTrue(dto.presenceHidden)
|
||||||
|
assertEquals("signed_in", dto.presenceAudience)
|
||||||
|
assertEquals("server.wipe", dto.events.single().kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
package com.runicgateway.app.ui.rust
|
package com.runicgateway.app.ui.rust
|
||||||
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import com.runicgateway.app.data.api.dto.RustEventListDto
|
||||||
import com.runicgateway.app.data.api.dto.RustLeaderboardDto
|
import com.runicgateway.app.data.api.dto.RustLeaderboardDto
|
||||||
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
import com.runicgateway.app.data.api.dto.RustLeaderboardRowDto
|
||||||
import com.runicgateway.app.data.api.dto.RustOnlineDto
|
import com.runicgateway.app.data.api.dto.RustOnlineDto
|
||||||
@@ -100,6 +101,35 @@ class RustServerViewModelTest {
|
|||||||
assertEquals(onlineBefore + 1, api.onlineCalls)
|
assertEquals(onlineBefore + 1, api.onlineCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `withheld names arrive as withheld, with the count, never as an empty list`() {
|
||||||
|
// Nothing names who is online by default (org lead, 2026-09-22). The
|
||||||
|
// screen's whole job with this answer is to say "12 online" rather than
|
||||||
|
// "nobody is on", so the state must carry `hidden` and `count` intact.
|
||||||
|
api.online = RustOnlineDto(players = emptyList(), hidden = true, count = 12, audience = "staff")
|
||||||
|
val vm = viewModel()
|
||||||
|
|
||||||
|
vm.selectTab(RustTab.ONLINE)
|
||||||
|
|
||||||
|
val state = vm.state.value.online.state
|
||||||
|
assertTrue(state is UiState.Success)
|
||||||
|
val answer = (state as UiState.Success).data
|
||||||
|
assertTrue(answer.hidden)
|
||||||
|
assertEquals(12, answer.count)
|
||||||
|
assertEquals("staff", answer.audience)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `a feed with its players withheld says so in the state`() {
|
||||||
|
api.events = RustEventListDto(events = emptyList(), presenceHidden = true, presenceAudience = "signed_in")
|
||||||
|
val vm = viewModel()
|
||||||
|
|
||||||
|
val state = vm.state.value.feed.state
|
||||||
|
assertTrue(state is UiState.Success)
|
||||||
|
assertTrue((state as UiState.Success).data.presenceHidden)
|
||||||
|
assertEquals("signed_in", state.data.presenceAudience)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `a poll on a still panel asks for nothing but the server line`() {
|
fun `a poll on a still panel asks for nothing but the server line`() {
|
||||||
api.wipes = RustWipeListDto(listOf(RustWipeDto(wipeId = "w1")))
|
api.wipes = RustWipeListDto(listOf(RustWipeDto(wipeId = "w1")))
|
||||||
|
|||||||
Reference in New Issue
Block a user