chai-fs

Build Status Dependency Status devDependency Status NPM version

用於 Node.js 檔案系統 API 的 Chai 斷言外掛。使用 path 和同步 fs 來斷言檔案和目錄。

所有斷言都可以在 expectshouldassert 風格中使用,並且支援可選的訊息參數。

用法

伺服器端

從 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、二進制緩衝區等)。
  • 您可以使用 .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、二進制緩衝區等)。
  • 您可以使用 .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、二進制緩衝區等)。
  • 若要使用 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、二進制緩衝區等)。
  • 若要使用 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 否定。
  • withusing 鏈接只是語法糖。

計畫中的斷言

未來斷言的一些想法儲存在此文件中

歷史

  • 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。

此模式將測試分成樣式宣告樹和 3 種測試情境的變化組合。然後,產生器將每個情境變化與樣式樹資料結合(「乘法」),以獲得所有案例的良好涵蓋範圍。

樣式樹定義了使用斷言的方式:第一層是樣式:expect/should 和 assert。然後,它定義了正常使用和否定,然後將它們分成每個樣式不同的調用模式。因此,您可以測試是否包含/不包含訊息,或作為鏈式方法或屬性等。

測試是指定斷言和測試期望的方式。

  • valid - 預期通過的測試 (但會使否定失敗)
  • invalid - 預期失敗的測試 (但會使否定通過)。
  • error - 測試預期總是會失敗 (即使是否定情況),因為資料無效 (例如:錯誤的資料類型、缺少參數等)。

若測試失敗,報告欄位會用來驗證錯誤訊息。它支援使用斷言資料物件的簡單模板格式。

為什麼?

這看起來有點複雜且繁瑣,但它確實可以讓您快速地為所有斷言新增大量的詳細測試。到目前為止,它似乎運作良好,賦予了力量,所以我稍後可能會將其提取到一個單獨的 npm 模組中。

請注意,它會產生大量的案例變化,因此程式碼或您的測試設定中的一個小錯誤可能會導致套件中出現許多失敗的斷言。請仔細查看哪些測試失敗,以了解原因。

授權許可

版權所有 (c) 2013 Bart van der Schoor

根據 MIT 許可證授權。