mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-14 23:18:43 +00:00
Add tests for SmartlingClient.
This commit is contained in:
committed by
jeffrey-signal
parent
ffecdb3747
commit
c31b2edeab
@@ -25,8 +25,9 @@ dependencies {
|
|||||||
implementation(gradleApi())
|
implementation(gradleApi())
|
||||||
|
|
||||||
implementation(libs.dnsjava)
|
implementation(libs.dnsjava)
|
||||||
implementation(libs.square.okhttp3)
|
api(libs.square.okhttp3)
|
||||||
|
|
||||||
testImplementation(testLibs.junit.junit)
|
testImplementation(testLibs.junit.junit)
|
||||||
testImplementation(testLibs.mockk)
|
testImplementation(testLibs.mockk)
|
||||||
|
testImplementation(testLibs.square.mockwebserver)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ import java.util.concurrent.TimeUnit
|
|||||||
class SmartlingClient(
|
class SmartlingClient(
|
||||||
private val userIdentifier: String,
|
private val userIdentifier: String,
|
||||||
private val userSecret: String,
|
private val userSecret: String,
|
||||||
private val projectId: String
|
private val projectId: String,
|
||||||
|
private val baseUrl: String = "https://api.smartling.com",
|
||||||
|
client: OkHttpClient? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val client = OkHttpClient.Builder()
|
private val client = client ?: OkHttpClient.Builder()
|
||||||
.connectTimeout(30, TimeUnit.SECONDS)
|
.connectTimeout(30, TimeUnit.SECONDS)
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
.writeTimeout(30, TimeUnit.SECONDS)
|
.writeTimeout(30, TimeUnit.SECONDS)
|
||||||
@@ -41,7 +43,7 @@ class SmartlingClient(
|
|||||||
).toString()
|
).toString()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("https://api.smartling.com/auth-api/v2/authenticate")
|
.url("$baseUrl/auth-api/v2/authenticate")
|
||||||
.post(jsonBody.toRequestBody("application/json".toMediaType()))
|
.post(jsonBody.toRequestBody("application/json".toMediaType()))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ class SmartlingClient(
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("https://api.smartling.com/files-api/v2/projects/$projectId/file")
|
.url("$baseUrl/files-api/v2/projects/$projectId/file")
|
||||||
.header("Authorization", "Bearer $authToken")
|
.header("Authorization", "Bearer $authToken")
|
||||||
.post(requestBody)
|
.post(requestBody)
|
||||||
.build()
|
.build()
|
||||||
@@ -94,7 +96,7 @@ class SmartlingClient(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun getLocales(authToken: String, fileUri: String): List<String> {
|
fun getLocales(authToken: String, fileUri: String): List<String> {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("https://api.smartling.com/files-api/v2/projects/$projectId/file/status?fileUri=$fileUri")
|
.url("$baseUrl/files-api/v2/projects/$projectId/file/status?fileUri=$fileUri")
|
||||||
.header("Authorization", "Bearer $authToken")
|
.header("Authorization", "Bearer $authToken")
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
@@ -120,7 +122,7 @@ class SmartlingClient(
|
|||||||
*/
|
*/
|
||||||
fun downloadFile(authToken: String, fileUri: String, locale: String): String {
|
fun downloadFile(authToken: String, fileUri: String, locale: String): String {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("https://api.smartling.com/files-api/v2/projects/$projectId/locales/$locale/file?fileUri=$fileUri")
|
.url("$baseUrl/files-api/v2/projects/$projectId/locales/$locale/file?fileUri=$fileUri")
|
||||||
.header("Authorization", "Bearer $authToken")
|
.header("Authorization", "Bearer $authToken")
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
package org.signal.buildtools
|
||||||
|
|
||||||
|
import mockwebserver3.MockResponse
|
||||||
|
import mockwebserver3.MockWebServer
|
||||||
|
import okhttp3.ExperimentalOkHttpApi
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@OptIn(ExperimentalOkHttpApi::class)
|
||||||
|
class SmartlingClientTest {
|
||||||
|
|
||||||
|
private lateinit var server: MockWebServer
|
||||||
|
private lateinit var client: SmartlingClient
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
server = MockWebServer()
|
||||||
|
server.start()
|
||||||
|
client = SmartlingClient(
|
||||||
|
userIdentifier = "test-user",
|
||||||
|
userSecret = "test-secret",
|
||||||
|
projectId = "test-project",
|
||||||
|
baseUrl = server.url("/").toString().removeSuffix("/")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
server.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `authenticate returns access token on success`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"response": {
|
||||||
|
"data": {
|
||||||
|
"accessToken": "test-token-123"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val token = client.authenticate()
|
||||||
|
|
||||||
|
assertEquals("test-token-123", token)
|
||||||
|
|
||||||
|
val request = server.takeRequest()
|
||||||
|
assertEquals("POST", request.method)
|
||||||
|
assertEquals("/auth-api/v2/authenticate", request.path)
|
||||||
|
assertTrue(request.body.readUtf8().contains("test-user"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `authenticate throws on HTTP error`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(401)
|
||||||
|
.body("Unauthorized")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
client.authenticate()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `authenticate throws on malformed response`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body("{}")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
client.authenticate()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `uploadFile returns response body on success`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body("""{"response": {"data": {"uploaded": true}}}""")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val tempFile = File.createTempFile("test-strings", ".xml").apply {
|
||||||
|
writeText("<resources><string name=\"test\">Test</string></resources>")
|
||||||
|
deleteOnExit()
|
||||||
|
}
|
||||||
|
|
||||||
|
val response = client.uploadFile("auth-token", tempFile, "strings.xml")
|
||||||
|
|
||||||
|
assertTrue(response.contains("uploaded"))
|
||||||
|
|
||||||
|
val request = server.takeRequest()
|
||||||
|
assertEquals("POST", request.method)
|
||||||
|
assertEquals("/files-api/v2/projects/test-project/file", request.path)
|
||||||
|
assertEquals("Bearer auth-token", request.headers["Authorization"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `uploadFile throws on HTTP error`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(500)
|
||||||
|
.body("Internal Server Error")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val tempFile = File.createTempFile("test-strings", ".xml").apply {
|
||||||
|
writeText("<resources/>")
|
||||||
|
deleteOnExit()
|
||||||
|
}
|
||||||
|
|
||||||
|
client.uploadFile("auth-token", tempFile, "strings.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getLocales returns list of locale IDs`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"response": {
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{"localeId": "de"},
|
||||||
|
{"localeId": "fr"},
|
||||||
|
{"localeId": "es"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val locales = client.getLocales("auth-token", "strings.xml")
|
||||||
|
|
||||||
|
assertEquals(listOf("de", "fr", "es"), locales)
|
||||||
|
|
||||||
|
val request = server.takeRequest()
|
||||||
|
assertEquals("GET", request.method)
|
||||||
|
assertEquals("/files-api/v2/projects/test-project/file/status?fileUri=strings.xml", request.path)
|
||||||
|
assertEquals("Bearer auth-token", request.headers["Authorization"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `getLocales throws on HTTP error`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(404)
|
||||||
|
.body("Not Found")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
client.getLocales("auth-token", "strings.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `getLocales throws on malformed response`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body("""{"response": {"data": {}}}""")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
client.getLocales("auth-token", "strings.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `downloadFile returns file content`() {
|
||||||
|
val xmlContent = """<resources><string name="hello">Hallo</string></resources>"""
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(200)
|
||||||
|
.body(xmlContent)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
val content = client.downloadFile("auth-token", "strings.xml", "de")
|
||||||
|
|
||||||
|
assertEquals(xmlContent, content)
|
||||||
|
|
||||||
|
val request = server.takeRequest()
|
||||||
|
assertEquals("GET", request.method)
|
||||||
|
assertEquals("/files-api/v2/projects/test-project/locales/de/file?fileUri=strings.xml", request.path)
|
||||||
|
assertEquals("Bearer auth-token", request.headers["Authorization"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = SmartlingClient.SmartlingException::class)
|
||||||
|
fun `downloadFile throws on HTTP error`() {
|
||||||
|
server.enqueue(
|
||||||
|
MockResponse.Builder()
|
||||||
|
.code(500)
|
||||||
|
.body("Internal Server Error")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
client.downloadFile("auth-token", "strings.xml", "de")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,5 +24,6 @@ assertk = "com.willowtreeapps.assertk:assertk:0.28.1"
|
|||||||
mockk = "io.mockk:mockk:1.13.17"
|
mockk = "io.mockk:mockk:1.13.17"
|
||||||
mockk-android = "io.mockk:mockk-android:1.13.17"
|
mockk-android = "io.mockk:mockk-android:1.13.17"
|
||||||
|
|
||||||
|
square-mockwebserver = "com.squareup.okhttp3:mockwebserver:5.0.0-alpha.16"
|
||||||
conscrypt-openjdk-uber = "org.conscrypt:conscrypt-openjdk-uber:2.5.2"
|
conscrypt-openjdk-uber = "org.conscrypt:conscrypt-openjdk-uber:2.5.2"
|
||||||
diff-utils = "io.github.java-diff-utils:java-diff-utils:4.12"
|
diff-utils = "io.github.java-diff-utils:java-diff-utils:4.12"
|
||||||
|
|||||||
Reference in New Issue
Block a user