From 74fd0b4664cfd383617160d26f9700c8557a97db Mon Sep 17 00:00:00 2001 From: Soumya Ranjan Mahunt Date: Tue, 24 May 2022 19:12:54 +0530 Subject: [PATCH] test: add tests for dynamic JSON decoding with user context provider --- .../Guides/ContainerCodingKey.md | 2 + .../DynamicDecodingWrapper.swift | 10 ---- .../Models/PostPage.swift | 42 ++++++++++++++++ ...cDecodingCollectionDictionaryWrapper.swift | 15 ------ .../DynamicDecodingDictionaryWrapper.swift | 10 ---- .../Models/PostContainer.swift | 27 ++++++++++ .../Models/PostPath.swift | 49 +++++++++++++++++++ .../PathCodingKeyWrapper.swift | 47 ------------------ ...ecodingCollectionContextBasedWrapper.swift | 40 +++++++++++++++ .../DynamicDecodingContextBasedWrapper.swift | 39 +++++++++++++++ .../Models/ProviderPost.swift | 36 ++++++++++++++ .../Models/HashablePost.swift | 15 ------ .../DynamicCodableKitTests/Models/Post.swift | 15 ------ 13 files changed, 235 insertions(+), 112 deletions(-) create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/Models/PostPage.swift create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostContainer.swift create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostPath.swift create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingCollectionContextBasedWrapper.swift create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingContextBasedWrapper.swift create mode 100644 Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/Models/ProviderPost.swift diff --git a/Sources/DynamicCodableKit/DynamicCodableKit.docc/Guides/ContainerCodingKey.md b/Sources/DynamicCodableKit/DynamicCodableKit.docc/Guides/ContainerCodingKey.md index d056c64b..f2083841 100644 --- a/Sources/DynamicCodableKit/DynamicCodableKit.docc/Guides/ContainerCodingKey.md +++ b/Sources/DynamicCodableKit/DynamicCodableKit.docc/Guides/ContainerCodingKey.md @@ -112,7 +112,9 @@ struct PostPage: Decodable { ### Type Aliases - ``StrictDynamicDecodingArrayDictionaryWrapper`` +- ``DefaultValueDynamicDecodingArrayDictionaryWrapper`` - ``LossyDynamicDecodingArrayDictionaryWrapper`` - ``StrictDynamicDecodingCollectionDictionaryWrapper`` +- ``DefaultValueDynamicDecodingCollectionDictionaryWrapper`` - ``LossyDynamicDecodingCollectionDictionaryWrapper`` - ``OptionalPathCodingKeyWrapper`` diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/DynamicDecodingWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/DynamicDecodingWrapper.swift index cd0da6ad..8ac93886 100644 --- a/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/DynamicDecodingWrapper.swift +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/DynamicDecodingWrapper.swift @@ -35,13 +35,3 @@ final class DynamicDecodingWrapperTests: XCTestCase { XCTAssertNil(postPage.content) } } - -struct SinglePostPage: Decodable { - let next: URL - @DynamicDecodingWrapper var content: Post -} - -struct OptionalSinglePostPage: Decodable { - let next: URL - @OptionalDynamicDecodingWrapper var content: Post? -} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/Models/PostPage.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/Models/PostPage.swift new file mode 100644 index 00000000..65e6e0c5 --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextCodingKey/Models/PostPage.swift @@ -0,0 +1,42 @@ +import XCTest +@testable import DynamicCodableKit + +struct SinglePostPage: Decodable { + let next: URL + @DynamicDecodingWrapper var content: Post +} + +struct OptionalSinglePostPage: Decodable { + let next: URL + @OptionalDynamicDecodingWrapper var content: Post? +} + +struct ThrowingPostPage: Decodable { + let next: URL + @StrictDynamicDecodingArrayWrapper var content: [Post] +} + +struct DefaultPostPage: Decodable { + let next: URL + @DefaultValueDynamicDecodingArrayWrapper var content: [Post] +} + +struct LossyPostPage: Decodable { + let next: URL + @LossyDynamicDecodingArrayWrapper var content: [Post] +} + +struct ThrowingPostPageSet: Decodable { + let next: URL + @StrictDynamicDecodingCollectionWrapper>> var content: Set> +} + +struct DefaultPostPageSet: Decodable { + let next: URL + @DefaultValueDynamicDecodingCollectionWrapper>> var content: Set> +} + +struct LossyPostPageSet: Decodable { + let next: URL + @LossyDynamicDecodingCollectionWrapper>> var content: Set> +} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingCollectionDictionaryWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingCollectionDictionaryWrapper.swift index ee7427ec..6403b42a 100644 --- a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingCollectionDictionaryWrapper.swift +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingCollectionDictionaryWrapper.swift @@ -50,18 +50,3 @@ final class DynamicDecodingCollectionDictionaryWrapperTests: XCTestCase { } } } - -struct ThrowingKeyedPostPageCollection: Decodable { - let next: URL - @StrictDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] -} - -struct DefaultValueKeyedPostPageCollection: Decodable { - let next: URL - @DefaultValueDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] -} - -struct LossyKeyedPostPageCollection: Decodable { - let next: URL - @LossyDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] -} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingDictionaryWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingDictionaryWrapper.swift index cafa111b..2b93082f 100644 --- a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingDictionaryWrapper.swift +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/DynamicDecodingDictionaryWrapper.swift @@ -29,13 +29,3 @@ final class DynamicDecodingDictionaryWrapperTests: XCTestCase { postPage.content.forEach { XCTAssertEqual($1.type, $0) } } } - -struct ThrowingKeyedPostPage: Decodable { - let next: URL - @StrictDynamicDecodingDictionaryWrapper var content: [PostType: Post] -} - -struct LossyKeyedPostPage: Decodable { - let next: URL - @LossyDynamicDecodingDictionaryWrapper var content: [PostType: Post] -} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostContainer.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostContainer.swift new file mode 100644 index 00000000..62cc3c3d --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostContainer.swift @@ -0,0 +1,27 @@ +import XCTest +@testable import DynamicCodableKit + +struct ThrowingKeyedPostPage: Decodable { + let next: URL + @StrictDynamicDecodingDictionaryWrapper var content: [PostType: Post] +} + +struct LossyKeyedPostPage: Decodable { + let next: URL + @LossyDynamicDecodingDictionaryWrapper var content: [PostType: Post] +} + +struct ThrowingKeyedPostPageCollection: Decodable { + let next: URL + @StrictDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] +} + +struct DefaultValueKeyedPostPageCollection: Decodable { + let next: URL + @DefaultValueDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] +} + +struct LossyKeyedPostPageCollection: Decodable { + let next: URL + @LossyDynamicDecodingArrayDictionaryWrapper var content: [PostType: [Post]] +} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostPath.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostPath.swift new file mode 100644 index 00000000..aa81581c --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/Models/PostPath.swift @@ -0,0 +1,49 @@ +import XCTest +@testable import DynamicCodableKit + +struct CommonPost: Decodable { + let id: UUID + let author: UUID + let likes: Int + let createdAt: String + @PathCodingKeyWrapper var type: PostType +} + +struct OptionalTypeCommonPost: Decodable { + let id: UUID + let author: UUID + let likes: Int + let createdAt: String + @OptionalPathCodingKeyWrapper var type: PostType? +} + +struct CommonPostPage: Decodable { + let next: URL + @PostData var content: [PostType: [CommonPost]] +} + +struct ThrowingCommonPostPage: Decodable { + let next: URL + var content: [String: [CommonPost]] +} + +struct OptionalTypeCommonPostPage: Decodable { + let next: URL + var content: [String: [OptionalTypeCommonPost]] +} + +@propertyWrapper +struct PostData: Decodable { + public var wrappedValue: [PostType: [CommonPost]] + + public init(wrappedValue: [PostType: [CommonPost]]) { + self.wrappedValue = wrappedValue + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: PostType.self) + self.wrappedValue = try container.allKeys.reduce(into: [:], { values, key in + values[key] = try container.decode([CommonPost].self, forKey: key) + }) + } +} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/PathCodingKeyWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/PathCodingKeyWrapper.swift index dd81c610..6c9543aa 100644 --- a/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/PathCodingKeyWrapper.swift +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextContainerCodingKey/PathCodingKeyWrapper.swift @@ -33,50 +33,3 @@ final class PathCodingKeyWrapperTests: XCTestCase { } } } - -struct CommonPost: Decodable { - let id: UUID - let author: UUID - let likes: Int - let createdAt: String - @PathCodingKeyWrapper var type: PostType -} - -struct OptionalTypeCommonPost: Decodable { - let id: UUID - let author: UUID - let likes: Int - let createdAt: String - @OptionalPathCodingKeyWrapper var type: PostType? -} - -struct CommonPostPage: Decodable { - let next: URL - @PostData var content: [PostType: [CommonPost]] -} - -struct ThrowingCommonPostPage: Decodable { - let next: URL - var content: [String: [CommonPost]] -} - -struct OptionalTypeCommonPostPage: Decodable { - let next: URL - var content: [String: [OptionalTypeCommonPost]] -} - -@propertyWrapper -struct PostData: Decodable { - public var wrappedValue: [PostType: [CommonPost]] - - public init(wrappedValue: [PostType: [CommonPost]]) { - self.wrappedValue = wrappedValue - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: PostType.self) - self.wrappedValue = try container.allKeys.reduce(into: [:], { values, key in - values[key] = try container.decode([CommonPost].self, forKey: key) - }) - } -} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingCollectionContextBasedWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingCollectionContextBasedWrapper.swift new file mode 100644 index 00000000..95fb7fce --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingCollectionContextBasedWrapper.swift @@ -0,0 +1,40 @@ +import XCTest +@testable import DynamicCodableKit + +final class DynamicDecodingCollectionContextBasedWrapperTests: XCTestCase { + func testDecoding() throws { + let url = Bundle.module.url(forResource: "identifier-collection-decode", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + decoder.userInfo[.postKey] = DynamicDecodingContext(withKey: PostCodingKey.self) + let postPage = try decoder.decode(ProviderBasedThrowingPostPage.self, from: data) + XCTAssertEqual(postPage.content.count, 4) + XCTAssertEqual(postPage.content.map(\.type), [.text, .picture, .audio, .video]) + } + + func testInvalidDataDecodingWithThrowConfig() throws { + let url = Bundle.module.url(forResource: "identifier-collection-decode-with-invalid-data", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + XCTAssertThrowsError(try decoder.decode(ProviderBasedThrowingPostPage.self, from: data)) + } + + func testInvalidDataDecodingWithDefaultConfig() throws { + let url = Bundle.module.url(forResource: "identifier-collection-decode-with-invalid-data", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + decoder.userInfo[.postKey] = DynamicDecodingContext(withKey: PostCodingKey.self) + let postPage = try decoder.decode(ProviderBasedDefaultPostPage.self, from: data) + XCTAssertEqual(postPage.content.count, 0) + } + + func testInvalidDataDecodingWithLossyConfig() throws { + let url = Bundle.module.url(forResource: "identifier-collection-decode-with-invalid-data", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + decoder.userInfo[.postKey] = DynamicDecodingContext(withKey: PostCodingKey.self) + let postPage = try decoder.decode(ProviderBasedLossyPostPage.self, from: data) + XCTAssertEqual(postPage.content.count, 4) + XCTAssertEqual(postPage.content.map(\.type), [.text, .picture, .audio, .video]) + } +} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingContextBasedWrapper.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingContextBasedWrapper.swift new file mode 100644 index 00000000..2405f23b --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/DynamicDecodingContextBasedWrapper.swift @@ -0,0 +1,39 @@ +import XCTest +@testable import DynamicCodableKit + +final class DynamicDecodingContextBasedWrapperTests: XCTestCase { + func testDecoding() throws { + let url = Bundle.module.url(forResource: "identifier-decode", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + decoder.userInfo[.postKey] = DynamicDecodingContext(decoding: VideoPost.self) + let postPage = try decoder.decode(ProviderBasedSinglePostPage.self, from: data) + XCTAssertEqual(postPage.content.type, .video) + XCTAssertEqual(postPage.content.likes, 2345) + } + + func testOptionalDecoding() throws { + let url = Bundle.module.url(forResource: "identifier-decode", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + decoder.userInfo[.postKey] = DynamicDecodingContext(decoding: VideoPost.self) + let postPage = try decoder.decode(ProviderBasedOptionalSinglePostPage.self, from: data) + XCTAssertEqual(postPage.content?.type, .video) + XCTAssertEqual(postPage.content?.likes, 2345) + } + + func testInvalidDataDecodingWithThrowConfig() throws { + let url = Bundle.module.url(forResource: "identifier-decode-with-invalid-data", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + XCTAssertThrowsError(try decoder.decode(ProviderBasedSinglePostPage.self, from: data)) + } + + func testInvalidDataDecodingWithDefaultConfig() throws { + let url = Bundle.module.url(forResource: "identifier-decode-with-invalid-data", withExtension: "json")! + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + let postPage = try decoder.decode(ProviderBasedOptionalSinglePostPage.self, from: data) + XCTAssertNil(postPage.content) + } +} diff --git a/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/Models/ProviderPost.swift b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/Models/ProviderPost.swift new file mode 100644 index 00000000..b2502cf6 --- /dev/null +++ b/Tests/DynamicCodableKitTests/DynamicDecodingContextProvider/Models/ProviderPost.swift @@ -0,0 +1,36 @@ +import XCTest +@testable import DynamicCodableKit + +extension CodingUserInfoKey { + static let postKey = CodingUserInfoKey(rawValue: "post_key")! +} + +struct PostDecodingProvider: UserInfoDynamicDecodingContextProvider { + typealias Identified = Post + static var infoKey: CodingUserInfoKey { .postKey } +} + +struct ProviderBasedSinglePostPage: Decodable { + let next: URL + @DynamicDecodingContextBasedWrapper var content: Post +} + +struct ProviderBasedOptionalSinglePostPage: Decodable { + let next: URL + @OptionalDynamicDecodingContextBasedWrapper var content: Post? +} + +struct ProviderBasedThrowingPostPage: Decodable { + let next: URL + @StrictDynamicDecodingArrayContextBasedWrapper var content: [Post] +} + +struct ProviderBasedDefaultPostPage: Decodable { + let next: URL + @DefaultValueDynamicDecodingArrayContextBasedWrapper var content: [Post] +} + +struct ProviderBasedLossyPostPage: Decodable { + let next: URL + @LossyDynamicDecodingArrayContextBasedWrapper var content: [Post] +} diff --git a/Tests/DynamicCodableKitTests/Models/HashablePost.swift b/Tests/DynamicCodableKitTests/Models/HashablePost.swift index cc43d9a5..03d2a36a 100644 --- a/Tests/DynamicCodableKitTests/Models/HashablePost.swift +++ b/Tests/DynamicCodableKitTests/Models/HashablePost.swift @@ -64,18 +64,3 @@ enum PostSetCodingKey: String, DynamicDecodingContextIdentifierCodingKey { case type static var identifierCodingKey: Self { .type } } - -struct ThrowingPostPageSet: Decodable { - let next: URL - @StrictDynamicDecodingCollectionWrapper>> var content: Set> -} - -struct DefaultPostPageSet: Decodable { - let next: URL - @DefaultValueDynamicDecodingCollectionWrapper>> var content: Set> -} - -struct LossyPostPageSet: Decodable { - let next: URL - @LossyDynamicDecodingCollectionWrapper>> var content: Set> -} diff --git a/Tests/DynamicCodableKitTests/Models/Post.swift b/Tests/DynamicCodableKitTests/Models/Post.swift index 23eb46f0..7255d640 100644 --- a/Tests/DynamicCodableKitTests/Models/Post.swift +++ b/Tests/DynamicCodableKitTests/Models/Post.swift @@ -75,18 +75,3 @@ enum PostCodingKey: String, DynamicDecodingContextIdentifierCodingKey { case type static var identifierCodingKey: Self { .type } } - -struct ThrowingPostPage: Decodable { - let next: URL - @StrictDynamicDecodingArrayWrapper var content: [Post] -} - -struct DefaultPostPage: Decodable { - let next: URL - @DefaultValueDynamicDecodingArrayWrapper var content: [Post] -} - -struct LossyPostPage: Decodable { - let next: URL - @LossyDynamicDecodingArrayWrapper var content: [Post] -}