Skip to content

Commit 6874605

Browse files
committed
Update tests transformRequest tests
1 parent 1531386 commit 6874605

File tree

4 files changed

+223
-15
lines changed

4 files changed

+223
-15
lines changed

tracker/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
src/p.js
22
src/plausible.js
3+
npm_package/plausible.js
34
node_modules/

tracker/test/outbound-links.spec.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ for (const mode of ['web', 'esm']) {
3131
fulfill: {
3232
status: 200,
3333
contentType: 'text/html',
34-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
34+
body: OTHER_PAGE_BODY
3535
},
3636
awaitedRequestCount: 1
3737
})
@@ -78,7 +78,7 @@ for (const mode of ['web', 'esm']) {
7878
fulfill: {
7979
status: 200,
8080
contentType: 'text/html',
81-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
81+
body: OTHER_PAGE_BODY
8282
},
8383
awaitedRequestCount: 1
8484
})
@@ -151,7 +151,7 @@ for (const mode of ['legacy', 'web'])
151151
fulfill: {
152152
status: 200,
153153
contentType: 'text/html',
154-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
154+
body: OTHER_PAGE_BODY
155155
},
156156
awaitedRequestCount: 1
157157
})
@@ -201,7 +201,7 @@ for (const mode of ['legacy', 'web'])
201201
fulfill: {
202202
status: 200,
203203
contentType: 'text/html',
204-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
204+
body: OTHER_PAGE_BODY
205205
},
206206
awaitedRequestCount: 1
207207
})
@@ -253,7 +253,7 @@ for (const mode of ['legacy', 'web'])
253253
fulfill: {
254254
status: 200,
255255
contentType: 'text/html',
256-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
256+
body: OTHER_PAGE_BODY
257257
},
258258
awaitedRequestCount: 1
259259
})
@@ -340,7 +340,7 @@ test.describe('outbound links feature when using legacy .compat extension', () =
340340
fulfill: {
341341
status: 200,
342342
contentType: 'text/html',
343-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
343+
body: OTHER_PAGE_BODY
344344
},
345345
awaitedRequestCount: 2,
346346
mockRequestTimeout: 2000
@@ -396,7 +396,7 @@ test.describe('outbound links feature when using legacy .compat extension', () =
396396
fulfill: {
397397
status: 200,
398398
contentType: 'text/html',
399-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
399+
body: OTHER_PAGE_BODY
400400
},
401401
awaitedRequestCount: 1
402402
})
@@ -448,7 +448,7 @@ test.describe('outbound links feature when using legacy .compat extension', () =
448448
fulfill: {
449449
status: 200,
450450
contentType: 'text/html',
451-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
451+
body: OTHER_PAGE_BODY
452452
},
453453
awaitedRequestCount: 1
454454
})
@@ -478,7 +478,7 @@ test.describe('outbound links feature when using legacy .compat extension', () =
478478
fulfill: {
479479
status: 200,
480480
contentType: 'text/html',
481-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
481+
body: OTHER_PAGE_BODY
482482
},
483483
awaitedRequestCount: 2,
484484
mockRequestTimeout: 2000
@@ -522,3 +522,13 @@ test.describe('outbound links feature when using legacy .compat extension', () =
522522
})
523523
})
524524
})
525+
526+
const OTHER_PAGE_BODY = /* HTML */ `<!DOCTYPE html>
527+
<html>
528+
<head>
529+
<title>other page</title>
530+
</head>
531+
<body>
532+
other page
533+
</body>
534+
</html>`

