Skip to content

test: add playwright script that proxies Amplitude scripts to test customer pages#1682

Open
daniel-graham-amplitude wants to merge 11 commits into
mainfrom
ai-week-playwright-mcp
Open

test: add playwright script that proxies Amplitude scripts to test customer pages#1682
daniel-graham-amplitude wants to merge 11 commits into
mainfrom
ai-week-playwright-mcp

Conversation

@daniel-graham-amplitude
Copy link
Copy Markdown
Collaborator

@daniel-graham-amplitude daniel-graham-amplitude commented Apr 15, 2026

Summary

Checklist

  • Does your PR title have the correct title format?
  • Does your PR have a breaking change?:

Note

Medium Risk
Primarily adds dev/test tooling (Playwright proxy + Vite middleware) but also introduces new analytics-browser source files that could affect packaging/bundling if inadvertently wired into production exports.

Overview
Adds a new headed Playwright script (e2e/manual-test.js) that proxies a target website to swap Amplitude CDN script URLs to a local Vite dev server, strips SRI integrity hashes (including inside GTM scripts), and optionally rewrites event ingestion requests with a provided AMPLITUDE_API_KEY.

Updates the local test-server to better support this workflow by adding Private Network Access CORS handling (Access-Control-Allow-Private-Network), adjusting Vite plugin ordering so this middleware runs first, and fixing the gzip middleware to append (not overwrite) the Vary header.

Includes local unified-script artifacts (test-server/unified-script-local*.js), adds playwright as a dev dependency, extends .gitignore for Playwright MCP traces, and adds new analytics-browser source stubs (browser-client-precision.ts, default-instance.ts).

Reviewed by Cursor Bugbot for commit f7f5ca8. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for all 3 issues found in the latest run.

  • ✅ Fixed: Playwright added as production dependency instead of dev
    • Moved playwright from dependencies to devDependencies so it is not installed in production contexts.
  • ✅ Fixed: Playwright version mismatch with @playwright/test dependency
    • Pinned playwright to 1.55.0 to match the existing @playwright/test version and updated lockfile entries accordingly.
  • ✅ Fixed: ESM import syntax in .js without "type": "module"
    • Converted e2e/manual-test.js to CommonJS (require) and corrected usage text/comments so it runs with plain Node.js.

Create PR

Or push these changes by commenting:

@cursor push 7665094b95
Preview (7665094b95)
diff --git a/e2e/manual-test.js b/e2e/manual-test.js
--- a/e2e/manual-test.js
+++ b/e2e/manual-test.js
@@ -1,12 +1,12 @@
-// playwright-proxy.ts
-import { chromium } from 'playwright';
+// playwright-proxy.js
+const { chromium } = require('playwright');
 
 // Get URL from command line args
 const targetUrl = process.argv[2];
 
 if (!targetUrl) {
-  console.error('Usage: npx ts-node playwright-proxy.ts <url>');
-  console.error('Example: npx ts-node playwright-proxy.ts https://example.com');
+  console.error('Usage: node e2e/manual-test.js <url>');
+  console.error('Example: node e2e/manual-test.js https://example.com');
   process.exit(1);
 }
 

diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -78,6 +78,7 @@
     "morgan": "^1.10.0",
     "nodemon": "^3.0.1",
     "nx": "^21.2.1",
+    "playwright": "1.55.0",
     "prettier": "^2.8.1",
     "rimraf": "^3.0.2",
     "source-map": "^0.7.4",
@@ -95,7 +96,6 @@
     ]
   },
   "dependencies": {
-    "playwright": "^1.59.1",
     "tslib": "^2.4.1"
   },
   "packageManager": "pnpm@10.26.1+sha512.664074abc367d2c9324fdc18037097ce0a8f126034160f709928e9e9f95d98714347044e5c3164d65bd5da6c59c6be362b107546292a8eecb7999196e5ce58fa"

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,9 +8,6 @@
 
   .:
     dependencies:
