Skip to content

Instantly share code, notes, and snippets.

View tovkal's full-sized avatar

Andrés Pizá Bückmann tovkal

View GitHub Profile
@tovkal
tovkal / CustomNavigation.swift
Created June 6, 2024 11:00
How to implement NavigationLink's destination parameter without a closure?
import PlaygroundSupport
import Foundation
import SwiftUI
struct SomeView: View {
var body: some View {
Text("Some")
}
}
@tovkal
tovkal / BottomFindableScrollView.swift
Created March 16, 2022 15:34
Find the bottom of a ScrollView in SwiftUI
import SwiftUI
struct BottomFindableScrollView<Content: View>: View {
private let axes: Axis.Set
private let showsIndicators: Bool
@Binding private var bottomReached: Bool
private let content: Content
private let coordinateSpaceName = "scrollSize"
@State private var wholeSize: CGSize = .zero
@tovkal
tovkal / Snapshotting+ImpreciseImage.swift
Created June 10, 2021 16:20
Workaround M1 swift-snapshot-testing
import UIKit
import SnapshotTesting
private let precision: Float = 0.9
// MARK: - UIViewController
extension Snapshotting where Value == UIViewController, Format == UIImage {
/// A snapshot strategy for comparing views based on pixel equality.
public static var impreciseImage: Snapshotting {
<key>NSAppTransportSecurity</key>
<dict>
<!--To support localhost -->
<key>NSAllowsLocalNetworking</key>
<true/>
<!--To continue to work for iOS 9 -->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
class UITests: XCTestCase {
let app = XCUIApplication()
let dynamicStubs = HTTPDynamicStubs()
override func setUp() {
super.setUp()
dynamicStubs.setUp()
}
import Foundation
import Swifter
enum HTTPMethod {
case POST
case GET
}
struct HTTPStubInfo {
let url: String
private func beInitial() -> Predicate<SearchTableViewController.State> {
return Predicate.define("be <initial>") { expression, message in
if let actual = try expression.evaluate(), case .initial = actual {
return PredicateResult(status: .matches, message: message)
}
return PredicateResult(status: .fail, message: message)
}
}
// Just check the enum
expect(state).to(beContent())
// Check the enum and verify whatever properties we need from the associated value
expect(state).to(beContent { response in
expect(response) === expectedResponse
})
private func beContent(test: @escaping (Response) -> Void = { _ in }) -> Predicate<State> {
return Predicate.define("be <content>") { expression, message in
if let actual = try expression.evaluate(),
case let .content(response) = actual {
test(response)
return PredicateResult(status: .matches, message: message)
}
return PredicateResult(status: .fail, message: message)
}
}
if case let .content(response) = state {
expect(response.foo).to(equal(expectedResponse.foo))
} else {
fail("Expected <content> but got <\(state)>")
}