import Foundation import Testing @testable import LegadoCore struct LocalBookServiceTests { @Test func decodesDefaultTocRuleWithMissingReplacement() throws { let data = Data(#"{"id":-1,"name":"目录","rule":"^第.+章$","serialNumber":0,"enable":true}"#.utf8) let value = try JSONDecoder().decode(TxtTocRule.self, from: data) #expect(value.replacement == "") #expect(value.example == nil) #expect(value.enable) } @Test func importsUTF8TextSplitsChaptersAndReadsContent() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) let source = root.appending(path: "测试书.txt") let sourceData = Data("序言\n第一章 相遇\n这是第一章正文\n第二章 远行\n这是第二章正文".utf8) try sourceData.write(to: source) let service = LocalBookService() let report = try service.importTextFile(at: source, into: root.appending(path: "library")) #expect(report.book.origin == "local") #expect(report.book.charset == "UTF-8") #expect(report.chapters.map(\.title) == ["前言", "第一章 相遇", "第二章 远行"]) #expect(report.chapters[1].url == "82e56047094237f3") let firstTitle = try #require(sourceData.range(of: Data("第一章 相遇".utf8))) let secondTitle = try #require(sourceData.range(of: Data("第二章 远行".utf8))) #expect(report.chapters[1].start == Int64(firstTitle.upperBound)) #expect(report.chapters[1].end == Int64(secondTitle.lowerBound)) #expect(report.chapters.map(\.wordCount) == ["3字", "9字", "8字"]) #expect(report.book.wordCount == "20字") #expect(report.book.intro == "序言\n") let content = try service.loadContent(book: report.book, chapter: report.chapters[1]) #expect(content.content == "  这是第一章正文\n") #expect(FileManager.default.fileExists(atPath: try #require(URL(string: report.book.bookUrl)).path)) } @Test func createsSingleChapterWhenNoHeadingExists() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) let source = root.appending(path: "短篇.txt") try Data("这是一个没有章节标题的短篇。".utf8).write(to: source) let report = try LocalBookService().importTextFile(at: source, into: root.appending(path: "library")) #expect(report.chapters.count == 1) #expect(report.chapters[0].title == "短篇") #expect(try LocalBookService().loadContent(book: report.book, chapter: report.chapters[0]).content == "这是一个没有章节标题的短篇。") } @Test func splitsLongHeadinglessTextAtTenKiBThreshold() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) let source = root.appending(path: "无目录长文.txt") let paragraph = String(repeating: "a", count: 10_500) try Data("\(paragraph)\n\(paragraph)\n尾声".utf8).write(to: source) let report = try LocalBookService(tocRules: []).importTextFile( at: source, into: root.appending(path: "library") ) #expect(report.chapters.count == 2) #expect(report.chapters.map(\.title) == ["第1章(1)", "第1章(2)"]) #expect(report.chapters[0].end == report.chapters[1].start) #expect(report.book.wordCount == "2.1万字") #expect(report.book.intro == nil) } @Test func numbersHeadinglessChaptersBy512KBBlock() throws { let root = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString) defer { try? FileManager.default.removeItem(at: root) } try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) let source = root.appending(path: "多块无目录.txt") let paragraph = String(repeating: "a", count: 10_500) + "\n" try Data(String(repeating: paragraph, count: 55).utf8).write(to: source) let report = try LocalBookService(tocRules: []).importTextFile( at: source, into: root.appending(path: "library") ) #expect(report.chapters.first?.title == "第1章(1)") #expect(report.chapters.contains { $0.title.hasPrefix("第2章(") }) for index in 1..