AutoCat/AutoCatTests/SearchTests.swift

242 lines
7.7 KiB
Swift

//
// SearchTests.swift
// AutoCatTests
//
// Created by Selim Mustafaev on 22.02.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import Testing
import Mockable
import AutoCatCore
@testable import AutoCat
@MainActor
struct SearchTests {
let apiServiceMock = MockApiServiceProtocol()
let vehicleServiceMock = MockVehicleServiceProtocol()
var viewModel: SearchViewModel
init() {
viewModel = SearchViewModel(
apiService: apiServiceMock,
vehicleService: vehicleServiceMock
)
}
@Test("Initial load")
func initialLoad() async {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .value(nil), pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
await viewModel.onAppear()
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .value(nil), pageSize: .any)
.called(.once)
#expect(viewModel.vehicles == [.normal])
#expect(viewModel.vehicleSections.count == 1)
#expect(viewModel.searchText == "")
#expect(viewModel.hud == nil)
}
@Test("Initial load error")
func initialLoadError() async {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .value(nil), pageSize: .any)
.willThrow(TestError.generic)
await viewModel.onAppear()
#expect(viewModel.vehicles.isEmpty)
#expect(viewModel.hud == .error(TestError.generic))
}
@Test("Search")
func search() async throws {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
await viewModel.onAppear()
viewModel.searchText = "test1"
viewModel.searchText = "test2"
try await Task.sleep(for: .milliseconds(600))
viewModel.searchText = "test3"
try await Task.sleep(for: .milliseconds(600))
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.exactly(3))
#expect(viewModel.vehicles == [.normal])
#expect(viewModel.vehicleSections.count == 1)
#expect(viewModel.filter.searchString == "test3")
#expect(viewModel.hud == nil)
}
@Test("Search error")
func searchError() async throws {
var filterWithString = Filter()
filterWithString.searchString = "test"
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willThrow(TestError.generic)
await viewModel.onAppear()
viewModel.searchText = "test"
try await Task.sleep(for: .milliseconds(600))
#expect(viewModel.vehicles.isEmpty)
#expect(viewModel.hud == .error(TestError.generic))
}
@Test("Pagination")
func pagination() async {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: []))
await viewModel.onAppear()
await viewModel.loadMoreData()
await viewModel.loadMoreData()
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.exactly(3))
#expect(viewModel.vehicles.count == 2)
#expect(viewModel.hasMoreData == false)
#expect(viewModel.hud == nil)
}
@Test("Pagination error")
func paginationError() async {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willThrow(TestError.generic)
await viewModel.onAppear()
await viewModel.loadMoreData()
await viewModel.loadMoreData()
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.exactly(3))
#expect(viewModel.vehicles.count == 2)
#expect(viewModel.hasMoreData == false)
#expect(viewModel.hud == .error(TestError.generic))
}
@Test("Update vehicle")
func updateVehicle() async {
let updatedVehicle: VehicleDto = .normal
.addEvent(.valid)
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
given(vehicleServiceMock)
.updateSearch(number: .value(VehicleDto.normal.number))
.willReturn((updatedVehicle, []))
await viewModel.onAppear()
await viewModel.updateVehicle(.normal)
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.once)
verify(vehicleServiceMock)
.updateSearch(number: .any)
.called(.once)
#expect(viewModel.vehicles.first?.events.isEmpty == false)
#expect(viewModel.hud == nil)
}
@Test("Update vehicle error")
func updateVehicleError() async {
let updatedVehicle: VehicleDto = .normal
.addEvent(.valid)
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
given(vehicleServiceMock)
.updateSearch(number: .value(VehicleDto.normal.number))
.willReturn((updatedVehicle, [TestError.generic]))
await viewModel.onAppear()
await viewModel.updateVehicle(.normal)
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.once)
verify(vehicleServiceMock)
.updateSearch(number: .any)
.called(.once)
#expect(viewModel.vehicles.first?.events.isEmpty == true)
if case .message(_, _) = viewModel.hud {} else {
Issue.record("hud must be in .message state")
}
}
@Test("Update vehicle error 2")
func updateVehicleError2() async {
given(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.willReturn(PagedResponse(items: [VehicleDto.normal]))
given(vehicleServiceMock)
.updateSearch(number: .value(VehicleDto.normal.number))
.willThrow(TestError.generic)
await viewModel.onAppear()
await viewModel.updateVehicle(.normal)
verify(apiServiceMock)
.getVehicles(with: .any, pageToken: .any, pageSize: .any)
.called(.once)
verify(vehicleServiceMock)
.updateSearch(number: .any)
.called(.once)
#expect(viewModel.vehicles.first?.events.isEmpty == true)
#expect(viewModel.hud == .error(TestError.generic))
}
}