Files
kami-parse-server/spec/Adapters/Auth/line.spec.js

310 lines
7.9 KiB
JavaScript

const LineAdapter = require('../../../lib/Adapters/Auth/line').default;
describe('LineAdapter', function () {
let adapter;
beforeEach(function () {
adapter = new LineAdapter.constructor();
adapter.clientId = 'validClientId';
adapter.clientSecret = 'validClientSecret';
});
describe('getAccessTokenFromCode', function () {
it('should throw an error if code is missing in authData', async function () {
const authData = { redirect_uri: 'http://example.com' };
await expectAsync(adapter.getAccessTokenFromCode(authData)).toBeRejectedWithError(
'Line auth is invalid for this user.'
);
});
it('should fetch an access token successfully', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: true,
json: () =>
Promise.resolve({
access_token: 'mockAccessToken',
}),
},
},
]);
const authData = {
code: 'validCode',
redirect_uri: 'http://example.com',
};
const token = await adapter.getAccessTokenFromCode(authData);
expect(token).toBe('mockAccessToken');
});
it('should throw an error if response is not ok', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: false,
statusText: 'Bad Request',
},
},
]);
const authData = {
code: 'invalidCode',
redirect_uri: 'http://example.com',
};
await expectAsync(adapter.getAccessTokenFromCode(authData)).toBeRejectedWithError(
'Failed to exchange code for token: Bad Request'
);
});
it('should throw an error if response contains an error object', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: true,
json: () =>
Promise.resolve({
error: 'invalid_grant',
error_description: 'Code is invalid',
}),
},
},
]);
const authData = {
code: 'invalidCode',
redirect_uri: 'http://example.com',
};
await expectAsync(adapter.getAccessTokenFromCode(authData)).toBeRejectedWithError(
'Code is invalid'
);
});
});
describe('getUserFromAccessToken', function () {
it('should fetch user data successfully', async function () {
mockFetch([
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: true,
json: () =>
Promise.resolve({
userId: 'mockUserId',
displayName: 'mockDisplayName',
}),
},
},
]);
const accessToken = 'validAccessToken';
const user = await adapter.getUserFromAccessToken(accessToken);
expect(user).toEqual({
userId: 'mockUserId',
displayName: 'mockDisplayName',
});
});
it('should throw an error if response is not ok', async function () {
mockFetch([
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: false,
statusText: 'Unauthorized',
},
},
]);
const accessToken = 'invalidAccessToken';
await expectAsync(adapter.getUserFromAccessToken(accessToken)).toBeRejectedWithError(
'Failed to fetch Line user: Unauthorized'
);
});
it('should throw an error if user data is invalid', async function () {
mockFetch([
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: true,
json: () => Promise.resolve({}),
},
},
]);
const accessToken = 'validAccessToken';
await expectAsync(adapter.getUserFromAccessToken(accessToken)).toBeRejectedWithError(
'Invalid Line user data received.'
);
});
});
describe('LineAdapter E2E Test', function () {
beforeEach(async function () {
await reconfigureServer({
auth: {
line: {
clientId: 'validClientId',
clientSecret: 'validClientSecret',
},
},
});
});
it('should log in user successfully with valid code', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: true,
json: () =>
Promise.resolve({
access_token: 'mockAccessToken123',
}),
},
},
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: true,
json: () =>
Promise.resolve({
userId: 'mockUserId',
displayName: 'mockDisplayName',
}),
},
},
]);
const authData = {
code: 'validCode',
redirect_uri: 'http://example.com',
};
const user = await Parse.User.logInWith('line', { authData });
expect(user.id).toBeDefined();
});
it('should handle error when token exchange fails', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: false,
statusText: 'Invalid code',
},
},
]);
const authData = {
code: 'invalidCode',
redirect_uri: 'http://example.com',
};
await expectAsync(Parse.User.logInWith('line', { authData })).toBeRejectedWithError(
'Failed to exchange code for token: Invalid code'
);
});
it('should handle error when user data fetch fails', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: true,
json: () =>
Promise.resolve({
access_token: 'mockAccessToken123',
}),
},
},
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: false,
statusText: 'Unauthorized',
},
},
]);
const authData = {
code: 'validCode',
redirect_uri: 'http://example.com',
};
await expectAsync(Parse.User.logInWith('line', { authData })).toBeRejectedWithError(
'Failed to fetch Line user: Unauthorized'
);
});
it('should handle error when user data is invalid', async function () {
mockFetch([
{
url: 'https://api.line.me/oauth2/v2.1/token',
method: 'POST',
response: {
ok: true,
json: () =>
Promise.resolve({
access_token: 'mockAccessToken123',
}),
},
},
{
url: 'https://api.line.me/v2/profile',
method: 'GET',
response: {
ok: true,
json: () => Promise.resolve({}),
},
},
]);
const authData = {
code: 'validCode',
redirect_uri: 'http://example.com',
};
await expectAsync(Parse.User.logInWith('line', { authData })).toBeRejectedWithError(
'Invalid Line user data received.'
);
});
it('should handle error when no code is provided', async function () {
mockFetch();
const authData = {
redirect_uri: 'http://example.com',
};
await expectAsync(Parse.User.logInWith('line', { authData })).toBeRejectedWithError(
'Line code is required.'
);
});
});
});