diff --git a/.credo.exs b/.credo.exs index a73f6562c..daece9f67 100644 --- a/.credo.exs +++ b/.credo.exs @@ -126,7 +126,7 @@ ## Refactoring Opportunities # {Credo.Check.Refactor.CondStatements, []}, - {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.CyclomaticComplexity, [max_complexity: 15]}, {Credo.Check.Refactor.FunctionArity, []}, {Credo.Check.Refactor.LongQuoteBlocks, []}, {Credo.Check.Refactor.MapInto, false}, diff --git a/lib/ae_mdw/activities.ex b/lib/ae_mdw/activities.ex index 8ec39a781..9ccde965e 100644 --- a/lib/ae_mdw/activities.ex +++ b/lib/ae_mdw/activities.ex @@ -111,6 +111,12 @@ defmodule AeMdw.Activities do DbUtil.last_gen_to_txi(state, last_gen)} } + {:txi, first_txi..last_txi//_step} -> + { + {DbUtil.txi_to_gen(state, first_txi), DbUtil.txi_to_gen(state, last_txi)}, + {first_txi, last_txi} + } + nil -> {nil, nil} end diff --git a/lib/ae_mdw/txs.ex b/lib/ae_mdw/txs.ex index 16846b621..fba5d8ae7 100644 --- a/lib/ae_mdw/txs.ex +++ b/lib/ae_mdw/txs.ex @@ -557,6 +557,20 @@ defmodule AeMdw.Txs do @spec fetch(State.t(), txi() | tx_hash(), opts()) :: {:ok, tx()} | {:error, Error.t()} def fetch(state, tx_hash, opts) when is_binary(tx_hash) do + with {:ok, tx} <- tx_hash_to_tx(state, tx_hash) do + {:ok, render(state, tx, opts)} + end + end + + def fetch(state, txi, opts) do + case State.get(state, @table, txi) do + {:ok, tx} -> {:ok, render(state, tx, opts)} + :not_found -> {:error, ErrInput.NotFound.exception(value: txi)} + end + end + + @spec tx_hash_to_tx(State.t(), binary()) :: {:ok, Model.tx()} | {:error, Error.t()} + def tx_hash_to_tx(state, tx_hash) do encoded_tx_hash = :aeser_api_encoder.encode(:tx_hash, tx_hash) with mb_hash when is_binary(mb_hash) <- :aec_db.find_tx_location(tx_hash), @@ -567,7 +581,7 @@ defmodule AeMdw.Txs do |> Enum.find_value( {:error, ErrInput.NotFound.exception(value: encoded_tx_hash)}, fn - Model.tx(id: ^tx_hash) = tx -> {:ok, render(state, tx, opts)} + Model.tx(id: ^tx_hash) = tx -> {:ok, tx} _tx -> nil end ) @@ -577,13 +591,6 @@ defmodule AeMdw.Txs do end end - def fetch(state, txi, opts) do - case State.get(state, @table, txi) do - {:ok, tx} -> {:ok, render(state, tx, opts)} - :not_found -> {:error, ErrInput.NotFound.exception(value: txi)} - end - end - defp render(state, tx, opts) do if Keyword.get(opts, :render_v3?, false) do render_v3(state, tx) diff --git a/lib/ae_mdw/validate.ex b/lib/ae_mdw/validate.ex index dbcff75f2..dd84e2461 100644 --- a/lib/ae_mdw/validate.ex +++ b/lib/ae_mdw/validate.ex @@ -10,7 +10,7 @@ defmodule AeMdw.Validate do @typep pubkey :: AE.Db.pubkey() @typep hash_str :: String.t() - @typep hash_type :: :micro_block_hash | :key_block_hash + @typep hash_type :: :micro_block_hash | :key_block_hash | :tx_hash @typep hash :: AE.Db.hash() @typep id :: String.t() | {:id, atom(), pubkey()} | Names.raw_data_pointer() @typep tx_type :: AE.tx_type() @@ -18,10 +18,10 @@ defmodule AeMdw.Validate do @typep tx_field :: atom() @type block_index :: AeMdw.Blocks.block_index() - @spec hash(hash_str(), hash_type()) :: {:ok, hash()} | {:error, {ErrInput.Hash, binary()}} + @spec hash(hash_str(), hash_type()) :: {:ok, hash()} | {:error, Error.t()} def hash(hash_str, type) do with {:error, :invalid_encoding} <- Enc.safe_decode(type, hash_str) do - {:error, {ErrInput.Hash, hash_str}} + {:error, ErrInput.Hash.exception(value: hash_str)} end end diff --git a/lib/ae_mdw_web/plugs/paginated_plug.ex b/lib/ae_mdw_web/plugs/paginated_plug.ex index 664fe9ca8..fc4d0f5ed 100644 --- a/lib/ae_mdw_web/plugs/paginated_plug.ex +++ b/lib/ae_mdw_web/plugs/paginated_plug.ex @@ -3,11 +3,16 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do import Plug.Conn - alias AeMdw.Db.State + alias AeMdw.Db.Model + alias AeMdw.Error.Input, as: ErrInput alias AeMdw.Db.Util, as: DbUtil + alias AeMdw.Txs + alias AeMdw.Validate alias Phoenix.Controller alias Plug.Conn + require Model + @typep opt() :: {:order_by, [atom()]} | {:txi_scope?, boolean()} @@ -18,7 +23,8 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do "gen" => :gen, "txi" => :txi, "time" => :time, - "epoch" => :epoch + "epoch" => :epoch, + "transaction" => :tx } @scope_types_keys Map.keys(@scope_types) @@ -57,27 +63,32 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do |> assign(:offset, {limit, page}) |> clean_query() else - {:error, error_msg} -> + {:error, %ErrInput{message: message}} -> conn |> put_status(:bad_request) - |> Controller.json(%{"error" => error_msg}) + |> Controller.json(%{"error" => message}) |> halt() end end def call(conn, _opts), do: conn - defp extract_direction_and_scope(%{"range_or_dir" => "forward"}, _txi_scope?, _state), - do: {:ok, :forward, @default_scope} - - defp extract_direction_and_scope(%{"range_or_dir" => "backward"}, _txi_scope?, _state), - do: {:ok, :backward, @default_scope} - - defp extract_direction_and_scope(%{"range_or_dir" => range} = params, txi_scope?, state) do - params - |> Map.delete("range_or_dir") - |> Map.put("range", range) - |> extract_direction_and_scope(txi_scope?, state) + defp extract_direction_and_scope( + %{"scope" => "transaction:" <> transaction_scope} = params, + _txi_scope, + state + ) do + with tx_hashes when length(tx_hashes) > 0 and length(tx_hashes) <= 2 <- + String.split(transaction_scope, "-"), + {:ok, txis} <- tx_hashes_to_txis(tx_hashes, state) do + case txis do + [from, to] -> generate_range(state, :txi, from, to, params) + [single] -> generate_range(state, :txi, single, single, params) + end + else + {:error, reason} -> {:error, reason} + _invalid_scope -> {:error, ErrInput.Scope.exception(value: transaction_scope)} + end end defp extract_direction_and_scope( @@ -88,29 +99,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do when scope_type in @scope_types_keys do scope_type = Map.fetch!(@scope_types, scope_type) - range - |> extract_range() - |> case do - {:ok, first, last} when first < last -> - {:forward, generate_range(state, scope_type, first, last)} - - {:ok, first, last} when first > last -> - {:backward, generate_range(state, scope_type, last, first)} - - {:ok, first, last} -> - if Map.get(params, "direction", "backward") == "forward" do - {:forward, generate_range(state, scope_type, last, first)} - else - {:backward, generate_range(state, scope_type, last, first)} - end - - {:error, reason} -> - {nil, {:error, reason}} - end - |> case do - {_direction, {:error, reason}} -> {:error, reason} - {direction, range} -> {:ok, direction, range} - end + extract_range(state, scope_type, range, params) end defp extract_direction_and_scope( @@ -118,12 +107,12 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do _txi_scope? = false, state ) - when scope_type in ["gen", "time", "epoch"] do + when scope_type in ["gen", "time", "epoch", "transaction"] do extract_direction_and_scope(params, true, state) end defp extract_direction_and_scope(%{"scope_type" => scope_type}, _txi_scope?, _state), - do: {:error, "invalid scope: #{scope_type}"} + do: {:error, ErrInput.Scope.exception(value: scope_type)} defp extract_direction_and_scope(%{"range" => _range} = params, txi_scope?, state), do: extract_direction_and_scope(Map.put(params, "scope_type", "gen"), txi_scope?, state) @@ -137,7 +126,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do |> extract_direction_and_scope(txi_scope?, state) _invalid_scope -> - {:error, "invalid scope: #{scope}"} + {:error, ErrInput.Scope.exception(value: scope)} end end @@ -148,40 +137,87 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do do: {:ok, :backward, @default_scope} defp extract_direction_and_scope(%{"direction" => direction}, _txi_scope?, _state), - do: {:error, "invalid direction: #{direction}"} + do: {:error, ErrInput.Query.exception(value: "invalid direction `#{direction}`")} defp extract_direction_and_scope(_params, _txi_scope?, _state), do: {:ok, :backward, @default_scope} - defp extract_range(range) when is_binary(range) do + defp extract_range(state, scope_type, range, params) when is_binary(range) do case String.split(range, "-") do [from, to] -> case {Integer.parse(from), Integer.parse(to)} do - {{from, ""}, {to, ""}} when from >= 0 and to >= 0 -> {:ok, from, to} - {_from_err, _to_err} -> {:error, "invalid range: #{range}"} + {{from, ""}, {to, ""}} when from >= 0 and to >= 0 -> + generate_range(state, scope_type, from, to, params) + + {_from_err, _to_err} -> + {:error, ErrInput.Scope.exception(value: range)} end [single] -> case Integer.parse(single) do - {single, ""} when single >= 0 -> {:ok, single, single} - _single_err -> {:error, "invalid range: #{range}"} + {single, ""} when single >= 0 -> + generate_range(state, scope_type, single, single, params) + + _single_err -> + {:error, ErrInput.Scope.exception(value: range)} end _splitted_range -> - {:error, "invalid range: #{range}"} + {:error, ErrInput.Scope.exception(value: range)} + end + end + + defp extract_range(_state, _scope_type, range, _params), + do: {:error, ErrInput.Scope.exception(value: "invalid range: #{inspect(range)}")} + + defp generate_range(state, :time, first, last, params) do + with {_first, {:ok, first_parsed}} <- {first, DateTime.from_unix(first)}, + {_last, {:ok, last_parsed}} <- {last, DateTime.from_unix(last)} do + {first_txi, last_txi} = + DbUtil.time_to_txi( + state, + DateTime.to_unix(first_parsed, :millisecond), + DateTime.to_unix(last_parsed, :millisecond) + ) + + generate_range(state, :txi, first_txi, last_txi, params) + else + {invalid_unix_time, {:error, _reason}} -> + {:error, ErrInput.Scope.exception(value: "invalid unix time `#{invalid_unix_time}`")} end end - defp extract_range(range), do: {:error, "invalid range: #{range}"} + defp generate_range(_state, scope_type, first, last, _params) when first < last do + {:ok, :forward, {scope_type, first..last}} + end + + defp generate_range(_state, scope_type, first, last, _params) when last < first do + {:ok, :backward, {scope_type, last..first}} + end + + defp generate_range(_state, scope_type, first, last, params) do + if Map.get(params, "direction", "backward") == "forward" do + {:ok, :forward, {scope_type, last..first}} + else + {:ok, :backward, {scope_type, last..first}} + end + end defp extract_limit(params, max_limit) do limit_bin = Map.get(params, "limit", "#{@default_limit}") case Integer.parse(limit_bin) do - {limit, ""} when limit <= max_limit and limit > 0 -> {:ok, limit} - {limit, ""} when limit > max_limit -> {:error, "limit too large: #{limit}"} - {_limit, _rest} -> {:error, "invalid limit: #{limit_bin}"} - :error -> {:error, "invalid limit: #{limit_bin}"} + {limit, ""} when limit <= max_limit and limit > 0 -> + {:ok, limit} + + {limit, ""} when limit > max_limit -> + {:error, ErrInput.Query.exception(value: "limit too large `#{limit}`")} + + {_limit, _rest} -> + {:error, ErrInput.Query.exception(value: "invalid limit `#{limit_bin}`")} + + :error -> + {:error, ErrInput.Query.exception(value: "invalid limit `#{limit_bin}`")} end end @@ -195,7 +231,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do {valid_orders, order_by} -> case Enum.find(valid_orders, &(Atom.to_string(&1) == order_by)) do - nil -> {:error, "invalid query: by=#{order_by}"} + nil -> {:error, ErrInput.Query.exception(value: "by=#{order_by}")} valid_order_by -> {:ok, valid_order_by} end end @@ -206,7 +242,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do defp extract_page(%{"page" => page}) do case Integer.parse(page) do {page, ""} -> {:ok, page} - _err_or_invalid -> {:error, "invalid_page: #{page}"} + _err_or_invalid -> {:error, ErrInput.Query.exception(value: "invalid_page `#{page}`")} end end @@ -219,7 +255,10 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do tx_hash? = Map.get(params, "tx_hash", "false") != "false" if expand? and tx_hash? do - {:error, "either `tx_hash` or `expand` parameters should be used, but not both."} + {:error, + ErrInput.Query.exception( + value: "either `tx_hash` or `expand` parameters should be used, but not both." + )} else {:ok, [ @@ -230,27 +269,15 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do end end - @spec generate_range(State.t(), atom(), pos_integer(), pos_integer()) :: - {atom(), Range.t()} | {:error, atom()} - defp generate_range(state, :time, first, last) do - with {_first, {:ok, first_parsed}} <- {first, DateTime.from_unix(first)}, - {_last, {:ok, last_parsed}} <- {last, DateTime.from_unix(last)} do - {first_txi, last_txi} = - DbUtil.time_to_txi( - state, - DateTime.to_unix(first_parsed, :millisecond), - DateTime.to_unix(last_parsed, :millisecond) - ) - - generate_range(state, :txi, first_txi, last_txi) - else - {invalid_unix_time, {:error, _reason}} -> - {:error, "invalid unix time: #{invalid_unix_time}"} - end - end - - defp generate_range(_state, scope_type, first, last) do - {scope_type, first..last} + defp tx_hashes_to_txis(tx_hashes, state) do + Enum.reduce_while(tx_hashes, {:ok, []}, fn tx_hash, {:ok, txis} -> + with {:ok, tx_hash} <- Validate.hash(tx_hash, :tx_hash), + {:ok, Model.tx(index: txi)} <- Txs.tx_hash_to_tx(state, tx_hash) do + {:cont, {:ok, txis ++ [txi]}} + else + {:error, reason} -> {:halt, {:error, reason}} + end + end) end defp clean_query(%Conn{query_params: query_params} = conn) do diff --git a/test/ae_mdw_web/controllers/activities_controller_test.exs b/test/ae_mdw_web/controllers/activities_controller_test.exs index 9e295a6ef..ad0cdcdd1 100644 --- a/test/ae_mdw_web/controllers/activities_controller_test.exs +++ b/test/ae_mdw_web/controllers/activities_controller_test.exs @@ -11,6 +11,7 @@ defmodule AeMdwWeb.ActivitiesControllerTest do alias AeMdw.Db.Origin alias AeMdw.Node.Db alias AeMdw.TestSamples, as: TS + alias AeMdw.Txs import Mock @@ -901,6 +902,102 @@ defmodule AeMdwWeb.ActivitiesControllerTest do end end + test "when it has both gen-based and tx-based events and scoping via tx", %{conn: conn} do + account_pk = TS.address(0) + account = Enc.encode(:account_pubkey, account_pk) + height1 = 397 + height2 = 398 + height3 = 399 + txi1 = 123 + kb_hash = TS.key_block_hash(0) + txi2 = 456 + txi3 = 789 + tx1_hash = TS.tx_hash(0) + tx2_hash = TS.tx_hash(1) + encoded_tx1_hash = Enc.encode(:tx_hash, tx1_hash) + encoded_tx2_hash = Enc.encode(:tx_hash, tx2_hash) + kb_hash1 = TS.key_block_hash(0) + kb_hash2 = TS.key_block_hash(1) + mb_hash1 = TS.key_block_hash(0) + mb_hash2 = TS.key_block_hash(1) + contract_pk = <<100::256>> + meta_info_aex9 = {"AE9Name", "AEXSymbol", 10} + + store = + empty_store() + |> Store.put( + Model.TargetKindIntTransferTx, + Model.target_kind_int_transfer_tx(index: {account_pk, "reward_dev", {height2, -1}, -1}) + ) + |> Store.put( + Model.IntTransferTx, + Model.int_transfer_tx( + index: {{height2, -1}, "reward_dev", account_pk, -1}, + amount: 30 + ) + ) + |> Store.put( + Model.Block, + Model.block(index: {height2, -1}, hash: kb_hash, tx_index: txi2) + ) + |> Store.put( + Model.AexnTransfer, + Model.aexn_transfer( + index: {:aex9, account_pk, txi1, 1, nil, 1}, + contract_pk: contract_pk + ) + ) + |> Store.put(Model.Tx, Model.tx(index: txi1, block_index: {height1, 0}, id: tx1_hash)) + |> Store.put( + Model.AexnTransfer, + Model.aexn_transfer( + index: {:aex9, account_pk, txi3, 2, nil, 2}, + contract_pk: contract_pk + ) + ) + |> Store.put(Model.Tx, Model.tx(index: txi3, block_index: {height3, 0}, id: tx2_hash)) + |> Store.put(Model.Block, Model.block(index: {height1, -1}, hash: kb_hash1)) + |> Store.put(Model.Block, Model.block(index: {height1, 0}, hash: mb_hash1)) + |> Store.put(Model.Block, Model.block(index: {height3, -1}, hash: kb_hash2)) + |> Store.put(Model.Block, Model.block(index: {height3, 0}, hash: mb_hash2)) + |> Store.put( + Model.AexnContract, + Model.aexn_contract(index: {:aex9, contract_pk}, meta_info: meta_info_aex9) + ) + + with_mocks [ + {Db, [:passthrough], + [ + get_block_time: fn _block_hash -> + 456 + end + ]}, + {Txs, [:passthrough], + [ + tx_hash_to_tx: fn + _state, ^tx1_hash -> {:ok, Model.tx(index: txi1)} + _state, ^tx2_hash -> {:ok, Model.tx(index: txi2)} + end + ]} + ] do + assert %{ + "prev" => nil, + "data" => [activity1, activity2], + "next" => nil + } = + conn + |> with_store(store) + |> get("/v3/accounts/#{account}/activities", + direction: "forward", + scope: "transaction:#{encoded_tx1_hash}-#{encoded_tx2_hash}" + ) + |> json_response(200) + + assert %{"height" => ^height1, "type" => "Aex9TransferEvent"} = activity1 + assert %{"height" => ^height2, "type" => "InternalTransferEvent"} = activity2 + end + end + test "when it has both gen-based and tx-based int transfers", %{conn: conn} do account_pk = TS.address(0) account = Enc.encode(:account_pubkey, account_pk) diff --git a/test/ae_mdw_web/controllers/name_controller_test.exs b/test/ae_mdw_web/controllers/name_controller_test.exs index ce1f81fcb..9aae452c8 100644 --- a/test/ae_mdw_web/controllers/name_controller_test.exs +++ b/test/ae_mdw_web/controllers/name_controller_test.exs @@ -334,7 +334,7 @@ defmodule AeMdwWeb.NameControllerTest do test "renders error when parameter direction is invalid", %{conn: conn} do by = "name" direction = "invalid_direction" - error = "invalid direction: #{direction}" + error = "invalid query: invalid direction `#{direction}`" assert %{"error" => ^error} = conn @@ -713,7 +713,7 @@ defmodule AeMdwWeb.NameControllerTest do test "renders error when parameter direction is invalid", %{conn: conn} do by = "name" direction = "invalid_direction" - error = "invalid direction: #{direction}" + error = "invalid query: invalid direction `#{direction}`" assert %{"error" => ^error} = conn @@ -1305,7 +1305,7 @@ defmodule AeMdwWeb.NameControllerTest do test "renders error when parameter direction is invalid", %{conn: conn} do by = "name" direction = "invalid_direction" - error = "invalid direction: #{direction}" + error = "invalid query: invalid direction `#{direction}`" assert %{"error" => ^error} = conn @@ -1701,7 +1701,7 @@ defmodule AeMdwWeb.NameControllerTest do test "renders error when parameter direction is invalid", %{conn: conn} do by = "name" direction = "invalid_direction" - error = "invalid direction: #{direction}" + error = "invalid query: invalid direction `#{direction}`" assert %{"error" => ^error} = conn |> get("/v3/names?by=#{by}&direction=#{direction}") |> json_response(400) diff --git a/test/ae_mdw_web/controllers/oracle_controller_test.exs b/test/ae_mdw_web/controllers/oracle_controller_test.exs index 882c6a860..372036969 100644 --- a/test/ae_mdw_web/controllers/oracle_controller_test.exs +++ b/test/ae_mdw_web/controllers/oracle_controller_test.exs @@ -384,7 +384,10 @@ defmodule AeMdwWeb.OracleControllerTest do end test "when both tx_hash and expand is sent, it displays error", %{conn: conn} do - assert %{"error" => "either `tx_hash` or `expand` parameters should be used, but not both."} = + assert %{ + "error" => + "invalid query: either `tx_hash` or `expand` parameters should be used, but not both." + } = conn |> get("/v2/oracles", tx_hash: "true", expand: "true") |> json_response(400) diff --git a/test/ae_mdw_web/controllers/stats_controller_test.exs b/test/ae_mdw_web/controllers/stats_controller_test.exs index 829f96067..a2f7d4d2f 100644 --- a/test/ae_mdw_web/controllers/stats_controller_test.exs +++ b/test/ae_mdw_web/controllers/stats_controller_test.exs @@ -1084,7 +1084,7 @@ defmodule AeMdwWeb.StatsControllerTest do |> get("/v3/stats/blocks", limit: 301) |> json_response(200) - assert %{"error" => "limit too large: 1001"} = + assert %{"error" => "invalid query: limit too large `1001`"} = conn |> get("/v3/stats/blocks", limit: 1001) |> json_response(400) diff --git a/test/ae_mdw_web/controllers/transfer_controller_test.exs b/test/ae_mdw_web/controllers/transfer_controller_test.exs index 503d706da..85b767aaa 100644 --- a/test/ae_mdw_web/controllers/transfer_controller_test.exs +++ b/test/ae_mdw_web/controllers/transfer_controller_test.exs @@ -100,7 +100,7 @@ defmodule AeMdwWeb.TransferControllerTest do test "renders error when the range is invalid", %{conn: conn} do range = "invalid" - error_msg = "invalid range: #{range}" + error_msg = "invalid scope: #{range}" conn = get(conn, "/v3/transfers", scope: "gen:#{range}") assert %{"error" => ^error_msg} = json_response(conn, 400) diff --git a/test/ae_mdw_web/plugs/paginated_plug_test.exs b/test/ae_mdw_web/plugs/paginated_plug_test.exs index a2e95c831..df72e2e89 100644 --- a/test/ae_mdw_web/plugs/paginated_plug_test.exs +++ b/test/ae_mdw_web/plugs/paginated_plug_test.exs @@ -26,7 +26,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlugTest do |> PaginatedPlug.call([]) |> get_assigns() - assert %{"error" => "invalid direction: foo"} = + assert %{"error" => "invalid query: invalid direction `foo`"} = conn |> with_store(store) |> put_query(%{"limit" => "20", "direction" => "foo"}) @@ -40,7 +40,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlugTest do |> PaginatedPlug.call([]) |> get_assigns() - assert %{"error" => "invalid limit: 0"} = + assert %{"error" => "invalid query: invalid limit `0`"} = conn |> with_store(store) |> put_query(%{"limit" => "0"}) @@ -117,7 +117,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlugTest do |> PaginatedPlug.call([]) |> get_assigns() - assert %{"error" => "invalid unix time: 10000000000000"} = + assert %{"error" => "invalid scope: invalid unix time `10000000000000`"} = conn |> with_store(store) |> put_query(%{ @@ -134,7 +134,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlugTest do |> PaginatedPlug.call([]) |> json_response(400) - assert %{"error" => "invalid range: asdf"} = + assert %{"error" => "invalid scope: asdf"} = conn |> with_store(store) |> put_query(%{"range" => "asdf"}) @@ -147,6 +147,13 @@ defmodule AeMdwWeb.Plugs.PaginatedPlugTest do |> put_query(%{"range" => "10-20", "scope_type" => "foo"}) |> PaginatedPlug.call([]) |> json_response(400) + + assert %{"error" => "invalid scope: asd-asd-asd"} = + conn + |> with_store(store) + |> put_query(%{"scope" => "transaction:asd-asd-asd"}) + |> PaginatedPlug.call([]) + |> json_response(400) end test "it ignores query_params starting with _", %{conn: conn} do diff --git a/test/integration/ae_mdw_web/controllers/aex9_controller_test.exs b/test/integration/ae_mdw_web/controllers/aex9_controller_test.exs index 9c498dbfc..71e3a741e 100644 --- a/test/integration/ae_mdw_web/controllers/aex9_controller_test.exs +++ b/test/integration/ae_mdw_web/controllers/aex9_controller_test.exs @@ -15,7 +15,6 @@ defmodule Integration.AeMdwWeb.Aex9ControllerTest do @big_balance_contract_id1 "ct_BwJcRRa7jTAvkpzc2D16tJzHMGCJurtJMUBtyyfGi2QjPuMVv" @big_balance_contract_id2 "ct_uGk1rkSdccPKXLzS259vdrJGTWAY9sfgVYspv6QYomxvWZWBM" - @big_balance_contract_id3 "ct_M9yohHgcLjhpp1Z8SaA1UTmRMQzR4FWjJHajGga8KBoZTEPwC" @default_limit 10