Skip to content

Commit

Permalink
Setting up hound integration tests
Browse files Browse the repository at this point in the history
Motivation:
  - The admin generates a lot of custom html, forms and user
    interactions. Setup end to end integration tests to make sure that
    the user's experience is working as expected.
  - /issues/11

Changes:
  - Setup Hound
  - Setup Travis to work with phantomjs
  - Turn on the server for the test environment and ensure cowboy is
    running.
  - Add new integration tests and required support files.
  - As a first test just test the edit page and dashboard for an
    example.
  • Loading branch information
gwincr11 committed Dec 2, 2016
1 parent 4436c7a commit bc92d81
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -2,12 +2,14 @@ services:
- postgresql
before_script:
- psql -c 'create database ex_admin_test;' -U postgres
- nohup phantomjs --wd &
language: elixir
elixir:
- 1.3.1
otp_release:
- 18.2.1
sudo: false
script: mix test --include integration:true
notification:
recipients:
- smpallen99@yahoo.com
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Expand Up @@ -194,6 +194,14 @@ in order to craft an excellent pull request:
mix test
```

There are also integration tests that make sure the forms are working in a phantomjs browser.
```bash
phantomjs --wd
mix test --include integration:true
```



7. Push your topic branch up to your fork:

```bash
Expand Down
5 changes: 2 additions & 3 deletions config/config.exs
Expand Up @@ -32,13 +32,12 @@ use Mix.Config
config :ex_admin,
repo: MyProject.Repo,
module: MyProject,
modules: []
modules: [],
module: ExAdmin

config :phoenix, :template_engines,
haml: PhoenixHaml.Engine,
eex: Phoenix.Template.EExEngine
config :ex_admin,
module: ExAdmin

# Sample configuration:
#
Expand Down
6 changes: 4 additions & 2 deletions config/test.exs
Expand Up @@ -3,7 +3,7 @@ use Mix.Config
config :ex_admin, TestExAdmin.Endpoint,
http: [port: 4001],
secret_key_base: "HL0pikQMxNSA58DV3mf26O/eh1e4vaJDmx1qLgqBcnS14gbKu9Xn3x114D+mHYcX",
server: false
server: true

config :ex_admin, TestExAdmin.Repo,
adapter: Ecto.Adapters.Postgres,
Expand All @@ -24,11 +24,13 @@ config :ex_admin,
TestExAdmin.ExAdmin.Simple,
TestExAdmin.ExAdmin.ModelDisplayName,
TestExAdmin.ExAdmin.DefnDisplayName,
TestExAdmin.ExAdmin.RestrictedEdit
TestExAdmin.ExAdmin.RestrictedEdit,
]

config :xain,
quote: "'",
after_callback: {Phoenix.HTML, :raw}

config :logger, level: :error

config :hound, driver: "phantomjs"
2 changes: 2 additions & 0 deletions lib/ex_admin.ex
@@ -0,0 +1,2 @@
defmodule ExAdmin do
end
5 changes: 3 additions & 2 deletions mix.exs
Expand Up @@ -28,7 +28,7 @@ defmodule ExAdmin.Mixfile do
end

