import Testing @testable import FlaroDownloads @Suite("Download-Zustandsautomat") struct DownloadStateTests { @Test("Ein abgeschlossener Download bleibt abgeschlossen") func completedIsTerminal() { // Der wichtigste Übergang, den es NICHT geben darf: wäre er erlaubt, // könnte ein verspäteter Rückruf aus der Hintergrundsitzung eine // fertige Datei wieder in die Warteschlange schieben — und sie damit // ein zweites Mal herunterladen. for next in DownloadState.allCases { #expect(!DownloadState.completed.canTransition(to: next)) } } @Test("Gescheiterte Downloads dürfen zurück in die Warteschlange") func failedCanBeRetried() { #expect(DownloadState.failed.canTransition(to: .queued)) } @Test("Gescheiterte Downloads springen nicht direkt ins Übertragen") func failedCannotSkipTheQueue() { // Sonst umgeht der Wiederholen-Knopf die Prüfungen auf WLAN und // Speicherplatz, die beim Verlassen der Warteschlange stattfinden. #expect(!DownloadState.failed.canTransition(to: .downloading)) } @Test("Angehalten und laufend zählen beim Speicherplatz mit") func partialTransfersOccupyStorage() { // Beide haben bereits Daten auf der Platte. Zählte man sie nicht mit, // liefe das Gerät trotz gesetzter Grenze voll. #expect(DownloadState.downloading.occupiesStorage) #expect(DownloadState.paused.occupiesStorage) #expect(DownloadState.completed.occupiesStorage) #expect(!DownloadState.queued.occupiesStorage) #expect(!DownloadState.waiting.occupiesStorage) #expect(!DownloadState.failed.occupiesStorage) } @Test("Nur wartende Zustände dürfen mit dem Übertragen beginnen") func onlyWaitingStatesAreTransferable() { #expect(DownloadState.queued.isTransferable) #expect(DownloadState.waiting.isTransferable) #expect(!DownloadState.downloading.isTransferable) #expect(!DownloadState.paused.isTransferable) #expect(!DownloadState.completed.isTransferable) } @Test("Kein Zustand geht in sich selbst über") func noSelfTransitions() { // Ein Übergang auf sich selbst wäre ein stilles Nichts und würde // Zählerstände wie „Versuche" doppelt hochzählen. for state in DownloadState.allCases { #expect(!state.canTransition(to: state)) } } @Test("Jeder Zustand außer dem abgeschlossenen hat einen Ausgang") func everyStateCanProgress() { for state in DownloadState.allCases where state != .completed { let hasExit = DownloadState.allCases.contains { state.canTransition(to: $0) } #expect(hasExit, "\(state.rawValue) ist eine Sackgasse") } } @Test("Die gespeicherten Namen bleiben stabil") func rawValuesAreStable() { // Sie landen in SwiftData. Ein umbenannter Fall würde beim nächsten // Start alle laufenden Downloads unlesbar machen. #expect(DownloadState.queued.rawValue == "queued") #expect(DownloadState.downloading.rawValue == "downloading") #expect(DownloadState.paused.rawValue == "paused") #expect(DownloadState.waiting.rawValue == "waiting") #expect(DownloadState.completed.rawValue == "completed") #expect(DownloadState.failed.rawValue == "failed") } }