fix create_thumbnail automation

This commit is contained in:
CJ_Clippy 2025-01-21 12:42:01 -08:00
parent 4cf90d78a9
commit db0222ff94
31 changed files with 469 additions and 870 deletions

View File

@ -12,9 +12,16 @@ defmodule Bright.B2 do
alias Bright.B2
@doc """
Put a file from local disk to Backblaze. This function uses the filename as the S3 key. Use put/2 if you want to specify the key
"""
def put(local_file) do
object_key = Path.basename(local_file)
put(local_file, object_key)
end
@doc """
Put a file from local disk to Backblaze
Put a file from local disk to Backblaze.
"""
def put(local_file, object_key) do
@ -23,13 +30,19 @@ defmodule Bright.B2 do
raise("bucket specification is missing")
end
s3_cdn_endpoint = Application.get_env(:bright, :s3_cdn_endpoint)
if s3_cdn_endpoint === nil do
raise("s3_cdn_endpoint specification is missing")
end
cdn_url = "#{s3_cdn_endpoint}/#{object_key}"
local_file
|> S3.Upload.stream_file
|> S3.upload(bucket, object_key)
|> ExAws.request
|> case do
{:ok, %{status_code: 200}} -> {:ok, object_key}
{:ok, %{status_code: 200}} -> {:ok, %{key: object_key, cdn_url: cdn_url}}
{:error, reason} -> {:error, reason}
end
@ -56,17 +69,19 @@ defmodule Bright.B2 do
end
end
@doc """
Given a S3 object_key, generate an appropriate CDN url.
"""
def generate_cdn_url(object_key) do
cdn_url = Application.get_env(:bright, :public_s3_endpoint) || raise(":public_s3_endpoint missing from App env")
"#{cdn_url}/#{object_key}"
end
# defp upload_to_s3(body, key) do
# body
# |> S3.upload(@bucket_name, key)
# |> ExAws.request()
# |> case do
# {:ok, _response} -> :ok
# {:error, reason} -> {:error, reason}
# end
# end
end

View File

