From 325a6f84fbf59cf1374a1af7897379d12ea0345c Mon Sep 17 00:00:00 2001 From: Dmitry Lobanov Date: Sun, 28 Jan 2024 17:16:33 +0300 Subject: [PATCH] Deeplink: Encoding deeplink has been added. --- Sources/Deeplink/Deeplink.swift | 6 + Sources/Deeplink/DeeplinkInterpolation.swift | 19 ++++ .../DeeplinkTests/EncodingDeeplinkTests.swift | 107 ++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 Tests/DeeplinkTests/EncodingDeeplinkTests.swift diff --git a/Sources/Deeplink/Deeplink.swift b/Sources/Deeplink/Deeplink.swift index 6ad52df..f210f12 100644 --- a/Sources/Deeplink/Deeplink.swift +++ b/Sources/Deeplink/Deeplink.swift @@ -45,6 +45,12 @@ public enum Deeplink: Equatable, Hashable { case .interpolated(let interpolation): return interpolation } } + + public func encode( + _ value: Value + ) -> String { + interpolation.encode(value) + } } // MARK: - ExpressibleByStringLiteral diff --git a/Sources/Deeplink/DeeplinkInterpolation.swift b/Sources/Deeplink/DeeplinkInterpolation.swift index d68c8fc..7dd1b4e 100644 --- a/Sources/Deeplink/DeeplinkInterpolation.swift +++ b/Sources/Deeplink/DeeplinkInterpolation.swift @@ -69,6 +69,17 @@ public struct DeeplinkInterpolation: Equatable, Hashable, StringInterpola case .argumentList: return "{{ argument list }}" } } + + func encode(value: Value) -> String { + switch self { + case let .literal(v): + return v + case let .argument(v): + return value[keyPath: v] ?? "" + case let .argumentList(v, separator: character): + return value[keyPath: v]?.joined(separator: String(character)) ?? "" + } + } } // MARK: - Properties @@ -206,6 +217,14 @@ public struct DeeplinkInterpolation: Equatable, Hashable, StringInterpola // Use the url data to pattern match the deeplink components. try data.match(components: self.components, into: &instance) } + + func encode( + _ value: Value + ) -> String { + self.components.map({ + $0.encode(value: value) + }).joined() + } } // MARK: - CustomStringConvertible diff --git a/Tests/DeeplinkTests/EncodingDeeplinkTests.swift b/Tests/DeeplinkTests/EncodingDeeplinkTests.swift new file mode 100644 index 0000000..c8f86b2 --- /dev/null +++ b/Tests/DeeplinkTests/EncodingDeeplinkTests.swift @@ -0,0 +1,107 @@ +// +// EncodingDeeplinkTests.swift +// +// +// Created by Dmitry Lobanov on 28.01.2024. +// + +import Foundation +import XCTest +@testable import Deeplink + +@MainActor +class EncodingDeeplinkTests: XCTestCase { + + struct Artist: Equatable { + var id: String? + var slug: String? + } + + struct Event: Equatable { + var id: String? + var slug: String? + } + + struct EventType: Equatable { + var id: String? + var slug: String? + var event = Event() + } + + struct Search: Equatable { + var query: String? + } + + struct CustomData: Equatable { + var testData: Int? + + var testDataString: String? { + get { testData.map { "\($0)" } } + set { testData = newValue.flatMap(Int.init) } + } + } + + struct Restaurants: Equatable { + var ids: [String]? + } + + func testEncoding_Artist() { + let deeplink = try! "/artist/\(\.slug)/\(\.id)" as Deeplink + + let url = "/artist/123/1" + + var object = Artist() + object.slug = "123" + object.id = "1" + XCTAssertEqual(url, deeplink.encode(object)) + } + + func testEncoding_EventType() { + let deeplink = try! "/event/\(\.event.slug)/\(\.slug)/\(\.event.id)/\(\.id)" as Deeplink + + let url = "/event/food/restaurants/123/1" + + var object = EventType() + var event = Event() + + event.slug = "food" + object.slug = "restaurants" + event.id = "123" + object.id = "1" + object.event = event + + XCTAssertEqual(url, deeplink.encode(object)) + } + + func testEncoding_Search() { + let deeplink = try! "/search?query=\(\.query)" as Deeplink + + let url = "/search?query=food" + + var object = Search() + object.query = "food" + XCTAssertEqual(url, deeplink.encode(object)) + } + + func testEncoding_CustomData() { + let deeplink = try! "/test/\(\.testDataString)" as Deeplink + + let url = "/test/123" + + var object = CustomData() + object.testData = 123 + + XCTAssertEqual(url, deeplink.encode(object)) + } + + func testEncoding_Restaurants() { + let deeplink = try! "/restaurants/ids=\(\.ids, separator: ",")" as Deeplink + + let url = "/restaurants/ids=123,456,789" + + var object = Restaurants() + object.ids = ["123", "456", "789"] + + XCTAssertEqual(url, deeplink.encode(object)) + } +}