AMPopTip

repository·main·Indexed 25 days ago

https://github.com/andreamazz/ampoptip

An animated popover library for iOS that allows developers to display subtle hints, onboarding popups, or custom views that 'pop out' of a specific frame. It supports both UIKit and SwiftUI.

Tokens
14.3K
Snippets
55
Records
74
Agent score
86%

What's inside AMPopTip

  1. Overview of Nimble

    main
    Nimble is a matcher framework used to express the expected outcomes of Swift or Objective-C expressions. It provides a more natural and readable syntax for assertions compared to standard XCTest macros, specifically addressing the lack of diverse assertion macros and the difficulty of writing asynchronous tests in XCTest.
  2. Test for exceptions and raised errors

    main

    Because expect evaluates its argument lazily, you can pass a closure to test if an expression raises an exception.

    In Swift, this is primarily for catching Objective-C exceptions. In Objective-C, you must use the expectAction macro for expressions that do not return a value.

  3. Test C Primitives

    main

    Nimble supports C primitives (like CInt) in Swift using type inference. In Objective-C, primitive C values must be wrapped in an object literal (e.g., @()) to be used with Nimble.

    // Swift
    let actual: CInt = 1
    expect(actual).to(equal(1))
    
    // Objective-C
    expect(@(1 + 1)).to(equal(@2));
  4. Install Quick and Nimble via Swift Package Manager

    main

    To install Quick and Nimble using Swift Package Manager, add the following dependencies to your Package.swift file:

    dependencies: [
        .package(url: "https://github.com/Quick/Quick.git", from: "7.0.0"),
        .package(url: "https://github.com/Quick/Nimble.git", from: "12.0.0"),
    ],
  5. Use Nimble-Snapshots for basic snapshot testing

    main

    Use haveValidSnapshot() to assert that a view matches its recorded snapshot. You can provide a custom name for the snapshot using named: or use the shorthand == snapshot("name") syntax. To record new snapshots, use recordSnapshot() or the emoji operator 📷.

    import Quick
    import Nimble
    import Nimble_Snapshots
    import UIKit
    
    class MySpec: QuickSpec {
        override func spec() {
            describe("in some context") {
                it("has valid snapshot") {
                    let view = ... // some view you want to test
                    expect(view).to( haveValidSnapshot() )
                }
            }
        }
    }
    
    // Custom named snapshots
    expect(view).to( haveValidSnapshot(named: "some custom name") )
    expect(view) == snapshot("some custom name")
    
    // Recording snapshots
    expect(view).to( recordSnapshot() )
    expect(view).to( recordSnapshot(named: "some custom name") )
    📷(view)
    📷(view, "some custom name")
  6. Install Nimble-Snapshots via Swift Package Manager

    main

    Add Nimble-Snapshots to the dependencies array of your Package.swift and include it in your target's dependencies.

    import PackageDescription
    let package = Package(
        name: "<Your Product Name>",
        dependencies: [
           .package(url: "https://github.com/ashfurrow/Nimble-Snapshots", .upToNextMajor(from: "9.0.0"))
        ],
        targets: [
            .target(
                name: "<Your Target Name>",
                dependencies: ["Nimble-Snapshots"]),
        ]
    )
  7. Customize failure messages in matchers

    main

    Nimble provides several ways to control the error message shown when a test fails:

    1. Predicate.simple(message) or Predicate.simpleNilable(message): Automatically generates a standard message: "expected to <message>, got <actual>".
    2. Predicate.define(message): Allows you to receive a pre-constructed ExpectationMessage (msg) and return a custom PredicateResult.
    3. Full Customization: Return a PredicateResult directly to use any ExpectationMessage case (like .expectedTo or .expectedCustomValueTo).
    public func equal<T: Equatable>(_ expectedValue: T?) -> Predicate<T> {
        return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
            let actualValue = try actualExpression.evaluate()
            let matches = actualValue == expectedValue && expectedValue != nil
            // ... custom logic returning PredicateResult ...
            return PredicateResult(bool: matches, message: msg)
        }
    }
  8. Use Nimble without XCTest (Standalone App)

    main

    To use Nimble in a standalone app outside of XCTest, you must implement a custom assertion handler and perform a post-build cleanup to prevent unnecessary library copying.

    1. Implement and assign an AssertionHandler

    Create a class conforming to AssertionHandler and assign it to the global NimbleAssertionHandler variable before using assertions.

    2. Add Post-build Action

    To prevent the Swift XCTest support library from being copied into your app:

    1. Edit your scheme in Xcode and navigate to Build -> Post-actions.
    2. Click + and select New Run Script Action.
    3. Set "Provide build settings from" to your target.
    4. Add the following script: rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib"
    class MyAssertionHandler : AssertionHandler {
        func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) {
            if (!assertion) {
                print("Expectation failed: \(message.stringValue)")
            }
        }
    }
    
    // Somewhere before you use any assertions
    NimbleAssertionHandler = MyAssertionHandler()