[WIP] got all tests passing

This commit is contained in:
Kieran Eglin 2024-03-12 09:52:03 -07:00
parent 6c19f096fb
commit a202652c00
No known key found for this signature in database
GPG key ID: 193984967FCF432D
43 changed files with 219 additions and 321 deletions

View file

@ -4,7 +4,6 @@ alias Pinchflat.Repo
alias Pinchflat.Tasks.Task
alias Pinchflat.Sources.Source
alias Pinchflat.Media.MediaItem
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.Metadata.MediaMetadata
alias Pinchflat.Profiles.MediaProfile
@ -14,14 +13,14 @@ alias Pinchflat.Profiles
alias Pinchflat.Sources
alias Pinchflat.Settings
alias Pinchflat.MediaClient.MediaDownloader
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
alias Pinchflat.YtDlp.Backend.MediaCollection, as: YtDlpCollection
alias Pinchflat.Downloading.MediaDownloader
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
alias Pinchflat.YtDlp.MediaCollection, as: YtDlpCollection
alias Pinchflat.FastIndexing.YoutubeRss
alias Pinchflat.Metadata.MetadataFileHelpers
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
alias Pinchflat.SlowIndexing.FileFollowerServer
defmodule IexHelpers do
def playlist_url do

View file

@ -12,7 +12,7 @@ config :pinchflat,
generators: [timestamp_type: :utc_datetime],
# Specifying backend data here makes mocking and local testing SUPER easy
yt_dlp_executable: System.find_executable("yt-dlp"),
yt_dlp_runner: Pinchflat.YtDlp.Backend.CommandRunner,
yt_dlp_runner: Pinchflat.YtDlp.CommandRunner,
media_directory: "/downloads",
# The user may or may not store metadata for their needs, but the app will always store its copy
metadata_directory: "/config/metadata",

View file

@ -4,7 +4,7 @@ defmodule Pinchflat.Downloading.DownloadOptionBuilder do
"""
alias Pinchflat.Media.MediaItem
alias Pinchflat.Profiles.OutputPathBuilder
alias Pinchflat.Downloading.OutputPathBuilder
@doc """
Builds the options for yt-dlp to download media based on the given media's profile.

View file

@ -3,18 +3,8 @@ defmodule Pinchflat.Downloading.DownloadingHelpers do
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.Sources
alias Pinchflat.Sources.Source
alias Pinchflat.FastIndexing.YoutubeRss
alias Pinchflat.Media.MediaItem
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.YtDlp.Backend.MediaCollection
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
@doc """
Starts tasks for downloading media for any of a sources _pending_ media items.

View file

@ -9,8 +9,8 @@ defmodule Pinchflat.Downloading.MediaDownloadWorker do
alias Pinchflat.Repo
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.MediaClient.MediaDownloader
alias Pinchflat.Workers.FilesystemDataWorker
alias Pinchflat.Downloading.MediaDownloader
alias Pinchflat.Filesystem.FilesystemDataWorker
@impl Oban.Worker
@doc """

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.MediaClient.MediaDownloader do
defmodule Pinchflat.Downloading.MediaDownloader do
@moduledoc """
This is the integration layer for actually downloading media.
It takes into account the media profile's settings in order
@ -9,7 +9,7 @@ defmodule Pinchflat.MediaClient.MediaDownloader do
alias Pinchflat.Media
alias Pinchflat.Media.MediaItem
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
alias Pinchflat.Downloading.DownloadOptionBuilder, as: YtDlpDownloadOptionBuilder
alias Pinchflat.Metadata.MetadataParser, as: YtDlpMetadataParser
alias Pinchflat.Metadata.MetadataFileHelpers, as: YtDlpMetadataHelpers

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.RenderedString.Base do
defmodule Pinchflat.Downloading.OutputPath.Base do
@moduledoc """
A base module for parsing rendered strings, designed as a macro to be used
in other modules. See https://elixirforum.com/t/help-to-parse-a-template-with-nimbleparsec/47980
@ -6,7 +6,7 @@ defmodule Pinchflat.RenderedString.Base do
NOTE: if the needs here get any more complicated, look into using a Liquid
template parser. No need to reinvent the wheel any more than I already have.
NOTE: this is effectively tested by the `Pinchflat.RenderedString.Parser`'s tests
NOTE: this is effectively tested by the `Pinchflat.Downloading.OutputPath.Parser`'s tests
"""
defmacro __using__(_opts) do

View file

@ -1,11 +1,11 @@
defmodule Pinchflat.RenderedString.Parser do
defmodule Pinchflat.Downloading.OutputPath.Parser do
@moduledoc """
Parses liquid-ish-style strings into a rendered string
Used for turning filepath templates into real filepaths
"""
use Pinchflat.RenderedString.Base
use Pinchflat.Downloading.OutputPath.Base
@doc """
Parses a string into a rendered string, using the provided variables. Optionally

