Skip to content

Commit

Permalink
chore: detailed canary timings (#2214)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 authored May 6, 2024
1 parent a13b878 commit 75a897a
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 49 deletions.
13 changes: 10 additions & 3 deletions apps/laboratory/tests/canary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ testConnectedMW.beforeEach(async ({ modalValidator, walletValidator }) => {
timeEnd('beforeEach expectConnection')
})

testConnectedMW.afterEach(async ({ browserName }, testInfo) => {
testConnectedMW.afterEach(async ({ browserName, timingRecords }, testInfo) => {
if (browserName === 'firefox') {
return
}
Expand All @@ -28,21 +28,28 @@ testConnectedMW.afterEach(async ({ browserName }, testInfo) => {
'https://lab.web3modal.com/',
'HappyPath.sign',
testInfo.status === 'passed',
duration
duration,
timingRecords
)
timeEnd('uploadCanaryResultsToCloudWatch')
}
})

testConnectedMW(
'it should sign',
async ({ modalPage, walletPage, modalValidator, walletValidator }) => {
async ({ modalPage, walletPage, modalValidator, walletValidator, timingRecords }) => {
timeStart('modalPage.sign()')
await modalPage.sign()
timeEnd('modalPage.sign()')
const signRequestedTime = new Date()
timeStart('walletValidator.expectReceivedSign')
await walletValidator.expectReceivedSign({})
timeEnd('walletValidator.expectReceivedSign')
const signReceivedTime = new Date()
timingRecords.push({
item: 'sign',
timeMs: signReceivedTime.getTime() - signRequestedTime.getTime()
})
timeStart('walletPage.handleRequest')
await walletPage.handleRequest({ accept: true })
timeEnd('walletPage.handleRequest')
Expand Down
11 changes: 11 additions & 0 deletions apps/laboratory/tests/shared/fixtures/timing-fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test as base } from '@playwright/test'

export type TimingRecords = { item: string; timeMs: number }[]

export interface TimingFixture {
timingRecords: TimingRecords
}

export const timingFixture = base.extend<TimingFixture>({
timingRecords: []
})
4 changes: 2 additions & 2 deletions apps/laboratory/tests/shared/fixtures/w3m-email-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { ModalValidator } from '../validators/ModalValidator'
import { Email } from '../utils/email'
import { timingFixture } from './timing-fixture'

export const testMEmail = base.extend<ModalFixture>({
export const testMEmail = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library, context }, use, testInfo) => {
const modalPage = new ModalPage(page, library, 'email')
Expand Down
6 changes: 3 additions & 3 deletions apps/laboratory/tests/shared/fixtures/w3m-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint no-console: 0 */

import { test as base } from '@playwright/test'
import { ModalPage } from '../pages/ModalPage'
import { ModalValidator } from '../validators/ModalValidator'
import { timeStart, timeEnd } from '../utils/logs'
import { timingFixture } from './timing-fixture'

// Declare the types of fixtures to use
export interface ModalFixture {
Expand All @@ -13,7 +13,7 @@ export interface ModalFixture {
}

// M -> test Modal
export const testM = base.extend<ModalFixture>({
export const testM = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
timeStart('new ModalPage')
Expand All @@ -31,7 +31,7 @@ export const testM = base.extend<ModalFixture>({
await use(modalValidator)
}
})
export const testMSiwe = base.extend<ModalFixture>({
export const testMSiwe = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'siwe')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { test as base } from '@playwright/test'
import type { ModalFixture } from './w3m-fixture'
import { Email } from '../utils/email'
import { ModalWalletPage } from '../pages/ModalWalletPage'
import { ModalWalletValidator } from '../validators/ModalWalletValidator'
import type { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

// Test Modal + Smart Account
export const testModalSmartAccount = base.extend<ModalFixture & { slowModalPage: ModalPage }>({
export const testModalSmartAccount = timingFixture.extend<
ModalFixture & { slowModalPage: ModalPage }
>({
library: ['wagmi', { option: true }],
modalPage: [
async ({ page, library, context }, use, testInfo) => {
Expand Down
10 changes: 8 additions & 2 deletions apps/laboratory/tests/shared/fixtures/w3m-wallet-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface ModalWalletFixture {

// MW -> test Modal + Wallet
export const testConnectedMW = base.extend<ModalWalletFixture>({
walletPage: async ({ context, modalPage }, use) => {
walletPage: async ({ context, modalPage, timingRecords }, use) => {
if (modalPage.library === 'solana') {
// Because solana doesn't support react-wallet-v2
timeStart('new WalletPage')
Expand All @@ -29,14 +29,20 @@ export const testConnectedMW = base.extend<ModalWalletFixture>({
const walletValidator = new WalletValidator(walletPage.page)
timeEnd('walletPage.connectWithUri')
timeStart('modalPage.getConnectUri')
const uri = await modalPage.getConnectUri()
const uri = await modalPage.getConnectUri(timingRecords)
timeEnd('modalPage.getConnectUri')
timeStart('walletPage.connectWithUri')
await walletPage.connectWithUri(uri)
timeEnd('walletPage.connectWithUri')
const connectionInitiated = new Date()
timeStart('walletPage.handleSessionProposal')
await walletPage.handleSessionProposal(DEFAULT_SESSION_PARAMS)
timeEnd('walletPage.handleSessionProposal')
const proposalReceived = new Date()
timingRecords.push({
item: 'receiveSessionProposal',
timeMs: proposalReceived.getTime() - connectionInitiated.getTime()
})
timeStart('walletValidator.expectConnected')
await walletValidator.expectConnected()
timeEnd('walletValidator.expectConnected')
Expand Down
15 changes: 13 additions & 2 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BASE_URL } from '../constants'
import { doActionAndWaitForNewPage } from '../utils/actions'
import { Email } from '../utils/email'
import { DeviceRegistrationPage } from './DeviceRegistrationPage'
import type { TimingRecords } from '../fixtures/timing-fixture'

export type ModalFlavor = 'default' | 'siwe' | 'email' | 'wallet'

Expand Down Expand Up @@ -38,7 +39,7 @@ export class ModalPage {
return value!
}

async getConnectUri(): Promise<string> {
async getConnectUri(timingRecords?: TimingRecords): Promise<string> {
await this.page.goto(this.url)
await this.connectButton.click()
const connect = this.page.getByTestId('wallet-selector-walletconnect')
Expand All @@ -47,12 +48,22 @@ export class ModalPage {
timeout: 5000
})
await connect.click()
const qrLoadInitiatedTime = new Date()

// Using getByTestId() doesn't work on my machine, I'm guessing because this element is inside of a <slot>
const qrCode = this.page.locator('wui-qr-code')
await expect(qrCode).toBeVisible()

return this.assertDefined(await qrCode.getAttribute('uri'))
const uri = this.assertDefined(await qrCode.getAttribute('uri'))
const qrLoadedTime = new Date()
if (timingRecords) {
timingRecords.push({
item: 'qrLoad',
timeMs: qrLoadedTime.getTime() - qrLoadInitiatedTime.getTime()
})
}

return uri
}

async emailFlow(
Expand Down
65 changes: 30 additions & 35 deletions apps/laboratory/tests/shared/utils/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
type MetricDatum,
type PutMetricDataCommandInput
} from '@aws-sdk/client-cloudwatch'
import type { TimingRecords } from '../fixtures/timing-fixture'

// eslint-disable-next-line func-style
export const uploadCanaryResultsToCloudWatch = async (
Expand All @@ -11,63 +12,57 @@ export const uploadCanaryResultsToCloudWatch = async (
target: string,
metricsPrefix: string,
isTestPassed: boolean,
testDurationMs: number
testDurationMs: number,
timingRecords: TimingRecords
// eslint-disable-next-line max-params
) => {
const cloudwatch = new CloudWatch({ region: 'eu-central-1' })
const ts = new Date()
const Dimensions = [
{
Name: 'Target',
Value: target
},
{
Name: 'Region',
Value: region
}
]
const Timestamp = new Date()
const metrics: MetricDatum[] = [
{
MetricName: `${metricsPrefix}.success`,
Dimensions: [
{
Name: 'Target',
Value: target
},
{
Name: 'Region',
Value: region
}
],
Dimensions,
Unit: 'Count',
Value: isTestPassed ? 1 : 0,
Timestamp: ts
Timestamp
},
{
MetricName: `${metricsPrefix}.failure`,
Dimensions: [
{
Name: 'Target',
Value: target
},
{
Name: 'Region',
Value: region
}
],
Dimensions,
Unit: 'Count',
Value: isTestPassed ? 0 : 1,
Timestamp: ts
Timestamp
}
]

if (isTestPassed) {
metrics.push({
MetricName: `${metricsPrefix}.latency`,
Dimensions: [
{
Name: 'Target',
Value: target
},
{
Name: 'Region',
Value: region
}
],
Dimensions,
Unit: 'Milliseconds',
Value: testDurationMs,
Timestamp: ts
Timestamp
})

for (const record of timingRecords) {
metrics.push({
MetricName: `${metricsPrefix}.timing.${record.item}`,
Dimensions,
Unit: 'Milliseconds',
Value: record.timeMs,
Timestamp
})
}
}

const params: PutMetricDataCommandInput = {
Expand Down

0 comments on commit 75a897a

Please sign in to comment.