Skip to content

Commit

Permalink
IOS-9553. Add unit tests for file management view model and related U…
Browse files Browse the repository at this point in the history
…C and Repos
  • Loading branch information
rgmez committed Feb 6, 2025
1 parent 587f4e7 commit 8ffa194
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 36 deletions.
32 changes: 30 additions & 2 deletions MEGADataTests/Repos/OfflineFilesRepositoryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,45 @@ struct OfflineFilesRepositoryTestSuite {
}
}

@Suite("OfflineFilesRepository offlineSize Tests")
struct OfflineSizeTests {
@Test("When offlineURL is nil, should return 0")
func whenOfflineURLIsNil_shouldReturnZero() throws {
let (sut, _) = makeSUT(offlineURL: nil)

#expect(sut.offlineSize() == 0)
}

@Test("When offlineURL is valid, should return calculated folder size")
func whenOfflineURLIsValid_shouldReturnCalculatedSize() throws {
let expectedSize: UInt64 = 1024
let (sut, _) = makeSUT(folderSize: expectedSize)

#expect(sut.offlineSize() == expectedSize)
}

@Test("When folder size calculator returns 0, should return 0")
func whenFolderSizeIsZero_shouldReturnZero() throws {
let expectedSize: UInt64 = 0

let (sut, _) = makeSUT(folderSize: expectedSize)

#expect(sut.offlineSize() == expectedSize)
}
}

