diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 0000000..9304539 --- /dev/null +++ b/.credo.exs @@ -0,0 +1,159 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any exec using `mix credo -C `. If no exec name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: ["lib/", "src/", "test/", "web/", "apps/"], + excluded: [~r"/_build/", ~r"/deps/"] + }, + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: false, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames}, + {Credo.Check.Consistency.LineEndings}, + {Credo.Check.Consistency.ParameterPatternMatching}, + {Credo.Check.Consistency.SpaceAroundOperators}, + {Credo.Check.Consistency.SpaceInParentheses}, + {Credo.Check.Consistency.TabsOrSpaces}, + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, priority: :low}, + # For some checks, you can also set other parameters + # + # If you don't want the `setup` and `test` macro calls in ExUnit tests + # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just + # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. + # + {Credo.Check.Design.DuplicatedCode, excluded_macros: []}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, exit_status: 0}, + {Credo.Check.Design.TagFIXME}, + + # + ## Readability Checks + # + {Credo.Check.Readability.FunctionNames}, + {Credo.Check.Readability.LargeNumbers}, + {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80}, + {Credo.Check.Readability.ModuleAttributeNames}, + {Credo.Check.Readability.ModuleDoc}, + {Credo.Check.Readability.ModuleNames}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs}, + {Credo.Check.Readability.ParenthesesInCondition}, + {Credo.Check.Readability.PredicateFunctionNames}, + {Credo.Check.Readability.PreferImplicitTry}, + {Credo.Check.Readability.RedundantBlankLines}, + {Credo.Check.Readability.StringSigils}, + {Credo.Check.Readability.TrailingBlankLine}, + {Credo.Check.Readability.TrailingWhiteSpace}, + {Credo.Check.Readability.VariableNames}, + {Credo.Check.Readability.Semicolons}, + {Credo.Check.Readability.SpaceAfterCommas}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.DoubleBooleanNegation}, + {Credo.Check.Refactor.CondStatements}, + {Credo.Check.Refactor.CyclomaticComplexity}, + {Credo.Check.Refactor.FunctionArity}, + {Credo.Check.Refactor.LongQuoteBlocks}, + {Credo.Check.Refactor.MatchInCondition}, + {Credo.Check.Refactor.NegatedConditionsInUnless}, + {Credo.Check.Refactor.NegatedConditionsWithElse}, + {Credo.Check.Refactor.Nesting}, + {Credo.Check.Refactor.PipeChainStart, + excluded_argument_types: [:atom, :binary, :fn, :keyword], excluded_functions: []}, + {Credo.Check.Refactor.UnlessWithElse}, + + # + ## Warnings + # + {Credo.Check.Warning.BoolOperationOnSameValues}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck}, + {Credo.Check.Warning.IExPry}, + {Credo.Check.Warning.IoInspect}, + {Credo.Check.Warning.LazyLogging}, + {Credo.Check.Warning.OperationOnSameValues}, + {Credo.Check.Warning.OperationWithConstantResult}, + {Credo.Check.Warning.UnusedEnumOperation}, + {Credo.Check.Warning.UnusedFileOperation}, + {Credo.Check.Warning.UnusedKeywordOperation}, + {Credo.Check.Warning.UnusedListOperation}, + {Credo.Check.Warning.UnusedPathOperation}, + {Credo.Check.Warning.UnusedRegexOperation}, + {Credo.Check.Warning.UnusedStringOperation}, + {Credo.Check.Warning.UnusedTupleOperation}, + {Credo.Check.Warning.RaiseInsideRescue}, + + # + # Controversial and experimental checks (opt-in, just remove `, false`) + # + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.AppendSingleItem, false}, + {Credo.Check.Refactor.VariableRebinding, false}, + {Credo.Check.Warning.MapGetUnsafePass, false}, + {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, + + # + # Deprecated checks (these will be deleted after a grace period) + # + {Credo.Check.Readability.Specs, false} + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/.travis.yml b/.travis.yml index fe06704..d4c6560 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ install: - mix deps.get script: - mix test + - mix credo matrix: exclude: - elixir: 1.3.4 diff --git a/lib/catalog_api.ex b/lib/catalog_api.ex index d86f5fb..7db6c49 100644 --- a/lib/catalog_api.ex +++ b/lib/catalog_api.ex @@ -196,7 +196,7 @@ defmodule CatalogApi do | {:error, {:catalog_api_fault, Error.extracted_fault()}} | {:error, Poison.ParseError.t()} | {:error, :unparseable_response_description} - def cart_set_address(socket_id, external_user_id, address = %Address{}) do + def cart_set_address(socket_id, external_user_id, %Address{} = address) do address_params = Map.from_struct(address) cart_set_address(socket_id, external_user_id, address_params) end @@ -613,7 +613,9 @@ defmodule CatalogApi do """ def order_list(external_user_id, opts \\ []) do defaults = [per_page: 10, page: 1] - %{per_page: per_page, page: page} = Keyword.merge(defaults, opts) |> Enum.into(%{}) + %{per_page: per_page, page: page} = defaults + |> Keyword.merge(opts) + |> Enum.into(%{}) # TODO: validate that per_page is at most 50. diff --git a/lib/catalog_api/address.ex b/lib/catalog_api/address.ex index 87eb0d3..cdf13a5 100644 --- a/lib/catalog_api/address.ex +++ b/lib/catalog_api/address.ex @@ -313,12 +313,10 @@ defmodule CatalogApi.Address do def validate_field(_field, _value), do: %{} defp validate_field_length(field, value, max_length) when is_binary(value) do - cond do - String.length(value) > max_length -> - %{field => ["cannot be longer than #{max_length} characters"]} - - true -> - %{} + if String.length(value) > max_length do + %{field => ["cannot be longer than #{max_length} characters"]} + else + %{} end end end diff --git a/lib/catalog_api/coercion.ex b/lib/catalog_api/coercion.ex index 37f05b9..cc7e400 100644 --- a/lib/catalog_api/coercion.ex +++ b/lib/catalog_api/coercion.ex @@ -15,9 +15,10 @@ defmodule CatalogApi.Coercion do @spec coerce_to_boolean_if_needed(String.t() | atom(), any(), list(String.t() | atom())) :: {String.t(), any()} defp coerce_to_boolean_if_needed(key, value, boolean_fields) do - cond do - key in boolean_fields -> {key, coerce_integer_to_boolean(value)} - true -> {key, value} + if key in boolean_fields do + {key, coerce_integer_to_boolean(value)} + else + {key, value} end end @@ -42,9 +43,10 @@ defmodule CatalogApi.Coercion do @spec coerce_to_integer_if_needed(String.t() | atom(), any(), list(Strin.t() | atom())) :: {String.t(), any()} defp coerce_to_integer_if_needed(key, value, boolean_fields) do - cond do - key in boolean_fields -> {key, coerce_boolean_to_integer(value)} - true -> {key, value} + if key in boolean_fields do + {key, coerce_boolean_to_integer(value)} + else + {key, value} end end diff --git a/mix.exs b/mix.exs index 496d6ec..400d2f2 100644 --- a/mix.exs +++ b/mix.exs @@ -27,6 +27,7 @@ defmodule CatalogApi.Mixfile do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:credo, "~> 0.9.1", only: [:dev, :test], runtime: false}, {:ex_doc, "~> 0.16", only: :dev, runtime: false}, {:httpoison, "~> 1.0"}, {:mock, "~> 0.3.0", only: :test}, diff --git a/mix.lock b/mix.lock index af5b0b6..106d8d5 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,7 @@ %{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, + "credo": {:hex, :credo, "0.9.2", "841d316612f568beb22ba310d816353dddf31c2d94aa488ae5a27bb53760d0bf", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.18.2", "993e0a95e9fbb790ac54ea58e700b45b299bd48bc44b4ae0404f28161f37a83e", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.11.0", "4951ee019df102492dabba66a09e305f61919a8a183a7860236c0fde586134b6", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, diff --git a/test/catalog_api/address_test.exs b/test/catalog_api/address_test.exs index 04b998a..00acd34 100644 --- a/test/catalog_api/address_test.exs +++ b/test/catalog_api/address_test.exs @@ -57,7 +57,8 @@ defmodule CatalogApi.AddressTest do test "returns :ok for valid address params when params have mixed keys" do params = - Map.put(@valid_address_params, :city, "Cleveland") + @valid_address_params + |> Map.put(:city, "Cleveland") |> Map.delete("city") assert :ok = Address.validate_params(params) diff --git a/test/support/fixture_helper.ex b/test/support/fixture_helper.ex index 7d98203..8db1093 100644 --- a/test/support/fixture_helper.ex +++ b/test/support/fixture_helper.ex @@ -1,4 +1,6 @@ defmodule CatalogApi.FixtureHelper do + @moduledoc false + @response_headers [ {"Access-Control-Allow-Methods", "GET"}, {"Access-Control-Allow-Origin", "*"}, @@ -19,7 +21,7 @@ defmodule CatalogApi.FixtureHelper do end def retrieve_json_fixture(fixture_name) do - retrieve_fixture("#{fixture_name}.json") |> Poison.decode!() + "#{fixture_name}.json" |> retrieve_fixture |> Poison.decode!() end def retrieve_json_response(fixture_name, status_code \\ 200) do diff --git a/test/support/format_helper.ex b/test/support/format_helper.ex index d15dde1..edbde97 100644 --- a/test/support/format_helper.ex +++ b/test/support/format_helper.ex @@ -1,4 +1,6 @@ defmodule CatalogApi.FormatHelper do + @moduledoc false + def is_iso8601_datetime_string(datetime) when is_binary(datetime) do case datetime do <<_year::bytes-size(4)>> <>