0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

chore(schemas,test,core): add IT to ensure mock connectors are installed (#3762)

This commit is contained in:
Darcy Ye 2023-04-28 15:42:43 +08:00 committed by GitHub
parent 858854b9b1
commit 6e5b48bdcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 21 deletions

View file

@ -1,6 +1,6 @@
import { buildRawConnector } from '@logto/cli/lib/connector/index.js';
import { demoConnectorIds, validateConfig } from '@logto/connector-kit';
import { Connectors, ConnectorType } from '@logto/schemas';
import { connectorFactoryResponseGuard, Connectors, ConnectorType } from '@logto/schemas';
import { buildIdGenerator } from '@logto/shared';
import cleanDeep from 'clean-deep';
import { string, object } from 'zod';
@ -200,18 +200,29 @@ export default function connectorRoutes<T extends AuthedRouter>(
}
);
router.get('/connector-factories', async (ctx, next) => {
router.get(
'/connector-factories',
koaGuard({
response: connectorFactoryResponseGuard.array(),
status: [200],
}),
async (ctx, next) => {
const connectorFactories = await loadConnectorFactories();
ctx.body = connectorFactories.map((connectorFactory) =>
transpileConnectorFactory(connectorFactory)
);
return next();
});
}
);
router.get(
'/connector-factories/:id',
koaGuard({ params: object({ id: string().min(1) }) }),
koaGuard({
params: object({ id: string().min(1) }),
response: connectorFactoryResponseGuard,
status: [200],
}),
async (ctx, next) => {
const {
params: { id },

View file

@ -1,4 +1,9 @@
import type { Connector, ConnectorResponse, CreateConnector } from '@logto/schemas';
import type {
Connector,
ConnectorFactoryResponse,
ConnectorResponse,
CreateConnector,
} from '@logto/schemas';
import { authedAdminApi } from './api.js';
@ -8,6 +13,12 @@ export const listConnectors = async () =>
export const getConnector = async (connectorId: string) =>
authedAdminApi.get(`connectors/${connectorId}`).json<ConnectorResponse>();
export const listConnectorFactories = async () =>
authedAdminApi.get('connector-factories').json<ConnectorFactoryResponse[]>();
export const getConnectorFactory = async (connectorId: string) =>
authedAdminApi.get(`connector-factories/${connectorId}`).json<ConnectorFactoryResponse>();
// FIXME @Darcy: correct use of `id` and `connectorId`.
export const postConnector = async (
payload: Pick<CreateConnector, 'connectorId' | 'config' | 'metadata' | 'syncProfile'>

View file

@ -18,16 +18,43 @@ import {
sendEmailTestMessage,
sendSmsTestMessage,
updateConnectorConfig,
listConnectorFactories,
getConnectorFactory,
} from '#src/api/connector.js';
const connectorIdMap = new Map<string, string>();
const mockConnectorSetups = [
{ connectorId: mockSmsConnectorId, config: mockSmsConnectorConfig },
{ connectorId: mockEmailConnectorId, config: mockEmailConnectorConfig },
{ connectorId: mockSocialConnectorId, config: mockSocialConnectorConfig },
];
/*
* We'd better only use mock connectors in integration tests.
* Since we will refactor connectors soon, keep using some real connectors
* for testing updating configs and enabling/disabling for now.
*/
test('connector set-up flow', async () => {
/**
* Check whether mock connector factories are properly installed using
* both connector factory APIs:
* 1. GET /connector-factories (listConnectorFactories()).
* 2. GET /connector-factories/:connectorId (getConnectorFactory()).
*/
const connectorFactories = await listConnectorFactories();
await Promise.all(
mockConnectorSetups.map(async ({ connectorId }) => {
expect(connectorFactories.find(({ id }) => id === connectorId)).toBeDefined();
const connectorFactory = await getConnectorFactory(connectorId);
expect(connectorFactory).toBeDefined();
})
);
/**
* Clean up `connector` table
*/
const connectors = await listConnectors();
await Promise.all(
connectors.map(async ({ id }) => {
@ -40,11 +67,7 @@ test('connector set-up flow', async () => {
* Set up social/SMS/email connectors
*/
await Promise.all(
[
{ connectorId: mockSmsConnectorId, config: mockSmsConnectorConfig },
{ connectorId: mockEmailConnectorId, config: mockEmailConnectorConfig },
{ connectorId: mockSocialConnectorId, config: mockSocialConnectorConfig },
].map(async ({ connectorId, config }) => {
mockConnectorSetups.map(async ({ connectorId, config }) => {
// @darcy FIXME: should call post method directly
const { id } = await postConnector({ connectorId });
connectorIdMap.set(connectorId, id);

View file

@ -1,4 +1,6 @@
import type { BaseConnector, ConnectorMetadata, ConnectorType } from '@logto/connector-kit';
import type { BaseConnector, ConnectorMetadata } from '@logto/connector-kit';
import { ConnectorType, connectorMetadataGuard } from '@logto/connector-kit';
import { z } from 'zod';
import type { Connector } from '../db-entries/index.js';
@ -12,8 +14,11 @@ export type ConnectorResponse = Pick<
Omit<BaseConnector<ConnectorType>, 'configGuard' | 'metadata'> &
ConnectorMetadata & { isDemo?: boolean };
export type ConnectorFactoryResponse = Omit<
BaseConnector<ConnectorType>,
'configGuard' | 'metadata'
> &
ConnectorMetadata & { isDemo?: boolean };
export const connectorFactoryResponseGuard = z
.object({
type: z.nativeEnum(ConnectorType), // Omit<BaseConnector<ConnectorType>, 'configGuard' | 'metadata'>
isDemo: z.boolean().optional(),
})
.merge(connectorMetadataGuard);
export type ConnectorFactoryResponse = z.infer<typeof connectorFactoryResponseGuard>;