Merge branch '6.8-MAINT'
This commit is contained in:
commit
45d79a9a16
14 changed files with 340 additions and 110 deletions
|
@ -0,0 +1,7 @@
|
|||
- Added DNSSEC support when looking for server settings during setup
|
||||
- Made a change to prevent some software keyboards from capitalizing/auto-correcting email addresses in account setup
|
||||
- Fixed a crash when a very long subject was used
|
||||
- Fixed displaying OAuth 2.0 error messages
|
||||
- Fixed rare crash when downloading an attachment
|
||||
- Added code to disallow line breaks in single line text inputs
|
||||
- Updated translations
|
2
app-k9mail/proguard-rules.pro
vendored
2
app-k9mail/proguard-rules.pro
vendored
|
@ -39,6 +39,8 @@
|
|||
public <init>(android.content.Context);
|
||||
}
|
||||
|
||||
-keep class com.fsck.k9.mail.oauth.XOAuth2Response { *; }
|
||||
|
||||
# okhttp rules
|
||||
# see: https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ public class AttachmentDownloadDialogFragment extends DialogFragment {
|
|||
private static final String ARG_MESSAGE = "message";
|
||||
|
||||
|
||||
private ProgressDialog dialog;
|
||||
private MessagingListener messagingListener;
|
||||
private MessagingController messagingController;
|
||||
|
||||
|
@ -42,6 +41,14 @@ public class AttachmentDownloadDialogFragment extends DialogFragment {
|
|||
|
||||
final SizeUnit sizeUnit = SizeUnit.getAppropriateFor(size);
|
||||
|
||||
ProgressDialog dialog = new ProgressDialog(getActivity());
|
||||
dialog.setMessage(message);
|
||||
dialog.setMax(sizeUnit.valueInSizeUnit(size));
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
dialog.setProgress(0);
|
||||
dialog.setProgressNumberFormat("%1d/%2d " + sizeUnit.shortName);
|
||||
dialog.show();
|
||||
|
||||
messagingListener = new SimpleMessagingListener() {
|
||||
@Override
|
||||
public void updateProgress(int progress) {
|
||||
|
@ -52,14 +59,6 @@ public class AttachmentDownloadDialogFragment extends DialogFragment {
|
|||
messagingController = MessagingController.getInstance(getActivity());
|
||||
messagingController.addListener(messagingListener);
|
||||
|
||||
dialog = new ProgressDialog(getActivity());
|
||||
dialog.setMessage(message);
|
||||
dialog.setMax(sizeUnit.valueInSizeUnit(size));
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
dialog.setProgress(0);
|
||||
dialog.setProgressNumberFormat("%1d/%2d " + sizeUnit.shortName);
|
||||
dialog.show();
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@
|
|||
Locale-specific versions are kept in res/raw-<locale qualifier>/changelog.xml.
|
||||
-->
|
||||
<changelog>
|
||||
<release version="6.801" versioncode="38001" date="2024-03-11">
|
||||
<change>Added DNSSEC support when looking for server settings during setup</change>
|
||||
<change>Made a change to prevent some software keyboards from capitalizing/auto-correcting email addresses in account setup</change>
|
||||
<change>Fixed a crash when a very long subject was used</change>
|
||||
<change>Fixed displaying OAuth 2.0 error messages</change>
|
||||
<change>Fixed rare crash when downloading an attachment</change>
|
||||
<change>Added code to disallow line breaks in single line text inputs</change>
|
||||
<change>Updated translations</change>
|
||||
</release>
|
||||
<release version="6.800" versioncode="38000" date="2024-02-29">
|
||||
<change>New and improved account setup</change>
|
||||
<change>Added option to return to the message list after marking a message as unread in the message view</change>
|
||||
|
|
|
@ -5,6 +5,12 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
|
||||
private val LINE_BREAK = "[\\r\\n]".toRegex()
|
||||
|
||||
internal fun stripLineBreaks(onValueChange: (String) -> Unit): (String) -> Unit = { value ->
|
||||
onValueChange(value.replace(LINE_BREAK, replacement = ""))
|
||||
}
|
||||
|
||||
internal fun selectLabel(
|
||||
label: String?,
|
||||
isRequired: Boolean,
|
||||
|
|
|
@ -26,7 +26,7 @@ fun TextFieldOutlined(
|
|||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
onValueChange = if (isSingleLine) stripLineBreaks(onValueChange) else onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
|
|
|
@ -22,13 +22,14 @@ fun TextFieldOutlinedEmailAddress(
|
|||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
onValueChange = stripLineBreaks(onValueChange),
|
||||
modifier = modifier,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
readOnly = isReadOnly,
|
||||
isError = hasError,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
autoCorrect = false,
|
||||
keyboardType = KeyboardType.Email,
|
||||
),
|
||||
singleLine = true,
|
||||
|
|
|
@ -35,7 +35,7 @@ fun TextFieldOutlinedPassword(
|
|||
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
onValueChange = stripLineBreaks(onValueChange),
|
||||
modifier = modifier,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
|
@ -70,7 +70,7 @@ fun TextFieldOutlinedPassword(
|
|||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
onValueChange = stripLineBreaks(onValueChange),
|
||||
modifier = modifier,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
private const val TEST_TAG = "TextFieldOutlinedEmailAddress"
|
||||
|
||||
class TextFieldOutlinedEmailAddressKtTest : ComposeTest() {
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = "initial"
|
||||
setContent {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("initial + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should strip line breaks before onValueChange is called`() = runComposeTest {
|
||||
var value = ""
|
||||
setContent {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput("one\n two")
|
||||
|
||||
assertThat(value).isEqualTo("one two")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
private const val TEST_TAG = "TextFieldOutlined"
|
||||
|
||||
class TextFieldOutlinedKtTest : ComposeTest() {
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes with isSingleLine = false`() = runComposeTest {
|
||||
var value = "initial"
|
||||
setContent {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isSingleLine = false,
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("initial + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes with isSingleLine = true`() = runComposeTest {
|
||||
var value = "initial"
|
||||
setContent {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isSingleLine = true,
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("initial + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should allow line breaks when isSingleLine = false`() = runComposeTest {
|
||||
var value = ""
|
||||
setContent {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isSingleLine = false,
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput("one\ntwo")
|
||||
|
||||
assertThat(value).isEqualTo("one\ntwo")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should strip line breaks before onValueChange is called when isSingleLine = true`() = runComposeTest {
|
||||
var value = ""
|
||||
setContent {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isSingleLine = true,
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput("one\n two")
|
||||
|
||||
assertThat(value).isEqualTo("one two")
|
||||
}
|
||||
}
|
|
@ -1,18 +1,24 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.test.SemanticsNodeInteraction
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import app.k9mail.core.ui.compose.designsystem.R
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isTrue
|
||||
import org.junit.Test
|
||||
|
||||
private const val PASSWORD = "Password input"
|
||||
private const val TEST_TAG = "TextFieldOutlinedPassword"
|
||||
|
||||
class TextFieldOutlinedPasswordKtTest : ComposeTest() {
|
||||
|
||||
|
@ -131,6 +137,78 @@ class TextFieldOutlinedPasswordKtTest : ComposeTest() {
|
|||
onNodeWithText(PASSWORD).assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variant 1 should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = "initial"
|
||||
setContent {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("initial + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variant 2 should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = "initial"
|
||||
setContent {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isPasswordVisible = false,
|
||||
onPasswordVisibilityToggleClicked = {},
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("initial + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variant 1 should strip line breaks before onValueChange is called`() = runComposeTest {
|
||||
var value = ""
|
||||
setContent {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput("one\n two")
|
||||
|
||||
assertThat(value).isEqualTo("one two")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `variant 2 should strip line breaks before onValueChange is called`() = runComposeTest {
|
||||
var value = ""
|
||||
setContent {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
isPasswordVisible = false,
|
||||
onPasswordVisibilityToggleClicked = {},
|
||||
modifier = Modifier.testTag(TEST_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(TEST_TAG).performClick()
|
||||
onNodeWithTag(TEST_TAG).performTextInput("one\n two")
|
||||
|
||||
assertThat(value).isEqualTo("one two")
|
||||
}
|
||||
|
||||
private fun SemanticsNodeInteractionsProvider.onShowPasswordNode(): SemanticsNodeInteraction {
|
||||
return onNodeWithContentDescription(
|
||||
getString(R.string.designsystem_atom_password_textfield_show_password),
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner
|
||||
|
||||
data class TextInputTextFieldTestData(
|
||||
val name: String,
|
||||
val input: String,
|
||||
val content: @Composable (
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier,
|
||||
) -> Unit,
|
||||
)
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner::class)
|
||||
class TextInputTextFieldTest(
|
||||
data: TextInputTextFieldTestData,
|
||||
) : ComposeTest() {
|
||||
|
||||
private val testSubjectName = data.name
|
||||
private val testSubject = data.content
|
||||
private val testInput = data.input
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = testInput
|
||||
setContent {
|
||||
testSubject(
|
||||
value,
|
||||
{ value = it },
|
||||
Modifier.testTag(testSubjectName),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).performClick()
|
||||
onNodeWithTag(testSubjectName).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("$testInput + added text")
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
|
||||
fun data(): List<TextInputTextFieldTestData> = listOf(
|
||||
TextInputTextFieldTestData(
|
||||
name = "TextFieldOutlined",
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier ->
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
),
|
||||
TextInputTextFieldTestData(
|
||||
name = "TextFieldOutlinedPassword",
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier ->
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
),
|
||||
TextInputTextFieldTestData(
|
||||
name = "TextFieldOutlinedEmail",
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier ->
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,23 +1,29 @@
|
|||
package com.fsck.k9.mail.internet
|
||||
|
||||
import org.apache.james.mime4j.util.MimeUtil
|
||||
|
||||
object MimeHeaderEncoder {
|
||||
@JvmStatic
|
||||
fun encode(name: String, value: String): String {
|
||||
// TODO: Fold long text that provides enough opportunities for folding and doesn't contain any characters that
|
||||
// need to be encoded.
|
||||
return if (hasToBeEncoded(name, value)) {
|
||||
EncoderUtil.encodeEncodedWord(value)
|
||||
|
||||
// Number of characters already used up on the first line (header field name + colon + space)
|
||||
val usedCharacters = name.length + COLON_PLUS_SPACE_LENGTH
|
||||
|
||||
return if (hasToBeEncoded(value, usedCharacters)) {
|
||||
MimeUtil.fold(EncoderUtil.encodeEncodedWord(value), usedCharacters)
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasToBeEncoded(name: String, value: String): Boolean {
|
||||
return exceedsRecommendedLineLength(name, value) || charactersNeedEncoding(value)
|
||||
private fun hasToBeEncoded(value: String, usedCharacters: Int): Boolean {
|
||||
return exceedsRecommendedLineLength(value, usedCharacters) || charactersNeedEncoding(value)
|
||||
}
|
||||
|
||||
private fun exceedsRecommendedLineLength(name: String, value: String): Boolean {
|
||||
return name.length + COLON_PLUS_SPACE_LENGTH + value.length > RECOMMENDED_MAX_LINE_LENGTH
|
||||
private fun exceedsRecommendedLineLength(value: String, usedCharacters: Int): Boolean {
|
||||
return usedCharacters + value.length > RECOMMENDED_MAX_LINE_LENGTH
|
||||
}
|
||||
|
||||
private fun charactersNeedEncoding(text: String): Boolean {
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package com.fsck.k9.mail.internet
|
||||
|
||||
import assertk.Assert
|
||||
import assertk.all
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.each
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isLessThanOrEqualTo
|
||||
import assertk.assertions.length
|
||||
import assertk.fail
|
||||
import kotlin.test.Test
|
||||
|
||||
class MimeHeaderEncoderTest {
|
||||
@Test
|
||||
fun `short subject containing only ASCII characters should not be encoded`() {
|
||||
val result = MimeHeaderEncoder.encode(name = "Subject", value = "Hello World!")
|
||||
|
||||
assertThat(result).isEqualTo("Hello World!")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `short subject containing non-ASCII characters should be encoded`() {
|
||||
val result = MimeHeaderEncoder.encode(name = "Subject", value = "Gänseblümchen")
|
||||
|
||||
assertThat(result).isEqualTo("=?UTF-8?Q?G=C3=A4nsebl=C3=BCmchen?=")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `subject with recommended line length should not be folded`() {
|
||||
val subject = "a".repeat(RECOMMENDED_MAX_LINE_LENGTH - "Subject: ".length)
|
||||
|
||||
val result = MimeHeaderEncoder.encode(name = "Subject", value = subject)
|
||||
|
||||
assertThat(result).isEqualTo(subject)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `subject exceeding recommended line length should be folded`() {
|
||||
val subject = "a".repeat(34) + " " + "a".repeat(35)
|
||||
|
||||
val result = MimeHeaderEncoder.encode(name = "Subject", value = subject)
|
||||
|
||||
assertThat(result).all {
|
||||
transform { it.lines() }.each {
|
||||
it.length().isLessThanOrEqualTo(RECOMMENDED_MAX_LINE_LENGTH)
|
||||
}
|
||||
isValidHeader(name = "Subject")
|
||||
decodesTo(subject)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `subject exceeding maximum line length should be encoded`() {
|
||||
val subject = "a".repeat(999)
|
||||
|
||||
val result = MimeHeaderEncoder.encode(name = "Subject", value = subject)
|
||||
|
||||
assertThat(result).all {
|
||||
isValidHeader(name = "Subject")
|
||||
decodesTo(subject)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Assert<String>.isValidHeader(name: String) = given { value ->
|
||||
try {
|
||||
MimeHeaderChecker.checkHeader(name, value)
|
||||
} catch (e: MimeHeaderParserException) {
|
||||
fail(AssertionError("Not a valid RFC5322 header", e))
|
||||
}
|
||||
}
|
||||
|
||||
private fun Assert<String>.decodesTo(expected: String) = given { value ->
|
||||
assertThat(MimeUtility.unfoldAndDecode(value)).isEqualTo(expected)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue