Merge pull request #871 from poanetwork/865-fill-in-holes

Fill-in skipped blocks on page render for blocks list
pull/890/merge v1.0-beta
John Stamates 6 years ago committed by GitHub
commit a9be1d4da6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 62
      apps/block_scout_web/assets/__tests__/pages/block.js
  2. 39
      apps/block_scout_web/assets/__tests__/pages/chain.js
  3. 6
      apps/block_scout_web/assets/css/components/_tile.scss
  4. 29
      apps/block_scout_web/assets/js/pages/block.js
  5. 47
      apps/block_scout_web/assets/js/pages/chain.js
  6. 31
      apps/block_scout_web/assets/js/utils.js
  7. 2
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  8. 11
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  9. 20
      apps/block_scout_web/priv/gettext/default.pot
  10. 22
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  11. 4
      apps/block_scout_web/test/block_scout_web/features/pages/address_page.ex
  12. 2
      apps/block_scout_web/test/block_scout_web/features/pages/block_list_page.ex
  13. 10
      apps/block_scout_web/test/block_scout_web/features/pages/chain_page.ex
  14. 31
      apps/block_scout_web/test/block_scout_web/features/viewing_blocks_test.exs
  15. 10
      apps/block_scout_web/test/block_scout_web/features/viewing_chain_test.exs