@ -6,16 +6,38 @@ defmodule Bright.Cache do
alias Bright.Streams.Vod
@cache_dir "/tmp/bright_cache"
@cache_dir Path.join(System.user_home!(), ".cache/futureporn")
require Logger
def generate_filename(input) do
def generate_basename(input) do
prefix = :crypto.strong_rand_bytes(6) |> Base.encode64(padding: false) |> String.replace(~r/[^a-zA-Z0-9]/, "")
base = Path.basename(input)
"#{prefix}-#{base}"
end
def generate_basename(input, ext) do
input
|> generate_basename
|> Path.rootname
|> Kernel.<>(".#{ext}")
end
def generate_filename(input) do
Path.join(@cache_dir, generate_basename(input))
end
def generate_filename(input, ext) do
Path.join(@cache_dir, generate_basename(input, ext))
# @cache_dir
# input
# |> generate_basename
# |> Path.join(@cache_dir)
# |> Path.rootname
# |> Kernel.<>(".#{ext}")
end
# Ensure the cache directory exists
defp ensure_cache_dir! do
@ -24,98 +46,9 @@ defmodule Bright.Cache do
end
end
@doc """
Save data to the cache with a given key.
## Examples
iex> Bright.Cache.put("example_key", "example_data")
:ok
"""
def put(key, data) do
ensure_cache_dir!()
file_path = cache_file_path(key)
case File.write(file_path, data) do
:ok ->
Logger.debug("[Cache] Saved key #{key} to #{file_path}")
:ok
{:error, reason} ->
Logger.error("[Cache] Failed to save key #{key}: #{reason}")
{:error, reason}
end
end
@doc """
Save a VOD file to the cache using its origin_temp_input_url.
## Examples
iex> Bright.Cache.put(%Vod{key: "vod_key", origin_temp_input_url: "http://example.com/video.mp4"})
:ok
"""
def put(%Vod{origin_temp_input_url: url}) do
ensure_cache_dir!()
key = generate_filename(url)
file_path = cache_file_path(key)
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
case File.write(file_path, body) do
:ok ->
Logger.debug("[Cache] Downloaded and saved VOD #{key} from #{url} to #{file_path}")
:ok
{:error, reason} ->
Logger.error("[Cache] Failed to save VOD #{key}: #{reason}")
{:error, reason}
end
{:ok, %HTTPoison.Response{status_code: status}} ->
Logger.error("[Cache] Failed to download VOD #{key}: HTTP #{status}")
{:error, :http_error}
{:error, %HTTPoison.Error{reason: reason}} ->
Logger.error("[Cache] Failed to download VOD #{key}: #{reason}")
{:error, reason}
end
end
@doc """
Retrieve data from the cache for a given key.
## Examples
iex> Bright.Cache.get("example_key")
{:ok, "example_data"}
iex> Bright.Cache.get("nonexistent_key")
:error
"""
def get(key) do
ensure_cache_dir!()
file_path = cache_file_path(key)
case File.read(file_path) do
{:ok, data} ->
Logger.debug("[Cache] Retrieved key #{key} from #{file_path}")
{:ok, data}
{:error, :enoent} ->
Logger.debug("[Cache] Key #{key} not found in cache")
:error
{:error, reason} ->
Logger.error("[Cache] Failed to retrieve key #{key}: #{reason}")
{:error, reason}
end
end
@doc """
Delete a cached item by its key.
@ -131,7 +64,7 @@ defmodule Bright.Cache do
def delete(key) do
ensure_cache_dir!()
file_path = cache_file_path(key)
file_path = generate_filename(key)
case File.rm(file_path) do
:ok ->
@ -171,8 +104,5 @@ defmodule Bright.Cache do
end
end
# Helper function to generate the file path for a given key
defp cache_file_path(key) do
Path.join(@cache_dir, key)
end
end

View File

@ -0,0 +1,33 @@
defmodule Bright.Downloader do
@moduledoc """
Downloader functions
"""
def get(url) do
local_file = Bright.Cache.generate_filename(url)
headers = %{}
case HTTPoison.get(url, headers) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
case File.write(local_file, body) do
:ok -> {:ok, local_file}
end
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
{:error, %{status: status, body: body}}
{:error, %HTTPoison.Error{reason: reason}} ->
{:error, reason}
failed ->
Logger.error("Failed to GET #{url}")
{:error, :failed}
end
end
end

View File

@ -6,7 +6,7 @@ defmodule Bright.Images do
import FFmpex
use FFmpex.Options
require Logger
alias Bright.Cache
def get_video_duration(file_path) do
case FFprobe.streams(file_path) do
@ -56,9 +56,7 @@ defmodule Bright.Images do
end
end
def create_thumbnail(input_file, output_file) do
defp gen_thumb(input_file, output_file) do
case get_video_framecount(input_file) do
{:error, reason} -> {:error, reason}
{:ok, framecount} ->
@ -75,13 +73,32 @@ defmodule Bright.Images do
|> add_output_file(output_file)
|> add_file_option(option_vframes(1))
|> add_file_option(option_vf("select=not(mod(n\\,#{frame_interval})),scale=#{scale_width}:-1,tile=#{tile_grid}"))
|> add_file_option(option_vsync(1)) # -vsync is deprecated in ffmpeg but ffmpex doesn't have the modern replacement, -fps_mode
|> add_file_option(option_vsync(0)) # -vsync is deprecated in ffmpeg but ffmpex doesn't have the modern replacement, -fps_mode
# |> add_file_option(option_update(1)) # ffmpeg complains but it doesn't necessarily need this. I'm omitting because ffmpex doesn't know this function
# |> add_file_option(option_fps_mode("passthrough")) # -fps_mode is the modern replacement for -vsync
execute(command)
Logger.info("generating thumbnail...")
IO.puts "generating thumbnail with input_file=#{input_file} output_file=#{output_file}"
case execute(command) do
{:ok, output} ->
{:ok, %{output: output, filename: output_file}}
{:error, reason} ->
Logger.error("Error generating thumbnail: #{inspect(reason)}")
{:error, reason}
end
end
end
def create_thumbnail(input_file) do
output_file = Cache.generate_filename(input_file, "png")
IO.puts "creating_thumbnail from #{input_file} and saving it to #{output_file}"
gen_thumb(input_file, output_file)
end
def create_thumbnail(input_file, output_file) do
gen_thumb(input_file, output_file)
end

View File

@ -1,47 +1,48 @@
defmodule Bright.ObanWorkers.CreateS3Asset do
use Oban.Worker, queue: :default, max_attempts: 3
alias ExAws.S3
require Logger
@bucket_name System.get_env("AWS_BUCKET")
alias ExAws.S3
alias Bright.Cache
alias Bright.Downloader
alias Bright.B2
alias Bright.Repo
@impl Oban.Worker
def perform(%Oban.Job{args: %{"input_url" => input_url, "vod_id" => vod_id}}) do
Logger.info("@todo implementation needed")
# random_string = for _ <- 1..12, into: "", do: <<Enum.random(~c"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")>>
# output_file = "/tmp/#{random_string}-#{key}"
# with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- fetch_file(input_url),
# {:ok, local_path} <- save_file(body, key),
# :ok <- upload_to_s3(local_path, key) do
# :ok
# else
# {:error, reason} ->
# Logger.error("Failed to process job: #{inspect(reason)}")
# {:error, reason}
# end
Logger.info("CreateS3Asset begin.")
vod = Repo.get!(Vod, vod_id)
basename = Cache.generate_basename(input_url)
with {:ok, local_file} <- Downloader.get(input_url),
{:ok, object_key} <- B2.put(local_file, basename) do
update_vod_with_s3_asset(vod, object_key)
else
{:error, reason} ->
Logger.error("Failed to create S3 Asset for VOD ID #{vod_id}: #{inspect(reason)}")
{:error, reason}
end
end
# defp fetch_file(url) do
# case HTTPoison.get(url, [], stream_to: self()) do
# {:ok, response} when response.status_code in 200..299 ->
# {:ok, response}
defp update_vod_with_s3_asset(vod, object_key) do
basename = Path.basename(vod.thumbnail_url)
s3_cdn_url = B2.generate_cdn_url(object_key)
# {:ok, %HTTPoison.Response{status_code: status}} ->
# {:error, "HTTP request failed with status: #{status}"}
vod
|> Ecto.Changeset.change(s3_cdn_url: s3_cdn_url)
|> Repo.update!()
end
# {:error, %HTTPoison.Error{reason: reason}} ->
# {:error, reason}
# end
# defp update_vod_with_playlist_url(vod, asset_id) do
# playlist_url = generate_playlist_url(asset_id)
# Logger.info("playlist_url=#{playlist_url}")
# vod
# |> Ecto.Changeset.change(playlist_url: playlist_url)
# |> Repo.update!()
# end
# defp upload_to_s3(body, key) do
# body
# |> S3.upload(@bucket_name, key)
# |> ExAws.request()
# |> case do
# {:ok, _response} -> :ok
# {:error, reason} -> {:error, reason}
# end
# end
end

View File

@ -1,46 +1,60 @@
defmodule Bright.ObanWorkers.CreateThumbnail do
use Oban.Worker, queue: :default, max_attempts: 3
alias Bright.Cache
alias Bright.Images
alias Bright.B2
alias Bright.Streams.Vod
alias Bright.{
Repo,
Downloader,
B2,
Images,
Cache
}
require Logger
@impl Oban.Worker
def perform(%Oban.Job{args: %{"vod_id" => vod_id, "origin_temp_input_url" => origin_temp_input_url}}) do
def perform(%Oban.Job{args: %{"vod_id" => vod_id}}) do
Logger.info(">>>> CreateThumbnail is performing. with vod_id=#{vod_id}")
IO.puts ">>>> CreateThumbnail is performing. with vod_id=#{vod_id}"
vod = Repo.get!(Vod, vod_id)
case Repo.get(Vod, vod_id) do
nil ->
Logger.error("VOD ID #{vod_id} not found")
{:error, "VOD not found"}
with {:ok, cache_filename} <- Cache.put(origin_temp_input_url),
{:ok, thumb_filename} <- Images.create_thumbnail(cache_filename),
{:ok, s3Asset} <- B2.put(thumb_filename) do
%Vod{origin_temp_input_url: origin_temp_input_url} = vod ->
with {:ok, local_filename} <- Downloader.get(origin_temp_input_url),
{:ok, %{output: output, filename: output_file}} <- Images.create_thumbnail(local_filename),
{:ok, s3Asset} <- B2.put(output_file)
do
IO.puts("updating vod ...")
update_vod_with_thumbnail_url(vod, s3Asset.cdn_url)
else
{:error, reason} ->
Logger.error("Failed to create HLS playlist for VOD ID #{vod_id}: #{inspect(reason)}")
Logger.error("Failed to create thumbnail for VOD ID #{vod_id}: #{inspect(reason)}")
{:error, reason}
end
end
end
# vod
# |> Cache.put
# |> Images.create_thumbnail
# |> B2.put
defp generate_thumbnail_url(basename), do: "#{@public_s3_endpoint}/#{basename}"
# defp update_vod_with_thumbnail_url(vod, thumbnail_url) do
# IO.puts "thumbnail_url=#{thumbnail_url}"
# vod
# |> Ecto.Changeset.change(thumbnail_url: thumbnail_url)
# |> Repo.update!()
# end
defp update_vod_with_thumbnail_url(vod, thumbnail_url) do
basename = Path.basename(thumbnail_url)
thumbnail_url = generate_thumbnail_url(basename)
Logger.info("thumbnail_url=#{thumbnail_url}")
vod
|> Ecto.Changeset.change(thumbnail_url: thumbnail_url)
|> Repo.update!()
IO.puts "thumbnail_url=#{thumbnail_url}"
case Repo.update(vod |> Ecto.Changeset.change(thumbnail_url: thumbnail_url)) do
{:ok, updated_vod} -> {:ok, updated_vod}
{:error, changeset} -> {:error, changeset}
end
end
end

View File

@ -12,22 +12,16 @@ defmodule Bright.ObanWorkers.ProcessVod do
}
@impl Oban.Worker
def perform(%Oban.Job{args: %{"id" => id}} = job) do
Logger.info("Performing job: #{inspect(job)}")
def perform(%Oban.Job{args: %{"vod_id" => vod_id}}) do
vod = Repo.get!(Vod, id)
vod = Repo.get!(Vod, vod_id)
if vod.playlist_url == nil and vod.origin_temp_input_url != nil do
queue_create_hls_playlist(vod)
end
if vod.s3_key == nil do
queue_create_s3_asset(vod)
end
if vod.thumbnail_url == nil and vod.origin_temp_input_url != nil do
queue_create_thumbnail(vod)
if vod.origin_temp_input_url do
unless vod.playlist_url, do: queue_create_hls_playlist(vod)
unless vod.s3_cdn_url, do: queue_create_s3_asset(vod)
unless vod.thumbnail_url, do: queue_create_thumbnail(vod)
end
@ -46,7 +40,7 @@ defmodule Bright.ObanWorkers.ProcessVod do
end
defp queue_create_thumbnail(%Vod{id: id, origin_temp_input_url: url}) do
job_args = %{vod_id: id}
job_args = %{vod_id: id, input_url: url}
Oban.insert!(CreateThumbnail.new(job_args))
end

View File

@ -123,12 +123,6 @@ defmodule Bright.Streams do
|> Ecto.Changeset.put_assoc(:platforms, platforms)
end
def inc_page_views(%Stream{} = stream) do
{1, [%Stream{views: views}]} =
from(s in Stream, where: s.id == ^stream.id, select: [:views])
|> Repo.update_all(inc: [views: 1])
put_in(stream.views, views)
end
def list_tags_by_id(nil), do: []
def list_tags_by_id(tag_ids) do
@ -198,8 +192,8 @@ defmodule Bright.Streams do
|> Vod.changeset(attrs)
|> Repo.insert()
|> case do
{:ok, vod} ->
maybe_enqueue_process_vod(vod)
{:ok, %Vod{} = vod} ->
Oban.insert!(Bright.ObanWorkers.ProcessVod.new(%{vod_id: vod.id}))
{:ok, vod}
{:error, changeset} ->
@ -207,22 +201,28 @@ defmodule Bright.Streams do
end
end
defp maybe_enqueue_process_vod(%Vod{id: id, origin_temp_input_url: origin_temp_input_url} = vod) do
if origin_temp_input_url do
%{id: id, origin_temp_input_url: origin_temp_input_url}
|> Bright.ObanWorkers.ProcessVod.new()
|> Oban.insert()
end
vod
def create_tag(attrs \\ %{}) do
%Tag{}
|> Tag.changeset(attrs)
|> Repo.insert()
end
# def create_stream(attrs \\ %{}) do
# %Stream{}
# # |> Stream.changeset(attrs)
# |> change_stream(attrs)
# |> Repo.insert()
# end
# defp enqueue_process_vod(%Vod{id: id} = vod) do
# %{vod_id: id}
# |> Bright.ObanWorkers.ProcessVod.new()
# |> Oban.insert()
# vod
# end
@doc """

