GPTSession2CPAandSub2API单元测试揭秘:如何用Node vm+假DOM提取内联脚本验证转换逻辑
【免费下载链接】GPTSession2CPAandSub2API项目地址https://gitcode.com/gh_mirrors/gp/GPTSession2CPAandSub2API点击查看免费下载GPTSession2CPAandSub2API是一个纯前端的 ChatGPT session JSON 格式转换工具把 ChatGPT Web 登录 session 一键转换成 CPA、sub2api、Cockpit、9router、Codex、AxonHub、Codex-Manager 等多种可导入的 JSON。所有逻辑都内联在 docs/index.html 的script里没有独立的 JS 模块——这给单元测试出了个难题怎么在没有浏览器、没有测试框架的情况下验证转换逻辑本文带你拆解 tests/convert-session.test.js 的完整套路用Node 内置 vm 模块 手工假 DOM把 HTML 里的内联脚本抽出来跑起来并断言结果。一、为什么不用 Jest / Vitest而是裸跑 Node 这个项目的约束很苛刻单页工具核心逻辑全部内联在 docs/index.html 底部那段script中没有可 import 的模块不想引入任何依赖克隆下来node一跑就行想直接测试真实页面跑的那份代码而不是复制一份测试专用逻辑那样测的不是产品本身。所以作者选择了最轻量的方案零依赖 Node 内置模块。整个测试只用到 4 个内置模块模块用途node:vm在沙箱上下文里执行 HTML 内联脚本node:assert/strict严格断言node:fs读取docs/index.html源码node:path拼接文件路径对应源码见 tests/convert-session.test.js#L3-L6。二、第一步用正则把内联脚本从 HTML 里抽出来 页面结构是HTML 壳 底部一段内联脚本测试直接读源码并匹配const html fs.readFileSync(path.join(__dirname, .., docs, index.html), utf8); const match html.match(/script\s*([\s\S]*?)\s*\/script\s*\/body/); assert.ok(match, expected docs/index.html to contain one inline script);见 tests/convert-session.test.js#L52-L57。正则\/script\s*\/body锚定了body 前最后一个内联脚本正好是页面主逻辑所在即 docs/index.html#L778 开始、#L1758 结束的那段 IIFE。这一步保证了被测代码 用户浏览器里真实运行的代码不存在测试版与线上版分叉的问题。三、第二步造一个能骗过页面脚本的假 DOM 内联脚本一启动就会调用document.querySelector、addEventListener等一大串浏览器 API。测试没有引入 jsdom而是手工实现了一个最小化的假 DOMtests/convert-session.test.js#L8-L501通用假元素createFakeElement—— 每个元素只保留页面脚本真正会碰的属性和方法addEventListener(type, handler)把事件处理器记进listeners供测试稍后手动触发classList.add/remove/toggle用一个Set实现增删setAttribute、value、dataset、click()等基础字段。2假document对象#L64-L81—— 关键技巧是querySelector按选择器缓存同一实例querySelector(selector) { if (!elements.has(selector)) { elements.set(selector, createFakeElement(selector)); } return elements.get(selector); }这样页面脚本初始化时拿到的#session-input和测试后面往同一个 Map 里取的#session-input是同一个对象——测试才能写入输入框然后从输出框里读结果。同时querySelectorAll([data-format])会返回 7 个预制的格式按钮sub2api / cpa / cockpit / 9router / codex / axonhub / codexmanager对应页面 docs/index.html#L662-L668让测试能模拟点击某个输出格式按钮。3沙箱上下文补齐浏览器 API#L83-L103TextEncoder/TextDecoder解码 JWT 用、atob/btoa、console、setTimeout、navigator.clipboard.writeText存根、URL.createObjectURL下载按钮用返回blob:test……哪些 API 页面脚本用到了就补哪些缺一个都会在运行时报错天然帮你发现遗漏。四、第三步vm.runInNewContext 一键启动浏览器 准备工作做完后真正执行页面脚本只有一行tests/convert-session.test.js#L105vm.runInNewContext(match[1], context, { filename: docs/index.html });vm模块把这段脚本当作独立上下文里的顶层脚本执行脚本里的document、navigator解析到的是你伪造的对象而不是真的不存在Node 里本来就没有它们每个测试用例都会重新调用loadPageScript()得到一份全新的沙箱和全新的元素集合用例之间互不污染——这相当于每个用例都刷新一次页面。执行完页面脚本已经把事件监听器挂到了假元素上。测试通过dispatch()手动派发事件来模拟用户操作#L110-L113function dispatch(element, type) { assert.equal(typeof element.listeners[type], function, missing ${type} listener on ${element.selector}); element.listenerstype; }先断言监听器存在防止脚本静默没注册事件再触发input/click事件完整复现用户粘贴 JSON → 点击格式按钮 → 页面输出结果的操作链路。五、10 个用例验证的是转换正确性而不是页面长什么样 ✅有了沙箱测试就能聚焦业务本身。每个用例的模式高度统一loadPageScript()起一个新沙箱往#session-input塞一段伪造的 session JSONdispatch(input, input)触发转换JSON.parse(output.value)断言输出的关键字段。其中jwtWithPayload()辅助函数#L115-L121用base64url快速拼出一个形如header.payload.sig的假 JWT用来测试页面从 access token 的 exp 读过期时间这类逻辑。用例验证点sub2api 单账号过期时间expires_at精确取自 JWT 的exp且只写在账号级、不写到顶层sub2api 多账号各自过期批量输入时每个账号用自己的exp互不串味有 refreshToken 则省略过期字段可刷新账号不再输出expires_at/auto_pause_on_expired合成 id_token 可被 Codex 解析缺真实id_token时合成的 JWT 必须是完整 3 段且 claims 里 email、account_id 正确AxonHub 缺 refreshToken 用占位符写入__missing_refresh_token__并附说明字段last_refresh为过期时间前 1 小时AxonHub 保留真实 token有真实refreshToken/idToken时原样透传、不留占位标记Codex 原生 auth.json 结构auth_mode: chatgpt、OPENAI_API_KEY: null、refresh 缺失时留空串Codex 保留真实 token真实refresh_token、id_token、account_id全部保留Codex-Manager 缺 token 留空串空串避免被误判为可刷新账号meta.label用邮箱命名Codex-Manager 保留元数据workspace_id、chatgpt_account_id等元数据正确落到meta所有用例在文件末尾按序调用最后打印convert-session tests passed#L441-L451。六、如何自己跑一遍零依赖验证转换逻辑 克隆仓库后在项目根目录执行node tests/convert-session.test.js没有任何npm install10 个断言组全部通过即输出convert-session tests passed想扩展用例也很容易复制一个testXxx函数在input.value里造新的输入、在output.value里断言新期望末尾加一行调用即可——加一个用例 加一个纯函数心智负担极低。七、这套内联脚本测试法值得抄的作业 对于单个 HTML 文件 内联脚本形态的工具这个仓库给出了一个可复用的测试模板正则提取用带锚点的正则\/script\s*\/body稳定定位内联脚本测的就是线上代码最小假 DOM不用 jsdomquerySelector用 Map 缓存实现选择器 ↔ 实例双向可达沙箱执行vm.runInNewContext补齐document/navigator/TextEncoder等 API缺什么报什么天然暴露依赖事件驱动断言dispatch()手动触发input/click模拟真实用户操作路径每用例新沙箱loadPageScript()即刷新页面用例天然隔离。配合 README.md 里所有解析和转换都在浏览器本地完成不上传 token的定位这套零依赖测试既守住了单文件开箱即用的产品形态又给转换逻辑兜了一层自动化保障——新手读者完全可以照着 tests/convert-session.test.js 这个 400 多行的文件为自己的内联脚本页面复刻一套同款测试。赞分享【免费下载链接】GPTSession2CPAandSub2API项目地址https://gitcode.com/gh_mirrors/gp/GPTSession2CPAandSub2API点击查看免费下载相关推荐Reachability.swift单元测试策略如何验证网络状态切换逻辑Reachability.swift单元测试策略如何验证网络状态切换逻辑 你是否在开发iOS应用时遇到过网络状态判断不准确的问题用户反馈明明有网却提示连接网络LeRobot视觉增强实战如何将机器人视觉系统的泛化能力提升40%LeRobot视觉增强实战如何将机器人视觉系统的泛化能力提升40% 在工业机器人部署的实践中超过90%的视觉系统失败案例源于环境变化带来的挑战——光照突变、人工智能机器学习深度学习机器人具身智能强化学习深蓝词库转换测试体系揭秘xUnit 单元测试 集成测试如何保证 50 格式转换零差错深蓝词库转换测试体系揭秘xUnit 单元测试 集成测试如何保证 50 格式转换零差错 深蓝词库转换IME WL Converter是一款开源免费的输桌面应用CLI开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