@ -1,6 +1,5 @@
import { reducer, initialState } from '../../js/pages/block'
test('CHANNEL_DISCONNECTED', () => {
const state = initialState
const action = {
@ -11,6 +10,61 @@ test('CHANNEL_DISCONNECTED', () => {
expect(output.channelDisconnected).toBe(true)
})
describe('PAGE_LOAD', () => {
test('page 1 loads block numbers', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
beyondPageOne: false,
blockNumbers: [2, 1]
}
const output = reducer(state, action)
expect(output.beyondPageOne).toBe(false)
expect(output.blockNumbers).toEqual([2, 1])
expect(output.skippedBlockNumbers).toEqual([])
})
test('page 2 loads block numbers', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
beyondPageOne: true,
blockNumbers: [2, 1]
}
const output = reducer(state, action)
expect(output.beyondPageOne).toBe(true)
expect(output.blockNumbers).toEqual([2, 1])
expect(output.skippedBlockNumbers).toEqual([])
})
test('page 1 with skipped blocks', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
beyondPageOne: false,
blockNumbers: [4, 1]
}
const output = reducer(state, action)
expect(output.beyondPageOne).toBe(false)
expect(output.blockNumbers).toEqual([4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([3, 2])
})
test('page 2 with skipped blocks', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
beyondPageOne: true,
blockNumbers: [4, 1]
}
const output = reducer(state, action)
expect(output.beyondPageOne).toBe(true)
expect(output.blockNumbers).toEqual([4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([3, 2])
})
})
describe('RECEIVED_NEW_BLOCK', () => {
test('receives new block', () => {
const action = {
@ -56,12 +110,12 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.newBlock).toBe('test5')
expect(output.blockNumbers).toEqual([5, 4, 3, 2])
expect(output.skippedBlockNumbers).toEqual([3, 4])
expect(output.skippedBlockNumbers).toEqual([4, 3])
})
test('replaces skipped block', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4, 3, 2, 1],
skippedBlockNumbers: [1, 3, 4]
skippedBlockNumbers: [4, 3, 1]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
@ -74,7 +128,7 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.newBlock).toBe('test3')
expect(output.blockNumbers).toEqual([5, 4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([1, 4])
expect(output.skippedBlockNumbers).toEqual([4, 1])
})
test('replaces duplicated block', () => {
const state = Object.assign({}, initialState, {

@ -1,5 +1,30 @@
import { reducer, initialState } from '../../js/pages/chain'
describe('PAGE_LOAD', () => {
test('loads block numbers', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
blockNumbers: [2, 1]
}
const output = reducer(state, action)
expect(output.blockNumbers).toEqual([2, 1])
expect(output.skippedBlockNumbers).toEqual([])
})
test('loads with skipped blocks', () => {
const state = initialState
const action = {
type: 'PAGE_LOAD',
blockNumbers: [4, 1]
}
const output = reducer(state, action)
expect(output.blockNumbers).toEqual([4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([3, 2])
})
})
test('RECEIVED_NEW_ADDRESS_COUNT', () => {
const state = Object.assign({}, initialState, {
addressCount: '1,000'
@ -54,12 +79,12 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.averageBlockTime).toEqual('5 seconds')
expect(output.newBlock).toBe('test5')
expect(output.blockNumbers).toEqual([5, 4, 3, 2])
expect(output.skippedBlockNumbers).toEqual([3, 4])
expect(output.skippedBlockNumbers).toEqual([4, 3])
})
test('replaces skipped block', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [4, 3, 2, 1],
skippedBlockNumbers: [1, 2, 3]
skippedBlockNumbers: [3, 2, 1]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
@ -74,7 +99,7 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.averageBlockTime).toEqual('5 seconds')
expect(output.newBlock).toBe('test2')
expect(output.blockNumbers).toEqual([4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([1, 3])
expect(output.skippedBlockNumbers).toEqual([3, 1])
})
test('replaces duplicated block', () => {
const state = Object.assign({}, initialState, {
@ -116,7 +141,7 @@ describe('RECEIVED_NEW_BLOCK', () => {
test('only tracks 4 blocks based on page display limit', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4, 3, 2],
skippedBlockNumbers: [2, 3, 4]
skippedBlockNumbers: [4, 3, 2]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
@ -129,12 +154,12 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.newBlock).toBe('test6')
expect(output.blockNumbers).toEqual([6, 5, 4, 3])
expect(output.skippedBlockNumbers).toEqual([3, 4])
expect(output.skippedBlockNumbers).toEqual([4, 3])
})
test('skipped blocks list replaced when another block comes in with +3 blockheight', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4, 3, 2],
skippedBlockNumbers: [2, 3, 4]
skippedBlockNumbers: [4, 3, 2]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
@ -147,7 +172,7 @@ describe('RECEIVED_NEW_BLOCK', () => {
expect(output.newBlock).toBe('test10')
expect(output.blockNumbers).toEqual([10, 9, 8, 7])
expect(output.skippedBlockNumbers).toEqual([7, 8, 9])
expect(output.skippedBlockNumbers).toEqual([9, 8, 7])
})
})

@ -17,7 +17,7 @@
&-type {
&-Block {
&-block {
border-left: 4px solid $indigo;
.tile-label {
@ -25,7 +25,7 @@
}
}
&-Uncle {
&-uncle {
border-left: 4px solid $cyan;
.tile-label {
@ -33,7 +33,7 @@
}
}
&-Reorg {
&-reorg {
border-left: 4px solid $purple;
.tile-label {

@ -4,7 +4,7 @@ import URI from 'urijs'
import humps from 'humps'
import socket from '../socket'
import { updateAllAges } from '../lib/from_now'
import { initRedux, prependWithClingBottom } from '../utils'
import { buildFullBlockList, initRedux, beforeWithClingBottom, skippedBlockListBuilder } from '../utils'
export const initialState = {
blockNumbers: [],
@ -18,9 +18,12 @@ export const initialState = {
export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD': {
const blockNumbers = buildFullBlockList(action.blockNumbers)
const skippedBlockNumbers = _.difference(blockNumbers, action.blockNumbers)
return Object.assign({}, state, {
beyondPageOne: action.beyondPageOne,
blockNumbers: action.blockNumbers
blockNumbers,
skippedBlockNumbers
})
}
case 'CHANNEL_DISCONNECTED': {
@ -43,9 +46,7 @@ export function reducer (state = initialState, action) {
} else {
let skippedBlockNumbers = state.skippedBlockNumbers.slice(0)
if (blockNumber > state.blockNumbers[0] + 1) {
for (let i = state.blockNumbers[0] + 1; i < blockNumber; i++) {
skippedBlockNumbers.push(i)
}
skippedBlockListBuilder(skippedBlockNumbers, blockNumber, state.blockNumbers[0])
}
const newBlockNumbers = _.chain([blockNumber])
.union(skippedBlockNumbers, state.blockNumbers)
@ -85,22 +86,21 @@ if ($blockListPage.length) {
},
render (state, oldState) {
const $channelDisconnected = $('[data-selector="channel-disconnected-message"]')
const $blocksList = $('[data-selector="blocks-list"]')
const skippedBlockNumbers = _.difference(state.skippedBlockNumbers, oldState.skippedBlockNumbers)
if (state.channelDisconnected) $channelDisconnected.show()
if (oldState.newBlock !== state.newBlock || (state.replaceBlock && oldState.replaceBlock !== state.replaceBlock)) {
if ((state.newBlock && oldState.newBlock !== state.newBlock) || skippedBlockNumbers.length) {
if (state.replaceBlock && oldState.replaceBlock !== state.replaceBlock) {
const $replaceBlock = $(`[data-block-number="${state.replaceBlock}"]`)
$replaceBlock.addClass('shrink-out')
setTimeout(() => $replaceBlock.replaceWith(state.newBlock), 400)
} else {
if (oldState.skippedBlockNumbers !== state.skippedBlockNumbers) {
const newSkippedBlockNumbers = _.difference(state.skippedBlockNumbers, oldState.skippedBlockNumbers)
_.map(newSkippedBlockNumbers, (skippedBlockNumber) => {
prependWithClingBottom($blocksList, placeHolderBlock(skippedBlockNumber))
if (skippedBlockNumbers.length) {
_.forEachRight(skippedBlockNumbers, (skippedBlockNumber) => {
beforeWithClingBottom($(`[data-block-number="${skippedBlockNumber - 1}"]`), placeHolderBlock(skippedBlockNumber))
})
}
prependWithClingBottom($blocksList, state.newBlock)
beforeWithClingBottom($(`[data-block-number="${state.blockNumbers[0] - 1}"]`), state.newBlock)
}
updateAllAges()
}
@ -110,11 +110,10 @@ if ($blockListPage.length) {
function placeHolderBlock (blockNumber) {
return `
<div class="my-3">
<div class="my-3" style="height: 98px;" data-selector="place-holder" data-block-number="${blockNumber}">
<div
class="tile tile-type-block d-flex align-items-center fade-up"
data-selector="place-holder"
data-block-number="${blockNumber}"
style="height: 98px;"
>
<span class="loading-spinner-small ml-1 mr-4">
<span class="loading-spinner-block-1"></span>

@ -5,7 +5,7 @@ import numeral from 'numeral'
import socket from '../socket'
import { updateAllAges } from '../lib/from_now'
import { exchangeRateChannel, formatUsdValue } from '../lib/currency'
import { batchChannel, initRedux, slideDownPrepend } from '../utils'
import { batchChannel, buildFullBlockList, initRedux, skippedBlockListBuilder, slideDownPrepend } from '../utils'
import { createMarketHistoryChart } from '../lib/market_history_chart'
const BATCH_THRESHOLD = 10
@ -28,9 +28,13 @@ export const initialState = {
export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD': {
const fullBlockNumberList = buildFullBlockList(action.blockNumbers)
const fullSkippedBlockNumberList = _.difference(fullBlockNumberList, action.blockNumbers)
const blockNumbers = fullBlockNumberList.slice(0, 4)
return Object.assign({}, state, {
blockNumbers: action.blockNumbers,
transactionCount: numeral(action.transactionCount).value()
blockNumbers,
transactionCount: numeral(action.transactionCount).value(),
skippedBlockNumbers: _.intersection(fullSkippedBlockNumberList, blockNumbers)
})
}
case 'RECEIVED_NEW_ADDRESS_COUNT': {
@ -52,21 +56,18 @@ export function reducer (state = initialState, action) {
} else {
let skippedBlockNumbers = state.skippedBlockNumbers.slice(0)
if (blockNumber > state.blockNumbers[0] + 1) {
let lastPlaceholder = state.blockNumbers[0] + 1
if (blockNumber - lastPlaceholder > 3) {
lastPlaceholder = blockNumber - 3
let oldestBlock = state.blockNumbers[0]
if (blockNumber - oldestBlock >= 3) {
skippedBlockNumbers = []
if (blockNumber - oldestBlock > 3) oldestBlock = blockNumber - 4
}
for (let i = lastPlaceholder; i < blockNumber; i++) {
skippedBlockNumbers.push(i)
}
skippedBlockListBuilder(skippedBlockNumbers, blockNumber, oldestBlock)
}
const newBlockNumbers = _.chain([blockNumber])
.union(skippedBlockNumbers, state.blockNumbers)
.orderBy([], ['desc'])
.slice(0, 4)
.value()
const newSkippedBlockNumbers = _.intersection(skippedBlockNumbers, newBlockNumbers)
return Object.assign({}, state, {
averageBlockTime: action.msg.averageBlockTime,
@ -142,6 +143,8 @@ if ($chainDetailsPage.length) {
const $marketCap = $('[data-selector="market-cap"]')
const $transactionsList = $('[data-selector="transactions-list"]')
const $transactionCount = $('[data-selector="transaction-count"]')
const newTransactions = _.difference(state.newTransactions, oldState.newTransactions)
const skippedBlockNumbers = _.difference(state.skippedBlockNumbers, oldState.skippedBlockNumbers)
if (oldState.addressCount !== state.addressCount) {
$addressCount.empty().append(state.addressCount)
@ -152,24 +155,23 @@ if ($chainDetailsPage.length) {
if (oldState.usdMarketCap !== state.usdMarketCap) {
$marketCap.empty().append(formatUsdValue(state.usdMarketCap))
}
if (state.newBlock && oldState.newBlock !== state.newBlock) {
if ((state.newBlock && oldState.newBlock !== state.newBlock) || skippedBlockNumbers.length) {
if (state.replaceBlock && oldState.replaceBlock !== state.replaceBlock) {
const $replaceBlock = $(`[data-block-number="${state.replaceBlock}"]`)
$replaceBlock.addClass('shrink-out')
setTimeout(() => $replaceBlock.replaceWith(state.newBlock), 400)
} else {
if (oldState.skippedBlockNumbers !== state.skippedBlockNumbers) {
const newSkippedBlockNumbers = _.chain(state.skippedBlockNumbers)
.difference(oldState.skippedBlockNumbers)
.intersection(state.blockNumbers)
.value()
_.map(newSkippedBlockNumbers, (skippedBlockNumber) => {
if (state.newBlock) {
$blockList.children().last().remove()
$blockList.prepend(placeHolderBlock(skippedBlockNumber))
})
$blockList.prepend(newBlockHtml(state.newBlock))
}
if (skippedBlockNumbers.length) {
const newSkippedBlockNumbers = _.intersection(skippedBlockNumbers, state.blockNumbers)
_.each(newSkippedBlockNumbers, (skippedBlockNumber) => {
$blockList.children().last().remove()
$blockList.prepend(newBlockHtml(state.newBlock))
$(`[data-block-number="${skippedBlockNumber + 1}"]`).parent().after(placeHolderBlock(skippedBlockNumber))
})
}
}
updateAllAges()
}
@ -180,7 +182,7 @@ if ($chainDetailsPage.length) {
} else {
$channelBatching.hide()
}
if (oldState.newTransactions !== state.newTransactions) {
if (newTransactions.length) {
const newTransactionsToInsert = state.newTransactions.slice(oldState.newTransactions.length)
$transactionsList
.children()
@ -190,7 +192,6 @@ if ($chainDetailsPage.length) {
updateAllAges()
}
if (oldState.availableSupply !== state.availableSupply || oldState.marketHistoryData !== state.marketHistoryData) {
chart.update(state.availableSupply, state.marketHistoryData)
}
@ -214,9 +215,9 @@ function placeHolderBlock (blockNumber) {
>
<div
class="tile tile-type-block d-flex align-items-center fade-up"
style="height: 100px;"
data-selector="place-holder"
data-block-number="${blockNumber}"
style="height: 100px;"
>
<span class="loading-spinner-small ml-1 mr-4">
<span class="loading-spinner-block-1"></span>

@ -14,6 +14,12 @@ export function batchChannel (func) {
}
}
export function buildFullBlockList (blockNumbers) {
const newestBlock = _.first(blockNumbers)
const oldestBlock = _.last(blockNumbers)
return skippedBlockListBuilder([], newestBlock + 1, oldestBlock - 1)
}
export function initRedux (reducer, { main, render, debug } = {}) {
if (!reducer) {
console.error('initRedux: You need a reducer to initialize Redux.')
@ -34,16 +40,33 @@ export function initRedux (reducer, { main, render, debug } = {}) {
if (main) main(store)
}
export function skippedBlockListBuilder (skippedBlockNumbers, newestBlock, oldestBlock) {
for (let i = newestBlock - 1; i > oldestBlock; i--) skippedBlockNumbers.push(i)
return skippedBlockNumbers
}
export function slideDownPrepend ($el, content, callback) {
const $content = $(content)
$el.prepend($content.hide())
$content.slideDown({ complete: callback })
}
export function slideDownBefore ($el, content, callback) {
const $content = $(content)
$el.before($content.hide())
$content.slideDown({ complete: callback })
}
export function prependWithClingBottom ($el, content) {
return slideDownPrepend($el, content, clingBottom($el, content))
}
export function beforeWithClingBottom ($el, content) {
return slideDownBefore($el, content, clingBottom($el, content))
}
function clingBottom ($el, content) {
function userAtTop () {
return window.scrollY < $('[data-selector="navbar"]').outerHeight()
}
if (userAtTop()) return slideDownPrepend($el, content)
if (userAtTop()) return true
let isAnimating
function setIsAnimating () {
@ -73,8 +96,10 @@ export function prependWithClingBottom ($el, content) {
$el.off('animationend animationcancel', stopClinging)
}
return slideDownPrepend($el, content, () => {
return {
function () {
$el.on('animationend animationcancel', stopClinging)
setTimeout(() => !isAnimating && stopClinging(), 100)
})
}
}
}

@ -31,7 +31,7 @@
</div>
<script>
window.localized = {
'Block Processing': '<%= gettext("Block Mined, awaiting processing...") %>',
'Block Processing': '<%= gettext("Block Mined, awaiting import...") %>',
'Less than': '<%= gettext("Less than") %>',
'Market Cap': '<%= gettext("Market Cap") %>',
'Price': '<%= gettext("Price") %>',

@ -141,17 +141,6 @@ defmodule BlockScoutWeb.AddressView do
|> Base.encode64()
end
def render_partial(%{partial: partial, address: address, contract: contract?, truncate: truncate}) do
render(
partial,
address: address,
contract: contract?,
truncate: truncate
)
end
def render_partial(text), do: text
def smart_contract_verified?(%Address{smart_contract: %SmartContract{}}), do: true
def smart_contract_verified?(%Address{smart_contract: nil}), do: false

@ -157,7 +157,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:90
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:122
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:141
#: lib/block_scout_web/views/address_view.ex:223
#: lib/block_scout_web/views/address_view.ex:212
msgid "Code"
msgstr ""
@ -423,7 +423,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:14
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:222
#: lib/block_scout_web/views/address_view.ex:211
#: lib/block_scout_web/views/transaction_view.ex:176
msgid "Internal Transactions"
msgstr ""
@ -639,7 +639,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:53
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:75
#: lib/block_scout_web/views/address_view.ex:224
#: lib/block_scout_web/views/address_view.ex:213
#: lib/block_scout_web/views/tokens/overview_view.ex:37
msgid "Read Contract"
msgstr ""
@ -839,7 +839,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:18
#: lib/block_scout_web/templates/address_validation/index.html.eex:62
#: lib/block_scout_web/templates/address_validation/index.html.eex:70
#: lib/block_scout_web/views/address_view.ex:220
#: lib/block_scout_web/views/address_view.ex:209
msgid "Tokens"
msgstr ""
@ -889,7 +889,7 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:56
#: lib/block_scout_web/templates/transaction/index.html.eex:56
#: lib/block_scout_web/views/address_view.ex:221
#: lib/block_scout_web/views/address_view.ex:210
msgid "Transactions"
msgstr ""
@ -1056,11 +1056,6 @@ msgstr ""
msgid "%{subnetwork} %{network} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:34
msgid "Block Mined, awaiting processing..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:3
msgid "%{address} - %{subnetwork} Explorer"
@ -1161,3 +1156,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23
msgid "Uncles"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:34
msgid "Block Mined, awaiting import..."
msgstr ""

@ -157,7 +157,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:90
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:122
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:141
#: lib/block_scout_web/views/address_view.ex:223
#: lib/block_scout_web/views/address_view.ex:212
msgid "Code"
msgstr ""
@ -423,7 +423,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:14
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:43
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:222
#: lib/block_scout_web/views/address_view.ex:211
#: lib/block_scout_web/views/transaction_view.ex:176
msgid "Internal Transactions"
msgstr ""
@ -639,7 +639,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:53
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:75
#: lib/block_scout_web/views/address_view.ex:224
#: lib/block_scout_web/views/address_view.ex:213
#: lib/block_scout_web/views/tokens/overview_view.ex:37
msgid "Read Contract"
msgstr ""
@ -839,7 +839,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_validation/index.html.eex:18
#: lib/block_scout_web/templates/address_validation/index.html.eex:62
#: lib/block_scout_web/templates/address_validation/index.html.eex:70
#: lib/block_scout_web/views/address_view.ex:220
#: lib/block_scout_web/views/address_view.ex:209
msgid "Tokens"
msgstr ""
@ -889,7 +889,7 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:56
#: lib/block_scout_web/templates/transaction/index.html.eex:56
#: lib/block_scout_web/views/address_view.ex:221
#: lib/block_scout_web/views/address_view.ex:210
msgid "Transactions"
msgstr ""
@ -1056,11 +1056,6 @@ msgstr ""
msgid "%{subnetwork} %{network} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:34
msgid "Block Mined, awaiting processing..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_metatags.html.eex:3
msgid "%{address} - %{subnetwork} Explorer"
@ -1136,7 +1131,7 @@ msgstr ""
msgid "%{block_type}s"
msgstr ""
#, elixir-format, fuzzy
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:13
msgid "Block Height: %{height}"
msgstr ""
@ -1161,3 +1156,8 @@ msgstr ""
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23
msgid "Uncles"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/app.html.eex:34
msgid "Block Mined, awaiting import..."
msgstr ""

@ -113,10 +113,6 @@ defmodule BlockScoutWeb.AddressPage do
css("[data-transaction-hash='#{hash}'] [data-test='address_hash_link'] [data-address-hash='#{address_hash}']")
end
def transaction_count do
css("[data-selector='transaction-count']")
end
def transaction_status(%Transaction{hash: transaction_hash}) do
css("[data-transaction-hash='#{transaction_hash}'] [data-test='transaction_status']")
end

@ -20,7 +20,7 @@ defmodule BlockScoutWeb.BlockListPage do
end
def block(%Block{number: block_number}) do
css("[data-selector='block-tile'][data-block-number='#{block_number}']")
css("[data-block-number='#{block_number}']")
end
def place_holder_blocks(count) do

@ -5,7 +5,11 @@ defmodule BlockScoutWeb.ChainPage do
import Wallaby.Query, only: [css: 1, css: 2]
alias Explorer.Chain.Transaction
alias Explorer.Chain.{Block, Transaction}
def block(%Block{number: block_number}) do
css("[data-block-number='#{block_number}']")
end
def blocks(count: count) do
css("[data-selector='chain-block']", count: count)
@ -15,6 +19,10 @@ defmodule BlockScoutWeb.ChainPage do
css("[data-test='contract-creation'] [data-address-hash='#{hash}']")
end
def place_holder_blocks(count) do
css("[data-selector='place-holder']", count: count)
end
def search(session, text) do
session
|> fill_in(css("[data-test='search_input']"), with: text)

@ -1,7 +1,8 @@
defmodule BlockScoutWeb.ViewingBlocksTest do
use BlockScoutWeb.FeatureCase, async: true
alias BlockScoutWeb.{BlockListPage, BlockPage, Notifier}
alias BlockScoutWeb.{BlockListPage, BlockPage}
alias Explorer.Chain.Block
setup do
timestamp = Timex.now() |> Timex.shift(hours: -1)
@ -131,33 +132,13 @@ defmodule BlockScoutWeb.ViewingBlocksTest do
|> assert_has(BlockListPage.block(block))
end
test "inserts place holder blocks if out of order block received", %{session: session} do
BlockListPage.visit_page(session)
block = insert(:block, number: 315)
Notifier.handle_event({:chain_event, :blocks, :realtime, [block]})
test "inserts place holder blocks on render for out of order blocks", %{session: session} do
insert(:block, number: 315)
session
|> assert_has(BlockListPage.block(block))
|> assert_has(BlockListPage.place_holder_blocks(3))
end
test "replaces place holder block if skipped block received", %{session: session} do
BlockListPage.visit_page(session)
block = insert(:block, number: 315)
Notifier.handle_event({:chain_event, :blocks, :realtime, [block]})
session
|> assert_has(BlockListPage.block(block))
|> BlockListPage.visit_page()
|> assert_has(BlockListPage.block(%Block{number: 314}))
|> assert_has(BlockListPage.place_holder_blocks(3))
skipped_block = insert(:block, number: 314)
Notifier.handle_event({:chain_event, :blocks, :realtime, [skipped_block]})
session
|> assert_has(BlockListPage.block(skipped_block))
|> assert_has(BlockListPage.place_holder_blocks(2))
end
end

@ -4,6 +4,7 @@ defmodule BlockScoutWeb.ViewingChainTest do
use BlockScoutWeb.FeatureCase, async: true
alias BlockScoutWeb.{AddressPage, BlockPage, ChainPage, TransactionPage}
alias Explorer.Chain.Block
setup do
Enum.map(401..404, &insert(:block, number: &1))
@ -50,6 +51,15 @@ defmodule BlockScoutWeb.ViewingChainTest do
|> ChainPage.visit_page()
|> assert_has(ChainPage.blocks(count: 4))
end
test "inserts place holder blocks on render for out of order blocks", %{session: session} do
insert(:block, number: 409)
session
|> ChainPage.visit_page()
|> assert_has(ChainPage.block(%Block{number: 408}))
|> assert_has(ChainPage.place_holder_blocks(3))
end
end
describe "viewing transactions" do

Loading…
Cancel
Save