Paralelismo Task e processo

# EX 1
def transaction(conn, params) do
# O exemplo abaixo inicia um processo, e não o espera, sem await, ótimo por exemplo quando se vai gerar um relatório que é muito demorado e precisa continuar a aplicação enquanto isso.
    task = Task.start(fn -> Rocketpay.transaction(params) end)

      conn
      |> put_status(:no_content)
      |> text("OK")
  end

# EX 2
def transaction(conn, params) d
# O exemplo abaixo inicia um processo, e o espera, assim como no node com async await.
    task = Task.async(fn -> Rocketpay.transaction(params) end)

    with {:ok, %TransactionResponse{} = transaction} <- Task.await(task) do
      conn
      |> put_status(:ok)
      |> render("transaction.json", transaction: transaction)
    end
  end

Todas as requests no Phoenix, são um processo isolado


Basic Auth

config/config.ex

config :rocketpay, :basic_auth,
  username: "batata",
  password: "batata123"

Router

pipeline :auth do
    plug :basic_auth, Application.compile_env(:rocketpay, :basic_auth)
  end

scope "/api", RocketpayWeb do
    # pipe_through são regras para as rotas assim como app.use no node
    pipe_through [:api, :auth]

    post "/accounts/:id/deposit", AccountsController, :deposit
    post "/accounts/:id/withdraw", AccountsController, :withdraw
    post "/accounts/transaction", AccountsController, :transaction
  end

Teste de Módulo

defmodule Rocketpay.Users.CreateTest do
# DataCase, o async: true serve para os testes rodarem mais rápido  
  use Rocketpay.DataCase, async: true

  alias Rocketpay.Repo
  alias Rocketpay.User
  alias Rocketpay.Users.Create

  describe "call/1" do
    test "when all params are valid, return an user" do
      params = %{
        name: "Daniel",
        password: "123456",
        nickname: "dan",
        email: "dan@email.com",
        age: 20
      }

      {:ok, %User{id: user_id}} = Create.call(params)
      user = Repo.get(User, user_id)

      assert %User{name: "Daniel", age: 20, id: ^user_id} = user
    end

    test "when there are invalid params, return an error" do
      params = %{
        name: "Daniel",
        nickname: "dan",
        email: "dan@email.com",
        age: 13
      }

      {:error, changeset} = Create.call(params)

      expected_response = %{
        age: ["must be greater than or equal to 18"],
        password: ["can't be blank"]
      }

      assert errors_on(changeset) == expected_response
    end
  end
end

Teste de Controller

defmodule RocketpayWeb.AccountsControllerTest do
# ConnCase, o async: true serve para os testes rodarem mais rápido  
use RocketpayWeb.ConnCase, async: true

  alias Rocketpay.{Account, User}

  describe "deposit/2" do
    setup %{conn: conn} do
      params = %{
        name: "Daniel",
        password: "123456",
        nickname: "dan",
        email: "dan@email.com",
        age: 20
      }

      {:ok, %User{account: %Account{id: account_id}}} = Rocketpay.create_user(params)

      # o user e senha decodificado = YmF0YXRhOmJhdGF0YTEyMw==
      conn = put_req_header(conn, "authorization", "Basic YmF0YXRhOmJhdGF0YTEyMw==")

      {:ok, conn: conn, account_id: account_id}
    end

    test "when all params are valid, make the deposit", %{conn: conn, account_id: account_id} do
      params = %{"value" => "10.00"}

      response =
        conn
        |> post(Routes.accounts_path(conn, :deposit, account_id, params))
        |> json_response(:ok)

      assert %{
               "account" => %{"balance" => "10.00", "id" => _id},
               "message" => "Balance changed sucessfully"
             } = response
    end

    test "when there are invalid params, returns an error", %{conn: conn, account_id: account_id} do
      params = %{"value" => "batata"}

      response =
        conn
        |> post(Routes.accounts_path(conn, :deposit, account_id, params))
        |> json_response(:bad_request)

      expected_response = %{"message" => "Invalid operation value"}

      assert response == expected_response
    end
  end
end

Teste de View (Não precisa testar a falha, pois a View só é renderizada quando a request é bem sucedida)