mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
test/e2e: add test for transaction finalized metric events (#19837)
* add transaction finalized metric events * remove another time based property * better error messaging * try to guarantee order of events
This commit is contained in:
parent
90bfbf2725
commit
484dae32e8
326
test/e2e/metrics/transaction-finalized.spec.js
Normal file
326
test/e2e/metrics/transaction-finalized.spec.js
Normal file
@ -0,0 +1,326 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const { strict: assert } = require('assert');
|
||||
const {
|
||||
defaultGanacheOptions,
|
||||
withFixtures,
|
||||
unlockWallet,
|
||||
sendTransaction,
|
||||
getEventPayloads,
|
||||
} = require('../helpers');
|
||||
const FixtureBuilder = require('../fixture-builder');
|
||||
|
||||
/**
|
||||
* mocks the segment api multiple times for specific payloads that we expect to
|
||||
* see when these tests are run. In this case we are looking for
|
||||
* 'Transaction Submitted' and 'Transaction Finalized'. In addition on the
|
||||
* first event of each series we require a field that should only appear in the
|
||||
* anonymized events so that we can guarantee order of seenRequests and can
|
||||
* properly make assertions. Do not use the constants from the metrics
|
||||
* constants files, because if these change we want a strong indicator to our
|
||||
* data team that the shape of data will change.
|
||||
*
|
||||
* @param {import('mockttp').Mockttp} mockServer
|
||||
* @returns {Promise<import('mockttp/dist/pluggable-admin').MockttpClientResponse>[]}
|
||||
*/
|
||||
async function mockSegment(mockServer) {
|
||||
return [
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Submitted',
|
||||
properties: { status: 'submitted' },
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Submitted',
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Finalized',
|
||||
properties: { status: 'confirmed' },
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Finalized',
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
const RECIPIENT = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
|
||||
|
||||
describe('Transaction Finalized Event', function () {
|
||||
it('Successfully tracked when sending a transaction', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder()
|
||||
.withMetaMetricsController({
|
||||
metaMetricsId: 'fake-metrics-id',
|
||||
participateInMetaMetrics: true,
|
||||
})
|
||||
.build(),
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
testSpecificMock: mockSegment,
|
||||
},
|
||||
async ({ driver, mockedEndpoint: mockedEndpoints }) => {
|
||||
await driver.navigate();
|
||||
await unlockWallet(driver);
|
||||
|
||||
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;
|
||||
|
||||
// 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\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedNoMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Finalized event with sensitive properties has messageId \"${transactionFinalizedNoMMId.messageId}\" that does not begin with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionSubmittedWithMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Submitted event has messageId \"${transactionSubmittedWithMMId.messageId}\" that does not begin with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedWithMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Finalized event has messageID \"${transactionFinalizedWithMMId.messageId}\" that does not begin with \"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
|
||||
|
||||
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',
|
||||
},
|
||||
'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',
|
||||
},
|
||||
'Transaction Finalized event without sensitive properties does not match the expected payload',
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user