Implemented some test cases for the "init(configuration: coordination)" and the "fetch()" functions of the FeedListViewModel view model in the Feed framework.
This commit is contained in:
parent
4ea48bd671
commit
5de35984dc
@ -57,7 +57,7 @@ extension FeedListViewController {
|
|||||||
|
|
||||||
var isWordsShowing: Bool {
|
var isWordsShowing: Bool {
|
||||||
filter != .all
|
filter != .all
|
||||||
&& !words.isEmpty
|
&& !words.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Functions
|
// MARK: Functions
|
||||||
@ -89,6 +89,9 @@ extension FeedListViewController {
|
|||||||
items = filter == .all
|
items = filter == .all
|
||||||
? reviewsAll
|
? reviewsAll
|
||||||
: reviewsFiltered[filter] ?? []
|
: reviewsFiltered[filter] ?? []
|
||||||
|
words = filter == .all
|
||||||
|
? []
|
||||||
|
: reviewsTopWords[filter] ?? []
|
||||||
|
|
||||||
isFilterEnabled = !items.isEmpty
|
isFilterEnabled = !items.isEmpty
|
||||||
state = items.isEmpty
|
state = items.isEmpty
|
||||||
|
@ -0,0 +1,264 @@
|
|||||||
|
//
|
||||||
|
// FeedListViewModelTests.swift
|
||||||
|
// ReviewsFeedTests
|
||||||
|
//
|
||||||
|
// Created by Javier Cicchelli on 22/03/2024.
|
||||||
|
// Copyright © 2024 Röck+Cöde. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import ReviewsFoundationKit
|
||||||
|
import ReviewsiTunesKit
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import ReviewsFeed
|
||||||
|
|
||||||
|
final class FeedListViewModelTests: XCTestCase {
|
||||||
|
|
||||||
|
// MARK: Properties
|
||||||
|
private var sut: FeedListViewController.ViewModel!
|
||||||
|
|
||||||
|
private var cancellables: Set<AnyCancellable> = []
|
||||||
|
|
||||||
|
// MARK: Setup
|
||||||
|
override func setUp() async throws {
|
||||||
|
sut = .init(
|
||||||
|
configuration: .init(session: .mock),
|
||||||
|
coordination: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDown() async throws {
|
||||||
|
cancellables.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Initialisers tests
|
||||||
|
func testInit() {
|
||||||
|
// GIVEN
|
||||||
|
// WHEN
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(sut.filter, .all)
|
||||||
|
XCTAssertFalse(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isFiltering)
|
||||||
|
XCTAssertFalse(sut.isLoading)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertTrue(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 0)
|
||||||
|
XCTAssertEqual(sut.state, .initial)
|
||||||
|
XCTAssertTrue(sut.words.isEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Functions tests
|
||||||
|
func testFetch_allItems_whenResponseOK_withSomeItems() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
MockURLProtocol.response = .init(
|
||||||
|
statusCode: 200,
|
||||||
|
object: Feed(entries: .sample)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertTrue(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertFalse(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.items.count, 5)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 5)
|
||||||
|
XCTAssertEqual(sut.state, .populated)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFetch_allItems_whenResponseOK_withNoItems() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
MockURLProtocol.response = .init(
|
||||||
|
statusCode: 200,
|
||||||
|
object: Feed(entries: .none)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertFalse(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertTrue(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 0)
|
||||||
|
XCTAssertEqual(sut.state, .empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFetch_allItems_whenResponseNotOK() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
MockURLProtocol.response = .init(statusCode: 404)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertFalse(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertTrue(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 0)
|
||||||
|
XCTAssertEqual(sut.state, .error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFetch_filteredItems_whenResponseOK_withSomeItems() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
sut.filter = .only1Star
|
||||||
|
|
||||||
|
MockURLProtocol.response = .init(
|
||||||
|
statusCode: 200,
|
||||||
|
object: Feed(entries: .sample)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertTrue(sut.isFilterEnabled)
|
||||||
|
XCTAssertTrue(sut.isWordsShowing)
|
||||||
|
XCTAssertFalse(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.items.count, 1)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 2)
|
||||||
|
XCTAssertEqual(sut.state, .populated)
|
||||||
|
XCTAssertFalse(sut.words.isEmpty)
|
||||||
|
XCTAssertEqual(sut.words.count, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFetch_filteredItems_whenResponseOK_withNoItems() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
sut.filter = .only1Star
|
||||||
|
|
||||||
|
MockURLProtocol.response = .init(
|
||||||
|
statusCode: 200,
|
||||||
|
object: Feed(entries: .none)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertFalse(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertTrue(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 0)
|
||||||
|
XCTAssertEqual(sut.state, .empty)
|
||||||
|
XCTAssertTrue(sut.words.isEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFetch_filteredItems_whenResponseNotOK() {
|
||||||
|
let expectation = XCTestExpectation()
|
||||||
|
|
||||||
|
var isLoading: [Bool] = []
|
||||||
|
|
||||||
|
// GIVEN
|
||||||
|
sut.filter = .only1Star
|
||||||
|
|
||||||
|
MockURLProtocol.response = .init(statusCode: 404)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
sut.fetch()
|
||||||
|
|
||||||
|
sut.$isLoading
|
||||||
|
.collect(3)
|
||||||
|
.sink { value in
|
||||||
|
isLoading.append(contentsOf: value)
|
||||||
|
|
||||||
|
expectation.fulfill()
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
wait(for: [expectation], timeout: 2)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
XCTAssertEqual(isLoading, [false, true, false])
|
||||||
|
XCTAssertFalse(sut.isFilterEnabled)
|
||||||
|
XCTAssertFalse(sut.isWordsShowing)
|
||||||
|
XCTAssertTrue(sut.items.isEmpty)
|
||||||
|
XCTAssertEqual(sut.itemsCount, 0)
|
||||||
|
XCTAssertEqual(sut.state, .error)
|
||||||
|
XCTAssertTrue(sut.words.isEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test
|
||||||
|
|
||||||
|
}
|
@ -18,8 +18,8 @@
|
|||||||
02909E792BAB6B0200710E14 /* FilterOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E782BAB6B0200710E14 /* FilterOption.swift */; };
|
02909E792BAB6B0200710E14 /* FilterOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E782BAB6B0200710E14 /* FilterOption.swift */; };
|
||||||
02909E7B2BAB6D2E00710E14 /* Bundle+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E7A2BAB6D2E00710E14 /* Bundle+Constants.swift */; };
|
02909E7B2BAB6D2E00710E14 /* Bundle+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E7A2BAB6D2E00710E14 /* Bundle+Constants.swift */; };
|
||||||
02909E7D2BAB7FFE00710E14 /* Review+DTOs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E7C2BAB7FFE00710E14 /* Review+DTOs.swift */; };
|
02909E7D2BAB7FFE00710E14 /* Review+DTOs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02909E7C2BAB7FFE00710E14 /* Review+DTOs.swift */; };
|
||||||
02B36F7C2BAD9D1A00F1A89D /* ReviewsFeedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B36F7B2BAD9D1A00F1A89D /* ReviewsFeedTests.swift */; };
|
|
||||||
02B36F7D2BAD9D1A00F1A89D /* ReviewsFeed.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02DC7F8F2BA51793000EEEBE /* ReviewsFeed.framework */; platformFilter = ios; };
|
02B36F7D2BAD9D1A00F1A89D /* ReviewsFeed.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02DC7F8F2BA51793000EEEBE /* ReviewsFeed.framework */; platformFilter = ios; };
|
||||||
|
02B36F852BAD9DDB00F1A89D /* FeedListViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B36F842BAD9DDB00F1A89D /* FeedListViewModelTests.swift */; };
|
||||||
02B36F892BADB26C00F1A89D /* Array+ReviewDTOs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B36F882BADB26C00F1A89D /* Array+ReviewDTOs.swift */; };
|
02B36F892BADB26C00F1A89D /* Array+ReviewDTOs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B36F882BADB26C00F1A89D /* Array+ReviewDTOs.swift */; };
|
||||||
02C1B1972BAC9BFE001781DE /* FeedListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C1B1962BAC9BFE001781DE /* FeedListCoordinator.swift */; };
|
02C1B1972BAC9BFE001781DE /* FeedListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C1B1962BAC9BFE001781DE /* FeedListCoordinator.swift */; };
|
||||||
02C1B1A92BACA722001781DE /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C1B1A82BACA722001781DE /* AppCoordinator.swift */; };
|
02C1B1A92BACA722001781DE /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C1B1A82BACA722001781DE /* AppCoordinator.swift */; };
|
||||||
@ -86,7 +86,7 @@
|
|||||||
02909E7A2BAB6D2E00710E14 /* Bundle+Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Constants.swift"; sourceTree = "<group>"; };
|
02909E7A2BAB6D2E00710E14 /* Bundle+Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Constants.swift"; sourceTree = "<group>"; };
|
||||||
02909E7C2BAB7FFE00710E14 /* Review+DTOs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Review+DTOs.swift"; sourceTree = "<group>"; };
|
02909E7C2BAB7FFE00710E14 /* Review+DTOs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Review+DTOs.swift"; sourceTree = "<group>"; };
|
||||||
02B36F792BAD9D1A00F1A89D /* FeedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FeedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
02B36F792BAD9D1A00F1A89D /* FeedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FeedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
02B36F7B2BAD9D1A00F1A89D /* ReviewsFeedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewsFeedTests.swift; sourceTree = "<group>"; };
|
02B36F842BAD9DDB00F1A89D /* FeedListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListViewModelTests.swift; sourceTree = "<group>"; };
|
||||||
02B36F882BADB26C00F1A89D /* Array+ReviewDTOs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+ReviewDTOs.swift"; sourceTree = "<group>"; };
|
02B36F882BADB26C00F1A89D /* Array+ReviewDTOs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+ReviewDTOs.swift"; sourceTree = "<group>"; };
|
||||||
02C1B1962BAC9BFE001781DE /* FeedListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListCoordinator.swift; sourceTree = "<group>"; };
|
02C1B1962BAC9BFE001781DE /* FeedListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedListCoordinator.swift; sourceTree = "<group>"; };
|
||||||
02C1B1A82BACA722001781DE /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
|
02C1B1A82BACA722001781DE /* AppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = "<group>"; };
|
||||||
@ -254,11 +254,19 @@
|
|||||||
02B36F742BAD9C4500F1A89D /* Tests */ = {
|
02B36F742BAD9C4500F1A89D /* Tests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
02B36F7B2BAD9D1A00F1A89D /* ReviewsFeedTests.swift */,
|
02B36F832BAD9DC700F1A89D /* View Models */,
|
||||||
);
|
);
|
||||||
path = Tests;
|
path = Tests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
02B36F832BAD9DC700F1A89D /* View Models */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
02B36F842BAD9DDB00F1A89D /* FeedListViewModelTests.swift */,
|
||||||
|
);
|
||||||
|
path = "View Models";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
02B36F862BADB1FD00F1A89D /* Previews */ = {
|
02B36F862BADB1FD00F1A89D /* Previews */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -574,7 +582,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
02B36F7C2BAD9D1A00F1A89D /* ReviewsFeedTests.swift in Sources */,
|
02B36F852BAD9DDB00F1A89D /* FeedListViewModelTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user