Skip to content

Commit

Permalink
Refactor integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
danschultzer committed Dec 28, 2024
1 parent 5ab2f96 commit df1a8fd
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 109 deletions.
12 changes: 2 additions & 10 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
# Used by "mix format" and to export configuration.
export_locals_without_parens = [
plug: 1,
plug: 2,
get: 2
]

# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{integration,lib,test}/**/*.{ex,exs}"],
locals_without_parens: export_locals_without_parens,
export: [locals_without_parens: export_locals_without_parens]
inputs: ["{mix,.formatter}.exs", "{lib,test}/**/*.{ex,exs}"]
]
31 changes: 29 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,44 @@ jobs:
otp-version: 27.0
elixir-version: 1.18
- uses: actions/cache@v4
env:
cache-name: assent
with:
path: |
_build/test
_build
deps
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
key: ${{ runner.os }}-mix-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }}
- run: mix deps.get
- run: mix compile --warnings-as-errors
- run: mix credo --strict --ignore design.tagtodo
- run: mix format --check-formatted
- run: mix dialyzer --format github

integration:
runs-on: ubuntu-latest
name: Integration server
defaults:
run:
working-directory: integration
steps:
- uses: actions/checkout@v3
- uses: erlef/setup-beam@v1
with:
otp-version: 27.0
elixir-version: 1.18
- uses: actions/cache@v4
env:
cache-name: integration-server
with:
path: |
integration/_build
integration/deps
key: ${{ runner.os }}-mix-${{ env.cache-name }}-${{ hashFiles('**/integration/mix.lock') }}
- run: mix deps.get
- run: mix compile --warnings-as-errors
- run: mix format --check-formatted
- run: mix dialyzer --format github

test:
strategy:
matrix:
Expand Down
12 changes: 12 additions & 0 deletions integration/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Used by "mix format" and to export configuration.
export_locals_without_parens = [
plug: 1,
plug: 2,
get: 2
]

[
inputs: ["{mix,.formatter}.exs", "{integration,lib,test}/**/*.{ex,exs}"],
locals_without_parens: export_locals_without_parens,
export: [locals_without_parens: export_locals_without_parens]
]
23 changes: 23 additions & 0 deletions integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
project-*.tar

# Temporary files, for example, from tests.
/tmp/
2 changes: 1 addition & 1 deletion integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
Simple plug-based server to test assent integration with all providers.

```bash
CLIENT_ID=CLIENT_ID CLIENT_SECRET=CLIENT_SECRET MIX_ENV=test mix run --no-halt integration/server.exs
mix run --no-halt
```
12 changes: 12 additions & 0 deletions integration/lib/application.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule IntegrationServer.Application do
use Application

def start(_type, _args) do
children = [
{Bandit, plug: IntegrationServer.Router}
]

opts = [strategy: :one_for_one, name: IntegrationServer.Supervisor]
Supervisor.start_link(children, opts)
end
end
122 changes: 122 additions & 0 deletions integration/lib/router.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
defmodule IntegrationServer.Router do
use Plug.Router
use Plug.Debugger
use Plug.ErrorHandler

require Logger

import Plug.Conn

@session_options [
store: :cookie,
key: "_assent_integration_server",
signing_salt: "Q1OaP6Pz",
same_site: "Lax"
]

plug :secret_key_base
plug Plug.Session, @session_options
plug :fetch_session
plug :match
plug :dispatch

{:ok, modules} = :application.get_key(:assent, :modules)

@path_modules modules
|> Enum.map(&{Module.split(&1), &1})
|> Enum.map(fn
{["Assent", "Strategy", uri], module} ->
path = Macro.underscore(uri)
fun_name = String.to_atom(path)
{path, module, fun_name}

_any ->
nil
end)
|> Enum.reject(&is_nil/1)

defp secret_key_base(conn, _opts) do
%{conn | secret_key_base: "LG8WiSkAlUlwVJpISmRYsi7aJV/Qlv65FXyxwWXxp1QUzQY3hzEfg73YKfKZPpe0"}
end

