Skip to content

Commit

Permalink
- Throw error instead of returning nil in NavigationRoutes.
Browse files Browse the repository at this point in the history
- Fix where we test for Self in makeRoute.
- Add tests for `Routable` logic.
- Add documentation.
  • Loading branch information
boscojwho committed Sep 26, 2023
1 parent 3840110 commit 4da024b
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 8 deletions.
12 changes: 12 additions & 0 deletions Mlem.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@
E4D4DBA22A7F233200C4F3DE /* FancyTabNavigationSelectionHashValueEnvironmentKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4D4DBA12A7F233200C4F3DE /* FancyTabNavigationSelectionHashValueEnvironmentKey.swift */; };
E4DDB4322A81819300B3A7E0 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DDB4312A81819300B3A7E0 /* Double.swift */; };
E4DDB4342A819C8000B3A7E0 /* QuickLookView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DDB4332A819C8000B3A7E0 /* QuickLookView.swift */; };
E4F0B5722AC2581800BC3E4A /* RoutableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F0B5712AC2581800BC3E4A /* RoutableTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -881,6 +882,7 @@
E4D4DBA12A7F233200C4F3DE /* FancyTabNavigationSelectionHashValueEnvironmentKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FancyTabNavigationSelectionHashValueEnvironmentKey.swift; sourceTree = "<group>"; };
E4DDB4312A81819300B3A7E0 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = "<group>"; };
E4DDB4332A819C8000B3A7E0 /* QuickLookView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickLookView.swift; sourceTree = "<group>"; };
E4F0B5712AC2581800BC3E4A /* RoutableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutableTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -1507,6 +1509,7 @@
isa = PBXGroup;
children = (
504ECBAF2AB4B0DF006C0B96 /* Model */,
E4F0B5702AC257FD00BC3E4A /* Navigation */,
50CC4A802AA0D5F90074C845 /* Parsers */,
50CC4A7B2A9CFF840074C845 /* Supporting Files */,
50BC1AB72A89741000E3C48B /* Community List */,
Expand Down Expand Up @@ -2291,6 +2294,14 @@
path = Animations;
sourceTree = "<group>";
};
E4F0B5702AC257FD00BC3E4A /* Navigation */ = {
isa = PBXGroup;
children = (
E4F0B5712AC2581800BC3E4A /* RoutableTests.swift */,
);
path = Navigation;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -2882,6 +2893,7 @@
031BF9552AB25AFB00F4517F /* SiteVersionTests.swift in Sources */,
50CC4A782A9CBDF70074C845 /* TimestampedValueTests.swift in Sources */,
50CC4A822AA0D61F0074C845 /* InstanceMetadataParserTests.swift in Sources */,
E4F0B5722AC2581800BC3E4A /* RoutableTests.swift in Sources */,
50C86ABC2A7E50E200277519 /* PersistenceRepositoryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
2 changes: 1 addition & 1 deletion Mlem/Navigation/Routable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation
/// Conforming types can be added to a `NavigationRouter`'s path.
protocol Routable: Hashable {

/// - Parameter value: A data type for a given navigation destination.
/// - Parameter value: A data type for a given navigation destination. This value could be (but not limited to) some raw data, a view model, or an enum case (representing a route on a navigation path).
/// - Returns: `nil` if data value cannot be mapped to a navigation route.
static func makeRoute<V>(_ value: V) throws -> Self where V: Hashable

Expand Down
8 changes: 5 additions & 3 deletions Mlem/Navigation/Route/NavigationRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ enum NavigationRoute: Routable {
case userModeratorLink(UserModeratorLink)

// swiftlint:disable cyclomatic_complexity
static func makeRoute<V>(_ value: V) -> NavigationRoute? where V: Hashable {
static func makeRoute<V>(_ value: V) throws -> NavigationRoute where V: Hashable {
switch value {
case let value as APICommunityView:
return .apiCommunityView(value)
Expand All @@ -49,9 +49,11 @@ enum NavigationRoute: Routable {
return .lazyLoadPostLinkWithContext(value)
case let value as UserModeratorLink:
return .userModeratorLink(value)
case let value as Self:
/// Value is an enum case of type `Self` with either no associated value or pre-populated associated value.
return value
default:
print(Self.makeRouteErrorString)
return nil
throw RoutableError.routeNotConfigured(value: value)
}
}
// swiftlint:enable cyclomatic_complexity
Expand Down
10 changes: 6 additions & 4 deletions Mlem/Navigation/Route/SettingsRoutes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ enum SettingsRoute: Routable {

static func makeRoute<V>(_ value: V) throws -> SettingsRoute where V: Hashable {
switch value {
case let value as Self:
return value
case let value as AboutSettingsRoute:
return try .aboutPage(AboutSettingsRoute.makeRoute(value))
case let value as AppearanceSettingsRoute:
Expand All @@ -36,6 +34,9 @@ enum SettingsRoute: Routable {
return try .postPage(PostSettingsRoute.makeRoute(value))
case let value as LicensesSettingsRoute:
return try .licensesPage(LicensesSettingsRoute.makeRoute(value))
case let value as Self:
/// Value is an enum case of type `Self` with either no associated value or pre-populated associated value.
return value
default:
throw RoutableError.routeNotConfigured(value: value)
}
Expand Down Expand Up @@ -68,11 +69,12 @@ enum AboutSettingsRoute: Routable {

static func makeRoute<V>(_ value: V) throws -> AboutSettingsRoute where V: Hashable {
switch value {
case let value as Self:
return value
case let value as Document:
// return .privacyPolicy(value)
return .eula(value)
case let value as Self:
/// Value is an enum case of type `Self` with either no associated value or pre-populated associated value.
return value
default:
throw RoutableError.routeNotConfigured(value: value)
}
Expand Down
96 changes: 96 additions & 0 deletions MlemTests/Navigation/RoutableTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// RoutableTests.swift
// MlemTests
//
// Created by Bosco Ho on 2023-09-25.
//

@testable import Mlem
import XCTest

final class RoutableTests: XCTestCase {

private enum MockRoute: Routable {
case routeA
case routeB(Int)
case routeC(MockNestedRoute)
}

private enum MockNestedRoute: Routable {
case route1(Bool)
}

// MARK: - MockRoute

func testMockRoute_handlesNoAssociatedValueEnumCase() throws {
let value = MockRoute.routeA
let route = try MockRoute.makeRoute(value)
XCTAssert(route == value)
}

func testMockRoute_handlesNonNestedAssociatedValueEnumCase() throws {
let data = 1
let value = MockRoute.routeB(data)
let route = try MockRoute.makeRoute(value)
XCTAssert(route == value)
}

func testMockRoute_handlesNestedAssociatedValueEnumCase() throws {
let data = true
let value = MockRoute.routeC(.route1(data))
let route = try MockRoute.makeRoute(value)
XCTAssert(route == value)
}

func testMockRoute_handlesUnsupportedValue() throws {
let value = "Mock Unsupported Value"
XCTAssertThrowsError(try MockRoute.makeRoute(value))
}

func testMockRoute_handlesNestedUnsupportedValue() throws {
let data = "Mock Unsupported Value"
XCTAssertThrowsError(try MockRoute.routeC(.makeRoute(data)))
}

// MARK: - NavigationRoutes

/// Passing in raw data value should return a valid route.
/// Assert `(Data) –> Route`.
func testNavigationRouteHandlesDataValue() throws {
let value = CommunityLinkWithContext(community: nil, feedType: .all)
let route = try NavigationRoute.makeRoute(value)
XCTAssert(route == .communityLinkWithContext(value))
}

/// Passing in a route enum with an associated value should return the passed in value.
func testNavigationRouteHandlesNonNestedAssociatedValueEnumCase() throws {
let data = CommunityLinkWithContext(community: nil, feedType: .all)
let value = NavigationRoute.communityLinkWithContext(data)
let route = try NavigationRoute.makeRoute(value)
XCTAssert(route == value)
}

// MARK: - SettingsRoutes

/// Passing in a route enum with no associated value should return the passed in value.
func testSettingsRouteHandlesNoAssociatedValueEnumCase() throws {
let value = SettingsRoute.general
let route = try SettingsRoute.makeRoute(value)
XCTAssert(route == value)
}

/// Passing in a route enum with an associated value should return the passed in value.
func testSettingsRouteHandlesNonNestedAssociatedValueEnumCase() throws {
let value = SettingsRoute.aboutPage(.contributors)
let route = try SettingsRoute.makeRoute(value)
XCTAssert(route == value)
}

/// Passing in a route enum with an associated value that also has an associated value should return the passed in value.
func testSettingsRouteHandlesNestedAssociatedValueEnumCase() throws {
let nestedValue = Document(body: "Mock EULA")
let value = SettingsRoute.aboutPage(.eula(nestedValue))
let route = try SettingsRoute.makeRoute(value)
XCTAssert(route == value)
}
}

0 comments on commit 4da024b

Please sign in to comment.