- UI组件
- 前端
【免费下载链接】awesomplete
Ultra lightweight, usable, beautiful autocomplete with zero dependencies.
Awesomplete 是一个零依赖的轻量级 autocomplete 组件(核心实现在 awesomplete.js)。本指南以仓库根目录的 CONTRIBUTING.md 为骨架,完整讲解参与该项目开发时必须掌握的三个环节:本地环境与依赖安装、基于 Karma + Jasmine 的测试运行与用例编写、以及基于 gulp 的产物构建。读完本文,你将能够在本仓库中跑通npm test、karma start与gulp三条核心命令,写出符合项目规范的测试用例,并理解构建产物(awesomplete.min.js、awesomplete.css)从源码生成的全过程。
一、环境准备:Node.js 与 npm
开始之前,需要先安装 Node.js 和 npm。在已安装 Homebrew 的 macOS 上,一条命令即可完成:
brew install node在 Linux 发行版(如本仓库常见的 CI 环境)上,可通过系统包管理器或 Node 官方二进制包安装,安装完成后用node --version与npm --version验证即可。本项目基于 npm 脚本、Karma 与 gulp 工作,Node 环境是运行一切开发命令的前提。
二、安装依赖:npm install
进入仓库根目录后执行:
npm install该命令会按照 package.json 中声明的devDependencies安装全部开发期依赖,其中与本文主题直接相关的包括:
- karma与karma-chrome-launcher:测试运行器及其 Chrome 浏览器启动器;
- jasmine-core、karma-jasmine、karma-jasmine-def:Jasmine 测试框架及其 Karma 适配器、
def/subject语法支持; - karma-fixture与karma-html2js-preprocessor:HTML fixture 加载与预处理,测试中用来装载真实 DOM 片段;
- karma-coverage:覆盖率采集与报告;
- gulp、gulp-concat、gulp-uglify、gulp-rename、gulp-header、gulp-sourcemaps:构建流水线(压缩、合并、重命名、文件头注释、sourcemap 生成)。
从 package.json 可以看到这些依赖的版本区间。需要说明的是,Awesomplete 本身零运行时依赖,这里列出的全部是开发工具,不会进入最终产物。
三、运行测试
CONTRIBUTING.md 提供了两种测试运行方式,分别对应一次性检查与持续开发两种场景。
3.1 一次性运行:npm test
npm test在 package.json 中,test脚本被定义为:
"scripts": { "test": "karma start --single-run" }即执行 Karma 的单次运行模式(--single-run):启动浏览器、运行完所有用例后自动退出并汇总结果。这也是 CI 环境中的标准调用方式——结合 karma.conf.js 中的browsers: process.env.TRAVIS ? ['ChromeTravisCI'] : ['Chrome']可以看出,在 Travis CI 上会使用带--no-sandbox参数的ChromeTravisCI自定义启动器,其余环境则使用本机 Chrome。
3.2 持续模式:karma start
karma start这是持续监听模式。Karma 会启动 Chrome 并保持运行,之后每当任何源码或测试文件发生变更,测试都会自动重新执行,非常适合 TDD 开发。几点使用要点:
- Chrome 会自动打开;在终端中按
Ctrl+C即可停止整个测试进程; - 也可以手动打开
http://localhost:9876/,只要该标签页保持打开,测试就会持续在那里运行并刷新结果。端口号 9876 定义在 karma.conf.js 的port: 9876; - 配置中的
autoWatch: true(见 karma.conf.js)负责文件变更监听,是持续模式的开关。
3.3 Karma 配置如何组织测试
理解 karma.conf.js 能帮你快速定位测试入口。关键配置如下:
| 配置项 | 值 | 作用 |
|---|---|---|
frameworks | ['jasmine', 'jasmine-def', 'fixture'] | 依次启用 Jasmine 断言、subject/def语法扩展、fixture DOM 装载 |
files | awesomplete.js、test/specHelper.js、test/fixtures/**/*.html、test/**/*Spec.js | 先加载被测库,再加载测试辅助函数与 HTML fixture,最后加载全部以Spec.js结尾的用例 |
preprocessors | awesomplete.js → coverage、**/*.html → html2js | 对被测库做覆盖率插桩,将 HTML fixture 编译为 JS 字符串以便注入 |
reporters | ['dots', 'coverage'] | 点状进度输出 + lcov 覆盖率报告 |
browsers | ['Chrome'](CI 下为ChromeTravisCI) | 测试运行浏览器 |
singleRun | false | 默认持续监听,npm test通过--single-run覆盖为 true |
四、添加测试:用 Jasmine 编写用例
Awesomplete 采用 Jasmine 作为测试框架。CONTRIBUTING.md 给出的最小用例模板如下:
describe("A fact", function(){ it("is always true",function(){ var fact = true; expect(fact).toBe(true); }); });结构拆解:
describe("...", function(){...}):定义一个测试组(suite),第一个参数是描述被测对象的字符串,第二个参数是包含具体断言的函数;it("...", function(){...}):定义一个具体用例(spec),字符串描述期望的行为,函数体内"安排(arrange)并断言(assert)"该功能;expect(x).toBe(y):Jasmine 断言 API 的一种,用于验证值相等。
4.1 项目中的测试辅助设施
仅靠裸 Jasmine 还不够,仓库在 test/specHelper.js 中封装了一套贴近真实交互的辅助函数,编写用例前应当熟悉:
$.fixture(name):在beforeEach中从 test/fixtures 加载对应 HTML 片段,并在afterEach中自动清理,保证用例间 DOM 隔离;$/$$:基于当前 fixture 的querySelector/querySelectorAll封装;$.type(input, text):聚焦输入框、写入文本并触发input事件,用于模拟用户打字;$.keydown(target, keyCode)与$.k常量:模拟按键,$.k.TAB/ENTER/ESC/DOWN/UP分别对应 9/13/27/40/38;$.fire(target, type, properties):构造并派发HTMLEvents;$.spyOnEvent(target, type):为指定事件创建 Jasmine spy,用于断言事件是否被触发;$.noop:每次调用返回一个新的空函数,适合作为无操作的 stub 选项。
测试文件按职责分层存放于 test 目录:
test/api/:核心 API 行为,如openSpec.js、closeSpec.js、evaluateSpec.js、gotoSpec.js、selectSpec.js、nextSpec.js等;test/events/:DOM 事件驱动行为,如inputSpec.js、keydownSpec.js、clickSpec.js、blurSpec.js、submitSpec.js;test/helpers/:内部辅助函数,如bindSpec.js、regExpEscapeSpec.js、createSpec.js;test/init/:初始化逻辑,如optionsSpec.js、listSpec.js、htmlSpec.js;test/static/:静态方法,如filterContainsSpec.js、filterStartsWithSpec.js、sortByLengthSpec.js、itemSpec.js。
4.2 从真实用例看测试模式
① 行为驱动型用例——以 test/events/inputSpec.js 为例,它验证"输入触发重建列表"这一行为:
describe("input event", function () { $.fixture("plain"); subject(function () { return new Awesomplete("#plain") }); it("rebuilds the list", function () { spyOn(Awesomplete.prototype, "evaluate"); $.type(this.subject.input, "ite"); expect(Awesomplete.prototype.evaluate).toHaveBeenCalled(); }); });subject(...)是karma-jasmine-def提供的懒初始化语法,等价于在beforeEach中this.subject = new Awesomplete(...);配合spyOn可以只验证"调用关系"而不依赖实现细节。这里对应的真实行为见 awesomplete.js:构造器会把input事件绑定到this.evaluate。
② 状态断言型用例——以 test/api/evaluateSpec.js 为例,它直接验证evaluate()的三种分支:输入过短时关闭(close({reason: "nomatches"}))、无匹配项时关闭、有匹配项时打开并填充列表,同时还覆盖了maxItems截断、minChars: 0立即展开等边界。对应实现见 awesomplete.js。
③ 事件断言型用例——以 test/api/openSpec.js 为例:
it("fires awesomplete-open event", function () { var handler = $.spyOnEvent(this.subject.input, "awesomplete-open"); this.subject.open(); expect(handler).toHaveBeenCalled(); });该用例验证open()会触发awesomplete-open自定义事件(对应实现 awesomplete.js),同时验证autoFirst选项的行为:开启时自动高亮第一项,关闭时不高亮。
④ 配置解析型用例——test/init/optionsSpec.js 验证了默认值(minChars: 2、maxItems: 10、autoFirst: false)、构造函数传参覆盖、以及data-*属性覆盖(如data-minchars="4"会覆盖默认值 2)。这与 awesomplete.js 中configure的实现一一对应。
⑤ 列表解析型用例——test/init/listSpec.js 覆盖list属性支持的全部输入形式:字符串数组、逗号分隔字符串、CSS 选择器、DOM 元素,以及data-list/listHTML 属性;对应的解析逻辑在 awesomplete.js 的 setter 中实现。
新增测试的推荐流程:在对应分层目录新建xxxSpec.js→ 用$.fixture装载所需 fixture(若缺可参考 test/fixtures/plain.html 与 test/fixtures/options.html 的既有写法新增)→ 编写describe/it→ 用karma start持续验证。所有用例命名统一以Spec.js结尾,这是 Karmafiles配置的匹配约定。
五、构建:gulp 流水线
测试通过后,使用 gulp 生成发布产物:
gulp该命令执行 gulpfile.js 中定义的default任务,它会并行运行minify与concat两个子任务:
5.1 minify:压缩 JS
gulp.task('minify', function() { return gulp.src(['awesomplete.js']) .pipe(sourcemaps.init()) .pipe(uglify()) .pipe(rename({ suffix: '.min' })) .pipe(header(banner)) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('.')); });流程说明(见 gulpfile.js):
- 以
awesomplete.js为输入; - 初始化 sourcemap →
uglify压缩 →rename追加.min后缀,得到awesomplete.min.js; header写入 banner 注释// Awesomplete - Lea Verou - MIT license(定义在 gulpfile.js);- 输出 sourcemap 到仓库根目录。
最终产物awesomplete.min.js与awesomplete.min.js.map即当前仓库根目录下可见的两个文件。
5.2 concat:合并 CSS
gulp.task('concat', function() { return gulp.src(['awesomplete.base.css', 'awesomplete.theme.css']) .pipe(sourcemaps.init()) .pipe(concat('awesomplete.css')) .pipe(sourcemaps.write('.')) .pipe(gulp.dest('.')); });流程说明(见 gulpfile.js):将基础样式 awesomplete.base.css 与主题样式 awesomplete.theme.css 按顺序合并为awesomplete.css,并生成对应的.map文件。这也印证了 CONTRIBUTING.md 中的描述:"mergeawesomplete.base.cssandawesomplete.theme.cssand generateawesomplete.css"。
六、从测试到构建的完整开发循环
综合来看,Awesomplete 的日常开发循环可以归纳为:
- 改代码:编辑 awesomplete.js 或新增测试文件;
- 验证:
karma start持续监听并自动重跑测试,或在改动完成后执行一次npm test全量回归(含覆盖率统计); - 发布产物:
gulp生成压缩版 JS 与合并版 CSS 及对应 sourcemap; - 交付使用:页面按 README.md 的方式引入
awesomplete.css与awesomplete.js(或awesomplete.min.js)即可。
这套工作流的所有关键命令都以仓库实际配置为准:npm test等价于karma start --single-run(见 package.json),Karma 的行为由 karma.conf.js 全权定义,构建产物路径与内容由 gulpfile.js 决定。对于想深入理解被测对象的人来说,测试目录本身就是最好的源码阅读入口——test 下的用例几乎覆盖了 awesomplete.js 的全部公开 API、静态方法与自定义事件,逐一对读即可快速建立对组件行为的完整认知。
- UI组件
- 前端
【免费下载链接】awesomplete
Ultra lightweight, usable, beautiful autocomplete with zero dependencies.
相关推荐
Octant 开发环境搭建与贡献实战指南:从 HACKING.md 到构建、测试与调试的完整工作流
Octant 开发环境搭建与贡献实战指南:从 HACKING.md 到构建、测试与调试的完整工作流 Octant 是一个面向开发者的高度可扩展 Kubernet
云原生后端前端运维可观测性开发工具SciPy 开发环境搭建与 Git 工作流实战指南
SciPy 开发环境搭建与 Git 工作流实战指南 本指南以 SciPy 仓库官方开发者文档 doc/source/dev/gitwash/ https://l
科学计算数据科学高性能计算watchdog 贡献开发指南:环境搭建、源码测试与提交工作流实战
watchdog 贡献开发指南:环境搭建、源码测试与提交工作流实战 本文基于 watchdog 官方贡献指南( docs/source/hacking.rst
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考