<commit_before>![Wallaby](https://i.imgur.com/eQ1tlI3.png)
============

[![Actions Status](https://github.com/elixir-wallaby/wallaby/workflows/CI/badge.svg)](https://github.com/elixir-wallaby/wallaby/actions)
[![codecov](https://codecov.io/gh/elixir-wallaby/wallaby/branch/main/graph/badge.svg?token=eaEe1AIM2e)](https://codecov.io/gh/elixir-wallaby/wallaby)
[![Module Version](https://img.shields.io/hexpm/v/wallaby.svg)](https://hex.pm/packages/wallaby)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/wallaby/)
[![License](https://img.shields.io/hexpm/l/wallaby.svg)](https://github.com/elixir-wallaby/wallaby/blob/master/LICENSE)

Wallaby helps you test your web applications by simulating realistic user interactions.
By default it runs each test case concurrently and manages browsers for you.
Here's an example test for a simple Todo application:

```elixir
defmodule MyApp.Features.TodoTest do
  use ExUnit.Case, async: true
  use Wallaby.Feature

  import Wallaby.Query, only: [css: 2, text_field: 1, button: 1]

  feature "users can create todos", %{session: session} do
    session
    |> visit("/todos")
    |> fill_in(text_field("New Todo"), with: "Write my first Wallaby test")
    |> click(button("Save"))
    |> assert_has(css(".alert", text: "You created a todo"))
    |> assert_has(css(".todo-list > .todo", text: "Write my first Wallaby test"))
  end
end
```

Because Wallaby manages multiple browsers for you, its possible to test several users interacting with a page simultaneously.

```elixir
defmodule MyApp.Features.MultipleUsersTest do
  use ExUnit.Case, async: true
  use Wallaby.Feature

  import Wallaby.Query, only: [text_field: 1, button: 1, css: 2]

  @page message_path(Endpoint, :index)
  @message_field text_field("Share Message")
  @share_button button("Share")

  def message(msg), do: css(".messages > .message", text: msg)

  @sessions 2
  feature "That users can send messages to each other", %{sessions: [user1, user2]} do
    user1
    |> visit(@page)
    |> fill_in(@message_field, with: "Hello there!")
    |> click(@share_button)

    user2
    |> visit(@page)
    |> fill_in(@message_field, with: "Hello yourself")
    |> click(@share_button)

    user1
    |> assert_has(message("Hello yourself"))

    user2
    |> assert_has(message("Hello there!"))
  end
end
```

Read on to see what else Wallaby can do or check out the [Official Documentation](https://hexdocs.pm/wallaby).

## Sponsors

![SmartLogic Logo](https://github.com/smartlogic/smartlogic.io/raw/main/images/brand-assets/smartlogic-logo-teal-400.png)

## Setup

### Requirements

Wallaby requires Elixir 1.8+ and OTP 21+.

Wallaby also requires `bash` to be installed. Generally `bash` is widely available, but it does not come pre-installed on Alpine Linux.

### Installation

Add Wallaby to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:wallaby, "~> 0.29.0", runtime: false, only: :test}
  ]
end
```

Configure the driver.

```elixir
# Chrome
config :wallaby, driver: Wallaby.Chrome # default

# Selenium
config :wallaby, driver: Wallaby.Selenium
```

When calling `use Wallaby.Feature` and using Ecto, please configure your `otp_app`.

```
config :wallaby, otp_app: :your_app
```

Then ensure that Wallaby is started in your `test_helper.exs`:

```elixir
{:ok, _} = Application.ensure_all_started(:wallaby)
```

### Phoenix

If you're testing a Phoenix application with Ecto and a database that [supports sandbox mode](https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html), you can enable concurrent testing by adding the `Phoenix.Ecto.SQL.Sandbox` plug to your `Endpoint`.
It's important that this is at the top of `endpoint.ex` before any other plugs.

```elixir
# lib/your_app_web/endpoint.ex

defmodule YourAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :your_app

  if sandbox = Application.get_env(:your_app, :sandbox) do
    plug Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox
  end
```

Make sure Phoenix is set up to serve endpoints in tests and that the sandbox is enabled:

```elixir
# config/test.exs

config :your_app, YourAppWeb.Endpoint,
  server: true

config :your_app, :sandbox, Ecto.Adapters.SQL.Sandbox
```

This enables the database connection to be owned by the process that is running your test, but the connection is shared to the process receiving the HTTP requests from the browser, so that the same data is visible in both processes.

If you have other resources that should be shared by both processes (e.g. expectations or stubs if using [Mox](https://hexdocs.pm/mox/Mox.html)), then you can define a custom sandbox module:

```elixir
# config/support/sandbox.ex

defmodule YourApp.Sandbox do
  def allow(repo, owner_pid, child_pid) do
    # Delegate to the Ecto sandbox
    Ecto.Adapters.SQL.Sandbox.allow(repo, owner_pid, child_pid)

    # Add custom process-sharing configuration
    Mox.allow(MyMock, owner_pid, child_pid)
  end
end
```
<commit_msg>Adds user_agent to endpoint.ex in the README (#676)<commit_after>![Wallaby](https://i.imgur.com/eQ1tlI3.png)
============

[![Actions Status](https://github.com/elixir-wallaby/wallaby/workflows/CI/badge.svg)](https://github.com/elixir-wallaby/wallaby/actions)
[![codecov](https://codecov.io/gh/elixir-wallaby/wallaby/branch/main/graph/badge.svg?token=eaEe1AIM2e)](https://codecov.io/gh/elixir-wallaby/wallaby)
[![Module Version](https://img.shields.io/hexpm/v/wallaby.svg)](https://hex.pm/packages/wallaby)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/wallaby/)
[![License](https://img.shields.io/hexpm/l/wallaby.svg)](https://github.com/elixir-wallaby/wallaby/blob/master/LICENSE)

Wallaby helps you test your web applications by simulating realistic user interactions.
By default it runs each test case concurrently and manages browsers for you.
Here's an example test for a simple Todo application:

```elixir
defmodule MyApp.Features.TodoTest do
  use ExUnit.Case, async: true
  use Wallaby.Feature

  import Wallaby.Query, only: [css: 2, text_field: 1, button: 1]

  feature "users can create todos", %{session: session} do
    session
    |> visit("/todos")
    |> fill_in(text_field("New Todo"), with: "Write my first Wallaby test")
    |> click(button("Save"))
    |> assert_has(css(".alert", text: "You created a todo"))
    |> assert_has(css(".todo-list > .todo", text: "Write my first Wallaby test"))
  end
end
```

Because Wallaby manages multiple browsers for you, its possible to test several users interacting with a page simultaneously.

```elixir
defmodule MyApp.Features.MultipleUsersTest do
  use ExUnit.Case, async: true
  use Wallaby.Feature

  import Wallaby.Query, only: [text_field: 1, button: 1, css: 2]

  @page message_path(Endpoint, :index)
  @message_field text_field("Share Message")
  @share_button button("Share")

  def message(msg), do: css(".messages > .message", text: msg)

  @sessions 2
  feature "That users can send messages to each other", %{sessions: [user1, user2]} do
    user1
    |> visit(@page)
    |> fill_in(@message_field, with: "Hello there!")
    |> click(@share_button)

    user2
    |> visit(@page)
    |> fill_in(@message_field, with: "Hello yourself")
    |> click(@share_button)

    user1
    |> assert_has(message("Hello yourself"))

    user2
    |> assert_has(message("Hello there!"))
  end
end
```

Read on to see what else Wallaby can do or check out the [Official Documentation](https://hexdocs.pm/wallaby).

## Sponsors

![SmartLogic Logo](https://github.com/smartlogic/smartlogic.io/raw/main/images/brand-assets/smartlogic-logo-teal-400.png)

## Setup

### Requirements

Wallaby requires Elixir 1.8+ and OTP 21+.

Wallaby also requires `bash` to be installed. Generally `bash` is widely available, but it does not come pre-installed on Alpine Linux.

### Installation

Add Wallaby to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:wallaby, "~> 0.29.0", runtime: false, only: :test}
  ]
end
```

Configure the driver.

```elixir
# Chrome
config :wallaby, driver: Wallaby.Chrome # default

# Selenium
config :wallaby, driver: Wallaby.Selenium
```

When calling `use Wallaby.Feature` and using Ecto, please configure your `otp_app`.

```
config :wallaby, otp_app: :your_app
```

Then ensure that Wallaby is started in your `test_helper.exs`:

```elixir
{:ok, _} = Application.ensure_all_started(:wallaby)
```

### Phoenix

If you're testing a Phoenix application with Ecto and a database that [supports sandbox mode](https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html), you can enable concurrent testing by adding the `Phoenix.Ecto.SQL.Sandbox` plug to your `Endpoint`.
It's important that this is at the top of `endpoint.ex` before any other plugs.

```elixir
# lib/your_app_web/endpoint.ex

defmodule YourAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :your_app

  if sandbox = Application.get_env(:your_app, :sandbox) do
    plug Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox
  end

  # ...

  socket("/live", Phoenix.LiveView.Socket,
    websocket: [connect_info: [:user_agent, session: @session_options]]
  )
```

It's also important to make sure the `user_agent` is passed in the `connect_info` in order to allow the database and browser session to be wired up correctly.

Then make sure Phoenix is set up to serve endpoints in tests and that the sandbox is enabled:

```elixir
# config/test.exs

config :your_app, YourAppWeb.Endpoint,
  server: true

config :your_app, :sandbox, Ecto.Adapters.SQL.Sandbox
```

This enables the database connection to be owned by the process that is running your test, but the connection is shared to the process receiving the HTTP requests from the browser, so that the same data is visible in both processes.

If you have other resources that should be shared by both processes (e.g. expectations or stubs if using [Mox](https://hexdocs.pm/mox/Mox.html)), then you can define a custom sandbox module:

```elixir
# config/support/sandbox.ex

defmodule YourApp.Sandbox do
  def allow(repo, owner_pid, child_pid) do
    # Delegate to the Ecto sandbox
    Ecto.Adapters.SQL.Sandbox.allow(repo, owner_pid, child_pid)

    # Add custom process-sharing configuration
    Mox.allow(MyMock, owner_pid, child_pid)
  end
end
```

{'fraction_non_alphanumeric': 0.12765335929892893, 'fraction_numerical': 0.005744888023369036, 'mean_word_length': 4.472029834842834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 30, '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': '2509279', 'n_tokens_mistral': 3560, 'n_tokens_neox': 3327, 'n_words': 1006}