Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ import NullCodableTests

var tests = [XCTestCaseEntry]()
tests += NullCodableTests.allTests()
tests += NullCodablePropertyWrapperTests.allTests()
tests += NullCodableJSONEncoderTests.allTests()
tests += NullCodableJSONDecoderTests.allTests()
tests += NullCodableComplexStructTests.allTests()
tests += NullCodableEquatableTests.allTests()
tests += NullCodableSendableTests.allTests()
XCTMain(tests)
119 changes: 119 additions & 0 deletions Tests/NullCodableTests/NullCodableComplexStructTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import Foundation
import XCTest
@testable import NullCodable

final class NullCodableComplexStructTests: XCTestCase {

private struct Address: Codable, Equatable {
let street: String
let city: String
let country: String
}

private struct LineItem: Codable, Equatable {
let name: String
let quantity: Int
let price: Decimal
}

private struct Customer: Codable, Equatable {
let name: String
@NullCodable var email: String?
let address: Address
}

private struct Order: Codable, Equatable {
let id: String
let customer: Customer
let items: [LineItem]
@NullCodable var notes: [String]?
@NullCodable var discount: Decimal?
}

func test_encodesComplexStructToJSON() throws {
let order = Order(
id: "order-123",
customer: Customer(
name: "Ada Lovelace",
email: nil,
address: Address(
street: "1 Analytical Engine Way",
city: "London",
country: "United Kingdom"
)
),
items: [
LineItem(name: "Notebook", quantity: 2, price: 12.50),
LineItem(name: "Pen", quantity: 1, price: 3.25),
],
notes: nil,
discount: 5
)

let data = try JSONEncoder().encode(order)
let actual = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? NSDictionary)
let expected = try XCTUnwrap(JSONSerialization.jsonObject(with: Data("""
{
"id": "order-123",
"customer": {
"name": "Ada Lovelace",
"email": null,
"address": {
"street": "1 Analytical Engine Way",
"city": "London",
"country": "United Kingdom"
}
},
"items": [
{ "name": "Notebook", "quantity": 2, "price": 12.5 },
{ "name": "Pen", "quantity": 1, "price": 3.25 }
],
"notes": null,
"discount": 5
}
""".utf8)) as? NSDictionary)

XCTAssertTrue(actual.isEqual(expected))
}

func test_decodesComplexStructFromJSON() throws {
let json = """
{
"id": "order-123",
"customer": {
"name": "Ada Lovelace",
"email": "ada@example.com",
"address": {
"street": "1 Analytical Engine Way",
"city": "London",
"country": "United Kingdom"
}
},
"items": [
{ "name": "Notebook", "quantity": 2, "price": 12.5 },
{ "name": "Pen", "quantity": 1, "price": 3.25 }
],
"notes": ["Gift wrap"],
"discount": null
}
"""

let order = try JSONDecoder().decode(Order.self, from: Data(json.utf8))

XCTAssertEqual(order.id, "order-123")
XCTAssertEqual(order.customer.name, "Ada Lovelace")
XCTAssertEqual(order.customer.email, "ada@example.com")
XCTAssertEqual(order.customer.address.city, "London")
XCTAssertEqual(order.items, [
LineItem(name: "Notebook", quantity: 2, price: 12.5),
LineItem(name: "Pen", quantity: 1, price: 3.25),
])
XCTAssertEqual(order.notes, ["Gift wrap"])
XCTAssertNil(order.discount)
}

static let allTests = [
("test_encodesComplexStructToJSON", test_encodesComplexStructToJSON),
("test_decodesComplexStructFromJSON", test_decodesComplexStructFromJSON),
]
}
28 changes: 28 additions & 0 deletions Tests/NullCodableTests/NullCodableEquatableTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import XCTest
@testable import NullCodable

final class NullCodableEquatableTests: XCTestCase {

func test_comparesWrappedValues() {
XCTAssertEqual(
NullCodable(wrappedValue: "value"),
NullCodable(wrappedValue: "value")
)
XCTAssertEqual(
NullCodable<String>(wrappedValue: nil),
NullCodable<String>(wrappedValue: nil)
)
XCTAssertNotEqual(
NullCodable(wrappedValue: "first"),
NullCodable(wrappedValue: "second")
)
XCTAssertNotEqual(
NullCodable<String>(wrappedValue: nil),
NullCodable(wrappedValue: "value")
)
}

static let allTests = [
("test_comparesWrappedValues", test_comparesWrappedValues),
]
}
53 changes: 53 additions & 0 deletions Tests/NullCodableTests/NullCodableJSONDecoderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import XCTest
@testable import NullCodable