View File

@ -9,7 +9,6 @@ defmodule Bright.Streams.Stream do
field :date, :utc_datetime
field :title, :string
field :notes, :string
field :views, :integer
many_to_many :tags, Tag, join_through: "streams_tags", on_replace: :delete

View File

@ -23,7 +23,7 @@ defmodule Bright.Uploads do
def download_file(url, destination_path) do
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
IO.puts "WE GOT A GOOD RESPONSE SO LETS WRITE"
# IO.puts "WE GOT A GOOD RESPONSE SO LETS WRITE"
case File.write(destination_path, body) do
:ok -> {:ok, "File downloaded successfully"}
{:error, reason} -> {:error, reason}

View File

@ -52,6 +52,7 @@
<:item title="S3 upload">{@vod.s3_upload_id}</:item>
<:item title="S3 key">{@vod.s3_key}</:item>
<:item title="S3 bucket">{@vod.s3_bucket}</:item>
<:item title="Thumbnail URL">{@vod.thumbnail_url}</:item>
<:item title="Ipfs CID">{@vod.ipfs_cid}</:item>
<:item title="Torrent">{@vod.torrent}</:item>

View File

@ -0,0 +1,9 @@
defmodule Bright.Repo.Migrations.RemoveViewsFromStreams do
use Ecto.Migration
def change do
alter table(:streams) do
remove :views
end
end
end

View File

@ -3,19 +3,25 @@ defmodule Bright.B2Test do
@cdn_url Application.get_env(:bright, :public_s3_endpoint)
describe "B2" do
alias Bright.B2
@tag :acceptance
test "put/1" do
local_file = Path.absname("test/fixtures/SampleVideo_1280x720_1mb.mp4")
{:ok, %{key: key, cdn_url: cdn_url}} = B2.put(local_file)
assert key === "SampleVideo_1280x720_1mb.mp4"
end
@tag :acceptance
test "put/2" do
local_file = Path.absname("test/fixtures/SampleVideo_1280x720_1mb.mp4")
object_key = "test/SampleVideo_1280x720_1mb.mp4"
{:ok, remote_file} = B2.put(local_file, object_key)
assert Regex.match?(~r/SampleVideo/, remote_file)
{:ok, %{key: key, cdn_url: cdn_url}} = B2.put(local_file, object_key)
assert Regex.match?(~r/SampleVideo/, key)
end
@ -34,6 +40,15 @@ defmodule Bright.B2Test do
File.rm!(local_file)
end
@tag :integration
test "generate_cdn_url/1" do
assert Regex.match?(~r"https:\/\/", @cdn_url), ":public_s3_endpoint was missing from `:bright` app config, which is a requirement for this test."
object_key = "test/SampleVideo_1280x720_1mb.mp4"
cdn_url = B2.generate_cdn_url(object_key)
assert cdn_url === "#{@cdn_url}/#{object_key}"
end
end
end