View file

@ -1,9 +1,9 @@
defmodule Pinchflat.Profiles.OutputPathBuilder do
defmodule Pinchflat.Downloading.OutputPathBuilder do
@moduledoc """
Builds yt-dlp-friendly output paths for downloaded media
"""
alias Pinchflat.RenderedString.Parser, as: TemplateParser
alias Pinchflat.Downloading.OutputPath.Parser, as: TemplateParser
@doc """
Builds the actual final filepath from a given template. Optionally, you can pass in

View file

@ -1,16 +1,13 @@
defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.Sources
alias Pinchflat.Sources.Source
alias Pinchflat.FastIndexing.YoutubeRss
alias Pinchflat.Media.MediaItem
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.YtDlp.Backend.MediaCollection
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
@doc """
Starts tasks for running a fast indexing task for a source's media
@ -56,4 +53,36 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpers do
|> Tasks.create_job_with_task(source)
end)
end
@doc """
Indexes a single media item for a source and enqueues a download job if the
media should be downloaded. This method creates the media item record so it's
the one-stop-shop for adding a media item (and possibly downloading it) just
by a URL and source.
Returns {:ok, media_item} | {:error, any()}
"""
def index_and_enqueue_download_for_media_item(%Source{} = source, url) do
maybe_media_item = create_media_item_from_url(source, url)
case maybe_media_item do
{:ok, media_item} ->
if source.download_media && Media.pending_download?(media_item) do
%{id: media_item.id}
|> MediaDownloadWorker.new()
|> Tasks.create_job_with_task(media_item)
end
{:ok, media_item}
err ->
err
end
end
defp create_media_item_from_url(source, url) do
{:ok, media_attrs} = YtDlpMedia.get_media_attributes(url)
Media.create_media_item_from_backend_attrs(source, media_attrs)
end
end

View file

@ -11,7 +11,7 @@ defmodule Pinchflat.FastIndexing.MediaIndexingWorker do
require Logger
alias Pinchflat.Sources
alias Pinchflat.Tasks.MediaItemTasks
alias Pinchflat.FastIndexing.FastIndexingHelpers
@impl Oban.Worker
@doc """
@ -42,7 +42,7 @@ defmodule Pinchflat.FastIndexing.MediaIndexingWorker do
def perform(%Oban.Job{args: %{"id" => source_id, "media_url" => media_url}}) do
source = Sources.get_source!(source_id)
case MediaItemTasks.index_and_enqueue_download_for_media_item(source, media_url) do
case FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, media_url) do
{:ok, media_item} ->
Logger.debug("Indexed and enqueued download for url: #{media_url} (media item: #{media_item.id})")

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.Workers.FilesystemDataWorker do
defmodule Pinchflat.Filesystem.FilesystemDataWorker do
@moduledoc false
use Oban.Worker,
@ -7,7 +7,7 @@ defmodule Pinchflat.Workers.FilesystemDataWorker do
max_attempts: 1
alias Pinchflat.Media
alias Pinchflat.Tasks.MediaItemTasks
alias Pinchflat.Filesystem.FilesystemHelpers
@impl Oban.Worker
@doc """
@ -18,7 +18,7 @@ defmodule Pinchflat.Workers.FilesystemDataWorker do
def perform(%Oban.Job{args: %{"id" => media_item_id}}) do
media_item = Media.get_media_item!(media_item_id)
MediaItemTasks.compute_and_save_media_filesize(media_item)
FilesystemHelpers.compute_and_save_media_filesize(media_item)
# Don't retry on failure - if it didn't work immediately there's no
# reason to believe it will work later.

View file

