From 4bc141cd67dfe47afb5d702ab256bb868d5fc390 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:14:55 -0800 Subject: [PATCH 1/6] Add fixture for RBF transactions --- frontend/cypress/fixtures/mainnet_rbf.json | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 frontend/cypress/fixtures/mainnet_rbf.json diff --git a/frontend/cypress/fixtures/mainnet_rbf.json b/frontend/cypress/fixtures/mainnet_rbf.json new file mode 100644 index 000000000..50dbbb2df --- /dev/null +++ b/frontend/cypress/fixtures/mainnet_rbf.json @@ -0,0 +1,52 @@ +{ + "rbfTransaction": { + "txid": "8913ec7ba0ede285dbd120e46f6d61a28f2903c10814a6f6c4f97d0edf3e1f46", + "version": 2, + "locktime": 632699, + "vin": [ + { + "txid": "02238126a63ea2669c5f378012180ef8b54402a949316f9b2f1352c51730a086", + "vout": 0, + "prevout": { + "scriptpubkey": "a914f8e495456956c833e5e8c69b9a9dc041aa14c72f87", + "scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 f8e495456956c833e5e8c69b9a9dc041aa14c72f OP_EQUAL", + "scriptpubkey_type": "p2sh", + "scriptpubkey_address": "3QP3LMD8veT5GtWV83Nosif2Bhr73857VB", + "value": 25000000 + }, + "scriptsig": "22002043288fbbc0fc5efa86c229dbb7d88ab78d57957c65b5d5ceaece70838976ad1b", + "scriptsig_asm": "OP_PUSHBYTES_34 002043288fbbc0fc5efa86c229dbb7d88ab78d57957c65b5d5ceaece70838976ad1b", + "witness": [ + "", + "3044022009e2d3a8e645f65bc89c8492cd9c08e6fb02609fd402214884a754a1970145340220575bb325429def59f3a3f1e22d9740a3feecbe97438ff3bb5796b2c46b3c477f01", + "3044022039c34372882da8fc1c1243bd72b5e7e5e6870301ef56bdebb87bc647fb50f9b5022071a704ee77d742f78b10e45be675d4c45a5f31e884139e75c975144fde70e41701", + "522102346eb7133f11e0dc279bc592d5ac948a91676372a6144c9ae2085625d7fbf70421021b9508a458f9d59be4eb8cc87ad582c3b494106fb1d4ec22801569be0700eb7b52ae" + ], + "is_coinbase": false, + "sequence": 4294967293, + "inner_redeemscript_asm": "OP_0 OP_PUSHBYTES_32 43288fbbc0fc5efa86c229dbb7d88ab78d57957c65b5d5ceaece70838976ad1b", + "inner_witnessscript_asm": "OP_PUSHNUM_2 OP_PUSHBYTES_33 02346eb7133f11e0dc279bc592d5ac948a91676372a6144c9ae2085625d7fbf704 OP_PUSHBYTES_33 021b9508a458f9d59be4eb8cc87ad582c3b494106fb1d4ec22801569be0700eb7b OP_PUSHNUM_2 OP_CHECKMULTISIG" + } + ], + "vout": [ + { + "scriptpubkey": "a914fd4e5e59dd5cf2dc48eaedf1a2a1650ca1ce9d7f87", + "scriptpubkey_asm": "OP_HASH160 OP_PUSHBYTES_20 fd4e5e59dd5cf2dc48eaedf1a2a1650ca1ce9d7f OP_EQUAL", + "scriptpubkey_type": "p2sh", + "scriptpubkey_address": "3QnNmDhZS7toHA7bhhbTPBdtpLJoeecq5c", + "value": 13986350 + }, + { + "scriptpubkey": "76a914edc93d0446deec1c2d514f3a490f050096e74e0e88ac", + "scriptpubkey_asm": "OP_DUP OP_HASH160 OP_PUSHBYTES_20 edc93d0446deec1c2d514f3a490f050096e74e0e OP_EQUALVERIFY OP_CHECKSIG", + "scriptpubkey_type": "p2pkh", + "scriptpubkey_address": "1NgJDkTUqJxxCAAZrrsC87kWag5kphrRtM", + "value": 11000000 + } + ], + "size": 372, + "weight": 828, + "fee": 1.5, + "status": { "confirmed": false } + } +} \ No newline at end of file From bc7bbf5fe5522eeb3aa8551b0c7f23927297687d Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:15:33 -0800 Subject: [PATCH 2/6] Fix formatting --- frontend/cypress/support/websocket.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/cypress/support/websocket.ts b/frontend/cypress/support/websocket.ts index 03f4a54f1..6df66e56e 100644 --- a/frontend/cypress/support/websocket.ts +++ b/frontend/cypress/support/websocket.ts @@ -31,19 +31,19 @@ export const mockWebSocket = () => { cy.on('window:before:load', (win) => { const winWebSocket = win.WebSocket; cy.stub(win, 'WebSocket').callsFake((url) => { - console.log(url); + console.log(url); if ((new URL(url).pathname.indexOf('/sockjs-node/') !== 0)) { const { server, websocket } = createMock(url); win.mockServer = server; win.mockServer.on('connection', (socket) => { win.mockSocket = socket; - win.mockSocket.send('{"action":"init"}'); + win.mockSocket.send('{"action":"init"}'); }); - win.mockServer.on('message', (message) => { - console.log(message); - }); + win.mockServer.on('message', (message) => { + console.log(message); + }); return websocket; } else { @@ -89,4 +89,4 @@ export const dropWebSocket = (() => { win.mockServer.simulate("error"); }); return cy.wait(500); -}); \ No newline at end of file +}); From 0af5d733c4bdda47e4a527d9cbb4bd50e4f34be0 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:16:13 -0800 Subject: [PATCH 3/6] Small refactor to support mocking RBF txs --- frontend/cypress/support/websocket.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/frontend/cypress/support/websocket.ts b/frontend/cypress/support/websocket.ts index 6df66e56e..4a411eeb2 100644 --- a/frontend/cypress/support/websocket.ts +++ b/frontend/cypress/support/websocket.ts @@ -68,7 +68,13 @@ export const emitMempoolInfo = ({ //TODO: Use network specific mocks case "signet": case "testnet": + case "mainnet": default: + break; + } + + switch (params.command) { + case "init": { win.mockSocket.send('{"action":"init"}'); win.mockSocket.send('{"action":"want","data":["blocks","stats","mempool-blocks","live-2h-chart"]}'); win.mockSocket.send('{"conversions":{"USD":32365.338815782445}}'); @@ -78,6 +84,16 @@ export const emitMempoolInfo = ({ cy.readFile('cypress/fixtures/mainnet_mempoolInfo.json', 'ascii').then((fixture) => { win.mockSocket.send(JSON.stringify(fixture)); }); + break; + } + case "rbfTransaction": { + cy.readFile('cypress/fixtures/mainnet_rbf.json', 'ascii').then((fixture) => { + win.mockSocket.send(JSON.stringify(fixture)); + }); + break; + } + default: + break; } }); cy.waitForSkeletonGone(); From 47103d85d3c3404260b9ce38fa04b53fcb707ae7 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:19:10 -0800 Subject: [PATCH 4/6] Update mocked ws tests to use the new syntax --- frontend/cypress/integration/mainnet/mainnet.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/cypress/integration/mainnet/mainnet.spec.ts b/frontend/cypress/integration/mainnet/mainnet.spec.ts index 679ba59de..c64c825e1 100644 --- a/frontend/cypress/integration/mainnet/mainnet.spec.ts +++ b/frontend/cypress/integration/mainnet/mainnet.spec.ts @@ -56,7 +56,7 @@ describe('Mainnet', () => { cy.get('.badge', {timeout: 25000}).should('not.exist'); emitMempoolInfo({ 'params': { - loaded: true + command: 'init' } }); cy.get(':nth-child(1) > #bitcoin-block-0').should('not.exist'); @@ -283,7 +283,7 @@ describe('Mainnet', () => { emitMempoolInfo({ 'params': { - loaded: true + command: 'init' } }); From 96a2c8ab4e88948fad836dcac738a724d85a62d5 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:21:40 -0800 Subject: [PATCH 5/6] Add methods to detect overlapping components --- .../integration/mainnet/mainnet.spec.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/frontend/cypress/integration/mainnet/mainnet.spec.ts b/frontend/cypress/integration/mainnet/mainnet.spec.ts index c64c825e1..825405ccc 100644 --- a/frontend/cypress/integration/mainnet/mainnet.spec.ts +++ b/frontend/cypress/integration/mainnet/mainnet.spec.ts @@ -2,6 +2,36 @@ import { emitMempoolInfo, dropWebSocket } from "../../support/websocket"; const baseModule = Cypress.env("BASE_MODULE"); + +//Credit: https://github.com/bahmutov/cypress-examples/blob/6cedb17f83a3bb03ded13cf1d6a3f0656ca2cdf5/docs/recipes/overlapping-elements.md + +/** + * Returns true if two DOM rectangles are overlapping + * @param {DOMRect} rect1 the bounding client rectangle of the first element + * @param {DOMRect} rect2 the bounding client rectangle of the second element + * @returns {boolean} +*/ +const areOverlapping = (rect1, rect2) => { + // if one rectangle is on the left side of the other + if (rect1.right < rect2.left || rect2.right < rect1.left) { + return false + } + + // if one rectangle is above the other + if (rect1.bottom < rect2.top || rect2.bottom < rect1.top) { + return false + } + + // the rectangles must overlap + return true +} + +/** + * Returns the bounding rectangle of the first DOM + * element in the given jQuery object. + */ +const getRectangle = ($el) => $el[0].getBoundingClientRect(); + describe('Mainnet', () => { beforeEach(() => { //cy.intercept('/sockjs-node/info*').as('socket'); From 7f045ae5b93ddb4e2a44e62c62122affd592b538 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Tue, 14 Dec 2021 23:21:59 -0800 Subject: [PATCH 6/6] Add tests to detect layout issues in RBF transactions --- .../integration/mainnet/mainnet.spec.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/frontend/cypress/integration/mainnet/mainnet.spec.ts b/frontend/cypress/integration/mainnet/mainnet.spec.ts index 825405ccc..461f5c0a8 100644 --- a/frontend/cypress/integration/mainnet/mainnet.spec.ts +++ b/frontend/cypress/integration/mainnet/mainnet.spec.ts @@ -458,6 +458,78 @@ describe('Mainnet', () => { cy.get('.pagination-container ul.pagination').first().children().should('have.length', 7); }); }); + + describe('RBF transactions', () => { + it('shows RBF transactions properly (mobile)', () => { + cy.viewport('iphone-xr'); + cy.mockMempoolSocket(); + cy.visit('/tx/f81a08699b62b2070ad8fe0f2a076f8bea0386a2fdcd8124caee42cbc564a0d5'); + + cy.waitForSkeletonGone(); + + emitMempoolInfo({ + 'params': { + command: 'init' + } + }); + + cy.get('#mempool-block-0'); + + emitMempoolInfo({ + 'params': { + command: 'rbfTransaction' + } + }); + + cy.get('.alert-mempool').should('be.visible'); + cy.get('.alert-mempool').invoke('css', 'width').then((alertWidth) => { + cy.get('.container-xl > :nth-child(3)').invoke('css', 'width').should('equal', alertWidth); + }); + + cy.get('.btn-success').then(getRectangle).then((rectA) => { + cy.get('.alert-mempool').then(getRectangle).then((rectB) => { + expect(areOverlapping(rectA, rectB), 'Confirmations box and RBF alert are overlapping').to.be.false; + }); + }); + }); + + it('shows RBF transactions properly (desktop)', () => { + cy.viewport('macbook-16'); + cy.mockMempoolSocket(); + cy.visit('/tx/f81a08699b62b2070ad8fe0f2a076f8bea0386a2fdcd8124caee42cbc564a0d5'); + + cy.waitForSkeletonGone(); + + emitMempoolInfo({ + 'params': { + command: 'init' + } + }); + + cy.get('#mempool-block-0'); + + emitMempoolInfo({ + 'params': { + command: 'rbfTransaction' + } + }); + + cy.get('.alert-mempool').should('be.visible'); + + const alertLocator = '.alert-mempool'; + const tableLocator = '.container-xl > :nth-child(3)'; + + cy.get(tableLocator).invoke('css', 'width').then((firstWidth) => { + cy.get(alertLocator).invoke('css', 'width').should('equal', firstWidth); + }); + + cy.get('.btn-success').then(getRectangle).then((rectA) => { + cy.get('.alert-mempool').then(getRectangle).then((rectB) => { + expect(areOverlapping(rectA, rectB), 'Confirmations box and RBF alert are overlapping').to.be.false; + }); + }); + }); + }); } else { it.skip(`Tests cannot be run on the selected BASE_MODULE ${baseModule}`); }