☰
Sentry JavaScript E2E 测试实战:solid-static —— 用纯静态 Solid SPA 验证 @sentry/solid 的完整机制
2026/9/25 2:57:37 网站建设 项目流程
  • 可观测性

【免费下载链接】sentry-javascript

Official Sentry SDKs for JavaScript

项目地址:https://gitcode.com/gh_mirrors/se/sentry-javascript
点击查看免费下载

本篇指南以 sentry-javascript 仓库中 solid-static 测试应用 为核心,讲清这个纯静态部署的 Solid 单页应用如何在端到端(E2E)测试体系中被构建、被注入本地构建的 Sentry SDK、以及如何通过 Playwright + 事件代理服务器验证错误捕获、错误边界与页面加载事务(pageload transaction)的完整链路。读完本文,你将掌握:该模板的可用脚本与部署方式、Sentry.init中每个参数的作用(尤其是traceLifecycle: 'static'与tunnel代理)、以及如何在仓库内实际运行这个 E2E 应用并理解其测试断言原理。

一、solid-static 在仓库中的定位

solid-static 位于dev-packages/e2e-tests/test-applications/目录下,是 sentry-javascript 单体仓库 E2E 测试体系中的一员。需要先明确它的定位:根据 E2E 测试总 README 的警告说明,这些测试应用不是用来当示例项目或模板的,它们可能包含用于向后兼容测试的过期依赖版本、甚至有意保留的已知安全漏洞。它的真正目的是"验证本仓库各包如同已发布状态下的实际行为"(verify the behavior of the packages in this repository as if they were to be published)。

具体到 solid-static,它依赖的是@sentry/solid(官方 Solid 平台 SDK,见 packages/solid),用于在真实浏览器环境中验证:

  • 未捕获异常(uncaught error)能否被全局 handler 捕获并上报;
  • Solid 错误边界(ErrorBoundary)配合withSentryErrorBoundary的受控捕获(handled error)是否带上正确的 mechanism;
  • 页面加载事务(pageload transaction)的op、origin、事务名等字段是否符合预期。

二、模板特性与可用脚本(README 核心内容)

模板 README 说明了该应用的三个要点,本文按 README 原脉络逐一展开并结合源码补充。

2.1 模板目标:展示 Solid 的路由能力

README 指出,该模板的目标是展示 Solid 的路由(routing)功能,并展示路由与 Suspense 如何协作、通过.data.ts模式将数据获取与路由并行化(这一模式属于 Solid 生态@solidjs/router的路由数据加载范式)。

对照当前快照的源码可以看到其路由组织方式:routes.ts 定义了四条路由,其中参数化路由/user/:id与 404 兜底路由**均采用lazy(() => import(...))懒加载,配合 Solid 的 Suspense 实现按路由切分的代码分割:

export const routes = [ { path: '/', component: Home }, { path: '/user/:id', component: lazy(() => import('./pages/user')) }, { path: '/error-boundary-example', component: ErrorBoundaryExample }, { path: '**', component: lazy(() => import('./errors/404')) }, ];

导航骨架由 pageroot.tsx 提供,使用@solidjs/router的<A>组件渲染 Home / Error Boundary Example / Error 三个导航入口。

2.2 依赖管理与安装方式

README 明确说明:模板依赖通过 pnpm 维护(pnpm up -Lri全链路升级),仓库中能看到pnpm-lock.yaml即源于此;不过任何包管理器都可用,克隆模板后该锁文件可以安全删除。基本安装命令:

npm install # 或 pnpm install 或 yarn install

查看 package.json 可以印证依赖构成:运行时依赖只有solid-js@^1.8.18和@sentry/solid;开发依赖包括vite@^5.4.11、vite-plugin-solid、tailwindcss、solid-devtools、PostCSS 工具链以及测试用的@playwright/test@~1.63.0。值得注意的是 SDK 的引入方式:

"dependencies": { "solid-js": "^1.8.18", "@sentry/solid": "file:../../packed/sentry-solid-packed.tgz" }

SDK 不是从 npm registry 拉取,而是指向dev-packages/e2e-tests/packed/下的本地打包 tarball(见 E2E README 的 "How they work":仓库会把各包构建成 tarball 并注入 pnpm overrides,使测试应用"如同已发布"地安装本地构建产物)。这正是该应用与真实业务项目最关键的差异,也是运行前必须先执行yarn build:tarball的原因。

2.3 可用脚本

脚本等价命令作用
npm run dev/npm startvite开发模式启动,热更新,打开 http://localhost:3000 查看(README 描述)
npm run buildvite build生产构建到dist目录,production 模式打包、压缩、文件名带 hash
npm run previewvite preview本地预览构建产物(Playwright 测试即依赖它,见下文)
pnpm test:prodTEST_ENV=production playwright test在生产构建上跑 Playwright 断言
pnpm test:buildpnpm install && pnpm buildE2E 框架约定的构建阶段入口
pnpm test:assertpnpm test:prodE2E 框架约定的断言阶段入口
pnpm cleannpx rimraf node_modules pnpm-lock.yaml dist清理本应用产物

