news 2026/9/5 22:45:39

33-js-concepts 贡献实战指南:用 Vitest 验证文档代码示例的测试规范与翻译流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
33-js-concepts 贡献实战指南:用 Vitest 验证文档代码示例的测试规范与翻译流程

33-js-concepts 贡献实战指南:用 Vitest 验证文档代码示例的测试规范与翻译流程

【免费下载链接】33-js-concepts📜 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts

本文基于 33-js-concepts 仓库的 CONTRIBUTING.md 展开,系统讲解该项目如何以 Vitest 测试框架保障“文档中的每段代码示例都真实可运行”:从三条 npm 测试命令的实际定义、tests/目录的分类组织方式,到编写测试的六条硬性规范(显式导入、断言转换、错误用例、浏览器 API 处理、严格模式注意),再到新增语言翻译的完整流程和 MIT 许可约定。读完后你可以独立完成:跑通全量测试、为新的概念文档编写配套测试、以及提交一个翻译 PR。

项目定位与“文档即代码”的贡献模式

33-js-concepts 是一个整理 JavaScript 核心概念的学习型仓库:docs/目录下按 fundamentals、functions-execution、object-oriented、functional-programming、beyond 等分类存放 MDX 文档(如 docs/concepts/call-stack.mdx、docs/concepts/promises.mdx),而 CONTRIBUTING.md 明确了本项目的核心贡献约定——使用 Vitest 作为测试运行器,用来验证文档中的代码示例工作正常

This project uses Vitest as the test runner to verify that code examples in the documentation work correctly.

这意味着仓库的贡献不是“写功能代码”,而是“写文档 + 写能验证文档示例的测试”。仓库本身没有业务源码,根目录的 index.js 只是一个包含项目说明的注释占位文件,真正的质量保障体系全部落在tests/目录和测试配置上。

运行测试:三条命令与其在 package.json 中的真实定义

CONTRIBUTING.md 给出三条测试命令:

# Run all tests once npm test # Run tests in watch mode (re-runs on file changes) npm run test:watch # Run tests with coverage report npm run test:coverage

对照 package.json 的scripts字段,可以确认每条命令背后的真实行为:

npm 命令实际执行的命令行为说明
npm testvitest run一次性运行全部测试并退出,适合 PR 前自检
npm run test:watchvitest进入 watch 模式,文件变化时自动重跑,适合开发中边写边验证
npm run test:coveragevitest run --coverage运行测试并输出覆盖率报告,依赖@vitest/coverage-v8提供

与之一致的devDependencies声明为:

  • vitest:^4.0.16
  • jsdom:^27.4.0(用于少量 DOM 测试)
  • @vitest/coverage-v8:^4.0.16test:coverage命令的支撑依赖)

另外两个值得注意的脚本是docscd docs && npx mintlify dev)与docs:buildcd docs && npx mintlify build),从 package.json 的 scripts 结构可以看出,仓库同时承担文档站点(基于 Mintlify)的构建,贡献者改完 MDX 后可以本地预览渲染效果。

测试全局配置:为什么必须显式 import

vitest.config.js 的全部配置只有三项,但它们直接决定了测试的写法:

import { defineConfig } from 'vitest/config' export default defineConfig({ test: { include: ['tests/**/*.test.js'], globals: false, environment: 'node' } })

三个配置项的含义与影响:

  • include: ['tests/**/*.test.js']:只有tests/目录下以.test.js结尾的文件会被执行。这解释了 CONTRIBUTING.md 中“在tests/{concept-name}/下创建{concept-name}.test.js”的命名约定——文件名不匹配这个 glob 就会被静默忽略。

  • globals: false:Vitest 不会把describe/it/expect挂到全局。这正是 CONTRIBUTING.md 第 2 条规范要求“使用显式导入”的配置级原因:

    import { describe, it, expect } from 'vitest'

    任何测试文件缺少这行导入都会直接报describe is not defined,而仓库中的 tests/fundamentals/call-stack/call-stack.test.js 第一行就是标准的显式导入写法。

  • environment: 'node':默认测试环境是 Node.js 而非浏览器,这也是 CONTRIBUTING.md 第 5 条“跳过浏览器专属示例”的根据(下文会讲到 DOM 测试的例外处理方式)。

tests/ 目录结构:按概念组织,并按知识域分层

CONTRIBUTING.md 中给出的结构示意是扁平化的:

tests/ ├── call-stack/ │ └── call-stack.test.js ├── primitive-types/ │ └── primitive-types.test.js └── ...

实际仓库在此基础上多做了一层按知识域分组,当前tests/的真实组织是“分类目录 / 概念目录 / 测试文件”三层,例如:

