From 7a8b2db3fb06afb4aa31f64bc4ca3f1bbb278c53 Mon Sep 17 00:00:00 2001 From: Miguel Medeiros Date: Fri, 6 Aug 2021 08:09:47 -0300 Subject: [PATCH] UI/UX: Fix Blockchain skeleton preloader. (#696) * Fix Blockchain skeleton preloader. * Fix Mempool Blocks skeleton preloader. * Add e2e test. * Add shared command to cyrpress e2e test. --- .../integration/mainnet/mainnet.spec.ts | 44 ++++++++++++------- frontend/cypress/support/commands.ts | 11 +++++ .../blockchain-blocks.component.html | 14 +++--- .../blockchain-blocks.component.ts | 23 +++++----- .../master-page/master-page.component.html | 2 +- .../mempool-blocks.component.html | 2 +- .../mempool-blocks.component.ts | 7 +++ 7 files changed, 69 insertions(+), 34 deletions(-) diff --git a/frontend/cypress/integration/mainnet/mainnet.spec.ts b/frontend/cypress/integration/mainnet/mainnet.spec.ts index 91cce9868..fc2a79b7b 100644 --- a/frontend/cypress/integration/mainnet/mainnet.spec.ts +++ b/frontend/cypress/integration/mainnet/mainnet.spec.ts @@ -12,28 +12,40 @@ describe('Mainnet', () => { Cypress.Commands.add('waitForBlockData', () => { cy.wait('@tx-outspends'); cy.wait('@pools'); - }); + }); }); it('loads the status screen', () => { - cy.visit('/status'); - cy.get('#mempool-block-0').should('be.visible'); - cy.get('[id^="bitcoin-block-"]').should('have.length', 8); - cy.get('.footer').should('be.visible'); - cy.get('.row > :nth-child(1)').invoke('text').then((text) => { - expect(text).to.match(/Tx vBytes per second:.* vB\/s/); - }); - cy.get('.row > :nth-child(2)').invoke('text').then((text) => { - expect(text).to.match(/Unconfirmed:(.*)/); - }); - cy.get('.row > :nth-child(3)').invoke('text').then((text) => { - expect(text).to.match(/Mempool size:(.*) (kB|MB) \((\d+) (block|blocks)\)/); - }); + cy.visit('/status'); + cy.get('#mempool-block-0').should('be.visible'); + cy.get('[id^="bitcoin-block-"]').should('have.length', 8); + cy.get('.footer').should('be.visible'); + cy.get('.row > :nth-child(1)').invoke('text').then((text) => { + expect(text).to.match(/Tx vBytes per second:.* vB\/s/); + }); + cy.get('.row > :nth-child(2)').invoke('text').then((text) => { + expect(text).to.match(/Unconfirmed:(.*)/); + }); + cy.get('.row > :nth-child(3)').invoke('text').then((text) => { + expect(text).to.match(/Mempool size:(.*) (kB|MB) \((\d+) (block|blocks)\)/); + }); }); + it('loads the dashboard', () => { - cy.visit('/'); - cy.waitForSkeletonGone(); + cy.visit('/'); + cy.waitForSkeletonGone(); + }); + + it('loads skeleton when changes between networks', () => { + cy.visit('/'); + cy.waitForSkeletonGone(); + + cy.changeNetwork("testnet"); + cy.changeNetwork("signet"); + cy.changeNetwork("liquid"); + cy.changeNetwork("mainnet"); + cy.changeNetwork("bisq"); }); it('loads the dashboard with the skeleton blocks', () => { diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts index 96e2270fe..b240a7bc4 100644 --- a/frontend/cypress/support/commands.ts +++ b/frontend/cypress/support/commands.ts @@ -64,3 +64,14 @@ Cypress.Commands.add( Cypress.Commands.add('mockMempoolSocket', () => { mockWebSocket(); }); + +Cypress.Commands.add('changeNetwork', (network: "testnet"|"signet"|"liquid"|"bisq"|"mainnet" ) => { + cy.get('.dropdown-toggle').click().then(() => { + cy.get(`.${network}`).click().then(() => { + cy.waitForPageIdle(); + if(network !== 'bisq'){ + cy.waitForSkeletonGone(); + } + }); + }); +}); diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html index dd74114c2..ab2ffbe65 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.html @@ -1,4 +1,4 @@ -
+
  @@ -25,11 +25,13 @@
-
-
-
-
+ +
+
+
+
+
-
+ diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts index c8c4dc5f4..9856cdfc1 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts @@ -16,9 +16,10 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { blocks: Block[] = this.mountEmptyBlocks(); markHeight: number; blocksSubscription: Subscription; - networkSubscriotion: Subscription; + networkSubscription: Subscription; tabHiddenSubscription: Subscription; markBlockSubscription: Subscription; + isLoadingWebsocketSubscription: Subscription; blockStyles = []; interval: any; tabHidden = false; @@ -45,7 +46,8 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { ngOnInit() { this.blocks.forEach((b) => this.blockStyles.push(this.getStyleForBlock(b))); - this.networkSubscriotion = this.stateService.networkChanged$.subscribe((network) => this.network = network); + this.isLoadingWebsocketSubscription = this.stateService.isLoadingWebSocket$.subscribe((loading) => this.loadingBlocks = loading); + this.networkSubscription = this.stateService.networkChanged$.subscribe((network) => this.network = network); this.tabHiddenSubscription = this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); this.blocksSubscription = this.stateService.blocks$ @@ -54,8 +56,6 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { return; } - this.loadingBlocks = true; - if (this.blocks.length && block.height !== this.blocks[0].height + 1) { this.blocks = []; this.blocksFilled = false; @@ -75,13 +75,15 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { this.moveArrowToPosition(true, false); } - this.blockStyles = []; - this.blocks.forEach((b) => this.blockStyles.push(this.getStyleForBlock(b))); - setTimeout(() => { + if (!this.loadingBlocks) { this.blockStyles = []; this.blocks.forEach((b) => this.blockStyles.push(this.getStyleForBlock(b))); - this.cd.markForCheck(); - }, 50); + setTimeout(() => { + this.blockStyles = []; + this.blocks.forEach((b) => this.blockStyles.push(this.getStyleForBlock(b))); + this.cd.markForCheck(); + }, 50); + } if (this.blocks.length === this.stateService.env.KEEP_BLOCKS_AMOUNT) { this.blocksFilled = true; @@ -124,9 +126,10 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy { ngOnDestroy() { this.blocksSubscription.unsubscribe(); - this.networkSubscriotion.unsubscribe(); + this.networkSubscription.unsubscribe(); this.tabHiddenSubscription.unsubscribe(); this.markBlockSubscription.unsubscribe(); + this.isLoadingWebsocketSubscription.unsubscribe(); clearInterval(this.interval); } diff --git a/frontend/src/app/components/master-page/master-page.component.html b/frontend/src/app/components/master-page/master-page.component.html index 55b703b35..e5b75254f 100644 --- a/frontend/src/app/components/master-page/master-page.component.html +++ b/frontend/src/app/components/master-page/master-page.component.html @@ -20,7 +20,7 @@ - +
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html index 4b90ce65b..9cbfe3ffa 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html @@ -1,5 +1,5 @@
-
+
  diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts index 0cd23f60a..34241205b 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts @@ -21,6 +21,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { mempoolBlocksFull: MempoolBlock[] = this.mountEmptyBlocks(); mempoolBlockStyles = []; markBlocksSubscription: Subscription; + isLoadingWebsocketSubscription: Subscription; blockSubscription: Subscription; networkSubscription: Subscription; network = ''; @@ -55,6 +56,11 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { }); this.reduceMempoolBlocksToFitScreen(this.mempoolBlocks); this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); + + this.isLoadingWebsocketSubscription = this.stateService.isLoadingWebSocket$.subscribe((loading) => { + this.loadingMempoolBlocks = loading; + this.cd.markForCheck(); + }); this.mempoolBlocks$ = merge( of(true), @@ -164,6 +170,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { this.markBlocksSubscription.unsubscribe(); this.blockSubscription.unsubscribe(); this.networkSubscription.unsubscribe(); + this.isLoadingWebsocketSubscription.unsubscribe(); clearTimeout(this.resetTransitionTimeout); }