for {path, module, fun_name} <- @path_modules do
@file "#{__ENV__.file}##{path}_auth"
defp unquote(fun_name)(conn, :auth) do
unquote(path)
|> config!()
|> unquote(module).authorize_url()
|> case do
{:ok, %{session_params: session_params, url: url}} ->
Logger.info("Redirecting to #{inspect(url)} with session params #{inspect(session_params)}")

html = Plug.HTML.html_escape(url)
body = "<html><body>You are being <a href=\"#{html}\">redirected</a>.</body></html>"

conn
|> put_session(:session_params, session_params)
|> put_resp_header("location", url)
|> put_resp_header("content-type", "text/html")
|> send_resp(302, body)

{:error, error} ->
body = "<html><body>An error occurred: #{inspect error}.</body></html>"

conn
|> put_resp_header("content-type", "text/html")
|> send_resp(500, body)
end
end

@file "#{__ENV__.file}##{path}_callback"
defp unquote(fun_name)(conn, :callback) do
conn = fetch_query_params(conn)

unquote(path)
|> config!()
|> Assent.Config.put(:session_params, get_session(conn, :session_params))
|> unquote(module).callback(conn.params)
|> case do
{:ok, %{user: user, token: token}} ->
body = "<html><body>#{inspect(%{user: user, token: token})}</body></html>"

send_resp(conn, 200, body)

{:error, error} ->
body = "<html><body>An error occurred: #{inspect error}.</body></html>"

conn
|> put_resp_header("content-type", "text/html")
|> send_resp(500, body)
end
end
end

get "/" do
list =
@path_modules
|> Enum.map(&"<li><a href=\"/#{elem(&1, 0)}\">#{elem(&1, 0)}</a></li>")
|> Enum.join()

body = "<html><body><ul>#{list}</ul></body></html>"

send_resp(conn, 200, body)
end

for {path, _module, fun_name} <- @path_modules do
get "/#{path}", do: unquote(fun_name)(conn, :auth)
get "/#{path}/callback", do: unquote(fun_name)(conn, :callback)
end

def config!(path) do
[
client_id: System.fetch_env!("CLIENT_ID"),
client_secret: System.fetch_env!("CLIENT_SECRET"),
redirect_uri: "http://localhost:4000/#{path}/callback"
]
end

@impl true
def handle_errors(conn, %{kind: _kind, reason: _reason, stack: _stack}) do
send_resp(conn, conn.status, "Something went wrong")
end
end
32 changes: 32 additions & 0 deletions integration/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule IntegrationServer.MixProject do
use Mix.Project

def project do
[
app: :integration_server,
version: "0.0.1",
elixir: "~> 1.13",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

def application do
[
mod: {IntegrationServer.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end

defp elixirc_paths(_), do: ["lib"]

defp deps do
[
{:assent, path: "../"},
{:plug, ">= 0.0.0"},
{:bandit, ">= 0.0.0"},
{:dialyxir, "~> 1.4", runtime: false}
]
end
end
12 changes: 12 additions & 0 deletions integration/mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
%{
"bandit": {:hex, :bandit, "1.6.1", "9e01b93d72ddc21d8c576a704949e86ee6cde7d11270a1d3073787876527a48f", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5a904bf010ea24b67979835e0507688e31ac873d4ffc8ed0e5413e8d77455031"},
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"hpax": {:hex, :hpax, "1.0.2", "762df951b0c399ff67cc57c3995ec3cf46d696e41f0bba17da0518d94acd4aac", [:mix], [], "hexpm", "2f09b4c1074e0abd846747329eaa26d535be0eb3d189fa69d812bfb8bfefd32f"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"thousand_island": {:hex, :thousand_island, "1.3.7", "1da7598c0f4f5f50562c097a3f8af308ded48cd35139f0e6f17d9443e4d0c9c5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0139335079953de41d381a6134d8b618d53d084f558c734f2662d1a72818dd12"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
}
96 changes: 0 additions & 96 deletions integration/server.exs

This file was deleted.

1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ defmodule Assent.MixProject do
{:credo, "~> 1.1", only: [:dev, :test]},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
{:test_server, "~> 0.1.0", only: :test},
{:plug, ">= 0.0.0", only: [:dev, :test]},
{:bandit, ">= 0.0.0", only: :test}
]
end
Expand Down

0 comments on commit df1a8fd

Please sign in to comment.