AutoCat/AutoCatCoreTests/VehicleServiceTests.swift

425 lines
14 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// VehicleServiceTests.swift
// AutoCatCoreTests
//
// Created by Selim Mustafaev on 24.01.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import Testing
import Mockable
import AutoCatCore
struct VehicleServiceTests {
let apiServiceMock = MockApiServiceProtocol()
let storageServiceMock = MockStorageServiceProtocol()
let locationServiceMock: MockLocationServiceProtocol
let vehicleService: VehicleServiceProtocol
let existingVehicleNumber = "А123АА761"
let nonExistingVehicleNumber = "А999АА761"
let testVin = "1234567890"
init () async throws {
self.locationServiceMock = await .init()
self.vehicleService = VehicleService(apiService: apiServiceMock,
storageService: storageServiceMock,
locationService: locationServiceMock)
}
@Test("Check vehicle (all throws)")
func checkVehicleAllThrows() async throws {
given(storageServiceMock)
.loadVehicle(number: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.getRecentLocation()
.willThrow(TestError.generic)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willThrow(TestError.generic)
await #expect(throws: TestError.generic) {
_ = try await vehicleService.check(number: existingVehicleNumber)
}
}
@Test("Check vehicle (all but DB update throws)")
func checkVehicleDbUpdate() async throws {
given(storageServiceMock)
.loadVehicle(number: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.getRecentLocation()
.willThrow(TestError.generic)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
let result = try await vehicleService.check(number: existingVehicleNumber)
#expect(result.vehicle.unrecognized)
#expect(result.vehicle.events.isEmpty)
#expect(result.errors.count == 2)
}
@Test("Check vehicle (existing unrecognized vehicle)")
func checkVehicleExistingVehicle() async throws {
var vehicle = VehicleDto(number: existingVehicleNumber)
vehicle.vin1 = testVin
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(vehicle)
given(locationServiceMock)
.getRecentLocation()
.willThrow(TestError.generic)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
let result = try await vehicleService.check(number: existingVehicleNumber)
#expect(result.vehicle.vin1 == testVin)
#expect(result.errors.count == 2)
}
@Test("Check vehicle (location received)")
func checkVehicleLocationReceived() async throws {
var vehicle = VehicleDto(number: existingVehicleNumber)
vehicle.vin1 = testVin
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(vehicle)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
let result = try await vehicleService.check(number: VehicleDto.validNumber)
#expect(result.vehicle.vin1 == testVin)
#expect(result.errors.count == 1)
#expect(result.vehicle.events.count == 1)
#expect(result.vehicle.events.first?.latitude == VehicleEventDto.validLatitude)
#expect(result.vehicle.events.first?.longitude == VehicleEventDto.validLongitude)
}
@Test("Check vehicle (existing normal vehicle)")
func checkVehicleExistingNormalVehicle() async throws {
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willThrow(TestError.generic)
let result = try await vehicleService.check(number: VehicleDto.validNumber)
#expect(result.vehicle.number == VehicleDto.validNumber)
#expect(result.errors.count == 2)
#expect(result.vehicle.events.count == 1)
#expect(result.vehicle.events.first?.latitude == VehicleEventDto.validLatitude)
#expect(result.vehicle.events.first?.longitude == VehicleEventDto.validLongitude)
}
@Test("Check vehicle (existing normal vehicle, add event)")
func checkVehicleExistingNormalVehicleAddEvent() async throws {
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willThrow(TestError.generic)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willReturn(.normal.addEvent(.valid))
let result = try await vehicleService.check(number: VehicleDto.validNumber)
#expect(result.vehicle.number == VehicleDto.validNumber)
#expect(result.errors.count == 1)
#expect(result.vehicle.events.count == 1)
#expect(result.vehicle.events.first?.latitude == VehicleEventDto.validLatitude)
#expect(result.vehicle.events.first?.longitude == VehicleEventDto.validLongitude)
}
@Test("Check vehicle (with server check working)")
func checkVehicleServerCheck() async throws {
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willReturn(.normal)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willReturn(.normal.addEvent(.valid))
let result = try await vehicleService.check(number: VehicleDto.validNumber)
#expect(result.vehicle.number == VehicleDto.validNumber)
#expect(result.errors.count == 0)
#expect(result.vehicle.events.count == 1)
#expect(result.vehicle.events.first?.latitude == VehicleEventDto.validLatitude)
#expect(result.vehicle.events.first?.longitude == VehicleEventDto.validLongitude)
}
@Test("Check")
func check() async throws {
let vehicle: VehicleDto = .normal
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willReturn(vehicle)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willReturn(vehicle.addEvent(.valid))
let result = try await vehicleService.check(number: vehicle.number)
verify(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .value(false))
.called(.once)
verify(locationServiceMock)
.getRecentLocation()
.called(.once)
verify(apiServiceMock)
.add(event: .any, to: .any)
.called(.once)
verify(storageServiceMock)
.updateVehicle(dto: .any, policy: .value(.always))
.called(.once)
#expect(result.vehicle.number == vehicle.number)
#expect(result.errors.count == 0)
#expect(result.vehicle.events.count == 1)
#expect(result.vehicle.events.first?.latitude == VehicleEventDto.validLatitude)
#expect(result.vehicle.events.first?.longitude == VehicleEventDto.validLongitude)
}
@Test("Update (history)")
func updateHistory() async throws {
let vehicle: VehicleDto = .normal
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willReturn(vehicle)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willReturn(vehicle.addEvent(.valid))
let result = try await vehicleService.updateHistory(number: vehicle.number)
verify(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .value(true))
.called(.once)
verify(locationServiceMock)
.getRecentLocation()
.called(.never)
verify(apiServiceMock)
.add(event: .any, to: .any)
.called(.never)
verify(storageServiceMock)
.updateVehicle(dto: .any, policy: .value(.always))
.called(.once)
#expect(result.vehicle.number == vehicle.number)
#expect(result.errors.count == 0)
#expect(result.vehicle.events.count == 0)
}
@Test("Update (search)")
func updateSearch() async throws {
let vehicle: VehicleDto = .normal
given(storageServiceMock)
.loadVehicle(number: .any)
.willReturn(.normal)
given(locationServiceMock)
.getRecentLocation()
.willReturn(.valid)
given(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .any)
.willReturn(vehicle)
given(locationServiceMock)
.resetLastEvent()
.willReturn()
given(storageServiceMock)
.updateVehicle(dto: .any, policy: .any)
.willReturn(true)
given(apiServiceMock)
.add(event: .any, to: .any)
.willReturn(vehicle.addEvent(.valid))
let result = try await vehicleService.updateSearch(number: vehicle.number)
verify(apiServiceMock)
.checkVehicle(by: .any, notes: .any, events: .any, force: .value(true))
.called(.once)
verify(locationServiceMock)
.getRecentLocation()
.called(.never)
verify(apiServiceMock)
.add(event: .any, to: .any)
.called(.never)
verify(storageServiceMock)
.updateVehicle(dto: .any, policy: .value(.ifExists))
.called(.once)
#expect(result.vehicle.number == vehicle.number)
#expect(result.errors.count == 0)
#expect(result.vehicle.events.count == 0)
}
}