9月20日
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import Foundation
|
||||
import CoreGraphics
|
||||
|
||||
@main
|
||||
struct PairConnectionLayoutTests {
|
||||
static func main() {
|
||||
let left = CGRect(x: 0, y: 80, width: 300, height: 500)
|
||||
let right = CGRect(x: 340, y: 80, width: 300, height: 500)
|
||||
let invoices = (0..<4).map { "i\($0)" }, payments = (0..<4).map { "p\($0)" }
|
||||
var frames: [String: CGRect] = [:]
|
||||
for index in 0..<4 {
|
||||
frames[invoices[index]] = CGRect(x: 3, y: 90 + index * 110, width: 290, height: 100)
|
||||
frames[payments[index]] = CGRect(x: 343, y: 90 + index * 110, width: 290, height: 100)
|
||||
}
|
||||
func layout(_ selectedInvoices: Set<String>, _ selectedPayments: Set<String>,
|
||||
_ currentFrames: [String: CGRect]) -> PairConnectionLayout {
|
||||
PairConnectionLayout(invoiceIDs: invoices, paymentIDs: payments,
|
||||
selectedInvoices: selectedInvoices, selectedPayments: selectedPayments,
|
||||
frames: currentFrames, invoiceViewport: left, paymentViewport: right)
|
||||
}
|
||||
for (invoiceCount, paymentCount) in [(1, 1), (1, 4), (4, 1), (4, 4)] {
|
||||
let result = layout(Set(invoices.prefix(invoiceCount)), Set(payments.prefix(paymentCount)), frames)
|
||||
precondition(result.representedPairCount == invoiceCount * paymentCount)
|
||||
precondition(result.invoices.count == invoiceCount && result.payments.count == paymentCount)
|
||||
precondition(result.invoices.allSatisfy { $0.overflow == nil })
|
||||
precondition(result.payments.allSatisfy { $0.overflow == nil })
|
||||
precondition(result.lines.allSatisfy { result.clipRect.contains($0.start) && result.clipRect.contains($0.end) })
|
||||
}
|
||||
precondition(layout([], Set(payments), frames).lines.isEmpty)
|
||||
precondition(layout(Set(invoices), [], frames).lines.isEmpty)
|
||||
let initial = layout(["i0"], Set(payments), frames)
|
||||
var scrolled = frames
|
||||
for id in payments { scrolled[id] = frames[id]!.offsetBy(dx: 0, dy: -160) }
|
||||
let afterScroll = layout(["i0"], Set(payments), scrolled)
|
||||
precondition(afterScroll.invoices.map(\.point) == initial.invoices.map(\.point))
|
||||
precondition(afterScroll.payments.map(\.point) != initial.payments.map(\.point))
|
||||
precondition(afterScroll.payments.reduce(0) { $0 + $1.count } == 4)
|
||||
precondition(afterScroll.payments.first(where: { $0.overflow == .above })?.count == 1)
|
||||
precondition(afterScroll.representedPairCount == 4)
|
||||
|
||||
// Offscreen anchors can disappear from LazyVGrid without removing their selected relationships.
|
||||
scrolled.removeValue(forKey: "p0")
|
||||
let recycled = layout(["i0"], Set(payments), scrolled)
|
||||
precondition(recycled.lines == afterScroll.lines)
|
||||
scrolled.removeValue(forKey: "p3")
|
||||
let bothEdges = layout(Set(invoices), Set(payments), scrolled)
|
||||
precondition(bothEdges.payments.first(where: { $0.overflow == .above })?.count == 1)
|
||||
precondition(bothEdges.payments.first(where: { $0.overflow == .below })?.count == 1)
|
||||
precondition(bothEdges.invoices.reduce(0) { $0 + $1.count } * bothEdges.payments.reduce(0) { $0 + $1.count } == 16)
|
||||
|
||||
var partial = frames
|
||||
partial["p0"] = CGRect(x: 343, y: 20, width: 290, height: 100)
|
||||
let clipped = layout(["i0"], ["p0"], partial)
|
||||
precondition(clipped.payments[0].point.y == 100)
|
||||
precondition(clipped.payments[0].overflow == nil)
|
||||
let allRecycled = layout(Set(invoices), Set(payments), [:])
|
||||
precondition(allRecycled.invoices[0].count == 4 && allRecycled.payments[0].count == 4)
|
||||
precondition(allRecycled.representedPairCount == 16 && allRecycled.lines.count <= 3)
|
||||
|
||||
let filtered = PairConnectionLayout(invoiceIDs: ["i0"], paymentIDs: ["p1"], selectedInvoices: Set(invoices),
|
||||
selectedPayments: Set(payments), frames: frames, invoiceViewport: left, paymentViewport: right)
|
||||
precondition(filtered.representedPairCount == 1)
|
||||
let empty = PairConnectionLayout(invoiceIDs: invoices, paymentIDs: payments, selectedInvoices: Set(invoices),
|
||||
selectedPayments: Set(payments), frames: frames, invoiceViewport: .zero, paymentViewport: right)
|
||||
precondition(empty.lines.isEmpty)
|
||||
let grid: [String: CGRect] = [
|
||||
"i0": CGRect(x: 3, y: 90, width: 140, height: 150),
|
||||
"i1": CGRect(x: 155, y: 90, width: 140, height: 150),
|
||||
"p0": CGRect(x: 343, y: 90, width: 140, height: 150),
|
||||
"p1": CGRect(x: 495, y: 90, width: 140, height: 150)
|
||||
]
|
||||
let routed = layout(["i0", "i1"], ["p0", "p1"], grid)
|
||||
precondition(routed.representedPairCount == 4)
|
||||
for line in routed.lines {
|
||||
let stroke = CGRect(x: min(line.start.x, line.end.x) - 0.5, y: min(line.start.y, line.end.y) - 0.5,
|
||||
width: abs(line.end.x - line.start.x) + 1, height: abs(line.end.y - line.start.y) + 1)
|
||||
precondition(grid.values.allSatisfy { !stroke.intersects($0.insetBy(dx: 1, dy: 1)) },
|
||||
"Connection crosses a card's contents")
|
||||
}
|
||||
print("Pair connections: 1:1, 1:N, N:1, N:M, independent scrolling, clipping, recycled cells and filtering passed")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user