Skip to content

Commit

Permalink
Add route support (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiaslins authored Feb 16, 2024
1 parent 8b1c58f commit 5a011aa
Show file tree
Hide file tree
Showing 31 changed files with 695 additions and 99 deletions.
2 changes: 1 addition & 1 deletion .github/composite-actions/install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ runs:
using: composite
steps:
- name: Set up Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.16.1
18.19.0
11 changes: 11 additions & 0 deletions apps/nextjs/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Link from 'next/link';

export default function BlogPage({ params }: { params: { slug: string } }) {
return (
<div>
<h2>{params.slug}</h2>

<Link href="/blog">Back to blog</Link>
</div>
);
}
11 changes: 11 additions & 0 deletions apps/nextjs/app/blog/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Link from 'next/link';

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div>
<Link href="/blog/my-first-blogpost">My first blog post</Link>
<Link href="/blog/new-feature-release">Feature just got released</Link>
<div>{children}</div>
</div>
);
}
3 changes: 3 additions & 0 deletions apps/nextjs/app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Blog() {
return <div>Welcome on the blog</div>;
}
7 changes: 6 additions & 1 deletion apps/nextjs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Analytics } from '@vercel/analytics/next';

export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
Expand All @@ -10,7 +12,10 @@ export default function RootLayout({
}) {
return (
<html lang="en">
<body>{children}</body>
<body>
<Analytics />
{children}
</body>
</html>
);
}
25 changes: 0 additions & 25 deletions apps/nextjs/components/withAnalytics.tsx

This file was deleted.