@ -1,8 +1,8 @@
defmodule Pinchflat.Utils.FilesystemUtils do
defmodule Pinchflat.Filesystem.FilesystemHelpers do
@moduledoc """
Utility methods for working with the filesystem
"""
alias Pinchflat.Media
alias Pinchflat.Utils.StringUtils
@doc """
@ -20,4 +20,19 @@ defmodule Pinchflat.Utils.FilesystemUtils do
filepath
end
@doc """
Fetches the file size of a media item and saves it to the database.
Returns {:ok, media_item} | {:error, any()}
"""
def compute_and_save_media_filesize(media_item) do
case File.stat(media_item.media_filepath) do
{:ok, %{size: size}} ->
Media.update_media_item(media_item, %{media_size_bytes: size})
err ->
err
end
end
end

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.Utils.FilesystemUtils.FileFollowerServer do
defmodule Pinchflat.SlowIndexing.FileFollowerServer do
@moduledoc """
A GenServer that watches a file for new lines and processes them as they come in.
This is useful for tailing log files and other similar tasks. If there's no activity

View file

@ -10,7 +10,6 @@ defmodule Pinchflat.SlowIndexing.MediaCollectionIndexingWorker do
alias Pinchflat.Tasks
alias Pinchflat.Sources
alias Pinchflat.Sources.Source
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.SlowIndexing.SlowIndexingHelpers

View file

@ -5,17 +5,14 @@ defmodule Pinchflat.SlowIndexing.SlowIndexingHelpers do
alias Pinchflat.Tasks
alias Pinchflat.Sources
alias Pinchflat.Sources.Source
alias Pinchflat.FastIndexing.YoutubeRss
alias Pinchflat.Media.MediaItem
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.YtDlp.Backend.MediaCollection
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
alias Pinchflat.YtDlp.MediaCollection
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.SlowIndexing.FileFollowerServer
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
@doc """
Starts tasks for indexing a source's media regardless of the source's indexing

View file

@ -9,9 +9,8 @@ defmodule Pinchflat.Sources do
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.Sources.Source
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.Profiles.MediaProfile
alias Pinchflat.YtDlp.Backend.MediaCollection
alias Pinchflat.YtDlp.MediaCollection
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.FastIndexing.FastIndexingHelpers
alias Pinchflat.SlowIndexing.SlowIndexingHelpers

View file

@ -1,61 +0,0 @@
defmodule Pinchflat.Tasks.MediaItemTasks do
@moduledoc """
Contains methods used by OR used to create/manage tasks for media items.
Tasks/workers are meant to be thin wrappers so most of the actual work they
do is also defined here. Essentially, a one-stop-shop for media-related tasks/workers.
"""
alias Pinchflat.Media
alias Pinchflat.Tasks
alias Pinchflat.Sources.Source
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
@doc """
Fetches the file size of a media item and saves it to the database.
Returns {:ok, media_item} | {:error, any()}
"""
def compute_and_save_media_filesize(media_item) do
case File.stat(media_item.media_filepath) do
{:ok, %{size: size}} ->
Media.update_media_item(media_item, %{media_size_bytes: size})
err ->
err
end
end
@doc """
Indexes a single media item for a source and enqueues a download job if the
media should be downloaded. This method creates the media item record so it's
the one-stop-shop for adding a media item (and possibly downloading it) just
by a URL and source.
Returns {:ok, media_item} | {:error, any()}
"""
def index_and_enqueue_download_for_media_item(%Source{} = source, url) do
maybe_media_item = create_media_item_from_url(source, url)
case maybe_media_item do
{:ok, media_item} ->
if source.download_media && Media.pending_download?(media_item) do
%{id: media_item.id}
|> MediaDownloadWorker.new()
|> Tasks.create_job_with_task(media_item)
end
{:ok, media_item}
err ->
err
end
end
defp create_media_item_from_url(source, url) do
{:ok, media_attrs} = YtDlpMedia.get_media_attributes(url)
Media.create_media_item_from_backend_attrs(source, media_attrs)
end
end

View file

@ -1,25 +0,0 @@
defmodule Pinchflat.Tasks.SourceTasks do
@moduledoc """
Contains methods used by OR used to create/manage tasks for sources.
Tasks/workers are meant to be thin wrappers so most of the actual work they
do is also defined here. Essentially, a one-stop-shop for source-related tasks/workers.
"""
require Logger
# alias Pinchflat.Media
# alias Pinchflat.Tasks
# alias Pinchflat.Sources
# alias Pinchflat.Sources.Source
# alias Pinchflat.FastIndexing.YoutubeRss
# alias Pinchflat.Media.MediaItem
# alias Pinchflat.FastIndexing.FastIndexingWorker
# alias Pinchflat.Downloading.MediaDownloadWorker
# alias Pinchflat.FastIndexing.MediaIndexingWorker
# alias Pinchflat.YtDlp.Backend.MediaCollection
# alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
# alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
# alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
end

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.YtDlp.Backend.BackendCommandRunner do
defmodule Pinchflat.YtDlp.BackendCommandRunner do
@moduledoc """
A behaviour for running CLI commands against a downloader backend (yt-dlp).

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.YtDlp.Backend.CommandRunner do
defmodule Pinchflat.YtDlp.CommandRunner do
@moduledoc """
Runs yt-dlp commands using the `System.cmd/3` function
"""
@ -6,8 +6,8 @@ defmodule Pinchflat.YtDlp.Backend.CommandRunner do
require Logger
alias Pinchflat.Utils.StringUtils
alias Pinchflat.Utils.FilesystemUtils, as: FSUtils
alias Pinchflat.YtDlp.Backend.BackendCommandRunner
alias Pinchflat.Filesystem.FilesystemHelpers, as: FSUtils
alias Pinchflat.YtDlp.BackendCommandRunner
@behaviour BackendCommandRunner

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.YtDlp.Backend.Media do
defmodule Pinchflat.YtDlp.Media do
@moduledoc """
Contains utilities for working with singular pieces of media
"""

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.YtDlp.Backend.MediaCollection do
defmodule Pinchflat.YtDlp.MediaCollection do
@moduledoc """
Contains utilities for working with collections of
media (aka: a source [ie: channels, playlists]).
@ -7,8 +7,8 @@ defmodule Pinchflat.YtDlp.Backend.MediaCollection do
require Logger
alias Pinchflat.Utils.FunctionUtils
alias Pinchflat.Utils.FilesystemUtils
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
alias Pinchflat.Filesystem.FilesystemHelpers
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
@doc """
Returns a list of maps representing the media in the collection.
@ -24,7 +24,7 @@ defmodule Pinchflat.YtDlp.Backend.MediaCollection do
runner = Application.get_env(:pinchflat, :yt_dlp_runner)
command_opts = [:simulate, :skip_download]
output_template = YtDlpMedia.indexing_output_template()
output_filepath = FilesystemUtils.generate_metadata_tmpfile(:json)
output_filepath = FilesystemHelpers.generate_metadata_tmpfile(:json)
file_listener_handler = Keyword.get(addl_opts, :file_listener_handler, false)
if file_listener_handler do

