Mix format, gettext, reorder function alphabetically, and bump coverage

pull/156/head
Tim Mecklem 7 years ago
parent 6549dd96d5
commit 82572acbe4
  1. 93
      apps/explorer/lib/explorer/chain.ex
  2. 3
      apps/explorer_web/lib/explorer_web/router.ex
  3. 1
      apps/explorer_web/test/explorer_web/controllers/address_internal_transaction_controller_test.exs
  4. 35
      apps/explorer_web/test/explorer_web/features/pages/address_page.ex
  5. 2
      coveralls.json

@ -48,6 +48,55 @@ defmodule Explorer.Chain do
# Functions # Functions
@doc """
`t:Explorer.Chain.InternalTransaction/0`s from `address`.
This function excludes any "representative" internal transactions, where the internal transaction is a mirror of the
parent transaction's value, to and from addresses. In the case of multiple internal transactions that have the same
value, to, and from address, it excludes the internal transaction with the lowest id.
## Options
* `:direction` - if specified, will filter internal transactions by address type. If `:to` is specified, only internal
transactions where the "to" address matches will be returned. Likewise, if `:from` is specified, only internal
transactions where the "from" address matches will be returned. If :direction is omitted, internal transactions either
to or from the address will be returned.
* `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is
`:required`, and the `t:Explorer.Chain.InternalTransaction.t/0` has no associated record for that association, then
the `t:Explorer.Chain.InternalTransaction.t/0` will not be included in the page `entries`.
* `:pagination` - pagination params to pass to scrivener.
"""
def address_to_internal_transactions(%Address{id: id}, options \\ []) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
direction = Keyword.get(options, :direction)
InternalTransaction
|> join(:inner, [internal_transaction], transaction in assoc(internal_transaction, :transaction))
|> join(:left, [internal_transaction, transaction], block in assoc(transaction, :block))
|> where_address_fields_match(direction, id)
|> where(
[it],
fragment(
"""
? NOT IN (
SELECT min(it.id) FROM internal_transactions AS it
INNER JOIN transactions AS t ON t.id = it.transaction_id
WHERE it.value = t.value
AND it.from_address_id = t.from_address_id
AND it.to_address_id = t.to_address_id
GROUP BY t.id
)
""",
it.id
)
)
|> order_by([it, transaction, block], desc: block.number, desc: transaction.transaction_index, desc: it.index)
|> preload(transaction: :block)
|> join_associations(necessity_by_association)
|> Repo.all()
end
@doc """ @doc """
`t:Explorer.Chain.Transaction/0`s from `address`. `t:Explorer.Chain.Transaction/0`s from `address`.
@ -415,49 +464,6 @@ defmodule Explorer.Chain do
|> Repo.aggregate(:count, :id) |> Repo.aggregate(:count, :id)
end end
@doc """
`t:Explorer.Chain.InternalTransaction/0`s from `address`.
This function excludes any "representative" internal transactions, where the internal transaction is a mirror of the
parent transaction's value, to and from addresses. In the case of multiple internal transactions that have the same
value, to, and from address, it excludes the internal transaction with the lowest id.
## Options
* `:direction` - if specified, will filter internal transactions by address type. If `:to` is specified, only internal
transactions where the "to" address matches will be returned. Likewise, if `:from` is specified, only internal
transactions where the "from" address matches will be returned. If :direction is omitted, internal transactions either
to or from the address will be returned.
* `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is
`:required`, and the `t:Explorer.Chain.InternalTransaction.t/0` has no associated record for that association, then
the `t:Explorer.Chain.InternalTransaction.t/0` will not be included in the page `entries`.
* `:pagination` - pagination params to pass to scrivener.
"""
def address_to_internal_transactions(%Address{id: id}, options \\ []) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
direction = Keyword.get(options, :direction)
InternalTransaction
|> join(:inner, [internal_transaction], transaction in assoc(internal_transaction, :transaction))
|> join(:left, [internal_transaction, transaction], block in assoc(transaction, :block))
|> where_address_fields_match(direction, id)
|> where([it], fragment("""
? NOT IN (
SELECT min(it.id) FROM "internal_transactions" AS it
INNER JOIN "transactions" AS t ON t.id = it.transaction_id
WHERE it.value = t.value
AND it.from_address_id = t.from_address_id
AND it.to_address_id = t.to_address_id
GROUP BY t.id
)
""" , it.id))
|> order_by([it, transaction, block], desc: block.number, desc: transaction.transaction_index, desc: it.index)
|> preload(transaction: :block)
|> join_associations(necessity_by_association)
|> Repo.all()
end
@doc """ @doc """
`t:Explorer.Chain.InternalTransaction/0`s in `t:Explorer.Chain.Transaction.t/0` with `hash` `t:Explorer.Chain.InternalTransaction/0`s in `t:Explorer.Chain.Transaction.t/0` with `hash`
@ -599,7 +605,6 @@ defmodule Explorer.Chain do
defp address_id_to_transactions(address_id, named_arguments) defp address_id_to_transactions(address_id, named_arguments)
when is_integer(address_id) and is_list(named_arguments) do when is_integer(address_id) and is_list(named_arguments) do
direction = Keyword.get(named_arguments, :direction) direction = Keyword.get(named_arguments, :direction)
necessity_by_association = Keyword.get(named_arguments, :necessity_by_association, %{}) necessity_by_association = Keyword.get(named_arguments, :necessity_by_association, %{})
pagination = Keyword.get(named_arguments, :pagination, %{}) pagination = Keyword.get(named_arguments, :pagination, %{})

