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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package social.grain
import org.junit.Assert.assertEquals
import org.junit.Test
import social.grain.data.model.AtLabel
import social.grain.data.model.LabelDefinition
import social.grain.data.model.LabelLocale
import social.grain.util.LabelAction
import social.grain.util.resolveLabels
/**
* What a label does to the thing it's attached to.
*
* Every gating decision in the app comes through this one function, and the
* failure it has to be held to is silent: a label that resolves a step too mild
* doesn't throw or look broken, it just shows the reader something a moderator
* said not to show them.
*/
class LabelResolutionTest {
private fun label(value: String, neg: Boolean? = null) = AtLabel(`val` = value, neg = neg)
private fun definition(
identifier: String,
blurs: String?,
defaultSetting: String?,
name: String = identifier,
) = LabelDefinition(
identifier = identifier,
locales = listOf(LabelLocale(name)),
blurs = blurs,
defaultSetting = defaultSetting,
)
@Test
fun `no labels resolves to no action`() {
assertEquals(LabelAction.NONE, resolveLabels(null, emptyList()).action)
assertEquals(LabelAction.NONE, resolveLabels(emptyList(), emptyList()).action)
}
@Test
fun `child safety hides without server definitions`() {
// grain's definitions include csae, so the fallback runs only when a
// caller passes none. Falling back to a badge there would put the one
// category we least want shown in front of a reader, at the exact
// moment nothing else is available to stop it.
val csae = resolveLabels(listOf(label("csae")), emptyList())
assertEquals(LabelAction.HIDE, csae.action)
assertEquals("Child Safety", csae.name)
}
@Test
fun `well-known labels resolve without server definitions`() {
val porn = resolveLabels(listOf(label("porn")), emptyList())
assertEquals(LabelAction.WARN_MEDIA, porn.action)
assertEquals("Adult Content", porn.name)
assertEquals(LabelAction.HIDE, resolveLabels(listOf(label("!hide")), emptyList()).action)
assertEquals(
LabelAction.WARN_CONTENT,
resolveLabels(listOf(label("!warn")), emptyList()).action,
)
}
@Test
fun `a server definition wins over the fallback for the same identifier`() {
val definitions = listOf(definition("porn", blurs = "content", defaultSetting = "hide"))
val result = resolveLabels(listOf(label("porn")), definitions)
assertEquals(LabelAction.HIDE, result.action)
}
@Test
fun `blurs media with a hide setting warns rather than hiding`() {
val definitions = listOf(definition("nsfl", blurs = "media", defaultSetting = "hide"))
assertEquals(
LabelAction.WARN_MEDIA,
resolveLabels(listOf(label("nsfl")), definitions).action,
)
}
@Test
fun `a label that blurs nothing is only a badge`() {
val definitions = listOf(definition("spoiler", blurs = "none", defaultSetting = "warn"))
val result = resolveLabels(listOf(label("spoiler")), definitions)
assertEquals(LabelAction.BADGE, result.action)
assertEquals("spoiler", result.name)
}
@Test
fun `an ignored label does nothing`() {
val definitions = listOf(definition("noop", blurs = "media", defaultSetting = "ignore"))
assertEquals(LabelAction.NONE, resolveLabels(listOf(label("noop")), definitions).action)
}
/** An identifier nobody has a definition for is still worth naming. */
@Test
fun `an unknown label is badged rather than dropped`() {
val result = resolveLabels(listOf(label("some-new-label")), emptyList())
assertEquals(LabelAction.BADGE, result.action)
assertEquals("some-new-label", result.name)
}
@Test
fun `the most restrictive label wins`() {
val result = resolveLabels(
listOf(label("some-new-label"), label("porn"), label("dmca-violation")),
emptyList(),
)
assertEquals(LabelAction.HIDE, result.action)
assertEquals("DMCA Violation", result.name)
}
/**
* `gore` is defined as blurring media but defaulting to hide, and media
* blurring caps the action at a cover-in-place rather than a full hide —
* a photo that can be blurred doesn't need the whole card taken away.
*/
@Test
fun `hiding is capped at a media warning when only the media blurs`() {
val result = resolveLabels(listOf(label("gore")), emptyList())
assertEquals(LabelAction.WARN_MEDIA, result.action)
assertEquals("Graphic Violence", result.name)
}
@Test
fun `a negated label is retracted, not applied`() {
assertEquals(
LabelAction.NONE,
resolveLabels(listOf(label("porn", neg = true)), emptyList()).action,
)
}
@Test
fun `a negation doesn't retract a different label on the same subject`() {
val result = resolveLabels(
listOf(label("porn", neg = true), label("dmca-violation")),
emptyList(),
)
assertEquals(LabelAction.HIDE, result.action)
assertEquals("DMCA Violation", result.name)
}
@Test
fun `the display name comes from the definition's first locale`() {
val definitions = listOf(
definition("custom", blurs = "media", defaultSetting = "warn", name = "Custom Warning"),
)
assertEquals("Custom Warning", resolveLabels(listOf(label("custom")), definitions).name)
}
}