Skip to content

Commit be4a2df

Browse files
committed
Add tests for multi error cases
1 parent 0dbe0d9 commit be4a2df

File tree

7 files changed

+109
-12
lines changed

7 files changed

+109
-12
lines changed

lib/upload.ex

+5-8
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ defmodule Upload do
9898
|> Upload.Multi.download_and_insert_variant(original_blob, variant, transform_fn)
9999
|> repo.transaction()
100100
|> case do
101-
{:ok, multi_result} -> Map.fetch!(multi_result, "download_and_insert_#{variant}")
101+
{:ok, multi_result} -> {:ok, Map.fetch!(multi_result, "download_and_insert_#{variant}")}
102102
{:error, error} -> {:error, error}
103103
end
104104
end
@@ -113,7 +113,7 @@ defmodule Upload do
113113
{:ok, [%Blob{...}, %Blob{...}]}
114114
"""
115115
@spec create_multiple_variants(Blob.t(), [variant_id()], any()) ::
116-
{:ok, [Blob.t()]} | {:error, any()}
116+
{:ok, [Blob.t()]} | {:error, String.t(), any()}
117117
def create_multiple_variants(original_blob, variants, transform_fn)
118118
when is_function(transform_fn, 3) do
119119
variants = Enum.map(variants, &to_string/1)
@@ -129,13 +129,10 @@ defmodule Upload do
129129
|> repo.transaction()
130130
|> case do
131131
{:ok, multi_result} ->
132-
{:ok,
133-
multi_result
134-
|> Map.values()
135-
|> Enum.map(fn {:ok, value} -> value end)}
132+
{:ok, Map.values(multi_result)}
136133

137-
{:error, error} ->
138-
{:error, error}
134+
{:error, stage, error, _} ->
135+
{:error, stage, error}
139136
end
140137
end
141138

lib/upload/errors.ex

+9
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,12 @@ defmodule Upload.RandomFileError do
66
"Failed to create temporary file: #{inspect(reason)}"
77
end
88
end
9+
10+
defmodule Upload.DownloadError do
11+
defexception [:reason, :path, :key]
12+
13+
@impl true
14+
def message(%{reason: reason, path: path, key: key}) do
15+
"Failed to download '#{key}' to '#{path}': #{inspect(reason)}"
16+
end
17+
end

lib/upload/multi.ex

+17-4
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,15 @@ defmodule Upload.Multi do
7676
def download_and_insert_variant(multi, original_blob, variant, transform_fn) do
7777
Multi.run(multi, "download_and_insert_#{variant}", fn repo, _ ->
7878
with {:ok, blob_path} <- create_random_file(),
79-
:ok <- Upload.Storage.download(original_blob.key, blob_path),
79+
:ok <- download_file(original_blob.key, blob_path),
8080
{:ok, variant_path} <- create_random_file(),
8181
:ok <- transform_fn.(blob_path, variant_path, variant),
8282
:ok <- cleanup(blob_path),
8383
{:ok, blob} <- insert_variant(repo, original_blob, variant, variant_path),
8484
:ok <- cleanup(variant_path) do
8585
{:ok, blob}
86+
else
87+
{:error, reason} -> {:error, reason}
8688
end
8789
end)
8890
end
@@ -105,7 +107,7 @@ defmodule Upload.Multi do
105107

106108
changeset = Blob.changeset(%Blob{}, params)
107109

108-
{:ok, repo.insert(changeset)}
110+
repo.insert(changeset)
109111
end
110112

111113
defp variant_filename(original_blob, variant) do
@@ -123,8 +125,19 @@ defmodule Upload.Multi do
123125
end
124126

125127
defp cleanup(path) do
126-
with {:error, reason} <- File.rm(path) do
127-
%File.Error{path: path, reason: reason, action: "remove temporary file"}
128+
case File.rm(path) do
129+
:ok ->
130+
:ok
131+
132+
{:error, reason} ->
133+
{:error, %File.Error{path: path, reason: reason, action: "remove temporary file"}}
134+
end
135+
end
136+
137+
defp download_file(key, path) do
138+
case Upload.Storage.download(key, path) do
139+
:ok -> :ok
140+
{:error, reason} -> {:error, %Upload.DownloadError{reason: reason, key: key, path: path}}
128141
end
129142
end
130143
end

mix.exs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ defmodule Upload.Mixfile do
5656
{:plug, "~> 1.13"},
5757
{:postgrex, ">= 0.0.0"},
5858
{:sweet_xml, ">= 0.0.0"},
59+
{:mock, "~> 0.3"},
5960

6061
# Test dependencies for this package
6162
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},

mix.lock

+2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
3232
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
3333
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
34+
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
3435
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
3536
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
3637
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
3738
"mix_test_watch": {:hex, :mix_test_watch, "1.2.0", "1f9acd9e1104f62f280e30fc2243ae5e6d8ddc2f7f4dc9bceb454b9a41c82b42", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "278dc955c20b3fb9a3168b5c2493c2e5cffad133548d307e0a50c7f2cfbf34f6"},
39+
"mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"},
3840
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
3941
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
4042
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},

test/support/data_case.ex

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ defmodule Upload.DataCase do
1010
using do
1111
quote do
1212
import Upload.DataCase
13+
import Mock
1314
end
1415
end
1516

test/upload_test.exs

+74
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,80 @@ defmodule UploadTest do
7878
assert small_avif_variant.key == "uploads/users/avatars/123/variant/small_avif.avif"
7979
assert small_avif_variant.key in list_uploaded_keys()
8080
end
81+
82+
test "returns an error when a temp file cannot be created" do
83+
changeset = change_person(%{avatar: @upload})
84+
85+
assert {:ok, %{person: person}} = upload_person(changeset)
86+
assert person.avatar
87+
88+
with_mock(Plug.Upload, random_file: fn _ -> {:error, :boom} end) do
89+
{:error, "download_and_insert_small", %Upload.RandomFileError{reason: {:error, :boom}}} =
90+
Upload.create_multiple_variants(
91+
person.avatar,
92+
[
93+
"small"
94+
],
95+
&transform_image/3
96+
)
97+
end
98+
end
99+
100+
test "returns an error when the original file cannot be downloaded" do
101+
changeset = change_person(%{avatar: @upload})
102+
103+
assert {:ok, %{person: person}} = upload_person(changeset)
104+
assert person.avatar
105+
106+
with_mock(Upload.Storage, download: fn _key, _ -> {:error, :boom} end) do
107+
{:error, "download_and_insert_small",
108+
%Upload.DownloadError{reason: :boom, key: "uploads/users/avatars/123.jpg"}} =
109+
Upload.create_multiple_variants(
110+
person.avatar,
111+
[
112+
"small"
113+
],
114+
&transform_image/3
115+
)
116+
end
117+
end
118+
119+
test "returns an error when a temp file cannot be deleted" do
120+
changeset = change_person(%{avatar: @upload})
121+
122+
assert {:ok, %{person: person}} = upload_person(changeset)
123+
assert person.avatar
124+
125+
with_mock(File, [:passthrough], rm: fn _path -> {:error, :enoent} end) do
126+
{:error, "download_and_insert_small",
127+
%File.Error{reason: :enoent, action: "remove temporary file"}} =
128+
Upload.create_multiple_variants(
129+
person.avatar,
130+
[
131+
"small"
132+
],
133+
fn _, _, _ -> :ok end
134+
)
135+
end
136+
end
137+
138+
test "returns an error when attempting to insert a bad key caused by a variant name" do
139+
changeset = change_person(%{avatar: @upload})
140+
141+
assert {:ok, %{person: person}} = upload_person(changeset)
142+
assert person.avatar
143+
144+
{:error, "download_and_insert_.", changeset} =
145+
Upload.create_multiple_variants(
146+
person.avatar,
147+
[
148+
"."
149+
],
150+
fn _, _, _ -> :ok end
151+
)
152+
153+
assert errors_on(changeset)[:key] == ["has invalid format"]
154+
end
81155
end
82156

83157
describe "put_access_control_list/2" do

0 commit comments

Comments
 (0)