0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

chore(core,connector-wechat-*): fix according to wechat naming convertion (#1251)

This commit is contained in:
Darcy Ye 2022-06-27 00:41:15 +08:00 committed by GitHub
parent c5cbc93aed
commit 5fb74537a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 71 deletions

View file

@ -1,17 +1,17 @@
import { ConnectorError, ConnectorErrorCodes, GetConnectorConfig } from '@logto/connector-types';
import nock from 'nock';
import WeChatNativeConnector from '.';
import WechatNativeConnector from '.';
import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './constant';
import { mockedConfig } from './mock';
import { WeChatNativeConfig } from './types';
import { WechatNativeConfig } from './types';
const getConnectorConfig = jest.fn() as GetConnectorConfig<WeChatNativeConfig>;
const getConnectorConfig = jest.fn() as GetConnectorConfig<WechatNativeConfig>;
const weChatNativeMethods = new WeChatNativeConnector(getConnectorConfig);
const wechatNativeMethods = new WechatNativeConnector(getConnectorConfig);
beforeAll(() => {
jest.spyOn(weChatNativeMethods, 'getConfig').mockResolvedValue(mockedConfig);
jest.spyOn(wechatNativeMethods, 'getConfig').mockResolvedValue(mockedConfig);
});
describe('getAuthorizationUri', () => {
@ -20,7 +20,7 @@ describe('getAuthorizationUri', () => {
});
it('should get a valid uri', async () => {
const authorizationUri = await weChatNativeMethods.getAuthorizationUri({
const authorizationUri = await wechatNativeMethods.getAuthorizationUri({
state: 'dummy-state',
redirectUri: 'dummy-redirect-uri',
});
@ -52,7 +52,7 @@ describe('getAccessToken', () => {
access_token: 'access_token',
openid: 'openid',
});
const { accessToken, openid } = await weChatNativeMethods.getAccessToken('code');
const { accessToken, openid } = await wechatNativeMethods.getAccessToken('code');
expect(accessToken).toEqual('access_token');
expect(openid).toEqual('openid');
});
@ -62,7 +62,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
await expect(weChatNativeMethods.getAccessToken('code')).rejects.toMatchError(
await expect(wechatNativeMethods.getAccessToken('code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -72,7 +72,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: 40_163, errmsg: 'code been used' });
await expect(weChatNativeMethods.getAccessToken('code')).rejects.toMatchError(
await expect(wechatNativeMethods.getAccessToken('code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'code been used')
);
});
@ -82,7 +82,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: -1, errmsg: 'system error' });
await expect(weChatNativeMethods.getAccessToken('wrong_code')).rejects.toMatchError(
await expect(wechatNativeMethods.getAccessToken('wrong_code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.General, 'system error')
);
});
@ -91,14 +91,14 @@ describe('getAccessToken', () => {
describe('validateConfig', () => {
it('should pass on valid config', async () => {
await expect(
weChatNativeMethods.validateConfig({ appId: 'appId', appSecret: 'appSecret' })
wechatNativeMethods.validateConfig({ appId: 'appId', appSecret: 'appSecret' })
).resolves.not.toThrow();
});
it('should throw on empty config', async () => {
await expect(weChatNativeMethods.validateConfig({})).rejects.toThrowError();
await expect(wechatNativeMethods.validateConfig({})).rejects.toThrowError();
});
it('should throw when missing appSecret', async () => {
await expect(weChatNativeMethods.validateConfig({ appId: 'appId' })).rejects.toThrowError();
await expect(wechatNativeMethods.validateConfig({ appId: 'appId' })).rejects.toThrowError();
});
});
@ -151,7 +151,7 @@ describe('getUserInfo', () => {
headimgurl: 'https://github.com/images/error/octocat_happy.gif',
nickname: 'wechat bot',
});
const socialUserInfo = await weChatNativeMethods.getUserInfo({ code: 'code' });
const socialUserInfo = await wechatNativeMethods.getUserInfo({ code: 'code' });
expect(socialUserInfo).toMatchObject({
id: 'this_is_an_arbitrary_wechat_union_id',
avatar: 'https://github.com/images/error/octocat_happy.gif',
@ -160,7 +160,7 @@ describe('getUserInfo', () => {
});
it('throws General error if code not provided in input', async () => {
await expect(weChatNativeMethods.getUserInfo({})).rejects.toMatchError(
await expect(wechatNativeMethods.getUserInfo({})).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -174,7 +174,7 @@ describe('getUserInfo', () => {
errcode: 41_009,
errmsg: 'missing openid',
});
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new Error('missing openid')
);
});
@ -184,14 +184,14 @@ describe('getUserInfo', () => {
.get(userInfoEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid credential')
);
});
it('throws unrecognized error', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(500);
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toThrow();
await expect(wechatNativeMethods.getUserInfo({ code: 'code' })).rejects.toThrow();
});
it('throws Error if request failed and errcode is not 40001', async () => {
@ -199,14 +199,14 @@ describe('getUserInfo', () => {
.get(userInfoEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_003, errmsg: 'invalid openid' });
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new Error('invalid openid')
);
});
it('throws SocialAccessTokenInvalid error if response code is 401', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(401);
await expect(weChatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatNativeMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});

View file

@ -25,21 +25,21 @@ import {
defaultTimeout,
} from './constant';
import {
weChatNativeConfigGuard,
wechatNativeConfigGuard,
accessTokenResponseGuard,
GetAccessTokenErrorHandler,
userInfoResponseGuard,
GetUserInfoErrorHandler,
WeChatNativeConfig,
WechatNativeConfig,
} from './types';
export default class WeChatNativeConnector implements SocialConnector {
export default class WechatNativeConnector implements SocialConnector {
public metadata: ConnectorMetadata = defaultMetadata;
constructor(public readonly getConfig: GetConnectorConfig<WeChatNativeConfig>) {}
constructor(public readonly getConfig: GetConnectorConfig<WechatNativeConfig>) {}
public validateConfig: ValidateConfig = async (config: unknown) => {
const result = weChatNativeConfigGuard.safeParse(config);
const result = wechatNativeConfigGuard.safeParse(config);
if (!result.success) {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig, result.error.message);

View file

@ -1,12 +1,12 @@
import { z } from 'zod';
export const weChatNativeConfigGuard = z.object({
export const wechatNativeConfigGuard = z.object({
appId: z.string(),
appSecret: z.string(),
universalLinks: z.string().optional(),
});
export type WeChatNativeConfig = z.infer<typeof weChatNativeConfigGuard>;
export type WechatNativeConfig = z.infer<typeof wechatNativeConfigGuard>;
export const accessTokenResponseGuard = z.object({
access_token: z.string().optional(),

View file

@ -1,17 +1,17 @@
import { ConnectorError, ConnectorErrorCodes, GetConnectorConfig } from '@logto/connector-types';
import nock from 'nock';
import WeChatConnector from '.';
import WechatConnector from '.';
import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './constant';
import { mockedConfig } from './mock';
import { WeChatConfig } from './types';
import { WechatConfig } from './types';
const getConnectorConfig = jest.fn() as GetConnectorConfig<WeChatConfig>;
const getConnectorConfig = jest.fn() as GetConnectorConfig<WechatConfig>;
const weChatMethods = new WeChatConnector(getConnectorConfig);
const wechatMethods = new WechatConnector(getConnectorConfig);
beforeAll(() => {
jest.spyOn(weChatMethods, 'getConfig').mockResolvedValue(mockedConfig);
jest.spyOn(wechatMethods, 'getConfig').mockResolvedValue(mockedConfig);
});
describe('getAuthorizationUri', () => {
@ -20,7 +20,7 @@ describe('getAuthorizationUri', () => {
});
it('should get a valid uri by redirectUri and state', async () => {
const authorizationUri = await weChatMethods.getAuthorizationUri({
const authorizationUri = await wechatMethods.getAuthorizationUri({
state: 'some_state',
redirectUri: 'http://localhost:3001/callback',
});
@ -52,7 +52,7 @@ describe('getAccessToken', () => {
access_token: 'access_token',
openid: 'openid',
});
const { accessToken, openid } = await weChatMethods.getAccessToken('code');
const { accessToken, openid } = await wechatMethods.getAccessToken('code');
expect(accessToken).toEqual('access_token');
expect(openid).toEqual('openid');
});
@ -62,7 +62,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_029, errmsg: 'invalid code' });
await expect(weChatMethods.getAccessToken('code')).rejects.toMatchError(
await expect(wechatMethods.getAccessToken('code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'invalid code')
);
});
@ -72,7 +72,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: 40_163, errmsg: 'code been used' });
await expect(weChatMethods.getAccessToken('code')).rejects.toMatchError(
await expect(wechatMethods.getAccessToken('code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, 'code been used')
);
});
@ -82,7 +82,7 @@ describe('getAccessToken', () => {
.get(accessTokenEndpointUrl.pathname)
.query(true)
.reply(200, { errcode: -1, errmsg: 'system error' });
await expect(weChatMethods.getAccessToken('wrong_code')).rejects.toMatchError(
await expect(wechatMethods.getAccessToken('wrong_code')).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.General, 'system error')
);
});
@ -91,14 +91,14 @@ describe('getAccessToken', () => {
describe('validateConfig', () => {
it('should pass on valid config', async () => {
await expect(
weChatMethods.validateConfig({ appId: 'appId', appSecret: 'appSecret' })
wechatMethods.validateConfig({ appId: 'appId', appSecret: 'appSecret' })
).resolves.not.toThrow();
});
it('should throw on empty config', async () => {
await expect(weChatMethods.validateConfig({})).rejects.toThrowError();
await expect(wechatMethods.validateConfig({})).rejects.toThrowError();
});
it('should throw when missing appSecret', async () => {
await expect(weChatMethods.validateConfig({ appId: 'appId' })).rejects.toThrowError();
await expect(wechatMethods.validateConfig({ appId: 'appId' })).rejects.toThrowError();
});
});
@ -142,7 +142,7 @@ describe('getUserInfo', () => {
headimgurl: 'https://github.com/images/error/octocat_happy.gif',
nickname: 'wechat bot',
});
const socialUserInfo = await weChatMethods.getUserInfo({
const socialUserInfo = await wechatMethods.getUserInfo({
code: 'code',
});
expect(socialUserInfo).toMatchObject({
@ -153,7 +153,7 @@ describe('getUserInfo', () => {
});
it('throws General error if code not provided in input', async () => {
await expect(weChatMethods.getUserInfo({})).rejects.toMatchError(
await expect(wechatMethods.getUserInfo({})).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.General, '{}')
);
});
@ -167,7 +167,7 @@ describe('getUserInfo', () => {
errcode: 41_009,
errmsg: 'missing openid',
});
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new Error('missing openid')
);
});
@ -177,14 +177,14 @@ describe('getUserInfo', () => {
.get(userInfoEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_001, errmsg: 'invalid credential' });
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, 'invalid credential')
);
});
it('throws unrecognized error', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(500);
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toThrow();
await expect(wechatMethods.getUserInfo({ code: 'code' })).rejects.toThrow();
});
it('throws Error if request failed and errcode is not 40001', async () => {
@ -192,14 +192,14 @@ describe('getUserInfo', () => {
.get(userInfoEndpointUrl.pathname)
.query(parameters)
.reply(200, { errcode: 40_003, errmsg: 'invalid openid' });
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new Error('invalid openid')
);
});
it('throws SocialAccessTokenInvalid error if response code is 401', async () => {
nock(userInfoEndpointUrl.origin).get(userInfoEndpointUrl.pathname).query(parameters).reply(401);
await expect(weChatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
await expect(wechatMethods.getUserInfo({ code: 'code' })).rejects.toMatchError(
new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid)
);
});

View file

@ -26,24 +26,21 @@ import {
defaultTimeout,
} from './constant';
import {
weChatConfigGuard,
wechatConfigGuard,
accessTokenResponseGuard,
GetAccessTokenErrorHandler,
userInfoResponseGuard,
GetUserInfoErrorHandler,
WeChatConfig,
WechatConfig,
} from './types';
// As creating a WeChat Web/Mobile application needs a real App or Website record, the real test is temporarily not finished.
// TODO: test with our own WeChat web application (LOG-2719), already tested with other verified WeChat web application
export default class WeChatConnector implements SocialConnector {
export default class WechatConnector implements SocialConnector {
public metadata: ConnectorMetadata = defaultMetadata;
constructor(public readonly getConfig: GetConnectorConfig<WeChatConfig>) {}
constructor(public readonly getConfig: GetConnectorConfig<WechatConfig>) {}
public validateConfig: ValidateConfig = async (config: unknown) => {
const result = weChatConfigGuard.safeParse(config);
const result = wechatConfigGuard.safeParse(config);
if (!result.success) {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig, result.error.message);

View file

@ -1,8 +1,8 @@
import { z } from 'zod';
export const weChatConfigGuard = z.object({ appId: z.string(), appSecret: z.string() });
export const wechatConfigGuard = z.object({ appId: z.string(), appSecret: z.string() });
export type WeChatConfig = z.infer<typeof weChatConfigGuard>;
export type WechatConfig = z.infer<typeof wechatConfigGuard>;
export const accessTokenResponseGuard = z.object({
access_token: z.string().optional(),

View file

@ -13,9 +13,9 @@ const mockConnectors = [
{ platform: 'Web', target: 'facebook' },
{ platform: 'Web', target: 'google' },
{ platform: 'Universal', target: 'facebook' },
{ platform: 'Universal', target: 'WeChat' },
{ platform: 'Native', target: 'WeChat' },
{ platform: 'Native', target: 'Alipay' },
{ platform: 'Universal', target: 'wechat' },
{ platform: 'Native', target: 'wechat' },
{ platform: 'Native', target: 'alipay' },
] as ConnectorData[];
jest.mock('@/utils/native-sdk', () => ({
@ -41,7 +41,7 @@ describe('filterSocialConnectors', () => {
expect(filterSocialConnectors(mockConnectors)).toEqual([
{ platform: 'Web', target: 'facebook' },
{ platform: 'Web', target: 'google' },
{ platform: 'Universal', target: 'WeChat' },
{ platform: 'Universal', target: 'wechat' },
]);
});
@ -50,7 +50,7 @@ describe('filterSocialConnectors', () => {
getLogtoNativeSdkMock.mockImplementation(() => ({
supportedConnector: {
universal: true,
nativeTargets: ['WeChat', 'Alipay'],
nativeTargets: ['wechat', 'alipay'],
},
}));
@ -62,7 +62,7 @@ describe('filterSocialConnectors', () => {
getLogtoNativeSdkMock.mockImplementation(() => ({
supportedConnector: {
universal: true,
nativeTargets: ['WeChat'],
nativeTargets: ['wechat'],
},
getPostMessage: jest.fn(),
callbackLink: 'logto://callback',
@ -70,7 +70,7 @@ describe('filterSocialConnectors', () => {
expect(filterSocialConnectors(mockConnectors)).toEqual([
{ platform: 'Universal', target: 'facebook' },
{ platform: 'Native', target: 'WeChat' },
{ platform: 'Native', target: 'wechat' },
]);
});
@ -79,13 +79,13 @@ describe('filterSocialConnectors', () => {
getLogtoNativeSdkMock.mockImplementation(() => ({
supportedConnector: {
universal: true,
nativeTargets: ['WeChat'],
nativeTargets: ['wechat'],
},
getPostMessage: jest.fn(),
}));
expect(filterSocialConnectors(mockConnectors)).toEqual([
{ platform: 'Native', target: 'WeChat' },
{ platform: 'Native', target: 'wechat' },
]);
});
@ -95,13 +95,13 @@ describe('filterSocialConnectors', () => {
platform: 'ios',
supportedConnector: {
universal: false,
nativeTargets: ['WeChat'],
nativeTargets: ['wechat'],
},
getPostMessage: jest.fn(),
}));
expect(filterSocialConnectors(mockConnectors)).toEqual([
{ platform: 'Native', target: 'WeChat' },
{ platform: 'Native', target: 'wechat' },
]);
});
});
@ -121,15 +121,15 @@ describe('filterPreviewSocialConnectors', () => {
expect(filterPreviewSocialConnectors(ConnectorPlatform.Web, mockConnectors)).toEqual([
{ platform: 'Web', target: 'facebook' },
{ platform: 'Web', target: 'google' },
{ platform: 'Universal', target: 'WeChat' },
{ platform: 'Universal', target: 'wechat' },
]);
});
it('filter Native Connectors', () => {
expect(filterPreviewSocialConnectors(ConnectorPlatform.Native, mockConnectors)).toEqual([
{ platform: 'Universal', target: 'facebook' },
{ platform: 'Native', target: 'WeChat' },
{ platform: 'Native', target: 'Alipay' },
{ platform: 'Native', target: 'wechat' },
{ platform: 'Native', target: 'alipay' },
]);
});
});