# `HTTPower.Test`
[🔗](https://github.com/mdepolli/httpower/blob/v0.22.0/lib/httpower/test.ex#L1)

Adapter-agnostic testing utilities for HTTPower.

This module provides a testing interface that works independently of which
adapter (Req, Tesla) you have installed. It allows you to write tests that
mock HTTP requests without coupling to adapter-specific test utilities.

## Example

    defmodule MyApp.ApiClientTest do
      use ExUnit.Case

      setup do
        HTTPower.Test.setup()
      end

      test "fetches users" do
        HTTPower.Test.stub(fn conn ->
          case {conn.method, conn.request_path} do
            {"GET", "/users"} ->
              HTTPower.Test.json(conn, %{users: ["alice", "bob"]})

            {"POST", "/users"} ->
              HTTPower.Test.json(conn, %{created: true})
          end
        end)

        {:ok, response} = HTTPower.get("https://api.example.com/users")

        assert response.status == 200
        assert response.body == %{"users" => ["alice", "bob"]}
      end
    end

## Benefits

- **Adapter independence**: No need to know if you're using Req or Tesla
- **Simple API**: One `stub/1` function for all mocking needs
- **Zero coupling**: Doesn't depend on Req.Test or Tesla.Mock
- **Convenient helpers**: `json/2`, `html/2`, `text/2` for responses

## Cross-Process Support

Mocks are automatically visible to processes spawned from the test
(e.g., `Task.async`, `Task.async_stream`) via `$callers` chain walking.

For pre-existing processes like GenServers, use `allow/2`:

    setup do
      HTTPower.Test.setup()
      HTTPower.Test.allow(Process.whereis(MyApp.HttpWorker))
    end

    test "worker uses mock" do
      HTTPower.Test.stub(fn conn ->
        HTTPower.Test.json(conn, %{ok: true})
      end)

      assert {:ok, response} = MyApp.HttpWorker.fetch()
    end

Allowances are transitive: if you allow a GenServer and it spawns a
Task, the Task will also see the mock.

# `allow`

Allows `pid` to use the mock registered by `owner` (defaults to `self()`).

Use this for pre-existing processes (e.g., GenServers started in the supervision
tree) that need to see test mocks. For processes spawned from the test
(Task.async, spawn, etc.), this is not needed — they automatically find
the parent's mock via `$callers`.

Allowances are transitive: if you allow a GenServer, and that GenServer
spawns a Task, the Task will also see the mock.

## Example

    setup do
      HTTPower.Test.setup()
      HTTPower.Test.allow(MyApp.HttpWorker)
    end

    test "worker uses mock" do
      HTTPower.Test.stub(fn conn ->
        HTTPower.Test.json(conn, %{ok: true})
      end)

      assert {:ok, response} = MyApp.HttpWorker.fetch()
    end

# `html`

Sends an HTML response with the given data.

## Options

  * `:status` - HTTP status code (default: 200)

## Examples

    HTTPower.Test.html(conn, "<h1>Hello</h1>")
    HTTPower.Test.html(conn, "<h1>Not Found</h1>", status: 404)

# `json`

Sends a JSON response with the given data.

## Options

  * `:status` - HTTP status code (default: 200)

## Examples

    HTTPower.Test.json(conn, %{success: true})
    HTTPower.Test.json(conn, %{error: "not found"}, status: 404)

# `setup`

Sets up HTTPower.Test for the current test.

Call this in your test setup to enable HTTP mocking for that test.

## Example

    setup do
      HTTPower.Test.setup()
    end

# `stub`

Registers a stub function to handle HTTP requests in tests.

The stub function receives a `Plug.Conn` struct and should return a
`Plug.Conn` with the response set using helper functions like `json/2`,
`html/2`, or `text/2`.

## Example

    HTTPower.Test.stub(fn conn ->
      case {conn.method, conn.request_path} do
        {"GET", "/weather"} ->
          HTTPower.Test.json(conn, %{temp: 25, condition: "sunny"})

        {"POST", "/users"} ->
          HTTPower.Test.json(conn, %{created: true}, status: 201)

        _ ->
          HTTPower.Test.json(conn, %{error: "not found"}, status: 404)
      end
    end)

# `text`

Sends a text response with the given data.

## Options

  * `:status` - HTTP status code (default: 200)

## Examples

    HTTPower.Test.text(conn, "Hello, World!")
    HTTPower.Test.text(conn, "Not Found", status: 404)

# `transport_error`

Simulates a network transport error.

This function allows you to test how your application handles various
network failures like timeouts, connection errors, and protocol issues.

## Supported error reasons

  * `:timeout` - Request timeout
  * `:closed` - Connection closed
  * `:econnrefused` - Connection refused
  * `:nxdomain` - DNS resolution failed

## Examples

    HTTPower.Test.stub(fn conn ->
      HTTPower.Test.transport_error(conn, :timeout)
    end)

    {:error, error} = HTTPower.get("https://api.example.com/slow")
    assert error.reason == :test_transport_error
    assert error.message =~ "timeout"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