20 changes: 19 additions & 1 deletion apps/nextjs/e2e/development/beforeSend.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ test.describe('beforeSend', () => {
page,
}) => {
const messages: string[] = [];
await useMockForProductionScript({
page,
onPageView: () => {},
debug: true,
});

page.on('console', (msg) => {
const message = msg.text();
Expand All @@ -28,6 +33,19 @@ test.describe('beforeSend', () => {

await page.waitForLoadState('networkidle');

expect(messages).toHaveLength(5);
expect(
messages.find((m) =>
m.includes('[pageview] http://localhost:3000/before-send/first')
)
).toBeDefined();
expect(
messages.find((m) =>
m.includes(
'[pageview] http://localhost:3000/before-send/second?secret=REDACTED'
)
)
).toBeDefined();

expect(messages.find((m) => m.includes('secret=vercel'))).toBeUndefined();
});
});
21 changes: 17 additions & 4 deletions apps/nextjs/e2e/development/pageview.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { test, expect } from '@playwright/test';
import { useMockForProductionScript } from '../utils';

test.describe('pageview', () => {
test('should track page views when navigating between pages', async ({
page,
}) => {
const messages: string[] = [];
await useMockForProductionScript({
page,
onPageView: () => {},
debug: true,
});

page.on('console', (msg) => {
const message = msg.text();

console.log(message);

if (
message.includes('[Vercel Web Analytics]') ||
message.includes('[Vercel Analytics]')
Expand All @@ -20,7 +24,7 @@ test.describe('pageview', () => {
});

await page.goto('/navigation/first');
await page.waitForTimeout(200);
await page.waitForTimeout(800);

await page.click('text=Next');

Expand All @@ -29,6 +33,15 @@ test.describe('pageview', () => {

await page.waitForTimeout(200);

expect(messages).toHaveLength(3);
expect(
messages.find((m) =>
m.includes('[pageview] http://localhost:3000/navigation/first')
)
).toBeDefined();
expect(
messages.find((m) =>
m.includes('[pageview] http://localhost:3000/navigation/second')
)
).toBeDefined();
});
});
4 changes: 2 additions & 2 deletions apps/nextjs/e2e/production/beforeSend.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test.describe('beforeSend', () => {
payload: {
o: 'http://localhost:3000/before-send/first',
sv: expect.any(String),
sdkn: '@vercel/analytics',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
ts: expect.any(Number),
r: '',
Expand All @@ -42,7 +42,7 @@ test.describe('beforeSend', () => {
o: 'http://localhost:3000/before-send/second?secret=REDACTED',
ts: expect.any(Number),
sv: expect.any(String),
sdkn: '@vercel/analytics',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
},
},
Expand Down
130 changes: 128 additions & 2 deletions apps/nextjs/e2e/production/pageview.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ test.describe('pageview', () => {
ts: expect.any(Number),
r: '',
sv: expect.any(String),
sdkn: '@vercel/analytics',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
dp: '/navigation/first',
},
},
{
Expand All @@ -42,8 +43,133 @@ test.describe('pageview', () => {
o: 'http://localhost:3000/navigation/second',
ts: expect.any(Number),
sv: expect.any(String),
sdkn: '@vercel/analytics',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
dp: '/navigation/second',
},
},
]);
});

test('should properly send dynamic route', async ({ page }) => {
const payloads: { page: string; payload: Object }[] = [];

await useMockForProductionScript({
page,
onPageView: (page, payload) => {
payloads.push({ page, payload });
},
});

await page.goto('/blog');
await page.waitForLoadState('networkidle');

await page.click('text=My first blog post');

await expect(page).toHaveURL('/blog/my-first-blogpost');
await expect(page.locator('h2')).toContainText('my-first-blogpost');

await page.waitForLoadState('networkidle');

await page.click('text=Back to blog');

await page.waitForLoadState('networkidle');
await expect(page).toHaveURL('/blog');

await page.click('text=Feature just got released');

await expect(page.locator('h2')).toContainText('new-feature-release');

expect(payloads).toEqual([
{
page: 'http://localhost:3000/blog',
payload: {
dp: '/blog',
o: 'http://localhost:3000/blog',
r: '',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
},
},
{
page: 'http://localhost:3000/blog/my-first-blogpost',
payload: {
dp: '/blog/[slug]',
o: 'http://localhost:3000/blog/my-first-blogpost',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
},
},
{
page: 'http://localhost:3000/blog',
payload: {
dp: '/blog',
o: 'http://localhost:3000/blog',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
},
},
{
page: 'http://localhost:3000/blog/new-feature-release',
payload: {
dp: '/blog/[slug]',
o: 'http://localhost:3000/blog/new-feature-release',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
},
},
]);
});

test('should send pageviews when route doesnt change but path does', async ({
page,
}) => {
const payloads: { page: string; payload: Object }[] = [];

await useMockForProductionScript({
page,
onPageView: (page, payload) => {
payloads.push({ page, payload });
},
});

await page.goto('/blog/my-first-blogpost');
await page.waitForLoadState('networkidle');

await page.click('text=Feature just got released');

await expect(page.locator('h2')).toContainText('new-feature-release');

expect(payloads).toEqual([
{
page: 'http://localhost:3000/blog/my-first-blogpost',
payload: {
dp: '/blog/[slug]',
o: 'http://localhost:3000/blog/my-first-blogpost',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
r: '',
},
},
{
page: 'http://localhost:3000/blog/new-feature-release',
payload: {
dp: '/blog/[slug]',
o: 'http://localhost:3000/blog/new-feature-release',
sdkn: '@vercel/analytics/next',
sdkv: expect.any(String),
sv: expect.any(String),
ts: expect.any(Number),
},
},
]);
Expand Down
7 changes: 6 additions & 1 deletion apps/nextjs/e2e/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { Page } from '@playwright/test';
export async function useMockForProductionScript(props: {
page: Page;
onPageView: (page: string, payload: Object) => void;
debug?: boolean;
}) {
await props.page.route('**/_vercel/insights/script.js', async (route, _) => {
return route.fulfill({
status: 301,
headers: { location: 'https://cdn.vercel-insights.com/v1/script.js' },
headers: {
location: props.debug
? 'https://cdn.vercel-insights.com/v1/script.debug.js'
: 'https://cdn.vercel-insights.com/v1/script.js',
},
});
});

Expand Down
1 change: 1 addition & 0 deletions apps/nextjs/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const nextConfig = {
experimental: {
serverActions: true,
},
// reactStrictMode: false,
};

module.exports = nextConfig;
2 changes: 1 addition & 1 deletion apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@vercel/analytics": "workspace:*",
"next": "13.5.4",
"next": "14.1.0",
"react": "18.2.0",
"react-dom": "18.2.0"
},
Expand Down
22 changes: 22 additions & 0 deletions apps/nextjs/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Analytics } from '@vercel/analytics/next';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Analytics
beforeSend={(event) => {
const url = new URL(event.url);
if (url.searchParams.has('secret')) {
url.searchParams.set('secret', 'REDACTED');
}
return {
...event,
url: url.toString(),
};
}}
/>
<Component {...pageProps} />
</>
);
}
Loading

0 comments on commit 5a011aa

Please sign in to comment.