Skip to content

Commit

Permalink
Merge pull request #1327 from oasisprotocol/lw/e2e-analytics
Browse files Browse the repository at this point in the history
Add e2e tests for analytics
  • Loading branch information
lukaw3d authored Mar 14, 2024
2 parents 3710ea1 + 5441a4b commit 191469f
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 4 deletions.
1 change: 1 addition & 0 deletions .changelog/1327.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Integrate matomo analytics
9 changes: 9 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ const config = {
],
},
],
'no-restricted-syntax': [
'error',
{
selector:
'MemberExpression[object.object.name="process"][object.property.name="env"][property.name="REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS"]',
message:
'Replace with window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS to support overriding in e2e tests',
},
],
'prefer-template': 'error',

'react/jsx-no-target-blank': 'off', // Not needed with modern browsers
Expand Down
94 changes: 94 additions & 0 deletions playwright/tests/analytics.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import '../../src/types/global.d.ts'
import { Page, expect, test } from '@playwright/test'

async function setup(page: Page, mode: 'allow-matomo-lib' | 'block-matomo-lib') {
await page.route('**/v1/', route => {
// Don't respond
})
await page.route('https://matomo.oasis.io/matomo.php?**', route => {
// Don't send tracked events
})
await page.route('https://matomo.oasis.io/matomo.js', async route => {
if (mode === 'allow-matomo-lib') route.continue()
if (mode === 'block-matomo-lib') route.abort('blockedbyclient')
})

const matomoRequests: string[] = []
page.on('request', request => {
if (request.url().startsWith('https://matomo.oasis.io/')) matomoRequests.push(request.url())
})

await page.goto('http://localhost:1234/mainnet/sapphire/block')
await expect(page.getByText('Latest Blocks')).toBeVisible()
await page.waitForTimeout(100)

return {
getMatomoRequests: () => matomoRequests,
}
}

test.describe('analytics', () => {
test('enabled', async ({ page }) => {
await page.addInitScript(() => (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS = 'true'))
const { getMatomoRequests } = await setup(page, 'allow-matomo-lib')
await expect(page.getByText('tracking')).toBeVisible()
await expect(page.getByRole('button', { name: 'Privacy Settings' })).toBeVisible()
expect(getMatomoRequests()).toHaveLength(1) // Loaded library

await page.getByRole('link', { name: 'Oasis Explorer' }).click()
await page.getByRole('button', { name: 'Decline' }).click()
expect(getMatomoRequests()).toHaveLength(1)

await page.getByRole('button', { name: 'Privacy Settings' }).click()
await page.getByRole('button', { name: 'Accept' }).click()
await page.waitForTimeout(1)
expect(getMatomoRequests()).toHaveLength(2) // Tracked

await page.getByRole('link', { name: 'Blocks' }).first().click()
await page.waitForRequest('https://matomo.oasis.io/matomo.php?**') // Debounced
await page.waitForTimeout(1)
expect(getMatomoRequests()).toHaveLength(3) // Tracked
})

test('adblocked', async ({ page }) => {
await page.addInitScript(() => (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS = 'true'))
const { getMatomoRequests } = await setup(page, 'block-matomo-lib')
await expect(page.getByText('tracking')).not.toBeVisible()
await expect(page.getByRole('button', { name: 'Privacy Settings' })).toBeVisible()
expect(getMatomoRequests()).toHaveLength(1) // Tried to load library
await page.getByRole('link', { name: 'Oasis Explorer' }).click()
await page.getByRole('button', { name: 'Privacy Settings' }).click()
await expect(page.getByText('tracking failed')).toBeVisible()
expect(getMatomoRequests()).toHaveLength(1) // No new requests
})

test('disabled in env', async ({ page }) => {
await page.addInitScript(() => (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS = 'false'))
const { getMatomoRequests } = await setup(page, 'allow-matomo-lib')
await expect(page.getByText('tracking')).not.toBeVisible()
await expect(page.getByRole('button', { name: 'Privacy Settings' })).not.toBeVisible()
expect(getMatomoRequests()).toHaveLength(0)
await page.getByRole('link', { name: 'Oasis Explorer' }).click()
expect(getMatomoRequests()).toHaveLength(0)
})

test('pre-consented and then disabled in env', async ({ page }) => {
await page.addInitScript(() => (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS = 'true'))
const { getMatomoRequests } = await setup(page, 'allow-matomo-lib')
await test.step('consent', async () => {
expect(getMatomoRequests()).toHaveLength(1) // Loaded library
await page.getByRole('button', { name: 'Accept' }).click()
await page.waitForTimeout(1)
expect(getMatomoRequests()).toHaveLength(2) // Tracked
})

await page.addInitScript(() => (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS = 'false'))
await page.goto('http://localhost:1234/mainnet/sapphire/block')
await page.waitForTimeout(100)
await expect(page.getByText('tracking')).not.toBeVisible()
await expect(page.getByRole('button', { name: 'Privacy Settings' })).not.toBeVisible()
expect(getMatomoRequests()).toHaveLength(2) // No new requests
await page.getByRole('link', { name: 'Oasis Explorer' }).click()
expect(getMatomoRequests()).toHaveLength(2) // No new requests
})
})
4 changes: 4 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>
// Allow e2e tests to pre-define it in runtime
window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS ??= "$REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS"
</script>
<script type="module" src="../src/index.tsx"></script>
</body>
</html>
6 changes: 3 additions & 3 deletions src/app/components/AnalyticsConsent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable react-hooks/rules-of-hooks -- REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS can't change in runtime */
/* eslint-disable react-hooks/rules-of-hooks -- REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS won't change in runtime */
import { createContext, useContext, useEffect, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { styled } from '@mui/material/styles'
Expand All @@ -17,7 +17,7 @@ const AnalyticsContext = createContext<{
} | null>(null)

export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) => {
if (process.env.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <>{props.children}</>
if (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <>{props.children}</>

const [hasAccepted, setHasAccepted] = useState<
matomo.HasAccepted | 'loading' | 'timed_out_matomo_not_loaded_force_open'
Expand Down Expand Up @@ -87,7 +87,7 @@ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) =
}

export const ReopenAnalyticsConsentButton = () => {
if (process.env.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <></>
if (window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <></>

const { t } = useTranslation()
const context = useContext(AnalyticsContext)
Expand Down
7 changes: 6 additions & 1 deletion src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ declare global {
REACT_APP_BUILD_DATETIME: string
REACT_APP_BUILD_SHA: string
REACT_APP_BUILD_VERSION: string
REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS: 'true' | 'false'
/** Access it through {@link window.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS} instead, to support overriding it in e2e tests */
REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS: never
REACT_APP_API: string
REACT_APP_TESTNET_API: string
REACT_APP_SHOW_BUILD_BANNERS: 'true' | 'false'
Expand All @@ -29,6 +30,10 @@ declare global {
REACT_APP_SHOW_FIAT_VALUES: 'true' | 'false'
}
}

interface Window {
REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS: 'true' | 'false'
}
}

export {}

0 comments on commit 191469f

Please sign in to comment.