Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge dot file settings and project settings #122

Merged
merged 2 commits into from
Dec 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions lib/excoveralls/settings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ defmodule ExCoveralls.Settings do
"""

defmodule Files do
@file_name "coveralls.json"
def default_file, do: "#{Path.dirname(__ENV__.file)}/../conf/#{@file_name}"
def custom_file do
dot_file = Path.expand("~/.excoveralls/coveralls.json")
if File.exists?(dot_file), do: dot_file, else: "#{System.cwd}/#{@file_name}"
end
@filename "coveralls.json"
def default_file, do: "#{Path.dirname(__ENV__.file)}/../conf/#{@filename}"
def custom_file, do: "#{System.cwd}/#{@filename}"
def dot_file, do: Path.expand("~/.excoveralls/#{@filename}")
end

@doc """
Expand Down Expand Up @@ -83,10 +81,31 @@ defmodule ExCoveralls.Settings do
Reads the value for the specified key defined in the json file.
"""
def read_config(key, default \\ nil) do
case (read_config_file(Files.custom_file) |> Map.get(key)) do
nil -> read_config_file(Files.default_file) |> Map.get(key, default)
case (read_merged_config(Files.dot_file, Files.custom_file) |> Map.get(key)) do
nil -> read_config_file(Files.default_file()) |> Map.get(key, default)
config -> config
end
end

defp read_merged_config(dot, custom) do
dot_config = read_config_file(dot)
project_config = read_config_file(custom)
merge(dot_config, project_config)
end

defp merge(left, right) when is_map(left) and is_map(right) do
keys = Map.keys(left) ++ Map.keys(right)
Enum.reduce(keys, %{}, fn k, new_map ->
merged = cond do
Map.has_key?(left, k) and Map.has_key?(right, k) -> merge(Map.get(left, k), Map.get(right, k))
Map.has_key?(left, k) == false and Map.has_key?(right, k) -> Map.get(right, k)
Map.has_key?(left, k) and Map.has_key?(right, k) == false -> Map.get(left, k)
true -> %{}
end
Map.put(new_map, k, merged)
end)
end
defp merge(left, right) when is_list(left) and is_list(right), do: Enum.uniq(left ++ right)
defp merge(left, right), do: right
end

9 changes: 9 additions & 0 deletions test/fixtures/dotfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"coverage_options": {
"template_path": "/users/test/.excoveralls/templates/html/htmlcov"
},
"custom_stop_words": [
"cc",
"dd"
]
}
41 changes: 31 additions & 10 deletions test/settings_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Excoveralls.SettingsTest do

@fixture_default Path.dirname(__ENV__.file) <> "/fixtures/default.json"
@fixture_custom Path.dirname(__ENV__.file) <> "/fixtures/custom.json"
@fixture_dotfile Path.dirname(__ENV__.file) <> "/fixtures/dotfile.json"
@fixture_invalid Path.dirname(__ENV__.file) <> "/fixtures/invalid.json"
@fixture_not_covered Path.dirname(__ENV__.file) <> "/fixtures/no_relevant_lines_not_covered.json"
@fixture_covered Path.dirname(__ENV__.file) <> "/fixtures/no_relevant_lines_are_covered.json"
Expand All @@ -23,49 +24,57 @@ defmodule Excoveralls.SettingsTest do

test_with_mock "read config defined in default file", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_custom end] do
custom_file: fn -> @fixture_custom end,
dot_file: fn -> @fixture_dotfile end] do
assert(Settings.read_config("default_stop_words") == ["a", "b"])
end

test_with_mock "read config defined in custom file", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_custom end] do
custom_file: fn -> @fixture_custom end,
dot_file: fn -> "__invalid__" end] do
assert(Settings.read_config("custom_stop_words") == ["aa", "bb"])
end

test_with_mock "get stop words returns merged default and custom stop words", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_custom end] do
custom_file: fn -> @fixture_custom end,
dot_file: fn -> "__invalid__" end] do
assert(Settings.get_stop_words == [~r"a", ~r"b", ~r"aa", ~r"bb"])
end

test_with_mock "get coverage options returns options as Dict", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_custom end] do
custom_file: fn -> @fixture_custom end,
dot_file: fn -> "__invalid__" end] do
assert(inspect(Settings.get_coverage_options) == "%{\"f\" => true}")
end

test_with_mock "get terminal width for file column", Settings.Files,
[default_file: fn -> @fixture_column_default end,
custom_file: fn -> @fixture_column_integer end] do
custom_file: fn -> @fixture_column_integer end,
dot_file: fn -> @fixture_dotfile end] do
assert(inspect(Settings.get_file_col_width) == "40")
end

test_with_mock "read config returns nil when default file is not found", Settings.Files,
[default_file: fn -> "__invalid__" end,
custom_file: fn -> "__invalid__" end] do
custom_file: fn -> "__invalid__" end,
dot_file: fn -> "__invalid__" end] do
assert(Settings.read_config("custom_stop_words", []) == [])
end

test_with_mock "read config returns default value when custom file is not found", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> "__invalid__" end] do
custom_file: fn -> "__invalid__" end,
dot_file: fn -> @fixture_dotfile end] do
assert(Settings.read_config("default_stop_words") == ["a", "b"])
end

test_with_mock "read config fails if JSON file is invalid", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_invalid end] do
custom_file: fn -> @fixture_invalid end,
dot_file: fn -> @fixture_dotfile end] do
assert_raise RuntimeError, fn ->
Settings.read_config("default_stop_words")
end
Expand All @@ -74,17 +83,29 @@ defmodule Excoveralls.SettingsTest do
test_with_mock "default coverage value returns 100 when treating irrelevant lines as covered",
Settings.Files, [
default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_covered end
custom_file: fn -> @fixture_covered end,
dot_file: fn -> @fixture_dotfile end
] do
assert Settings.default_coverage_value == 100
end

test_with_mock "default coverage value returns 0 when treating irrelevant lines as not covered",
Settings.Files, [
default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_not_covered end,
dot_file: fn -> @fixture_dotfile end
] do
assert Settings.default_coverage_value == 0
end

test_with_mock "merges dotfile config with custom config",
Settings.Files, [
default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_not_covered end
custom_file: fn -> @fixture_custom end,
dot_file: fn -> @fixture_dotfile end
] do
assert Settings.default_coverage_value == 0
assert Settings.get_stop_words()== [~r/a/, ~r/b/, ~r/cc/, ~r/dd/, ~r/aa/, ~r/bb/]
end

end
Expand Down
3 changes: 2 additions & 1 deletion test/stats_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ defmodule ExCoveralls.StatsTest do

test_with_mock "skip files", Settings.Files,
[default_file: fn -> @fixture_default end,
custom_file: fn -> @fixture_custom end] do
custom_file: fn -> @fixture_custom end,
dot_file: fn -> "__invalid__" end] do
assert Stats.skip_files(@source_info) == []
end

Expand Down