Initial yt-dlp implementation (#3)
* Added basic runner for yt-dlp commands * Updated formatting rules * Added JSON runner; Added test script for CLI interactions * Reworked yt-dlp runner; added proper test mocks
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
defmodule Pinchflat.DownloaderBackends.YtDlp.CommandRunnerTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pinchflat.DownloaderBackends.YtDlp.CommandRunner, as: Runner
|
||||
|
||||
@original_executable Application.compile_env(:pinchflat, :yt_dlp_executable)
|
||||
@video_url "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||
|
||||
setup do
|
||||
on_exit(&reset_executable/0)
|
||||
end
|
||||
|
||||
describe "run/2" do
|
||||
test "it returns the output and status when the command succeeds" do
|
||||
assert {:ok, _output} = Runner.run(@video_url, [])
|
||||
end
|
||||
|
||||
test "it converts symbol k-v arg keys to kebab case" do
|
||||
assert {:ok, output} = Runner.run(@video_url, buffer_size: 1024)
|
||||
|
||||
assert String.contains?(output, "--buffer-size 1024")
|
||||
end
|
||||
|
||||
test "it keeps string k-v arg keys untouched" do
|
||||
assert {:ok, output} = Runner.run(@video_url, [{"--under_score", 1024}])
|
||||
|
||||
assert String.contains?(output, "--under_score 1024")
|
||||
end
|
||||
|
||||
test "it converts symbol arg keys to kebab case" do
|
||||
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors])
|
||||
|
||||
assert String.contains?(output, "--ignore-errors")
|
||||
end
|
||||
|
||||
test "it keeps string arg keys untouched" do
|
||||
assert {:ok, output} = Runner.run(@video_url, ["-v"])
|
||||
|
||||
assert String.contains?(output, "-v")
|
||||
refute String.contains?(output, "--v")
|
||||
end
|
||||
|
||||
test "it places arg keys (flags) at the beginning of the command" do
|
||||
assert {:ok, output} =
|
||||
Runner.run(@video_url, [{"--under_score", 1024}, :ignore_errors])
|
||||
|
||||
assert String.contains?(output, "--ignore-errors --under_score 1024")
|
||||
end
|
||||
|
||||
test "it includes the video url as the last argument" do
|
||||
assert {:ok, output} = Runner.run(@video_url, [:ignore_errors])
|
||||
|
||||
assert String.contains?(output, "--ignore-errors #{@video_url}\n")
|
||||
end
|
||||
|
||||
test "it returns the output and status when the command fails" do
|
||||
wrap_executable("/bin/false", fn ->
|
||||
assert {:error, "", 1} = Runner.run(@video_url, [])
|
||||
end)
|
||||
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
|
||||
@@ -0,0 +1,44 @@
|
||||
defmodule Pinchflat.DownloaderBackends.YtDlp.VideoCollectionTest do
|
||||
use ExUnit.Case, async: true
|
||||
import Mox
|
||||
|
||||
alias Pinchflat.DownloaderBackends.YtDlp.VideoCollection, as: VideoCollection
|
||||
|
||||
@channel_url "https://www.youtube.com/@TheUselessTrials"
|
||||
|
||||
setup :verify_on_exit!
|
||||
|
||||
describe "get_video_ids/2" do
|
||||
test "returns a list of video ids with no blank elements" do
|
||||
expect(CommandRunnerMock, :run, fn _url, _opts -> {:ok, "id1\nid2\n\nid3\n"} end)
|
||||
|
||||
assert {:ok, ["id1", "id2", "id3"]} = VideoCollection.get_video_ids(@channel_url)
|
||||
end
|
||||
|
||||
test "it passes the expected default args" do
|
||||
expect(CommandRunnerMock, :run, fn _url, opts ->
|
||||
assert opts == [:simulate, :skip_download, :get_id]
|
||||
|
||||
{:ok, ""}
|
||||
end)
|
||||
|
||||
assert {:ok, _} = VideoCollection.get_video_ids(@channel_url)
|
||||
end
|
||||
|
||||
test "it passes the expected custom args" do
|
||||
expect(CommandRunnerMock, :run, fn _url, opts ->
|
||||
assert opts == [:custom_arg, :simulate, :skip_download, :get_id]
|
||||
|
||||
{:ok, ""}
|
||||
end)
|
||||
|
||||
assert {:ok, _} = VideoCollection.get_video_ids(@channel_url, [:custom_arg])
|
||||
end
|
||||
|
||||
test "returns the error straight through when the command fails" do
|
||||
expect(CommandRunnerMock, :run, fn _url, _opts -> {:error, "Big issue", 1} end)
|
||||
|
||||
assert {:error, "Big issue", 1} = VideoCollection.get_video_ids(@channel_url)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
defmodule Pinchflat.Utils.StringUtilsTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pinchflat.Utils.StringUtils, as: StringUtils
|
||||
|
||||
describe "to_kebab_case/1" do
|
||||
test "converts a space-delimited string to kebab-case" do
|
||||
assert StringUtils.to_kebab_case("hello world") == "hello-world"
|
||||
end
|
||||
|
||||
test "converts an underscore-delimited string to kebab-case" do
|
||||
assert StringUtils.to_kebab_case("hello_world") == "hello-world"
|
||||
end
|
||||
end
|
||||
end
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$@" == *"--dump-json"* ]]; then
|
||||
echo '{ "args": "'$@'"}'
|
||||
else
|
||||
echo $@
|
||||
fi
|
||||
@@ -1,2 +1,5 @@
|
||||
Mox.defmock(CommandRunnerMock, for: Pinchflat.DownloaderBackends.BackendCommandRunner)
|
||||
Application.put_env(:pinchflat, :yt_dlp_runner, CommandRunnerMock)
|
||||
|
||||
ExUnit.start()
|
||||
Ecto.Adapters.SQL.Sandbox.mode(Pinchflat.Repo, :manual)
|
||||
|
||||
Reference in New Issue
Block a user