1
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import Foundation
|
||||
|
||||
@main
|
||||
struct ExpensePreviewTests {
|
||||
static func rejects(_ action: () throws -> Void) {
|
||||
do {
|
||||
try action()
|
||||
preconditionFailure("Unexpected success")
|
||||
} catch {
|
||||
precondition(!error.localizedDescription.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
static func main() throws {
|
||||
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true)
|
||||
defer { try? FileManager.default.removeItem(at: root) }
|
||||
let source = root.appendingPathComponent("组 模板.XLSX")
|
||||
let data = Data("test worksheet bytes".utf8)
|
||||
try data.write(to: source)
|
||||
let accepted = try ExpenseTemplateImportSource.validate([source])
|
||||
precondition(accepted == source)
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([]) }
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([source, source]) }
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([root]) }
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([URL(string: "https://example.invalid/template.xlsx")!]) }
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([root.appendingPathComponent("missing.xlsx")]) }
|
||||
let empty = root.appendingPathComponent("empty.xlsx")
|
||||
try Data().write(to: empty)
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([empty]) }
|
||||
let oldFormat = root.appendingPathComponent("old.xls")
|
||||
try data.write(to: oldFormat)
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([oldFormat]) }
|
||||
let oversized = root.appendingPathComponent("large.xlsx")
|
||||
try Data(count: 20 * 1024 * 1024 + 1).write(to: oversized)
|
||||
rejects { _ = try ExpenseTemplateImportSource.validate([oversized]) }
|
||||
let request: [String: Any] = ["purpose": "交通", "amount": "100.30", "payee": ["recipient": "测试"]]
|
||||
let preview = PreparedExpensePreview(file: source, requestDigest: try PreparedExpensePreview.digest(request),
|
||||
fileDigest: ExpenseTemplateStorage.fingerprint(data), templateName: "测试",
|
||||
uncalculatedCells: [])
|
||||
let verified = try preview.verifiedData(request: request)
|
||||
precondition(verified == data)
|
||||
var changed = request
|
||||
changed["destination"] = "/different/output.xlsx"
|
||||
let relocated = try preview.verifiedData(request: changed)
|
||||
precondition(relocated == data)
|
||||
changed["payee"] = ["recipient": "新收款人"]
|
||||
rejects { _ = try preview.verifiedData(request: changed) }
|
||||
changed = request
|
||||
changed["amount"] = "444.00"
|
||||
rejects { _ = try preview.verifiedData(request: changed) }
|
||||
changed = request
|
||||
changed["templateMapping"] = ["purpose": "D"]
|
||||
rejects { _ = try preview.verifiedData(request: changed) }
|
||||
try Data("changed file".utf8).write(to: source)
|
||||
rejects { _ = try preview.verifiedData(request: request) }
|
||||
preview.remove()
|
||||
precondition(!FileManager.default.fileExists(atPath: source.path))
|
||||
rejects { _ = try preview.verifiedData(request: request) }
|
||||
print("Template drop validation, preview identity, stale input and temporary cleanup tests passed")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Foundation
|
||||
|
||||
@main
|
||||
struct ExpenseTemplateTests {
|
||||
static func rejects(_ action: () throws -> Void) {
|
||||
do {
|
||||
try action()
|
||||
preconditionFailure("Unexpected success")
|
||||
} catch {
|
||||
precondition(!error.localizedDescription.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
static func main() throws {
|
||||
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true)
|
||||
defer { try? FileManager.default.removeItem(at: root) }
|
||||
let source = root.appendingPathComponent("原模板.xlsx")
|
||||
let data = Data("Synthetic template fixture".utf8)
|
||||
try data.write(to: source)
|
||||
let storage = ExpenseTemplateStorage(root: root)
|
||||
let initial = try storage.load()
|
||||
precondition(initial == nil)
|
||||
let mapping = ExpenseTemplateMapping(sheetName: "组 A", startRow: 5, endRow: 10,
|
||||
columns: ["purpose": "B", "amount": "F"], cells: ["recipient": "B12"])
|
||||
let validation = ExpenseTemplateValidation(templateVersion: "mapped-xlsx-v1",
|
||||
fingerprint: ExpenseTemplateStorage.fingerprint(data),
|
||||
mapping: mapping, mappingDigest: "test-mapping-digest")
|
||||
let saved = try storage.save(name: source.lastPathComponent, source: source, validation: validation)
|
||||
let reloadedStorage = ExpenseTemplateStorage(root: root)
|
||||
let reloaded = try reloadedStorage.load()!
|
||||
precondition(reloaded.mapping == mapping)
|
||||
precondition(reloaded.name == "原模板.xlsx")
|
||||
let reloadedData = try Data(contentsOf: reloadedStorage.file(for: reloaded))
|
||||
precondition(reloadedData == data)
|
||||
let workspace = root.appendingPathComponent("workspace.json")
|
||||
try Data("current expense data".utf8).write(to: workspace)
|
||||
try Data("{}".utf8).write(to: workspace, options: .atomic)
|
||||
let afterWorkspaceClear = try reloadedStorage.load()
|
||||
precondition(afterWorkspaceClear?.fingerprint == saved.fingerprint)
|
||||
let next = try storage.save(name: "新模板.xlsx", source: source, validation: validation)
|
||||
precondition(!FileManager.default.fileExists(atPath: storage.directory.appendingPathComponent(saved.fileName).path))
|
||||
precondition(next.fileName != saved.fileName)
|
||||
var bad = validation
|
||||
bad.fingerprint = "wrong"
|
||||
rejects { _ = try storage.save(name: "invalid", source: source, validation: bad) }
|
||||
let afterFailedSave = try storage.load()
|
||||
precondition(afterFailedSave?.fileName == next.fileName)
|
||||
var traversal = next
|
||||
traversal.fileName = "../原模板.xlsx"
|
||||
rejects { _ = try storage.file(for: traversal) }
|
||||
let result = try JSONSerialization.data(withJSONObject: [
|
||||
"templateVersion": "mapped-xlsx-v1", "templateFingerprint": saved.fingerprint,
|
||||
"templateMappingDigest": saved.mappingDigest
|
||||
])
|
||||
try ExpenseTemplateStorage.validateExport(result, template: saved)
|
||||
rejects { try ExpenseTemplateStorage.validateExport(Data("{}".utf8), template: saved) }
|
||||
var differentMapping = saved
|
||||
differentMapping.mappingDigest = "different"
|
||||
rejects { try ExpenseTemplateStorage.validateExport(result, template: differentMapping) }
|
||||
let storedFile = try storage.file(for: next)
|
||||
try Data("changed".utf8).write(to: storedFile)
|
||||
rejects { _ = try storage.file(for: next) }
|
||||
try storage.remove()
|
||||
let afterRemoval = try storage.load()
|
||||
precondition(afterRemoval == nil)
|
||||
precondition(!FileManager.default.fileExists(atPath: storage.directory.path))
|
||||
let originalData = try Data(contentsOf: source)
|
||||
precondition(originalData == data)
|
||||
precondition(FileManager.default.fileExists(atPath: workspace.path))
|
||||
try storage.remove()
|
||||
print("Template persistence, replacement, reset isolation and export fingerprint tests passed")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user