Skip to content

Commit a96ee66

Browse files
committed
test(e2e): validate embed and watch page_type telemetry scenarios
1 parent 6752851 commit a96ee66

1 file changed

Lines changed: 88 additions & 25 deletions

File tree

scripts/e2e-player-telemetry.mjs

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ function leakHits(value, options = {}) {
630630
function eventSummary(events) {
631631
return events.map((event) => ({
632632
phase: event.phase,
633+
page_type: event.page_type,
633634
playback_session_id: event.playback_session_id,
634635
bootstrap_duration_ms: event.bootstrap_duration_ms,
635636
bootstrap_http_status: event.bootstrap_http_status,
@@ -654,7 +655,8 @@ async function scanPageAndBundles(siteBaseUrl, embedUrl) {
654655
const url = src.startsWith("http") ? src : `${siteBaseUrl}${src}`;
655656
const text = await fetch(url, { cache: "no-store" }).then((response) => response.text()).catch(() => "");
656657
const urlPath = new URL(url).pathname;
657-
const frameworkChunk = /\/_next\/static\/chunks\/(?:1eet_next_|%5Bturbopack%5D)/.test(urlPath);
658+
const frameworkChunk =
659+
/\/_next\/static\/chunks\/(?:[^/]+_next_dist_|%5Bturbopack%5D)/.test(urlPath);
658660
bundleResults.push({
659661
url_path: urlPath,
660662
byte_length: text.length,
@@ -713,20 +715,34 @@ function validatePlaybackEvents(events) {
713715
};
714716
}
715717

716-
async function runPlaybackScenario({ chromePort, siteBaseUrl, assetId, name, blockTelemetry = false }) {
718+
function validatePageType(events, pageType) {
719+
return events
720+
.filter((event) => event.phase !== "player_load")
721+
.every((event) => event.page_type === pageType);
722+
}
723+
724+
async function runPlaybackScenario({
725+
chromePort,
726+
siteBaseUrl,
727+
assetId,
728+
name,
729+
route = "embed",
730+
blockTelemetry = false,
731+
}) {
717732
const page = await newPage(chromePort);
718733
const capture = attachNetworkCapture(page);
719734
const blockedTelemetryCount = blockTelemetry ? await configureTelemetryBlock(page, siteBaseUrl) : () => 0;
720-
const embedUrl = `${siteBaseUrl}/embed/${encodeURIComponent(assetId)}?autoplay=1&playbackBaseUrl=${encodeURIComponent(edgeBaseUrl)}`;
735+
const playbackUrl = `${siteBaseUrl}/${route}/${encodeURIComponent(assetId)}?autoplay=1&playbackBaseUrl=${encodeURIComponent(edgeBaseUrl)}`;
721736

722-
await navigate(page, embedUrl);
737+
await navigate(page, playbackUrl);
723738
const playback = await waitForPlayback(page);
724739
const telemetryPosts = capture.telemetryPosts(siteBaseUrl);
725740
page.close();
726741

727742
return {
728743
name,
729-
url: embedUrl,
744+
route,
745+
url: playbackUrl,
730746
playback,
731747
telemetry_posts: telemetryPosts.map((request) => ({
732748
url_path: new URL(request.url).pathname,
@@ -815,42 +831,89 @@ async function main() {
815831

816832
try {
817833
log("driving browser playback through /embed");
818-
const playback = await runPlaybackScenario({
834+
const embedPlayback = await runPlaybackScenario({
835+
chromePort: chrome.port,
836+
siteBaseUrl: site.baseUrl,
837+
assetId,
838+
name: "local_embed_playback",
839+
route: "embed",
840+
});
841+
artifact.local.embed_playback = embedPlayback;
842+
843+
assertCheck("embed video reached readyState and advanced", embedPlayback.playback.readyState >= 2 && embedPlayback.playback.currentTime > 0.1, embedPlayback.playback);
844+
assertCheck("embed telemetry POST reached site endpoint", embedPlayback.telemetry_posts.some((post) => post.status === 200), embedPlayback.telemetry_posts);
845+
846+
const embedRecent = await waitForRecentEvents(site.baseUrl, assetId, embedPlayback.playback.playbackSessionId, [
847+
"player_load",
848+
"bootstrap_complete",
849+
"source_selected",
850+
"metadata_loaded",
851+
"canplay",
852+
"first_frame",
853+
]);
854+
artifact.local.embed_recent = {
855+
url: embedRecent.url,
856+
events: embedRecent.events,
857+
event_summary: eventSummary(embedRecent.events),
858+
};
859+
860+
const embedEventQuality = validatePlaybackEvents(embedRecent.events);
861+
artifact.local.embed_event_quality = embedEventQuality;
862+
assertCheck("embed telemetry contains same playback_session_id", embedRecent.events.every((event) => event.playback_session_id === embedPlayback.playback.playbackSessionId), {
863+
playback_session_id: embedPlayback.playback.playbackSessionId,
864+
count: embedRecent.events.length,
865+
});
866+
assertCheck("embed telemetry is labeled with page_type embed", validatePageType(embedRecent.events, "embed"), {
867+
event_summary: eventSummary(embedRecent.events),
868+
});
869+
assertCheck("embed bootstrap timing exists", embedEventQuality.bootstrap_timing, embedEventQuality);
870+
assertCheck("embed selected playback mode and artifact exist", embedEventQuality.source_selection, embedEventQuality);
871+
assertCheck("embed metadata/canplay/first-frame timing exists", embedEventQuality.metadata_timing && embedEventQuality.canplay_timing && embedEventQuality.first_frame_timing, embedEventQuality);
872+
assertCheck("embed stored telemetry is sanitized", leakHits(embedRecent.events, { noUrls: true }).length === 0, {
873+
leak_hits: leakHits(embedRecent.events, { noUrls: true }),
874+
});
875+
876+
log("driving browser playback through /watch");
877+
const watchPlayback = await runPlaybackScenario({
819878
chromePort: chrome.port,
820879
siteBaseUrl: site.baseUrl,
821880
assetId,
822-
name: "local_playback",
881+
name: "local_watch_playback",
882+
route: "watch",
823883
});
824-
artifact.local.playback = playback;
884+
artifact.local.watch_playback = watchPlayback;
825885

826-
assertCheck("browser video reached readyState and advanced", playback.playback.readyState >= 2 && playback.playback.currentTime > 0.1, playback.playback);
827-
assertCheck("telemetry POST reached site endpoint", playback.telemetry_posts.some((post) => post.status === 200), playback.telemetry_posts);
886+
assertCheck("watch video reached readyState and advanced", watchPlayback.playback.readyState >= 2 && watchPlayback.playback.currentTime > 0.1, watchPlayback.playback);
887+
assertCheck("watch telemetry POST reached site endpoint", watchPlayback.telemetry_posts.some((post) => post.status === 200), watchPlayback.telemetry_posts);
828888

829-
const recent = await waitForRecentEvents(site.baseUrl, assetId, playback.playback.playbackSessionId, [
889+
const watchRecent = await waitForRecentEvents(site.baseUrl, assetId, watchPlayback.playback.playbackSessionId, [
830890
"player_load",
831891
"bootstrap_complete",
832892
"source_selected",
833893
"metadata_loaded",
834894
"canplay",
835895
"first_frame",
836896
]);
837-
artifact.local.recent = {
838-
url: recent.url,
839-
events: recent.events,
840-
event_summary: eventSummary(recent.events),
897+
artifact.local.watch_recent = {
898+
url: watchRecent.url,
899+
events: watchRecent.events,
900+
event_summary: eventSummary(watchRecent.events),
841901
};
842902

843-
const eventQuality = validatePlaybackEvents(recent.events);
844-
artifact.local.event_quality = eventQuality;
845-
assertCheck("recent telemetry contains same playback_session_id", recent.events.every((event) => event.playback_session_id === playback.playback.playbackSessionId), {
846-
playback_session_id: playback.playback.playbackSessionId,
847-
count: recent.events.length,
903+
const watchEventQuality = validatePlaybackEvents(watchRecent.events);
904+
artifact.local.watch_event_quality = watchEventQuality;
905+
assertCheck("watch telemetry contains same playback_session_id", watchRecent.events.every((event) => event.playback_session_id === watchPlayback.playback.playbackSessionId), {
906+
playback_session_id: watchPlayback.playback.playbackSessionId,
907+
count: watchRecent.events.length,
908+
});
909+
assertCheck("watch telemetry is labeled with page_type watch", validatePageType(watchRecent.events, "watch"), {
910+
event_summary: eventSummary(watchRecent.events),
848911
});
849-
assertCheck("bootstrap timing exists", eventQuality.bootstrap_timing, eventQuality);
850-
assertCheck("selected playback mode and artifact exist", eventQuality.source_selection, eventQuality);
851-
assertCheck("metadata/canplay/first-frame timing exists", eventQuality.metadata_timing && eventQuality.canplay_timing && eventQuality.first_frame_timing, eventQuality);
852-
assertCheck("stored telemetry is sanitized", leakHits(recent.events, { noUrls: true }).length === 0, {
853-
leak_hits: leakHits(recent.events, { noUrls: true }),
912+
assertCheck("watch bootstrap timing exists", watchEventQuality.bootstrap_timing, watchEventQuality);
913+
assertCheck("watch selected playback mode and artifact exist", watchEventQuality.source_selection, watchEventQuality);
914+
assertCheck("watch metadata/canplay/first-frame timing exists", watchEventQuality.metadata_timing && watchEventQuality.canplay_timing && watchEventQuality.first_frame_timing, watchEventQuality);
915+
assertCheck("watch stored telemetry is sanitized", leakHits(watchRecent.events, { noUrls: true }).length === 0, {
916+
leak_hits: leakHits(watchRecent.events, { noUrls: true }),
854917
});
855918

856919
log("checking unavailable asset telemetry");

0 commit comments

Comments
 (0)