Packages
espec
0.8.25
1.10.0
1.9.2
1.9.1
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.8.28
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.7
0.3.5
0.3.0
0.2.0
0.1.0
BDD testing framework for Elixir inspired by RSpec.
Current section
Files
Jump to
Current section
Files
lib/espec/output/html.ex
defmodule ESpec.Output.Html do
@moduledoc """
Generates html output.
"""
alias ESpec.Example
@doc "Format the final result."
def format_result(examples, times, _opts) do
tree = context_tree(examples)
html = make_html(tree, true)
summary = format_summary(examples, times)
string = EEx.eval_file(template_path, [examples: html, summary: summary])
String.replace(string, "\n", "")
end
@doc "Formats an example result."
def format_example(_example, _opts), do: ""
defp template_path, do: Path.join(Path.dirname(__ENV__.file), "templates/html.html.eex")
defp context_tree(examples) do
examples
|> Enum.reduce({Map.new, []}, fn(ex, acc) ->
contexts = Enum.filter(ex.context, &(&1.__struct__ == ESpec.Context))
put_deep(acc, contexts, ex)
end)
end
defp put_deep({dict, values}, [el | tl], value) when length(tl) > 0 do
d = case Map.get(dict, el) do
{inner, vals} -> put_deep({inner, vals}, tl, value)
nil -> put_deep({Map.new, []}, tl, value)
end
{Map.put(dict, el, d), values}
end
defp put_deep({dict, values}, [el], value) do
new_dict = case Map.get(dict, el) do
{inner, vals} -> Map.put(dict, el, {inner, [value | vals]})
nil -> Map.put(dict, el, {Map.new, [value]})
end
{new_dict, values}
end
defp put_deep({dict, values}, [], value) do
{dict, [value | values]}
end
defp make_html({dict, values}, top? \\ false, firstli? \\ false) do
lis = Enum.reduce(values, "", fn(ex, acc) ->
acc <> "<li class='#{li_class(ex)}'>#{ex_desc(ex)}</li>"
end)
lis = if String.length(lis) > 0 do
if firstli?, do: "<ul class='tree'>" <> lis <> "</ul>", else: "<ul>" <> lis <> "</ul>"
else
lis
end
uls = Enum.reduce(dict, lis, fn({key, d}, acc) ->
if top? do
acc <> "<section class='context'><h3>#{key.description}</h3>" <> make_html(d, false, true) <> "</section>"
else
mainli = "<li><h4>#{key.description}</h4>"
if firstli? do
acc <> "<ul class='tree'>#{mainli}" <> make_html(d) <> "</li></ul>"
else
acc <> "<ul>#{mainli}" <> make_html(d) <> "</li></ul>"
end
end
end)
uls
end
defp ex_desc(ex) do
res = if String.length(ex.description) > 0 do
ex.description
else
if ex.status == :failure, do: ex.error.message, else: ex.result
end
res = "#{res} (#{ex.duration} ms)"
String.replace(res, "\"", "'")
end
defp li_class(ex), do: ex.status
defp format_summary(examples, {start_loading_time, finish_loading_time, finish_specs_time}) do
pending = Example.pendings(examples)
failed = Example.failure(examples)
load_time = :timer.now_diff(finish_loading_time, start_loading_time)
spec_time = :timer.now_diff(finish_specs_time, finish_loading_time)
seed = get_seed
{
Enum.count(examples), Enum.count(failed), Enum.count(pending),
us_to_sec(load_time + spec_time), us_to_sec(load_time), us_to_sec(spec_time),
seed
}
end
defp us_to_sec(us), do: div(us, 10000) / 100
defp get_seed do
if ESpec.Configuration.get(:order) do
false
else
ESpec.Configuration.get(:seed)
end
end
end