tests/ ├── fundamentals/ │ ├── call-stack/call-stack.test.js │ ├── primitive-types/primitive-types.test.js │ └── ... ├── functions-execution/ │ ├── event-loop/event-loop.test.js │ ├── promises/promises.test.js │ └── ... ├── object-oriented/ │ ├── this-call-apply-bind/this-call-apply-bind.test.js │ └── ... ├── functional-programming/ │ ├── recursion/recursion.test.js │ └── ... ├── web-platform/ │ ├── dom/dom.test.js │ └── http-fetch/http-fetch.test.js └── beyond/ ├── memory-performance/memoization/memoization.test.js ├── observer-apis/performance-observer/performance-observer.test.js └── ...

可以推断,外层分类(fundamentals/beyond/等)与 docs/ 下的concepts/beyond/concepts/文档分类保持对应,贡献者在为新文档补测试时,应把测试文件放进与文档一致的概念目录中,而不是平铺在tests/根部。

为代码示例编写测试:六条规范逐条解析

CONTRIBUTING.md 的“Writing Tests for Code Examples”给出了六条规范。下面逐条结合仓库实际代码展开,使每条规范可操作、可验证。

1. 文件命名:tests/{concept-name}/{concept-name}.test.js

文件名必须匹配vitest.config.jsincludeglob,且目录名与概念名一致。以调用栈为例,tests/fundamentals/call-stack/call-stack.test.js 中的测试按主题组织成describe块("Basic Function Calls"、"Nested Function Calls" 等),每条it的标题直接描述被验证的行为,如'should execute nested function calls and return correct greeting'

2. 显式导入:由globals: false强制要求

见上文“测试全局配置”一节。CONTRIBUTING.md 给出的标准写法:

import { describe, it, expect } from 'vitest'

需要 mock 或生命周期钩子时按需补充导入,例如 tests/beyond/browser-storage/cookies/cookies.dom.test.js 额外导入了beforeEachafterEachvi,并在afterEach中用vi.restoreAllMocks()还原 mock,这是多测试共享 DOM 状态时的标准清理姿势。

3. 把 console.log 示例转成断言

这是本仓库测试哲学的核心:文档里// => "string"这种注释式预期,在测试中必须变成可执行的expect。CONTRIBUTING.md 给出的对照示例:

// Documentation example: // console.log(typeof "hello") // "string" // Test: it('should return string type', () => { expect(typeof "hello").toBe("string") })

实际仓库中的写法与之完全一致,比如 call-stack 测试中:

it('should execute nested function calls and return correct greeting', () => { function createGreeting(name) { return "Hello, " + name + "!" } function greet(name) { const greeting = createGreeting(name) return greeting } expect(greet("Alice")).toBe("Hello, Alice!") })

即:先完整搬入文档中的示例函数,再对文档注释里写明的输出用toBe/toEqual断言。对对象、数组等复合结果使用toEqual(深度比较),对原始值使用toBe,仓库中两种断言均有实例。

4. 错误用例:用toThrow()验证“应当抛出”的行为

CONTRIBUTING.md 第 4 条:对预期抛错的示例使用expect(() => { ... }).toThrow()。典型场景是文档中讲解“访问 TDZ 中的变量会抛 ReferenceError”“调用Object.freeze后的属性赋值在严格模式下抛 TypeError”这类内容——测试代码把抛错本身当作断言对象,从而保证文档描述的失败行为与运行时行为一致。

5. 浏览器专属示例:默认跳过,需要时用 jsdom docblock

因为environment: 'node'window/document/DOM相关示例默认不在 Node 测试中覆盖(CONTRIBUTING.md 第 5 条)。但仓库并没有完全放弃 DOM 测试:对确实要验证浏览器 API 的文档(如 cookies、DOM 操作、Observer 系列),采用文件后缀 + docblock 注释的方式单独标记,例如 tests/beyond/browser-storage/cookies/cookies.dom.test.js:

/** * @vitest-environment jsdom */ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'

文件头部的@vitest-environment jsdom注释会覆盖全局的node环境,使该文件单独运行在 jsdom 中(对应 devDependencies 里的jsdom),这也解释了仓库中.dom.test.js与普通.test.js并存的双文件模式:同一概念(如 cookies)会同时有 Node 环境可测的cookies.test.js与 jsdom 环境的cookies.dom.test.js。该文件还在beforeEach/afterEach中清理document.cookie与 mock,保证 DOM 测试之间互不污染。

6. 严格模式行为:Vitest 下“静默失败”会变成 TypeError

CONTRIBUTING.md 第 6 条提醒:Vitest 以严格模式运行,因此在非严格模式下“静默失败”的操作(如给未声明变量赋值、修改只读属性)在测试中会直接抛TypeError。写测试时要据此调整预期:文档若演示非严格模式的宽松行为,测试里要么用toThrow(TypeError)断言其失败,要么改写示例本身使其在严格模式下成立。这与beyond/文档中 strict-mode 主题的内容相呼应。

覆盖率:用 test:coverage 检查示例覆盖情况

npm run test:coverage(即vitest run --coverage)会基于@vitest/coverage-v8输出覆盖率报告。对“文档示例 + 配套测试”的仓库而言,覆盖率的意义在于核对文档里出现过、但没有对应测试的示例——它们是贡献者可以补齐的空白点。

