У меня проблема, которая забирает мою голову. Я выполняю социальную регистрацию через Facebook и Google, используя паспорт JS, passport-facebook-token
и passport-google-oauth20
внутри моего узла - express API.
Проблема возникает при модульном тестировании; Я не нашел, как сделать интеграцию.
Вот что я попробовал:
Маршруты
router.post(
'/facebook',
passport.authenticate('facebook-token', { session: false }),
authCtrl.socialLogin,
);
router.post('/google', passport.authenticate('google', { session: false }), authCtrl.socialLogin);
Маршрут использует паспорт JS промежуточное ПО, которое я конфигурируется следующим образом:
passport.use(
'facebook-token',
new FacebookTokenStrategy(
{
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
},
async (_accessToken: string, _refreshToken: string, profile, done) => {
done(null, profile);
},
),
);
passport.use(
'google',
new GoogleStrategy(
{
clientID: GOOGLE_APP_ID,
clientSecret: GOOGLE_APP_SECRET,
},
async (_accessToken: string, _refreshToken: string, profile, done) => {
done(undefined, profile);
},
),
);
Контроллер
Вот как выглядит мой контроллер
public async socialLogin(req: Request, res: Response): Promise<any> {
try {
const { provider, displayName, emails, photos }: any = req.user;
const profile = {
username: displayName.replace(' ', '_').toLowerCase(),
email: emails ? emails[0].value : null,
image: photos[0].value,
};
console.log(req.user);
User.findOneAndUpdate(
{ 'profile.username': profile.username, 'profile.email': profile.email },
{ provider, profile, isLoggedIn: true, isAdmin: false },
{ new: true, upsert: true },
(err, data: any) => {
if (err) return helper.getServerError(res, err.message);
const { _id, profile, isAdmin } = data;
const { email } = profile;
const token = helper.generateToken({ _id, email, isAdmin });
return helper.getResponse(res, httpStatus.CREATED, { token, data });
},
);
return helper.getResponse(res, httpStatus.CREATED, { data: profile });
} catch (error) {
return helper.getServerError(res, error.message);
}
}
const { provider, displayName, emails, photos }: any = req.user;
Короче говоря, я должны получать провайдера, displayName, электронные письма и фотографии от объекта user
, который естественным образом возвращается методом промежуточного программного обеспечения authenticate()
для паспорта. Вы можете оглянуться назад на определение маршрута, чтобы понять.
Модульный тест
Поскольку я использую jest для модульного тестирования контроллера, я использовал метод насмешки над ответом и запросом, чтобы я мог передать объект user
в запрос , Я пытался использовать утилиты для проверки подлинности из jest, я не смог правильно смоделировать запрос и ответ express, поэтому попытался использовать разные сторонние библиотеки, такие как jest- express, которые я нашел так интересно
Вот как выглядит мой тест:
describe(Auth.prototype.socialLogin, () => {
let response: any;
let request: any;
beforeEach(() => {
response = new Response();
});
afterAll(() => {
response.resetMocked();
request.resetMocked();
});
it('should create a new user', async () => {
const requestMock: any = {
user: {
provider: 'facebook-token',
displayName: 'user name',
emails: [{ value: 'username@mail.com' }],
photos: [{ value: 'image.jpg' }],
},
};
request = new Request(requestMock);
await authCtrl.socialLogin(request, response);
expect(response.status).toHaveBeenCalledWith(201);
});
});
Проблема
Когда я запускаю тест, я получаю этот ответ.
Наглядно видно, что контроллер работает, но падает на блок перехвата, который предполагает, что статус 500 означает неправильный запрос.
Поэтому мне очень нужна помощь, если есть место, где я делаю что-то неправильно, или любая документация, которая может помочь мне эффективно высмеивать express ответ и запрос.