550万护理员缺口下的机器人养老:具身智能离“抱起老人“还差3道门槛

550万护理员缺口下的机器人养老:具身智能离“抱起老人“还差3道门槛

【摘要】2026年中国60岁以上人口已达3.2亿,养老护理员缺口达550万,2024年智能养老设备细分口径市场规模仅约79亿元。全文将照护拆解为身体、情感、认知3类劳动,以莫拉维克悖论解析底层数据门槛,复盘日本20年产业实践得失&#xff…

2026/10/11 8:03:09 阅读更多 →
小程序文档打开与转发分享全链路实现:从按钮到参数传递

小程序文档打开与转发分享全链路实现:从按钮到参数传递

1. 先把转发链路拆开看:按钮只是冰山一角做小程序经常遇到这样一个需求:用户在小程序里打开一份合同、报告或者产品手册,看完之后顺手想转发给同事、客户,标题说得也非常直白——“小程序打开文档,右上角有转发分享的功…

2026/10/11 8:03:09 阅读更多 →
FFDNet图像去噪实战:从PyTorch推理到ONNX部署的完整指南

FFDNet图像去噪实战:从PyTorch推理到ONNX部署的完整指南

简介:FFDNet-pytorch 是面向 PyTorch 用户的图像去噪完整实现,适合从事计算机视觉的研究者、算法工程师及高年级学生。FFDNet 由 Zhang 等人于 2018 年提出,通过卷积残差块和跳跃连接,可有效去除高斯噪声、椒盐噪声,并…