View File

@ -1,61 +0,0 @@
defmodule Bright.BlogTest do
use Bright.DataCase
alias Bright.Blog
describe "posts" do
alias Bright.Blog.Post
import Bright.BlogFixtures
@invalid_attrs %{title: nil, body: nil}
test "list_posts/0 returns all posts" do
post = post_fixture()
assert Blog.list_posts() == [post]
end
test "get_post!/1 returns the post with given id" do
post = post_fixture()
assert Blog.get_post!(post.id) == post
end
test "create_post/1 with valid data creates a post" do
valid_attrs = %{title: "some title", body: "some body"}
assert {:ok, %Post{} = post} = Blog.create_post(valid_attrs)
assert post.title == "some title"
assert post.body == "some body"
end
test "create_post/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Blog.create_post(@invalid_attrs)
end
test "update_post/2 with valid data updates the post" do
post = post_fixture()
update_attrs = %{title: "some updated title", body: "some updated body"}
assert {:ok, %Post{} = post} = Blog.update_post(post, update_attrs)
assert post.title == "some updated title"
assert post.body == "some updated body"
end
test "update_post/2 with invalid data returns error changeset" do
post = post_fixture()
assert {:error, %Ecto.Changeset{}} = Blog.update_post(post, @invalid_attrs)
assert post == Blog.get_post!(post.id)
end
test "delete_post/1 deletes the post" do
post = post_fixture()
assert {:ok, %Post{}} = Blog.delete_post(post)
assert_raise Ecto.NoResultsError, fn -> Blog.get_post!(post.id) end
end
test "change_post/1 returns a post changeset" do
post = post_fixture()
assert %Ecto.Changeset{} = Blog.change_post(post)
end
end
end

View File

@ -3,23 +3,47 @@ defmodule Bright.CacheTest do
alias Bright.Cache
@sample_url "https://example.com/my_video.mp4"
describe "cache" do
@tag :unit
test "generate_filename generates a random alphanumeric prefix with the correct basename and extension" do
test "generate_basename/1" do
# Test with a URL
url = "https://example.com/my_video.mp4"
filename = Cache.generate_filename(url)
url = @sample_url
filename = Cache.generate_basename(url)
assert Regex.match?(~r/^[a-zA-Z0-9]+-my_video\.mp4$/, filename)
# Test with a file path
path = "/home/cj/Downloads/taco.mp4"
filename = Cache.generate_filename(path)
filename = Cache.generate_basename(path)
assert Regex.match?(~r/^[a-zA-Z0-9]+-taco\.mp4$/, filename)
end
@tag :unit
test "generate_basename/2" do
filename = Cache.generate_basename(@sample_url, "png")
assert Regex.match?(~r/^[a-zA-Z0-9]+-my_video\.png/, filename)
end
@tag :unit
test "generate_filename/1" do
filename = Cache.generate_filename(@sample_url)
assert Regex.match?(~r/.cache\/futureporn\/.+-my_video\.mp4/, filename)
filename = Cache.generate_filename("/home/cj/Downloads/test.mp4")
assert Regex.match?(~r/.cache\/futureporn\/.+-test\.mp4/, filename)
end
@tag :unit
test "generate_filename/2" do
filename = Cache.generate_filename(@sample_url, "png")
assert Regex.match?(~r/.cache\/futureporn\/.+-my_video\.png/, filename)
end
end

View File

@ -1,119 +0,0 @@
defmodule Bright.CatalogTest do
use Bright.DataCase
alias Bright.Catalog
describe "products" do
alias Bright.Catalog.Product
import Bright.CatalogFixtures
@invalid_attrs %{description: nil, title: nil, price: nil, views: nil}
test "list_products/0 returns all products" do
product = product_fixture()
assert Catalog.list_products() == [product]
end
test "get_product!/1 returns the product with given id" do
product = product_fixture()
assert Catalog.get_product!(product.id) == product
end
test "create_product/1 with valid data creates a product" do
valid_attrs = %{description: "some description", title: "some title", price: "120.5", views: 42}
assert {:ok, %Product{} = product} = Catalog.create_product(valid_attrs)
assert product.description == "some description"
assert product.title == "some title"
assert product.price == Decimal.new("120.5")
assert product.views == 42
end
test "create_product/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Catalog.create_product(@invalid_attrs)
end
test "update_product/2 with valid data updates the product" do
product = product_fixture()
update_attrs = %{description: "some updated description", title: "some updated title", price: "456.7", views: 43}
assert {:ok, %Product{} = product} = Catalog.update_product(product, update_attrs)
assert product.description == "some updated description"
assert product.title == "some updated title"
assert product.price == Decimal.new("456.7")
assert product.views == 43
end
test "update_product/2 with invalid data returns error changeset" do
product = product_fixture()
assert {:error, %Ecto.Changeset{}} = Catalog.update_product(product, @invalid_attrs)
assert product == Catalog.get_product!(product.id)
end
test "delete_product/1 deletes the product" do
product = product_fixture()
assert {:ok, %Product{}} = Catalog.delete_product(product)
assert_raise Ecto.NoResultsError, fn -> Catalog.get_product!(product.id) end
end
test "change_product/1 returns a product changeset" do
product = product_fixture()
assert %Ecto.Changeset{} = Catalog.change_product(product)
end
end
describe "categories" do
alias Bright.Catalog.Category
import Bright.CatalogFixtures
@invalid_attrs %{title: nil}
test "list_categories/0 returns all categories" do
category = category_fixture()
assert Catalog.list_categories() == [category]
end
test "get_category!/1 returns the category with given id" do
category = category_fixture()
assert Catalog.get_category!(category.id) == category
end
test "create_category/1 with valid data creates a category" do
valid_attrs = %{title: "some title"}
assert {:ok, %Category{} = category} = Catalog.create_category(valid_attrs)
assert category.title == "some title"
end
test "create_category/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Catalog.create_category(@invalid_attrs)
end
test "update_category/2 with valid data updates the category" do
category = category_fixture()
update_attrs = %{title: "some updated title"}
assert {:ok, %Category{} = category} = Catalog.update_category(category, update_attrs)
assert category.title == "some updated title"
end
test "update_category/2 with invalid data returns error changeset" do
category = category_fixture()
assert {:error, %Ecto.Changeset{}} = Catalog.update_category(category, @invalid_attrs)
assert category == Catalog.get_category!(category.id)
end
test "delete_category/1 deletes the category" do
category = category_fixture()
assert {:ok, %Category{}} = Catalog.delete_category(category)
assert_raise Ecto.NoResultsError, fn -> Catalog.get_category!(category.id) end
end
test "change_category/1 returns a category changeset" do
category = category_fixture()
assert %Ecto.Changeset{} = Catalog.change_category(category)
end
end
end

