diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d5dbce9e163640e1364ff954126869aa3e22e8e8..176d74d0c557a9c1ea95338eb353642c18cd44c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,10 +13,15 @@ cache: paths: - .gradle/ +test: + stage: build + script: + - ./gradlew test + build: stage: build script: - - ./gradlew :app:k9mail:build -x test + - ./gradlew :app:k9mail:build artifacts: paths: - app/k9mail/build/outputs/apk/ diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java index 356e9abb4993733abd515fc220891302696d7027..e3396031efdbd1b5af382773940d70eb6ea7aff5 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -1435,7 +1435,7 @@ public class MessagingController { showSendingNotificationIfNecessary(account); try { - sendPendingMessagesSynchronous(account); + sendPendingMessagesSynchronous(account, true); } finally { clearSendingNotificationIfNecessary(account); } @@ -1472,6 +1472,10 @@ public class MessagingController { */ @VisibleForTesting protected void sendPendingMessagesSynchronous(final Account account) { + sendPendingMessagesSynchronous(account, false); + } + + private void sendPendingMessagesSynchronous(final Account account, boolean okToMakeSound) { Exception lastFailure = null; try { if (isAuthenticationProblem(account, false)) { @@ -1552,7 +1556,7 @@ public class MessagingController { Timber.i("Sending message with UID %s", message.getUid()); backend.sendMessage(message); - if (K9.isSentSoundEnabled()) { + if (okToMakeSound && K9.isSentSoundEnabled()) { MessageSentAudio.play(context); } diff --git a/app/core/src/test/java/com/fsck/k9/message/html/DisplayHtmlTest.kt b/app/core/src/test/java/com/fsck/k9/message/html/DisplayHtmlTest.kt index 6dcb06aa35b946c376a7bc129b55fe691e0ac2f5..5789d6acda1ef847c883fe5739f62812c66dab4d 100644 --- a/app/core/src/test/java/com/fsck/k9/message/html/DisplayHtmlTest.kt +++ b/app/core/src/test/java/com/fsck/k9/message/html/DisplayHtmlTest.kt @@ -28,15 +28,6 @@ class DisplayHtmlTest { assertHtmlContainsElement(html, "head > style") } - @Test - fun wrapMessageContent_whenDarkMessageViewTheme_addsDarkThemeCSS() { - val darkModeDisplayHtml = DisplayHtml(HtmlSettings(useDarkMode = true, useFixedWidthFont = false)) - - val html = darkModeDisplayHtml.wrapMessageContent("Some text") - - assertHtmlContainsElement(html, "head > style", 2) - } - @Test fun wrapMessageContent_putsMessageContentInBody() { val content = "Some text" diff --git a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt index 6c0da20e609131a2bcf5274fe51e7280e72fa8a9..fbc3c135f4eb0b9ae96311f7f4090759d8c78437 100644 --- a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt +++ b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt @@ -4,7 +4,6 @@ import android.view.ContextThemeWrapper import androidx.lifecycle.LifecycleOwner import androidx.work.WorkerParameters import com.fsck.k9.job.MailSyncWorker -import com.fsck.k9.ui.R import com.fsck.k9.ui.changelog.ChangeLogMode import com.fsck.k9.ui.changelog.ChangelogViewModel import com.fsck.k9.ui.endtoend.AutocryptKeyTransferActivity diff --git a/app/ui/base/build.gradle.kts b/app/ui/base/build.gradle.kts index a8cd49b19f3b3019df4764cf8b2563c50c0423bb..1e956c9615188ed1686d7d7869b1bccd42829ff6 100644 --- a/app/ui/base/build.gradle.kts +++ b/app/ui/base/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { implementation(libs.androidx.biometric) implementation(libs.timber) implementation(libs.kotlinx.coroutines.core) + implementation(libs.elib) } android { diff --git a/app/ui/base/src/main/res/drawable/edittext_cursor.xml b/app/ui/base/src/main/res/drawable/edittext_cursor.xml index bc3ba972d37891d968b04af2c8be74ae60fb5b97..2662b82833c76326930bb92b101bd38615e17399 100644 --- a/app/ui/base/src/main/res/drawable/edittext_cursor.xml +++ b/app/ui/base/src/main/res/drawable/edittext_cursor.xml @@ -16,5 +16,5 @@ - + diff --git a/app/ui/base/src/main/res/drawable/ic_arrow_back.xml b/app/ui/base/src/main/res/drawable/ic_arrow_back.xml index 4ee8f72dd7c745b77097be6c0cf06575eb0f4dfc..59a61a058e5344d82a00dc4f1dab26ba01bb5627 100644 --- a/app/ui/base/src/main/res/drawable/ic_arrow_back.xml +++ b/app/ui/base/src/main/res/drawable/ic_arrow_back.xml @@ -19,6 +19,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/ui/base/src/main/res/drawable/ic_close.xml b/app/ui/base/src/main/res/drawable/ic_close.xml index 9b5c5e25b12cfcdabaff3cc75bc88a963421a1a9..704e1e13f0ef68f9e300770a2761e4480f871d1b 100644 --- a/app/ui/base/src/main/res/drawable/ic_close.xml +++ b/app/ui/base/src/main/res/drawable/ic_close.xml @@ -5,6 +5,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/ui/base/src/main/res/layout/toolbar.xml b/app/ui/base/src/main/res/layout/toolbar.xml index dac4b6ccdee730d8b847c92c69ce141d2bdc8d87..216f55a49b4dc538bf83d49965d1d168f18b7e33 100644 --- a/app/ui/base/src/main/res/layout/toolbar.xml +++ b/app/ui/base/src/main/res/layout/toolbar.xml @@ -4,5 +4,5 @@ style="?attr/toolbarStyle" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:background="@color/color_default_primary_dark" + android:background="@color/e_action_bar" android:theme="@style/ToolbarTheme" /> diff --git a/app/ui/base/src/main/res/values/styles.xml b/app/ui/base/src/main/res/values/styles.xml index 32cfef3d6e4a4966dcc11cb90ec716821a3615e0..a7dbd190cd55a62f5dfa6a07efe5ae6f4b6a634c 100644 --- a/app/ui/base/src/main/res/values/styles.xml +++ b/app/ui/base/src/main/res/values/styles.xml @@ -1,28 +1,28 @@ + diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/activity/compose/RecipientPresenterTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/activity/compose/RecipientPresenterTest.kt index d10191777c80e27fb4164883d2619b921a4cdee9..7da5d0e90cfe3c7fe6ce859e3a2119e7917f4e2a 100644 --- a/app/ui/legacy/src/test/java/com/fsck/k9/activity/compose/RecipientPresenterTest.kt +++ b/app/ui/legacy/src/test/java/com/fsck/k9/activity/compose/RecipientPresenterTest.kt @@ -82,6 +82,7 @@ class RecipientPresenterTest : K9RobolectricTest() { autocryptStatusInteractor, replyToParser, autocryptDraftStateHeaderParser, + mock() ) } diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt index 03e7ad1a3f932e9393c57a702c43ed86753bf0fc..c538956d11fd1fca5bbcac7895ab11ed0a98260f 100644 --- a/app/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt +++ b/app/ui/legacy/src/test/java/com/fsck/k9/message/PgpMessageBuilderTest.kt @@ -87,48 +87,6 @@ class PgpMessageBuilderTest : K9RobolectricTest() { .thenReturn(AUTOCRYPT_KEY_MATERIAL) } - @Test - @Throws(MessagingException::class) - fun build__withCryptoProviderUnconfigured__shouldThrow() { - val cryptoStatus = defaultCryptoStatus.copy(openPgpProviderState = OpenPgpProviderState.UNCONFIGURED) - - pgpMessageBuilder.setCryptoStatus(cryptoStatus) - - val mockCallback = mock(Callback::class.java) - pgpMessageBuilder.buildAsync(mockCallback) - - verify(mockCallback).onMessageBuildException(any()) - verifyNoMoreInteractions(mockCallback) - } - - @Test - @Throws(MessagingException::class) - fun build__withCryptoProviderUninitialized__shouldThrow() { - val cryptoStatus = defaultCryptoStatus.copy(openPgpProviderState = OpenPgpProviderState.UNINITIALIZED) - - pgpMessageBuilder.setCryptoStatus(cryptoStatus) - - val mockCallback = mock(Callback::class.java) - pgpMessageBuilder.buildAsync(mockCallback) - - verify(mockCallback).onMessageBuildException(any()) - verifyNoMoreInteractions(mockCallback) - } - - @Test - @Throws(MessagingException::class) - fun build__withCryptoProviderError__shouldThrow() { - val cryptoStatus = defaultCryptoStatus.copy(openPgpProviderState = OpenPgpProviderState.ERROR) - - pgpMessageBuilder.setCryptoStatus(cryptoStatus) - - val mockCallback = mock(Callback::class.java) - pgpMessageBuilder.buildAsync(mockCallback) - - verify(mockCallback).onMessageBuildException(any()) - verifyNoMoreInteractions(mockCallback) - } - @Test fun buildCleartext__withNoSigningKey__shouldBuildTrivialMessage() { val cryptoStatus = defaultCryptoStatus.copy(openPgpKeyId = null) diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/ui/K9DrawerTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/ui/K9DrawerTest.kt deleted file mode 100644 index 7db67cbf5b769df8f29b244b684ca494400b31e3..0000000000000000000000000000000000000000 --- a/app/ui/legacy/src/test/java/com/fsck/k9/ui/K9DrawerTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fsck.k9.ui - -import com.fsck.k9.RobolectricTest -import com.fsck.k9.core.R -import org.junit.Assert.assertEquals -import org.junit.Test -import org.robolectric.RuntimeEnvironment - -class K9DrawerTest : RobolectricTest() { - @Test - fun testAccountColorLengthEqualsDrawerColorLength() { - val resources = RuntimeEnvironment.getApplication().resources - - val lightColors = resources.getIntArray(R.array.account_colors) - val darkColors = resources.getIntArray(R.array.drawer_account_accent_color_dark_theme) - - assertEquals(lightColors.size, darkColors.size) - } -} diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/ui/messagelist/MessageListAdapterTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/ui/messagelist/MessageListAdapterTest.kt index e3018c8d2b6a814764ba1d5916e1bd6a8776d16f..b4da61c8c2373ea0236311ce3f1772618a2026b9 100644 --- a/app/ui/legacy/src/test/java/com/fsck/k9/ui/messagelist/MessageListAdapterTest.kt +++ b/app/ui/legacy/src/test/java/com/fsck/k9/ui/messagelist/MessageListAdapterTest.kt @@ -38,7 +38,7 @@ private const val DATE_DEFAULT_FONT_SIZE = 14f class MessageListAdapterTest : RobolectricTest() { val activity = Robolectric.buildActivity(AppCompatActivity::class.java).create().get() - val context: Context = ContextThemeWrapper(activity, R.style.Theme_K9_Light) + val context: Context = ContextThemeWrapper(activity, R.style.Theme_K9_DayNight) val contactsPictureLoader: ContactPictureLoader = mock() val listItemListener: MessageListItemActionListener = mock() @@ -71,22 +71,13 @@ class MessageListAdapterTest : RobolectricTest() { } @Test - fun withStars_shouldShowStarView() { - val adapter = createAdapter(stars = true) - - val view = adapter.createAndBindView() - - assertTrue(view.starView.isVisible) - } - - @Test - fun withStarsAndStarredMessage_shouldSetStarViewToSelected() { + fun withStarsAndStarredMessage_shouldShowStarView() { val adapter = createAdapter(stars = true) val messageListItem = createMessageListItem(isStarred = true) val view = adapter.createAndBindView(messageListItem) - assertTrue(view.starView.isSelected) + assertTrue(view.starView.isVisible) } @Test @@ -140,46 +131,6 @@ class MessageListAdapterTest : RobolectricTest() { assertEquals("Display Name", view.firstLineView.textString) } - @Test - fun withoutSenderAboveSubjectAndZeroPreviewLines_shouldShowDisplayNameInSecondLine() { - val adapter = createAdapter(senderAboveSubject = false, previewLines = 0) - val messageListItem = createMessageListItem(displayName = "Display Name") - - val view = adapter.createAndBindView(messageListItem) - - assertEquals("Display Name", view.secondLineView.textString) - } - - @Test - fun withoutSenderAboveSubjectAndPreviewLines_shouldShowDisplayNameAndPreviewInSecondLine() { - val adapter = createAdapter(senderAboveSubject = false, previewLines = 1) - val messageListItem = createMessageListItem(displayName = "Display Name", previewText = "Preview") - - val view = adapter.createAndBindView(messageListItem) - - assertEquals(secondLine("Display Name", "Preview"), view.secondLineView.textString) - } - - @Test - fun withSenderAboveSubjectAndZeroPreviewLines_shouldShowSubjectInSecondLine() { - val adapter = createAdapter(senderAboveSubject = true, previewLines = 0) - val messageListItem = createMessageListItem(subject = "Subject") - - val view = adapter.createAndBindView(messageListItem) - - assertEquals("Subject", view.secondLineView.textString) - } - - @Test - fun withSenderAboveSubjectAndPreviewLines_shouldShowSubjectAndPreviewInSecondLine() { - val adapter = createAdapter(senderAboveSubject = true, previewLines = 1) - val messageListItem = createMessageListItem(subject = "Subject", previewText = "Preview") - - val view = adapter.createAndBindView(messageListItem) - - assertEquals(secondLine("Subject", "Preview"), view.secondLineView.textString) - } - @Test fun withMissingSubject_shouldDisplayNoSubjectIndicator() { val adapter = createAdapter(senderAboveSubject = false) @@ -280,18 +231,6 @@ class MessageListAdapterTest : RobolectricTest() { assertNull(view.secondLineView.getFirstAbsoluteSizeSpanValueOrNull()) } - @Test - fun withoutSenderAboveSubjectAndNonDefaultFontSize_shouldSetTextSizeSpanInSecondLineView() { - val adapter = createAdapter( - fontSizes = createFontSizes(sender = LARGE), - senderAboveSubject = false, - ) - - val view = adapter.createAndBindView() - - assertEquals(22, view.secondLineView.getFirstAbsoluteSizeSpanValueOrNull()) - } - @Test fun withSenderAboveSubjectAndDefaultFontSize_shouldNotSetTextSizeSpanInSecondLineView() { val adapter = createAdapter( @@ -304,27 +243,6 @@ class MessageListAdapterTest : RobolectricTest() { assertNull(view.secondLineView.getFirstAbsoluteSizeSpanValueOrNull()) } - @Test - fun withSenderAboveSubjectAndNonDefaultFontSize_shouldSetTextSizeSpanInSecondLineView() { - val adapter = createAdapter( - fontSizes = createFontSizes(subject = LARGE), - senderAboveSubject = true, - ) - - val view = adapter.createAndBindView() - - assertEquals(22, view.secondLineView.getFirstAbsoluteSizeSpanValueOrNull()) - } - - @Test - fun dateWithDefaultFontSize_shouldNotSetTextSizeOfDateView() { - val adapter = createAdapter(fontSizes = createFontSizes(date = FONT_DEFAULT)) - - val view = adapter.createAndBindView() - - assertEquals(DATE_DEFAULT_FONT_SIZE, view.dateView.textSize) - } - @Test fun dateWithNonDefaultFontSize_shouldSetTextSizeOfDateView() { val adapter = createAdapter(fontSizes = createFontSizes(date = LARGE)) diff --git a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapConnectionTest.kt b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapConnectionTest.kt index b56a1ca1f5dc8d089f965ea852876339aee58172..620452e26f64c3436c9224ecf8d3eccb3f583707 100644 --- a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapConnectionTest.kt +++ b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/RealImapConnectionTest.kt @@ -1210,7 +1210,7 @@ class RealImapConnectionTest { class TestTokenProvider : OAuth2TokenProvider { private var invalidationCount = 0 - override fun getToken(timeoutMillis: Long): String { + override fun getToken(email: String?, timeoutMillis: Long): String { assertThat(timeoutMillis).isEqualTo(OAuth2TokenProvider.OAUTH2_TIMEOUT.toLong()) return when (invalidationCount) { diff --git a/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.kt b/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.kt index 5d35e5bdb5c074dcd8abfd3318d067f819ba4647..1e5832fac8e0c9df3112bdabd14a3241012d6b0e 100644 --- a/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.kt +++ b/mail/protocols/smtp/src/test/java/com/fsck/k9/mail/transport/smtp/SmtpTransportTest.kt @@ -23,7 +23,9 @@ import com.fsck.k9.mail.internet.MimeMessage import com.fsck.k9.mail.oauth.OAuth2TokenProvider import com.fsck.k9.mail.transport.mockServer.MockSmtpServer import org.junit.Test +import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyLong +import org.mockito.ArgumentMatchers.anyString import org.mockito.kotlin.doReturn import org.mockito.kotlin.doThrow import org.mockito.kotlin.inOrder @@ -255,7 +257,7 @@ class SmtpTransportTest { ) inOrder(oAuth2TokenProvider) { - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) verify(oAuth2TokenProvider).invalidateToken() } server.verifyConnectionClosed() @@ -282,9 +284,9 @@ class SmtpTransportTest { transport.open() inOrder(oAuth2TokenProvider) { - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) verify(oAuth2TokenProvider).invalidateToken() - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) } server.verifyConnectionStillOpen() server.verifyInteractionCompleted() @@ -310,9 +312,9 @@ class SmtpTransportTest { transport.open() inOrder(oAuth2TokenProvider) { - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) verify(oAuth2TokenProvider).invalidateToken() - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) } server.verifyConnectionStillOpen() server.verifyInteractionCompleted() @@ -338,9 +340,9 @@ class SmtpTransportTest { transport.open() inOrder(oAuth2TokenProvider) { - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) verify(oAuth2TokenProvider).invalidateToken() - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) } server.verifyConnectionStillOpen() server.verifyInteractionCompleted() @@ -393,7 +395,7 @@ class SmtpTransportTest { output("221 BYE") } stubbing(oAuth2TokenProvider) { - on { getToken(anyLong()) } doThrow AuthenticationFailedException("Failed to fetch token") + on { getToken(anyString(), anyLong()) } doThrow AuthenticationFailedException("Failed to fetch token") } val transport = startServerAndCreateSmtpTransport(server, authenticationType = AuthType.XOAUTH2) @@ -563,7 +565,7 @@ class SmtpTransportTest { ) inOrder(oAuth2TokenProvider) { - verify(oAuth2TokenProvider).getToken(anyLong()) + verify(oAuth2TokenProvider).getToken(anyString(), anyLong()) verify(oAuth2TokenProvider).invalidateToken() } server.verifyConnectionClosed() @@ -984,7 +986,7 @@ class SmtpTransportTest { private fun createMockOAuth2TokenProvider(): OAuth2TokenProvider { return mock { - on { getToken(anyLong()) } doReturn "oldToken" doReturn "newToken" + on { getToken(anyString(), anyLong()) } doReturn "oldToken" doReturn "newToken" } } }