Skip to content

Commit

Permalink
Add and update tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
ckoch-cars committed Jul 20, 2022
1 parent e382b11 commit 8c58d8c
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 6 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ Use at your peril, _for now._
- [X] dry-run option
- [X] CLI output, list files changed and created.
- [X] format changes
- [X] guthub actions, run test suite
- [X] github actions, run test suite
- [X] Add Mix.Task tests
- [X] Add CLI tests

## Roadmap TODO

- [] Add and configure CHANGELOG tracking.
- [] How does this work with macro code? Does that even make sense as a case to handle?
- [] Update .exs files too?
- [] Write tests to ensure we can find modules across umbrella apps.
Expand All @@ -44,7 +47,7 @@ by adding `ex_factor` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:ex_factor, "~> 0.2.1", only: [:dev]}
{:ex_factor, "~> 0.3", only: [:dev]}
]
end
```
Expand Down
2 changes: 1 addition & 1 deletion lib/ex_factor/changer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule ExFactor.Changer do

defp update_caller_groups([], opts) do
source_module = Keyword.fetch!(opts, :source_module)
[%ExFactor{state: [:unchanged], message: "module: #{source_module} not found"}]
[%ExFactor{state: [:unchanged], message: "No additional references to source module: (#{source_module}) detected"}]
end

defp update_caller_groups(callers, opts) do
Expand Down
1 change: 0 additions & 1 deletion lib/mix/tasks/ex_factor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ defmodule Mix.Tasks.ExFactor do

defp cli_output(map, opts) do
verbose = Keyword.get(opts, :verbose, false)
# dry_run = Keyword.get(opts, :dryrun, false)

format_entry(Map.get(map, :additions), "Additions", :light_cyan_background, verbose)
format_entry(Map.get(map, :changes), "Changes", :light_green_background, verbose)
Expand Down
1 change: 0 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ defmodule ExFactor.MixProject do
]
end

# Run "mix help deps" to learn about dependencies.
defp package() do
[
licenses: ["CC-BY-NC-ND-4.0"],
Expand Down
2 changes: 1 addition & 1 deletion test/ex_factor/changer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ defmodule ExFactor.ChangerTest do
]

[change] = Changer.change(opts)
assert change.message == "module: ExFactor.Tmp.SourceModMissing not found"
assert change.message == "No additional references to source module: (ExFactor.Tmp.SourceModMissing) detected"
assert change.state == [:unchanged]
end

Expand Down
63 changes: 63 additions & 0 deletions test/ex_factor/cli_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
defmodule ExFactor.CLITest do
use ExUnit.Case
import ExUnit.CaptureIO

setup_all do
File.mkdir_p("test/tmp")

on_exit(fn ->
File.rm_rf("test/tmp")
end)
end

test "missing required options exit != 0" do
opts = [
module: "ExFactorSampleModule",
function: "pub1",
arity: 1
]
argv = OptionParser.to_argv(opts)

capture_io fn ->
{_, exit_status} = System.cmd("mix", ["ex_factor" | argv])
refute exit_status == 0
end
end

test "with dry run" do
content = """
defmodule ExFactorSampleModule do
@somedoc "This is somedoc"
# a comment and no aliases
_docp = "here's an arbitrary module underscore"
@spec pub1(term()) :: term()
def pub1(arg1) do
:pub1_ok
end
end
"""

File.write("test/tmp/source_module.ex", content)
target_path = "test/tmp/target_module.ex"

opts = [
target_path: target_path,
target: "ExFactor.NewMod",
module: "ExFactorSampleModule",
source_path: "test/tmp/source_module.ex",
function: :pub1,
arity: 1,
dryrun: true
]

argv = OptionParser.to_argv(opts)

{cli_output, exit_status} = System.cmd("mix", ["ex_factor" | argv])
assert exit_status == 0

assert cli_output =~ "Message: --dry_run changes to make"

# no new file gets written
assert {:error, :enoent} = File.read(target_path)
end
end
189 changes: 189 additions & 0 deletions test/ex_factor/mix_task_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
defmodule ExFactor.MixTaskTest do
use ExUnit.Case
import ExUnit.CaptureIO

setup do
File.mkdir_p("test/tmp")

on_exit(fn ->
File.rm_rf("test/tmp")
end)
end

describe "mix task" do
test "requires some options" do
opts = [
module: "ExFactorSampleModule",
function: "pub1",
arity: 1
]
argv = OptionParser.to_argv(opts)

assert_raise KeyError, "key :target not found in: #{inspect(opts)}", fn ->
Mix.Tasks.ExFactor.run(argv)
end
end

test "write a new file with the function" do
content = """
defmodule ExFactorSampleModule do
@somedoc "This is somedoc"
# a comment and no aliases
_docp = "here's an arbitrary module underscore"
@spec pub1(term()) :: term()
def pub1(arg1) do
:pub1_ok
end
end
"""

File.write("test/tmp/source_module.ex", content)
target_path = "test/tmp/target_module.ex"

opts = [
target_path: target_path,
target: "ExFactor.NewMod",
module: "ExFactorSampleModule",
source_path: "test/tmp/source_module.ex",
function: :pub1,
arity: 1
]

argv = OptionParser.to_argv(opts)

capture_io fn -> Mix.Tasks.ExFactor.run(argv) end

file = File.read!(target_path)

assert file =~ "def pub1(arg1) do"
assert file =~ "defmodule ExFactor.NewMod do"
# includes additional attrs
assert file =~ "@spec pub1(term()) :: term()"
assert file =~ "@somedoc \"This is somedoc\""
# assert the added elements get flattened correctly
refute file =~ "[@somedoc \"This is somedoc\", "
# comments don't get moved
refute file =~ "# a comment and no aliases"
end

test "write a new file add a moduledoc comment" do
content = """
defmodule ExFactorSampleModule do
def pub1(arg1) do
:pub1_ok
end
end
"""

File.write("test/tmp/source_module.ex", content)
target_path = "test/tmp/target_module.ex"

opts = [
target_path: target_path,
target: "ExFactor.NewMod",
module: "ExFactorSampleModule",
source_path: "test/tmp/source_module.ex",
function: :pub1,
arity: 1
]

argv = OptionParser.to_argv(opts)
capture_io fn -> Mix.Tasks.ExFactor.run(argv) end

file = File.read!(target_path)
assert file =~ "def pub1(arg1)"
assert file =~ "@moduledoc \"This module created with ExFactor\""
end

test " with dry_run option, don't write the file." do
content = """
defmodule ExFactorSampleModule do
@somedoc "This is somedoc"
# a comment and no aliases
_docp = "here's an arbitrary module underscore"
@spec pub1(term()) :: term()
def pub1(arg1) do
:ok
end
end
"""

File.write("test/tmp/source_module.ex", content)
target_path = "test/tmp/target_module.ex"

opts = [
target_path: target_path,
target: "ExFactor.NewMod",
module: "ExFactorSampleModule",
source_path: "test/tmp/source_module.ex",
function: :pub1,
arity: 1,
dryrun: true
]

argv = OptionParser.to_argv(opts)

output = capture_io fn -> Mix.Tasks.ExFactor.run(argv) end

# no new file gets written
assert {:error, :enoent} = File.read(target_path)
# assert output.file_contents
assert output =~ "--dry_run changes to make"
assert output =~ "ExFactor.NewMod"
end

test "write multiple functions and their docs, into an existing module" do
content = """
defmodule ExFactor.Tmp.SourceModule do
@somedoc "This is somedoc"
@doc "this is some documentation for refactor1/1"
def refactor1(arg1) do
:ok
end
def refactor1([]) do
:empty
end
end
"""

File.write("test/tmp/source_module.ex", content)

content = """
defmodule ExFactor.Tmp.TargetModule do
@moduledoc false
@somedoc "This is somedoc TargetModule"
@doc "some docs"
def pub_exists(arg_exists) do
:ok
end
def pub_exists(:error) do
:error
end
end
"""

target_path = "test/tmp/target_module.ex"
File.write(target_path, content)

opts = [
target: "ExFactor.Tmp.TargetModule",
module: "ExFactor.Tmp.SourceModule",
target_path: target_path,
source_path: "test/tmp/source_module.ex",
function: :refactor1,
arity: 1
]

argv = OptionParser.to_argv(opts)

capture_io fn -> Mix.Tasks.ExFactor.run(argv) end

file = File.read!(target_path)
assert file =~ "def refactor1(arg1) do"
assert file =~ "def refactor1([]) do"
assert file =~ " @doc \"some docs\""
end

end
end

0 comments on commit 8c58d8c

Please sign in to comment.