From 59af3b2298faf5c102ea8699fe918c739345234e Mon Sep 17 00:00:00 2001 From: Ayu Date: Wed, 11 Sep 2024 19:07:04 +0300 Subject: [PATCH] fix(tracker): add trailing slash to data-api option (#147) * fix(tracker): add trailing slash to data api * test: add e2e testing for data-api option --- bun.lockb | Bin 320456 -> 320456 bytes tracker/README.md | 6 ++--- tracker/dist/click-events.js | 2 +- tracker/dist/click-events.min.js | 2 +- tracker/dist/click-events.page-events.js | 2 +- tracker/dist/click-events.page-events.min.js | 2 +- tracker/dist/default.js | 2 +- tracker/dist/default.min.js | 2 +- tracker/dist/page-events.js | 2 +- tracker/dist/page-events.min.js | 2 +- tracker/package.json | 4 +-- tracker/playwright.config.js | 3 +-- tracker/src/tracker.js | 2 +- tracker/tests/data-api.spec.js | 21 +++++++++++++++ tracker/tests/fixtures/data-api/index.html | 26 +++++++++++++++++++ tracker/tests/fixtures/serve.js | 2 +- 16 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 tracker/tests/data-api.spec.js create mode 100644 tracker/tests/fixtures/data-api/index.html diff --git a/bun.lockb b/bun.lockb index 70da5a392cd958605dd32cf4fcd20bafb13fb244..48f620ad7a3bdfe8518bbae839f3380b47ffb350 100644 GIT binary patch delta 168 zcmV;Z09XIW#}mlM6Ob+-D%bs^W#-6@?vS;X;AEccj&>kNxkhNHxME`_N;n>Zu}+rr z0U(pnF)NeM-wA^m^tT!G0USR-zj3X@axC8XaQ`_>BGS z%8Q?>yzNWWKpE$z*=ol+;ibpH5zQe1Gn=pfi WGA=N;<=+FV{sS^DFt?N51T_UQV@^l_ delta 168 zcmV;Z09XIW#}mlM6Ob+-;zDCSnq1Q<0v``7%naTwOqy6@M`OhlyQ&x} zZU_dh#p#s=Y!*8jH&BcgLmxgqzO@bizOTNp4rveuhjlXow{ WF)lN=<=+FV{sS>CHn)@B1T_WjDMuy% diff --git a/tracker/README.md b/tracker/README.md index 4eecdbc..8cf298c 100644 --- a/tracker/README.md +++ b/tracker/README.md @@ -10,9 +10,9 @@ Our tracker is designed with compression in mind, given that web traffic is usua | File | Size | Compressed (gzip) | Compressed (brotli) | | --------------------- | -------------------- | ------------------- | ------------------- | -| `default.min.js` | 1512 bytes (1.48 KB) | 766 bytes (0.75 KB) | 620 bytes (0.61 KB) | -| `page-events.min.js` | 1750 bytes (1.71 KB) | 890 bytes (0.87 KB) | 731 bytes (0.71 KB) | -| `click-events.min.js` | 1991 bytes (1.94 KB) | 977 bytes (0.95 KB) | 792 bytes (0.77 KB) | +| `default.min.js` | 1513 bytes (1.48 KB) | 768 bytes (0.75 KB) | 621 bytes (0.61 KB) | +| `page-events.min.js` | 1751 bytes (1.71 KB) | 891 bytes (0.87 KB) | 732 bytes (0.71 KB) | +| `click-events.min.js` | 1992 bytes (1.95 KB) | 973 bytes (0.95 KB) | 793 bytes (0.77 KB) | The listed sizes only show the size of the tracker itself with one specific feature. When combining multiple features, the size of the tracker will relatively increase (although some features may share code with each other). diff --git a/tracker/dist/click-events.js b/tracker/dist/click-events.js index 8624685..18d82cd 100644 --- a/tracker/dist/click-events.js +++ b/tracker/dist/click-events.js @@ -54,7 +54,7 @@ * src attribute to determine the host. */ const host = currentScript.getAttribute('data-api') - ? `${location.protocol}//${currentScript.getAttribute('data-api')}` + ? `${location.protocol}//${currentScript.getAttribute('data-api')}/` : // @ts-ignore - We know this won't be an SVGScriptElement. currentScript.src.replace(/[^\/]+$/, 'api/'); diff --git a/tracker/dist/click-events.min.js b/tracker/dist/click-events.min.js index cb9905f..0b99116 100644 --- a/tracker/dist/click-events.min.js +++ b/tracker/dist/click-events.min.js @@ -1 +1 @@ -!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,i=Date.now(),r=!1;const c=history.pushState,s=history.replaceState,d=()=>{o=!1,a=n(),i=Date.now(),r=!1},p=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),d(),t.apply(this,arguments),h()):t.apply(this,arguments)},u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone}),mode:"no-cors"})}))},l=()=>{r||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-i})),r=!0},m=t=>{if(t.button>1||!(t.target instanceof HTMLElement))return;const n=(t.target.getAttribute("data-m:click")||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{});Object.keys(n).length>0&&fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"custom",g:location.hostname,d:n}),mode:"no-cors"})};for(const t of document.querySelectorAll("[data-m\\:click]"))t.addEventListener("click",m),t.addEventListener("auxclick",m);"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=p(c),history.replaceState=p(s),addEventListener("popstate",(()=>{l(),d(),h()}),{capture:!0}))}))}(); \ No newline at end of file +!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}/`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,i=Date.now(),r=!1;const c=history.pushState,s=history.replaceState,d=()=>{o=!1,a=n(),i=Date.now(),r=!1},p=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),d(),t.apply(this,arguments),h()):t.apply(this,arguments)},u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone}),mode:"no-cors"})}))},l=()=>{r||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-i})),r=!0},m=t=>{if(t.button>1||!(t.target instanceof HTMLElement))return;const n=(t.target.getAttribute("data-m:click")||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{});Object.keys(n).length>0&&fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"custom",g:location.hostname,d:n}),mode:"no-cors"})};for(const t of document.querySelectorAll("[data-m\\:click]"))t.addEventListener("click",m),t.addEventListener("auxclick",m);"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=p(c),history.replaceState=p(s),addEventListener("popstate",(()=>{l(),d(),h()}),{capture:!0}))}))}(); \ No newline at end of file diff --git a/tracker/dist/click-events.page-events.js b/tracker/dist/click-events.page-events.js index 9bd184b..042a9d7 100644 --- a/tracker/dist/click-events.page-events.js +++ b/tracker/dist/click-events.page-events.js @@ -54,7 +54,7 @@ * src attribute to determine the host. */ const host = currentScript.getAttribute('data-api') - ? `${location.protocol}//${currentScript.getAttribute('data-api')}` + ? `${location.protocol}//${currentScript.getAttribute('data-api')}/` : // @ts-ignore - We know this won't be an SVGScriptElement. currentScript.src.replace(/[^\/]+$/, 'api/'); diff --git a/tracker/dist/click-events.page-events.min.js b/tracker/dist/click-events.page-events.min.js index 410073a..f1574d0 100644 --- a/tracker/dist/click-events.page-events.min.js +++ b/tracker/dist/click-events.page-events.min.js @@ -1 +1 @@ -!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,r=Date.now(),i=!1;const c=history.pushState,d=history.replaceState,s=()=>{o=!1,a=n(),r=Date.now(),i=!1},l=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(m(),s(),t.apply(this,arguments),h()):t.apply(this,arguments)},p=(t,e)=>(t.getAttribute("data-m:"+e)||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{}),u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone,d:[...document.querySelectorAll("[data-m\\:load]")].reduce(((t,e)=>({...t,...p(e,"load")})),{})}),mode:"no-cors"})}))},m=()=>{i||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-r})),i=!0},g=t=>{if(t.button>1||!(t.target instanceof HTMLElement))return;const n=p(t.target,"click");Object.keys(n).length>0&&fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"custom",g:location.hostname,d:n}),mode:"no-cors"})};for(const t of document.querySelectorAll("[data-m\\:click]"))t.addEventListener("click",g),t.addEventListener("auxclick",g);"onpagehide"in self?addEventListener("pagehide",m,{capture:!0}):(addEventListener("beforeunload",m,{capture:!0}),addEventListener("unload",m,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&m()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=l(c),history.replaceState=l(d),addEventListener("popstate",(()=>{m(),s(),h()}),{capture:!0}))}))}(); \ No newline at end of file +!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}/`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,r=Date.now(),i=!1;const c=history.pushState,d=history.replaceState,s=()=>{o=!1,a=n(),r=Date.now(),i=!1},l=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(m(),s(),t.apply(this,arguments),h()):t.apply(this,arguments)},p=(t,e)=>(t.getAttribute("data-m:"+e)||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{}),u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone,d:[...document.querySelectorAll("[data-m\\:load]")].reduce(((t,e)=>({...t,...p(e,"load")})),{})}),mode:"no-cors"})}))},m=()=>{i||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-r})),i=!0},g=t=>{if(t.button>1||!(t.target instanceof HTMLElement))return;const n=p(t.target,"click");Object.keys(n).length>0&&fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"custom",g:location.hostname,d:n}),mode:"no-cors"})};for(const t of document.querySelectorAll("[data-m\\:click]"))t.addEventListener("click",g),t.addEventListener("auxclick",g);"onpagehide"in self?addEventListener("pagehide",m,{capture:!0}):(addEventListener("beforeunload",m,{capture:!0}),addEventListener("unload",m,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&m()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=l(c),history.replaceState=l(d),addEventListener("popstate",(()=>{m(),s(),h()}),{capture:!0}))}))}(); \ No newline at end of file diff --git a/tracker/dist/default.js b/tracker/dist/default.js index 497a7c9..399fcd3 100644 --- a/tracker/dist/default.js +++ b/tracker/dist/default.js @@ -54,7 +54,7 @@ * src attribute to determine the host. */ const host = currentScript.getAttribute('data-api') - ? `${location.protocol}//${currentScript.getAttribute('data-api')}` + ? `${location.protocol}//${currentScript.getAttribute('data-api')}/` : // @ts-ignore - We know this won't be an SVGScriptElement. currentScript.src.replace(/[^\/]+$/, 'api/'); diff --git a/tracker/dist/default.min.js b/tracker/dist/default.min.js index 85baeef..ed44e54 100644 --- a/tracker/dist/default.min.js +++ b/tracker/dist/default.min.js @@ -1 +1 @@ -!function(){if(!document)return;const e=document.currentScript,t=e.getAttribute("data-api")?`${location.protocol}//${e.getAttribute("data-api")}`:e.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,i=Date.now(),r=!1;const s=history.pushState,d=history.replaceState,p=()=>{o=!1,a=n(),i=Date.now(),r=!1},c=e=>function(t,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),p(),e.apply(this,arguments),u()):e.apply(this,arguments)},h=e=>new Promise((t=>{const n=new XMLHttpRequest;n.onload=()=>{t(0==n.responseText)},n.open("GET",e),n.setRequestHeader("Content-Type","text/plain"),n.send()})),u=async()=>{h(t+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((e=>{fetch(t+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:e,t:Intl.DateTimeFormat().resolvedOptions().timeZone}),mode:"no-cors"})}))},l=()=>{r||navigator.sendBeacon(t+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-i})),r=!0};"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),h(t+"event/ping").then((t=>{o=t,u(),e.getAttribute("data-hash")?addEventListener("hashchange",u,{capture:!0}):(history.pushState=c(s),history.replaceState=c(d),addEventListener("popstate",(()=>{l(),p(),u()}),{capture:!0}))}))}(); \ No newline at end of file +!function(){if(!document)return;const e=document.currentScript,t=e.getAttribute("data-api")?`${location.protocol}//${e.getAttribute("data-api")}/`:e.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,i=Date.now(),r=!1;const s=history.pushState,d=history.replaceState,p=()=>{o=!1,a=n(),i=Date.now(),r=!1},c=e=>function(t,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),p(),e.apply(this,arguments),u()):e.apply(this,arguments)},h=e=>new Promise((t=>{const n=new XMLHttpRequest;n.onload=()=>{t(0==n.responseText)},n.open("GET",e),n.setRequestHeader("Content-Type","text/plain"),n.send()})),u=async()=>{h(t+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((e=>{fetch(t+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:e,t:Intl.DateTimeFormat().resolvedOptions().timeZone}),mode:"no-cors"})}))},l=()=>{r||navigator.sendBeacon(t+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-i})),r=!0};"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),h(t+"event/ping").then((t=>{o=t,u(),e.getAttribute("data-hash")?addEventListener("hashchange",u,{capture:!0}):(history.pushState=c(s),history.replaceState=c(d),addEventListener("popstate",(()=>{l(),p(),u()}),{capture:!0}))}))}(); \ No newline at end of file diff --git a/tracker/dist/page-events.js b/tracker/dist/page-events.js index fd230bd..7e4d935 100644 --- a/tracker/dist/page-events.js +++ b/tracker/dist/page-events.js @@ -54,7 +54,7 @@ * src attribute to determine the host. */ const host = currentScript.getAttribute('data-api') - ? `${location.protocol}//${currentScript.getAttribute('data-api')}` + ? `${location.protocol}//${currentScript.getAttribute('data-api')}/` : // @ts-ignore - We know this won't be an SVGScriptElement. currentScript.src.replace(/[^\/]+$/, 'api/'); diff --git a/tracker/dist/page-events.min.js b/tracker/dist/page-events.min.js index cfb6f3e..4703456 100644 --- a/tracker/dist/page-events.min.js +++ b/tracker/dist/page-events.min.js @@ -1 +1 @@ -!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,r=Date.now(),i=!1;const d=history.pushState,s=history.replaceState,c=()=>{o=!1,a=n(),r=Date.now(),i=!1},p=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),c(),t.apply(this,arguments),h()):t.apply(this,arguments)},u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone,d:[...document.querySelectorAll("[data-m\\:load]")].reduce(((t,e)=>{return{...t,...(n=e,(n.getAttribute("data-m:load")||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{}))};var n}),{})}),mode:"no-cors"})}))},l=()=>{i||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-r})),i=!0};"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=p(d),history.replaceState=p(s),addEventListener("popstate",(()=>{l(),c(),h()}),{capture:!0}))}))}(); \ No newline at end of file +!function(){if(!document)return;const t=document.currentScript,e=t.getAttribute("data-api")?`${location.protocol}//${t.getAttribute("data-api")}/`:t.src.replace(/[^\/]+$/,"api/"),n=()=>Date.now().toString(36)+Math.random().toString(36).substr(2);let a=n(),o=!0,r=Date.now(),i=!1;const d=history.pushState,s=history.replaceState,c=()=>{o=!1,a=n(),r=Date.now(),i=!1},p=t=>function(e,n,a){a&&location.pathname!==new URL(a,location.href).pathname?(l(),c(),t.apply(this,arguments),h()):t.apply(this,arguments)},u=t=>new Promise((e=>{const n=new XMLHttpRequest;n.onload=()=>{e(0==n.responseText)},n.open("GET",t),n.setRequestHeader("Content-Type","text/plain"),n.send()})),h=async()=>{u(e+"event/ping?u="+encodeURIComponent(location.host+location.pathname)).then((t=>{fetch(e+"event/hit",{method:"POST",body:JSON.stringify({b:a,e:"load",u:location.href,r:document.referrer,p:o,q:t,t:Intl.DateTimeFormat().resolvedOptions().timeZone,d:[...document.querySelectorAll("[data-m\\:load]")].reduce(((t,e)=>{return{...t,...(n=e,(n.getAttribute("data-m:load")||"").split(";").reduce(((t,e)=>{const[n,a]=e.split("=").map((t=>t.trim()));return n&&a&&(t[n]=a),t}),{}))};var n}),{})}),mode:"no-cors"})}))},l=()=>{i||navigator.sendBeacon(e+"event/hit",JSON.stringify({b:a,e:"unload",m:Date.now()-r})),i=!0};"onpagehide"in self?addEventListener("pagehide",l,{capture:!0}):(addEventListener("beforeunload",l,{capture:!0}),addEventListener("unload",l,{capture:!0})),addEventListener("visibilitychange",(()=>{document.hidden&&l()}),{capture:!0}),u(e+"event/ping").then((e=>{o=e,h(),t.getAttribute("data-hash")?addEventListener("hashchange",h,{capture:!0}):(history.pushState=p(d),history.replaceState=p(s),addEventListener("popstate",(()=>{l(),c(),h()}),{capture:!0}))}))}(); \ No newline at end of file diff --git a/tracker/package.json b/tracker/package.json index f910edc..52bc24f 100644 --- a/tracker/package.json +++ b/tracker/package.json @@ -4,11 +4,11 @@ "author": "Ayuhito", "main": "dist/default.js", "devDependencies": { - "@playwright/test": "^1.45.3", + "@playwright/test": "^1.47.0", "brotli-size": "^4.0.0", "gzip-size": "^7.0.0", "preprocess": "^3.2.0", - "terser": "^5.31.3" + "terser": "^5.32.0" }, "description": "Tracker script for Medama Analytics", "license": "MIT", diff --git a/tracker/playwright.config.js b/tracker/playwright.config.js index d1006c2..60baa67 100644 --- a/tracker/playwright.config.js +++ b/tracker/playwright.config.js @@ -76,8 +76,7 @@ module.exports = defineConfig({ timeout: 2500, }, { - command: - 'task start -- start -logger=pretty -level=warn -corsorigins=http://localhost:8080,http://localhost:3000', + command: 'task dev -- start', port: 8080, reuseExistingServer: !process.env.CI, cwd: '../core', diff --git a/tracker/src/tracker.js b/tracker/src/tracker.js index ed3779b..e1cf30c 100644 --- a/tracker/src/tracker.js +++ b/tracker/src/tracker.js @@ -54,7 +54,7 @@ * src attribute to determine the host. */ const host = currentScript.getAttribute('data-api') - ? `${location.protocol}//${currentScript.getAttribute('data-api')}` + ? `${location.protocol}//${currentScript.getAttribute('data-api')}/` : // @ts-ignore - We know this won't be an SVGScriptElement. currentScript.src.replace(/[^\/]+$/, 'api/'); diff --git a/tracker/tests/data-api.spec.js b/tracker/tests/data-api.spec.js new file mode 100644 index 0000000..5ae122a --- /dev/null +++ b/tracker/tests/data-api.spec.js @@ -0,0 +1,21 @@ +// @ts-check + +import { test, expect } from '@playwright/test'; + +test.describe('data-api', () => { + test('data-api connects to alternative api', async ({ page }) => { + const requests = []; + await page.on('request', (request) => { + console.log('>>', request.method(), request.url()); + if (request.url().includes('/api/event')) requests.push(request.url()); + }); + + await page.goto('/data-api/index.html', { waitUntil: 'load' }); + await page.waitForLoadState(); + + expect(requests.length).toBeGreaterThan(0); + for (const url of requests) { + expect(url).toContain('example.com'); + } + }); +}); diff --git a/tracker/tests/fixtures/data-api/index.html b/tracker/tests/fixtures/data-api/index.html new file mode 100644 index 0000000..4321634 --- /dev/null +++ b/tracker/tests/fixtures/data-api/index.html @@ -0,0 +1,26 @@ + + + + + + Normal Webpage + + + +

Normal Webpage

+ +
+

This is the home page.

+ + + +
+ + + + \ No newline at end of file diff --git a/tracker/tests/fixtures/serve.js b/tracker/tests/fixtures/serve.js index 738cced..f0d9df0 100644 --- a/tracker/tests/fixtures/serve.js +++ b/tracker/tests/fixtures/serve.js @@ -1,4 +1,4 @@ -const ACCEPTED_PATHS = ['/simple', '/history']; +const ACCEPTED_PATHS = ['/simple', '/history', '/data-api']; console.log('Serving on http://localhost:3000'); Bun.serve({