Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
blob: 170a77cc3d9f80b4a4a2b6c07bf615aa9190ccf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
defmodule PandocTest do
  use ExUnit.Case, async: true

  alias Pandoc.Watcher
  import ExUnit.CaptureIO

  @version Pandoc.latest_version()

  test "run on default" do
    assert capture_io(fn ->
             assert Pandoc.run(:default, ["--version"]) == 0
           end) =~ @version
  end

  test "run on profile" do
    assert capture_io(fn ->
             assert Pandoc.run(:another, []) == 0
           end) =~ @version
  end

  test "updates on install" do
    Application.put_env(:pandoc, :version, "3.6")

    Mix.Task.rerun("pandoc.install", ["--if-missing"])

    assert capture_io(fn ->
             assert Pandoc.run(:default, ["--version"]) == 0
           end) =~ "3.6"

    Application.delete_env(:pandoc, :version)

    Mix.Task.rerun("pandoc.install", ["--if-missing"])

    assert capture_io(fn ->
             assert Pandoc.run(:default, ["--version"]) == 0
           end) =~ @version
  after
    Application.delete_env(:pandoc, :version)
  end

  test "install and run multiple concurrently" do
    bin_path = Pandoc.bin_path()

    assert :ok = File.exists?(bin_path) && File.rm!(bin_path)

    results =
      [:extra1, :extra2, :extra3]
      |> Enum.map(fn profile ->
        Application.put_env(:pandoc, profile, args: ["--version"])

        Task.async(fn ->
          capture_io(fn ->
            ret_code = Pandoc.install_and_run(profile, [])
            # Let the first finished task set the binary file to read and execute only,
            # so that the others will fail if they try to overwrite it.
            File.chmod!(bin_path, 0o500)
            ret_code == 0
          end)
        end)
      end)
      |> Task.await_many(:infinity)

    File.chmod!(bin_path, 0o700)
    assert Enum.all?(results)
  end

  test "installs with custom URL" do
    assert :ok =
             Mix.Task.rerun("pandoc.install", [
               "https://github.com/jgm/pandoc/releases/download/$version/pandoc-$version-$target.tar.gz"
             ])
  end

  test "starts watching and writes to stdio" do
    in_tmp("documents", fn ->
      task = Task.async(fn -> Pandoc.watch(:default) end)
      %{pid: pid, ref: ref} = task
      :timer.sleep(200)

      {_, watcher_pid, _, _} =
        Pandoc.Supervisor
        |> Supervisor.which_children()
        |> Enum.find(fn
          {Watcher, _, _, _} -> true
          _ -> false
        end)

      assert capture_io(fn ->
               # Redirect watcher output to current process so it can be captured
               Process.group_leader(watcher_pid, Process.group_leader())
               File.write!("hello.md", "# hello")
               Task.yield(task, 200)
             end) =~ ~s{<h1 id="hello">hello</h1>\n}

      assert :ok = Supervisor.terminate_child(Pandoc.Supervisor, Watcher)
      assert_receive {:DOWN, ^ref, :process, ^pid, :normal}, 1000
    end)
  after
    File.rm_rf!(tmp_path())
  end

  defp in_tmp(which, function) do
    path = tmp_path(which)
    File.rm_rf!(path)
    File.mkdir_p!(path)
    File.cd!(path, function)
  end

  defp tmp_path, do: Path.expand("../tmp", __DIR__)
  defp tmp_path(extension), do: Path.join(tmp_path(), extension)
end