2026/10/11 8:03:09 阅读更多 →

最新新闻

告别命令行!可视化安装 OpenClaw,Windows 新手轻松上手 TaoToken 配置指南

告别命令行!可视化安装 OpenClaw,Windows 新手轻松上手 TaoToken 配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 12:08:26 阅读更多 →
Spring Cloud Gateway与OAuth2.1的移动端令牌安全实践

Spring Cloud Gateway与OAuth2.1的移动端令牌安全实践

1. 为什么移动端 Token 泄露问题,比 Web 端严重得多 先说一个结论:在很多团队里,移动端 App 对接 OAuth2.0 的姿势,从设计上就是错的——只是大家习惯把问题归结为“网关配置不对”或者“Token 有效期太短”。 这件事得从移动端的…

2026/10/11 12:08:26 阅读更多 →
BirdCLEF音频分类Baseline:从log-mel特征到CNN训练的工程实践

BirdCLEF音频分类Baseline:从log-mel特征到CNN训练的工程实践

简介:面向2018年LifeCLEF BirdCLEF鸟种识别任务,这套基于Python与Shell脚本的Baseline工程实现,尤其适合音频识别、生物信息处理和竞赛复现相关研究者参考。压缩包共40个文件、约1.36MB,包含19个Python脚本、15个文本文件&#xf…

2026/10/11 12:08:26 阅读更多 →
PLC编程避坑指南:90条实战经验精选(01-20条)

PLC编程避坑指南:90条实战经验精选(01-20条)

如果让我给刚入行时的自己留一句话,我不会说“多学指令”,而会说“先把那些不该犯的错列成清单”。入行头一两年,我最大的问题根本不是不会编程序,而是总在同一个地方翻车:NPN和PNP传感器配错、输出点一上电就烧、双线…

2026/10/11 12:08:26 阅读更多 →
3k张VOC规范火焰数据集:解决标注格式不一致与小目标检测难题

3k张VOC规范火焰数据集:解决标注格式不一致与小目标检测难题

简介:本资源是面向深度学习初学者与安全监控项目开发者的火焰识别专用VOC格式标注数据集,聚焦火灾预警、智能安防等实际应用场景,支持YOLO系列模型快速训练与验证。压缩包共2000个文件,含3008张JPG火焰图像、3008份对应XML标注文件…

2026/10/11 12:08:26 阅读更多 →
UniDAC 10.3源码包在Delphi 12与Lazarus中的编译安装指南

UniDAC 10.3源码包在Delphi 12与Lazarus中的编译安装指南

简介:UniDAC 10.3 源代码包专为 Delphi 12、Free Pascal 3.3.1 与 Lazarus 3.9.9 打造,是面向 Delphi 控件开发者的通用数据访问组件。它能够统一连接 MySQL、Oracle、SQL Server 等主流数据库,让开发者无需关心底层协议差异即可完成数据读写…

2026/10/11 12:07:25 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →