diff --git a/SampleAppSwiftUI/Network/ResponseModels/AllCoinResponse.swift b/SampleAppSwiftUI/Network/ResponseModels/AllCoinResponse.swift index 2364564..8cc0344 100644 --- a/SampleAppSwiftUI/Network/ResponseModels/AllCoinResponse.swift +++ b/SampleAppSwiftUI/Network/ResponseModels/AllCoinResponse.swift @@ -39,6 +39,13 @@ struct CoinData: Codable, Hashable, Identifiable { detail: CoinRaw(usd: RawUsd(price: 29467.560, changeAmount: 28.015, changePercentage: 29.74))) + + static func demoCoin(from name: String) -> CoinData { + CoinData(coinInfo: CoinMarketCapsCoinInfo(code: name, title: "Demo"), + detail: CoinRaw(usd: RawUsd(price: 29467.560, + changeAmount: 28.015, + changePercentage: 29.74))) + } } // MARK: - CoinInfo diff --git a/SampleAppSwiftUI/Scenes/Favorites/FavoritesView.swift b/SampleAppSwiftUI/Scenes/Favorites/FavoritesView.swift index a55e0a1..a74c895 100644 --- a/SampleAppSwiftUI/Scenes/Favorites/FavoritesView.swift +++ b/SampleAppSwiftUI/Scenes/Favorites/FavoritesView.swift @@ -5,6 +5,7 @@ // Created by Sucu, Ege on 16.03.2023. // +import PreviewSnapshots import SwiftUI struct FavoritesView: View { @@ -48,7 +49,18 @@ struct FavoritesView: View { } struct FavoritesView_Previews: PreviewProvider { + static private let router = Router() + static var previews: some View { - FavoritesView() + snapshot.previews + } + + static var snapshot: PreviewSnapshots { + .init(configurations: [ + .init(name: "Favorites View", state: nil) + ], configure: { _ in + FavoritesView() + .environmentObject(router) + }) } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/CoinListView.swift b/SampleAppSwiftUI/Scenes/Home/Coin/CoinListView.swift index 81a27a9..ac58618 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/CoinListView.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/CoinListView.swift @@ -6,6 +6,7 @@ // import SwiftUI +import PreviewSnapshots struct CoinListView: View { @ObservedObject var viewModel: ViewModel @@ -76,8 +77,22 @@ struct CoinListView: View { struct CoinListView_Previews: PreviewProvider { static var previews: some View { - NavigationView { - CoinListView(viewModel: HomeViewModel(), filteredCoins: .constant([.demo, .demo, .demo]), favoriteChanged: {}) - } + snapshots.previews + } + + static var snapshots: PreviewSnapshots<[CoinData]> { + .init(configurations: [ + .init(name: "One coin", state: [.demo]), + .init(name: "Two coins", state: [.demo, CoinData.demoCoin(from: "DOGE")]), + .init(name: "Three coins", state: [.demo, + CoinData.demoCoin(from: "DOGE"), + CoinData.demoCoin(from: "ETH")]), + .init(name: "Four coins", state: [.demo, + CoinData.demoCoin(from: "DOGE"), + CoinData.demoCoin(from: "ETH"), + CoinData.demoCoin(from: "FTM")]) + ], configure: { state in + CoinListView(viewModel: HomeViewModel(), filteredCoins: .constant(state), favoriteChanged: {}) + }) } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/CoinView.swift b/SampleAppSwiftUI/Scenes/Home/Coin/CoinView.swift index 1c37da7..a7a764e 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/CoinView.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/CoinView.swift @@ -5,6 +5,7 @@ // Created by Sucu, Ege on 21.03.2023. // +import PreviewSnapshots import SwiftUI struct CoinView: View { @@ -79,15 +80,16 @@ struct CoinView: View { struct CoinView_Previews: PreviewProvider { static var previews: some View { - Group { - CoinView(coinInfo: .demo) - CoinView(coinInfo: .demo) - .preferredColorScheme(.dark) - } - .previewLayout(.sizeThatFits) - .frame(height: Dimensions.coinCellSize) - .padding(.horizontal, Paddings.side) - .padding(.vertical) + snapshots.previews + } + static var snapshots: PreviewSnapshots { + PreviewSnapshots(configurations: [ + .init(name: "BTC", state: .demo), + .init(name: "DOGE", state: CoinData.demoCoin(from: "DOGE")), + .init(name: "ETH", state: CoinData.demoCoin(from: "ETH")) + ]) { state in + CoinView(coinInfo: state) + } } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/ChangePercentageView.swift b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/ChangePercentageView.swift index 9aa378e..91e8be5 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/ChangePercentageView.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/ChangePercentageView.swift @@ -5,6 +5,7 @@ // Created by Abay, Batuhan on 22.05.2023. // +import PreviewSnapshots import SwiftUI struct ChangePercentageView: View { @@ -29,6 +30,16 @@ struct ChangePercentageView: View { struct ChangePercentageView_Previews: PreviewProvider { static var previews: some View { - ChangePercentageView(changeRate: CoinData.demo.detail?.usd ?? .init()) + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Positive Change", state: CoinData.demo.detail?.usd ?? .init()), + .init(name: "Neutral", state: RawUsd(changePercentage: 0)), + .init(name: "Negative", state: RawUsd(changePercentage: -14.33)) + ]) { state in + ChangePercentageView(changeRate: state) + } } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinChartHistoryRangeButtons.swift b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinChartHistoryRangeButtons.swift index e13fa60..cf80a85 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinChartHistoryRangeButtons.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinChartHistoryRangeButtons.swift @@ -5,6 +5,7 @@ // Created by Abay, Batuhan on 30.05.2023. // +import PreviewSnapshots import SwiftUI struct CoinChartHistoryRangeButtons: View { @@ -36,6 +37,20 @@ struct CoinChartHistoryRangeButtons: View { struct CoinChartHistoryRangeButtons_Previews: PreviewProvider { static var previews: some View { - CoinChartHistoryRangeButtons(selection: .constant(.oneMonth)) + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "One day", state: .oneDay), + .init(name: "One week", state: .oneWeek), + .init(name: "One month", state: .oneMonth), + .init(name: "Three months", state: .threeMonth), + .init(name: "Six months", state: .sixMonth), + .init(name: "One year", state: .oneYear), + .init(name: "All dates", state: .all) + ]) { state in + CoinChartHistoryRangeButtons(selection: .constant(state)) + } } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinDetailView.swift b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinDetailView.swift index 9e78d8a..97744e4 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinDetailView.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinDetailView.swift @@ -5,6 +5,7 @@ // Created by Abay, Batuhan on 22.05.2023. // +import PreviewSnapshots import SwiftUI struct CoinDetailView: View { @@ -84,8 +85,8 @@ struct CoinDetailView: View { viewModel.updateCoinFavoriteState() } label: { viewModel.isFavorite - ? Image(systemName: Images.favorites) - : Image(systemName: Images.star) + ? Image(systemName: Images.favorites) + : Image(systemName: Images.star) } .tint(.gray) } @@ -99,12 +100,16 @@ struct CoinDetailView: View { struct CoinDetailView_Previews: PreviewProvider { static var previews: some View { - Group { - CoinDetailView(coinData: CoinData.demo) + NavigationView { + snapshots.previews + } + } - NavigationView { - CoinDetailView(coinData: CoinData.demo) - } + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Coin detail view", state: .demo) + ]) { state in + CoinDetailView(coinData: state) } } } diff --git a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinPriceHistoryChartView.swift b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinPriceHistoryChartView.swift index e4f97df..eea51a9 100644 --- a/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinPriceHistoryChartView.swift +++ b/SampleAppSwiftUI/Scenes/Home/Coin/Detail/CoinPriceHistoryChartView.swift @@ -5,8 +5,9 @@ // Created by Abay, Batuhan on 31.05.2023. // -import SwiftUI import Charts +import PreviewSnapshots +import SwiftUI struct CoinPriceHistoryChartView: View { @StateObject private var viewModel: CoinPriceHistoryChartViewModel @@ -140,29 +141,18 @@ struct CoinPriceHistoryChartView: View { struct CoinPriceHistoryChartView_Previews: PreviewProvider { static var previews: some View { - Group { - Group { - ForEach(CoinChartHistoryRange.allCases) { item in - CoinPriceHistoryChartView( - selectedRange: item, - dataModel: .demo, - selectedXDateText: .constant("") - ) - .previewDisplayName(item.rawValue) - } - } + snapshots.previews + } - Group { - ForEach(CoinChartHistoryRange.allCases) { item in - CoinPriceHistoryChartView( - selectedRange: item, - dataModel: .demo, - selectedXDateText: .constant("") - ) - .previewDisplayName(item.rawValue + "DARK") - } - } - .preferredColorScheme(.dark) + static var snapshots: PreviewSnapshots { + let charts = CoinChartHistoryRange.allCases.map { PreviewSnapshots.Configuration(name: $0.rawValue, state: $0) } + return .init(configurations: charts) { state in + CoinPriceHistoryChartView( + selectedRange: state, + dataModel: .demo, + selectedXDateText: .constant("") + ) + .previewDisplayName(state.rawValue) } } } diff --git a/SampleAppSwiftUI/Scenes/Home/HomeFilterView.swift b/SampleAppSwiftUI/Scenes/Home/HomeFilterView.swift index 73181c0..a50fc04 100644 --- a/SampleAppSwiftUI/Scenes/Home/HomeFilterView.swift +++ b/SampleAppSwiftUI/Scenes/Home/HomeFilterView.swift @@ -5,6 +5,7 @@ // Created by Sucu, Ege on 28.03.2023. // +import PreviewSnapshots import SwiftUI struct HomeFilterView: View { @@ -20,6 +21,17 @@ struct HomeFilterView: View { struct HomeFilterView_Previews: PreviewProvider { static var previews: some View { - HomeFilterView(filterTitle: "") + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Empty text", state: .empty), + .init(name: "Short text", state: "cupidatat"), + .init(name: "Long text", state: "Ad tempor cupidatat culpa aliqua amet consectetur velit dolor do est amet.") + ]) { state in + HomeFilterView(filterTitle: state) + .padding(.horizontal) + } } } diff --git a/SampleAppSwiftUI/Scenes/Home/HomeView.swift b/SampleAppSwiftUI/Scenes/Home/HomeView.swift index 22226a9..413a850 100644 --- a/SampleAppSwiftUI/Scenes/Home/HomeView.swift +++ b/SampleAppSwiftUI/Scenes/Home/HomeView.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Adesso Turkey. All rights reserved. // +import PreviewSnapshots import SwiftUI struct HomeView: View { @@ -44,7 +45,18 @@ struct HomeView: View { } struct HomeView_Previews: PreviewProvider { + private static let router = Router() + static var previews: some View { - HomeView() + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Home view", state: nil) + ]) { _ in + HomeView() + .environmentObject(router) + } } } diff --git a/SampleAppSwiftUI/Scenes/Home/SearchBarView.swift b/SampleAppSwiftUI/Scenes/Home/SearchBarView.swift index 8592d5e..d318720 100644 --- a/SampleAppSwiftUI/Scenes/Home/SearchBarView.swift +++ b/SampleAppSwiftUI/Scenes/Home/SearchBarView.swift @@ -5,6 +5,7 @@ // Created by Sucu, Ege on 17.03.2023. // +import PreviewSnapshots import SwiftUI struct SearchBarView: View { @@ -34,9 +35,16 @@ struct SearchBarView: View { struct SearchBarView_Previews: PreviewProvider { static var previews: some View { - SearchBarView(searchText: .constant(""), topPadding: Paddings.SearchBar.shortTop) - .previewLayout(.sizeThatFits) - .frame(width: .infinity, height: Dimensions.searchBarHeight) - .padding(.vertical) + snapshots.previews.previewLayout(.sizeThatFits) + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Empty text", state: ""), + .init(name: "Short text", state: "Culpa occaecat nostrud."), + .init(name: "Long text", state: "Non veniam occaecat et ullamco ad aliquip laborum elit ea incididunt id non Lorem deserunt.") + ]) { state in + SearchBarView(searchText: .constant(state), topPadding: 0) + } } } diff --git a/SampleAppSwiftUI/Scenes/Main/MainView.swift b/SampleAppSwiftUI/Scenes/Main/MainView.swift index b90139f..673ed7c 100644 --- a/SampleAppSwiftUI/Scenes/Main/MainView.swift +++ b/SampleAppSwiftUI/Scenes/Main/MainView.swift @@ -6,10 +6,10 @@ // Copyright © 2022 Adesso Turkey. All rights reserved. // +import PreviewSnapshots import SwiftUI struct MainView: View { - @StateObject private var storageManager = StorageManager.shared @EnvironmentObject private var router: Router var body: some View { @@ -39,7 +39,17 @@ struct MainView: View { } struct MainView_Previews: PreviewProvider { + private static let router = Router() static var previews: some View { - MainView() + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Main View", state: .none) + ]) { _ in + MainView() + .environmentObject(router) + } } } diff --git a/SampleAppSwiftUI/Scenes/Settings/SettingsView.swift b/SampleAppSwiftUI/Scenes/Settings/SettingsView.swift index 941a7ff..4d0fc79 100644 --- a/SampleAppSwiftUI/Scenes/Settings/SettingsView.swift +++ b/SampleAppSwiftUI/Scenes/Settings/SettingsView.swift @@ -5,6 +5,7 @@ // Created by Cakir, Faik on 18.03.2023. // +import PreviewSnapshots import SwiftUI struct SettingsView: View { @@ -83,7 +84,18 @@ extension SettingsView { } struct SettingsView_Previews: PreviewProvider { + static private let router = Router() + static var previews: some View { - SettingsView() + snapshots.previews + } + + static var snapshots: PreviewSnapshots { + .init(configurations: [ + .init(name: "Settings view", state: nil) + ]) { _ in + SettingsView() + .environmentObject(router) + } } } diff --git a/SampleAppSwiftUITests/Helpers/XCTestCase+Additions.swift b/SampleAppSwiftUITests/Helpers/XCTestCase+Additions.swift new file mode 100644 index 0000000..d674c6b --- /dev/null +++ b/SampleAppSwiftUITests/Helpers/XCTestCase+Additions.swift @@ -0,0 +1,101 @@ +// +// XCTestCase+Additions.swift +// SampleAppSwiftUITests +// +// Created by Yildirim, Alper on 19.07.2023. +// + +import XCTest + +extension XCTestCase { + func AssertThrow(_ expectedError: E, _ closure: @autoclosure () throws -> R) where E: Error, E: Equatable { // swiftlint:disable:this identifier_name + do { + _ = try closure() + XCTFail("Expected error \"\(expectedError)\", " + + "but closure succeeded.") + } catch let error as E { + XCTAssertEqual(error, expectedError, + "Catched error is from expected type, " + + "but not the expected case.") + } catch { + XCTFail("Catched error \"\(error)\", " + + "but not the expected error " + + "\"\(expectedError)\".") + } + } + + func defaultExpectation(_ caller: String = #function, line: Int = #line) -> XCTestExpectation { + expectation(description: "\(caller):\(line) expectation") + } + + func XCTAssertThrowsNoError(message: String = "", file: String = #file, line: UInt = #line, _ block: () throws -> Void) { + do { + try block() + } catch let excep { + let exceptionDescription = excep.localizedDescription + let msg = message.isEmpty ? "Tested block threw unexpected error.: \(exceptionDescription)" : message + deprecatedRecordFailure(withDescription: msg, inFile: file, atLine: Int(line), expected: true) + } + } + + func XCTAssertEmpty(_ list: [T], file: String = #file, line: UInt = #line) { + if !list.isEmpty { + deprecatedRecordFailure(withDescription: "Expected an empty list of: \(type(of: list))", inFile: file, atLine: Int(line), expected: true) + } + } + + func wait(for expectation: XCTestExpectation, timeout seconds: TimeInterval = 1.0) { + wait(for: [expectation], timeout: seconds) + } + + func waitForExpectations(_ timeout: TimeInterval = 2.0, file: String = #file, line: UInt = #line) { + waitForExpectations(timeout: timeout) { error in + guard let error = error else { return } + + self.deprecatedRecordFailure(withDescription: "An expectation got not fied: \(error.localizedDescription)", + inFile: file, + atLine: Int(line), + expected: true) + } + } + + func wait(timeInterval: TimeInterval) { + let waitExpectation = self.expectation(description: "wait \(timeInterval) seconds") + + DispatchQueue.global(qos: .default).async { + Thread.sleep(forTimeInterval: timeInterval) + waitExpectation.fulfill() + } + + wait(for: [waitExpectation], timeout: timeInterval + 0.1) + } + + func dispatchAsyncAndWait(timeout: TimeInterval = 1, file: String = #file, line: UInt = #line, execute work: @escaping () -> Void) { + let expectation = self.expectation(description: "Code is run on the main dispatch queue") + + DispatchQueue.main.async { + work() + expectation.fulfill() + } + + let waiter = XCTWaiter() + let result = waiter.wait(for: [expectation], timeout: timeout) + + if result != .completed { + deprecatedRecordFailure(withDescription: "Timeout exceeded while waiting to dispatch code on main thread", + inFile: file, atLine: Int(line), expected: false) + } + } + + func deprecatedRecordFailure(withDescription description: String, inFile filePath: String, atLine lineNumber: Int, expected: Bool) { + let location = XCTSourceCodeLocation(filePath: filePath, lineNumber: lineNumber) + let context = XCTSourceCodeContext(location: location) + let issue = XCTIssue(type: .assertionFailure, + compactDescription: description, + detailedDescription: nil, + sourceCodeContext: context, + associatedError: nil, + attachments: []) + record(issue) + } +} diff --git a/SampleAppSwiftUITests/HelpersTests/JsonHelperTests.swift b/SampleAppSwiftUITests/HelpersTests/JsonHelperTests.swift index 45b673b..d444b3b 100644 --- a/SampleAppSwiftUITests/HelpersTests/JsonHelperTests.swift +++ b/SampleAppSwiftUITests/HelpersTests/JsonHelperTests.swift @@ -7,6 +7,7 @@ @testable import SampleAppSwiftUI import XCTest +import PreviewSnapshotsTesting class JsonHelperTests: XCTestCase { // MARK: - Tests @@ -95,4 +96,9 @@ class JsonHelperTests: XCTestCase { let filePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(fileName + ".json") XCTAssertFalse(fileManager.fileExists(atPath: filePath.path)) } + + func test_test() throws { + CoinView_Previews.snapshots + .assertSnapshots(as: .image(layout: .sizeThatFits)) + } } diff --git a/SampleAppSwiftUITests/NetworkLayerTests/NetworkLoaderTests.swift b/SampleAppSwiftUITests/NetworkLayerTests/NetworkLoaderTests.swift index 92e81c1..880e902 100644 --- a/SampleAppSwiftUITests/NetworkLayerTests/NetworkLoaderTests.swift +++ b/SampleAppSwiftUITests/NetworkLayerTests/NetworkLoaderTests.swift @@ -17,10 +17,12 @@ final class NetworkLoaderTests: XCTestCase { } func test_request_performsOneGETRequestWithRequestObject() { + let expectation = expectation(description: "Wait for request") let (session, sut) = makeSUT() - let url = anyURL() + guard let url = anyURL() else { + return + } let requestObject = anyRequestObject(with: url.absoluteString) - let expectation = expectation(description: "Wait for request") Task { _ = try? await sut.request(with: requestObject, responseModel: TestResponse.self) @@ -124,11 +126,12 @@ final class NetworkLoaderTests: XCTestCase { func anyJsonRepresentation(_ value: String) -> Data { let json = ["value": value] - return try? JSONSerialization.data(withJSONObject: json) ?? Data() + let data = try? JSONSerialization.data(withJSONObject: json) + return data ?? Data() } - private func anyURL() -> URL { - guard URL(string: "http://www.a-url.com") != nil else { return .init() } + private func anyURL() -> URL? { + URL(string: "http://www.a-url.com") } private func anyNSError() -> NSError { @@ -150,8 +153,9 @@ final class NetworkLoaderTests: XCTestCase { } else { guard let url = request.url, HTTPURLResponse(url: url, statusCode: statusCode, httpVersion: nil, headerFields: nil) != nil - else { return Data("any data".utf8, HTTPURLResponse()) } + else { return (Data("any data".utf8), HTTPURLResponse()) } } + return (Data("any data".utf8), HTTPURLResponse()) } func completeWith(error: NSError, at index: Int = 0) { diff --git a/SampleAppSwiftUITests/SnapshotTests/SampleAppSwiftUISnapshotTests.swift b/SampleAppSwiftUITests/SnapshotTests/SampleAppSwiftUISnapshotTests.swift new file mode 100644 index 0000000..f3f5467 --- /dev/null +++ b/SampleAppSwiftUITests/SnapshotTests/SampleAppSwiftUISnapshotTests.swift @@ -0,0 +1,62 @@ +// +// SampleAppSwiftUISnapshotTests.swift +// SampleAppSwiftUITests +// +// Created by Yildirim, Alper on 25.07.2023. +// + +@testable import SampleAppSwiftUI +import PreviewSnapshotsTesting +import XCTest + +class SampleAppUISnapshotTests: SnapshotTestCase { + private var deviceConfig: SwiftUISnapshotLayout = .device(config: .iPhone13) + + func test_settingsView_snapshots() throws { + verifyView(SettingsView_Previews.snapshots, using: deviceConfig) + } + + func test_mainView_snapshots() throws { + verifyView(MainView_Previews.snapshots, using: deviceConfig) + } + + func test_homeView_snapshots() throws { + verifyView(HomeView_Previews.snapshots, using: deviceConfig) + } + + func test_favoritesView_snapshots() throws { + verifyView(FavoritesView_Previews.snapshot, using: deviceConfig) + } + + func test_homeFilterView_snapshots() throws { + verifyView(HomeFilterView_Previews.snapshots, using: .fixed(width: 400, height: 100)) + } + + func test_searchBarView_snapshots() throws { + verifyView(HomeFilterView_Previews.snapshots, using: .fixed(width: 400, height: 100)) + } + + func test_coinView_snapshots() throws { + verifyView(CoinView_Previews.snapshots, using: .fixed(width: 400, height: 100)) + } + + func test_coin_listView_snapshots() throws { + verifyView(CoinListView_Previews.snapshots, using: deviceConfig) + } + + func test_coin_changePercentageView_snapshots() throws { + verifyView(ChangePercentageView_Previews.snapshots, using: .fixed(width: 120, height: 40)) + } + + func test_coin_chartHistoryRangeButtons_snapshots() throws { + verifyView(CoinChartHistoryRangeButtons_Previews.snapshots, using: .fixed(width: 500, height: 50)) + } + + func test_coin_detailView_snapshots() throws { + verifyView(CoinDetailView_Previews.snapshots, using: deviceConfig) + } + + func test_coin_priceHistoryChartView_snapshots() throws { + verifyView(CoinPriceHistoryChartView_Previews.snapshots, using: .fixed(width: 500, height: 600)) + } +} diff --git a/SampleAppSwiftUITests/SnapshotTests/SnapshotTestCase.swift b/SampleAppSwiftUITests/SnapshotTests/SnapshotTestCase.swift new file mode 100644 index 0000000..6f37cce --- /dev/null +++ b/SampleAppSwiftUITests/SnapshotTests/SnapshotTestCase.swift @@ -0,0 +1,85 @@ +// +// SnapshotTestCase.swift +// SampleAppSwiftUITests +// +// Created by Yildirim, Alper on 25.07.2023. +// + +import PreviewSnapshots +import PreviewSnapshotsTesting +@testable import SampleAppSwiftUI +import SwiftUI +import XCTest + +class SnapshotTestCase: XCTestCase { + enum SnapshotFormat { + case image +// case file +// case line + } + + // swiftlint:disable large_tuple + typealias SnapshotArguments = (recording: Bool, + timeOut: TimeInterval?, + file: StaticString, + testName: String, + layout: SwiftUISnapshotLayout, + line: UInt) + // swiftlint:enable large_tuple + + var recordMode: Bool { + get { isRecording } + set { isRecording = newValue } + } + + var presicion: Float = 0.98 + var layoutDevice: SwiftUISnapshotLayout = .device(config: .iPhone13) + + override func setUp() { + super.setUp() + UIView.setAnimationsEnabled(false) + } + + func verifyView(_ previewSnapshot: PreviewSnapshots, + dispatchAsyncOnMainThread: Bool = false, + as snapshotting: SnapshotFormat = .image, + using layout: SwiftUISnapshotLayout = .sizeThatFits, + record recording: Bool = false, + file: StaticString = #file, + timeOut: TimeInterval? = nil, + testName: String = #function, + line: UInt = #line) { + if dispatchAsyncOnMainThread { + dispatchAsyncAndWait { + self.assertSnap(previewSnapshot, as: snapshotting, with: (recording: recording, timeOut: timeOut, file: file, testName: testName, layout: layout, line: line)) + } + } else { + assertSnap(previewSnapshot, as: snapshotting, with: (recording: recording, timeOut: timeOut, file: file, testName: testName, layout: layout, line: line)) + } + } + + private func assertSnap(_ previewSnapshot: PreviewSnapshots, + as snapshotting: SnapshotFormat = .image, + with arguments: SnapshotArguments) { + switch snapshotting { + case .image: + guard let timeOutDuration = arguments.timeOut else { + assertImage(previewSnapshot, with: arguments) + return + } + asssertImageWithDuration(previewSnapshot, timeOut: timeOutDuration, with: arguments) + } + } + + private func assertImage(_ previewSnapshot: PreviewSnapshots, + with arguments: SnapshotArguments) { + previewSnapshot.assertSnapshots(as: .image(precision: presicion, layout: arguments.layout), record: arguments.recording) + } + + private func asssertImageWithDuration(_ previewSnapshot: PreviewSnapshots, + timeOut: TimeInterval, + with arguments: SnapshotArguments) { + previewSnapshot.assertSnapshots(as: .wait(for: timeOut, on: .image(precision: presicion, layout: arguments.layout)), record: arguments.recording) + } + +} diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1D.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1D.png new file mode 100644 index 0000000..4b10401 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1D.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1M.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1M.png new file mode 100644 index 0000000..4cc1e14 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1M.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1W.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1W.png new file mode 100644 index 0000000..f894b6b Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1W.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1Y.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1Y.png new file mode 100644 index 0000000..41414d7 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.1Y.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.3M.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.3M.png new file mode 100644 index 0000000..d0646e2 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.3M.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.6M.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.6M.png new file mode 100644 index 0000000..d0646e2 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.6M.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ALL.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ALL.png new file mode 100644 index 0000000..41414d7 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ALL.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.All-dates.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.All-dates.png new file mode 100644 index 0000000..66c2311 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.All-dates.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.BTC.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.BTC.png new file mode 100644 index 0000000..90893f4 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.BTC.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Coin-detail-view.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Coin-detail-view.png new file mode 100644 index 0000000..8199451 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Coin-detail-view.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.DOGE.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.DOGE.png new file mode 100644 index 0000000..147aaae Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.DOGE.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ETH.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ETH.png new file mode 100644 index 0000000..d510317 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.ETH.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Empty-text.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Empty-text.png new file mode 100644 index 0000000..e3422f0 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Empty-text.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Favorites-View.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Favorites-View.png new file mode 100644 index 0000000..c54a154 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Favorites-View.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Four-coins.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Four-coins.png new file mode 100644 index 0000000..e31e1db Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Four-coins.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Home-view.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Home-view.png new file mode 100644 index 0000000..ccaa1ca Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Home-view.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Long-text.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Long-text.png new file mode 100644 index 0000000..6b6b133 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Long-text.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Main-View.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Main-View.png new file mode 100644 index 0000000..4c0b7ba Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Main-View.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Negative.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Negative.png new file mode 100644 index 0000000..8425d4c Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Negative.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Neutral.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Neutral.png new file mode 100644 index 0000000..9e98ed4 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Neutral.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-coin.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-coin.png new file mode 100644 index 0000000..d221b13 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-coin.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-day.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-day.png new file mode 100644 index 0000000..6730453 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-day.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-month.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-month.png new file mode 100644 index 0000000..af50572 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-month.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-week.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-week.png new file mode 100644 index 0000000..09d09e9 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-week.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-year.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-year.png new file mode 100644 index 0000000..2027a23 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.One-year.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Positive-Change.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Positive-Change.png new file mode 100644 index 0000000..c8f768e Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Positive-Change.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Settings-view.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Settings-view.png new file mode 100644 index 0000000..3762f42 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Settings-view.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Short-text.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Short-text.png new file mode 100644 index 0000000..deb298c Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Short-text.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Six-months.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Six-months.png new file mode 100644 index 0000000..ae18bb4 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Six-months.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-coins.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-coins.png new file mode 100644 index 0000000..0ecb692 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-coins.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-months.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-months.png new file mode 100644 index 0000000..f5e6f1d Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Three-months.png differ diff --git a/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Two-coins.png b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Two-coins.png new file mode 100644 index 0000000..321fcd2 Binary files /dev/null and b/SampleAppSwiftUITests/SnapshotTests/__Snapshots__/SnapshotTestCase/assertImage-_-with.Two-coins.png differ diff --git a/SampleAppSwiftUIUITests/SampleAppSwiftUIUITests.swift b/SampleAppSwiftUIUITests/SampleAppSwiftUIUITests.swift deleted file mode 100644 index 6d178be..0000000 --- a/SampleAppSwiftUIUITests/SampleAppSwiftUIUITests.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// boilerplate-ios-swiftuiUITests.swift -// boilerplate-ios-swiftuiUITests -// -// Created by Can Baybunar on 18.11.2020. -// Copyright © 2020 Adesso Turkey. All rights reserved. -// - -import XCTest - -class SampleAppSwiftUIUITests: XCTestCase { - -} diff --git a/project.yml b/project.yml index d2b7ad3..d9db1b0 100644 --- a/project.yml +++ b/project.yml @@ -26,6 +26,9 @@ packages: swift-log: url: https://github.com/apple/swift-log.git majorVersion: 1.5.2 + swiftui-preview-snapshots: + url: https://github.com/doordash-oss/swiftui-preview-snapshots + majorVersion: 1.0.0 targets: SampleAppSwiftUI: @@ -36,6 +39,8 @@ targets: - package: Pulse product: Pulse product: PulseUI + - package: swiftui-preview-snapshots + product: PreviewSnapshots configFiles: Development: SampleAppSwiftUI/Configs/Development.xcconfig Production: SampleAppSwiftUI/Configs/Production.xcconfig @@ -69,6 +74,10 @@ targets: sources: - path: SampleAppSwiftUITests SampleAppSwiftUIUITests: + dependencies: + - target: SampleAppSwiftUIUITests + - package: swiftui-preview-snapshots + product: PreviewSnapshotsTests type: bundle.ui-testing platform: iOS sources: