Coder Social home page Coder Social logo

catbird's Introduction

Catbird

Build Status GitHub license CocoaPods Compatible Platform SPM compatible

Catbird | Drozd | Дрозд

Mock server for ui tests

Features

  • Dynamic mock server
  • Static file mock server
  • Proxy server with writing response files

Requirements

Install libressl for swift-nio

$ brew install libressl

Installation

Cocoapods

Add Catbird to UI tests target.

target 'App' do
  use_frameworks!

  target 'AppUITests' do
    inherit! :search_paths

    pod 'Catbird'
  end
end

Setup in Xcode project

  • Open Schema/Edit scheme...
  • Select Test action
  • Select Pre-Actions
    • Add New Run Script action
    • Provide build setting from <YOUR_APP_TARGET>
    • ${PODS_ROOT}/Catbird/start.sh
  • Select Post-Actions
    • Add New Run Script action
    • Provide build setting from <YOUR_APP_TARGET>
    • ${PODS_ROOT}/Catbird/stop.sh

Usage

import XCTest
import Catbird

enum LoginMock: RequestBagConvertible {
    case success
    case blockedUserError

    var pattern: RequestPattern {
        return RequestPattern.post(URL(string: "/login")!)
    }

    var responseData: ResponseData {
        switch self {
        case .success:
            let json: [String: Any] = [
                "data": [
                    "access_token": "abc",
                    "refresh_token": "xyz",
                    "expired_in": "123",
                ]
            ]
            return ResponseData(
                statusCode: 200,
                headerFields: ["Content-Type": "application/json"],
                body: try! JSONSerialization.data(withJSONObject: json))

        case .blockedUserError:
            let json: [String: Any] = [
                "error": [
                    "code": "user_blocked",
                    "message": "user blocked"
                ]
            ]
            return ResponseData(
                statusCode: 400,
                headerFields: ["Content-Type": "application/json"],
                body: try! JSONSerialization.data(withJSONObject: json))
        }
    }
}

final class LoginUITests: XCTestCase {
    
    private let catbird = Catbird()
    private var app: XCUIApplication!

    override func setUp() {
        super.setUp()
        continueAfterFailure = false
        app = XCUIApplication()

        // Base URL in app `UserDefaults.standard.url(forKey: "url_key")`
        app.launchArguments = ["-url_key", catbird.url.absoluteString]
        app.launch()
    }

    override func tearDown() {
        XCTAssertNoThrow(try catbird.send(.clear), "Remove all requests")
        super.tearDown()
    }

    func testLogin() {
        XCTAssertNoThrow(try catbird.send(.add(LoginMock.success)))

        app.textFields["login"].tap()
        app.textFields["login"].typeText("[email protected]")
        app.secureTextFields["password"].tap()
        app.secureTextFields["password"].typeText("qwerty")
        app.buttons["Done"].tap()

        wait(forElement: app.staticTexts["Main Screen"])
    }

    func testBlockedUserError() {
        XCTAssertNoThrow(try catbird.send(.add(LoginMock.blockedUserError)))

        app.textFields["login"].tap()
        app.textFields["login"].typeText("[email protected]")
        app.secureTextFields["password"].tap()
        app.secureTextFields["password"].typeText("burger")
        app.buttons["Done"].tap()

        wait(forElement: app.alerts["Error"])
    }
}

extension XCTestCase {
    func wait(forElement element: XCUIElement, timeout: TimeInterval = 3.0) {
        let predicate = NSPredicate(format: "exists == 1")
        expectation(for: predicate, evaluatedWith: element)
        waitForExpectations(timeout: timeout)
    }
}

Request patterns

You can specify a pattern for catch http requests and make a response with mock data. Pattern matching applied for URL and http headers in the request. See RequestPattern struct.

Three types of patterns can be used:

  • equal - the request value must be exactly the same as the pattern value,
  • wildcard - the request value match with the wildcard pattern (see below),
  • regexp - the request value match with the regular expression pattern.
Note:

If you want to apply a wildcard pattern for the url query parameters, don't forget escape ? symbol after domain or path.

Pattern.wildcard("http://example.com\?query=*")

Wildcard pattern

"Wildcards" are the patterns you type when you do stuff like ls *.js on the command line, or put build/* in a .gitignore file.

In our implementation any wildcard pattern translates to regular expression and applies matching with URL or header string.

The following characters have special magic meaning when used in a pattern:

  • * matches 0 or more characters
  • ? matches 1 character
  • [a-z] matches a range of characters, similar to a RegExp range.
  • {bar,baz} matches one of the substitution listed in braces. For example pattern foo{bar,baz} matches strings foobar or foobaz

You can escape special characters with backslash \.

Negation in groups is not supported.

Example project

$ cd Example/CatbirdX
$ bundle exec pod install
$ xed .

Environment variables

CATBIRD_MOCKS_DIR — Directory where static mocks are located.

CATBIRD_PROXY_URL — If you specify this URL Catbird will run in write mode. In this mode, requests to Catbird will be redirected to the CATBIRD_PROXY_URL. Upon receipt of response from the server it will be written to the CATBIRD_MOCKS_DIR directory.

Logs

Logs can be viewed in the Console.app with subsystem com.redmadrobot.catbird

Don't forget to include the message in the action menu

  • Include Info Messages
  • Include Debug Messages

Without this, only error messages will be visible

Web

You can view a list of all intercepted requests on the page http://127.0.0.1:8080/catbird

catbird's People

Contributors

modestman avatar alexander-ignition avatar subdan avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.