创建新翻译:完整流程与格式约定

CONTRIBUTING.md 的“Creating a New Translation”给出了八步流程,全部步骤与格式约定如下(翻译工作针对的是整个文档仓库,而非当前仓库的代码):

  1. Fork 主仓库(leonardomso/33-js-concepts);
  2. 将主仓库加入 watch 列表,保持与上游同步;
  3. 在自己的 fork 中完成翻译;
  4. 在主仓库的 README.md 中编辑链接,指向你的翻译仓库;
  5. Community区块按固定格式新增一行:
    • 格式:Your language in native form (English name) — Your Name
    • 文档给出的示例:[日本語 (Japanese)](https://github.com/oimo23/33-js-concepts) — oimo23
  6. 创建 Pull Request,命名格式为"Add *your language here* translation."
  7. 等待合并。

仓库根目录另有 TRANSLATIONS.md 汇总现有翻译,docs/translations.mdx 则提供文档站内的翻译入口;README.md 也声明该指南已被翻译为 40+ 语言(README 的 Community 区块即为翻译链接的挂载位置)。

许可约定:贡献即接受 MIT

CONTRIBUTING.md 末尾明确:

By contributing, you agree that your contributions will be licensed under the MIT license.

即任何贡献(文档、测试、翻译)一经提交,即视为以 LICENSE 中的 MIT 协议授权。这一点在提交 PR 前需要知悉——MIT 是宽松协议,允许自由使用、修改与再分发,但对贡献者的实际约束主要体现在:不附带担保、贡献内容归入项目统一的 MIT 授权之下。

贡献前自检清单

结合 CONTRIBUTING.md 与仓库实际配置,提交前可按以下清单自查:

  1. 测试文件位置正确tests/{分类}/{concept-name}/{concept-name}.test.js,文件名匹配tests/**/*.test.js
  2. 第一行显式导入import { describe, it, expect } from 'vitest'globals: false下不可省略);
  3. 文档示例全部转为断言:原始值用toBe,复合结构用toEqual,抛错行为用toThrow()
  4. 浏览器 API 处理得当:Node 测试跳过 DOM 示例;确需 DOM 验证时使用@vitest-environment jsdomdocblock 并妥善清理全局状态;
  5. 严格模式预期:确认示例在严格模式下的行为与文档描述一致;
  6. 本地跑通npm test一次性全量通过;开发过程可用npm run test:watch,合并前用npm run test:coverage查看覆盖情况;
  7. 翻译类 PR:README 的 Community 区块格式与 PR 命名符合约定。

这套“文档示例 + Vitest 断言”的组合,使 33-js-concepts 的每个代码片段都不只是“看起来能跑”,而是被测试持续验证的行为契约——这也是贡献者理解并参与该项目最重要的机制。

【免费下载链接】33-js-concepts📜 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 22:43:10

DeepSeek模型深度解析:架构、部署与评测全攻略

抱歉,这篇文章我没法按原样写。原因有三点,我说清楚:“DeepSeek V4 Pro 正式版”缺乏可核实的信息基础。截至当前公开信息,DeepSeek 已发布并被广泛讨论的版本主要是 V3、R1 等型号。对于“V4 Pro 正式版”的发布时间、技术报告、…

作者头像 李华
网站建设 2026/9/5 22:39:52

UVR|3分钟AI人声分离,一键提取卡拉OK伴奏

UVR|3分钟AI人声分离,一键提取卡拉OK伴奏 【免费下载链接】ultimatevocalremovergui GUI for a Vocal Remover that uses Deep Neural Networks. 项目地址: https://gitcode.com/GitHub_Trending/ul/ultimatevocalremovergui 你刚在阳台把一首歌…

作者头像 李华
网站建设 2026/9/5 22:39:17

钢筋目标检测专用数据集:面向工程落地的AI质检实践

简介:本资源是面向建筑行业AI视觉应用的钢筋目标检测专用数据集,适用于YOLO系列模型训练与多类目标检测研究,解决施工现场钢筋自动识别、定位与计数等工程痛点。压缩包共2000个文件,含1028张真实场景JPG图像、对应YOLO格式TXT标注…

作者头像 李华
网站建设 2026/9/5 22:37:51

DataEase 3D 地图大屏完整指南:从数据准备到动态可视化一次讲清

DataEase 3D 地图大屏完整指南:从数据准备到动态可视化一次讲清 【免费下载链接】dataease 🔥 人人可用的开源 BI 工具,数据可视化神器。An open-source BI tool alternative to Tableau. 项目地址: https://gitcode.com/GitHub_Trending/d…

作者头像 李华
网站建设 2026/9/5 22:37:41

PyTorch手语识别工程实践:从数据清洗到端侧部署

简介:本资源是一套面向高校计算机专业本科生的Python毕业设计项目,基于PyTorch实现连续手语识别,旨在解决听障人士与智能系统间的自然语言交互难题,适用于深度学习课程设计、毕设开发及人机交互方向实践。压缩包共47个文件&#x…

作者头像 李华