Skip to content

Commit 36dd6d2

Browse files
committed
🚨 Improve tests and code coverage
1 parent 2b3a99e commit 36dd6d2

File tree

5 files changed

+208
-21
lines changed

5 files changed

+208
-21
lines changed

‎JavaScriptKit.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
5530C2FE1F5D8429005A97C9 /* SingleValueDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5530C2FC1F5D8429005A97C9 /* SingleValueDecodingTests.swift */; };
2424
5530C3001F5DAC73005A97C9 /* KeyedEncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5530C2FF1F5DAC73005A97C9 /* KeyedEncodingTests.swift */; };
2525
5530C3011F5DAC73005A97C9 /* KeyedEncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5530C2FF1F5DAC73005A97C9 /* KeyedEncodingTests.swift */; };
26+
5538FC781F6F10280039AFD2 /* CodableSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5538FC771F6F10280039AFD2 /* CodableSupportTests.swift */; };
27+
5538FC791F6F10280039AFD2 /* CodableSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5538FC771F6F10280039AFD2 /* CodableSupportTests.swift */; };
2628
5543E4931F5736D80057E28B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5543E4911F5736BF0057E28B /* Result.framework */; };
2729
5543E4951F5736E50057E28B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5543E4941F5736E50057E28B /* Result.framework */; };
2830
5543E4961F5737370057E28B /* JavaScriptKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 556E88E71F556EF70031476D /* JavaScriptKit.framework */; };
@@ -114,6 +116,7 @@
114116
551B2F6C1F5A9466009AE800 /* JavaScriptDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptDecoder.swift; sourceTree = "<group>"; };
115117
5530C2FC1F5D8429005A97C9 /* SingleValueDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleValueDecodingTests.swift; sourceTree = "<group>"; };
116118
5530C2FF1F5DAC73005A97C9 /* KeyedEncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyedEncodingTests.swift; sourceTree = "<group>"; };
119+
5538FC771F6F10280039AFD2 /* CodableSupportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableSupportTests.swift; sourceTree = "<group>"; };
117120
5543E48A1F57336D0057E28B /* JavaScriptKit.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = JavaScriptKit.podspec; sourceTree = "<group>"; };
118121
5543E48B1F57336D0057E28B /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
119122
5543E48C1F57336D0057E28B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
@@ -311,6 +314,7 @@
311314
children = (
312315
5513C3671F6E71B700030A30 /* TestsSupport.swift */,
313316
55C410B71F5AEF6C008B0B0E /* CodableModels.swift */,
317+
5538FC771F6F10280039AFD2 /* CodableSupportTests.swift */,
314318
556987D61F5C0B4700FC4E07 /* Encoding */,
315319
5530C2FB1F5D8415005A97C9 /* Decoding */,
316320
550F9F2D1F6E93FE00792329 /* Expressions */,
@@ -538,6 +542,7 @@
538542
550F9F321F6E94AA00792329 /* ExpressionModels.swift in Sources */,
539543
550F9F341F6E9C8F00792329 /* ExecutionTests.swift in Sources */,
540544
55C410B91F5AEF6C008B0B0E /* CodableModels.swift in Sources */,
545+
5538FC791F6F10280039AFD2 /* CodableSupportTests.swift in Sources */,
541546
5513C3691F6E71B700030A30 /* TestsSupport.swift in Sources */,
542547
5513C36C1F6E78A000030A30 /* KeyedDecodingTests.swift in Sources */,
543548
5530C2FE1F5D8429005A97C9 /* SingleValueDecodingTests.swift in Sources */,
@@ -572,6 +577,7 @@
572577
550F9F311F6E94AA00792329 /* ExpressionModels.swift in Sources */,
573578
550F9F331F6E9C8F00792329 /* ExecutionTests.swift in Sources */,
574579
55C410B81F5AEF6C008B0B0E /* CodableModels.swift in Sources */,
580+
5538FC781F6F10280039AFD2 /* CodableSupportTests.swift in Sources */,
575581
5513C3681F6E71B700030A30 /* TestsSupport.swift in Sources */,
576582
5513C36B1F6E78A000030A30 /* KeyedDecodingTests.swift in Sources */,
577583
5530C2FD1F5D8429005A97C9 /* SingleValueDecodingTests.swift in Sources */,

‎Sources/Codable/CodableSupport.swift

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,6 @@ enum JSCodingContainer {
1515
/// A keyed value container associated with a reference to a dictionary storage.
1616
case keyed(DictionaryStorage)
1717

18-
/// The type of the container (for debug printing)
19-
var debugType: String {
20-
21-
switch self {
22-
case .singleValue(_):
23-
return "a single value"
24-
case .unkeyed(_):
25-
return "an unkeyed"
26-
case .keyed(_):
27-
return "a keyed"
28-
}
29-
30-
}
31-
3218
}
3319

