pinchflat/test/pinchflat/yt_dlp/command_runner_test.exs
Kieran 6ead29182d
[Enhancement] Auto-update yt-dlp (#589)
* Added a command for updating yt-dlp

* Added a yt-dlp update worker to run daily

* Added a new file that runs post-boot when the app is ready to serve requests; put yt-dlp updater in there

* Updated config to expose the current env globally; updated startup tasks to not run in test env

* Removes unneeded test code
2025-01-27 11:33:38 -08:00

174 lines
5.7 KiB
Elixir

defmodule Pinchflat.YtDlp.CommandRunnerTest do
use Pinchflat.DataCase
alias Pinchflat.Settings
alias Pinchflat.Utils.FilesystemUtils
alias Pinchflat.YtDlp.CommandRunner, as: Runner
@original_executable Application.compile_env(:pinchflat, :yt_dlp_executable)
@media_url "https://www.youtube.com/watch?v=-LHXuyzpex0"
setup do
on_exit(&reset_executable/0)
end
describe "run/4" do
test "returns the output and status when the command succeeds" do
assert {:ok, _output} = Runner.run(@media_url, :foo, [], "")
end
test "considers a 101 exit code as being successful" do
wrap_executable("/app/test/support/scripts/yt-dlp-mocks/101_exit_code.sh", fn ->
assert {:ok, _output} = Runner.run(@media_url, :foo, [], "")
end)
end
test "includes the media url as the first argument" do
assert {:ok, output} = Runner.run(@media_url, :foo, [:ignore_errors], "")
assert String.contains?(output, "#{@media_url} --ignore-errors")
end
test "automatically includes the --print-to-file flag" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "%(id)s")
assert String.contains?(output, "--print-to-file %(id)s /tmp/")
end
test "returns the output and status when the command fails" do
wrap_executable("/bin/false", fn ->
assert {:error, "", 1} = Runner.run(@media_url, :foo, [], "")
end)
end
test "optionally lets you specify an output_filepath" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "%(id)s", output_filepath: "/tmp/yt-dlp-output.json")
assert String.contains?(output, "--print-to-file %(id)s /tmp/yt-dlp-output.json")
end
end
describe "run/4 when testing external file options" do
setup do
base_dir = Application.get_env(:pinchflat, :extras_directory)
cookie_file = Path.join(base_dir, "cookies.txt")
yt_dlp_file = Path.join([base_dir, "yt-dlp-configs", "main.txt"])
{:ok, cookie_file: cookie_file, yt_dlp_file: yt_dlp_file}
end
test "includes cookie options when cookies.txt exists and enabled", %{cookie_file: cookie_file} do
FilesystemUtils.write_p!(cookie_file, "cookie data")
assert {:ok, output} = Runner.run(@media_url, :foo, [], "", use_cookies: true)
assert String.contains?(output, "--cookies #{cookie_file}")
end
test "doesn't include cookie options when cookies.txt exists but disabled", %{cookie_file: cookie_file} do
FilesystemUtils.write_p!(cookie_file, "cookie data")
assert {:ok, output} = Runner.run(@media_url, :foo, [], "", use_cookies: false)
refute String.contains?(output, "--cookies #{cookie_file}")
end
test "doesn't include cookie options when cookies.txt blank", %{cookie_file: cookie_file} do
FilesystemUtils.write_p!(cookie_file, " \n \n ")
assert {:ok, output} = Runner.run(@media_url, :foo, [], "", use_cookies: true)
refute String.contains?(output, "--cookies")
refute String.contains?(output, cookie_file)
end
test "doesn't include cookie options when cookies.txt doesn't exist", %{cookie_file: cookie_file} do
File.rm(cookie_file)
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
refute String.contains?(output, "--cookies")
refute String.contains?(output, cookie_file)
# Cleanup
FilesystemUtils.write_p!(cookie_file, "")
end
end
describe "run/4 when testing sleep interval options" do
test "includes sleep interval options by default" do
Settings.set(extractor_sleep_interval_seconds: 5)
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
assert String.contains?(output, "--sleep-interval")
assert String.contains?(output, "--sleep-requests")
assert String.contains?(output, "--sleep-subtitles")
end
test "doesn't include sleep interval options when skip_sleep_interval is true" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "", skip_sleep_interval: true)
refute String.contains?(output, "--sleep-interval")
refute String.contains?(output, "--sleep-requests")
refute String.contains?(output, "--sleep-subtitles")
end
test "doesn't include sleep interval options when extractor_sleep_interval_seconds is 0" do
Settings.set(extractor_sleep_interval_seconds: 0)
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
refute String.contains?(output, "--sleep-interval")
refute String.contains?(output, "--sleep-requests")
refute String.contains?(output, "--sleep-subtitles")
end
end
describe "run/4 when testing global options" do
test "creates windows-safe filenames" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
assert String.contains?(output, "--windows-filenames")
end
test "runs quietly" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
assert String.contains?(output, "--quiet")
end
test "sets the cache directory" do
assert {:ok, output} = Runner.run(@media_url, :foo, [], "")
assert String.contains?(output, "--cache-dir /tmp/test/tmpfiles/yt-dlp-cache")
end
end
describe "version/0" do
test "adds the version arg" do
assert {:ok, output} = Runner.version()
assert String.contains?(output, "--version")
end
end
describe "update/0" do
test "adds the update arg" do
assert {:ok, output} = Runner.update()
assert String.contains?(output, "--update")
end
end
defp wrap_executable(new_executable, fun) do
Application.put_env(:pinchflat, :yt_dlp_executable, new_executable)
fun.()
reset_executable()
end
def reset_executable do
Application.put_env(:pinchflat, :yt_dlp_executable, @original_executable)
end
end