2022-05-27 21:21:23 +08:00
|
|
|
import { EmailMessageTypes, ValidateConfig } from '@logto/connector-types';
|
2022-03-10 11:54:33 +08:00
|
|
|
import { Connector, ConnectorType } from '@logto/schemas';
|
|
|
|
|
2022-05-27 21:21:23 +08:00
|
|
|
import { mockConnectorInstanceList, mockMetadata, mockConnector } from '@/__mocks__';
|
2022-03-10 11:54:33 +08:00
|
|
|
import {
|
|
|
|
ConnectorMetadata,
|
2022-03-14 11:11:37 +08:00
|
|
|
EmailConnectorInstance,
|
2022-04-06 12:11:06 +08:00
|
|
|
SmsConnectorInstance,
|
2022-03-10 11:54:33 +08:00
|
|
|
} from '@/connectors/types';
|
|
|
|
import RequestError from '@/errors/RequestError';
|
|
|
|
import assertThat from '@/utils/assert-that';
|
|
|
|
import { createRequester } from '@/utils/test-utils';
|
|
|
|
|
|
|
|
import connectorRoutes from './connector';
|
|
|
|
|
|
|
|
type ConnectorInstance = {
|
|
|
|
connector: Connector;
|
|
|
|
metadata: ConnectorMetadata;
|
|
|
|
validateConfig?: ValidateConfig;
|
2022-05-23 23:39:36 +08:00
|
|
|
sendMessage?: unknown;
|
2022-03-10 11:54:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const getConnectorInstancesPlaceHolder = jest.fn() as jest.MockedFunction<
|
|
|
|
() => Promise<ConnectorInstance[]>
|
|
|
|
>;
|
|
|
|
|
|
|
|
jest.mock('@/connectors', () => ({
|
|
|
|
getConnectorInstances: async () => getConnectorInstancesPlaceHolder(),
|
2022-05-27 21:21:23 +08:00
|
|
|
getConnectorInstanceById: async (connectorId: string) => {
|
|
|
|
const connectorInstances = await getConnectorInstancesPlaceHolder();
|
|
|
|
const connector = connectorInstances.find(({ connector }) => connector.id === connectorId);
|
|
|
|
assertThat(
|
|
|
|
connector,
|
|
|
|
new RequestError({
|
|
|
|
code: 'entity.not_found',
|
|
|
|
connectorId,
|
|
|
|
status: 404,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return connector;
|
|
|
|
},
|
2022-03-10 11:54:33 +08:00
|
|
|
}));
|
|
|
|
|
|
|
|
describe('connector route', () => {
|
|
|
|
const connectorRequest = createRequester({ authedRoutes: connectorRoutes });
|
|
|
|
|
|
|
|
describe('GET /connectors', () => {
|
|
|
|
afterEach(() => {
|
|
|
|
jest.clearAllMocks();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('throws if more than one email connector is enabled', async () => {
|
2022-05-23 23:39:36 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstanceList);
|
2022-03-10 11:54:33 +08:00
|
|
|
const response = await connectorRequest.get('/connectors').send({});
|
|
|
|
expect(response).toHaveProperty('statusCode', 400);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('throws if more than one SMS connector is enabled', async () => {
|
2022-05-23 23:39:36 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(
|
2022-03-10 11:54:33 +08:00
|
|
|
mockConnectorInstanceList.filter(
|
2022-03-17 23:01:15 +08:00
|
|
|
(connectorInstance) => connectorInstance.metadata.type !== ConnectorType.Email
|
2022-03-10 11:54:33 +08:00
|
|
|
)
|
|
|
|
);
|
|
|
|
const response = await connectorRequest.get('/connectors').send({});
|
|
|
|
expect(response).toHaveProperty('statusCode', 400);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows all connectors', async () => {
|
2022-05-23 23:39:36 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(
|
2022-03-10 11:54:33 +08:00
|
|
|
mockConnectorInstanceList.filter(
|
2022-03-17 23:01:15 +08:00
|
|
|
(connectorInstance) => connectorInstance.metadata.type === ConnectorType.Social
|
2022-03-10 11:54:33 +08:00
|
|
|
)
|
|
|
|
);
|
|
|
|
const response = await connectorRequest.get('/connectors').send({});
|
|
|
|
expect(response).toHaveProperty('statusCode', 200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('GET /connectors/:id', () => {
|
|
|
|
afterEach(() => {
|
|
|
|
jest.clearAllMocks();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('throws when connector can not be found by given connectorId (locally)', async () => {
|
2022-05-27 21:21:23 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstanceList.slice(2));
|
2022-03-10 11:54:33 +08:00
|
|
|
const response = await connectorRequest.get('/connectors/findConnector').send({});
|
|
|
|
expect(response).toHaveProperty('statusCode', 404);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('throws when connector can not be found by given connectorId (remotely)', async () => {
|
2022-05-27 21:21:23 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([]);
|
2022-05-24 11:39:44 +08:00
|
|
|
const response = await connectorRequest.get('/connectors/id0').send({});
|
2022-03-10 11:54:33 +08:00
|
|
|
expect(response).toHaveProperty('statusCode', 404);
|
|
|
|
});
|
|
|
|
|
2022-05-27 21:21:23 +08:00
|
|
|
it('shows found connector information', async () => {
|
2022-03-10 11:54:33 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstanceList);
|
2022-05-27 21:21:23 +08:00
|
|
|
const response = await connectorRequest.get('/connectors/id0').send({});
|
2022-03-10 11:54:33 +08:00
|
|
|
expect(response).toHaveProperty('statusCode', 200);
|
|
|
|
});
|
|
|
|
});
|
2022-03-14 11:11:37 +08:00
|
|
|
|
|
|
|
describe('POST /connectors/test/email', () => {
|
|
|
|
afterEach(() => {
|
|
|
|
jest.clearAllMocks();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should get email connector and send message', async () => {
|
|
|
|
const mockedEmailConnector: EmailConnectorInstance = {
|
2022-05-27 21:21:23 +08:00
|
|
|
connector: mockConnector,
|
|
|
|
metadata: mockMetadata,
|
2022-03-31 18:02:35 +08:00
|
|
|
validateConfig: jest.fn(),
|
2022-04-29 10:37:13 +08:00
|
|
|
getConfig: jest.fn(),
|
2022-03-14 11:11:37 +08:00
|
|
|
sendMessage: async (
|
|
|
|
address: string,
|
|
|
|
type: keyof EmailMessageTypes,
|
|
|
|
_payload: EmailMessageTypes[typeof type]
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
|
|
): Promise<any> => {},
|
|
|
|
};
|
2022-05-23 23:39:36 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([mockedEmailConnector]);
|
2022-03-14 11:11:37 +08:00
|
|
|
const sendMessageSpy = jest.spyOn(mockedEmailConnector, 'sendMessage');
|
|
|
|
const response = await connectorRequest
|
|
|
|
.post('/connectors/test/email')
|
2022-06-22 13:01:26 +08:00
|
|
|
.send({ email: 'test@email.com', config: { test: 123 } });
|
2022-03-14 11:11:37 +08:00
|
|
|
expect(sendMessageSpy).toHaveBeenCalledTimes(1);
|
2022-06-22 13:01:26 +08:00
|
|
|
expect(sendMessageSpy).toHaveBeenCalledWith(
|
|
|
|
'test@email.com',
|
|
|
|
'Test',
|
|
|
|
{
|
|
|
|
code: 'email-test',
|
|
|
|
},
|
|
|
|
{ test: 123 }
|
|
|
|
);
|
2022-03-14 11:11:37 +08:00
|
|
|
expect(response).toHaveProperty('statusCode', 204);
|
|
|
|
});
|
2022-05-23 23:39:36 +08:00
|
|
|
|
|
|
|
it('should throw when email connector is not found', async () => {
|
2022-05-27 21:21:23 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([]);
|
2022-05-23 23:39:36 +08:00
|
|
|
const response = await connectorRequest
|
|
|
|
.post('/connectors/test/email')
|
|
|
|
.send({ email: 'test@email.com' });
|
|
|
|
expect(response).toHaveProperty('statusCode', 400);
|
|
|
|
});
|
2022-03-14 11:11:37 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('POST /connectors/test/sms', () => {
|
|
|
|
afterEach(() => {
|
|
|
|
jest.clearAllMocks();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should get SMS connector and send message', async () => {
|
2022-05-12 12:17:17 +08:00
|
|
|
const mockedMetadata = {
|
|
|
|
...mockMetadata,
|
|
|
|
type: ConnectorType.SMS,
|
|
|
|
};
|
|
|
|
const mockedSmsConnectorInstance: SmsConnectorInstance = {
|
2022-05-27 21:21:23 +08:00
|
|
|
connector: mockConnector,
|
2022-05-12 12:17:17 +08:00
|
|
|
metadata: mockedMetadata,
|
2022-03-31 18:02:35 +08:00
|
|
|
validateConfig: jest.fn(),
|
2022-04-29 10:37:13 +08:00
|
|
|
getConfig: jest.fn(),
|
2022-03-14 11:11:37 +08:00
|
|
|
sendMessage: async (
|
|
|
|
address: string,
|
|
|
|
type: keyof EmailMessageTypes,
|
|
|
|
_payload: EmailMessageTypes[typeof type]
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
|
|
): Promise<any> => {},
|
|
|
|
};
|
2022-05-23 23:39:36 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([mockedSmsConnectorInstance]);
|
2022-05-12 12:17:17 +08:00
|
|
|
const sendMessageSpy = jest.spyOn(mockedSmsConnectorInstance, 'sendMessage');
|
2022-03-14 11:11:37 +08:00
|
|
|
const response = await connectorRequest
|
|
|
|
.post('/connectors/test/sms')
|
2022-06-22 13:01:26 +08:00
|
|
|
.send({ phone: '12345678901', config: { test: 123 } });
|
2022-03-14 11:11:37 +08:00
|
|
|
expect(sendMessageSpy).toHaveBeenCalledTimes(1);
|
2022-06-22 13:01:26 +08:00
|
|
|
expect(sendMessageSpy).toHaveBeenCalledWith(
|
|
|
|
'12345678901',
|
|
|
|
'Test',
|
|
|
|
{
|
|
|
|
code: '123456',
|
|
|
|
},
|
|
|
|
{ test: 123 }
|
|
|
|
);
|
2022-03-14 11:11:37 +08:00
|
|
|
expect(response).toHaveProperty('statusCode', 204);
|
|
|
|
});
|
2022-05-23 23:39:36 +08:00
|
|
|
|
|
|
|
it('should throw when sms connector is not found', async () => {
|
2022-05-27 21:21:23 +08:00
|
|
|
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([]);
|
2022-05-23 23:39:36 +08:00
|
|
|
const response = await connectorRequest
|
|
|
|
.post('/connectors/test/sms')
|
|
|
|
.send({ phone: '12345678901' });
|
|
|
|
expect(response).toHaveProperty('statusCode', 400);
|
|
|
|
});
|
2022-03-14 11:11:37 +08:00
|
|
|
});
|
2022-03-10 11:54:33 +08:00
|
|
|
});
|