Chai HTTP ビルドステータス semantic-release

Chaiアサーションを使用したHTTP統合テスト。

機能

  • 統合テストのリクエスト構成
  • httpアプリまたは外部サービスのテスト
  • 一般的なhttpタスクのアサーション
  • chai expect および should インターフェース

インストール

これはChaiアサーションライブラリのアドオンプラグインです。npm経由でインストールしてください。

npm install chai-http

プラグイン

他のすべてのChaiプラグインと同様にこのプラグインを使用します。

var chai = require('chai')
  , chaiHttp = require('chai-http');

chai.use(chaiHttp);

WebページでChai HTTPを使用するには、dist/chai-http.jsファイルを含めるだけです

<script src="chai.js"></script>
<script src="chai-http.js"></script>
<script>
  chai.use(chaiHttp);
</script>

統合テスト

Chai HTTPは、superagentを介してライブ統合テスト用のインターフェースを提供します。これを行うには、最初にアプリケーションまたはURLへのリクエストを構築する必要があります。

構築すると、呼び出したいhttp VERBリクエスト(get、postなど)を指定できるチェーン可能なAPIが提供されます。

アプリケーション/サーバー

関数(expressまたはconnectアプリなど)またはnode.js http(s)サーバーをリクエストの基礎として使用できます。サーバーが実行されていない場合、chai-httpは特定のテストでリッスンするのに適切なポートを見つけます。

注:この機能は、Webブラウザーではなく、Node.jsでのみサポートされています。

chai.request(app)
  .get('/')

apprequestに渡すと、着信リクエストのためにサーバーが自動的に開かれ(listen()を呼び出すことにより)、リクエストが行われると、サーバーは自動的にシャットダウンされます(.close()を呼び出すことにより)。複数のリクエストを作成する場合など、サーバーを開いたままにする場合は、.request()の後に.keepOpen()を呼び出して、サーバーを手動で閉じる必要があります

var requester = chai.request(app).keepOpen()

Promise.all([
  requester.get('/a'),
  requester.get('/b'),
])
.then(responses => ....)
.then(() => requester.close())

URL

リクエストの基礎としてベースURLを使用することもできます。

chai.request('https://:8080')
  .get('/')

リクエストの設定

指定されたVERB(get、postなど)でリクエストが作成されたら、これらの追加メソッドを連鎖させてリクエストを作成します

メソッド 目的
.set(key, value) リクエストヘッダーを設定します
.send(data) リクエストデータを設定します(デフォルトのタイプはJSONです)
.type(dataType) .send()メソッドから送信されるデータのタイプを変更します(xml、フォームなど)
.attach(field, file, attachment) ファイルを添付します
.auth(username, password) Basic認証用の認証ヘッダーを追加します
.query(parmasObject) いくつかのGETパラメーターを連鎖させます

.set()

// Set a request header
chai.request(app)
  .put('/user/me')
  .set('Content-Type', 'application/json')
  .send({ password: '123', confirmPassword: '123' })

.send()

// Send some JSON
chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })

.type()

// Send some Form Data
chai.request(app)
  .post('/user/me')
  .type('form')
  .send({
    '_method': 'put',
    'password': '123',
    'confirmPassword': '123'
  })

.attach()

// Attach a file
chai.request(app)
  .post('/user/avatar')
  .attach('imageField', fs.readFileSync('avatar.png'), 'avatar.png')

.auth()

// Authenticate with Basic authentication
chai.request(app)
  .get('/protected')
  .auth('user', 'pass')

.query()

// Chain some GET query parameters
chai.request(app)
  .get('/search')
  .query({name: 'foo', limit: 10}) // /search?name=foo&limit=10

レスポンスの処理 - 従来の方法

次の例では、ChaiのExpectアサーションライブラリを使用します

var expect = chai.expect;

リクエストを作成してそのレスポンスをアサートするには、endメソッドを使用できます

chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })
  .end(function (err, res) {
     expect(err).to.be.null;
     expect(res).to.have.status(200);
  });
注意点

end関数にはコールバックが渡されるため、アサーションは非同期的に実行されます。したがって、コールバックが完了したことをテストフレームワークに通知するメカニズムを使用する必要があります。そうしないと、アサーションがチェックされる前にテストが合格します。

たとえば、Mochaテストフレームワークでは、これはdoneコールバックを使用して実行されます。これは、コールバックが完了したことを示すものであり、アサーションを検証できます

it('fails, as expected', function(done) { // <= Pass in done callback
  chai.request('https://:8080')
  .get('/')
  .end(function(err, res) {
    expect(res).to.have.status(123);
    done();                               // <= Call done to signal callback end
  });
});

it('succeeds silently!', function() {   // <= No done callback
  chai.request('https://:8080')
  .get('/')
  .end(function(err, res) {
    expect(res).to.have.status(123);    // <= Test completes before this runs
  });
});

doneが渡されると、Mochaはdone()の呼び出しまで、またはタイムアウトが切れるまで待機します。doneは完了を通知するときにエラーパラメーターも受け入れます。

レスポンスの処理 - Promise

Promiseが利用可能な場合、request()はPromise対応ライブラリになり、thenのチェーンが可能になります

chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })
  .then(function (res) {
     expect(res).to.have.status(200);
  })
  .catch(function (err) {
     throw err;
  });

注:Node.jsバージョン0.10.xおよび一部の古いWebブラウザーには、ネイティブのPromiseサポートがありません。次のような仕様に準拠したライブラリを使用できます。