View file

@ -4,7 +4,7 @@ defmodule Pinchflat.Boot.DataBackfillWorkerTest do
import Pinchflat.MediaFixtures
alias Pinchflat.Boot.DataBackfillWorker
alias Pinchflat.Workers.FilesystemDataWorker
alias Pinchflat.Filesystem.FilesystemDataWorker
describe "cancel_pending_backfill_jobs/0" do
test "cancels all pending backfill jobs" do

View file

@ -2,20 +2,12 @@ defmodule Pinchflat.Downloading.DownloadingHelpersTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.TasksFixtures
import Pinchflat.MediaFixtures
import Pinchflat.SourcesFixtures
import Pinchflat.ProfilesFixtures
alias Pinchflat.Tasks
alias Pinchflat.Tasks.Task
alias Pinchflat.Media.MediaItem
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.SlowIndexing.SlowIndexingHelpers
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.Downloading.MediaDownloadWorker
setup :verify_on_exit!

View file

@ -6,7 +6,7 @@ defmodule Pinchflat.Downloading.MediaDownloadWorkerTest do
alias Pinchflat.Sources
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.Workers.FilesystemDataWorker
alias Pinchflat.Filesystem.FilesystemDataWorker
setup :verify_on_exit!

View file

@ -1,9 +1,9 @@
defmodule Pinchflat.MediaClient.MediaDownloaderTest do
defmodule Pinchflat.Downloading.MediaDownloaderTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.MediaFixtures
alias Pinchflat.MediaClient.MediaDownloader
alias Pinchflat.Downloading.MediaDownloader
setup :verify_on_exit!

