chai-fs
Chai 断言 插件 用于 Node.js 文件系统 API。使用 path
和同步 fs
来断言文件和目录。
所有断言都可以在 expect
、should
和 assert
样式中使用,并支持可选的消息参数。
使用
服务器端
从 npm 安装
$ npm install chai-fs
让 chai 使用 chai-fs 模块
var chai = require('chai');
chai.use(require('chai-fs'));
浏览器端
没有文件系统。
断言
basename()
断言 path.basename(path)
的返回值
expect(path).to.have.basename(name, ?msg);
expect(path).to.not.have.basename(name, ?msg);
path.should.have.basename(name, ?msg);
path.should.not.have.basename(name, ?msg);
assert.basename(path, name, ?msg);
assert.notBasename(path, name, ?msg);
dirname()
断言 path.dirname(path)
的返回值
expect(path).to.have.dirname(name, ?msg);
expect(path).to.not.have.dirname(name, ?msg);
path.should.have.dirname(name, ?msg);
path.should.not.have.dirname(name, ?msg);
assert.dirname(path, name, ?msg);
assert.notDirname(path, name, ?msg);
extname()
断言 path.extname(path)
的返回值
expect(path).to.have.extname(name, ?msg);
expect(path).to.not.have.extname(name, ?msg);
path.should.have.extname(name, ?msg);
path.should.not.have.extname(name, ?msg);
assert.extname(path, name, ?msg);
assert.notExtname(path, name, ?msg);
path()
断言路径存在。
使用 fs.existsSync()
。
expect(path).to.be.a.path(?msg);
expect(path).to.not.be.a.path(?msg);
path.should.be.a.path(?msg);
path.should.not.be.a.path(?msg);
assert.pathExists(path, ?msg);
assert.notPathExists(path, ?msg);
使用 Chai 的 exist
链会很好,但但是在否定和消息参数方面存在问题。所以不要这样做。
directory()
断言路径存在并且是一个目录。
使用 fs.statSync().isDirectory()
expect(path).to.be.a.directory(?msg);
expect(path).to.not.be.a.directory(?msg);
path.should.be.a.directory(?msg);
path.should.not.be.a.directory(?msg);
assert.isDirectory(path, ?msg);
assert.notIsDirectory(path, ?msg);
directory().and.empty
断言路径存在,是一个目录并且包含零个项目。
expect(path).to.be.a.directory(?msg).and.empty;
expect(path).to.be.a.directory(?msg).and.not.empty;
path.should.be.a.directory(?msg).and.empty;
path.should.be.a.directory(?msg).and.not.empty;
assert.isEmptyDirectory(path, ?msg);
assert.notIsEmptyDirectory(path, ?msg);
- 在
directory()
后链接 - 使用
fs.readdirSync().length === 0
。 - 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
directory().with.contents([…])
断言路径存在,是一个目录并且具有特定内容(文件、子目录、符号链接等)。
expect(path).to.be.a.directory(?msg).with.contents(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.contents(array, ?msg);
expect(path).to.be.a.directory(?msg).with.deep.contents(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.deep.contents(array, ?msg);
expect(path).to.be.a.directory(?msg).and.include.contents(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.include.contents(array, ?msg);
path.should.be.a.directory(?msg).with.contents(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.contents(array, ?msg);
path.should.be.a.directory(?msg).with.deep.contents(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.deep.contents(array, ?msg);
path.should.be.a.directory(?msg).and.include.contents(array, ?msg);
path.should.be.a.directory(?msg).and.not.include.contents(array, ?msg);
assert.directoryContent(path, array, ?msg);
assert.notDirectoryContent(path, array, ?msg);
assert.directoryDeepContent(path, array, ?msg);
assert.notDirectoryDeepContent(path, array, ?msg);
assert.directoryInclude(path, array, ?msg);
assert.notDirectoryInclude(path, array, ?msg);
- 内容的路径相对于目录
- 只有顶层内容包含在内,除非链中包含
.deep
- 如果链中包含
.include
或.contain
,则目录必须至少包含指定的内容,但可以包含更多内容 - 你可以使用
.content()
或.contents()
。它们都是一样的。 - 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
directory().with.files([…])
断言路径存在,是一个目录并且包含特定文件。
expect(path).to.be.a.directory(?msg).with.files(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.files(array, ?msg);
expect(path).to.be.a.directory(?msg).with.deep.files(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.deep.files(array, ?msg);
expect(path).to.be.a.directory(?msg).and.include.files(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.include.files(array, ?msg);
path.should.be.a.directory(?msg).with.files(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.files(array, ?msg);
path.should.be.a.directory(?msg).with.deep.files(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.deep.files(array, ?msg);
path.should.be.a.directory(?msg).and.include.files(array, ?msg);
path.should.be.a.directory(?msg).and.not.include.files(array, ?msg);
assert.directoryFiles(path, array, ?msg);
assert.notDirectoryFiles(path, array, ?msg);
assert.directoryDeepFiles(path, array, ?msg);
assert.notDirectoryDeepFiles(path, array, ?msg);
assert.directoryIncludeFiles(path, array, ?msg);
assert.notDirectoryIncludeFiles(path, array, ?msg);
- 文件路径相对于目录
- 只有顶层文件包含在内,除非链中包含
.deep
- 如果链中包含
.include
或.contain
,则目录必须至少包含指定的文件,但可以包含更多文件 - 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
directory().with.subDirs([…])
断言路径存在,是一个目录并且包含特定子目录。
expect(path).to.be.a.directory(?msg).with.subDirs(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.subDirs(array, ?msg);
expect(path).to.be.a.directory(?msg).with.deep.subDirs(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.have.deep.subDirs(array, ?msg);
expect(path).to.be.a.directory(?msg).and.include.subDirs(array, ?msg);
expect(path).to.be.a.directory(?msg).and.not.include.subDirs(array, ?msg);
path.should.be.a.directory(?msg).with.subDirs(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.subDirs(array, ?msg);
path.should.be.a.directory(?msg).with.deep.subDirs(array, ?msg);
path.should.be.a.directory(?msg).and.not.have.deep.subDirs(array, ?msg);
path.should.be.a.directory(?msg).and.include.subDirs(array, ?msg);
path.should.be.a.directory(?msg).and.not.include.subDirs(array, ?msg);
assert.directorySubDirs(path, array, ?msg);
assert.notDirectorySubDirs(path, array, ?msg);
assert.directoryDeepSubDirs(path, array, ?msg);
assert.notDirectoryDeepSubDirs(path, array, ?msg);
assert.directoryIncludeSubDirs(path, array, ?msg);
assert.notDirectoryIncludeSubDirs(path, array, ?msg);
- 内容的路径相对于起始目录
- 只有顶层子目录包含在内,除非链中包含
.deep
- 如果链中包含
.include
或.contain
,则目录必须至少包含指定的子目录,但可以包含更多子目录 - 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
directory().with.contents.that.satisfy(fn)
你可以将 .contents
、.files
和 .subDirs
与任何可以在数组上操作的 Chai.js 断言链接起来,包括 .lengthOf()
、.satisfy()
、.members()
等。
expect(path).to.be.a.directory().and.content.is.an('array');
expect(path).to.be.a.directory().and.files.have.lengthOf(5);
path.should.be.a.directory().with.subDirs.that.include.members(['subDir1', 'subDir2']);
path.should.be.a.directory().with.files.that.satisfy(function(files) {
return files.every(function(file) {
return file.substr(-4) === '.txt';
});
})
- 内容的路径相对于目录
- 只有顶层内容包含在内,除非链中包含
.deep
- 你可以使用
.content()
或.contents()
。它们都是一样的。 - 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
directory().and.equal(otherPath)
断言两者路径都存在,是目录并且包含相同的内容(文件、子目录、符号链接等)。
expect(path).to.be.a.directory(?msg).and.equal(otherPath, ?msg);
expect(path).to.be.a.directory(?msg).and.not.equal(otherPath, ?msg);
expect(path).to.be.a.directory(?msg).and.deep.equal(otherPath, ?msg);
expect(path).to.be.a.directory(?msg).and.not.deep.equal(otherPath, ?msg);
path.should.be.a.directory(?msg).and.equal(otherPath, ?msg);
path.should.be.a.directory(?msg).and.not.equal(otherPath, ?msg);
path.should.be.a.directory(?msg).and.deep.equal(otherPath, ?msg);
path.should.be.a.directory(?msg).and.not.deep.equal(otherPath, ?msg);
assert.directoryEqual(path, otherPath, ?msg);
assert.notDirectoryEqual(path, otherPath, ?msg);
assert.directoryDeepEqual(path, otherPath, ?msg);
assert.notDirectoryDeepEqual(path, otherPath, ?msg);
- 只有顶层内容进行比较,除非链中包含
.deep
- 要使用
expect/should
否定它,你需要在常规的directory()
后链接.not
否定。
file()
断言路径存在并且是一个文件。
使用 fs.statSync().isFile()
expect(path).to.be.a.file(?msg);
expect(path).to.not.be.a.file(?msg);
path.should.be.a.file(?msg);
path.should.not.be.a.file(?msg);
assert.isFile(path, ?msg);
assert.notIsFile(path, ?msg);
file().and.empty
断言路径存在,是一个文件并且大小为零。
expect(path).to.be.a.file(?msg).and.empty;
expect(path).to.be.a.file(?msg).and.not.empty;
path.should.be.a.file(?msg).and.empty;
path.should.be.a.file(?msg).and.not.empty;
assert.isEmptyFile(path, ?msg);
assert.notIsEmptyFile(path, ?msg);
- 在
file()
后链接 - 使用
fs.statSync().size === 0
。 - 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。
file().with.content(str)
断言路径存在,是一个文件并且具有特定内容。
expect(path).to.be.a.file(?msg).with.content(data, ?msg);
expect(path).to.be.a.file(?msg).and.not.have.content(data, ?msg);
path.should.be.a.file(?msg).with.content(data, ?msg);
path.should.be.a.file(?msg).and.not.have.content(data, ?msg);
assert.fileContent(path, data, ?msg);
assert.notFileContent(path, data, ?msg);
- 将文件读取为 utf8 文本(可以更新以支持 base64、二进制 Buffer 等)。
- 你可以使用
.content()
或.contents()
。它们都是一样的。 - 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。
file().with.contents.that.match(/xyz/)
断言路径存在,是一个文件并且内容与正则表达式匹配。
expect(path).to.be.a.file(?msg).with.contents.that.match(/xyz/, ?msg);
expect(path).to.be.a.file(?msg).and.not.have.contents.that.match(/xyz/, ?msg);
path.should.be.a.file(?msg).with.contents.that.match(/xyz/, ?msg);
path.should.be.a.file(?msg).and.not.have.contents.that.match(/xyz/, ?msg);
assert.fileContentMatch(path, /xyz/, ?msg);
assert.notFileContentMatch(path, /xyz/, ?msg);
- 将文件读取为 utf8 文本(可以更新以支持 base64、二进制 Buffer 等)。
- 你可以使用
.content
或.contents
。它们都是一样的。 - 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。
file().and.equal(otherPath)
断言两者路径都存在,是文件并且包含相同的内容
expect(path).to.be.a.file(?msg).and.equal(otherPath, ?msg);
expect(path).to.be.a.file(?msg).and.not.equal(otherPath, ?msg);
path.should.be.a.file(?msg).and.equal(otherPath, ?msg);
path.should.be.a.file(?msg).and.not.equal(otherPath, ?msg);
assert.fileEqual(path, otherPath, ?msg);
assert.notFileEqual(path, otherPath, ?msg);
- 将两个文件读取为 utf8 文本(可以更新以支持 base64、二进制 Buffer 等)。
- 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。
file().and.deep.equal(otherPath)
断言两者路径都存在,是文件,包含相同的内容,并且具有相同的属性,包括
- 所有者 (
stats.uid
) - 组 (
stats.gid
) - 创建时间 (
stats.birthtime
) - 最后修改时间 (
stats.mtime
) -
最后更改时间 (
stats.ctime
)expect(path).to.be.a.file(?msg).and.deep.equal(otherPath, ?msg); expect(path).to.be.a.file(?msg).and.not.deep.equal(otherPath, ?msg);
path.should.be.a.file(?msg).and.deep.equal(otherPath, ?msg); path.should.be.a.file(?msg).and.not.deep.equal(otherPath, ?msg);
assert.fileDeepEqual(path, otherPath, ?msg); assert.notFileDeepEqual(path, otherPath, ?msg);
- 将两个文件读取为 utf8 文本(可以更新以支持 base64、二进制 Buffer 等)。
- 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。 - 最后访问时间 (
stats.atime
)不包含在比较中,因为仅仅读取此值(通过fs.stat()
)会导致它在某些操作系统上发生更改,这可能导致测试不稳定
file().with.json
断言路径存在,是一个文件并且包含可解析的 JSON 文本。
expect(path).to.be.a.file(?msg).with.json;
expect(path).to.be.a.file(?msg).with.not.json;
path.should.be.a.file(?msg).with.json;
path.should.be.a.file(?msg).with.not.json;
assert.jsonFile(path, ?msg);
assert.notJsonFile(path, ?msg);
- 在
file()
后链接 - 要使用
expect/should
否定它,你需要在常规的file()
后链接.not
否定。 with
链只是语法糖。
file().using.json.schema(obj)
断言路径存在,是一个文件,包含符合给定 JSON-Schema 的可解析 JSON 文本。
expect(path).to.be.a.file(?msg).with.json.using.schema(obj);
expect(path).to.be.a.file(?msg).with.json.not.using.schema(obj);
path.should.be.a.file(?msg).with.json.using.schema(obj);
path.should.be.a.file(?msg).with.json.not.using.schema(obj);
assert.jsonSchemaFile(path, schema,?msg);
assert.notJsonSchemaFile(path, schema, ?msg);
- 在
file().with.json
后链接 - schema 参数必须是有效的 JSON-Schema v4。
- 依赖于 chai-json-schema 插件,需要使用
chai.use()
单独激活。 - 要使用
expect/should
否定它,你需要在常规的json
后链接.not
否定。 with
和using
链只是语法糖。
计划中的断言
这里保存了一些关于未来断言的想法 在此文档中.
历史
- 0.1.0 - 添加了 content.match 功能(感谢 @legendary-mich)
- 0.0.2 - 插件发布
- 0.0.1 - Alpha 版发布
贡献
欢迎贡献。请遵循代码、测试和样式模式,并确保 JSHint 满意。请确保所有平台都能正常工作,或者至少在 Widows/Mac/Linux 上正常工作。
构建和测试
在您的 git 检出中安装开发依赖项
$ npm install
您需要全局的 grunt 命令
$ npm install grunt-cli -g
构建并运行测试
$ grunt
查看 Gruntfile
以获取其他命令。
:wrench: 测试生成器
此插件使用“断言插件测试生成器”的原型来为断言的所有方面生成测试,同时保持规格 DRY。
该模式将测试拆分为样式声明树和三种类型测试场景的变体。然后生成器将每个场景变体与样式树数据组合(“相乘”)以获得对所有情况的良好覆盖率。
样式树定义了使用断言的方式:第一级是样式:expect/should 和 assert。然后它定义了正常使用和否定,然后将它们划分为每种样式的不同调用模式。因此,您可以使用/不使用消息进行测试,或者作为链式方法或属性等等。
测试是指定断言和测试预期的方式。
valid
- 预期通过的测试(但否定失败)。invalid
- 预期失败的测试(但否定通过)。error
- 预期始终失败的测试(即使否定时也是如此),因为数据无效(例如:数据类型错误、参数缺失等等)。
report 字段用于验证测试失败时的错误消息。它支持使用断言数据对象进行简单的模板格式。
为什么?
这看起来有点复杂和繁琐,但它确实允许快速添加大量详细的测试以进行所有断言。到目前为止,它似乎运行良好,因此我可能稍后将其提取到单独的 npm 模块中。
请注意,它将生成大量的用例变体,因此代码或测试设置中的一个小错误可能会导致测试套件爆炸,并产生许多失败的断言。仔细观察哪些测试失败,以了解导致什么。
许可证
版权所有 (c) 2013 Bart van der Schoor
根据 MIT 许可证授权。