0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor: use vitest for connectors (#5562)

This commit is contained in:
Gao Sun 2024-03-28 10:21:50 +08:00 committed by GitHub
parent 2ccc54ac98
commit d45cd37f9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
76 changed files with 634 additions and 856 deletions

View file

@ -1,8 +1,7 @@
# generated files
/*/types
/*/tsconfig.*
/*/jest.config.*
/*/rollup.config.*
/*/vitest.config.*
# keep templates
!/templates/**

View file

@ -29,9 +29,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,13 +6,11 @@ import { alipayEndpoint } from './constant.js';
import createConnector, { getAccessToken } from './index.js';
import { mockedAlipayNativeConfigWithValidPrivateKey } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedAlipayNativeConfigWithValidPrivateKey);
const getConfig = vi.fn().mockResolvedValue(mockedAlipayNativeConfigWithValidPrivateKey);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by state', async () => {
@ -26,7 +24,7 @@ describe('getAuthorizationUri', () => {
jti: 'dummy-jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toBe('alipay://?app_id=2021000000000000&state=dummy-state');
});
@ -35,7 +33,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const alipayEndpointUrl = new URL(alipayEndpoint);
@ -72,7 +70,7 @@ describe('getAccessToken', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -93,7 +91,7 @@ describe('getAccessToken', () => {
});
await expect(
getAccessToken('code', mockedAlipayNativeConfigWithValidPrivateKey)
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
it('should fail with wrong code', async () => {
@ -110,7 +108,7 @@ describe('getAccessToken', () => {
});
await expect(
getAccessToken('wrong_code', mockedAlipayNativeConfigWithValidPrivateKey)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'Invalid code')
);
});
@ -136,7 +134,7 @@ describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const alipayEndpointUrl = new URL(alipayEndpoint);
@ -158,7 +156,7 @@ describe('getUserInfo', () => {
const connector = await createConnector({ getConfig });
const { id, name, avatar, rawData } = await connector.getUserInfo(
{ auth_code: 'code' },
jest.fn()
vi.fn()
);
expect(id).toEqual('2088000000000000');
expect(name).toEqual('PlayboyEric');
@ -189,9 +187,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'Invalid auth token')
);
});
@ -210,9 +206,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'Invalid auth code')
);
});
@ -231,9 +225,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'Invalid parameter',
code: '40002',
@ -258,14 +250,14 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.InvalidResponse));
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
);
});
it('should throw with other request errors', async () => {
nock(alipayEndpointUrl.origin).post(alipayEndpointUrl.pathname).query(true).reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toThrow();
});
});

View file

@ -5,14 +5,12 @@ import {
} from './mock.js';
import { signingParameters } from './utils.js';
const { jest } = import.meta;
const listenJSONParse = jest.spyOn(JSON, 'parse');
const listenJSONStringify = jest.spyOn(JSON, 'stringify');
const listenJSONParse = vi.spyOn(JSON, 'parse');
const listenJSONStringify = vi.spyOn(JSON, 'stringify');
describe('signingParameters', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
const testingParameters = {

View file

@ -28,9 +28,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,13 +6,11 @@ import { alipayEndpoint, authorizationEndpoint } from './constant.js';
import createConnector, { getAccessToken } from './index.js';
import { mockedAlipayConfigWithValidPrivateKey } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedAlipayConfigWithValidPrivateKey);
const getConfig = vi.fn().mockResolvedValue(mockedAlipayConfigWithValidPrivateKey);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
@ -26,7 +24,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?app_id=2021000000000000&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback&scope=auth_user&state=some_state`
@ -37,7 +35,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const alipayEndpointUrl = new URL(alipayEndpoint);
@ -78,7 +76,7 @@ describe('getAccessToken', () => {
await expect(
getAccessToken('code', mockedAlipayConfigWithValidPrivateKey)
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
it('should fail with wrong code', async () => {
@ -96,7 +94,7 @@ describe('getAccessToken', () => {
await expect(
getAccessToken('wrong_code', mockedAlipayConfigWithValidPrivateKey)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'Invalid code')
);
});
@ -105,7 +103,7 @@ describe('getAccessToken', () => {
describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
beforeEach(() => {
@ -144,7 +142,7 @@ describe('getUserInfo', () => {
const connector = await createConnector({ getConfig });
const { id, name, avatar, rawData } = await connector.getUserInfo(
{ auth_code: 'code' },
jest.fn()
vi.fn()
);
expect(id).toEqual('2088000000000000');
expect(name).toEqual('PlayboyEric');
@ -163,7 +161,7 @@ describe('getUserInfo', () => {
it('throw General error if auth_code not provided in input', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.InvalidResponse, '{}')
);
});
@ -182,9 +180,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'Invalid auth token')
);
});
@ -203,9 +199,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'Invalid auth code')
);
});
@ -224,9 +218,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ auth_code: 'wrong_code' }, jest.fn())
).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'wrong_code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'Invalid parameter',
code: '40002',
@ -251,7 +243,7 @@ describe('getUserInfo', () => {
sign: '<signature>',
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ auth_code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ auth_code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
);
});
@ -259,6 +251,6 @@ describe('getUserInfo', () => {
it('should throw with other request errors', async () => {
nock(alipayEndpointUrl.origin).post(alipayEndpointUrl.pathname).query(true).reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ auth_code: 'code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ auth_code: 'code' }, vi.fn())).rejects.toThrow();
});
});

View file

@ -2,14 +2,12 @@ import { methodForAccessToken } from './constant.js';
import { mockedAlipayConfigWithValidPrivateKey, mockedAlipayPublicParameters } from './mock.js';
import { signingParameters } from './utils.js';
const { jest } = import.meta;
const listenJSONParse = jest.spyOn(JSON, 'parse');
const listenJSONStringify = jest.spyOn(JSON, 'stringify');
const listenJSONParse = vi.spyOn(JSON, 'parse');
const listenJSONStringify = vi.spyOn(JSON, 'stringify');
describe('signingParameters', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
const testingParameters = {

View file

@ -23,9 +23,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,16 +2,14 @@ import { TemplateType } from '@logto/connector-kit';
import { mockedConfigWithAllRequiredTemplates } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConfigWithAllRequiredTemplates);
const getConfig = jest.fn().mockResolvedValue(mockedConfigWithAllRequiredTemplates);
const singleSendMail = jest.fn(() => ({
const singleSendMail = vi.fn(() => ({
body: JSON.stringify({ EnvId: 'env-id', RequestId: 'request-id' }),
statusCode: 200,
}));
jest.unstable_mockModule('./single-send-mail.js', () => ({
vi.mock('./single-send-mail.js', () => ({
singleSendMail,
}));
@ -19,7 +17,7 @@ const { default: createConnector } = await import('./index.js');
describe('sendMessage()', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should call singleSendMail() with correct template and content', async () => {

View file

@ -1,8 +1,6 @@
const { jest } = import.meta;
const request = vi.fn();
const request = jest.fn();
jest.unstable_mockModule('./utils.js', () => ({
vi.mock('./utils.js', () => ({
request,
}));

View file

@ -1,10 +1,8 @@
import { mockedParameters } from './mock.js';
const { jest } = import.meta;
const post = vi.fn();
const post = jest.fn();
jest.unstable_mockModule('got', () => ({
vi.mock('got', () => ({
got: { post },
}));

View file

@ -23,9 +23,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,16 +2,14 @@ import { TemplateType } from '@logto/connector-kit';
import { mockedConnectorConfig, phoneTest, codeTest } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConnectorConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConnectorConfig);
const sendSms = jest.fn().mockResolvedValue({
const sendSms = vi.fn().mockResolvedValue({
body: JSON.stringify({ Code: 'OK', RequestId: 'request-id', Message: 'OK' }),
statusCode: 200,
});
jest.unstable_mockModule('./single-send-text.js', () => ({
vi.mock('./single-send-text.js', () => ({
sendSms,
}));
@ -19,7 +17,7 @@ const { default: createConnector } = await import('./index.js');
describe('sendMessage()', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should call singleSendMail() and replace code in content', async () => {

View file

@ -1,10 +1,8 @@
import { mockedRandomCode } from './mock.js';
const { jest } = import.meta;
const request = vi.fn();
const request = jest.fn();
jest.unstable_mockModule('./utils.js', () => ({ request }));
vi.mock('./utils.js', () => ({ request }));
const { sendSms } = await import('./single-send-text.js');

View file

@ -1,10 +1,8 @@
import { mockedParameters } from './mock.js';
const { jest } = import.meta;
const post = vi.fn();
const post = jest.fn();
jest.unstable_mockModule('got', () => ({
vi.mock('got', () => ({
got: { post },
}));

View file

@ -25,9 +25,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,15 +2,13 @@ import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-kit';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const jwtVerify = vi.fn();
const jwtVerify = jest.fn();
jest.unstable_mockModule('jose', () => ({
vi.mock('jose', () => ({
jwtVerify,
createRemoteJWKSet: jest.fn(),
createRemoteJWKSet: vi.fn(),
}));
const { authorizationEndpoint } = await import('./constant.js');
@ -18,12 +16,12 @@ const { default: createConnector } = await import('./index.js');
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
const connector = await createConnector({ getConfig });
const setSession = jest.fn();
const setSession = vi.fn();
const authorizationUri = await connector.getAuthorizationUri(
{
state: 'some_state',
@ -50,7 +48,7 @@ describe('getAuthorizationUri', () => {
describe('getUserInfo', () => {
afterAll(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get user info from id token payload', async () => {
@ -59,7 +57,7 @@ describe('getUserInfo', () => {
payload: { sub: userId, email: 'foo@bar.com', email_verified: true },
}));
const connector = await createConnector({ getConfig });
const userInfo = await connector.getUserInfo({ id_token: 'idToken' }, jest.fn());
const userInfo = await connector.getUserInfo({ id_token: 'idToken' }, vi.fn());
expect(userInfo).toEqual({
id: userId,
email: 'foo@bar.com',
@ -72,7 +70,7 @@ describe('getUserInfo', () => {
payload: { sub: 'userId', email: 'foo@bar.com' },
}));
const connector = await createConnector({ getConfig });
const userInfo = await connector.getUserInfo({ id_token: 'idToken' }, jest.fn());
const userInfo = await connector.getUserInfo({ id_token: 'idToken' }, vi.fn());
expect(userInfo).toEqual({ id: 'userId', rawData: { id_token: 'idToken' } });
});
@ -90,7 +88,7 @@ describe('getUserInfo', () => {
name: { firstName: 'foo', lastName: 'bar' },
}),
},
jest.fn()
vi.fn()
);
// Should use info from `user` field first
expect(userInfo).toEqual({
@ -109,7 +107,7 @@ describe('getUserInfo', () => {
it('should throw if id token is missing', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -119,7 +117,7 @@ describe('getUserInfo', () => {
throw new Error('jwtVerify failed');
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ id_token: 'id_token' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ id_token: 'id_token' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialIdTokenInvalid)
);
});
@ -129,7 +127,7 @@ describe('getUserInfo', () => {
payload: { iat: 123_456 },
}));
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ id_token: 'id_token' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ id_token: 'id_token' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialIdTokenInvalid)
);
});

View file

@ -26,9 +26,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -4,11 +4,9 @@ import { TemplateType } from '@logto/connector-kit';
import createConnector from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
jest.spyOn(SESv2Client.prototype, 'send').mockResolvedValue({
vi.spyOn(SESv2Client.prototype, 'send').mockResolvedValue({
MessageId: 'mocked-message-id',
$metadata: {
httpStatusCode: 200,
@ -17,7 +15,7 @@ jest.spyOn(SESv2Client.prototype, 'send').mockResolvedValue({
describe('sendMessage()', () => {
afterAll(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should call SendMail() with correct template and content', async () => {

View file

@ -25,7 +25,6 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,14 +6,12 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('Discord connector', () => {
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid authorizationUri with redirectUri and state', async () => {
@ -27,7 +25,7 @@ describe('Discord connector', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&response_type=code&scope=identify+email&state=some_state`
@ -38,7 +36,7 @@ describe('Discord connector', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -66,7 +64,7 @@ describe('Discord connector', () => {
await expect(
getAccessToken(mockedConfig, { code: 'code', redirectUri: 'dummyRedirectUri' })
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
});
@ -82,7 +80,7 @@ describe('Discord connector', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -99,7 +97,7 @@ describe('Discord connector', () => {
code: 'code',
redirectUri: 'dummyRedirectUri',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toStrictEqual({
id: '1234567890',
@ -120,15 +118,15 @@ describe('Discord connector', () => {
nock(userInfoEndpoint).get('').reply(401);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: 'dummyRedirectUri' }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
connector.getUserInfo({ code: 'code', redirectUri: 'dummyRedirectUri' }, vi.fn())
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
});
it('throws unrecognized error', async () => {
nock(userInfoEndpoint).get('').reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: 'dummyRedirectUri' }, jest.fn())
connector.getUserInfo({ code: 'code', redirectUri: 'dummyRedirectUri' }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,14 +6,12 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { clientId, clientSecret, code, dummyRedirectUri, fields, mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('Facebook connector', () => {
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid authorizationUri with redirectUri and state', async () => {
@ -29,7 +27,7 @@ describe('Facebook connector', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
const encodedRedirectUri = encodeURIComponent(redirectUri);
@ -42,7 +40,7 @@ describe('Facebook connector', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -86,7 +84,7 @@ describe('Facebook connector', () => {
await expect(
getAccessToken(mockedConfig, { code, redirectUri: dummyRedirectUri })
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
});
@ -110,7 +108,7 @@ describe('Facebook connector', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -130,7 +128,7 @@ describe('Facebook connector', () => {
code,
redirectUri: dummyRedirectUri,
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toStrictEqual({
id: '1234567890',
@ -150,8 +148,8 @@ describe('Facebook connector', () => {
nock(userInfoEndpoint).get('').query({ fields }).reply(400);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code, redirectUri: dummyRedirectUri }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
connector.getUserInfo({ code, redirectUri: dummyRedirectUri }, vi.fn())
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
});
it('throws AuthorizationFailed error if error is access_denied', async () => {
@ -174,9 +172,9 @@ describe('Facebook connector', () => {
error_description: 'Permissions error.',
error_reason: 'user_denied',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.AuthorizationFailed, 'Permissions error.')
);
});
@ -201,9 +199,9 @@ describe('Facebook connector', () => {
error_description: 'General error encountered.',
error_reason: 'user_denied',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
error: 'general_error',
error_code: 200,
@ -217,7 +215,7 @@ describe('Facebook connector', () => {
nock(userInfoEndpoint).get('').reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code, redirectUri: dummyRedirectUri }, jest.fn())
connector.getUserInfo({ code, redirectUri: dummyRedirectUri }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,13 +6,11 @@ import { accessTokenEndpoint, codeEndpoint, userInfoEndpoint } from './constant.
import createConnector, { buildAuthorizationUri, getAccessToken } from './index.js';
import { mockedFeishuConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedFeishuConfig);
const getConfig = vi.fn().mockResolvedValue(mockedFeishuConfig);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should build authorization uri', function () {
@ -33,7 +31,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${codeEndpoint}?client_id=1112233&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback&response_type=code&state=some_state`
@ -44,7 +42,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const accessTokenUrl = new URL(accessTokenEndpoint);
@ -73,7 +71,7 @@ describe('getAccessToken', () => {
await expect(
getAccessToken('code', '123', '123', 'http://localhost:3000')
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'access_token is empty')
);
});
@ -86,7 +84,7 @@ describe('getAccessToken', () => {
await expect(
getAccessToken('code', '123', '123', 'http://localhost:3000')
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -95,7 +93,7 @@ describe('getAccessToken', () => {
describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
beforeEach(() => {
@ -137,7 +135,7 @@ describe('getUserInfo', () => {
code: 'code',
redirectUri: 'http://localhost:3000',
},
jest.fn()
vi.fn()
);
expect(id).toEqual('ou_caecc734c2e3328a62489fe0648c4b98779515d3');
expect(name).toEqual('李雷');
@ -147,7 +145,7 @@ describe('getUserInfo', () => {
it('throw General error if code not provided in input', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.InvalidResponse, '{}')
);
});
@ -159,8 +157,8 @@ describe('getUserInfo', () => {
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'error_code', redirectUri: 'http://localhost:3000' }, jest.fn())
).rejects.toMatchError(
connector.getUserInfo({ code: 'error_code', redirectUri: 'http://localhost:3000' }, vi.fn())
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid access token')
);
});
@ -171,8 +169,8 @@ describe('getUserInfo', () => {
});
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: 'http://localhost:3000' }, jest.fn())
).rejects.toMatchError(
connector.getUserInfo({ code: 'code', redirectUri: 'http://localhost:3000' }, vi.fn())
).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.InvalidResponse, 'invalid user response')
);
});
@ -181,7 +179,7 @@ describe('getUserInfo', () => {
nock(userInfoUrl.origin).get(userInfoUrl.pathname).query(true).reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: 'http://localhost:3000' }, jest.fn())
connector.getUserInfo({ code: 'code', redirectUri: 'http://localhost:3000' }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -25,9 +25,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -7,13 +7,11 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
@ -27,7 +25,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&state=some_state&scope=read%3Auser`
@ -38,7 +36,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -60,7 +58,7 @@ describe('getAccessToken', () => {
nock(accessTokenEndpoint)
.post('')
.reply(200, qs.stringify({ access_token: '', scope: 'scope', token_type: 'token_type' }));
await expect(getAccessToken(mockedConfig, { code: 'code' })).rejects.toMatchError(
await expect(getAccessToken(mockedConfig, { code: 'code' })).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid)
);
});
@ -82,7 +80,7 @@ describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -94,7 +92,7 @@ describe('getUserInfo', () => {
foo: 'bar',
});
const connector = await createConnector({ getConfig });
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, jest.fn());
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, vi.fn());
expect(socialUserInfo).toStrictEqual({
id: '1',
avatar: 'https://github.com/images/error/octocat_happy.gif',
@ -118,7 +116,7 @@ describe('getUserInfo', () => {
email: null,
});
const connector = await createConnector({ getConfig });
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, jest.fn());
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, vi.fn());
expect(socialUserInfo).toMatchObject({
id: '1',
rawData: {
@ -133,7 +131,7 @@ describe('getUserInfo', () => {
it('throws SocialAccessTokenInvalid error if remote response code is 401', async () => {
nock(userInfoEndpoint).get('').reply(401);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});
@ -154,9 +152,9 @@ describe('getUserInfo', () => {
error_uri:
'https://docs.github.com/apps/troubleshooting-authorization-request-errors#access-denied',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(
ConnectorErrorCodes.AuthorizationFailed,
'The user has denied your application access.'
@ -178,9 +176,9 @@ describe('getUserInfo', () => {
error: 'general_error',
error_description: 'General error encountered.',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(
ConnectorErrorCodes.General,
'{"error":"general_error","error_description":"General error encountered."}'
@ -191,6 +189,6 @@ describe('getUserInfo', () => {
it('throws unrecognized error', async () => {
nock(userInfoEndpoint).get('').reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toThrow();
});
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,14 +6,12 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('google connector', () => {
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid authorizationUri with redirectUri and state', async () => {
@ -27,7 +25,7 @@ describe('google connector', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&response_type=code&state=some_state&scope=openid+profile+email`
@ -38,7 +36,7 @@ describe('google connector', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -60,7 +58,7 @@ describe('google connector', () => {
.reply(200, { access_token: '', scope: 'scope', token_type: 'token_type' });
await expect(
getAccessToken(mockedConfig, { code: 'code', redirectUri: 'dummyRedirectUri' })
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
});
@ -75,7 +73,7 @@ describe('google connector', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -96,7 +94,7 @@ describe('google connector', () => {
code: 'code',
redirectUri: 'redirectUri',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toStrictEqual({
id: '1234567890',
@ -111,8 +109,8 @@ describe('google connector', () => {
nock(userInfoEndpoint).post('').reply(401);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
});
it('throws General error', async () => {
@ -133,9 +131,9 @@ describe('google connector', () => {
error: 'general_error',
error_description: 'General error encountered.',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(
ConnectorErrorCodes.General,
'{"error":"general_error","error_description":"General error encountered."}'
@ -147,7 +145,7 @@ describe('google connector', () => {
nock(userInfoEndpoint).post('').reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,14 +6,12 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('kakao connector', () => {
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid authorizationUri with redirectUri and state', async () => {
@ -27,7 +25,7 @@ describe('kakao connector', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&response_type=code&state=some_state`
@ -38,7 +36,7 @@ describe('kakao connector', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -60,7 +58,7 @@ describe('kakao connector', () => {
.reply(200, { access_token: '', scope: 'scope', token_type: 'token_type' });
await expect(
getAccessToken(mockedConfig, { code: 'code', redirectUri: 'dummyRedirectUri' })
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
});
@ -75,7 +73,7 @@ describe('kakao connector', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -98,7 +96,7 @@ describe('kakao connector', () => {
code: 'code',
redirectUri: 'redirectUri',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toStrictEqual({
id: '1234567890',
@ -113,8 +111,8 @@ describe('kakao connector', () => {
nock(userInfoEndpoint).post('').reply(401);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
});
it('throws General error', async () => {
@ -135,9 +133,9 @@ describe('kakao connector', () => {
error: 'general_error',
error_description: 'General error encountered.',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(
ConnectorErrorCodes.General,
'{"error":"general_error","error_description":"General error encountered."}'
@ -149,7 +147,7 @@ describe('kakao connector', () => {
nock(userInfoEndpoint).post('').reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,16 +6,14 @@ import { TemplateType } from '@logto/connector-kit';
import { emailEndpoint, usageEndpoint } from './constant.js';
import createConnector from './index.js';
const { jest } = import.meta;
const endpoint = 'http://localhost:3003';
const api = got.extend({ prefixUrl: endpoint });
const dropLeadingSlash = (path: string) => path.replace(/^\//, '');
const buildUrl = (path: string, endpoint: string) => new URL(`${endpoint}/api${path}`);
const getConfig = jest.fn().mockResolvedValue({});
const getCloudServiceClient = jest.fn().mockResolvedValue({
const getConfig = vi.fn().mockResolvedValue({});
const getCloudServiceClient = vi.fn().mockResolvedValue({
post: async (path: string, payload: { body: unknown }) => {
return api(dropLeadingSlash(path), {
method: 'POST',

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -5,9 +5,7 @@ import { TemplateType } from '@logto/connector-kit';
import { smsEndpoint } from './constant.js';
import { mockedAccessTokenResponse, mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
const { default: createConnector } = await import('./index.js');

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,14 +2,12 @@ import createConnector from './index.js';
import type { SocialDemoConfig } from './types.js';
import { SocialProvider } from './types.js';
const { jest } = import.meta;
const mockedConfig: SocialDemoConfig = {
provider: SocialProvider.GitHub,
clientId: 'client-id',
redirectUri: 'http://localhost:3000/callback',
};
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('getAuthorizationUri', () => {
it('should get a valid uri by redirectUri and state', async () => {
@ -23,7 +21,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toContain(encodeURIComponent(mockedConfig.redirectUri));
expect(authorizationUri).toContain(

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -5,9 +5,7 @@ import { TemplateType } from '@logto/connector-kit';
import createMailgunConnector from './index.js';
import { type MailgunConfig } from './types.js';
const { jest } = import.meta;
const getConfig = jest.fn();
const getConfig = vi.fn();
const domain = 'example.com';
const apiKey = 'apiKey';
@ -210,7 +208,7 @@ describe('Maligun connector', () => {
code: '123456',
},
})
).rejects.toThrowErrorMatchingInlineSnapshot('"ConnectorError: template_not_found"');
).rejects.toThrowErrorMatchingInlineSnapshot('[Error: ConnectorError: template_not_found]');
await expect(
connector.sendMessage({
@ -221,7 +219,7 @@ describe('Maligun connector', () => {
code: '123456',
},
})
).rejects.toThrowErrorMatchingInlineSnapshot('"ConnectorError: template_not_found"');
).rejects.toThrowErrorMatchingInlineSnapshot('[Error: ConnectorError: template_not_found]');
});
it('should throw error if mailgun returns error', async () => {
@ -247,7 +245,7 @@ describe('Maligun connector', () => {
},
})
).rejects.toThrowErrorMatchingInlineSnapshot(
'"ConnectorError: {"statusCode":400,"body":"{\\"message\\":\\"error\\"}"}"'
'[Error: ConnectorError: {"statusCode":400,"body":"{\\"message\\":\\"error\\"}"}]'
);
});
});

View file

@ -13,9 +13,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"main": "./lib/index.js",

View file

@ -13,9 +13,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"main": "./lib/index.js",

View file

@ -13,9 +13,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"main": "./lib/index.js",

View file

@ -13,9 +13,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"main": "./lib/index.js",

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,14 +6,12 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('naver connector', () => {
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid authorizationUri with redirectUri and state', async () => {
@ -27,7 +25,7 @@ describe('naver connector', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&response_type=code&state=some_state`
@ -38,7 +36,7 @@ describe('naver connector', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get an accessToken by exchanging with code', async () => {
@ -60,7 +58,7 @@ describe('naver connector', () => {
.reply(200, { access_token: '', scope: 'scope', token_type: 'token_type' });
await expect(
getAccessToken(mockedConfig, { code: 'code', redirectUri: 'dummyRedirectUri' })
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid));
});
});
@ -75,7 +73,7 @@ describe('naver connector', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid SocialUserInfo', async () => {
@ -100,7 +98,7 @@ describe('naver connector', () => {
code: 'code',
redirectUri: 'redirectUri',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toMatchObject({
id: '32742776',
@ -115,8 +113,8 @@ describe('naver connector', () => {
nock(userInfoEndpoint).post('').reply(401);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
).rejects.toMatchError(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toStrictEqual(new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid));
});
it('throws General error', async () => {
@ -137,9 +135,9 @@ describe('naver connector', () => {
error: 'general_error',
error_description: 'General error encountered.',
},
jest.fn()
vi.fn()
)
).rejects.toMatchError(
).rejects.toStrictEqual(
new ConnectorError(
ConnectorErrorCodes.General,
'{"error":"general_error","error_description":"General error encountered."}'
@ -151,7 +149,7 @@ describe('naver connector', () => {
nock(userInfoEndpoint).post('').reply(500);
const connector = await createConnector({ getConfig });
await expect(
connector.getUserInfo({ code: 'code', redirectUri: '' }, jest.fn())
connector.getUserInfo({ code: 'code', redirectUri: '' }, vi.fn())
).rejects.toThrow();
});
});

View file

@ -25,9 +25,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,20 +2,18 @@ import nock from 'nock';
import { mockConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockConfig);
const getConfig = vi.fn().mockResolvedValue(mockConfig);
const { default: createConnector } = await import('./index.js');
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
const connector = await createConnector({ getConfig });
const setSession = jest.fn();
const setSession = vi.fn();
const authorizationUri = await connector.getAuthorizationUri(
{
state: 'some_state',
@ -40,7 +38,7 @@ describe('getAuthorizationUri', () => {
describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid userInfo', async () => {
@ -64,7 +62,7 @@ describe('getUserInfo', () => {
const connector = await createConnector({ getConfig });
const userInfo = await connector.getUserInfo(
{ code: 'code' },
jest.fn().mockImplementationOnce(() => {
vi.fn().mockImplementationOnce(() => {
return { redirectUri: 'http://localhost:3001/callback' };
})
);

View file

@ -26,9 +26,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,22 +2,20 @@ import nock from 'nock';
import { mockConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockConfig);
const getConfig = jest.fn().mockResolvedValue(mockConfig);
const jwtVerify = vi.fn();
const jwtVerify = jest.fn();
jest.unstable_mockModule('jose', () => ({
vi.mock('jose', () => ({
jwtVerify,
createRemoteJWKSet: jest.fn(),
createRemoteJWKSet: vi.fn(),
}));
const { default: createConnector } = await import('./index.js');
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
@ -31,7 +29,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
const { origin, pathname, searchParams } = new URL(authorizationUri);
@ -48,7 +46,7 @@ describe('getAuthorizationUri', () => {
describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get valid userInfo', async () => {
@ -65,7 +63,7 @@ describe('getUserInfo', () => {
const connector = await createConnector({ getConfig });
const userInfo = await connector.getUserInfo(
{ code: 'code' },
jest.fn().mockImplementationOnce(() => {
vi.fn().mockImplementationOnce(() => {
return { nonce: 'nonce', redirectUri: 'http://localhost:3001/callback' };
})
);

View file

@ -26,9 +26,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -1,18 +1,16 @@
import createConnector, { validateSamlAssertion } from './index.js';
import { mockAttributes, mockedConfig, mockSamlResponse } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const setSession = jest.fn();
const getSession = jest.fn();
const setSession = vi.fn();
const getSession = vi.fn();
const connector = await createConnector({ getConfig });
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri and save required information to storage', async () => {
@ -39,11 +37,11 @@ describe('getAuthorizationUri', () => {
describe('validateSamlAssertion', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('Should return right redirectUri', async () => {
jest.useFakeTimers().setSystemTime(new Date('2023-01-18T14:55:45.406Z'));
vi.useFakeTimers().setSystemTime(new Date('2023-01-18T14:55:45.406Z'));
getSession.mockResolvedValue({
connectorFactoryId: 'saml',
state: 'some_state',
@ -61,13 +59,13 @@ describe('validateSamlAssertion', () => {
);
expect(setSession).toHaveBeenCalledWith(expect.anything());
expect(redirectUri).toEqual('http://localhost:3000/callback?state=some_state');
jest.useRealTimers();
vi.useRealTimers();
});
});
describe('getUserInfo', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('get right profile', async () => {

View file

@ -1,10 +1,8 @@
import { userProfileMapping } from './utils.js';
const { jest } = import.meta;
describe('userProfileMapping', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should return right user profile', () => {

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -1,9 +1,7 @@
import createConnector from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('SendGrid connector', () => {
it('init without throwing errors', async () => {

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -1,9 +1,7 @@
import createConnector from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('SMSAero SMS connector', () => {
it('init without throwing errors', async () => {

View file

@ -28,9 +28,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -16,18 +16,16 @@ import {
} from './mock.js';
import { smtpConfigGuard } from './types.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const sendMail = jest.fn();
const sendMail = vi.fn();
// @ts-expect-error for testing
jest.spyOn(nodemailer, 'createTransport').mockReturnValue({ sendMail } as Transporter);
vi.spyOn(nodemailer, 'createTransport').mockReturnValue({ sendMail } as Transporter);
describe('SMTP connector', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('init without throwing errors', async () => {

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -2,11 +2,9 @@ import { TemplateType } from '@logto/connector-kit';
import { codeTest, mockedConnectorConfig, mockedTemplateCode, phoneTest } from './mock.js';
const { jest } = import.meta;
const getConfig = vi.fn().mockResolvedValue(mockedConnectorConfig);
const getConfig = jest.fn().mockResolvedValue(mockedConnectorConfig);
const sendSmsRequest = jest.fn(() => {
const sendSmsRequest = vi.fn(() => {
return {
body: {
Response: {
@ -27,10 +25,10 @@ const sendSmsRequest = jest.fn(() => {
};
});
jest.unstable_mockModule('./http.js', () => {
vi.mock('./http.js', () => {
return {
sendSmsRequest,
isSmsErrorResponse: jest.fn((response) => {
isSmsErrorResponse: vi.fn((response) => {
return response.Response.Error !== undefined;
}),
};
@ -40,7 +38,7 @@ const { default: createConnector } = await import('./index.js');
describe('sendMessage()', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should call sendSmsRequest() and replace code in content', async () => {

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -1,9 +1,7 @@
import createConnector from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('Twilio SMS connector', () => {
it('init without throwing errors', async () => {

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,13 +6,11 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri', async () => {
@ -26,7 +24,7 @@ describe('getAuthorizationUri', () => {
jti: 'dummy-jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?app_id=%3Capp-id%3E&state=dummy-state`
@ -37,7 +35,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const accessTokenEndpointUrl = new URL(accessTokenEndpoint);
@ -66,7 +64,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
await expect(getAccessToken('code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -76,7 +74,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: 40_163, errmsg: 'code been used' });
await expect(getAccessToken('code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'code been used')
);
});
@ -86,7 +84,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: -1, errmsg: 'system error' });
await expect(getAccessToken('wrong_code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('wrong_code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'system error',
errcode: -1,
@ -132,7 +130,7 @@ describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const userInfoEndpointUrl = new URL(userInfoEndpoint);
@ -149,7 +147,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(0, jsonResponse);
const connector = await createConnector({ getConfig });
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, jest.fn());
const socialUserInfo = await connector.getUserInfo({ code: 'code' }, vi.fn());
expect(socialUserInfo).toMatchObject({
id: 'this_is_an_arbitrary_wechat_union_id',
avatar: 'https://github.com/images/error/octocat_happy.gif',
@ -160,7 +158,7 @@ describe('getUserInfo', () => {
it('throws General error if code not provided in input', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -175,7 +173,7 @@ describe('getUserInfo', () => {
errmsg: 'missing openid',
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'missing openid',
errcode: 41_009,
@ -189,7 +187,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid credential')
);
});
@ -197,7 +195,7 @@ describe('getUserInfo', () => {
it('throws unrecognized error', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toThrow();
});
it('throws Error if request failed and errcode is not 40001', async () => {
@ -206,7 +204,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_003, errmsg: 'invalid openid' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'invalid openid',
errcode: 40_003,
@ -217,7 +215,7 @@ describe('getUserInfo', () => {
it('throws SocialAccessTokenInvalid error if response code is 401', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(401);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -6,13 +6,11 @@ import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
@ -26,7 +24,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
expect(authorizationUri).toEqual(
`${authorizationEndpoint}?appid=%3Capp-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback&response_type=code&scope=snsapi_login&state=some_state`
@ -37,7 +35,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const accessTokenEndpointUrl = new URL(accessTokenEndpoint);
@ -66,7 +64,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
await expect(getAccessToken('code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -76,7 +74,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: 40_163, errmsg: 'code been used' });
await expect(getAccessToken('code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'code been used')
);
});
@ -86,7 +84,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: -1, errmsg: 'system error' });
await expect(getAccessToken('wrong_code', mockedConfig)).rejects.toMatchError(
await expect(getAccessToken('wrong_code', mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'system error',
errcode: -1,
@ -123,7 +121,7 @@ describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const userInfoEndpointUrl = new URL(userInfoEndpoint);
@ -144,7 +142,7 @@ describe('getUserInfo', () => {
{
code: 'code',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toMatchObject({
id: 'this_is_an_arbitrary_wechat_union_id',
@ -156,7 +154,7 @@ describe('getUserInfo', () => {
it('throws General error if code not provided in input', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -171,7 +169,7 @@ describe('getUserInfo', () => {
errmsg: 'missing openid',
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'missing openid',
errcode: 41_009,
@ -185,7 +183,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid credential')
);
});
@ -193,7 +191,7 @@ describe('getUserInfo', () => {
it('throws unrecognized error', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toThrow();
});
it('throws Error if request failed and errcode is not 40001', async () => {
@ -202,7 +200,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_003, errmsg: 'invalid openid' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'invalid openid',
errcode: 40_003,
@ -213,7 +211,7 @@ describe('getUserInfo', () => {
it('throws SocialAccessTokenInvalid error if response code is 401', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(401);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});

View file

@ -24,9 +24,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {

View file

@ -11,13 +11,11 @@ import {
import createConnector, { getAccessToken } from './index.js';
import { mockedConfig } from './mock.js';
const { jest } = import.meta;
const getConfig = jest.fn().mockResolvedValue(mockedConfig);
const getConfig = vi.fn().mockResolvedValue(mockedConfig);
describe('getAuthorizationUri', () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it('should get a valid uri by redirectUri and state', async () => {
@ -31,7 +29,7 @@ describe('getAuthorizationUri', () => {
jti: 'some_jti',
headers: {},
},
jest.fn()
vi.fn()
);
const userAgent = 'some_UA';
const isWecom = userAgent.toLowerCase().includes('wxwork');
@ -48,7 +46,7 @@ describe('getAuthorizationUri', () => {
describe('getAccessToken', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const accessTokenEndpointUrl = new URL(accessTokenEndpoint);
@ -74,7 +72,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
await expect(getAccessToken(mockedConfig)).rejects.toMatchError(
await expect(getAccessToken(mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -84,7 +82,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: 40_163, errmsg: 'code been used' });
await expect(getAccessToken(mockedConfig)).rejects.toMatchError(
await expect(getAccessToken(mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'code been used')
);
});
@ -94,7 +92,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: -1, errmsg: 'system error' });
await expect(getAccessToken(mockedConfig)).rejects.toMatchError(
await expect(getAccessToken(mockedConfig)).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'system error',
errcode: -1,
@ -128,7 +126,7 @@ describe('getUserInfo', () => {
afterEach(() => {
nock.cleanAll();
jest.clearAllMocks();
vi.clearAllMocks();
});
const userInfoEndpointUrl = new URL(userInfoEndpoint);
@ -148,7 +146,7 @@ describe('getUserInfo', () => {
{
code: 'code',
},
jest.fn()
vi.fn()
);
expect(socialUserInfo).toMatchObject({
id: 'wecom_id',
@ -160,7 +158,7 @@ describe('getUserInfo', () => {
it('throws General error if code not provided in input', async () => {
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({}, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({}, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -175,7 +173,7 @@ describe('getUserInfo', () => {
errmsg: 'missing openid',
});
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'missing openid',
errcode: 41_009,
@ -189,7 +187,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid credential')
);
});
@ -197,7 +195,7 @@ describe('getUserInfo', () => {
it('throws unrecognized error', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(500);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toThrow();
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toThrow();
});
it('throws Error if request failed and errcode is not 40001', async () => {
@ -206,7 +204,7 @@ describe('getUserInfo', () => {
.query(parameters)
.reply(200, { errcode: 40_003, errmsg: 'invalid openid' });
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.General, {
errorDescription: 'invalid openid',
errcode: 40_003,
@ -217,7 +215,7 @@ describe('getUserInfo', () => {
it('throws SocialAccessTokenInvalid error if response code is 401', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(401);
const connector = await createConnector({ getConfig });
await expect(connector.getUserInfo({ code: 'code' }, jest.fn())).rejects.toMatchError(
await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toStrictEqual(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});

View file

@ -17,9 +17,8 @@
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test:only": "NODE_OPTIONS=--experimental-vm-modules jest",
"test": "pnpm build:test && pnpm test:only",
"test:ci": "pnpm test:only --silent --coverage",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"dependencies": {
@ -29,26 +28,24 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@jest/types": "^29.5.0",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-typescript": "^11.0.0",
"@silverhand/eslint-config": "5.0.0",
"@silverhand/ts-config": "5.0.0",
"@types/jest": "^29.4.0",
"@types/node": "^20.9.5",
"@types/supertest": "^6.0.0",
"@vitest/coverage-v8": "^1.4.0",
"eslint": "^8.44.0",
"jest": "^29.7.0",
"jest-matcher-specific-error": "^1.0.0",
"lint-staged": "^15.0.0",
"nock": "^13.2.2",
"prettier": "^3.0.0",
"rollup": "^4.0.0",
"rollup-plugin-output-size": "^1.3.0",
"supertest": "^6.2.2",
"typescript": "^5.3.3"
"typescript": "^5.3.3",
"vitest": "^1.4.0"
},
"engines": {
"node": "^20.9.0"

View file

@ -1,7 +0,0 @@
/** @type {import('jest').Config} */
const config = {
setupFilesAfterEnv: ['jest-matcher-specific-error'],
roots: ['lib'],
};
export default config;

View file

@ -1,7 +1,7 @@
{
"extends": "./tsconfig.base",
"compilerOptions": {
"types": ["node", "jest", "jest-matcher-specific-error"]
"types": ["node", "vitest/globals"]
},
"include": ["src", "types"]
}

View file

@ -1,10 +0,0 @@
interface ImportMeta {
jest: typeof jest & {
// Almost same as `jest.mock()`, but factory is required
unstable_mockModule: <T = unknown>(
moduleName: string,
factory: () => T,
options?: jest.MockOptions
) => typeof jest;
};
}

View file

@ -0,0 +1,7 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
},
})

View file

@ -17,10 +17,8 @@ const templateKeys = Object.keys(templateJson);
/**
* An object that contains exceptions for scripts that are allowed to be different from the template.
*
* This is useful when we transiting from Jest to Vitest, as they have different scripts.
*/
const scriptExceptions = { 'connector-azuread': ['test', 'test:ci'] };
const scriptExceptions = {};
const sync = async () => {
const packagesDirectory = './';

File diff suppressed because it is too large Load diff