View File

@ -0,0 +1,23 @@
defmodule Bright.DownloaderTest do
use Bright.DataCase
alias Bright.Downloader
@test_fixture "https://futureporn-b2.b-cdn.net/projekt-melody.jpg"
describe "downloader" do
test "get/1" do
{:ok, local_file} = Downloader.get(@test_fixture)
assert File.exists?(local_file)
{:ok, stat} = File.stat(local_file)
assert stat.size > 0, "File is empty"
assert Regex.match?(~r/.cache\/futureporn\/.+-projekt-melody\.jpg/, local_file)
end
end
end

View File

@ -9,7 +9,17 @@ defmodule Bright.ImagesTest do
test "should generate a 5x5 thumbnail using a local file" do
@tag :unit
test "create_thumbnail/1" do
{:ok, %{:output => output, :filename => filename}} = Images.create_thumbnail(@test_fixture)
assert output === ""
assert Regex.match?(~r/[a-zA-Z0-9]+-.*\.png$/, filename)
assert File.exists?(filename)
assert File.stat!(filename).size > 0, "thumbnail file is empty"
end
@tag :unit
test "create_thumbnail/2" do
# ffmpeg -y -i ~/Videos/moose-encounter_75.mp4 -frames:v 1 -vf 'select=not(mod(n\,257)),scale=160:-1,tile=5x5' -update 1 -fps_mode passthrough ~/Videos/thumb.jpg
basename = "thumb.jpg"
@ -17,13 +27,11 @@ defmodule Bright.ImagesTest do
output_file = "/tmp/#{random_string}-#{basename}"
IO.puts "output_file=#{inspect(output_file)} @test_fixture=#{inspect(@test_fixture)}"
Images.create_thumbnail(@test_fixture, output_file)
{:ok, output } = Images.create_thumbnail(@test_fixture, output_file)
assert File.exists?(output_file)
{:ok, stat} = File.stat(output_file)
assert stat.size > 0, "File is empty"
end
# Feature creep! Download the image for now. Make it work, first. THen make it right. THEN make it fast.

View File

@ -13,6 +13,8 @@ defmodule Bright.CreateHlsPlaylistTest do
describe "CreateHlsPlaylist" do
import Bright.StreamsFixtures
@tag :integration
test "sheduling upon vod creation" do
@ -43,88 +45,4 @@ defmodule Bright.CreateHlsPlaylistTest do
end
describe "perform/1" do
# test "throw when vod_id is missing" do
# job_args = %{"vod_id" => 1}
# {:error, reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
# assert Regex.match?(~r/missing.*vod_id/i, reason)
# end
# test "evergreen?" do
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/my_video.mp4"}
# assert :ok = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
# end
# test "bypassing activation when sign up fails" do
# {:error, _reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
# refute_enqueued worker: MyApp.ActivationWorker
# end
# test "successfully creates an HLS playlist and updates the VOD" do
# # Mock the VOD to be returned by Repo.get!/2
# vod = %Vod{id: 1, playlist_url: nil}
# expect(RepoMock, :get!, fn Vod, 1 -> vod end)
# # Mock the start_transcode function
# expect(HTTPoisonMock, :post, fn url, body, headers ->
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/transcode"
# assert headers == [
# {"authorization", "Bearer #{System.get_env("SUPERSTREAMER_AUTH_TOKEN")}"},
# {"content-type", "application/json"}
# ]
# {:ok, %HTTPoison.Response{status_code: 200, body: ~s({"jobId": "transcode-job-id"})}}
# end)
# # Mock the polling of the transcode job
# expect(HTTPoisonMock, :get, fn url, headers ->
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/jobs/transcode-job-id"
# {:ok, %HTTPoison.Response{
# status_code: 200,
# body: ~s({"state": "completed", "outputData": {"assetId": "asset-id"}})
# }}
# end)
# # Mock the start_package function
# expect(HTTPoisonMock, :post, fn url, body, headers ->
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/package"
# {:ok, %HTTPoison.Response{status_code: 200, body: ~s({"jobId": "package-job-id"})}}
# end)
# # Mock the polling of the package job
# expect(HTTPoisonMock, :get, fn url, headers ->
# assert url == "#{System.get_env("SUPERSTREAMER_URL")}/jobs/package-job-id"
# {:ok, %HTTPoison.Response{
# status_code: 200,
# body: ~s({"state": "completed", "outputData": {"assetId": "asset-id"}})
# }}
# end)
# # Mock the Repo.update!/1 call
# expect(RepoMock, :update!, fn changeset ->
# assert changeset.changes.playlist_url == "#{System.get_env("PUBLIC_S3_ENDPOINT")}/package/asset-id/hls/master.m3u8"
# {:ok, changeset}
# end)
# # Call the worker's perform function
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/input.mp4"}
# assert :ok = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
# end
# test "handles errors gracefully" do
# # Mock the VOD to be returned by Repo.get!/2
# vod = %Vod{id: 1, playlist_url: nil}
# expect(RepoMock, :get!, fn Vod, 1 -> vod end)
# # Mock the start_transcode function to return an error
# expect(HTTPoisonMock, :post, fn _url, _body, _headers ->
# {:error, %HTTPoison.Error{reason: "transcoding failed"}}
# end)
# # Call the worker's perform function
# job_args = %{"vod_id" => 1, "input_url" => "https://example.com/input.mp4"}
# assert {:error, _reason} = CreateHlsPlaylist.perform(%Oban.Job{args: job_args})
# end
end
end

View File