// Add promise support if this does not exist natively.
if (!global.Promise) {
  global.Promise = require('q');
}
var chai = require('chai');
chai.use(require('chai-http'));

各リクエストでCookieを保持する

場合によっては、あるリクエストからCookieを保持し、次のリクエストでそれらを送信する必要があります(たとえば、最初のリクエストでログインし、後で認証が必要なリソースにアクセスする場合)。このために、.request.agent()が利用可能です

// Log in
var agent = chai.request.agent(app)
agent
  .post('/session')
  .send({ username: 'me', password: '123' })
  .then(function (res) {
    expect(res).to.have.cookie('sessionid');
    // The `agent` now has the sessionid cookie saved, and will send it
    // back to the server in the next request:
    return agent.get('/user/me')
      .then(function (res) {
         expect(res).to.have.status(200);
      });
  });

注:chai.request.agent(app)によって起動されたサーバーは、テストの完了後に自動的に閉じません。プログラムが確実に終了するように、テスト後にagent.close()を呼び出す必要があります。

アサーション

Chai HTTPモジュールは、expectおよびshouldインターフェースに対して多数のアサーションを提供します。

.status (code)

  • @param {Number} ステータス番号

レスポンスが指定されたステータスを持っていることをアサートします。

expect(res).to.have.status(200);

.header (key[, value])

  • @param {String} ヘッダーキー(大文字と小文字を区別しない)
  • @param _{String RegExp}_ ヘッダー値(オプション)

ResponseまたはRequestオブジェクトがヘッダーを持っていることをアサートします。値が指定されている場合、値との等価性がアサートされます。チェックするために正規表現を渡すこともできます。

注:Webブラウザーで実行する場合、同一オリジンポリシーにより、Chai HTTPは特定のヘッダーのみを読み取ることができ、アサーションが失敗する可能性があります。

expect(req).to.have.header('x-api-key');
expect(req).to.have.header('content-type', 'text/plain');
expect(req).to.have.header('content-type', /^text/);

.headers

ResponseまたはRequestオブジェクトにヘッダーがあることをアサートします。

注:Webブラウザーで実行する場合、同一オリジンポリシーにより、Chai HTTPは特定のヘッダーのみを読み取ることができ、アサーションが失敗する可能性があります。

expect(req).to.have.headers;

.ip

文字列が有効なIPアドレスを表すことをアサートします。

expect('127.0.0.1').to.be.an.ip;
expect('2001:0db8:85a3:0000:0000:8a2e:0370:7334').to.be.an.ip;

.json / .text / .html

ResponseまたはRequestオブジェクトに指定されたcontent-typeがあることをアサートします。

expect(req).to.be.json;
expect(req).to.be.html;
expect(req).to.be.text;

.charset

ResponseまたはRequestオブジェクトに指定されたcharsetがあることをアサートします。

expect(req).to.have.charset('utf-8');

.redirect

Responseオブジェクトにリダイレクトステータスコードがあることをアサートします。

expect(res).to.redirect;
expect(res).to.not.redirect;

.redirectTo

  • @param _{String RegExp}_ ロケーションURL

Responseオブジェクトが指定されたロケーションにリダイレクトすることをアサートします。

expect(res).to.redirectTo('http://example.com');
expect(res).to.redirectTo(/^\/search\/results\?orderBy=desc$/);

.param

  • @param {String} パラメーター名
  • @param {String} パラメーター値

Requestオブジェクトに、指定されたキーを持ち、(オプションで)値と等しいクエリ文字列パラメーターがあることをアサートします

expect(req).to.have.param('orderby');
expect(req).to.have.param('orderby', 'date');
expect(req).to.not.have.param('limit');
  • @param {String} パラメーター名
  • @param {String} パラメーター値

RequestまたはResponseオブジェクトに、指定されたキーを持ち、(オプションで)値と等しいcookieヘッダーがあることをアサートします

expect(req).to.have.cookie('session_id');
expect(req).to.have.cookie('session_id', '1234');
expect(req).to.not.have.cookie('PHPSESSID');
expect(res).to.have.cookie('session_id');
expect(res).to.have.cookie('session_id', '1234');
expect(res).to.not.have.cookie('PHPSESSID');

リリース

chai-httpは、semantic-releaseを使用して、次のプラグインでリリースされます

ライセンス

(MITライセンス)

Copyright (c) Jake Luer jake@alogicalparadox.com

このソフトウェアおよび関連ドキュメントファイル(「ソフトウェア」)のコピーを入手するすべての人に対し、以下の条件に従うことを条件として、ソフトウェアの使用、コピー、変更、結合、公開、配布、サブライセンス、および/またはソフトウェアのコピーの販売を含むがこれらに限定されない、ソフトウェアを制限なく扱う権利を無償でここに許可します。

上記の著作権表示およびこの許可表示は、ソフトウェアのすべてのコピーまたは実質的な部分に含まれるものとします。

本ソフトウェアは、「現状のまま」、明示的または黙示的を問わず、商品性、特定目的への適合性、および非侵害の保証を含むがこれらに限定されない、いかなる種類の保証もなしに提供されます。いかなる場合も、著者または著作権者は、契約、不法行為、またはその他によるかにかかわらず、ソフトウェアの使用またはその他の取引から、またはそれに関連して発生するいかなる請求、損害、またはその他の責任についても責任を負いません。