diff --git a/test/e2e/metrics/transaction-finalized.spec.js b/test/e2e/metrics/transaction-finalized.spec.js index df4cc21d0..1fbfeba0d 100644 --- a/test/e2e/metrics/transaction-finalized.spec.js +++ b/test/e2e/metrics/transaction-finalized.spec.js @@ -1,11 +1,12 @@ /* eslint-disable no-useless-escape */ -const { strict: assert } = require('assert'); +const { isEqual, omit } = require('lodash'); const { defaultGanacheOptions, withFixtures, unlockWallet, sendTransaction, getEventPayloads, + assertInAnyOrder, } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); @@ -91,6 +92,47 @@ async function mockSegment(mockServer) { const RECIPIENT = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3'; +/** + * Assert that the event names begin with the appropriate prefixes. Even + * finalized events begin with transaction-submitted because they start as + * event fragments created when the transaction is submitted. + * + * @param {object} payload + */ +const messageIdStartsWithTransactionSubmitted = (payload) => + payload.messageId.startsWith('transaction-submitted'); + +/** + * Assert that the events with sensitive properties should have messageIds + * ending in 0x000 this is important because otherwise the events are seen as + * duplicates in segment + * + * @param {object} payload + */ +const messageIdEndsWithZeros = (payload) => payload.messageId.endsWith('0x000'); + +/** + * Assert that the events with sensitive data do not contain a userId (the + * random anonymous id generated when a user opts into metametrics) + * + * @param {object} payload + */ +const eventDoesNotIncludeUserId = (payload) => + typeof payload.userId === 'undefined'; + +const eventHasUserIdWithoutAnonymousId = (payload) => + typeof payload.userId === 'string' && + typeof payload.anonymousId === 'undefined'; + +/** + * Assert that the events with sensitive data have anonymousId set to + * 0x0000000000000000 which is our universal anonymous record + * + * @param {object} payload + */ +const eventHasZeroAddressAnonymousId = (payload) => + payload.anonymousId === '0x0000000000000000'; + describe('Transaction Finalized Event', function () { it('Successfully tracked when sending a transaction', async function () { await withFixtures( @@ -112,215 +154,139 @@ describe('Transaction Finalized Event', function () { await sendTransaction(driver, RECIPIENT, '2.0'); const events = await getEventPayloads(driver, mockedEndpoints); - // The order of these events is ensured by the mockSegment function - // which requires that the first, and third (0, 2 indexes) have the - // status property, which will only appear on the anonymous events. - const transactionSubmittedNoMMId = events[0]; - const transactionSubmittedWithMMId = events[1]; - const transactionFinalizedNoMMId = events[2]; - const transactionFinalizedWithMMId = events[3]; - // Assert doesn't have generic matchers so we delete these timestamp related properties. - // If we switch to a different assertion library we can use generic matchers in the future. - delete transactionSubmittedNoMMId.properties.first_seen; - delete transactionFinalizedNoMMId.properties.first_seen; - delete transactionFinalizedNoMMId.properties.completion_time; + const transactionSubmittedWithSensitivePropertiesAssertions = [ + messageIdStartsWithTransactionSubmitted, + messageIdEndsWithZeros, + eventDoesNotIncludeUserId, + eventHasZeroAddressAnonymousId, + (payload) => + isEqual(omit(payload.properties, ['first_seen']), { + status: 'submitted', + transaction_envelope_type: 'legacy', + gas_limit: '0x5208', + gas_price: '2', + default_gas: '0.000021', + default_gas_price: '2', + chain_id: '0x539', + referrer: 'metamask', + source: 'user', + network: '1337', + eip_1559_version: '0', + gas_edit_type: 'none', + gas_edit_attempted: 'none', + account_type: 'MetaMask', + device_model: 'N/A', + asset_type: 'NATIVE', + token_standard: 'NONE', + transaction_type: 'simpleSend', + transaction_speed_up: false, + ui_customizations: null, + category: 'Transactions', + locale: 'en', + environment_type: 'background', + }), + ]; - // Assert that the event names begin with the appropriate prefixes. Even finalized events begin with transaction-submitted - // because they start as event fragments created when the transaction is submitted. - assert.ok( - transactionSubmittedNoMMId.messageId.startsWith( - 'transaction-submitted', - ), - `Transaction Submitted event with sensitive properties has messageId \"${transactionSubmittedNoMMId.messageId}\" does not have a messageId beginning with \"transaction-submitted\"`, - ); + const transactionSubmittedWithoutSensitivePropertiesAssertions = [ + messageIdStartsWithTransactionSubmitted, + eventHasUserIdWithoutAnonymousId, + (payload) => + isEqual(payload.properties, { + chain_id: '0x539', + referrer: 'metamask', + source: 'user', + network: '1337', + eip_1559_version: '0', + gas_edit_type: 'none', + gas_edit_attempted: 'none', + account_type: 'MetaMask', + device_model: 'N/A', + asset_type: 'NATIVE', + token_standard: 'NONE', + transaction_type: 'simpleSend', + transaction_speed_up: false, + ui_customizations: null, + category: 'Transactions', + locale: 'en', + environment_type: 'background', + status: 'submitted', + }), + ]; - assert.ok( - transactionFinalizedNoMMId.messageId.startsWith( - 'transaction-submitted', - ), - `Transaction Finalized event with sensitive properties has messageId \"${transactionFinalizedNoMMId.messageId}\" that does not begin with \"transaction-submitted\"`, - ); + const transactionFinalizedWithSensitivePropertiesAssertions = [ + messageIdStartsWithTransactionSubmitted, + messageIdEndsWithZeros, + eventDoesNotIncludeUserId, + eventHasZeroAddressAnonymousId, + (payload) => + isEqual( + omit(payload.properties, ['first_seen', 'completion_time']), + { + status: 'confirmed', + transaction_envelope_type: 'legacy', + gas_limit: '0x5208', + gas_price: '2', + default_gas: '0.000021', + default_gas_price: '2', + chain_id: '0x539', + referrer: 'metamask', + source: 'user', + network: '1337', + eip_1559_version: '0', + gas_edit_type: 'none', + gas_edit_attempted: 'none', + account_type: 'MetaMask', + device_model: 'N/A', + asset_type: 'NATIVE', + token_standard: 'NONE', + transaction_type: 'simpleSend', + transaction_speed_up: false, + ui_customizations: null, + gas_used: '5208', + category: 'Transactions', + locale: 'en', + environment_type: 'background', + }, + ), + ]; - assert.ok( - transactionSubmittedWithMMId.messageId.startsWith( - 'transaction-submitted', - ), - `Transaction Submitted event has messageId \"${transactionSubmittedWithMMId.messageId}\" that does not begin with \"transaction-submitted\"`, - ); + const transactionFinalizedWithoutSensitivePropertiesAssertions = [ + messageIdStartsWithTransactionSubmitted, + eventHasUserIdWithoutAnonymousId, + (payload) => + isEqual(payload.properties, { + chain_id: '0x539', + referrer: 'metamask', + source: 'user', + network: '1337', + eip_1559_version: '0', + gas_edit_type: 'none', + gas_edit_attempted: 'none', + account_type: 'MetaMask', + device_model: 'N/A', + asset_type: 'NATIVE', + token_standard: 'NONE', + transaction_type: 'simpleSend', + transaction_speed_up: false, + ui_customizations: null, + category: 'Transactions', + locale: 'en', + environment_type: 'background', + status: 'confirmed', + }), + ]; - assert.ok( - transactionFinalizedWithMMId.messageId.startsWith( - 'transaction-submitted', - ), - `Transaction Finalized event has messageID \"${transactionFinalizedWithMMId.messageId}\" that does not begin with \"transaction-submitted\"`, - ); + const [event1, event2, event3, event4] = events; - // Assert that the events with sensitive properties should have messageIds ending in 0x000 - // This is important because otherwise the events are seen as duplicates in segment - - assert.ok( - transactionSubmittedNoMMId.messageId.endsWith('0x000'), - `Transaction Submitted event with sensitive properties has messageId \"${transactionSubmittedNoMMId.messageId}\" that does not end in \"0x000\" to differentiate it from the event that does not include sensitive data.`, - ); - - assert.ok( - transactionFinalizedNoMMId.messageId.endsWith('0x000'), - `Transaction Finalized event with sensitive properties has messageID \"${transactionFinalizedNoMMId.messageId}\" that does not end in \"0x000\" to differentiate it from the event that does not include sensitive data.`, - ); - - // Assert that transaction finalized events contain '-success-' in their messageId - assert.ok( - transactionFinalizedWithMMId.messageId.includes('-success-'), - `Transaction Finalized event has messageId \"${transactionFinalizedWithMMId.messageId}\" that does not contain "-success-"`, - ); - - assert.ok( - transactionFinalizedNoMMId.messageId.includes('-success-'), - `Transaction Finalized event with sensitive properties has messageID \"${transactionFinalizedNoMMId.messageId}\" that does not contain "-success-"`, - ); - - // Assert that the events with sensitive data do not contain a userId (the random anonymous id generated when a user opts into metametrics) - assert.ok( - typeof transactionSubmittedNoMMId.userId === 'undefined', - 'Transaction Submitted event with sensitive properties has a userId supplied when it should only have the anonymousId', - ); - assert.ok( - typeof transactionFinalizedNoMMId.userId === 'undefined', - 'Transaction Finalized event with sensitive properties has a userId supplied when it should only have the anonymousId', - ); - - // Assert that the events with sensitive data have anonymousId set to 0x0000000000000000 which is our universal anonymous record - assert.ok( - transactionSubmittedNoMMId.anonymousId === '0x0000000000000000', - 'Transaction Submitted event with sensitive properties has an anonymousId that does not match our universal anonymous id of 0x0000000000000000', - ); - assert.ok( - transactionFinalizedNoMMId.anonymousId === '0x0000000000000000', - 'Transaction Finalized event with sensitive properties has an anonymousId that does not match our universal anonymous id of 0x0000000000000000', - ); - - // Assert that our events without sensitive data have a userId but no anonymousId - assert.ok( - typeof transactionSubmittedWithMMId.userId === 'string' && - typeof transactionSubmittedWithMMId.anonymousId === 'undefined', - 'Transaction Submitted event without sensitive properties should only have a userId specified, and no anonymousId', - ); - assert.ok( - typeof transactionFinalizedWithMMId.userId === 'string' && - typeof transactionFinalizedWithMMId.anonymousId === 'undefined', - 'Transaction Finalized event without sensitive properties should only have a userId specified, and no anonymousId', - ); - - // Assert on the properties - - assert.deepStrictEqual( - transactionSubmittedNoMMId.properties, - { - status: 'submitted', - transaction_envelope_type: 'legacy', - gas_limit: '0x5208', - gas_price: '2', - default_gas: '0.000021', - default_gas_price: '2', - chain_id: '0x539', - referrer: 'metamask', - source: 'user', - network: '1337', - eip_1559_version: '0', - gas_edit_type: 'none', - gas_edit_attempted: 'none', - account_type: 'MetaMask', - device_model: 'N/A', - asset_type: 'NATIVE', - token_standard: 'NONE', - transaction_type: 'simpleSend', - transaction_speed_up: false, - ui_customizations: null, - category: 'Transactions', - locale: 'en', - environment_type: 'background', - }, - 'Transaction Submitted event with sensitive properties does not match the expected payload', - ); - assert.deepStrictEqual( - transactionSubmittedWithMMId.properties, - { - chain_id: '0x539', - referrer: 'metamask', - source: 'user', - network: '1337', - eip_1559_version: '0', - gas_edit_type: 'none', - gas_edit_attempted: 'none', - account_type: 'MetaMask', - device_model: 'N/A', - asset_type: 'NATIVE', - token_standard: 'NONE', - transaction_type: 'simpleSend', - transaction_speed_up: false, - ui_customizations: null, - category: 'Transactions', - locale: 'en', - environment_type: 'background', - status: 'submitted', - }, - 'Transaction Submitted event without sensitive properties does not match the expected payload', - ); - - assert.deepStrictEqual( - transactionFinalizedNoMMId.properties, - { - status: 'confirmed', - transaction_envelope_type: 'legacy', - gas_limit: '0x5208', - gas_price: '2', - default_gas: '0.000021', - default_gas_price: '2', - chain_id: '0x539', - referrer: 'metamask', - source: 'user', - network: '1337', - eip_1559_version: '0', - gas_edit_type: 'none', - gas_edit_attempted: 'none', - account_type: 'MetaMask', - device_model: 'N/A', - asset_type: 'NATIVE', - token_standard: 'NONE', - transaction_type: 'simpleSend', - transaction_speed_up: false, - ui_customizations: null, - gas_used: '5208', - category: 'Transactions', - locale: 'en', - environment_type: 'background', - }, - 'Transaction Finalized event with sensitive properties does not match the expected payload', - ); - assert.deepStrictEqual( - transactionFinalizedWithMMId.properties, - { - chain_id: '0x539', - referrer: 'metamask', - source: 'user', - network: '1337', - eip_1559_version: '0', - gas_edit_type: 'none', - gas_edit_attempted: 'none', - account_type: 'MetaMask', - device_model: 'N/A', - asset_type: 'NATIVE', - token_standard: 'NONE', - transaction_type: 'simpleSend', - transaction_speed_up: false, - ui_customizations: null, - category: 'Transactions', - locale: 'en', - environment_type: 'background', - status: 'confirmed', - }, - 'Transaction Finalized event without sensitive properties does not match the expected payload', + assertInAnyOrder( + [event1, event2, event3, event4], + [ + transactionSubmittedWithSensitivePropertiesAssertions, + transactionSubmittedWithoutSensitivePropertiesAssertions, + transactionFinalizedWithSensitivePropertiesAssertions, + transactionFinalizedWithoutSensitivePropertiesAssertions, + ], ); }, );