其中test:build/test:assert是 E2E 测试框架对每个测试应用的强制约定(E2E README 要求新建测试应用必须提供这两个命令)。

构建行为由 vite.config.ts 决定:启用vite-plugin-solid、构建目标esnext,并且设置了envPrefix: 'PUBLIC_'—— 这意味着只有PUBLIC_前缀的环境变量才会通过import.meta.env暴露给应用代码,下一节的PUBLIC_E2E_TEST_DSN正依赖这一配置才能被注入。

三、SDK 初始化配置逐项解析

应用的入口 src/index.tsx 展示了@sentry/solid的完整初始化配置(L7-L16):

Sentry.init({ traceLifecycle: 'static', dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, debug: true, environment: 'qa', // dynamic sampling bias to keep transactions integrations: [Sentry.browserTracingIntegration()], release: 'e2e-test', tunnel: 'http://localhost:3031/', // proxy server tracesSampleRate: 1.0, }); render(() => <App />, document.getElementById('root'));

各参数在本测试场景中的作用:

  • traceLifecycle: 'static':选择"静态 span 生命周期"模式。从源码结构看,client.ts 中,任何非'static'的取值都会归一化为默认值'stream'(span streaming);当为'static'时,span 在结束前不会流式上报,且 spanStreaming 集成 会直接跳过初始化。若你在static模式下配置了beforeSendSpan,还需用Sentry.withStaticSpan包裹回调,否则客户端会在 client.ts 中做一致性校验并提示。
  • dsn: import.meta.env.PUBLIC_E2E_TEST_DSN:DSN 不硬编码,而是由 E2E 测试基础设施通过环境变量注入(.env中配置,经 Vite 的PUBLIC_前缀规则暴露到浏览器端)。
  • tunnel: 'http://localhost:3031/':事件不直接发到 Sentry,而是发往本地事件代理服务器(event proxy)。该代理由 start-event-proxy.mjs 启动,内部调用@sentry-internal/test-utils的startEventProxyServer({ port: 3031, proxyServerName: 'solid-static' })。Playwright 测试正是通过这个代理"拦截"并断言 SDK 实际发出的事件,而不是依赖真实 Sentry 项目。
  • environment: 'qa':配合注释 "dynamic sampling bias to keep transactions",即利用 Sentry 的动态采样规则让qa环境的 transaction 更容易被保留,避免测试事务被采样丢弃。
  • release: 'e2e-test'、debug: true:统一的发布标识便于在代理端区分事件来源;debug: true打开 SDK 日志,也符合 E2E README 排障章节的第一条调试建议。
  • tracesSampleRate: 1.0+browserTracingIntegration():100% 采样所有浏览器事务,确保 pageload/navigation 事务必然产生。

四、应用层:两种错误路径与路由结构

sr c/app.tsx 是该应用的核心"测试桩",它构造了两条互不相同的错误路径:

  1. 未捕获错误:#errorBtn按钮的onClick直接throw new Error('Error thrown from Solid E2E test app'),不经过任何本地处理,交由浏览器全局 handler(window.onerror)捕获,验证 SDK 的auto.browser.global_handlers.onerror机制。
  2. 受控错误 + Sentry 错误边界:#caughtErrorBtn触发后渲染一个在onMount中抛错的组件,被外层SentryErrorBoundary捕获。该边界由Sentry.withSentryErrorBoundary(ErrorBoundary)包装 Solid 原生的ErrorBoundary而成(实现见 packages/solid/src/errorboundary.ts),其fallback渲染错误信息与 Reset 按钮,点击后setCount(count() + 1)使错误消息自增并调用reset()恢复子树——这正是"捕获第二次异常"测试的基础。

导航壳 pageroot.tsx 使用 Tailwind 类名组织了一个包含 Home / Error Boundary Example / Error 链接的nav,/error链接会命中**通配路由渲染 404 页,用于覆盖路由参数化场景。

五、Playwright 测试如何验证 SDK 行为

playwright.config.mjs 使用@sentry-internal/test-utils的getPlaywrightConfig({ startCommand: 'pnpm preview --port 3030', port: 3030 })生成配置。从 dev-packages/test-utils/src/playwright-config.ts 的源码结构看,当传入startCommand时,配置会在webServer中追加以该命令启动的服务器项——即测试运行前 Playwright 会先pnpm preview --port 3030把生产构建(dist)挂起来,应用跑在 3030 端口,事件代理跑在 3031 端口(对应tunnel配置)。

tests 目录下有三个测试文件,分别验证上面三件事:

5.1 错误上报(errors.test.ts)

tests/errors.test.ts 通过waitForError('solid-static', ...)订阅代理端事件流,点击#errorBtn后断言事件对象:

expect(error).toMatchObject({ exception: { values: [{ type: 'Error', value: 'Error thrown from Solid E2E test app', mechanism: { type: 'auto.browser.global_handlers.onerror', handled: false, }, }], }, transaction: '/', });

断言覆盖了三个维度:错误类型与消息、mechanism 标记其为未处理(handled: false)且来自全局 onerror handler、以及事件携带的关联事务名/。

5.2 Sentry 错误边界(errorboundary.test.ts)

tests/errorboundary.test.ts 包含两个用例:

  • 点击#caughtErrorBtn后,断言捕获的事件 mechanism 为auto.function.solid.error_boundary且handled: true,错误消息为Error 1 thrown from Sentry ErrorBoundary in Solid E2E test app——证明错误被边界受控处理,并与 SDK 的 mechanism 标记体系一致;
  • 随后点击 Reset 按钮再次触发,断言第二条事件消息为Error 2 ...,验证reset()恢复后边界仍可继续捕获新错误(对应 app.tsx 中count自增的设计)。

5.3 页面加载事务(performance.test.ts)

tests/performance.test.ts 用waitForTransaction('solid-static', ...)等待代理端收到事务事件,page.goto('/')后断言:

expect(pageloadTransaction).toMatchObject({ contexts: { trace: { op: 'pageload', origin: 'auto.pageload.browser', }, }, transaction: '/', transaction_info: { source: 'url' }, });

这验证了browserTracingIntegration在纯客户端路由的静态 SPA 上正确生成了pageload事务,且事务名是原始 URL(source: 'url'表示名称来源于原始 URL 而非服务端约定名)。

六、构建、运行与部署

6.1 在仓库内运行该 E2E 应用

按照 E2E README 的标准流程:

  1. 复制.env.example为.env(PUBLIC_E2E_TEST_DSN等变量由此注入;纯本地断言不需要真实 Sentry 凭证,因为事件走本地代理);
  2. 在仓库根目录执行yarn build:tarball,把packages/下各 SDK 打成 tarball 并建立packed/软链(packages/有任何改动后都必须重跑);
  3. 只运行本应用:
yarn test:run solid-static

框架会依次调用本应用package.json中的test:build(安装依赖 + 生产构建)与test:assert(TEST_ENV=production playwright test)。也可以交互式地用仓库提供的 Makefile(需fzf):make list列出全部测试应用,make run打开模糊搜索菜单选择运行。CI 侧则由dev-packages/e2e-tests/lib/getTestMatrix.mjs生成测试矩阵,且基于 nx affected projects 按依赖变更自动裁剪——只有依赖链上的 SDK 包有改动时,solid-static 才会被触发。

6.2 作为普通项目使用(README 的部署说明)

若剥离 E2E 基础设施、把该模板当作普通 Solid 项目使用,README 给出的路径是:

npm run dev # 开发模式,http://localhost:3000,编辑即刷新 npm run build # 生产构建输出到 dist(压缩、文件名含 hash)

"Deployment" 一节的结论是:dist文件夹可部署到任意静态托管服务(README 列举了 netlify、surge、now 等)。这与应用形态自洽——纯客户端渲染、无服务端数据获取(.data.ts模式在本静态快照中未启用),路由切换全部发生在浏览器内,因此对静态托管零要求。

6.3 本地手动调试组合

理解两个端口即可手动复现测试环境:pnpm build && pnpm preview --port 3030启动应用;同时运行 start-event-proxy.mjs(如node start-event-proxy.mjs)在 3031 端口起事件代理;配合Sentry.init中的debug: true,浏览器控制台会输出 SDK 完整日志,代理端则能看到 SDK 实际发出的原始事件,逐字段对照测试断言。

七、小结

solid-static 是一个麻雀虽小五脏俱全的 E2E 测试应用:README 交代了模板的安装、脚本与静态部署方式;package.json 与 tarball 机制保证它测试的是"即将发布"的@sentry/solid;index.tsx 的traceLifecycle: 'static'+tunnel+ 1.0 采样率构成了一套可完全本地观测的埋点环境;app.tsx 与 routes.ts 提供受控/未受控两条错误路径和懒加载路由;三个 Playwright 测试文件则把错误 mechanism、错误边界行为与 pageload 事务字段逐条钉死。它示范的"本地 tarball + 事件代理 + 生产构建 + Playwright 断言"套路,是理解整个 sentry-javascript E2E 体系的最好切入口。

  • 可观测性

【免费下载链接】sentry-javascript

Official Sentry SDKs for JavaScript

项目地址:https://gitcode.com/gh_mirrors/se/sentry-javascript
点击查看免费下载
上一篇:通过Docker容器快速部署Hermes WebUI:AI助手的现代化Web界面
下一篇:Lerna快速入门指南:10分钟搭建你的第一个monorepo项目

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询