From 83667d8a31012ef20fc7fb1ce29fda756ee5d27e Mon Sep 17 00:00:00 2001 From: Lee Dong-Yeon <83625797+easternkite@users.noreply.github.com> Date: Sun, 1 Dec 2024 22:25:06 +0900 Subject: [PATCH] Update NavArguments with RouteEncoder applied and add test code (#58) --- .../eungabi/navigation/NavArguments.kt | 73 +++++++++++++ .../eungabi/navigation/NavArgumentsTest.kt | 103 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 eungabi/src/commonMain/kotlin/com/easternkite/eungabi/navigation/NavArguments.kt create mode 100644 eungabi/src/commonTest/kotlin/com/easternkite/eungabi/navigation/NavArgumentsTest.kt diff --git a/eungabi/src/commonMain/kotlin/com/easternkite/eungabi/navigation/NavArguments.kt b/eungabi/src/commonMain/kotlin/com/easternkite/eungabi/navigation/NavArguments.kt new file mode 100644 index 0000000..cdf2b38 --- /dev/null +++ b/eungabi/src/commonMain/kotlin/com/easternkite/eungabi/navigation/NavArguments.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2024 easternkite + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.easternkite.eungabi.navigation + +import com.easternkite.eungabi.utils.RouteEncoder +import com.easternkite.eungabi.utils.decodeArgumentValue +import com.easternkite.eungabi.utils.encodeFullRoute +import com.easternkite.eungabi.utils.withScheme +import com.eygraber.uri.Uri + +/** + * The EunGabi navigation arguments. + * It parses the query parameters of the destination then holds them in a [arguments]. + */ +class NavArguments( + route: String +) { + /** + * The [Uri] converted from the route. + */ + internal val routeUri = Uri.parse(withScheme(RouteEncoder.encodeFullRoute(route))) + + /** + * The actual arguments parsed from query parameters of [routeUri]. + */ + private val arguments get() = + routeUri + .getQueryParameterNames() + .associateWith { routeUri.getQueryParameter(it) } + + /** + * Returns the [String] value of the argument with the given [key]. + */ + fun getString(key: String) = arguments[key]?.let { RouteEncoder.decodeArgumentValue(it) } + + /** + * Returns the [Int] value of the argument with the given [key]. + */ + fun getInt(key: String) = runCatching { arguments[key]?.toInt() }.getOrNull() + + /** + * Returns the [Long] value of the argument with the given [key]. + */ + fun getLong(key: String) = runCatching { arguments[key]?.toLong() }.getOrNull() + + /** + * Returns the [Float] value of the argument with the given [key]. + */ + fun getFloat(key: String) = runCatching { arguments[key]?.toFloat() }.getOrNull() + + /** + * Returns the [Double] value of the argument with the given [key]. + */ + fun getDouble(key: String) = runCatching { arguments[key]?.toDouble() }.getOrNull() + + /** + * Returns the [Boolean] value of the argument with the given [key]. + */ + fun getBoolean(key: String) = runCatching { arguments[key]?.toBoolean() }.getOrNull() +} diff --git a/eungabi/src/commonTest/kotlin/com/easternkite/eungabi/navigation/NavArgumentsTest.kt b/eungabi/src/commonTest/kotlin/com/easternkite/eungabi/navigation/NavArgumentsTest.kt new file mode 100644 index 0000000..d939753 --- /dev/null +++ b/eungabi/src/commonTest/kotlin/com/easternkite/eungabi/navigation/NavArgumentsTest.kt @@ -0,0 +1,103 @@ +package com.easternkite.eungabi.navigation + +import com.eygraber.uri.Uri +import kotlin.test.Test +import kotlin.test.assertEquals + +class NavArgumentsTest { + @Test + fun GIVEN_route_with_query_parameters_WHEN_call_routeUri_THEN_return_uri_parsed_from_route() { + val route = "route?param1=value1¶m2=value2" + val expected = Uri.parse("navhost://route?param1=value1¶m2=value2") + val actual = NavArguments(route).routeUri + assertEquals(expected = "navhost", actual = actual.scheme) + assertEquals(expected = "route", actual = actual.host) + assertEquals(expected = expected.query, actual = actual.query) + assertEquals(expected = expected, actual = actual) + } + + @Test + fun GIVEN_wrong_formatted_route_with_query_parameters_WHEN_call_routeUri_THEN_return_uri_parsed_from_route() { + val route = "//://::::???::@#@route?param1=value1¶m2" + val expected = Uri.parse("navhost://route?param1=value1¶m2") + val actual = NavArguments(route).routeUri + assertEquals(expected = "navhost", actual = actual.scheme) + assertEquals(expected = "route", actual = actual.host) + assertEquals(expected = expected.query, actual = actual.query) + assertEquals(expected = expected, actual = actual) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getString_THEN_return_value_of_query_parameter() { + val route = "route?param1=value1¶m2=value2" + + val expected = "value1" + val actual = NavArguments(route).getString("param1") + assertEquals(expected = expected, actual = actual) + + val expected2 = "value2" + val actual2 = NavArguments(route).getString("param2") + assertEquals(expected = expected2, actual = actual2) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getInt_THEN_return_value_of_query_parameter() { + val route = "route?param1=1¶m2=2" + val expected = 1 + val actual = NavArguments(route).getInt("param1") + assertEquals(expected = expected, actual = actual) + + val expected2 = 2 + val actual2 = NavArguments(route).getInt("param2") + assertEquals(expected = expected2, actual = actual2) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getLong_THEN_return_value_of_query_parameter() { + val route = "route?param1=123123123123¶m2=2" + val expected = 123123123123L + val actual = NavArguments(route).getLong("param1") + assertEquals(expected = expected, actual = actual) + + val expected2 = 2L + val actual2 = NavArguments(route).getLong("param2") + assertEquals(expected = expected2, actual = actual2) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getFloat_THEN_return_value_of_query_parameter() { + val route = "route?param1=1.0¶m2=2.0" + val expected = 1.0f + val actual = NavArguments(route).getFloat("param1") + assertEquals(expected = expected, actual = actual) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getDouble_THEN_return_value_of_query_parameter() { + val route = "route?param1=1.0¶m2=2.0" + val expected = 1.0 + val actual = NavArguments(route).getDouble("param1") + assertEquals(expected = expected, actual = actual) + } + + @Test + fun GIVEN_key_of_query_parameter_WHEN_call_getBoolean_THEN_return_value_of_query_parameter() { + val route = "route?param1=true¶m2=false" + val expected = true + val actual = NavArguments(route).getBoolean("param1") + assertEquals(expected = expected, actual = actual) + } + + @Test + fun GIVEN_url_included_value_of_key_of_query_parameter_WHEN_call_getString_THEN_return_value_of_query_parameter() { + val route = "route?url={https://easternkite.github.io/eungabi}" + val expected = "https://easternkite.github.io/eungabi" + val actual = NavArguments(route).getString("url") + assertEquals(expected = expected, actual = actual) + + val route2 = "route?url={https://easternkite.github.io/eungabi?param1=value1¶m2=value2}&id=123" + val expected2 = "https://easternkite.github.io/eungabi?param1=value1¶m2=value2" + val actual2 = NavArguments(route2).getString("url") + assertEquals(expected = expected2, actual = actual2) + } +}