private static func makeSUT(
sdk: MockSdk = MockSdk(),
fileManager: FileManager = MockFileManager(),
offlineURL: URL? = testOfflineURL
offlineURL: URL? = testOfflineURL,
folderSize: UInt64 = 0
) -> (OfflineFilesRepository, MockMEGAStore) {
let store = MockMEGAStore()
let sut = OfflineFilesRepository(
store: store,
offlineURL: offlineURL,
sdk: sdk,
folderSizeCalculator: MockFolderSizeCalculator()
folderSizeCalculator: MockFolderSizeCalculator(folderSize: folderSize)
)
return (sut, store)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public final class MockFileSystemRepository: FileSystemRepositoryProtocol, @unch
private let relativePath: String
private let _offlineDirectoryURL: URL?

public var removeFolderContents_calledTimes: Int = 0

@Atomic public var removeFileURLs = [URL]()

public init(fileExists: Bool = false,
Expand Down Expand Up @@ -66,7 +68,9 @@ public final class MockFileSystemRepository: FileSystemRepositoryProtocol, @unch
relativePath
}

public func removeFolderContents(atURL url: URL) async throws {}
public func removeFolderContents(atURL url: URL) async throws {
removeFolderContents_calledTimes += 1
}

public func offlineDirectoryURL() -> URL? {
_offlineDirectoryURL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ public final class MockOfflineFilesRepository: OfflineFilesRepositoryProtocol, @

private let offlineFileEntities: [OfflineFileEntity]
private let offlineFileEntity: OfflineFileEntity?
private let _offlineSize: UInt64

public var removeAllOfflineNodesCalledTimes = 0

public init(
offlineFileEntities: [OfflineFileEntity] = [],
offlineFileEntity: OfflineFileEntity? = nil
offlineFileEntity: OfflineFileEntity? = nil,
offlineSize: UInt64 = 0
) {
self.offlineFileEntities = offlineFileEntities
self.offlineFileEntity = offlineFileEntity
_offlineSize = offlineSize
}

public var offlineURL: URL? = URL(fileURLWithPath: "Documents")
Expand All @@ -34,6 +37,6 @@ public final class MockOfflineFilesRepository: OfflineFilesRepositoryProtocol, @
}

public func offlineSize() -> UInt64 {
0
_offlineSize
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Foundation
import MEGADomain

public final class MockCacheUseCase: CacheUseCaseProtocol, @unchecked Sendable {
private var _cacheSize: UInt64
public var cleanCache_calledTimes = 0

public init(cacheSize: UInt64) {
_cacheSize = cacheSize
}

public func cacheSize() throws -> UInt64 {
_cacheSize
}

public func cleanCache() async throws {
_cacheSize = 0
cleanCache_calledTimes += 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import MEGADomain

public final class MockMobileDataUseCase: MobileDataUseCaseProtocol {
private var _isEnabled = false

public init(isEnabled: Bool = false) {
_isEnabled = isEnabled
}

public func isMobileDataForPreviewingEnabled() -> Bool {
_isEnabled
}

public func updateMobileDataForPreviewingEnabled(_ enabled: Bool) {
_isEnabled = enabled
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MEGASwift

public final class MockOfflineUseCase: OfflineUseCaseProtocol, @unchecked Sendable {
private let _relativePathToDocumentsDirectory: String
private let offlinesize: UInt64
private var _offlineSize: UInt64

private(set) var removeItem_calledTimes = 0
private(set) var removeAllOfflineFiles_calledTimes = 0
Expand All @@ -17,12 +17,12 @@ public final class MockOfflineUseCase: OfflineUseCaseProtocol, @unchecked Sendab
relativePathToDocumentsDirectory: String = "",
stubbedRelativePath: String = "",
stubbedError: Error? = nil,
offlinesize: UInt64 = 0
offlineSize: UInt64 = 0
) {
_relativePathToDocumentsDirectory = relativePathToDocumentsDirectory
self.stubbedRelativePath = stubbedRelativePath
self.stubbedError = stubbedError
self.offlinesize = offlinesize
_offlineSize = offlineSize
}

public func relativePathToDocumentsDirectory(for url: URL) -> String {
Expand All @@ -37,14 +37,16 @@ public final class MockOfflineUseCase: OfflineUseCaseProtocol, @unchecked Sendab
}

public func removeAllOfflineFiles() async {
_offlineSize = 0
removeAllOfflineFiles_calledTimes += 1
}

public func removeAllStoredFiles() {
_offlineSize = 0
removeAllStoredFiles_calledTimes += 1
}

public func offlineSize() -> UInt64 {
offlinesize
_offlineSize
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,96 @@ import Testing

@Suite("OfflineUseCase Tests - Validates OfflineUseCase functionality")
struct OfflineUseCaseTests {
private let testURL = URL(string: "file:///data/Containers/Data/Application/3EAE35E8-ABD4-49DE-90C9-C1070C22A6E1/Documents/photos/readme.md")!
private let expectedRelativePath = "photos/readme.md"
private static let testURL = URL(string: "file:///data/Containers/Data/Application/3EAE35E8-ABD4-49DE-90C9-C1070C22A6E1/Documents/photos/readme.md")!
private static let invalidURL = URL(string: "invalid://path")!
private static let expectedRelativePath = "photos/readme.md"

private func makeSUT(
private static func makeSUT(
relativePath: String? = nil,
offlineFileEntities: [OfflineFileEntity] = [],
offlineFileEntity: OfflineFileEntity? = nil
offlineSize: UInt64 = 0,
offlineDirectoryURL: URL? = nil
) -> (
sut: OfflineUseCase,
fileSystemRepository: MockFileSystemRepository,
offlineFilesRepository: MockOfflineFilesRepository
) {
let fileSystemRepository = MockFileSystemRepository(relativePath: relativePath ?? expectedRelativePath)
let offlineFilesRepository = MockOfflineFilesRepository(
offlineFileEntities: offlineFileEntities,
offlineFileEntity: offlineFileEntity
let fileSystemRepository = MockFileSystemRepository(
relativePath: relativePath ?? "",
offlineDirectoryURL: offlineDirectoryURL
)
let offlineFilesRepository = MockOfflineFilesRepository(offlineSize: offlineSize)
let sut = OfflineUseCase(
fileSystemRepository: fileSystemRepository,
offlineFilesRepository: offlineFilesRepository
)
return (sut, fileSystemRepository, offlineFilesRepository)
}

@Test("relativePathToDocumentsDirectory should return expected path")
func relativePathToDocumentsDirectory_shouldReturnExpectedPath() {
let (sut, _, _) = makeSUT(relativePath: expectedRelativePath)
@Suite("OfflineUseCase relativePath Tests")
struct RelativePathTests {
@Test("When given a valid URL, should return expected path")
func withValidURL_shouldReturnExpectedPath() {
let (sut, _, _) = makeSUT(relativePath: expectedRelativePath)
let result = sut.relativePathToDocumentsDirectory(for: testURL)
#expect(result == expectedRelativePath)
}

let result = sut.relativePathToDocumentsDirectory(for: testURL)

#expect(result == expectedRelativePath, "Expected \(expectedRelativePath), but got \(result)")
@Test("When given an invalid URL, should return empty string")
func withInvalidURL_shouldReturnEmptyString() {
let (sut, _, _) = makeSUT()
let result = sut.relativePathToDocumentsDirectory(for: invalidURL)
#expect(result.isEmpty)
}
}

@Test("removeItem should successfully remove the item")
func removeItem_whenSuccess_shouldRemoveTheItem() async throws {
let (sut, fileSystemRepository, _) = makeSUT()
@Suite("OfflineUseCase removeItem Tests")
struct RemoveItemTests {
@Test("When file exists, should remove the item")
func withExistingFile_shouldRemoveItem() async throws {
let (sut, fileSystemRepository, _) = makeSUT()
try await sut.removeItem(at: testURL)
#expect(fileSystemRepository.removeFileURLs == [testURL])
}
}

try await sut.removeItem(at: testURL)
@Suite("OfflineUseCase removeAllOfflineFiles Tests")
struct RemoveAllOfflineFilesTests {
@Test("When offline directory exists, should remove all files")
func withOfflineDirectory_shouldRemoveAllFiles() async throws {
let (sut, fileSystemRepository, _) = makeSUT(offlineDirectoryURL: testURL)
try await sut.removeAllOfflineFiles()
#expect(fileSystemRepository.removeFolderContents_calledTimes == 1)
}

#expect(fileSystemRepository.removeFileURLs == [testURL], "Expected file removal for \(testURL)")
@Test("When offline directory is nil, should not throw error")
func withNilOfflineDirectory_shouldNotThrowError() async throws {
let (sut, _, _) = makeSUT()

await #expect(throws: Never.self) {
try await sut.removeAllOfflineFiles()
}
}
}

@Test("removeAllOfflineFiles should invoke repository correctly")
func removeAllOfflineFiles_whenCalled_shouldInvokeRepository() async throws {
let (sut, _, offlineFilesRepository) = makeSUT()

try await sut.removeAllOfflineFiles()
sut.removeAllStoredFiles()
@Suite("OfflineUseCase removeAllStoredFiles Tests")
struct RemoveAllStoredFilesTests {
@Test("Should clear all stored offline nodes")
func shouldClearAllStoredNodes() {
let (sut, _, offlineFilesRepository) = makeSUT()
sut.removeAllStoredFiles()
#expect(offlineFilesRepository.removeAllOfflineNodesCalledTimes == 1)
}
}

#expect(offlineFilesRepository.removeAllOfflineNodesCalledTimes == 1, "Expected removeAllOfflineNodes to be called exactly once.")
@Suite("OfflineUseCase offlineSize Tests")
struct OfflineSizeTests {
@Test("Should return correct total size")
func shouldReturnCorrectTotalSize() {
let expectedSize: UInt64 = 1024 * 1024 * 50
let (sut, _, _) = makeSUT(offlineSize: expectedSize)
let result = sut.offlineSize()
#expect(result == expectedSize)
}
}

}
Loading

0 comments on commit 8ffa194

Please sign in to comment.