@ -40,8 +40,7 @@ defmodule ExplorerWeb.Router do
end end
pipeline :jasmine do pipeline :jasmine do
if Mix.env() != :prod, if Mix.env() != :prod, do: plug(Jasmine, js_files: ["js/test.js"], css_files: ["css/test.css"])
do: plug(Jasmine, js_files: ["js/test.js"], css_files: ["css/test.css"])
end end
pipeline :api do pipeline :api do

@ -23,6 +23,7 @@ defmodule ExplorerWeb.AddressInternalTransactionControllerTest do
to_internal_transaction = to_internal_transaction =
insert(:internal_transaction, transaction_id: transaction.id, to_address_id: address.id, index: 2) insert(:internal_transaction, transaction_id: transaction.id, to_address_id: address.id, index: 2)
path = address_internal_transaction_path(ExplorerWeb.Endpoint, :index, :en, address.hash) path = address_internal_transaction_path(ExplorerWeb.Endpoint, :index, :en, address.hash)
conn = get(conn, path) conn = get(conn, path)

@ -5,36 +5,33 @@ defmodule ExplorerWeb.AddressPage do
import Wallaby.Query, only: [css: 1, css: 2] import Wallaby.Query, only: [css: 1, css: 2]
alias Explorer.Chain.{Address, Transaction} alias Explorer.Chain.{Address, Transaction}
def visit_page(session, %Address{hash: address_hash}), do: visit_page(session, address_hash) def apply_filter(session, direction) do
session
|> click(css("[data-test='filter_dropdown']", text: "Filter: All"))
|> click(css("[data-test='filter_option']", text: direction))
end
def visit_page(session, address_hash) do def balance do
visit(session, "/en/addresses/#{address_hash}") css("[data-test='address_balance']")
end end
@internal_transactions_link_selector "[data-test='internal_transactions_tab_link']"
def click_internal_transactions(session) do def click_internal_transactions(session) do
click(session, css(@internal_transactions_link_selector)) click(session, css("[data-test='internal_transactions_tab_link']"))
end
def internal_transactions(count: count) do
css("[data-test='internal_transaction']", count: count)
end end
@transaction_selector "[data-test='transaction_hash']"
def transaction(%Transaction{hash: transaction_hash}), do: transaction(transaction_hash) def transaction(%Transaction{hash: transaction_hash}), do: transaction(transaction_hash)
def transaction(transaction_hash) do def transaction(transaction_hash) do
css(@transaction_selector, text: transaction_hash) css("[data-test='transaction_hash']", text: transaction_hash)
end end
@internal_transactions_selector "[data-test='internal_transaction']" def visit_page(session, %Address{hash: address_hash}), do: visit_page(session, address_hash)
def internal_transactions(count: count) do
css(@internal_transactions_selector, count: count)
end
def apply_filter(session, direction) do
session
|> click(css("[data-test='filter_dropdown']", text: "Filter: All"))
|> click(css("[data-test='filter_option']", text: direction))
end
def balance do def visit_page(session, address_hash) do
css("[data-test='address_balance']") visit(session, "/en/addresses/#{address_hash}")
end end
end end

@ -1,7 +1,7 @@
{ {
"coverage_options": { "coverage_options": {
"treat_no_relevant_lines_as_covered": true, "treat_no_relevant_lines_as_covered": true,
"minimum_coverage": 84 "minimum_coverage": 85
}, },
"terminal_options": { "terminal_options": {
"file_column_width": 120 "file_column_width": 120

Loading…
Cancel
Save