私はPassport.jsを認証(ローカル戦略)に使用し、MochaとSupertestでテストしています。PassportでSupertest要求を認証する方法は?
セッションを作成し、認証済みのリクエストをSupertestで作成するにはどうすればよいですか?
私はPassport.jsを認証(ローカル戦略)に使用し、MochaとSupertestでテストしています。PassportでSupertest要求を認証する方法は?
セッションを作成し、認証済みのリクエストをSupertestで作成するにはどうすればよいですか?
これにはsuperagentを使用してください。これは下位レベルのモジュールで、supertest
によって使用されます。
var request = require('superagent');
var user1 = request.agent();
user1
.post('http://localhost:4000/signin')
.send({ user: '[email protected]', password: 'password' })
.end(function(err, res) {
// user1 will manage its own cookies
// res.redirects contains an Array of redirects
});
今、あなたは、認証済みの要求を行うためにuser1
を使用することができます:セクションPersisting an agentを見てみましょう。
は
var request=require('supertest');
var cookie;
request(app)
.post('/login')
.send({ email: "[email protected]", password:'password' })
.end(function(err,res){
res.should.have.status(200);
cookie = res.headers['set-cookie'];
done();
});
//
// and use the cookie on the next request
request(app)
.get('/v1/your/path')
.set('cookie', cookie)
.end(function(err,res){
res.should.have.status(200);
done();
});
は、私はあなたがCookieSessionミドルウェアを使用していると仮定するつもりだ、これを試してみてください。
前述のように、目標はリクエストに渡すCookieの値を取得することです。しかし、何らかの理由で(少なくとも私のテストでは)、supertestは同じテストで2つのリクエストを起動しません。したがって、適切なクッキー値を取得する方法をリバースエンジニアリングする必要があります。まず、クッキーを構築するためにモジュールを必要とする必要があります:
var Cookie = require("express/node_modules/connect/lib/middleware/session/cookie")
, cookieSignature = require("express/node_modules/cookie-signature")
はい、それは醜いです。私はそれらをテストファイルの一番上に置きます。
次に、クッキー値を作成する必要があります。私は、認証されたユーザーが必要となるテスト用beforeEach
にこれを置く:
var cookie = new Cookie()
, session = {
passport: {
user: Test.user.id
}
}
var val = "j:" + JSON.stringify(session)
val = 's:' + cookieSignature.sign(val, App.config.cookieSecret)
Test.cookie = cookie.serialize("session",val)
Test.user.id
は、以前私は「ログイン」としていたユーザーを定義し、私のbeforeEach
鎖の一部で定義されていました。 session
の構造は、Passport(現在は少なくとも現在)が現在のユーザー情報をセッションに挿入する方法です。
"j:"
と"s:"
の行は、Cookieベースのセッションを使用している場合、PassportがフォールバックするConnect CookieSessionミドルウェアから切り捨てられます。最後に、Cookieをシリアライズします。私は"session"
をそこに入れました。それが私のCookieセッションミドルウェアをどのように設定したのかということです。また、App.config.cookieSecret
は他の場所で定義されており、Express/Connect CookieSessionミドルウェアに渡す秘密でなければなりません。私はそれを後でアクセスできるように、Test.cookie
に隠しています。
実際のテストでは、そのクッキーを使用する必要があります。例えば、私は次のテストがあります
it("should logout a user", function(done) {
r = request(App.app)
.del(App.Test.versionedPath("/logout"))
.set("cookie", Test.cookie)
// ... other sets and expectations and your .end
}
を"cookie"
とTest.cookie
とset
への呼び出しに注目してください。これにより、リクエストしたCookieを使用するようになります。
これで、ユーザーがログインしていると考えてアプリを偽装し、実際のサーバーを稼働させる必要はありません。
また、要求ハンドラを直接テストして、いくつかのダミーのreqおよびresオブジェクトを渡すこともできます。もちろん、それはあなたのルーティングをテストしません。 – juanpaco
zeMircoが指摘するように、基盤となるsuperagent
モジュールはセッションをサポートし、自動的にクッキーを管理します。ただし、文書化されていない機能を通じてsupertest
のsuperagent.agent()
機能を使用することは可能です。
単に代わりrequire('supertest')('url')
のrequire('supertest').agent('url')
を使用します。アンディの答えに補遺として
var request = require('supertest');
var server = request.agent('http://localhost:3000');
describe('GET /api/getDir', function(){
it('login', loginUser());
it('uri that requires user to be logged in', function(done){
server
.get('/api/getDir')
.expect(200)
.end(function(err, res){
if (err) return done(err);
console.log(res.body);
done()
});
});
});
function loginUser() {
return function(done) {
server
.post('/login')
.send({ username: 'admin', password: 'admin' })
.expect(302)
.expect('Location', '/')
.end(onResponse);
function onResponse(err, res) {
if (err) return done(err);
return done();
}
};
};
app.jsを '' 'request.agent(app);' 'に入れると、実行中のサーバなしで動作します。クール。 – shredding
現在、このソリューションが機能しています。 –
、Supertestはあなたのためにサーバーを起動させるために、あなたはこのようにそれを行うことができます。
var request = require('supertest');
/**
* `../server` should point to your main server bootstrap file,
* which has your express app exported. For example:
*
* var app = express();
* module.exports = app;
*/
var server = require('../server');
// Using request.agent() is the key
var agent = request.agent(server);
describe('Sessions', function() {
it('Should create a session', function(done) {
agent.post('/api/session')
.send({ username: 'user', password: 'pass' })
.end(function(err, res) {
expect(req.status).to.equal(201);
done();
});
});
it('Should return the current session', function(done) {
agent.get('/api/session').end(function(err, res) {
expect(req.status).to.equal(200);
done();
});
});
});
'req.status'ではなく' expect(res.status) 'でなければなりません。 –
申し訳ありませんが、どちらの解決方法も私にとってはうまくいかない。
がsupertest.agent()
で、私は、私はsupertest-as-promised
のlibを使用することはできません、私は事前にサーバーを実行するために必要だapp
インスタンスを使用してhttp://127.0.0.1:port
を指定し、しかも私はsupertestの期待(アサーション)を使用することはできませんすることはできませんし、 so on ...
cookies
ケースはまったく機能しません。
だから、私の解決策は次のとおりです。
あなたはPassport.jsを使用している場合は、それが「無記名トークン」メカニズムを利用して、あなたのスペックでは、以下の例を使用することができます。
var request = require('supertest');
var should = require('should');
var app = require('../server/app.js'); // your server.js file
describe('Some auth-required API', function() {
var token;
before(function (done) {
request(app)
.post('/auth/local')
.send({
email: '[email protected]',
password: 'the secret'
})
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.to.have.property('token');
token = res.body.token;
done();
});
});
it('should respond with status code 200 and so on...', function (done) {
request(app)
.get('/api/v2/blah-blah')
.set('authorization', 'Bearer ' + token) // 1) using the authorization header
.expect(200)
.expect('Content-Type', /json/)
.end(function (err, res) {
if (err) {
return done(err);
}
// some `res.body` assertions...
done();
});
});
it('should respond with status code 200 and so on...', function (done) {
request(app)
.get('/api/v2/blah-blah')
.query({access_token: token}) // 2) using the query string
.expect(200)
.expect('Content-Type', /json/)
.end(function (err, res) {
if (err) {
return done(err);
}
// some `res.body` assertions...
done();
});
});
});
あなたは、ユーザーを認証するためのヘルパー機能を持つようにしたいことがあります。
test/auth-helper.js
'use strict';
var request = require('supertest');
var app = require('app.js');
/**
* Authenticate a test user.
*
* @param {User} user
* @param {function(err:Error, token:String)} callback
*/
exports.authenticate = function (user, callback) {
request(app)
.post('/auth/local')
.send({
email: user.email,
password: user.password
})
.end(function (err, res) {
if (err) {
return callback(err);
}
callback(null, res.body.token);
});
};
生産的な1日を過ごしましょう!
この方法では、テストサーバーを実行する必要があります。それはSupertestのサーバーでも使用できますか? セッション・クッキーを使用していますが、動作しません。私はuser1.postからの応答を見て、Cookieにはユーザー情報が含まれていません。 –
テスト・サーバーは必要ありません。通常のexpress app.jsを使用することができますあなたは[example](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js)を見ましたか?テストを別のファイルに保存したい場合は、ヘッダーに 'require(../ app.js)'を入れてアプリを起動してください。 – zemirco
私はそれが動作するようにしましたが、すでに実行されている開発サーバーを強制終了した場合に限ります。 supertestと私はそれをする必要はありません。どのようにしてそれをスーパーエージェントとうまく組み合わせるためのアイディアですか?おそらく、テスト環境のために別のポートを聞く? –