Skip to content

Commit

Permalink
test installer (#36)
Browse files Browse the repository at this point in the history
* test vox.new task

- add flag support for installer version
- print mix help info when `mix vox.new` is ran without args
- add test for vox.new task

* test cleanup

* run installer tests in ci

* loosen installer's elixir version

* line wrap pipe

* fix deps for CI
  • Loading branch information
Parker-Bartlett authored Sep 17, 2023
1 parent 0871358 commit 7781765
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/elixir.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ jobs:
run: mix deps.get
- name: Run tests
run: mix test
- name: Run installer tests
run: |
cd installer
mix deps.get
mix test
37 changes: 24 additions & 13 deletions installer/lib/mix/tasks/vox.new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ defmodule Mix.Tasks.Vox.New do
## Command line options
* `--esbuild` - include a simple esbuild system for asset compliation
* `-v`, `--version` - prints the Vox installer version
"""

@template_string_to_replace "APP"
@version Mix.Project.config()[:version]

use Mix.Task
use VoxNew.Templater
Expand All @@ -32,20 +35,28 @@ defmodule Mix.Tasks.Vox.New do
template("test/#{@template_string_to_replace}_test.exs")

@impl Mix.Task
def run([version]) when version in ~w(-v --version) do
Mix.shell().info("Vox installer v#{@version}")
end

def run(argv) do
{flags, [path | _rest]} = OptionParser.parse!(argv, strict: [esbuild: :boolean])

# [TODO] I think these could result in incorrect formatting
module_name = Macro.camelize(path)
app_name = Macro.underscore(path)
esbuild = Keyword.get(flags, :esbuild, false)

generate(%Project{
app_name: app_name,
base_path: path,
esbuild: esbuild,
module_name: module_name
})
case OptionParser.parse!(argv, strict: [esbuild: :boolean]) do
{_, []} ->
Mix.Tasks.Help.run(["vox.new"])

{flags, [path | _rest]} ->
# [TODO] I think these could result in incorrect formatting
module_name = Macro.camelize(path)
app_name = Macro.underscore(path)
esbuild = Keyword.get(flags, :esbuild, false)

generate(%Project{
app_name: app_name,
base_path: path,
esbuild: esbuild,
module_name: module_name
})
end
end

defp generate(project) do
Expand Down
4 changes: 2 additions & 2 deletions installer/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule VoxNew.MixProject do
[
app: :vox_new,
version: @version,
elixir: "~> 1.15",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
source_url: @source_url,
package: package(),
Expand Down Expand Up @@ -43,7 +43,7 @@ defmodule VoxNew.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:ex_doc, "~> 0.30.6"}
{:ex_doc, "~> 0.30.6", only: :dev, runtime: false}
]
end

Expand Down
53 changes: 53 additions & 0 deletions installer/test/mix_helper.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Mix.shell(Mix.Shell.Process)

defmodule MixHelper do
import ExUnit.Assertions

def tmp_path do
Path.expand("../../tmp", __DIR__)
end

defp random_string(len) do
len
|> :crypto.strong_rand_bytes()
|> Base.encode64()
|> binary_part(0, len)
end

def in_tmp(which, function) do
path = Path.join([tmp_path(), random_string(10), to_string(which)])

try do
File.rm_rf!(path)
File.mkdir_p!(path)
File.cd!(path, function)
after
File.rm_rf!(path)
end
end

def assert_file(file) do
assert File.regular?(file), "Expected #{file} to exist, but does not"
end

def assert_file(file, match) do
cond do
is_list(match) ->
assert_file(file, &Enum.each(match, fn m -> assert &1 =~ m end))

is_binary(match) or is_struct(match, Regex) ->
assert_file(file, &assert(&1 =~ match))

is_function(match, 1) ->
assert_file(file)
match.(File.read!(file))

true ->
raise inspect({file, match})
end
end

def refute_file(file) do
refute File.regular?(file), "Expected #{file} to not exist, but it does"
end
end
78 changes: 75 additions & 3 deletions installer/test/vox_new_test.exs
Original file line number Diff line number Diff line change
@@ -1,8 +1,80 @@
Code.require_file("mix_helper.exs", __DIR__)

defmodule VoxNewTest do
use ExUnit.Case
doctest VoxNew
import MixHelper
import ExUnit.CaptureIO

@app_name "blog"

test "returns the version" do
Mix.Tasks.Vox.New.run(["-v"])
assert_received {:mix_shell, :info, ["Vox installer v" <> _]}
end

test "new with defaults" do
in_tmp("new with defaults", fn ->
Mix.Tasks.Vox.New.run([@app_name])

assert_file("#{@app_name}/mix.exs", fn file ->
assert file =~ "defmodule Blog.MixProject"
assert file =~ "app: :blog"
refute file =~ "mod: {Blog.Application, []}"
refute file =~ ":esbuild"
end)

assert_file("#{@app_name}/config/config.exs", fn file ->
assert file =~ "src_dir = \"site\""
assert file =~ "output_dir = \"_html\""
refute file =~ "config :esbuild"
end)

refute_file("#{@app_name}/assets/app.js")
refute_file("#{@app_name}/lib/application.ex")
refute_file("#{@app_name}/lib/#{@app_name}/esbuild.ex")
end)
end

test "new with --esbuild" do
in_tmp("new with --esbuild", fn ->
Mix.Tasks.Vox.New.run([@app_name, "--esbuild"])

shared_file_assertions()

assert_file("#{@app_name}/mix.exs", fn file ->
assert file =~ "defmodule Blog.MixProject"
assert file =~ "app: :blog"
assert file =~ "mod: {Blog.Application, []}"
assert file =~ ":esbuild"
end)

assert_file("#{@app_name}/config/config.exs", fn file ->
assert file =~ "src_dir = \"site\""
assert file =~ "output_dir = \"_html\""
assert file =~ "config :esbuild"
end)

assert_file("#{@app_name}/assets/app.js")
assert_file("#{@app_name}/lib/application.ex")
assert_file("#{@app_name}/lib/#{@app_name}/esbuild.ex")
end)
end

test "new without args" do
in_tmp("new without args", fn ->
assert capture_io(fn -> Mix.Tasks.Vox.New.run([]) end) =~
"Generate a new Vox application."
end)
end

test "greets the world" do
assert VoxNew.hello() == :world
def shared_file_assertions() do
assert_file("#{@app_name}/README.md")
assert_file("#{@app_name}/lib/#{@app_name}.ex")
assert_file("#{@app_name}/site/_root.html.eex")
assert_file("#{@app_name}/site/_template.html.eex")
assert_file("#{@app_name}/site/index.html.eex")
assert_file("#{@app_name}/site/posts/hello-world.html.eex")
assert_file("#{@app_name}/test/test_helper.exs")
assert_file("#{@app_name}/test/#{@app_name}_test.exs")
end
end

0 comments on commit 7781765

Please sign in to comment.