unit tests
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
@testable import Peered
|
||||
|
||||
final class InMemoryStorageProvider: StorageProvider {
|
||||
private(set) var files: [String: Data] = [:]
|
||||
|
||||
func contentsOfDirectory(atPath path: String) throws -> [String] {
|
||||
return files.keys.compactMap { filePath -> String? in
|
||||
guard filePath.hasPrefix(path) else { return nil }
|
||||
let remainder = String(filePath.dropFirst(path.count))
|
||||
let stripped = remainder.hasPrefix("/") ? String(remainder.dropFirst()) : remainder
|
||||
guard !stripped.isEmpty, !stripped.contains("/") else { return nil }
|
||||
return stripped
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func createFile(
|
||||
atPath path: String,
|
||||
contents data: Data?,
|
||||
attributes attr: [FileAttributeKey: Any]?
|
||||
) -> Bool {
|
||||
files[path] = data ?? Data()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import Peered
|
||||
|
||||
@Suite
|
||||
struct NoteContentCodableTests {
|
||||
@Test("encode → decode")
|
||||
func coding() throws {
|
||||
let original = NoteInvitation.NoteContent(
|
||||
title: "My note", noteSnapshot: "Note Sample Snapshot")
|
||||
let data = try JSONEncoder().encode(original)
|
||||
let decoded = try JSONDecoder().decode(NoteInvitation.NoteContent.self, from: data)
|
||||
|
||||
#expect(decoded.title == original.title)
|
||||
#expect(decoded.noteSnapshot == original.noteSnapshot)
|
||||
}
|
||||
|
||||
@Test
|
||||
func containsExpectedKeys() throws {
|
||||
let content = NoteInvitation.NoteContent(title: "Titlee", noteSnapshot: "Snapshott")
|
||||
let data = try JSONEncoder().encode(content)
|
||||
let json = try #require(try? JSONSerialization.jsonObject(with: data) as? [String: String])
|
||||
|
||||
#expect(json["title"] == "Titlee")
|
||||
#expect(json["noteSnapshot"] == "Snapshott")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import MultipeerConnectivity
|
||||
import Testing
|
||||
|
||||
@testable import Peered
|
||||
|
||||
extension NoteInvitation {
|
||||
fileprivate init(handler: @escaping (Bool) -> Void) {
|
||||
self.init(
|
||||
invitatorID: .init(
|
||||
displayName: "host"
|
||||
),
|
||||
note: .init(title: "Shared note", noteSnapshot: "Snapshot"),
|
||||
invitationHandler: handler
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suite
|
||||
struct NoteInvitationTests {
|
||||
@Test
|
||||
func acceptCallsHandlerWithTrue() {
|
||||
var received: Bool? = nil
|
||||
var invitation = NoteInvitation { received = $0 }
|
||||
|
||||
invitation.accept()
|
||||
|
||||
#expect(received == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
func declineCallsHandlerWithFalse() {
|
||||
var received: Bool? = nil
|
||||
var invitation = NoteInvitation { received = $0 }
|
||||
|
||||
invitation.decline()
|
||||
|
||||
#expect(received == false)
|
||||
}
|
||||
|
||||
@Test
|
||||
func acceptIsIdempotent() {
|
||||
var callCount = 0
|
||||
var invitation = NoteInvitation { _ in callCount += 1 }
|
||||
|
||||
invitation.accept()
|
||||
invitation.accept()
|
||||
|
||||
#expect(callCount == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
func declineIsIdempotent() {
|
||||
var callCount = 0
|
||||
var invitation = NoteInvitation { _ in callCount += 1 }
|
||||
|
||||
invitation.decline()
|
||||
invitation.decline()
|
||||
|
||||
#expect(callCount == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
func declineAfterAcceptIsNoOp() {
|
||||
var callCount = 0
|
||||
var invitation = NoteInvitation { _ in callCount += 1 }
|
||||
|
||||
invitation.accept()
|
||||
invitation.decline()
|
||||
|
||||
#expect(callCount == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
func noteNameReturnsTitle() {
|
||||
let invitation = NoteInvitation { _ in }
|
||||
#expect(invitation.noteName == "Shared note")
|
||||
}
|
||||
|
||||
@Test
|
||||
func idIsInvitatorPeerID() {
|
||||
let peerID = MCPeerID(displayName: "host")
|
||||
let invitation = NoteInvitation(
|
||||
invitatorID: peerID,
|
||||
note: .init(title: "T", noteSnapshot: "S")
|
||||
)
|
||||
#expect(invitation.id == peerID)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import Peered
|
||||
|
||||
@Suite
|
||||
struct NoteMessageCodableTests {
|
||||
@Test
|
||||
func encodesToJSON() throws {
|
||||
let message = NoteMessage(senderID: "host", content: "Content")
|
||||
let data = try JSONEncoder().encode(message)
|
||||
let json = try #require(try? JSONSerialization.jsonObject(with: data) as? [String: String])
|
||||
|
||||
#expect(json["senderID"] == "host")
|
||||
#expect(json["content"] == "Content")
|
||||
}
|
||||
|
||||
@Test
|
||||
func decodesFromJSON() throws {
|
||||
let json = #"{"senderID":"host","content":"contentt"}"#
|
||||
let data = try #require(json.data(using: .utf8))
|
||||
let message = try JSONDecoder().decode(NoteMessage.self, from: data)
|
||||
|
||||
#expect(message.senderID == "host")
|
||||
#expect(message.content == "contentt")
|
||||
}
|
||||
|
||||
@Test("encode → decode")
|
||||
func coding() throws {
|
||||
let original = NoteMessage(senderID: "host", content: "coding test")
|
||||
let data = try JSONEncoder().encode(original)
|
||||
let decoded = try JSONDecoder().decode(NoteMessage.self, from: data)
|
||||
|
||||
#expect(decoded.senderID == original.senderID)
|
||||
#expect(decoded.content == original.content)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import Peered
|
||||
|
||||
@Suite
|
||||
struct NotesStorageTests {
|
||||
private func makeStorage(root: URL = URL(filePath: "/test")) -> (
|
||||
NotesStorage, InMemoryStorageProvider
|
||||
) {
|
||||
let provider = InMemoryStorageProvider()
|
||||
let storage = NotesStorage(storageProvider: provider, rootDirectory: root)
|
||||
return (storage, provider)
|
||||
}
|
||||
|
||||
@Test
|
||||
func loadNotesReturnsEmptyArrayWhenNoFiles() {
|
||||
let (storage, _) = makeStorage()
|
||||
let notes = storage.loadNotes()
|
||||
#expect(notes.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
func createNoteCreatesFile() {
|
||||
let root = URL(filePath: "/test")
|
||||
let (storage, provider) = makeStorage(root: root)
|
||||
|
||||
storage.createNote(name: "My note")
|
||||
|
||||
#expect(!provider.files.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
func loadNotesReturnCreatedNote() {
|
||||
let root = URL(filePath: "/test")
|
||||
let (storage, provider) = makeStorage(root: root)
|
||||
|
||||
let filePath = root.appendingPathComponent("Note").path
|
||||
provider.createFile(atPath: filePath, contents: Data(), attributes: nil)
|
||||
|
||||
let notes = storage.loadNotes()
|
||||
|
||||
#expect(notes.count == 1)
|
||||
#expect(notes.first?.name == "Note")
|
||||
}
|
||||
|
||||
@Test
|
||||
func createNoteDeduplicatesNames() {
|
||||
let root = URL(filePath: "/test")
|
||||
let (storage, provider) = makeStorage(root: root)
|
||||
|
||||
let existingPath = root.appendingPathComponent("Note").path
|
||||
provider.createFile(atPath: existingPath, contents: Data(), attributes: nil)
|
||||
|
||||
storage.createNote(name: "Note")
|
||||
|
||||
#expect(provider.files.count == 2)
|
||||
|
||||
let paths = provider.files.keys
|
||||
#expect(paths.contains(where: { $0.contains("Note 1") }))
|
||||
}
|
||||
|
||||
@Test
|
||||
func createNoteTwiceCreatesTwoFiles() {
|
||||
let root = URL(filePath: "/test")
|
||||
let (storage, _) = makeStorage(root: root)
|
||||
|
||||
storage.createNote(name: "Note")
|
||||
storage.createNote(name: "Note")
|
||||
|
||||
let notes = storage.loadNotes()
|
||||
#expect(notes.count == 2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user