final class NullCodableJSONDecoderTests: XCTestCase {

func test_decodesJSONNullAsNil() throws {
let value = try JSONDecoder().decode(
NullCodable<String>.self,
from: Data("null".utf8)
)

XCTAssertNil(value.wrappedValue)
}

func test_decodesWrappedValue() throws {
let value = try JSONDecoder().decode(
NullCodable<Int>.self,
from: Data("42".utf8)
)

XCTAssertEqual(value.wrappedValue, 42)
}

func test_decodesInvalidWrappedValueWithAnError() {
XCTAssertThrowsError(
try JSONDecoder().decode(
NullCodable<Int>.self,
from: Data("\"not an integer\"".utf8)
)
) { error in
XCTAssertTrue(error is DecodingError)
}
}

func test_supportsCollectionValues() throws {
let value = NullCodable(wrappedValue: ["one", "two"])

let data = try JSONEncoder().encode(value)
let decoded = try JSONDecoder().decode(
NullCodable<[String]>.self,
from: data
)

XCTAssertEqual(decoded.wrappedValue, ["one", "two"])
}

static let allTests = [
("test_decodesJSONNullAsNil", test_decodesJSONNullAsNil),
("test_decodesWrappedValue", test_decodesWrappedValue),
("test_decodesInvalidWrappedValueWithAnError", test_decodesInvalidWrappedValueWithAnError),
("test_supportsCollectionValues", test_supportsCollectionValues),
]
}
26 changes: 26 additions & 0 deletions Tests/NullCodableTests/NullCodableJSONEncoderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import XCTest
@testable import NullCodable

final class NullCodableJSONEncoderTests: XCTestCase {

func test_encodesNilAsJSONNull() throws {
let value = NullCodable<String>(wrappedValue: nil)

let data = try JSONEncoder().encode(value)

XCTAssertEqual(String(decoding: data, as: UTF8.self), "null")
}

func test_encodesWrappedValue() throws {
let value = NullCodable(wrappedValue: 42)

let data = try JSONEncoder().encode(value)

XCTAssertEqual(String(decoding: data, as: UTF8.self), "42")
}

static let allTests = [
("test_encodesNilAsJSONNull", test_encodesNilAsJSONNull),
("test_encodesWrappedValue", test_encodesWrappedValue),
]
}
26 changes: 26 additions & 0 deletions Tests/NullCodableTests/NullCodablePropertyWrapperTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import XCTest
@testable import NullCodable

final class NullCodablePropertyWrapperTests: XCTestCase {

func test_defaultValueIsNil() {
let value = NullCodable<String>(wrappedValue: nil)

XCTAssertNil(value.wrappedValue)
}

func test_wrappedValueCanBeReadAndUpdated() {
var value = NullCodable(wrappedValue: "before")

XCTAssertEqual(value.wrappedValue, "before")

value.wrappedValue = "after"

XCTAssertEqual(value.wrappedValue, "after")
}

static let allTests = [
("test_defaultValueIsNil", test_defaultValueIsNil),
("test_wrappedValueCanBeReadAndUpdated", test_wrappedValueCanBeReadAndUpdated),
]
}
18 changes: 18 additions & 0 deletions Tests/NullCodableTests/NullCodableSendableTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import XCTest
@testable import NullCodable

final class NullCodableSendableTests: XCTestCase {

func test_conformsToSendableWhenWrappedValueIsSendable() {
assertSendable(NullCodable(wrappedValue: "value"))
assertSendable(NullCodable(wrappedValue: 42))
}

private func assertSendable<T: Sendable>(_ value: T) {
_ = value
}

static let allTests = [
("test_conformsToSendableWhenWrappedValueIsSendable", test_conformsToSendableWhenWrappedValueIsSendable),
]
}
2 changes: 1 addition & 1 deletion Tests/NullCodableTests/NullCodableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ final class NullCodableTests: XCTestCase {
XCTAssertEqual(test.b, 42)
}

static var allTests = [
static let allTests = [
("test_noConformance", test_noConformance),
("test_encodable", test_encodable),
("test_decodable", test_decodable),
Expand Down
6 changes: 6 additions & 0 deletions Tests/NullCodableTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import XCTest
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(NullCodableTests.allTests),
testCase(NullCodablePropertyWrapperTests.allTests),
testCase(NullCodableJSONEncoderTests.allTests),
testCase(NullCodableJSONDecoderTests.allTests),
testCase(NullCodableComplexStructTests.allTests),
testCase(NullCodableEquatableTests.allTests),
testCase(NullCodableSendableTests.allTests),
]
}
#endif