@ -1,31 +1,67 @@
defmodule Bright.ObanWorkers.CreateS3AssetTest do
use Bright.DataCase
use Oban.Testing, repo: Bright.Repo
alias Bright.ObanWorkers.CreateS3Asset
alias Bright.ObanWorkers.{
CreateS3Asset,
ProcessVod,
CreateThumbnail
}
alias Bright.Cache
alias Bright.Streams
alias Bright.Streams.Stream
@tag :unit
test "creating a new s3 asset (unit test)" do
url = "https://example.com/video.ts"
key = "video.ts"
{:ok, asset} = perform_job(CreateS3Asset, %{url: url, key: key})
end
@tag :acceptance
test "creating a new s3 asset (acceptance test)" do
# @tag :unit
# test "creating a new s3 asset (unit test)" do
url = "http://38.242.193.246:8081/fixtures/2024-12-19T03-10-30Z.ts"
key = unique_filename
# example_video = "http://example.com/video.ts"
# stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
# {:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
# {:ok, vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
# assert :ok
# {:ok, asset} = perform_job(CreateS3Asset, %{input_url: example_video, vod_id: vod.id})
# assert :ok
# end
@tag :integration
test "sheduling upon vod creation" do
example_video = "http://example.com/video.ts"
stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
{:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
{:ok, _vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
perform_job(CreateS3Asset, %{url: url, key: key})
{:ok, asset} = Oban.drain_queue(queue: :default)
assert_enqueued worker: ProcessVod, queue: :default
Oban.drain_queue(queue: :default) # ProcessVod is what queues CreateS3Asset so we need to make it run
assert_enqueued worker: CreateS3Asset, queue: :default
end
@tag :integration
test "not scheduled when origin_temp_input_url is missing" do
stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
{:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
{:ok, _vod} = Streams.create_vod(%{stream_id: stream.id})
refute_enqueued worker: CreateS3Asset
end
# @tag :acceptance
# test "creating a new s3 asset (acceptance test)" do
# url = "http://38.242.193.246:8081/fixtures/2024-12-19T03-10-30Z.ts"
# key = Cache.generate_filename(url)
# example_video = "http://example.com/video.ts"
# stream_attrs = %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
# {:ok, %Stream{} = stream} = Streams.create_stream(stream_attrs)
# {:ok, vod} = Streams.create_vod(%{stream_id: stream.id, origin_temp_input_url: example_video})
# perform_job(CreateS3Asset, %{input_url: example_video, vod_id: vod.id})
# {:ok, asset} = Oban.drain_queue(queue: :default)
# end
end

View File

@ -4,10 +4,28 @@ defmodule Bright.ObanWorkers.CreateThumbnailTest do
alias Bright.ObanWorkers.CreateThumbnail
alias Bright.ObanWorkers.ProcessVod
alias Bright.Streams
alias Bright.Streams.Stream
alias Bright.Streams.{
Stream,
Vod
}
describe "CreateThumbnail" do
import Bright.StreamsFixtures
@example_url "https://futureporn-b2.b-cdn.net/big_buck_bunny_720p_1mb.mp4"
@tag :integration
test "thumbnail creation" do
stream = stream_fixture()
vod = vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
{:ok, %Vod{thumbnail_url: thumbnail_url}} = perform_job(Bright.ObanWorkers.CreateThumbnail, %{vod_id: vod.id})
assert Regex.match?(~r/^https:\/\/.*\.png$/, thumbnail_url)
end
@tag :integration
test "sheduling upon vod creation" do
@ -35,5 +53,7 @@ defmodule Bright.ObanWorkers.CreateThumbnailTest do
refute_enqueued worker: CreateThumbnail
end
end
end

View File

@ -0,0 +1,63 @@
defmodule Bright.ObanWorkers.ProcessVodTest do
use Bright.DataCase
use Oban.Testing, repo: Bright.Repo
alias Bright.ObanWorkers.{
CreateThumbnail,
ProcessVod,
CreateS3Asset,
CreateHlsPlaylist
}
alias Bright.Streams
alias Bright.Streams.{Stream,Vod}
@example_url "https://example.com/my-video.mp4"
describe "ProcessVod" do
import Bright.StreamsFixtures
@tag :unit
test "processing a new vod" do
stream = stream_fixture()
vod = vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
:ok = perform_job(Bright.ObanWorkers.ProcessVod, %{vod_id: vod.id})
assert :ok
end
@tag :integration
test "schedule ProcessVod when a new vod is created" do
stream = stream_fixture()
vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
assert_enqueued worker: ProcessVod, queue: :default
end
@tag :integration
test "schedule CreateThumbnail when thumbnail_url is nil" do
stream = stream_fixture()
vod_fixture(%{thumbnail_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
assert_enqueued worker: ProcessVod, queue: :default
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
assert_enqueued worker: CreateThumbnail, queue: :default
end
@tag :integration
test "schedule CreateS3Asset when s3_cdn_url is nil" do
stream = stream_fixture()
vod_fixture(%{s3_cdn_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
assert_enqueued worker: ProcessVod, queue: :default
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
assert_enqueued worker: CreateS3Asset, queue: :default
end
@tag :integration
test "schedule CreateHlsPlaylist when playlist_url is nil" do
stream = stream_fixture()
vod_fixture(%{playlist_url: nil, stream_id: stream.id, origin_temp_input_url: @example_url})
assert_enqueued worker: ProcessVod, queue: :default
assert %{success: 1} = Oban.drain_queue(queue: :default, with_safety: false) # ProcessVod is what queues CreateThumbnail so we need to make it run
assert_enqueued worker: CreateHlsPlaylist, queue: :default
end
end
end

View File

@ -1,117 +0,0 @@
defmodule Bright.OrdersTest do
use Bright.DataCase
alias Bright.Orders
describe "orders" do
alias Bright.Orders.Order
import Bright.OrdersFixtures
@invalid_attrs %{user_uuid: nil, total_price: nil}
test "list_orders/0 returns all orders" do
order = order_fixture()
assert Orders.list_orders() == [order]
end
test "get_order!/1 returns the order with given id" do
order = order_fixture()
assert Orders.get_order!(order.id) == order
end
test "create_order/1 with valid data creates a order" do
valid_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960662", total_price: "120.5"}
assert {:ok, %Order{} = order} = Orders.create_order(valid_attrs)
assert order.user_uuid == "7488a646-e31f-11e4-aace-600308960662"
assert order.total_price == Decimal.new("120.5")
end
test "create_order/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Orders.create_order(@invalid_attrs)
end
test "update_order/2 with valid data updates the order" do
order = order_fixture()
update_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960668", total_price: "456.7"}
assert {:ok, %Order{} = order} = Orders.update_order(order, update_attrs)
assert order.user_uuid == "7488a646-e31f-11e4-aace-600308960668"
assert order.total_price == Decimal.new("456.7")
end
test "update_order/2 with invalid data returns error changeset" do
order = order_fixture()
assert {:error, %Ecto.Changeset{}} = Orders.update_order(order, @invalid_attrs)
assert order == Orders.get_order!(order.id)
end
test "delete_order/1 deletes the order" do
order = order_fixture()
assert {:ok, %Order{}} = Orders.delete_order(order)
assert_raise Ecto.NoResultsError, fn -> Orders.get_order!(order.id) end
end
test "change_order/1 returns a order changeset" do
order = order_fixture()
assert %Ecto.Changeset{} = Orders.change_order(order)
end
end
describe "order_line_items" do
alias Bright.Orders.LineItem
import Bright.OrdersFixtures
@invalid_attrs %{price: nil, quantity: nil}
test "list_order_line_items/0 returns all order_line_items" do
line_item = line_item_fixture()
assert Orders.list_order_line_items() == [line_item]
end
test "get_line_item!/1 returns the line_item with given id" do
line_item = line_item_fixture()
assert Orders.get_line_item!(line_item.id) == line_item
end
test "create_line_item/1 with valid data creates a line_item" do
valid_attrs = %{price: "120.5", quantity: 42}
assert {:ok, %LineItem{} = line_item} = Orders.create_line_item(valid_attrs)
assert line_item.price == Decimal.new("120.5")
assert line_item.quantity == 42
end
test "create_line_item/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Orders.create_line_item(@invalid_attrs)
end
test "update_line_item/2 with valid data updates the line_item" do
line_item = line_item_fixture()
update_attrs = %{price: "456.7", quantity: 43}
assert {:ok, %LineItem{} = line_item} = Orders.update_line_item(line_item, update_attrs)
assert line_item.price == Decimal.new("456.7")
assert line_item.quantity == 43
end
test "update_line_item/2 with invalid data returns error changeset" do
line_item = line_item_fixture()
assert {:error, %Ecto.Changeset{}} = Orders.update_line_item(line_item, @invalid_attrs)
assert line_item == Orders.get_line_item!(line_item.id)
end
test "delete_line_item/1 deletes the line_item" do
line_item = line_item_fixture()
assert {:ok, %LineItem{}} = Orders.delete_line_item(line_item)
assert_raise Ecto.NoResultsError, fn -> Orders.get_line_item!(line_item.id) end
end
test "change_line_item/1 returns a line_item changeset" do
line_item = line_item_fixture()
assert %Ecto.Changeset{} = Orders.change_line_item(line_item)
end
end
end

View File

@ -21,11 +21,11 @@ defmodule Bright.PlatformsTest do
end
test "create_platform/1 with valid data creates a platform" do
valid_attrs = %{name: "some name", url: true, icon: "<svg></svg>"}
valid_attrs = %{name: "some name", url: "some url", icon: "<svg></svg>"}
assert {:ok, %Platform{} = platform} = Platforms.create_platform(valid_attrs)
assert platform.name == "some name"
assert platform.url == true
assert platform.url == "some url"
assert platform.icon == "<svg></svg>"
end
@ -35,11 +35,11 @@ defmodule Bright.PlatformsTest do
test "update_platform/2 with valid data updates the platform" do
platform = platform_fixture()
update_attrs = %{name: "some updated name", url: false, icon: "<svg>blah</svg>"}
update_attrs = %{name: "some updated name", url: "https://example.com", icon: "<svg>blah</svg>"}
assert {:ok, %Platform{} = platform} = Platforms.update_platform(platform, update_attrs)
assert platform.name == "some updated name"
assert platform.url == false
assert platform.url == "https://example.com"
assert platform.icon == "<svg>blah</svg>"
end

View File

@ -1,115 +0,0 @@
defmodule Bright.ShoppingCartTest do
use Bright.DataCase
alias Bright.ShoppingCart
describe "carts" do
alias Bright.ShoppingCart.Cart
import Bright.ShoppingCartFixtures
@invalid_attrs %{user_uuid: nil}
test "list_carts/0 returns all carts" do
cart = cart_fixture()
assert ShoppingCart.list_carts() == [cart]
end
test "get_cart!/1 returns the cart with given id" do
cart = cart_fixture()
assert ShoppingCart.get_cart!(cart.id) == cart
end
test "create_cart/1 with valid data creates a cart" do
valid_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960662"}
assert {:ok, %Cart{} = cart} = ShoppingCart.create_cart(valid_attrs)
assert cart.user_uuid == "7488a646-e31f-11e4-aace-600308960662"
end
test "create_cart/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = ShoppingCart.create_cart(@invalid_attrs)
end
test "update_cart/2 with valid data updates the cart" do
cart = cart_fixture()
update_attrs = %{user_uuid: "7488a646-e31f-11e4-aace-600308960668"}
assert {:ok, %Cart{} = cart} = ShoppingCart.update_cart(cart, update_attrs)
assert cart.user_uuid == "7488a646-e31f-11e4-aace-600308960668"
end
test "update_cart/2 with invalid data returns error changeset" do
cart = cart_fixture()
assert {:error, %Ecto.Changeset{}} = ShoppingCart.update_cart(cart, @invalid_attrs)
assert cart == ShoppingCart.get_cart!(cart.id)
end
test "delete_cart/1 deletes the cart" do
cart = cart_fixture()
assert {:ok, %Cart{}} = ShoppingCart.delete_cart(cart)
assert_raise Ecto.NoResultsError, fn -> ShoppingCart.get_cart!(cart.id) end
end
test "change_cart/1 returns a cart changeset" do
cart = cart_fixture()
assert %Ecto.Changeset{} = ShoppingCart.change_cart(cart)
end
end
describe "cart_items" do
alias Bright.ShoppingCart.CartItem
import Bright.ShoppingCartFixtures
@invalid_attrs %{price_when_carted: nil, quantity: nil}
test "list_cart_items/0 returns all cart_items" do
cart_item = cart_item_fixture()
assert ShoppingCart.list_cart_items() == [cart_item]
end
test "get_cart_item!/1 returns the cart_item with given id" do
cart_item = cart_item_fixture()
assert ShoppingCart.get_cart_item!(cart_item.id) == cart_item
end
test "create_cart_item/1 with valid data creates a cart_item" do
valid_attrs = %{price_when_carted: "120.5", quantity: 42}
assert {:ok, %CartItem{} = cart_item} = ShoppingCart.create_cart_item(valid_attrs)
assert cart_item.price_when_carted == Decimal.new("120.5")
assert cart_item.quantity == 42
end
test "create_cart_item/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = ShoppingCart.create_cart_item(@invalid_attrs)
end
test "update_cart_item/2 with valid data updates the cart_item" do
cart_item = cart_item_fixture()
update_attrs = %{price_when_carted: "456.7", quantity: 43}
assert {:ok, %CartItem{} = cart_item} = ShoppingCart.update_cart_item(cart_item, update_attrs)
assert cart_item.price_when_carted == Decimal.new("456.7")
assert cart_item.quantity == 43
end
test "update_cart_item/2 with invalid data returns error changeset" do
cart_item = cart_item_fixture()
assert {:error, %Ecto.Changeset{}} = ShoppingCart.update_cart_item(cart_item, @invalid_attrs)
assert cart_item == ShoppingCart.get_cart_item!(cart_item.id)
end
test "delete_cart_item/1 deletes the cart_item" do
cart_item = cart_item_fixture()
assert {:ok, %CartItem{}} = ShoppingCart.delete_cart_item(cart_item)
assert_raise Ecto.NoResultsError, fn -> ShoppingCart.get_cart_item!(cart_item.id) end
end
test "change_cart_item/1 returns a cart_item changeset" do
cart_item = cart_item_fixture()
assert %Ecto.Changeset{} = ShoppingCart.change_cart_item(cart_item)
end
end
end

View File

@ -66,20 +66,23 @@ defmodule Bright.StreamsTest do
import Bright.StreamsFixtures
@invalid_attrs %{s3_cdn_url: nil, s3_upload_id: nil, s3_key: nil, s3_bucket: nil, mux_asset_id: nil, mux_playback_id: nil, ipfs_cid: nil, torrent: nil}
@invalid_attrs %{stream_id: nil, s3_cdn_url: nil, s3_upload_id: nil, s3_key: nil, s3_bucket: nil, mux_asset_id: nil, mux_playback_id: nil, ipfs_cid: nil, torrent: nil}
test "list_vods/0 returns all vods" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
assert Streams.list_vods() == [vod]
end
test "get_vod!/1 returns the vod with given id" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
assert Streams.get_vod!(vod.id) == vod
end
test "create_vod/1 with valid data creates a vod" do
valid_attrs = %{s3_cdn_url: "some s3_cdn_url", s3_upload_id: "some s3_upload_id", s3_key: "some s3_key", s3_bucket: "some s3_bucket", mux_asset_id: "some mux_asset_id", mux_playback_id: "some mux_playback_id", ipfs_cid: "some ipfs_cid", torrent: "some torrent"}
stream = stream_fixture()
valid_attrs = %{stream_id: stream.id, s3_cdn_url: "some s3_cdn_url", s3_upload_id: "some s3_upload_id", s3_key: "some s3_key", s3_bucket: "some s3_bucket", mux_asset_id: "some mux_asset_id", mux_playback_id: "some mux_playback_id", ipfs_cid: "some ipfs_cid", torrent: "some torrent"}
assert {:ok, %Vod{} = vod} = Streams.create_vod(valid_attrs)
assert vod.s3_cdn_url == "some s3_cdn_url"
@ -97,7 +100,8 @@ defmodule Bright.StreamsTest do
end
test "update_vod/2 with valid data updates the vod" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
update_attrs = %{s3_cdn_url: "some updated s3_cdn_url", s3_upload_id: "some updated s3_upload_id", s3_key: "some updated s3_key", s3_bucket: "some updated s3_bucket", mux_asset_id: "some updated mux_asset_id", mux_playback_id: "some updated mux_playback_id", ipfs_cid: "some updated ipfs_cid", torrent: "some updated torrent"}
assert {:ok, %Vod{} = vod} = Streams.update_vod(vod, update_attrs)
@ -112,19 +116,22 @@ defmodule Bright.StreamsTest do
end
test "update_vod/2 with invalid data returns error changeset" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
assert {:error, %Ecto.Changeset{}} = Streams.update_vod(vod, @invalid_attrs)
assert vod == Streams.get_vod!(vod.id)
end
test "delete_vod/1 deletes the vod" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
assert {:ok, %Vod{}} = Streams.delete_vod(vod)
assert_raise Ecto.NoResultsError, fn -> Streams.get_vod!(vod.id) end
end
test "change_vod/1 returns a vod changeset" do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
assert %Ecto.Changeset{} = Streams.change_vod(vod)
end
end

View File

@ -12,7 +12,7 @@ defmodule Bright.TagsTest do
test "list_tag/0 returns all tag" do
tag = tag_fixture()
assert Tags.list_tag() == [tag]
assert Tags.list_tags() == [tag]
end
test "get_tag!/1 returns the tag with given id" do

View File

@ -1,42 +0,0 @@
defmodule Bright.CatalogFixtures do
@moduledoc """
This module defines test helpers for creating
entities via the `Bright.Catalog` context.
"""
@doc """
Generate a product.
"""
def product_fixture(attrs \\ %{}) do
{:ok, product} =
attrs
|> Enum.into(%{
description: "some description",
price: "120.5",
title: "some title",
views: 42
})
|> Bright.Catalog.create_product()
product
end
@doc """
Generate a unique category title.
"""
def unique_category_title, do: "some title#{System.unique_integer([:positive])}"
@doc """
Generate a category.
"""
def category_fixture(attrs \\ %{}) do
{:ok, category} =
attrs
|> Enum.into(%{
title: unique_category_title()
})
|> Bright.Catalog.create_category()
category
end
end

View File

@ -1,36 +0,0 @@
defmodule Bright.OrdersFixtures do
@moduledoc """
This module defines test helpers for creating
entities via the `Bright.Orders` context.
"""
@doc """
Generate a order.
"""
def order_fixture(attrs \\ %{}) do
{:ok, order} =
attrs
|> Enum.into(%{
total_price: "120.5",
user_uuid: "7488a646-e31f-11e4-aace-600308960662"
})
|> Bright.Orders.create_order()
order
end
@doc """
Generate a line_item.
"""
def line_item_fixture(attrs \\ %{}) do
{:ok, line_item} =
attrs
|> Enum.into(%{
price: "120.5",
quantity: 42
})
|> Bright.Orders.create_line_item()
line_item
end
end

View File

@ -1,42 +0,0 @@
defmodule Bright.ShoppingCartFixtures do
@moduledoc """
This module defines test helpers for creating
entities via the `Bright.ShoppingCart` context.
"""
@doc """
Generate a unique cart user_uuid.
"""
def unique_cart_user_uuid do
raise "implement the logic to generate a unique cart user_uuid"
end
@doc """
Generate a cart.
"""
def cart_fixture(attrs \\ %{}) do
{:ok, cart} =
attrs
|> Enum.into(%{
user_uuid: unique_cart_user_uuid()
})
|> Bright.ShoppingCart.create_cart()
cart
end
@doc """
Generate a cart_item.
"""
def cart_item_fixture(attrs \\ %{}) do
{:ok, cart_item} =
attrs
|> Enum.into(%{
price_when_carted: "120.5",
quantity: 42
})
|> Bright.ShoppingCart.create_cart_item()
cart_item
end
end

View File

@ -34,10 +34,14 @@ defmodule Bright.StreamsFixtures do
s3_cdn_url: "some s3_cdn_url",
s3_key: "some s3_key",
s3_upload_id: "some s3_upload_id",
torrent: "some torrent"
torrent: "some torrent",
playlist_url: "some playlist_url",
thumbnail_url: "some thumbnail_url"
})
|> Bright.Streams.create_vod()
vod
end
end