mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
macos: add some unit tests
This commit is contained in:
124
macos/Tests/Helpers/TransferablePasteboardTests.swift
Normal file
124
macos/Tests/Helpers/TransferablePasteboardTests.swift
Normal file
@@ -0,0 +1,124 @@
|
||||
import Testing
|
||||
import AppKit
|
||||
import CoreTransferable
|
||||
import UniformTypeIdentifiers
|
||||
@testable import Ghostty
|
||||
|
||||
struct TransferablePasteboardTests {
|
||||
// MARK: - Test Helpers
|
||||
|
||||
/// A simple Transferable type for testing pasteboard conversion.
|
||||
private struct DummyTransferable: Transferable, Equatable {
|
||||
let payload: String
|
||||
|
||||
static var transferRepresentation: some TransferRepresentation {
|
||||
DataRepresentation(contentType: .utf8PlainText) { value in
|
||||
value.payload.data(using: .utf8)!
|
||||
} importing: { data in
|
||||
let string = String(data: data, encoding: .utf8)!
|
||||
return DummyTransferable(payload: string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Transferable type that registers multiple content types.
|
||||
private struct MultiTypeTransferable: Transferable {
|
||||
let text: String
|
||||
|
||||
static var transferRepresentation: some TransferRepresentation {
|
||||
DataRepresentation(contentType: .utf8PlainText) { value in
|
||||
value.text.data(using: .utf8)!
|
||||
} importing: { data in
|
||||
MultiTypeTransferable(text: String(data: data, encoding: .utf8)!)
|
||||
}
|
||||
DataRepresentation(contentType: .plainText) { value in
|
||||
value.text.data(using: .utf8)!
|
||||
} importing: { data in
|
||||
MultiTypeTransferable(text: String(data: data, encoding: .utf8)!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Basic Functionality
|
||||
|
||||
@Test func pasteboardItemIsCreated() {
|
||||
let transferable = DummyTransferable(payload: "hello")
|
||||
let item = transferable.pasteboardItem()
|
||||
#expect(item != nil)
|
||||
}
|
||||
|
||||
@Test func pasteboardItemContainsExpectedType() {
|
||||
let transferable = DummyTransferable(payload: "hello")
|
||||
guard let item = transferable.pasteboardItem() else {
|
||||
Issue.record("Expected pasteboard item to be created")
|
||||
return
|
||||
}
|
||||
|
||||
let expectedType = NSPasteboard.PasteboardType(UTType.utf8PlainText.identifier)
|
||||
#expect(item.types.contains(expectedType))
|
||||
}
|
||||
|
||||
@Test func pasteboardItemProvidesCorrectData() {
|
||||
let transferable = DummyTransferable(payload: "test data")
|
||||
guard let item = transferable.pasteboardItem() else {
|
||||
Issue.record("Expected pasteboard item to be created")
|
||||
return
|
||||
}
|
||||
|
||||
let pasteboardType = NSPasteboard.PasteboardType(UTType.utf8PlainText.identifier)
|
||||
|
||||
// Write to a pasteboard to trigger data provider
|
||||
let pasteboard = NSPasteboard(name: .init("test-\(UUID().uuidString)"))
|
||||
pasteboard.clearContents()
|
||||
pasteboard.writeObjects([item])
|
||||
|
||||
// Read back the data
|
||||
guard let data = pasteboard.data(forType: pasteboardType) else {
|
||||
Issue.record("Expected data to be available on pasteboard")
|
||||
return
|
||||
}
|
||||
|
||||
let string = String(data: data, encoding: .utf8)
|
||||
#expect(string == "test data")
|
||||
}
|
||||
|
||||
// MARK: - Multiple Content Types
|
||||
|
||||
@Test func multipleTypesAreRegistered() {
|
||||
let transferable = MultiTypeTransferable(text: "multi")
|
||||
guard let item = transferable.pasteboardItem() else {
|
||||
Issue.record("Expected pasteboard item to be created")
|
||||
return
|
||||
}
|
||||
|
||||
let utf8Type = NSPasteboard.PasteboardType(UTType.utf8PlainText.identifier)
|
||||
let plainType = NSPasteboard.PasteboardType(UTType.plainText.identifier)
|
||||
|
||||
#expect(item.types.contains(utf8Type))
|
||||
#expect(item.types.contains(plainType))
|
||||
}
|
||||
|
||||
@Test func multipleTypesProvideCorrectData() {
|
||||
let transferable = MultiTypeTransferable(text: "shared content")
|
||||
guard let item = transferable.pasteboardItem() else {
|
||||
Issue.record("Expected pasteboard item to be created")
|
||||
return
|
||||
}
|
||||
|
||||
let pasteboard = NSPasteboard(name: .init("test-\(UUID().uuidString)"))
|
||||
pasteboard.clearContents()
|
||||
pasteboard.writeObjects([item])
|
||||
|
||||
// Both types should provide the same content
|
||||
let utf8Type = NSPasteboard.PasteboardType(UTType.utf8PlainText.identifier)
|
||||
let plainType = NSPasteboard.PasteboardType(UTType.plainText.identifier)
|
||||
|
||||
if let utf8Data = pasteboard.data(forType: utf8Type) {
|
||||
#expect(String(data: utf8Data, encoding: .utf8) == "shared content")
|
||||
}
|
||||
|
||||
if let plainData = pasteboard.data(forType: plainType) {
|
||||
#expect(String(data: plainData, encoding: .utf8) == "shared content")
|
||||
}
|
||||
}
|
||||
}
|
||||
128
macos/Tests/Splits/TerminalSplitDropZoneTests.swift
Normal file
128
macos/Tests/Splits/TerminalSplitDropZoneTests.swift
Normal file
@@ -0,0 +1,128 @@
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import Ghostty
|
||||
|
||||
struct TerminalSplitDropZoneTests {
|
||||
private let standardSize = CGSize(width: 100, height: 100)
|
||||
|
||||
// MARK: - Basic Edge Detection
|
||||
|
||||
@Test func topEdge() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: 5), in: standardSize)
|
||||
#expect(zone == .top)
|
||||
}
|
||||
|
||||
@Test func bottomEdge() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: 95), in: standardSize)
|
||||
#expect(zone == .bottom)
|
||||
}
|
||||
|
||||
@Test func leftEdge() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 5, y: 50), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func rightEdge() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 95, y: 50), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
|
||||
// MARK: - Corner Tie-Breaking
|
||||
// When distances are equal, the check order determines the result:
|
||||
// left -> right -> top -> bottom
|
||||
|
||||
@Test func topLeftCornerSelectsLeft() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 0, y: 0), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func topRightCornerSelectsRight() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 100, y: 0), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
|
||||
@Test func bottomLeftCornerSelectsLeft() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 0, y: 100), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func bottomRightCornerSelectsRight() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 100, y: 100), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
|
||||
// MARK: - Center Point (All Distances Equal)
|
||||
|
||||
@Test func centerSelectsLeft() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: 50), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
// MARK: - Non-Square Aspect Ratio
|
||||
|
||||
@Test func rectangularViewTopEdge() {
|
||||
let size = CGSize(width: 200, height: 100)
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 100, y: 10), in: size)
|
||||
#expect(zone == .top)
|
||||
}
|
||||
|
||||
@Test func rectangularViewLeftEdge() {
|
||||
let size = CGSize(width: 200, height: 100)
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 10, y: 50), in: size)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func tallRectangleTopEdge() {
|
||||
let size = CGSize(width: 100, height: 200)
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: 10), in: size)
|
||||
#expect(zone == .top)
|
||||
}
|
||||
|
||||
// MARK: - Out-of-Bounds Points
|
||||
|
||||
@Test func pointLeftOfViewSelectsLeft() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: -10, y: 50), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func pointAboveViewSelectsTop() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: -10), in: standardSize)
|
||||
#expect(zone == .top)
|
||||
}
|
||||
|
||||
@Test func pointRightOfViewSelectsRight() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 110, y: 50), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
|
||||
@Test func pointBelowViewSelectsBottom() {
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 50, y: 110), in: standardSize)
|
||||
#expect(zone == .bottom)
|
||||
}
|
||||
|
||||
// MARK: - Diagonal Regions (Triangular Zones)
|
||||
|
||||
@Test func upperLeftTriangleSelectsLeft() {
|
||||
// Point in the upper-left triangle, closer to left than top
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 20, y: 30), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func upperRightTriangleSelectsRight() {
|
||||
// Point in the upper-right triangle, closer to right than top
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 80, y: 30), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
|
||||
@Test func lowerLeftTriangleSelectsLeft() {
|
||||
// Point in the lower-left triangle, closer to left than bottom
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 20, y: 70), in: standardSize)
|
||||
#expect(zone == .left)
|
||||
}
|
||||
|
||||
@Test func lowerRightTriangleSelectsRight() {
|
||||
// Point in the lower-right triangle, closer to right than bottom
|
||||
let zone = TerminalSplitDropZone.calculate(at: CGPoint(x: 80, y: 70), in: standardSize)
|
||||
#expect(zone == .right)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user