View file

@ -1,7 +1,7 @@
defmodule Pinchflat.RenderedString.ParserTest do
defmodule Pinchflat.Downloading.OutputPath.ParserTest do
use ExUnit.Case, async: true
alias Pinchflat.RenderedString.Parser
alias Pinchflat.Downloading.OutputPath.Parser
describe "parse/3" do
test "it returns the rendered string when the string is valid" do

View file

@ -1,7 +1,7 @@
defmodule Pinchflat.Profiles.OutputPathBuilderTest do
defmodule Pinchflat.Downloading.OutputPathBuilderTest do
use Pinchflat.DataCase
alias Pinchflat.Profiles.OutputPathBuilder
alias Pinchflat.Downloading.OutputPathBuilder
describe "build/2" do
test "it expands 'standard' curly brace variables in the template" do

View file

@ -9,16 +9,16 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpersTest do
alias Pinchflat.Tasks
alias Pinchflat.Tasks.Task
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.Media.MediaItem
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.FastIndexing.FastIndexingHelpers
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
setup :verify_on_exit!
@media_url "https://www.youtube.com/watch?v=test_1"
describe "kickoff_fast_indexing_task/1" do
test "it schedules a job" do
source = source_fixture()
@ -71,4 +71,72 @@ defmodule Pinchflat.FastIndexing.FastIndexingHelpersTest do
refute_enqueued(worker: MediaIndexingWorker)
end
end
describe "index_and_enqueue_download_for_media_item/2" do
setup do
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
{:ok, media_attributes_return_fixture()}
end)
{:ok, [source: source_fixture()]}
end
test "creates a new media item based on the URL", %{source: source} do
assert Repo.aggregate(MediaItem, :count) == 0
assert {:ok, _} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
assert Repo.aggregate(MediaItem, :count) == 1
end
test "won't duplicate media_items based on media_id and source", %{source: source} do
assert {:ok, mi_1} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
assert {:ok, mi_2} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
assert Repo.aggregate(MediaItem, :count) == 1
assert mi_1.id == mi_2.id
end
test "enqueues a download job", %{source: source} do
assert {:ok, media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id})
end
test "creates a download task record", %{source: source} do
assert {:ok, media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id, "MediaDownloadWorker")
end
test "does not enqueue a download job if the source does not allow it" do
source = source_fixture(%{download_media: false})
assert {:ok, _} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
refute_enqueued(worker: MediaDownloadWorker)
end
test "does not enqueue a download job if the media item does not match the format rules" do
profile = media_profile_fixture(%{shorts_behaviour: :exclude})
source = source_fixture(%{media_profile_id: profile.id})
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
output =
Phoenix.json_library().encode!(%{
id: "video2",
title: "Video 2",
webpage_url: "https://example.com/shorts/video2",
was_live: true,
description: "desc2",
aspect_ratio: 1.67,
duration: 345.67,
upload_date: "20210101"
})
{:ok, output}
end)
assert {:ok, _media_item} = FastIndexingHelpers.index_and_enqueue_download_for_media_item(source, @media_url)
refute_enqueued(worker: MediaDownloadWorker)
end
end
end

View file

@ -1,9 +1,9 @@
defmodule Pinchflat.Workers.FilesystemDataWorkerTest do
defmodule Pinchflat.Filesystem.FilesystemDataWorkerTest do
use Pinchflat.DataCase
import Pinchflat.MediaFixtures
alias Pinchflat.Workers.FilesystemDataWorker
alias Pinchflat.Filesystem.FilesystemDataWorker
describe "perform/1" do
test "Computes and stores the media file size" do

View file

@ -0,0 +1,36 @@
defmodule Pinchflat.Filesystem.FilesystemHelpersTest do
use Pinchflat.DataCase
import Pinchflat.MediaFixtures
alias Pinchflat.Filesystem.FilesystemHelpers
describe "generate_metadata_tmpfile/1" do
test "creates a tmpfile and returns its path" do
res = FilesystemHelpers.generate_metadata_tmpfile(:json)
assert String.ends_with?(res, ".json")
assert File.exists?(res)
File.rm!(res)
end
end
describe "compute_and_save_media_filesize/1" do
test "updates the media item with the file size" do
media_item = media_item_with_attachments()
refute media_item.media_size_bytes
assert {:ok, media_item} = FilesystemHelpers.compute_and_save_media_filesize(media_item)
assert Repo.reload!(media_item).media_size_bytes
end
test "returns the error if operation fails" do
media_item = media_item_fixture(%{media_filepath: "/nonexistent/file.mkv"})
assert {:error, _} = FilesystemHelpers.compute_and_save_media_filesize(media_item)
end
end
end