-      playwright:
-        specifier: ^1.59.1
-        version: 1.59.1
       tslib:
         specifier: ^2.4.1
         version: 2.8.1
@@ -111,6 +108,9 @@
       nx:
         specifier: ^21.2.1
         version: 21.6.8
+      playwright:
+        specifier: 1.55.0
+        version: 1.55.0
       prettier:
         specifier: ^2.8.1
         version: 2.8.8

You can send follow-ups to the cloud agent here.

Comment thread package.json Outdated
Comment thread package.json Outdated
Comment thread e2e/manual-test.js
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 4 total unresolved issues (including 3 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Usage error message references wrong filename and command
    • Updated e2e/manual-test.js to reference the correct script filename and invocation command in both the header comment and missing-argument usage/example messages.

Create PR

Or push these changes by commenting:

@cursor push d8388b0d1d
Preview (d8388b0d1d)
diff --git a/e2e/manual-test.js b/e2e/manual-test.js
--- a/e2e/manual-test.js
+++ b/e2e/manual-test.js
@@ -1,12 +1,12 @@
-// playwright-proxy.ts
+// manual-test.js
 import { chromium } from 'playwright';
 
 // Get URL from command line args
 const targetUrl = process.argv[2];
 
 if (!targetUrl) {
-  console.error('Usage: npx ts-node playwright-proxy.ts <url>');
-  console.error('Example: npx ts-node playwright-proxy.ts https://example.com');
+  console.error('Usage: node ./e2e/manual-test.js <website-url>');
+  console.error('Example: node ./e2e/manual-test.js https://example.com');
   process.exit(1);
 }

You can send follow-ups to the cloud agent here.

Comment thread e2e/manual-test.js Outdated
@daniel-graham-amplitude daniel-graham-amplitude changed the title add playwright script that proxies unified scripts on customer pages test: add playwright script that proxies Amplitude scripts to test customer pages Apr 16, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

There are 4 total unresolved issues (including 1 from previous review).

Autofix Details

Bugbot Autofix prepared fixes for all 3 issues found in the latest run.

  • ✅ Fixed: replace only strips first occurrence of each hash
    • Replaced hash stripping calls with replaceAll so every occurrence of each integrity hash is removed in GTM and document rewrite paths.
  • ✅ Fixed: Redundant duplicate hash stripping for HTML documents
    • Removed the second HTML-specific integrity stripping loop and fulfilled HTML responses directly from the already-stripped content.
  • ✅ Fixed: Non-HTML fulfill path missing encoding header removal
    • Updated the non-HTML fulfill branch to set status and dropped encoding/length headers before returning the decompressed text body.

Create PR

Or push these changes by commenting:

@cursor push 8a47623b97
Preview (8a47623b97)
diff --git a/e2e/manual-test.js b/e2e/manual-test.js
--- a/e2e/manual-test.js
+++ b/e2e/manual-test.js
@@ -71,7 +71,7 @@
         const response = await route.fetch();
         let body = await response.text();
         for (const hash of INTEGRITY_HASHES) {
-          body = body.replace(hash, '');
+          body = body.replaceAll(hash, '');
         }
         await route.fulfill({
           status: response.status(),
@@ -102,23 +102,22 @@
     }
     let content = await response.text();
     for (const hash of INTEGRITY_HASHES) {
-      content = content.replace(hash, '');
+      content = content.replaceAll(hash, '');
     }
 
     const ct = (response.headers()['content-type'] || '').toLowerCase();
     if (!ct.includes('text/html')) {
-      return route.fulfill({ response, body: content });
+      return route.fulfill({
+        status: response.status(),
+        headers: dropEncodingHeaders(response.headers()),
+        body: content,
+      });
     }
-    let html = content;
 
-    for (const hash of INTEGRITY_HASHES) {
-      html = html.replace(hash, '');
-    }
-
     await route.fulfill({
       status: response.status(),
       headers: dropEncodingHeaders(response.headers()),
-      body: html,
+      body: content,
     });
   });

You can send follow-ups to the cloud agent here.

