Added tests for filters screen

This commit is contained in:
Selim Mustafaev 2024-11-12 18:41:49 +03:00
parent ba09884a65
commit 2283ac8fe6
6 changed files with 147 additions and 38 deletions

View File

@ -19,6 +19,8 @@ enum DetailScreen: Hashable {
struct FiltersScreen: View { struct FiltersScreen: View {
@Environment(\.dismiss) var dismiss
@State var viewModel: FiltersViewModel @State var viewModel: FiltersViewModel
var body: some View { var body: some View {
@ -107,6 +109,7 @@ struct FiltersScreen: View {
ToolbarItem(placement: .topBarTrailing) { ToolbarItem(placement: .topBarTrailing) {
Button("Done") { Button("Done") {
viewModel.applyFilters() viewModel.applyFilters()
dismiss()
} }
} }
} }

View File

@ -4,6 +4,11 @@ public struct VehicleRegion: Codable, Hashable, Sendable {
public var name: String public var name: String
public var codes: [Int] public var codes: [Int]
public init(name: String, codes: [Int]) {
self.name = name
self.codes = codes
}
public static func == (lhs: VehicleRegion, rhs: VehicleRegion) -> Bool { public static func == (lhs: VehicleRegion, rhs: VehicleRegion) -> Bool {
return lhs.name == rhs.name return lhs.name == rhs.name
} }

View File

@ -6,8 +6,9 @@
// Copyright © 2024 Selim Mustafaev. All rights reserved. // Copyright © 2024 Selim Mustafaev. All rights reserved.
// //
import Foundation import Mockable
@Mockable
public protocol SettingsServiceProtocol { public protocol SettingsServiceProtocol {
var user: User { get set } var user: User { get set }

View File

@ -0,0 +1,20 @@
//
// TestError.swift
// AutoCatTests
//
// Created by Selim Mustafaev on 12.11.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import Foundation
enum TestError: LocalizedError {
case generic
var errorDescription: String? {
switch self {
case .generic: return "Generic test error"
}
}
}

View File

@ -0,0 +1,117 @@
//
// FiltersTests.swift
// AutoCatTests
//
// Created by Selim Mustafaev on 12.11.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import Testing
import AutoCatCore
import Mockable
@testable import AutoCat
@MainActor
struct FiltersTests {
var settingsServiceMock = MockSettingsServiceProtocol()
var apiServiceMock = MockApiServiceProtocol()
var viewModel: FiltersViewModel
let testBrand = "testBrand"
let testColor = "testColor"
let testModel = "testModel"
let testRegion = VehicleRegion(name: "testRegion", codes: [111])
let testYear = 2222
init() {
ServiceContainer.shared.register(SettingsServiceProtocol.self, instance: settingsServiceMock)
ServiceContainer.shared.register(ApiServiceProtocol.self, instance: apiServiceMock)
viewModel = FiltersViewModel(filter: Filter())
}
@Test("Main filters data loaded")
func mainDataLoaded() async {
given(apiServiceMock)
.getBrands().willReturn([testBrand])
.getColors().willReturn([testColor])
.getRegions().willReturn([testRegion])
.getYears().willReturn([testYear])
.getModels(of: .value(testBrand)).willReturn([testModel])
await viewModel.loadData()
await viewModel.loadModels(brand: testBrand)
verify(apiServiceMock)
.getBrands().called(.once)
.getColors().called(.once)
.getYears().called(.once)
.getModels(of: .value(testBrand)).called(.once)
.getRegions().called(.never)
#expect(viewModel.brands == [.any, .value(testBrand)])
#expect(viewModel.colors == [.any, .value(testColor)])
#expect(viewModel.years == [.any, .value(String(testYear))])
#expect(viewModel.models == [.any, .value(testModel)])
}
@Test("Try second load")
func trySecondLoad() async throws {
viewModel.brands.append(.value(testBrand))
viewModel.colors.append(.value(testColor))
viewModel.years.append(.value(String(testYear)))
viewModel.models.append(.value(testModel))
await viewModel.loadData()
verify(apiServiceMock)
.getBrands().called(.never)
.getColors().called(.never)
.getYears().called(.never)
.getModels(of: .any).called(.never)
.getRegions().called(.never)
#expect(viewModel.brands == [.any, .value(testBrand)])
#expect(viewModel.colors == [.any, .value(testColor)])
#expect(viewModel.years == [.any, .value(String(testYear))])
#expect(viewModel.models == [.any, .value(testModel)])
}
@Test("Load data error")
func loadDataError() async throws {
given(apiServiceMock)
.getBrands().willThrow(TestError.generic)
.getColors().willThrow(TestError.generic)
.getRegions().willThrow(TestError.generic)
.getYears().willThrow(TestError.generic)
.getModels(of: .any).willThrow(TestError.generic)
await viewModel.loadData()
await viewModel.loadModels(brand: testBrand)
#expect(viewModel.brands == [.any])
#expect(viewModel.colors == [.any])
#expect(viewModel.years == [.any])
#expect(viewModel.models == [.any])
}
@Test("Clear all filters")
func clearAllFilters() async throws {
viewModel.currentBrand = .value(testBrand)
viewModel.filter.brand = .value(testBrand)
viewModel.filter.color = .value(testColor)
viewModel.filter.year = .value(String(testYear))
viewModel.filter.model = .value(testModel)
viewModel.clearAllFilters()
#expect(viewModel.filter.brand == .any)
#expect(viewModel.filter.color == .any)
#expect(viewModel.filter.year == .any)
#expect(viewModel.filter.model == .any)
}
}

View File

@ -1,37 +0,0 @@
//
// ApiServiceMock.swift
// AutoCatTests
//
// Created by Selim Mustafaev on 13.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import AutoCatCore
actor ApiServiceMock {
var vehicle = VehicleDto()
func setVehicle(_ vehicle: VehicleDto) async {
self.vehicle = vehicle
}
func addNote(text: String) async {
vehicle.notes.append(VehicleNoteDto(text: text))
}
}
extension ApiServiceMock: ApiServiceProtocol {
func add(notes: [VehicleNoteDto], to number: String) async throws -> VehicleDto {
vehicle
}
func edit(note: VehicleNoteDto) async throws -> VehicleDto {
vehicle
}
func remove(note id: String) async throws -> VehicleDto {
vehicle
}
}