View file

@ -11,7 +11,7 @@ defmodule Pinchflat.MediaTest do
alias Pinchflat.Media.MediaItem
alias Pinchflat.Metadata.MetadataFileHelpers
alias Pinchflat.YtDlp.Backend.Media, as: YtDlpMedia
alias Pinchflat.YtDlp.Media, as: YtDlpMedia
setup :verify_on_exit!

View file

@ -1,4 +1,4 @@
defmodule Pinchflat.YtDlp.Backend.MediaParserTest do
defmodule Pinchflat.YtDlp.MediaParserTest do
use Pinchflat.DataCase
alias Pinchflat.Metadata.MetadataParser, as: Parser

View file

@ -1,12 +1,12 @@
defmodule Pinchflat.Utils.FilesystemUtils.FileFollowerServerTest do
defmodule Pinchflat.SlowIndexing.FileFollowerServerTest do
use ExUnit.Case, async: true
alias alias Pinchflat.Utils.FilesystemUtils
alias Pinchflat.Utils.FilesystemUtils.FileFollowerServer
alias alias Pinchflat.Filesystem.FilesystemHelpers
alias Pinchflat.SlowIndexing.FileFollowerServer
setup do
{:ok, pid} = FileFollowerServer.start_link()
tmpfile = FilesystemUtils.generate_metadata_tmpfile(:txt)
tmpfile = FilesystemHelpers.generate_metadata_tmpfile(:txt)
{:ok, %{pid: pid, tmpfile: tmpfile}}
end

View file

@ -7,7 +7,6 @@ defmodule Pinchflat.SourcesTest do
import Pinchflat.SourcesFixtures
alias Pinchflat.Sources
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.Sources.Source
alias Pinchflat.Downloading.DownloadingHelpers
alias Pinchflat.FastIndexing.FastIndexingWorker

View file

