Add HTML sanitization UI tests

189699 + 189700 and minor gardening.

MAILANDR-605
This commit is contained in:
Niccolò Forlini
2023-06-23 13:45:10 +00:00
parent 180eb1d178
commit 2be829425b
6 changed files with 185 additions and 7 deletions
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* This file is part of Proton Technologies AG and Proton Mail.
*
* Proton Mail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Proton Mail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.uitest.e2e.mailbox.detail.bodycontent
import ch.protonmail.android.di.ServerProofModule
import ch.protonmail.android.networkmocks.mockwebserver.requests.ignoreQueryParams
import ch.protonmail.android.networkmocks.mockwebserver.requests.matchWildcards
import ch.protonmail.android.networkmocks.mockwebserver.requests.respondWith
import ch.protonmail.android.networkmocks.mockwebserver.requests.serveOnce
import ch.protonmail.android.networkmocks.mockwebserver.requests.withStatusCode
import ch.protonmail.android.test.annotations.suite.SmokeTest
import ch.protonmail.android.uitest.MockedNetworkTest
import ch.protonmail.android.uitest.helpers.core.TestId
import ch.protonmail.android.uitest.helpers.core.navigation.Destination
import ch.protonmail.android.uitest.helpers.core.navigation.navigator
import ch.protonmail.android.uitest.helpers.login.LoginStrategy
import ch.protonmail.android.uitest.helpers.network.mockNetworkDispatcher
import ch.protonmail.android.uitest.robot.detail.conversationDetailRobot
import ch.protonmail.android.uitest.robot.detail.section.messageBodySection
import ch.protonmail.android.uitest.robot.detail.section.verify
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import io.mockk.mockk
import me.proton.core.auth.domain.usecase.ValidateServerProof
import org.junit.Test
@SmokeTest
@HiltAndroidTest
@UninstallModules(ServerProofModule::class)
internal class ConversationDetailHtmlSanitizationTests : MockedNetworkTest(loginStrategy = LoginStrategy.LoggedOut) {
@JvmField
@BindValue
val serverProofValidation: ValidateServerProof = mockk(relaxUnitFun = true)
@Test
@TestId("189699")
fun checkHtmlSanitizationInConversationMode() {
mockWebServer.dispatcher = mockNetworkDispatcher(useDefaultMailSettings = false) {
addMockRequests(
"/mail/v4/settings"
respondWith "/mail/v4/settings/mail-v4-settings_placeholder_conversation.json"
withStatusCode 200,
"/mail/v4/conversations"
respondWith "/mail/v4/conversations/conversations_189699.json"
withStatusCode 200 matchWildcards true ignoreQueryParams true,
"/mail/v4/conversations/*"
respondWith "/mail/v4/conversations/conversation-id/conversation-id_189699.json"
withStatusCode 200 matchWildcards true serveOnce true,
"/mail/v4/messages/*"
respondWith "/mail/v4/messages/message-id/message-id_189699.json"
withStatusCode 200 matchWildcards true serveOnce true
)
}
navigator {
navigateTo(Destination.MailDetail(0))
}
conversationDetailRobot {
messageBodySection {
waitUntilMessageIsShown()
verify { hasHtmlContentSanitised() }
}
}
}
}
@@ -16,7 +16,7 @@
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.uitest.e2e.mailbox.detail.conversation
package ch.protonmail.android.uitest.e2e.mailbox.detail.bodycontent
import arrow.core.Either
import ch.protonmail.android.di.ServerProofModule
@@ -52,7 +52,7 @@ import org.junit.Test
@RegressionTest
@HiltAndroidTest
@UninstallModules(ServerProofModule::class)
internal class ConversationDetailRemoteContentTest :
internal class ConversationDetailRemoteContentTests :
MockedNetworkTest(loginStrategy = LoginStrategy.LoggedOut),
DetailRemoteContentTest {
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* This file is part of Proton Technologies AG and Proton Mail.
*
* Proton Mail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Proton Mail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.uitest.e2e.mailbox.detail.bodycontent
import ch.protonmail.android.di.ServerProofModule
import ch.protonmail.android.networkmocks.mockwebserver.requests.ignoreQueryParams
import ch.protonmail.android.networkmocks.mockwebserver.requests.matchWildcards
import ch.protonmail.android.networkmocks.mockwebserver.requests.respondWith
import ch.protonmail.android.networkmocks.mockwebserver.requests.serveOnce
import ch.protonmail.android.networkmocks.mockwebserver.requests.withStatusCode
import ch.protonmail.android.test.annotations.suite.SmokeTest
import ch.protonmail.android.uitest.MockedNetworkTest
import ch.protonmail.android.uitest.helpers.core.TestId
import ch.protonmail.android.uitest.helpers.core.navigation.Destination
import ch.protonmail.android.uitest.helpers.core.navigation.navigator
import ch.protonmail.android.uitest.helpers.login.LoginStrategy
import ch.protonmail.android.uitest.helpers.network.mockNetworkDispatcher
import ch.protonmail.android.uitest.robot.detail.messageDetailRobot
import ch.protonmail.android.uitest.robot.detail.section.messageBodySection
import ch.protonmail.android.uitest.robot.detail.section.verify
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import io.mockk.mockk
import me.proton.core.auth.domain.usecase.ValidateServerProof
import org.junit.Test
@SmokeTest
@HiltAndroidTest
@UninstallModules(ServerProofModule::class)
internal class MessageDetailHtmlSanitizationTests : MockedNetworkTest(loginStrategy = LoginStrategy.LoggedOut) {
@JvmField
@BindValue
val serverProofValidation: ValidateServerProof = mockk(relaxUnitFun = true)
@Test
@TestId("189700")
fun checkHtmlSanitizationInMessageMode() {
mockWebServer.dispatcher = mockNetworkDispatcher(useDefaultMailSettings = false) {
addMockRequests(
"/mail/v4/settings"
respondWith "/mail/v4/settings/mail-v4-settings_placeholder_messages.json"
withStatusCode 200,
"/mail/v4/messages"
respondWith "/mail/v4/messages/messages_189700.json"
withStatusCode 200 matchWildcards true ignoreQueryParams true,
"/mail/v4/messages/*"
respondWith "/mail/v4/messages/message-id/message-id_189700.json"
withStatusCode 200 matchWildcards true serveOnce true
)
}
navigator {
navigateTo(Destination.MailDetail(0))
}
messageDetailRobot {
messageBodySection {
waitUntilMessageIsShown()
verify { hasHtmlContentSanitised() }
}
}
}
}
@@ -16,7 +16,7 @@
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.uitest.e2e.mailbox.detail.message
package ch.protonmail.android.uitest.e2e.mailbox.detail.bodycontent
import arrow.core.Either
import ch.protonmail.android.di.ServerProofModule
@@ -49,7 +49,7 @@ import org.junit.Test
@SmokeTest
@HiltAndroidTest
@UninstallModules(ServerProofModule::class)
internal class MessageDetailDetailRemoteContentTest :
internal class MessageDetailRemoteContentTests :
MockedNetworkTest(loginStrategy = LoginStrategy.LoggedOut),
DetailRemoteContentTest {
@@ -97,8 +97,6 @@ internal class MessageBodySection : ComposeSectionRobot() {
}
fun hasRemoteImageLoaded(expected: Boolean) {
composeTestRule.waitForIdle()
val jsSnippet = """
|var image = document.querySelector('img');
|var isLoaded = image.complete && image.naturalWidth != 0 && image.naturalHeight != 0;
@@ -108,6 +106,19 @@ internal class MessageBodySection : ComposeSectionRobot() {
runAndMatchJsCodeOutput(jsSnippet, expected)
}
fun hasHtmlContentSanitised() {
val jsSnippet = """
|var onLoad = document.querySelector('body').onload;
|var form = document.querySelector('form');
|var relLinks = document.querySelector('link');
|var iframe = document.querySelector('iframe');
|var ping = document.querySelector('a').ping;
|return onLoad == null && form == null && relLinks == null && iframe == null && ping == "";
""".trimMargin()
runAndMatchJsCodeOutput(jsSnippet, true)
}
private fun runAndMatchJsCodeOutput(script: String, expected: Boolean) {
webView.check(
webMatches(
+1 -1
View File
@@ -1 +1 @@
NETWORK_ASSETS_TARGET_REF=342e486a95b4128ea2c481d8522de77509b7dbc9
NETWORK_ASSETS_TARGET_REF=25c54c4ebd7d01b426006f2bc53fba56659c7d75