tracker/test/tagged-events.spec.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,15 @@ test.beforeEach(async ({ page }) => {
2626
await route.fulfill({
2727
status: 200,
2828
contentType: 'text/html',
29-
body: '<!DOCTYPE html><html><head><title>mocked page</title></head><body>mocked page</body></html>'
29+
body: /* HTML */ `<!DOCTYPE html>
30+
<html>
31+
<head>
32+
<title>mocked page</title>
33+
</head>
34+
<body>
35+
mocked page
36+
</body>
37+
</html>`
3038
})
3139
})
3240
})
@@ -40,7 +48,7 @@ for (const mode of ['web', 'esm']) {
4048
testId,
4149
scriptConfig: switchByMode(
4250
{
43-
web: { ...DEFAULT_CONFIG },
51+
web: config,
4452
esm: `<script type="module">import { init, track } from '/tracker/js/npm_package/plausible.js'; init(${JSON.stringify(
4553
config
4654
)})</script>`
@@ -457,8 +465,12 @@ for (const mode of ['legacy', 'web']) {
457465
action: () => page.click('circle'),
458466
expectedRequests: [
459467
{
460-
n: 'link click'
461-
// bug with p.url, can't assert
468+
n: 'link click',
469+
p: {
470+
expected: { url: {} },
471+
__expectation__: (actual) =>
472+
actual && JSON.stringify(actual) === '{"url":{}}'
473+
}
462474
}
463475
],
464476
shouldIgnoreRequest: [isPageviewEvent, isEngagementEvent]
@@ -568,7 +580,15 @@ test.describe('tagged events feature when using legacy .compat extension', () =>
568580
fulfill: {
569581
status: 200,
570582
contentType: 'text/html',
571-
body: '<!DOCTYPE html><html><head><title>other page</title></head><body>other page</body></html>'
583+
body: /* HTML */ `<!DOCTYPE html>
584+
<html>
585+
<head>
586+
<title>other page</title>
587+
</head>
588+
<body>
589+
other page
590+
</body>
591+
</html>`
572592
},
573593
awaitedRequestCount: 2,
574594
mockRequestTimeout: 2000
Lines changed: 178 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import {
66
e,
77
expectPlausibleInAction,
88
hideAndShowCurrentTab,
9+
isPageviewEvent,
910
isEngagementEvent,
1011
switchByMode
1112
} from './support/test-utils'
12-
import { test } from '@playwright/test'
13+
import { test, expect } from '@playwright/test'
1314
import { ScriptConfig } from './support/types'
1415
import { LOCAL_SERVER_ADDR } from './support/server'
16+
1517
const DEFAULT_CONFIG: ScriptConfig = {
1618
domain: 'example.com',
1719
endpoint: `${LOCAL_SERVER_ADDR}/api/event`,
@@ -263,3 +265,178 @@ for (const mode of ['web', 'esm']) {
263265
})
264266
})
265267
}
268+
269+
test.describe(`transformRequest examples from /docs work`, () => {
270+
test.beforeEach(async ({ page }) => {
271+
await page
272+
.context()
273+
.route(new RegExp('(http|https)://example\\.com.*'), async (route) => {
274+
await route.fulfill({
275+
status: 200,
276+
contentType: 'text/html',
277+
body: /* HTML */ `<!DOCTYPE html>
278+
<html>
279+
<head>
280+
<title>mocked page</title>
281+
</head>
282+
<body>
283+
mocked page
284+
</body>
285+
</html>`
286+
})
287+
})
288+
})
289+
290+
test('you can omit automatically tracked url property from tagged link clicks', async ({
291+
page
292+
}, { testId }) => {
293+
function omitAutomaticUrlProperty(payload) {
294+
if (payload.p && payload.p.url) {
295+
delete payload.p.url
296+
}
297+
return payload
298+
}
299+
const config = {
300+
...DEFAULT_CONFIG,
301+
transformRequest: omitAutomaticUrlProperty
302+
}
303+
const { url } = await initializePageDynamically(page, {
304+
testId,
305+
scriptConfig: config,
306+
bodyContent: /* HTML */ `<a
307+
class="plausible-event-name=Purchase plausible-event-discounted=true"
308+
href="https://example.com/target?user=sensitive"
309+
>Purchase</a
310+
>`
311+
})
312+
313+
await expectPlausibleInAction(page, {
314+
action: async () => {
315+
await page.goto(url)
316+
await page.click('a')
317+
},
318+
expectedRequests: [
319+
{
320+
n: 'Purchase',
321+
p: { discounted: 'true' } // <-- no url property
322+
}
323+
],
324+
shouldIgnoreRequest: [isPageviewEvent, isEngagementEvent]
325+
})
326+
await expect(page.getByText('mocked page')).toBeVisible()
327+
})
328+
329+
for (const { hashBasedRouting, urlSuffix, expectedUrlSuffix } of [
330+
{
331+
hashBasedRouting: true,
332+
urlSuffix:
333+
'?utm_source=example&utm_medium=referral&utm_campaign=test#fragment',
334+
expectedUrlSuffix: '#fragment'
335+
},
336+
{
337+
hashBasedRouting: false,
338+
urlSuffix: '?utm_source=example&utm_medium=referral&utm_campaign=test',
339+
expectedUrlSuffix: ''
340+
}
341+
]) {
342+
test(`you can omit UTM properties from pageview urls (hashBasedRouting: ${hashBasedRouting})`, async ({
343+
page
344+
}, { testId }) => {
345+
function omitUTMProperties(payload) {
346+
const parts = payload.u.split('?')
347+
let urlWithoutQuery = parts.shift()
348+
349+
if (payload.h) {
350+
const fragment = parts.join('?').split('#')[1]
351+
urlWithoutQuery =
352+
typeof fragment === 'string'
353+
? urlWithoutQuery + '#' + fragment
354+
: urlWithoutQuery
355+
}
356+
357+
payload.u = urlWithoutQuery
358+
return payload
359+
}
360+
361+
const config = {
362+
...DEFAULT_CONFIG,
363+
hashBasedRouting,
364+
transformRequest: omitUTMProperties
365+
}
366+
367+
// the star path is needed for the dynamic page to load when accessing it with query params
368+
const path = '*'
369+
const { url } = await initializePageDynamically(page, {
370+
testId,
371+
path,
372+
scriptConfig: config,
373+
bodyContent: ''
374+
})
375+
376+
const [actualUrl] = url.split('*')
377+
378+
await expectPlausibleInAction(page, {
379+
action: async () => {
380+
await page.goto(`${actualUrl}${urlSuffix}`)
381+
// await page.click('a')
382+
},
383+
expectedRequests: [
384+
{
385+
n: 'pageview',
386+
u: `${LOCAL_SERVER_ADDR}${actualUrl}${expectedUrlSuffix}`
387+
}
388+
],
389+
shouldIgnoreRequest: [isEngagementEvent]
390+
})
391+
})
392+
}
393+
394+
test('you can track pages using their canonical url', async ({ page }, {
395+
testId
396+
}) => {
397+
function rewriteUrlToCanonicalUrl(payload) {
398+
// Get the canonical URL element
399+
const canonicalMeta = document.querySelector('link[rel="canonical"]')
400+
// Use the canonical URL if it exists, falling back on the regular URL when it doesn't.
401+
if (canonicalMeta) {
402+
// @ts-expect-error - canonicalMeta definitely has the href attribute
403+
payload.u = canonicalMeta.href + window.location.search
404+
}
405+
return payload
406+
}
407+
408+
// the star path is needed for the dynamic page to load when accessing it with query params
409+
const nonCanonicalPath = '/products/clothes/shoes/banana-leather-shoe*'
410+
const { url } = await initializePageDynamically(page, {
411+
testId,
412+
path: nonCanonicalPath,
413+
scriptConfig: /* HTML */ `
414+
<link rel="canonical" href="/products/banana-leather-shoe" />
415+
<script type="module">
416+
import { init, track } from '/tracker/js/npm_package/plausible.js'
417+
init(
418+
${serializeWithFunctions({
419+
...DEFAULT_CONFIG,
420+
transformRequest: rewriteUrlToCanonicalUrl
421+
})}
422+
)
423+
</script>
424+
`,
425+
bodyContent: ''
426+
})
427+
const [actualUrl] = url.split('*')
428+
429+
await expectPlausibleInAction(page, {
430+
action: async () => {
431+
await page.goto(`${actualUrl}?utm_source=example`)
432+
},
433+
expectedRequests: [
434+
{
435+
n: 'pageview',
436+
u: `${LOCAL_SERVER_ADDR}/products/banana-leather-shoe?utm_source=example`
437+
}
438+
],
439+
shouldIgnoreRequest: [isEngagementEvent]
440+
})
441+
})
442+
})

0 commit comments

Comments
 (0)