<commit_before># YetAnotherHTTPStub

[![Build Status](https://travis-ci.org/kinwahlai/YetAnotherHTTPStub.svg?branch=master)](https://travis-ci.org/kinwahlai/YetAnotherHTTPStub)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![https://img.shields.io/badge/bitcoin-donate-blue.svg](https://img.shields.io/badge/bitcoin-donate-blue.svg)](#donation)
[![https://img.shields.io/badge/paypal.me-donate-blue.svg](https://img.shields.io/badge/paypal.me-donate-blue.svg)](#donation)

In many case, we need to mock the network response when we writing unit test that has network request, like calling an API.

This framework utilizes the URLProcotol to intercept the request and reply the response preset by developer.

This framework is inspired by [Mockingjay](https://github.com/kylef-archive/Mockingjay) and [Cuckoo](https://github.com/Brightify/Cuckoo)

## Key Concept 

![YetAnotherHTTPStub-concept.png](./YetAnotherHTTPStub-concept.png)

### Details

- There should be only 1 session for each test case
- You can register as many request as you want for 1 session
- You can register as many response as you want for 1 request
- When a session starts, this framework will replace/swizzle the default _URLSessionConfiguration_ creation to inject the custom _URLProtocol_
- Also when a session starts, this framework will add the session to _XCTestObservationCenter_ to remove session on testCaseDidFinish 

## Installation

### Carthage

To use YetAnotherHTTPStub with [Carthage](https://github.com/Carthage/Carthage) add in your Cartfile this line:

```
github "kinwahlai/YetAnotherHTTPStub"
``` 

Don't forget to add the Framework into your project.

## Example

```swift
YetAnotherURLProtocol.stubHTTP { (session) in
    session.whenRequest(matcher: everything)
    .thenResponse(responseBuilder: jsonString("{\"hello\":\"world\"}"))
}
```

You start a session with `YetAnotherURLProtocol.stubHTTP` , `session.whenRequest` to register a request and `.thenResponse` to register a response.

```swift
YetAnotherURLProtocol.stubHTTP { (session) in
    session.whenRequest(matcher:  http(.get, uri: "/login"))
    .thenResponse(responseBuilder: jsonString("{\"success\":true}"))

    session.whenRequest(matcher:  http(.get, uri: "/getContact?page=\\d+&per_page=50"))
    .thenResponse(responseBuilder: jsonString(<Page 1 Response>))
    .thenResponse(responseBuilder: jsonString(<Page 2 Response>))
}
```

### Matcher

A matcher is a pure function that takes a _URLRequest_ and returns a boolean for checking if the stub request matches the request. And built-in matcher to help simplify the work.

```swift
func matcher(request:NSURLRequest) -> Bool {
  return true
}
```

#### Built-in matcher

- `everything` - Matches everything
- `nothing` - Match nothing
- `uri(url/path)` - Check if url or path with wildcard matches the request
- `http(method, url/path)` - Check if url or path with wildcard and method matches the request

### Builder

A builder is another pure function that takes a _URLRequest_ and returns a success or failure response

```swift
func matcher(request:NSURLRequest) -> StubResponse {
    let response = NSHTTPURLResponse(URL: request.URL, statusCode: 200, HTTPVersion: nil, headerFields: nil)!
    return .success(response: response, content: .noContent)
}
```

#### Built-in builder

- `failure(error)` 
- `http(status, headers, StubContent)`
- `jsonString(string, status, headers)`
- `json(body, status, headers)`
- `json(data, status, headers)`

## Donation

<table>
    <tr>
        <td colspan="2"> If you like my work on <b>YetAnotherHTTPStub</b> or to support open source, consider a small donation to my bitcoin address or paypal.me: </td><commit_msg>add queue usage section to README<commit_after># YetAnotherHTTPStub

[![Build Status](https://travis-ci.org/kinwahlai/YetAnotherHTTPStub.svg?branch=master)](https://travis-ci.org/kinwahlai/YetAnotherHTTPStub)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![https://img.shields.io/badge/bitcoin-donate-blue.svg](https://img.shields.io/badge/bitcoin-donate-blue.svg)](#donation)
[![https://img.shields.io/badge/paypal.me-donate-blue.svg](https://img.shields.io/badge/paypal.me-donate-blue.svg)](#donation)

In many case, we need to mock the network response when we writing unit test that has network request, like calling an API.

This framework utilizes the URLProcotol to intercept the request and reply the response preset by developer.

This framework is inspired by [Mockingjay](https://github.com/kylef-archive/Mockingjay) and [Cuckoo](https://github.com/Brightify/Cuckoo)

## Key Concept 

![YetAnotherHTTPStub-concept.png](./YetAnotherHTTPStub-concept.png)

### Details

- There should be only 1 session for each test case
- You can register as many request as you want for 1 session
- You can register as many response as you want for 1 request
- When a session starts, this framework will replace/swizzle the default _URLSessionConfiguration_ creation to inject the custom _URLProtocol_
- Also when a session starts, this framework will add the session to _XCTestObservationCenter_ to remove session on testCaseDidFinish 

## Installation

### Carthage

To use YetAnotherHTTPStub with [Carthage](https://github.com/Carthage/Carthage) add in your Cartfile this line:

```
github "kinwahlai/YetAnotherHTTPStub"
``` 

Don't forget to add the Framework into your project.

## Example

```swift
YetAnotherURLProtocol.stubHTTP { (session) in
    session.whenRequest(matcher: everything)
    .thenResponse(responseBuilder: jsonString("{\"hello\":\"world\"}"))
}
```

You start a session with `YetAnotherURLProtocol.stubHTTP` , `session.whenRequest` to register a request and `.thenResponse` to register a response.

```swift
YetAnotherURLProtocol.stubHTTP { (session) in
    session.whenRequest(matcher:  http(.get, uri: "/login"))
    .thenResponse(responseBuilder: jsonString("{\"success\":true}"))

    session.whenRequest(matcher:  http(.get, uri: "/getContact?page=\\d+&per_page=50"))
    .thenResponse(responseBuilder: jsonString(<Page 1 Response>))
    .thenResponse(responseBuilder: jsonString(<Page 2 Response>))
}
```

### Matcher

A matcher is a pure function that takes a _URLRequest_ and returns a boolean for checking if the stub request matches the request. And built-in matcher to help simplify the work.

```swift
func matcher(request:NSURLRequest) -> Bool {
  return true
}
```

#### Built-in matcher

- `everything` - Matches everything
- `nothing` - Match nothing
- `uri(url/path)` - Check if url or path with wildcard matches the request
- `http(method, url/path)` - Check if url or path with wildcard and method matches the request

### Builder

A builder is another pure function that takes a _URLRequest_ and returns a success or failure response

```swift
func matcher(request:NSURLRequest) -> StubResponse {
    let response = NSHTTPURLResponse(URL: request.URL, statusCode: 200, HTTPVersion: nil, headerFields: nil)!
    return .success(response: response, content: .noContent)
}
```

#### Built-in builder

- `failure(error)` 
- `http(status, headers, StubContent)`
- `jsonString(string, status, headers)`
- `json(body, status, headers)`
- `json(data, status, headers)`

### Queue

StubResponse will be replied on a separate DispatchQueue automatically. However, you can specific or switch to use the queue of your choice by using `.responseOn(queue: customQueue)` function.
Response will use the queue from the last response until queue switch by `responseOn(queue: customQueue)`, and then all the subsequent response will use the new queue.

```swift
let customQueue = DispatchQueue(label: "custom.queue")
YetAnotherURLProtocol.stubHTTP { (session) in
    session.whenRequest(matcher:  http(.get, uri: "/getContact?page=\\d+&per_page=50"))
    .thenResponse(responseBuilder: jsonString(<Page 1 Response>))
    .responseOn(queue: customQueue)
    .thenResponse(responseBuilder: jsonString(<Page 2 Response>))
}
```

## Donation

<table>
    <tr>
        <td colspan="2"> If you like my work on <b>YetAnotherHTTPStub</b> or to support open source, consider a small donation to my bitcoin address or paypal.me: </td>
{'fraction_non_alphanumeric': 0.11921965317919075, 'fraction_numerical': 0.0038535645472061657, 'mean_word_length': 4.996389891696751, 'pattern_counts': {'":': 4, '<': 21, '<?xml version=': 0, '>': 25, 'https://': 22, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '274930', 'n_tokens_mistral': 2627, 'n_tokens_neox': 2491, 'n_words': 782}