defp applications(:test) do
[:plug | applications(:prod)]
[:plug, :cowboy | applications(:prod)]
end
defp applications(_) do
[:gettext, :phoenix, :ecto, :inflex, :scrivener, :scrivener_ecto, :csvlixir, :logger, :ex_queb, :xain]
Expand Down Expand Up @@ -56,7 +56,8 @@ defmodule ExAdmin.Mixfile do
{:earmark, "~> 0.1", only: :dev},
{:ex_queb, "~> 0.2"},
{:excoveralls, "~> 0.5", only: :test},
{:gettext, "~> 0.11"}
{:gettext, "~> 0.11"},
{:hound, "~> 1.0"}
]
end

Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Expand Up @@ -16,6 +16,8 @@
"floki": {:hex, :floki, "0.11.0", "b4532ab64d67225f13f5626e4ba1b8cf3ee9d5bd48017075bb975e1522efd32d", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, optional: false]}]},
"gettext": {:hex, :gettext, "0.12.1", "c0624f52763469ef7a3674919ae28b8286d88195b90fa1516180f31bbbd26d14", [:mix], []},
"hackney": {:hex, :hackney, "1.6.3", "d489d7ca2d4323e307bedc4bfe684323a7bf773ecfd77938f3ee8074e488e140", [:mix, :rebar3], [{:certifi, "0.7.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]},
"hound": {:hex, :hound, "1.0.2", "b6dd20142d00c28009fad503a23fa4a76bc11899e0d198f36a9c1448427788b2", [], [{:httpoison, "~> 0.8", [hex: :httpoison, optional: false]}, {:poison, ">= 1.4.0", [hex: :poison, optional: false]}]},
"httpoison": {:hex, :httpoison, "0.10.0", "4727b3a5e57e9a4ff168a3c2883e20f1208103a41bccc4754f15a9366f49b676", [], [{:hackney, "~> 1.6.3", [hex: :hackney, optional: false]}]},
"idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []},
"inflex": {:hex, :inflex, "1.8.0", "7cfc752ae244b30b42ac9cf4c092771b485bc3424139aba4a933e54be8c63931", [:mix], []},
"jsx": {:hex, :jsx, "2.8.0", "749bec6d205c694ae1786d62cea6cc45a390437e24835fd16d12d74f07097727", [:mix, :rebar], []},
Expand Down
46 changes: 46 additions & 0 deletions test/integration/create_test.exs
@@ -0,0 +1,46 @@
defmodule TestExAdmin.CreateTest do
use TestExAdmin.AcceptanceCase
alias TestExAdmin.{Noid, User, Product, Simple}
alias Hound.Element

hound_session
# Start hound session and destroy when tests are run
setup do
user = insert_user()
current_window_handle |> maximize_window
{:ok, user: user}
end

@tag :integration
test "create a product", %{ user: user } do
navigate_to admin_resource_path(Product, :new)

title_field = find_element(:name, "product[title]")
price_field = find_element(:name, "product[price]")
user_field = find_element(:name, "product[user_id]")

fill_field title_field, "Test Create"
fill_field price_field, ".99"
find_element(:css, "select[name*='product[user_id]']")
|> find_all_within_element(:css, "option")
|> Enum.find(fn(x) -> attribute_value(x, "value") == "#{user.id}" end)
|> click

click(find_element(:name, "commit"))

assert visible_text(find_element(:class, "td-title")) == "Test Create"
assert visible_text(find_element(:class, "td-price")) == "0.99"
assert visible_text(find_element(:class, "td-user")) == user.name
end

@tag :integration
test "validate product creation" do
navigate_to admin_resource_path(Product, :new)
click(find_element(:name, "commit"))

title_wrapper = find_element(:css, "#product_title_input")
price_wrapper = find_element(:css, "#product_price_input")
assert visible_text(title_wrapper) == "Title*\ncan't be blank"
assert visible_text(price_wrapper) == "Price*\ncan't be blank"
end
end
20 changes: 20 additions & 0 deletions test/integration/dashboard_test.exs
@@ -0,0 +1,20 @@
defmodule TestExAdmin.DashboardIntegrationTest do
use TestExAdmin.AcceptanceCase
alias TestExAdmin.{Noid, User, Product, Simple}
alias Hound.Element

hound_session

@tag :integration
test "gets dashboard" do
navigate_to "/admin"
assert(String.contains? visible_page_text, "dashboard")
end

@tag :integration
test "dashboard shows sidebar" do
navigate_to "/admin"
assert(String.contains? visible_page_text, "Test Sidebar")
assert(String.contains? visible_page_text, "This is a test.")
end
end
33 changes: 33 additions & 0 deletions test/integration/delete_test.exs
@@ -0,0 +1,33 @@
defmodule TestExAdmin.DeleteTest do
use TestExAdmin.AcceptanceCase
alias TestExAdmin.{Noid, User, Product, Simple}
alias Hound.Element

hound_session
# Start hound session and destroy when tests are run
setup do
user = insert_user()
{:ok, user: user}
end

#
# This test is pending PhantomJS dialog support
# https://github.com/detro/ghostdriver/issues/20
#
@tag :pending
test "delete a noid", %{user: user} do
noid = insert_noid(user_id: user.id, name: "controller 1")
user2 = insert_user()
current_window_handle |> maximize_window
navigate_to admin_resource_path(Noid, :index)

assert page_source =~ noid.name
click(find_element(:class, "delete_link"))

assert dialog_text() == "Are you sure you want to delete this?"
accept_dialog()

assert current_url == admin_resource_path(Noid, :index)
refute page_source =~ noid.name
end
end
41 changes: 41 additions & 0 deletions test/integration/update_test.exs
@@ -0,0 +1,41 @@
defmodule TestExAdmin.UpdateTest do
use TestExAdmin.AcceptanceCase
alias TestExAdmin.{Noid, User, Product, Simple}
alias Hound.Element

hound_session
# Start hound session and destroy when tests are run
setup do
user = insert_user()
{:ok, user: user}
end

@tag :integration
test "edit a noid updates correct data", %{user: user} do
noid = insert_noid(user_id: user.id, name: "controller 1")
user2 = insert_user()
current_window_handle |> maximize_window
navigate_to admin_resource_path(Noid, :index)
click(find_element(:class, "edit_link"))

name_field = find_element(:name, "noid[name]")
description_field = find_element(:name, "noid[description]")
company_field = find_element(:name, "noid[company]")
user_field = find_element(:name, "noid[user_id]")

assert attribute_value(name_field, "value") == noid.name
assert attribute_value(description_field, "value") == noid.description
assert attribute_value(company_field, "value") == noid.company
assert attribute_value(user_field, "value") == "#{noid.user_id}"

fill_field name_field, "Cory"
fill_field description_field, "Updated"
fill_field company_field, "This"

click(find_element(:name, "commit"))

assert visible_text(find_element(:class, "td-name")) == "Cory"
assert visible_text(find_element(:class, "td-description")) == "Updated"
assert visible_text(find_element(:class, "td-company")) == "This"
end
end
31 changes: 31 additions & 0 deletions test/support/acceptance_case.exs
@@ -0,0 +1,31 @@
defmodule TestExAdmin.AcceptanceCase do
use ExUnit.CaseTemplate

using do
quote do
use Hound.Helpers

import Ecto.Model
import Ecto.Query, only: [from: 2]

alias TestExAdmin.Repo
import TestExAdmin.Router.Helpers
import TestExAdmin.TestHelpers
import TestExAdmin.ErrorView
import ExAdmin.Utils
import TestExAdmin.TestHelpers
@endpoint TestExAdmin.Endpoint
end
end

setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(TestExAdmin.Repo)
metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(TestExAdmin.Repo, self())
Hound.start_session(metadata: metadata)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(TestExAdmin.Repo, {:shared, self()})
end
:ok
end
end

17 changes: 17 additions & 0 deletions test/support/web.exs
@@ -0,0 +1,17 @@
defmodule TestExAdmin.Web do

def view do
quote do
use Phoenix.View, root: "test/support/templates"
# Import convenience functions from controllers
import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]

# Use all HTML functionality (forms, tags, etc)
use Phoenix.HTML

end
end
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end
9 changes: 7 additions & 2 deletions test/test_helper.exs
@@ -1,14 +1,18 @@
Application.ensure_all_started(:hound)
ExUnit.configure(exclude: [pending: true, integration: true])
ExUnit.start()

Code.require_file "./support/web.exs", __DIR__
Code.require_file "./support/schema.exs", __DIR__
Code.require_file "./support/router.exs", __DIR__
Code.require_file "./support/repo.exs", __DIR__
Code.require_file "./support/migrations.exs", __DIR__
Code.require_file "./support/admin_resources.exs", __DIR__
Code.require_file "./support/router.exs", __DIR__
Code.require_file "./support/endpoint.exs", __DIR__
Code.require_file "./support/conn_case.exs", __DIR__
Code.require_file "./support/acceptance_case.exs", __DIR__
Code.require_file "./support/test_helpers.exs", __DIR__
Code.require_file "./support/view.exs", __DIR__
Code.require_file "./support/endpoint.exs", __DIR__

defmodule ExAdmin.RepoSetup do
use ExUnit.CaseTemplate
Expand All @@ -23,3 +27,4 @@ _ = Ecto.Migrator.up(TestExAdmin.Repo, 0, TestExAdmin.Migrations, log: false)
Process.flag(:trap_exit, true)
Ecto.Adapters.SQL.Sandbox.mode(TestExAdmin.Repo, :manual)


0 comments on commit bc92d81

Please sign in to comment.