Comment thread e2e/manual-test.js
Comment thread e2e/manual-test.js
Comment thread e2e/manual-test.js Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 5 total unresolved issues (including 4 from previous reviews).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Debug console.log accidentally committed in production SDK
    • Removed the accidental console.log('AI WEEK CODING CHANGES') from AmplitudeBrowser.init so SDK initialization no longer emits debug output.

Create PR

Or push these changes by commenting:

@cursor push 337b19c541
Preview (337b19c541)
diff --git a/packages/analytics-browser/src/browser-client.ts b/packages/analytics-browser/src/browser-client.ts
--- a/packages/analytics-browser/src/browser-client.ts
+++ b/packages/analytics-browser/src/browser-client.ts
@@ -97,7 +97,6 @@
   init(apiKey = '', userIdOrOptions?: string | BrowserOptions, maybeOptions?: BrowserOptions) {
     let userId: string | undefined;
     let options: BrowserOptions | undefined;
-    console.log('AI WEEK CODING CHANGES');
     if (arguments.length > 2) {
       userId = userIdOrOptions as string | undefined;
       options = maybeOptions;

You can send follow-ups to the cloud agent here.

Comment thread packages/analytics-browser/src/browser-client.ts Outdated
Copy link
Copy Markdown
Contributor

@Mercy811 Mercy811 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Dan!

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Production file rewritten with "dummy patch" comment
    • Removed the accidental analytics-browser production source files, including the dummy-patch default instance and unused precision client file.

Create PR

Or push these changes by commenting:

@cursor push f853e39994
Preview (f853e39994)
diff --git a/packages/analytics-browser/src/browser-client-precision.ts b/packages/analytics-browser/src/browser-client-precision.ts
deleted file mode 100644
--- a/packages/analytics-browser/src/browser-client-precision.ts
+++ /dev/null
@@ -1,356 +1,0 @@
-import {
-  AmplitudeCore,
-  Identify,
-  returnWrapper,
-  Revenue,
-  UUID,
-  getAnalyticsConnector,
-  setConnectorDeviceId,
-  setConnectorUserId,
-  isNewSession,
-  getQueryParams,
-  Event,
-  EventOptions,
-  IIdentify,
-  IRevenue,
-  TransportTypeOrOptions,
-  Result,
-  BrowserOptions,
-  BrowserConfig,
-  BrowserClient,
-  AnalyticsClient,
-  AnalyticsIdentity,
-  createIdentifyEvent,
-  Logger,
-  safeJsonStringify,
-  LogLevel,
-} from '@amplitude/analytics-core';
-import { convertProxyObjectToRealObject, isInstanceProxy } from './utils/snippet-helper';
-import { useBrowserConfig, createTransport } from './config';
-import { DEFAULT_SERVER_ZONE } from './constants';
-
-const UNSPECIFIED_SESSION_ID = -1;
-
-/**
- * Exported for `@amplitude/unified` or integration with blade plugins.
- * If you only use `@amplitude/analytics-browser`, use `amplitude.init()` or `amplitude.createInstance()` instead.
- */
-export class AmplitudeBrowser extends AmplitudeCore implements BrowserClient, AnalyticsClient {
-  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-  // @ts-ignore
-  config: BrowserConfig;
-  previousSessionDeviceId: string | undefined;
-  previousSessionUserId: string | undefined;
-
-  // Backdoor to set diagnostics sample rate
-  // by calling amplitude._setDiagnosticsSampleRate(1); before amplitude.init()
-  _diagnosticsSampleRate = 0;
-
-  // Backdoor to test request body compression
-  // by calling amplitude._enableRequestBodyCompressionExperimental(true); before amplitude.init()
-  _enableRequestBodyCompressionExperimentalValue = false;
-
-  init(apiKey = '', userIdOrOptions?: string | BrowserOptions, maybeOptions?: BrowserOptions) {
-    let userId: string | undefined;
-    let options: BrowserOptions | undefined;
-    if (arguments.length > 2) {
-      userId = userIdOrOptions as string | undefined;
-      options = maybeOptions;
-    } else {
-      if (typeof userIdOrOptions === 'string') {
-        userId = userIdOrOptions;
-        options = undefined;
-      } else {
-        userId = userIdOrOptions?.userId;
-        options = userIdOrOptions;
-      }
-    }
-    return returnWrapper(this._init({ ...options, userId, apiKey }));
-  }
-  protected async _init(options: BrowserOptions & { apiKey: string }) {
-    // Step 1: Block concurrent initialization
-    if (this.initializing) {
-      return;
-    }
-    this.initializing = true;
-
-    // Set up early dependencies needed for remote config client
-    // These use options directly or fall back to defaults
-    const loggerProvider = options.loggerProvider ?? new Logger();
-    if (!options.loggerProvider) {
-      loggerProvider.enable(options.logLevel ?? LogLevel.Warn);
-    }
-    const serverZone = options.serverZone ?? DEFAULT_SERVER_ZONE;
-
-    // Step 2.4: Create browser config with diagnosticsClient and earlyConfig
-    // earlyConfig ensures consistent logger/serverZone/diagnostics settings across all components
-    const browserOptions = await useBrowserConfig(options.apiKey, options, this, {
-      loggerProvider,
-      serverZone,
-    });
-
-    await super._init(browserOptions);
-    this.logBrowserOptions(browserOptions);
-
-    // Step 3: Set session ID
-    // Priority 1: `options.sessionId`
-    // Priority 2: sessionId from url if it's Number and ampTimestamp is valid
-    // Priority 3: last known sessionId from user identity storage
-    // Default: `Date.now()`
-    // Session ID is handled differently than device ID and user ID due to session events
-    const queryParams = getQueryParams();
-
-    // Check if ampTimestamp is present and valid
-    const ampTimestamp = queryParams.ampTimestamp ? Number(queryParams.ampTimestamp) : undefined;
-    const isWithinTimeLimit = ampTimestamp ? Date.now() < ampTimestamp : true;
-
-    // check if we need to set the sessionId
-    const querySessionId =
-      isWithinTimeLimit && !Number.isNaN(Number(queryParams.ampSessionId))
-        ? Number(queryParams.ampSessionId)
-        : undefined;
-
-    let deferredSessionId = this.config.deferredSessionId;
-    if (deferredSessionId === UNSPECIFIED_SESSION_ID && !this.config.optOut) {
-      deferredSessionId = Date.now();
-    }
-
-    this.setSessionId(options.sessionId ?? querySessionId ?? deferredSessionId ?? this.config.sessionId);
-
-    if (this.config.optOut) {
-      this.timeline.addOptOutListener(async (optOut) => {
-        if (!optOut && this.config.deferredSessionId) {
-          if (this.config.deferredSessionId === UNSPECIFIED_SESSION_ID) {
-            this.setSessionId(undefined);
-          } else {
-            this.setSessionId(this.config.deferredSessionId);
-          }
-        }
-      });
-    }
-
-    // Set up the analytics connector to integrate with the experiment SDK.
-    // Send events from the experiment SDK and forward identifies to the
-    // identity store.
-    const connector = getAnalyticsConnector(options.instanceName);
-    connector.identityStore.setIdentity({
-      userId: this.config.userId,
-      deviceId: this.config.deviceId,
-    });
-
-    // no plugins because precision
-
-    this.initializing = false;
-
-    // Step 6: Run queued dispatch functions
-    await this.runQueuedFunctions('dispatchQ');
-
-    // Step 7: Add the event receiver after running remaining queued functions.
-    connector.eventBridge.setEventReceiver((event) => {
-      const { time, ...cleanEventProperties } = event.eventProperties || {};
-      const eventOptions = typeof time === 'number' ? { time } : undefined;
-      void this.track(event.eventType, cleanEventProperties, eventOptions);
-    });
-  }
-
-  getUserId() {
-    return this.config?.userId;
-  }
-
-  setUserId(userId: string | undefined) {
-    if (!this.config) {
-      this.q.push(this.setUserId.bind(this, userId));
-      return;
-    }
-    this.config.loggerProvider.debug('function setUserId: ', userId);
-    if (userId !== this.config.userId || userId === undefined) {
-      this.config.userId = userId;
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-      this.timeline.onIdentityChanged({ userId: userId });
-      setConnectorUserId(userId, this.config.instanceName);
-    }
-  }
-
-  getDeviceId() {
-    return this.config?.deviceId;
-  }
-
-  setDeviceId(deviceId: string) {
-    if (!this.config) {
-      this.q.push(this.setDeviceId.bind(this, deviceId));
-      return;
-    }
-    this.config.loggerProvider.debug('function setDeviceId: ', deviceId);
-    if (deviceId !== this.config.deviceId) {
-      this.config.deviceId = deviceId;
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-      this.timeline.onIdentityChanged({ deviceId: deviceId });
-      setConnectorDeviceId(deviceId, this.config.instanceName);
-    }
-  }
-
-  reset() {
-    this.setDeviceId(UUID());
-    this.setUserId(undefined);
-    this.timeline.onReset();
-  }
-
-  getIdentity() {
-    return {
-      deviceId: this.config?.deviceId,
-      userId: this.config?.userId,
-      userProperties: this.userProperties,
-    };
-  }
-
-  setIdentity(identity: Partial<AnalyticsIdentity>) {
-    // Handle userId change
-    if ('userId' in identity) {
-      this.setUserId(identity.userId);
-    }
-
-    // Handle deviceId change
-    if ('deviceId' in identity && identity.deviceId) {
-      this.setDeviceId(identity.deviceId);
-    }
-
-    // Handle userProperties change - auto-send identify
-    if ('userProperties' in identity) {
-      this.userProperties = identity.userProperties;
-      // Auto-send identify event with $set operations
-      const identifyObj = new Identify();
-      // istanbul ignore next
-      const userProperties = identity.userProperties ?? {};
-      for (const [key, value] of Object.entries(userProperties)) {
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
-        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
-        identifyObj.set(key, value);
-      }
-      // The identify event processing in core-client already calls onIdentityChanged,
-      // so we don't need to call it explicitly here to avoid duplicate notifications.
-      this.identify(identifyObj);
-    }
-  }
-
-  getOptOut(): boolean | undefined {
-    return this.config?.optOut;
-  }
-
-  getSessionId() {
-    return this.config?.sessionId;
-  }
-
-  setSessionId(sessionId: number | undefined) {
-    const promises: Promise<Result>[] = [];
-    if (!this.config) {
-      this.q.push(this.setSessionId.bind(this, sessionId));
-      return returnWrapper(Promise.resolve());
-    }
-    // do not start a new session if optOut is true
-    if (this.config.optOut) {
-      // save the sessionId to storage to be used when optOut is false
-      this.config.deferredSessionId = sessionId ?? UNSPECIFIED_SESSION_ID;
-      return returnWrapper(Promise.resolve());
-    }
-
-    // default sessionId to current time
-    if (sessionId === undefined) {
-      sessionId = Date.now();
-    }
-
-    // Prevents starting a new session with the same session ID
-    if (sessionId === this.config.sessionId) {
-      return returnWrapper(Promise.resolve());
-    }
-
-    this.config.loggerProvider.debug('function setSessionId: ', sessionId);
-
-    const previousSessionId = this.getSessionId();
-    if (previousSessionId !== sessionId) {
-      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-      this.timeline.onSessionIdChanged(sessionId);
-    }
-
-    this.config.sessionId = sessionId;
-    this.config.lastEventTime = undefined;
-    this.config.pageCounter = 0;
-
-    // track the identify event if an Identify object is provided in the config
-    if (this.config.identify) {
-      promises.push(this.track(createIdentifyEvent(this.config.identify)).promise);
-    }
-
-    this.previousSessionDeviceId = this.config.deviceId;
-    this.previousSessionUserId = this.config.userId;
-    return returnWrapper(Promise.all(promises));
-  }
-
-  extendSession() {
-    if (!this.config) {
-      this.q.push(this.extendSession.bind(this));
-      return;
-    }
-    this.config.lastEventTime = Date.now();
-  }
-
-  setTransport(transport: TransportTypeOrOptions) {
-    if (!this.config) {
-      this.q.push(this.setTransport.bind(this, transport));
-      return;
-    }
-    this.config.transportProvider = createTransport(transport);
-  }
-
-  identify(identify: IIdentify, eventOptions?: EventOptions) {
-    if (isInstanceProxy(identify)) {
-      const queue = identify._q;
-      identify._q = [];
-      identify = convertProxyObjectToRealObject(new Identify(), queue);
-    }
-    if (eventOptions?.user_id) {
-      this.setUserId(eventOptions.user_id);
-    }
-    if (eventOptions?.device_id) {
-      this.setDeviceId(eventOptions.device_id);
-    }
-    return super.identify(identify, eventOptions);
-  }
-
-  groupIdentify(groupType: string, groupName: string | string[], identify: IIdentify, eventOptions?: EventOptions) {
-    if (isInstanceProxy(identify)) {
-      const queue = identify._q;
-      identify._q = [];
-      identify = convertProxyObjectToRealObject(new Identify(), queue);
-    }
-    return super.groupIdentify(groupType, groupName, identify, eventOptions);
-  }
-
-  revenue(revenue: IRevenue, eventOptions?: EventOptions) {
-    if (isInstanceProxy(revenue)) {
-      const queue = revenue._q;
-      revenue._q = [];
-      revenue = convertProxyObjectToRealObject(new Revenue(), queue);
-    }
-    return super.revenue(revenue, eventOptions);
-  }
-
-  async process(event: Event) {
-    return super.process(event);
-  }
-
-  private logBrowserOptions(browserConfig: BrowserOptions & { apiKey: string }) {
-    try {
-      const browserConfigCopy = {
-        ...browserConfig,
-        apiKey: browserConfig.apiKey.substring(0, 10) + '********',
-      };
-      this.config.loggerProvider.debug(
-        'Initialized Amplitude with BrowserConfig:',
-        safeJsonStringify(browserConfigCopy),
-      );
-    } catch (e) {
-      /* istanbul ignore next */
-      this.config.loggerProvider.error('Error logging browser config', e);
-    }
-  }
-}
\ No newline at end of file

diff --git a/packages/analytics-browser/src/default-instance.ts b/packages/analytics-browser/src/default-instance.ts
deleted file mode 100644
--- a/packages/analytics-browser/src/default-instance.ts
+++ /dev/null
@@ -1,30 +1,0 @@
-/* eslint-disable @typescript-eslint/unbound-method */
-// dummy patch analytics-browser to force GTM deploy
-import client from './browser-client-factory';
-
-export const {
-  add,
-  extendSession,
-  flush,
-  getDeviceId,
-  getIdentity,
-  getOptOut,
-  getSessionId,
-  getUserId,
-  groupIdentify,
-  identify,
-  init,
-  logEvent,
-  remove,
-  reset,
-  revenue,
-  setDeviceId,
-  setGroup,
-  setIdentity,
-  setOptOut,
-  setSessionId,
-  setTransport,
-  setUserId,
-  track,
-  _setDiagnosticsSampleRate,
-} = client;
\ No newline at end of file

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit f7f5ca8. Configure here.

setUserId,
track,
_setDiagnosticsSampleRate,
} = client;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Production file rewritten with "dummy patch" comment

High Severity

The default-instance.ts file — a production SDK export file — is completely rewritten with the comment "dummy patch analytics-browser to force GTM deploy." This appears to be an unrelated deployment workaround accidentally included in a test-only PR. Similarly, browser-client-precision.ts is added but never imported anywhere in the codebase (no references found via grep), making it dead code. Both changes modify the published analytics-browser package and don't belong in a PR titled "test: add playwright script."

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f7f5ca8. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants