|
|
import XCTest
|
|
|
@testable import DropTwoCore
|
|
|
|
|
|
final class FileNameParserTests: XCTestCase {
|
|
|
|
|
|
// MARK: - Erfolgreiches Parsen
|
|
|
|
|
|
func testParsesStandardFileName() {
|
|
|
let result = FileNameParser.parse("SOMOS-9x16-v3-DE.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, "SOMOS")
|
|
|
XCTAssertEqual(parsed.sourceFormatToken, "9x16")
|
|
|
XCTAssertEqual(parsed.remainder, "v3-DE")
|
|
|
XCTAssertEqual(parsed.fileExtension, "mp4")
|
|
|
XCTAssertEqual(parsed.originalFileName, "SOMOS-9x16-v3-DE.mp4")
|
|
|
XCTAssertEqual(parsed.targetFileName, "SOMOS-4x5-v3-DE.mp4")
|
|
|
}
|
|
|
|
|
|
func testProjectNameWithHyphenIsPreserved() {
|
|
|
let result = FileNameParser.parse("Somos-Pendant-9x16-v3-DE.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, "Somos-Pendant")
|
|
|
XCTAssertEqual(parsed.targetFileName, "Somos-Pendant-4x5-v3-DE.mp4")
|
|
|
}
|
|
|
|
|
|
func testLanguageSegmentWithHyphenIsPreserved() {
|
|
|
let result = FileNameParser.parse("SOMOS-9x16-v3-EN-US.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, "SOMOS")
|
|
|
XCTAssertEqual(parsed.remainder, "v3-EN-US")
|
|
|
XCTAssertEqual(parsed.targetFileName, "SOMOS-4x5-v3-EN-US.mp4")
|
|
|
}
|
|
|
|
|
|
func testCaseInsensitiveFormatTokenIsRecognized() {
|
|
|
let result = FileNameParser.parse("somos-9X16-v3-de.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
// Sonst unveränderte Schreibweise bleibt erhalten.
|
|
|
XCTAssertEqual(parsed.projectName, "somos")
|
|
|
XCTAssertEqual(parsed.sourceFormatToken, "9X16")
|
|
|
XCTAssertEqual(parsed.remainder, "v3-de")
|
|
|
XCTAssertEqual(parsed.targetFileName, "somos-4x5-v3-de.mp4")
|
|
|
}
|
|
|
|
|
|
func testFileExtensionIsPreservedVerbatim() {
|
|
|
for ext in ["mp4", "mov", "mxf", "MOV"] {
|
|
|
let fileName = "SOMOS-9x16-v3-DE.\(ext)"
|
|
|
let result = FileNameParser.parse(fileName)
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed für \(fileName), bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.fileExtension, ext)
|
|
|
XCTAssertEqual(parsed.targetFileName, "SOMOS-4x5-v3-DE.\(ext)")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// MARK: - Skip
|
|
|
|
|
|
func testAlreadyTargetFormatIsSkipped() {
|
|
|
let result = FileNameParser.parse("SOMOS-4x5-v3-DE.mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .skipped(.alreadyTargetFormat))
|
|
|
}
|
|
|
|
|
|
// MARK: - Rejection
|
|
|
|
|
|
func testMissingFormatSegmentIsRejected() {
|
|
|
let result = FileNameParser.parse("SOMOS-v3-DE.mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .rejected(.formatSegmentMissing))
|
|
|
}
|
|
|
|
|
|
func testFinderDuplicateIsRejected() {
|
|
|
let result = FileNameParser.parse("SOMOS-9x16-v3-DE (1).mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .rejected(.finderDuplicate))
|
|
|
}
|
|
|
|
|
|
func testFinderDuplicateTakesPriorityOverMissingFormatSegment() {
|
|
|
// Beide Aussagen wären technisch wahr; die handlungsleitende
|
|
|
// Meldung (falsche Kopie erwischt) muss gewinnen.
|
|
|
let result = FileNameParser.parse("SOMOS-v3-DE (1).mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .rejected(.finderDuplicate))
|
|
|
}
|
|
|
|
|
|
// MARK: - a) Rechtestes Vorkommen gewinnt
|
|
|
|
|
|
func testRightmostFormatOccurrenceWins() {
|
|
|
let result = FileNameParser.parse("Kampagne-9x16-Teaser-9x16-v3-DE.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, "Kampagne-9x16-Teaser")
|
|
|
XCTAssertEqual(parsed.remainder, "v3-DE")
|
|
|
XCTAssertEqual(parsed.targetFileName, "Kampagne-9x16-Teaser-4x5-v3-DE.mp4")
|
|
|
}
|
|
|
|
|
|
func testRightmostAlreadyTargetFormatOccurrenceWins() {
|
|
|
let result = FileNameParser.parse("Kampagne-4x5-Teaser-4x5-v3-DE.mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .skipped(.alreadyTargetFormat))
|
|
|
}
|
|
|
|
|
|
// MARK: - b) Projekt und Rest müssen existieren
|
|
|
|
|
|
func testRejectsWhenNoProjectSegment() {
|
|
|
let result = FileNameParser.parse("9x16-v3-DE.mp4")
|
|
|
|
|
|
XCTAssertEqual(result.outcome, .rejected(.formatSegmentMissing))
|
|
|
}
|
|
|
|
|
|
func testParsesWithoutRemainderSegment() {
|
|
|
let result = FileNameParser.parse("SOMOS-9x16.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, "SOMOS")
|
|
|
XCTAssertEqual(parsed.remainder, "")
|
|
|
XCTAssertEqual(parsed.targetFileName, "SOMOS-4x5.mp4")
|
|
|
}
|
|
|
|
|
|
// MARK: - d) Lockere Schreibweisen
|
|
|
|
|
|
func testUnderscoreAndSpaceSeparatorsArePreserved() {
|
|
|
let cases = [
|
|
|
("SOMOS_9x16_v3_DE.mp4", "SOMOS", "v3_DE", "SOMOS_4x5_v3_DE.mp4"),
|
|
|
("SOMOS 9x16 v3 DE.mov", "SOMOS", "v3 DE", "SOMOS 4x5 v3 DE.mov"),
|
|
|
("Somos Pendant - 9X16_v3-DE.mp4", "Somos Pendant", "v3-DE", "Somos Pendant - 4x5_v3-DE.mp4"),
|
|
|
("SOMOS-9×16-v3.mp4", "SOMOS", "v3", "SOMOS-4x5-v3.mp4"),
|
|
|
("SOMOS (9 x 16) v3.mp4", "SOMOS", "v3", "SOMOS (4x5) v3.mp4")
|
|
|
]
|
|
|
for (fileName, project, remainder, target) in cases {
|
|
|
guard case .parsed(let parsed) = FileNameParser.parse(fileName).outcome else {
|
|
|
XCTFail("Erwartete .parsed für \(fileName)")
|
|
|
continue
|
|
|
}
|
|
|
XCTAssertEqual(parsed.projectName, project, fileName)
|
|
|
XCTAssertEqual(parsed.remainder, remainder, fileName)
|
|
|
XCTAssertEqual(parsed.targetFileName, target, fileName)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func testTokenInsideWordIsNotAFormat() {
|
|
|
XCTAssertEqual(FileNameParser.parse("SOMOS-19x160-v3.mp4").outcome, .rejected(.formatSegmentMissing))
|
|
|
XCTAssertEqual(FileNameParser.parse("SOMOSx9x16v3.mp4").outcome, .rejected(.formatSegmentMissing))
|
|
|
}
|
|
|
|
|
|
func testTargetFormatInAnySpellingIsSkipped() {
|
|
|
for fileName in ["SOMOS_4X5_v3.mp4", "SOMOS 4x5.mp4", "SOMOS-4×5-v3-DE.mp4"] {
|
|
|
XCTAssertEqual(FileNameParser.parse(fileName).outcome, .skipped(.alreadyTargetFormat), fileName)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// MARK: - e) Format anhängen, wenn es fehlt
|
|
|
|
|
|
func testAppendingFormatUsesWholeStemAsProject() {
|
|
|
let parsed = FileNameParser.appendingTargetFormat(to: "Sommerfest Teaser.mov")
|
|
|
|
|
|
XCTAssertEqual(parsed?.projectName, "Sommerfest Teaser")
|
|
|
XCTAssertEqual(parsed?.targetFileName, "Sommerfest Teaser 4x5.mov")
|
|
|
XCTAssertEqual(parsed?.originalFileName, "Sommerfest Teaser.mov")
|
|
|
}
|
|
|
|
|
|
func testAppendingFormatPicksSeparatorFromName() {
|
|
|
XCTAssertEqual(FileNameParser.appendingTargetFormat(to: "SOMOS-v3-DE.mp4")?.targetFileName, "SOMOS-v3-DE-4x5.mp4")
|
|
|
XCTAssertEqual(FileNameParser.appendingTargetFormat(to: "SOMOS_v3.mp4")?.targetFileName, "SOMOS_v3_4x5.mp4")
|
|
|
XCTAssertEqual(FileNameParser.appendingTargetFormat(to: "SOMOS.mp4")?.targetFileName, "SOMOS-4x5.mp4")
|
|
|
}
|
|
|
|
|
|
func testAppendingFormatOnlyForMissingFormat() {
|
|
|
XCTAssertNil(FileNameParser.appendingTargetFormat(to: "SOMOS-9x16-v3-DE.mp4"))
|
|
|
XCTAssertNil(FileNameParser.appendingTargetFormat(to: "SOMOS-4x5-v3-DE.mp4"))
|
|
|
XCTAssertNil(FileNameParser.appendingTargetFormat(to: "SOMOS-v3-DE (1).mp4"))
|
|
|
}
|
|
|
|
|
|
// MARK: - c) Format-Segment in der Ausgabe immer klein geschrieben
|
|
|
|
|
|
func testTargetFormatTokenIsAlwaysLowercase() {
|
|
|
let result = FileNameParser.parse("SOMOS-9X16-v3-DE.mp4")
|
|
|
|
|
|
guard case .parsed(let parsed) = result.outcome else {
|
|
|
return XCTFail("Erwartete .parsed, bekam \(result.outcome)")
|
|
|
}
|
|
|
XCTAssertEqual(parsed.sourceFormatToken, "9X16")
|
|
|
XCTAssertTrue(parsed.targetFileName.contains("-4x5-"))
|
|
|
XCTAssertFalse(parsed.targetFileName.contains("4X16"))
|
|
|
XCTAssertEqual(parsed.targetFileName, "SOMOS-4x5-v3-DE.mp4")
|
|
|
}
|
|
|
}
|