3420
// MARK: - Single Value Storage
@@ -79,7 +65,16 @@ enum SingleValueStorage {
7965

8066
/// The type of the stored value.
8167
var storedType: Any.Type {
82-
return type(of: storedValue)
68+
69+
switch self {
70+
case .null: return NSNull.self
71+
case .string: return String.self
72+
case .boolean: return Bool.self
73+
case .number: return NSNumber.self
74+
case .date: return Date.self
75+
case .emptyObject: return Dictionary<String, Any>.self
76+
}
77+
8378
}
8479

8580
// MARK: Initialization

‎Sources/Codable/JavaScriptDecoder.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ private class JSStructureDecoder: Decoder {
7171
/// Contextual user-provided information for use during decoding.
7272
var userInfo: [CodingUserInfoKey : Any]
7373

74+
/// The type of the container (for debug printing)
75+
var containerType: String {
76+
77+
switch container {
78+
case .singleValue:
79+
return "a single value"
80+
case .unkeyed:
81+
return "an unkeyed"
82+
case .keyed:
83+
return "a keyed"
84+
}
85+
86+
}
87+
7488
// MARK: Initilization
7589

7690
init(container: JSCodingContainer, codingPath: [CodingKey] = [], userInfo: [CodingUserInfoKey: Any] = [:]) {
@@ -89,7 +103,7 @@ private class JSStructureDecoder: Decoder {
89103
return KeyedDecodingContainer(decodingContainer)
90104

91105
default:
92-
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using a keyed container container, but the data is encoded as a \(container.debugType) container.")
106+
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using a keyed container container, but the data is encoded as \(containerType) container.")
93107
throw DecodingError.dataCorrupted(errorContext)
94108
}
95109

@@ -102,7 +116,7 @@ private class JSStructureDecoder: Decoder {
102116
return JSUnkeyedDecodingContainer(referencing: self, storage: storage)
103117

104118
default:
105-
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using an unkeyed container container, but the data is encoded as a \(container.debugType) container.")
119+
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using an unkeyed container container, but the data is encoded as \(containerType) container.")
106120
throw DecodingError.dataCorrupted(errorContext)
107121
}
108122

@@ -115,7 +129,7 @@ private class JSStructureDecoder: Decoder {
115129
return JSSingleValueDecodingContainer(referencing: self, storage: storage, codingPath: codingPath)
116130

117131
default:
118-
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using a single value container, but the data is encoded as a \(container.debugType) container.")
132+
let errorContext = DecodingError.Context(codingPath: codingPath, debugDescription: "Attempt to decode the result using a single value container, but the data is encoded as \(containerType) container.")
119133
throw DecodingError.dataCorrupted(errorContext)
120134
}
121135

‎Sources/Codable/JavaScriptEncoder.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,22 @@ private class JSStructureEncoder: Encoder {
125125

126126
// MARK: Options
127127

128+
/// The type of the container (for debug printing)
129+
var containerType: String {
130+
131+
switch container {
132+
case .singleValue?:
133+
return "a single value"
134+
case .unkeyed?:
135+
return "an unkeyed"
136+
case .keyed?:
137+
return "a keyed"
138+
case nil:
139+
return "an invalid"
140+
}
141+
142+
}
143+
128144
/// The string literal quoting strategy.
129145
let stringLiteralQuoting: StringLiteralQuoting
130146

@@ -179,8 +195,7 @@ private class JSStructureEncoder: Encoder {
179195
func assertCanRequestNewContainer() {
180196

181197
guard self.container == nil else {
182-
let previousContainerType = self.container!.debugType
183-
preconditionFailure("Attempt to encode value with a new container when it has already been encoded with a \(previousContainerType) container.")
198+
preconditionFailure("Attempt to encode value with a new container when it has already been encoded with \(containerType) container.")
184199
}
185200

186201
guard !containsFailures else {
@@ -246,7 +261,7 @@ extension JSStructureEncoder: SingleValueEncodingContainer {
246261
preconditionFailure("Attempt to encode multiple values in a single value container.")
247262

248263
case .keyed(_)?, .unkeyed(_)?:
249-
preconditionFailure("Attempt to encode value with a new container when it has already been encoded with a \(container!.debugType) container.")
264+
preconditionFailure("Attempt to encode value with a new container when it has already been encoded with \(containerType) container.")
250265

251266
case nil:
252267
return
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import XCTest
2+
import Foundation
3+
@testable import JavaScriptKit
4+
5+
///
6+
/// Tests Codable-supporting data structures and utilities.
7+
///
8+
9+
class CodableSupportTests: XCTestCase {
10+
11+
// MARK: Single Value Storage
12+
13+
/// Tests creating a single value storage.
14+
func testCreateSingleValueStorage() throws {
15+
16+
let nullStorage = try SingleValueStorage(storedValue: NSNull())
17+
18+
switch nullStorage {
19+
case .null:
20+
break
21+
default:
22+
XCTFail("Should create a null storage.")
23+
}
24+
25+
let stringStorage = try SingleValueStorage(storedValue: "Hello")
26+
27+
switch stringStorage {
28+
case .string(let str):
29+
XCTAssertEqual(str, "Hello")
30+
default:
31+
XCTFail("Should create a string storage.")
32+
}
33+
34+
let nsStringStorage = try SingleValueStorage(storedValue: "Hello" as NSString)
35+
36+
switch nsStringStorage {
37+
case .string(let str):
38+
XCTAssertEqual(str, "Hello")
39+
default:
40+
XCTFail("Should create a string storage.")
41+
}
42+
43+
let intStorage = try SingleValueStorage(storedValue: Int(100))
44+
45+
switch intStorage {
46+
case .number(let num):
47+
XCTAssertEqual(num.intValue, 100)
48+
default:
49+
XCTFail("Should create a number storage.")
50+
}
51+
52+
let doubleStorage = try SingleValueStorage(storedValue: Double(100.8765))
53+
54+
switch doubleStorage {
55+
case .number(let num):
56+
XCTAssertEqual(num.doubleValue, 100.8765)
57+
default:
58+
XCTFail("Should create a number storage.")
59+
}
60+
61+
let floatStorage = try SingleValueStorage(storedValue: Float(100.8765))
62+
63+
switch floatStorage {
64+
case .number(let num):
65+
XCTAssertEqual(num.floatValue, 100.8765)
66+
default:
67+
XCTFail("Should create a number storage.")
68+
}
69+
70+
let dateStorage = try SingleValueStorage(storedValue: Date.distantFuture)
71+
72+
switch dateStorage {
73+
case .date(let date):
74+
XCTAssertEqual(date, .distantFuture)
75+
default:
76+
XCTFail("Should create a date storage.")
77+
}
78+
79+
let invalidStorage = try? SingleValueStorage(storedValue: ReaderFont.sanFrancisco)
80+
XCTAssertNil(invalidStorage)
81+
82+
}
83+
84+
/// Tests getting the stored value from a single value storage.
85+
func testGetSingleValueStorageStoredValue() {
86+
87+
let nullStorage = SingleValueStorage.null
88+
XCTAssertTrue(nullStorage.storedValue is NSNull)
89+
90+
let stringStorage = SingleValueStorage.string("Hello")
91+
XCTAssertTrue(stringStorage.storedValue as? String == "Hello")
92+
93+
let boolStorage = SingleValueStorage.boolean(true)
94+
XCTAssertTrue(boolStorage.storedValue as? Bool == true)
95+
96+
let numberStorage = SingleValueStorage.number(100)
97+
XCTAssertTrue(numberStorage.storedValue as? NSNumber == 100)
98+
99+
let dateStorage = SingleValueStorage.date(.distantFuture)
100+
XCTAssertTrue(dateStorage.storedValue as? Date == .distantFuture)
101+
102+
let emptyStorage = SingleValueStorage.emptyObject
103+
XCTAssertTrue((emptyStorage.storedValue as? [String: Any])?.isEmpty == true)
104+
105+
}
106+
107+
/// Tests getting the stored type from a single value storage.
108+
func testGetSingleValueStorageStoredType() {
109+
110+
let nullStorage = SingleValueStorage.null
111+
XCTAssertTrue(nullStorage.storedType == NSNull.self)
112+
113+
let stringStorage = SingleValueStorage.string("Hello")
114+
XCTAssertTrue(stringStorage.storedType == String.self)
115+
116+
let boolStorage = SingleValueStorage.boolean(true)
117+
XCTAssertTrue(boolStorage.storedType == Bool.self)
118+
119+
let numberStorage = SingleValueStorage.number(100)
120+
XCTAssertTrue(numberStorage.storedType == NSNumber.self)
121+
122+
let dateStorage = SingleValueStorage.date(.distantFuture)
123+
XCTAssertTrue(dateStorage.storedType == Date.self)
124+
125+
let emptyStorage = SingleValueStorage.emptyObject
126+
XCTAssertTrue(emptyStorage.storedType == Dictionary<String, Any>.self)
127+
128+
}
129+
130+
// MARK: - JSONKey
131+
132+
/// Tests internal JSON keys.
133+
func testJSONKey() {
134+
135+
let superKey = JSONKey.super
136+
XCTAssertEqual(superKey.stringValue, "super")
137+
XCTAssertNil(superKey.intValue)
138+
139+
let stringKey = JSONKey.string("foo")
140+
XCTAssertEqual(stringKey.stringValue, "foo")
141+
XCTAssertNil(stringKey.intValue)
142+
143+
let indexKey = JSONKey.index(10)
144+
XCTAssertEqual(indexKey.stringValue, "Index 10")
145+
XCTAssertTrue(indexKey.intValue == 10)
146+
147+
let barKey = JSONKey(stringValue: "bar")
148+
XCTAssertEqual(barKey.stringValue, "bar")
149+
XCTAssertNil(barKey.intValue)
150+
151+
let startIndexKey = JSONKey(intValue: 0)
152+
XCTAssertEqual(startIndexKey.stringValue, "Index 0")
153+
XCTAssertTrue(startIndexKey.intValue == 0)
154+
155+
}
156+
157+
}

0 commit comments

Comments
 (0)