@ -1,103 +0,0 @@
defmodule Pinchflat.Tasks.MediaItemTasksTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.MediaFixtures
import Pinchflat.SourcesFixtures
import Pinchflat.ProfilesFixtures
alias Pinchflat.Tasks
alias Pinchflat.Media.MediaItem
alias Pinchflat.Tasks.MediaItemTasks
alias Pinchflat.Downloading.MediaDownloadWorker
setup :verify_on_exit!
@media_url "https://www.youtube.com/watch?v=1234"
describe "compute_and_save_media_filesize/1" do
test "updates the media item with the file size" do
media_item = media_item_with_attachments()
refute media_item.media_size_bytes
assert {:ok, media_item} = MediaItemTasks.compute_and_save_media_filesize(media_item)
assert Repo.reload!(media_item).media_size_bytes
end
test "returns the error if operation fails" do
media_item = media_item_fixture(%{media_filepath: "/nonexistent/file.mkv"})
assert {:error, _} = MediaItemTasks.compute_and_save_media_filesize(media_item)
end
end
describe "index_and_enqueue_download_for_media_item/2" do
setup do
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
{:ok, media_attributes_return_fixture()}
end)
{:ok, [source: source_fixture()]}
end
test "creates a new media item based on the URL", %{source: source} do
assert Repo.aggregate(MediaItem, :count) == 0
assert {:ok, _} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
assert Repo.aggregate(MediaItem, :count) == 1
end
test "won't duplicate media_items based on media_id and source", %{source: source} do
assert {:ok, mi_1} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
assert {:ok, mi_2} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
assert Repo.aggregate(MediaItem, :count) == 1
assert mi_1.id == mi_2.id
end
test "enqueues a download job", %{source: source} do
assert {:ok, media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
assert_enqueued(worker: MediaDownloadWorker, args: %{"id" => media_item.id})
end
test "creates a download task record", %{source: source} do
assert {:ok, media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
assert [_] = Tasks.list_tasks_for(:media_item_id, media_item.id, "MediaDownloadWorker")
end
test "does not enqueue a download job if the source does not allow it" do
source = source_fixture(%{download_media: false})
assert {:ok, _} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
refute_enqueued(worker: MediaDownloadWorker)
end
test "does not enqueue a download job if the media item does not match the format rules" do
profile = media_profile_fixture(%{shorts_behaviour: :exclude})
source = source_fixture(%{media_profile_id: profile.id})
stub(YtDlpRunnerMock, :run, fn _url, _opts, _ot ->
output =
Phoenix.json_library().encode!(%{
id: "video2",
title: "Video 2",
webpage_url: "https://example.com/shorts/video2",
was_live: true,
description: "desc2",
aspect_ratio: 1.67,
duration: 345.67,
upload_date: "20210101"
})
{:ok, output}
end)
assert {:ok, _media_item} = MediaItemTasks.index_and_enqueue_download_for_media_item(source, @media_url)
refute_enqueued(worker: MediaDownloadWorker)
end
end
end

View file

@ -1,20 +0,0 @@
defmodule Pinchflat.Tasks.SourceTasksTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.TasksFixtures
import Pinchflat.MediaFixtures
import Pinchflat.SourcesFixtures
import Pinchflat.ProfilesFixtures
alias Pinchflat.Tasks
alias Pinchflat.Tasks.Task
alias Pinchflat.Tasks.SourceTasks
alias Pinchflat.Media.MediaItem
alias Pinchflat.FastIndexing.FastIndexingWorker
alias Pinchflat.Downloading.MediaDownloadWorker
alias Pinchflat.FastIndexing.MediaIndexingWorker
alias Pinchflat.SlowIndexing.MediaCollectionIndexingWorker
setup :verify_on_exit!
end

View file

@ -1,16 +0,0 @@
defmodule Pinchflat.Utils.FilesystemUtilsTest do
use ExUnit.Case, async: true
alias Pinchflat.Utils.FilesystemUtils
describe "generate_metadata_tmpfile/1" do
test "creates a tmpfile and returns its path" do
res = FilesystemUtils.generate_metadata_tmpfile(:json)
assert String.ends_with?(res, ".json")
assert File.exists?(res)
File.rm!(res)
end
end
end

View file

@ -1,7 +1,7 @@
defmodule Pinchflat.YtDlp.Backend.CommandRunnerTest do
defmodule Pinchflat.YtDlp.CommandRunnerTest do
use ExUnit.Case, async: true
alias Pinchflat.YtDlp.Backend.CommandRunner, as: Runner
alias Pinchflat.YtDlp.CommandRunner, as: Runner
@original_executable Application.compile_env(:pinchflat, :yt_dlp_executable)
@media_url "https://www.youtube.com/watch?v=-LHXuyzpex0"

View file

@ -1,10 +1,10 @@
defmodule Pinchflat.YtDlp.Backend.MediaCollectionTest do
defmodule Pinchflat.YtDlp.MediaCollectionTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.SourcesFixtures
alias Pinchflat.YtDlp.Backend.Media
alias Pinchflat.YtDlp.Backend.MediaCollection
alias Pinchflat.YtDlp.Media
alias Pinchflat.YtDlp.MediaCollection
@channel_url "https://www.youtube.com/c/TheUselessTrials"

View file

@ -1,9 +1,9 @@
defmodule Pinchflat.YtDlp.Backend.MediaTest do
defmodule Pinchflat.YtDlp.MediaTest do
use Pinchflat.DataCase
import Mox
import Pinchflat.MediaFixtures
alias Pinchflat.YtDlp.Backend.Media
alias Pinchflat.YtDlp.Media
@media_url "https://www.youtube.com/watch?v=TiZPUDkDYbk"

View file

@ -1,4 +1,4 @@
Mox.defmock(YtDlpRunnerMock, for: Pinchflat.YtDlp.Backend.BackendCommandRunner)
Mox.defmock(YtDlpRunnerMock, for: Pinchflat.YtDlp.BackendCommandRunner)
Application.put_env(:pinchflat, :yt_dlp_runner, YtDlpRunnerMock)
Mox.defmock(HTTPClientMock, for: Pinchflat.HTTP.HTTPBehaviour)